<commit_before>#![allow(unused_variables)]

use block::Block;
use cocoa::base::{BOOL, id};
use cocoa::foundation::NSUInteger;
use libc::c_void;
use {MTLFeatureSet, MTLPipelineOption, MTLSize};

pub type MTLNewLibraryCompletionHandler = Block<(id,), id>;
pub type MTLNewRenderPipleineStateCompletionHandler = Block<(id, id), ()>;
pub type MTLNewRenderPipelineStateWithReflectionCompletionHandler = Block<(id, id, id), ()>;
pub type MTLNewComputePipelineStateCompletionHandler = Block<(id, id), ()>;
pub type MTLNewComputePipelineStateWithReflectionCompletionHandler = Block<(id, id, id), ()>;

#[cfg(any(target_os = "macos", target_os = "ios"))]
pub trait MTLDevice {
    unsafe fn depth24Stencil8PixelFormatSupported(self) -> BOOL;
    unsafe fn headless(self) -> BOOL;
    unsafe fn lowPower(self) -> BOOL;
    unsafe fn maxThreadsPerGroup(self) -> MTLSize;
    unsafe fn name(self) -> id;
    unsafe fn supportsFeatureSet(self, featureSet: MTLFeatureSet) -> BOOL;
    unsafe fn supportsTextureSampleCount(self, textureSampleCount: NSUInteger) -> BOOL;

    unsafe fn newDefaultLibrary(self) -> id;
    unsafe fn newLibraryWithFile_error(self, filePath: id, error: id) -> id;
    unsafe fn newLibraryWithSource_options_completionHandler(self,
                                                             source: id,
                                                             options: id,
                                                             completionHandler: MTLNewLibraryCompletionHandler);
    unsafe fn newLibraryWithSource_options_error(self, source: id, options: id, error: id);
    unsafe fn newLibraryWithData_error(self, data: id, error: id);

    unsafe fn newCommandQueue(self) -> id;
    unsafe fn newCommandQueueWithMaxCommandBufferCount(self, maxCommandBufferCount: NSUInteger) -> id;

    unsafe fn newBufferWithLength_Options(self, length: NSUInteger, options: id) -> id;
    unsafe fn newBufferWithBytes_Length_Options(self, pointer: *mut c_void, length: NSUInteger, options: id) -> id;
    unsafe fn newBufferWithBytesNoCopy_length_options_deallocator(self,
                                                                  pointer: *mut c_void,
                                                                  length: NSUInteger,
                                                                  deallocator: Block<(*mut c_void, NSUInteger), ()>);

    unsafe fn newTextureWithDescriptor(self, descriptor: id) -> id;
    unsafe fn newSamplerStateWithDescriptor(self, descriptor: id) -> id;

    unsafe fn newStencilDepthStateWithDescriptor(self, descriptor: id) -> id;
    unsafe fn newRenderPipleineStateWithDescriptor_completionHandler(
                                                    self,
                                                    completionHandler: MTLNewRenderPipleineStateCompletionHandler);
    unsafe fn newRenderPipelineStateWithDescriptor_options_completionHandler(
                                        self,
                                        options: MTLPipelineOption,
                                        completionHandler: MTLNewRenderPipelineStateWithReflectionCompletionHandler);
    unsafe fn newRenderPipelineStateWithDescriptor_error(self, error: id);
    unsafe fn newRenderPipelineStateWithDescriptor_options_reflection(self,
                                                                      options: MTLPipelineOption,
                                                                      reflection: id,
                                                                      error: id);

    unsafe fn newComputePipelineStateWithFunction_completionHandler(
                                                        self,
                                                        function: id,
                                                        completionHandler: MTLNewComputePipelineStateCompletionHandler);
    unsafe fn newComputePipelineStateWithFunction_options_completionHandler(
                                        self,
                                        function: id,
                                        options: MTLPipelineOption,
                                        completionHandler: MTLNewComputePipelineStateWithReflectionCompletionHandler);
    unsafe fn newComputePipelineStateWithFunction_error(self, function: id, error: id);
    unsafe fn newComputePipelineStateWithFunction_options_reflection_error(self,
                                                                           function: id,
                                                                           options: MTLPipelineOption,
                                                                           reflection: id,
                                                                           error: id);

    unsafe fn newComputePipelineStateWithDescriptor_options_completionHandler(self,
                                        descriptor: id,
                                        options: MTLPipelineOption,
                                        completionHandler: MTLNewComputePipelineStateWithReflectionCompletionHandler);
    unsafe fn newComputePipelineStateWithDescriptor_options_reflection_error(self,
                                                                             descriptor: id,
                                                                             options: MTLPipelineOption,
                                                                             reflection: id,
                                                                             error: id);
}

impl MTLDevice for id {
    unsafe fn depth24Stencil8PixelFormatSupported(self) -> BOOL {
        msg_send![self, isDepth24Stencil8PixelFormatSupported]
    }

    unsafe fn headless(self) -> BOOL {
        msg_send![self, isHeadless]
    }

    unsafe fn lowPower(self) -> BOOL {
        msg_send![self, isLowPower]
    }

    unsafe fn maxThreadsPerGroup(self) -> MTLSize {
        msg_send![self, maxThreadsPerThreadgroup]
    }

    unsafe fn name(self) -> id {
        msg_send![self, name]
    }

    unsafe fn supportsFeatureSet(self, featureSet: MTLFeatureSet) -> BOOL {
        msg_send![self, supportsFeatureSet:featureSet]
    }

    unsafe fn supportsTextureSampleCount(self, textureSampleCount: NSUInteger) -> BOOL {
        msg_send![self, supportsTextureSampleCount:textureSampleCount]
    }

    unsafe fn newDefaultLibrary(self) -> id {
        msg_send![self, newDefaultLibrary]
    }

    unsafe fn newLibraryWithFile_error(self, filePath: id, error: id) -> id {
        msg_send![self, newLibraryWithFile:filePath error:error]
    }

    unsafe fn newLibraryWithSource_options_completionHandler(self,
                                                             source: id,
                                                             options: id,
                                                             completionHandler: MTLNewLibraryCompletionHandler) {
        msg_send![self, newLibraryWithSource:source options:options completionHandler:completionHandler]
    }

    unsafe fn newLibraryWithSource_options_error(self, source: id, options: id, error: id) {
        msg_send![self, newLibraryWithSource:source options:options error:error]
    }

    unsafe fn newLibraryWithData_error(self, data: id, error: id) {
        msg_send![self, newLibraryWithData:data error:error]
    }

    unsafe fn newCommandQueue(self) -> id {
        msg_send![self, newCommandQueue]
    }

    unsafe fn newCommandQueueWithMaxCommandBufferCount(self, maxCommandBufferCount: NSUInteger) -> id {
        msg_send![self, newCommandQueueWithMaxCommandBufferCount:maxCommandBufferCount]
    }

    unsafe fn newBufferWithLength_Options(self, length: NSUInteger, options: id) -> id {
        msg_send![self, newBufferWithLength:length options:options]
    }

    unsafe fn newBufferWithBytes_Length_Options(self, pointer: *mut c_void, length: NSUInteger, options: id) -> id {
        unimplemented!()
    }

    unsafe fn newBufferWithBytesNoCopy_length_options_deallocator(self,
                                                                  pointer: *mut c_void,
                                                                  length: NSUInteger,
                                                                  deallocator: Block<(*mut c_void, NSUInteger), ()>) {
        unimplemented!()
    }

    unsafe fn newTextureWithDescriptor(self, descriptor: id) -> id {
        unimplemented!()
    }

    unsafe fn newSamplerStateWithDescriptor(self, descriptor: id) -> id {
        unimplemented!()
    }

    unsafe fn newStencilDepthStateWithDescriptor(self, descriptor: id) -> id {
        unimplemented!()
    }

    unsafe fn newRenderPipleineStateWithDescriptor_completionHandler(
                                                    self,
                                                    completionHandler: MTLNewRenderPipleineStateCompletionHandler) {
        unimplemented!()
    }

    unsafe fn newRenderPipelineStateWithDescriptor_options_completionHandler(
                                        self,
                                        options: MTLPipelineOption,
                                        completionHandler: MTLNewRenderPipelineStateWithReflectionCompletionHandler) {
        unimplemented!()
    }

    unsafe fn newRenderPipelineStateWithDescriptor_error(self, error: id) {
        unimplemented!()
    }

    unsafe fn newRenderPipelineStateWithDescriptor_options_reflection(self,
                                                                      options: MTLPipelineOption,
                                                                      reflection: id,
                                                                      error: id) {
        unimplemented!()
    }

    unsafe fn newComputePipelineStateWithFunction_completionHandler(
                                                        self,
                                                        function: id,
                                                        completionHandler: MTLNewComputePipelineStateCompletionHandler) {
        unimplemented!()
    }

    unsafe fn newComputePipelineStateWithFunction_options_completionHandler(
                                        self,
                                        function: id,
                                        options: MTLPipelineOption,
                                        completionHandler: MTLNewComputePipelineStateWithReflectionCompletionHandler) {
        unimplemented!()
    }

    unsafe fn newComputePipelineStateWithFunction_error(self, function: id, error: id) {
        unimplemented!()
    }

    unsafe fn newComputePipelineStateWithFunction_options_reflection_error(self,
                                                                           function: id,
                                                                           options: MTLPipelineOption,
                                                                           reflection: id,
                                                                           error: id) {
        unimplemented!()
    }

    unsafe fn newComputePipelineStateWithDescriptor_options_completionHandler(self,
                                        descriptor: id,
                                        options: MTLPipelineOption,
                                        completionHandler: MTLNewComputePipelineStateWithReflectionCompletionHandler) {
        unimplemented!()
    }
    unsafe fn newComputePipelineStateWithDescriptor_options_reflection_error(self,
                                                                             descriptor: id,
                                                                             options: MTLPipelineOption,
                                                                             reflection: id,
                                                                             error: id) {
        unimplemented!()
    }
}
<commit_msg>Implement rest of MTLDevice methods<commit_after>#![allow(unused_variables)]

use block::Block;
use cocoa::base::{BOOL, id};
use cocoa::foundation::NSUInteger;
use libc::c_void;
use {MTLFeatureSet, MTLPipelineOption, MTLSize};

pub type MTLNewLibraryCompletionHandler = Block<(id,), id>;
pub type MTLNewRenderPipleineStateCompletionHandler = Block<(id, id), ()>;
pub type MTLNewRenderPipelineStateWithReflectionCompletionHandler = Block<(id, id, id), ()>;
pub type MTLNewComputePipelineStateCompletionHandler = Block<(id, id), ()>;
pub type MTLNewComputePipelineStateWithReflectionCompletionHandler = Block<(id, id, id), ()>;

#[cfg(any(target_os = "macos", target_os = "ios"))]
pub trait MTLDevice {
    unsafe fn depth24Stencil8PixelFormatSupported(self) -> BOOL;
    unsafe fn headless(self) -> BOOL;
    unsafe fn lowPower(self) -> BOOL;
    unsafe fn maxThreadsPerGroup(self) -> MTLSize;
    unsafe fn name(self) -> id;
    unsafe fn supportsFeatureSet(self, featureSet: MTLFeatureSet) -> BOOL;
    unsafe fn supportsTextureSampleCount(self, textureSampleCount: NSUInteger) -> BOOL;

    unsafe fn newDefaultLibrary(self) -> id;
    unsafe fn newLibraryWithFile_error(self, filePath: id, error: id) -> id;
    unsafe fn newLibraryWithSource_options_completionHandler(self,
                                                             source: id,
                                                             options: id,
                                                             completionHandler: MTLNewLibraryCompletionHandler);
    unsafe fn newLibraryWithSource_options_error(self, source: id, options: id, error: id);
    unsafe fn newLibraryWithData_error(self, data: id, error: id);

    unsafe fn newCommandQueue(self) -> id;
    unsafe fn newCommandQueueWithMaxCommandBufferCount(self, maxCommandBufferCount: NSUInteger) -> id;

    unsafe fn newBufferWithLength_Options(self, length: NSUInteger, options: id) -> id;
    unsafe fn newBufferWithBytes_Length_Options(self, pointer: *mut c_void, length: NSUInteger, options: id) -> id;
    unsafe fn newBufferWithBytesNoCopy_length_options_deallocator(self,
                                                                  pointer: *mut c_void,
                                                                  length: NSUInteger,
                                                                  deallocator: Block<(*mut c_void, NSUInteger), ()>);

    unsafe fn newTextureWithDescriptor(self, descriptor: id) -> id;
    unsafe fn newSamplerStateWithDescriptor(self, descriptor: id) -> id;

    unsafe fn newStencilDepthStateWithDescriptor(self, descriptor: id) -> id;
    unsafe fn newRenderPipleineStateWithDescriptor_completionHandler(
                                                    self,
                                                    descriptor: id,
                                                    completionHandler: MTLNewRenderPipleineStateCompletionHandler);
    unsafe fn newRenderPipelineStateWithDescriptor_options_completionHandler(
                                        self,
                                        descriptor: id,
                                        options: MTLPipelineOption,
                                        completionHandler: MTLNewRenderPipelineStateWithReflectionCompletionHandler);
    unsafe fn newRenderPipelineStateWithDescriptor_error(self, descriptor: id, error: id);
    unsafe fn newRenderPipelineStateWithDescriptor_options_reflection(self,
                                                                      descriptor: id,
                                                                      options: MTLPipelineOption,
                                                                      reflection: id,
                                                                      error: id);

    unsafe fn newComputePipelineStateWithFunction_completionHandler(
                                                        self,
                                                        function: id,
                                                        completionHandler: MTLNewComputePipelineStateCompletionHandler);
    unsafe fn newComputePipelineStateWithFunction_options_completionHandler(
                                        self,
                                        function: id,
                                        options: MTLPipelineOption,
                                        completionHandler: MTLNewComputePipelineStateWithReflectionCompletionHandler);
    unsafe fn newComputePipelineStateWithFunction_error(self, function: id, error: id);
    unsafe fn newComputePipelineStateWithFunction_options_reflection_error(self,
                                                                           function: id,
                                                                           options: MTLPipelineOption,
                                                                           reflection: id,
                                                                           error: id);

    unsafe fn newComputePipelineStateWithDescriptor_options_completionHandler(self,
                                        descriptor: id,
                                        options: MTLPipelineOption,
                                        completionHandler: MTLNewComputePipelineStateWithReflectionCompletionHandler);
    unsafe fn newComputePipelineStateWithDescriptor_options_reflection_error(self,
                                                                             descriptor: id,
                                                                             options: MTLPipelineOption,
                                                                             reflection: id,
                                                                             error: id);
}

impl MTLDevice for id {
    unsafe fn depth24Stencil8PixelFormatSupported(self) -> BOOL {
        msg_send![self, isDepth24Stencil8PixelFormatSupported]
    }

    unsafe fn headless(self) -> BOOL {
        msg_send![self, isHeadless]
    }

    unsafe fn lowPower(self) -> BOOL {
        msg_send![self, isLowPower]
    }

    unsafe fn maxThreadsPerGroup(self) -> MTLSize {
        msg_send![self, maxThreadsPerThreadgroup]
    }

    unsafe fn name(self) -> id {
        msg_send![self, name]
    }

    unsafe fn supportsFeatureSet(self, featureSet: MTLFeatureSet) -> BOOL {
        msg_send![self, supportsFeatureSet:featureSet]
    }

    unsafe fn supportsTextureSampleCount(self, textureSampleCount: NSUInteger) -> BOOL {
        msg_send![self, supportsTextureSampleCount:textureSampleCount]
    }

    unsafe fn newDefaultLibrary(self) -> id {
        msg_send![self, newDefaultLibrary]
    }

    unsafe fn newLibraryWithFile_error(self, filePath: id, error: id) -> id {
        msg_send![self, newLibraryWithFile:filePath error:error]
    }

    unsafe fn newLibraryWithSource_options_completionHandler(self,
                                                             source: id,
                                                             options: id,
                                                             completionHandler: MTLNewLibraryCompletionHandler) {
        msg_send![self, newLibraryWithSource:source options:options completionHandler:completionHandler]
    }

    unsafe fn newLibraryWithSource_options_error(self, source: id, options: id, error: id) {
        msg_send![self, newLibraryWithSource:source options:options error:error]
    }

    unsafe fn newLibraryWithData_error(self, data: id, error: id) {
        msg_send![self, newLibraryWithData:data error:error]
    }

    unsafe fn newCommandQueue(self) -> id {
        msg_send![self, newCommandQueue]
    }

    unsafe fn newCommandQueueWithMaxCommandBufferCount(self, maxCommandBufferCount: NSUInteger) -> id {
        msg_send![self, newCommandQueueWithMaxCommandBufferCount:maxCommandBufferCount]
    }

    unsafe fn newBufferWithLength_Options(self, length: NSUInteger, options: id) -> id {
        msg_send![self, newBufferWithLength:length options:options]
    }

    unsafe fn newBufferWithBytes_Length_Options(self, pointer: *mut c_void, length: NSUInteger, options: id) -> id {
        msg_send![self, newBufferWithBytes:pointer length:length options:options]
    }

    unsafe fn newBufferWithBytesNoCopy_length_options_deallocator(self,
                                                                  pointer: *mut c_void,
                                                                  length: NSUInteger,
                                                                  deallocator: Block<(*mut c_void, NSUInteger), ()>) {
        msg_send![self, newBufferWithBytesNoCopy:pointer length:length deallocator:deallocator]
    }

    unsafe fn newTextureWithDescriptor(self, descriptor: id) -> id {
        msg_send![self, newTextureWithDescriptor:descriptor]
    }

    unsafe fn newSamplerStateWithDescriptor(self, descriptor: id) -> id {
        msg_send![self, newSamplerStateWithDescriptor:descriptor]
    }

    unsafe fn newStencilDepthStateWithDescriptor(self, descriptor: id) -> id {
        msg_send![self, newStencilDepthStateWithDescriptor:descriptor]
    }

    unsafe fn newRenderPipleineStateWithDescriptor_completionHandler(
                                                    self,
                                                    descriptor: id,
                                                    completionHandler: MTLNewRenderPipleineStateCompletionHandler) {
        msg_send![self, newRenderPipleineStateWithDescriptor:descriptor completionHandler:completionHandler]
    }

    unsafe fn newRenderPipelineStateWithDescriptor_options_completionHandler(
                                        self,
                                        descriptor: id,
                                        options: MTLPipelineOption,
                                        completionHandler: MTLNewRenderPipelineStateWithReflectionCompletionHandler) {
        msg_send![self, newRenderPipelineStateWithDescriptor:descriptor
                                                     options:options
                                           completionHandler:completionHandler]
    }

    unsafe fn newRenderPipelineStateWithDescriptor_error(self, descriptor: id, error: id) {
        msg_send![self, newRenderPipelineStateWithDescriptor:descriptor error:error]
    }

    unsafe fn newRenderPipelineStateWithDescriptor_options_reflection(self,
                                                                      descriptor: id,
                                                                      options: MTLPipelineOption,
                                                                      reflection: id,
                                                                      error: id) {
        msg_send![self, newRenderPipelineStateWithDescriptor:descriptor
                                                     options:options
                                                  reflection:reflection
                                                       error:error]
    }

    unsafe fn newComputePipelineStateWithFunction_completionHandler(
                                                        self,
                                                        function: id,
                                                        completionHandler: MTLNewComputePipelineStateCompletionHandler) {
        msg_send![self, newComputePipelineStateWithFunction:function completionHandler:completionHandler]
    }

    unsafe fn newComputePipelineStateWithFunction_options_completionHandler(
                                        self,
                                        function: id,
                                        options: MTLPipelineOption,
                                        completionHandler: MTLNewComputePipelineStateWithReflectionCompletionHandler) {
        msg_send![self, newComputePipelineStateWithFunction:function
                                                    options:options
                                          completionHandler:completionHandler]
    }

    unsafe fn newComputePipelineStateWithFunction_error(self, function: id, error: id) {
        msg_send![self, newComputePipelineStateWithFunction:function error:error]
    }

    unsafe fn newComputePipelineStateWithFunction_options_reflection_error(self,
                                                                           function: id,
                                                                           options: MTLPipelineOption,
                                                                           reflection: id,
                                                                           error: id) {
        msg_send![self, newComputePipelineStateWithFunction:function options:options reflection:reflection error:error]
    }

    unsafe fn newComputePipelineStateWithDescriptor_options_completionHandler(
                    self,
                    descriptor: id,
                    options: MTLPipelineOption,
                    completionHandler: MTLNewComputePipelineStateWithReflectionCompletionHandler) {
        msg_send![self, newComputePipelineStateWithDescriptor:descriptor
                                                      options:options
                                            completionHandler:completionHandler]
    }
    unsafe fn newComputePipelineStateWithDescriptor_options_reflection_error(self,
                                                                             descriptor: id,
                                                                             options: MTLPipelineOption,
                                                                             reflection: id,
                                                                             error: id) {
        msg_send![self, newComputePipelineStateWithDescriptor:descriptor
                                                      options:options
                                                   reflection:reflection
                                                        error:error]
    }
}
<|endoftext|>


<commit_before>/* Copyright (c) 2014, Peter Nelson
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#![crate_id = "jit#0.1.2"]
#![comment = "LibJIT Bindings"]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![allow(raw_pointer_deriving, dead_code, non_camel_case_types)]
#![deny(unnecessary_parens, unrecognized_lint, unreachable_code, unnecessary_allocation, unnecessary_typecast, unnecessary_allocation, uppercase_variables, unused_must_use)]
#![feature(globs, macro_rules)]
#![stable]

//! This crate wraps LibJIT

extern crate libc;
use bindings::{
	jit_init,
	jit_uses_interpreter,
	jit_supports_threads,
	jit_supports_virtual_memory
};
pub use bindings::{
	jit_nint,
	jit_nuint
};
pub use compilable::Compilable;
pub use context::{
	Context,
	Functions
};
pub use function::{
	ABI,
	CDECL,
	Function
};
pub use label::Label;
pub use types::*;
pub use util::NativeRef;
pub use value::Value;

/// Initialise the library and prepare for operations
#[inline]
pub fn init() -> () {
	unsafe {
		jit_init()
	}
}
/// Check if the JIT is using a fallback interpreter
#[inline]
pub fn uses_interpreter() -> bool {
	unsafe {
		jit_uses_interpreter() != 0
	}
}
/// Check if the JIT supports theads
#[inline]
pub fn supports_threads() -> bool {
	unsafe {
		jit_supports_threads() != 0
	}
}
/// Check if the JIT supports virtual memory
#[inline]
pub fn supports_virtual_memory() -> bool {
	unsafe {
		jit_supports_virtual_memory() != 0
	}
}
macro_rules! native_ref(
	($name:ident, $field:ident, $pointer_ty:ty) => (
		pub struct $name {
			$field: $pointer_ty
		}
		impl NativeRef for $name {
			#[inline]
			/// Convert to a native pointer
			unsafe fn as_ptr(&self) -> $pointer_ty {
				self.$field
			}
			#[inline]
			/// Convert from a native pointer
			unsafe fn from_ptr(ptr:$pointer_ty) -> $name {
				$name {
					$field: ptr
				}
			}
		}
	)
)
mod bindings;
mod context;
mod compilable;
mod function;
mod label;
mod types;
mod util;
mod value;<commit_msg>Update docs<commit_after>/* Copyright (c) 2014, Peter Nelson
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#![crate_id = "jit#0.1.2"]
#![comment = "LibJIT Bindings"]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![allow(raw_pointer_deriving, dead_code, non_camel_case_types)]
#![deny(unnecessary_parens, unrecognized_lint, unreachable_code, unnecessary_allocation, unnecessary_typecast, unnecessary_allocation, uppercase_variables, unused_must_use)]
#![feature(globs, macro_rules)]
#![stable]
//! This crate wraps LibJIT in an idiomatic style.
//! For example, here's a quick example which makes a multiply function using LibJIT:
//!
//! ```rust
//! extern crate jit;
//! use jit::{C_DECL, Context, Function, Type, Types};
//! fn main() {
//! 	let cx = Context::new();
//! 	cx.build(|| {
//! 		// build the IR
//! 		let sig = Type::create_signature(C_DECL, &Types::get_int(), &[&Types::get_int(), &Types::get_int()]);
//! 		let func = Function::new(cx, sig);
//! 		let x = func.get_param(0);
//! 		let y = func.get_param(1);
//! 		let result = func.insn_mul(&x, &y);
//! 		func.insn_return(&result);
//! 		/// run the IR
//! 		func.compile();
//! 		let rfunc:fn(int, int) -> int = func.closure();
//! 		assert_eq(rfunc(4, 5), 20)
//! 	});
//! }
//! ```

extern crate libc;
use bindings::{
	jit_init,
	jit_uses_interpreter,
	jit_supports_threads,
	jit_supports_virtual_memory
};
pub use bindings::{
	jit_nint,
	jit_nuint
};
pub use compilable::Compilable;
pub use context::{
	Context,
	Functions
};
pub use function::{
	ABI,
	CDECL,
	Function
};
pub use label::Label;
pub use types::*;
pub use util::NativeRef;
pub use value::Value;

/// Initialise the library and prepare for operations
#[inline]
pub fn init() -> () {
	unsafe {
		jit_init()
	}
}
/// Check if the JIT is using a fallback interpreter
#[inline]
pub fn uses_interpreter() -> bool {
	unsafe {
		jit_uses_interpreter() != 0
	}
}
/// Check if the JIT supports theads
#[inline]
pub fn supports_threads() -> bool {
	unsafe {
		jit_supports_threads() != 0
	}
}
/// Check if the JIT supports virtual memory
#[inline]
pub fn supports_virtual_memory() -> bool {
	unsafe {
		jit_supports_virtual_memory() != 0
	}
}
macro_rules! native_ref(
	($name:ident, $field:ident, $pointer_ty:ty) => (
		pub struct $name {
			$field: $pointer_ty
		}
		impl NativeRef for $name {
			#[inline]
			/// Convert to a native pointer
			unsafe fn as_ptr(&self) -> $pointer_ty {
				self.$field
			}
			#[inline]
			/// Convert from a native pointer
			unsafe fn from_ptr(ptr:$pointer_ty) -> $name {
				$name {
					$field: ptr
				}
			}
		}
	)
)
mod bindings;
mod context;
mod compilable;
mod function;
mod label;
mod types;
mod util;
mod value;<|endoftext|>


<commit_before>use extra::url::Url;
use method::{Method, Options};
use status;
use std::rt::io::{Reader, Writer};
use std::rt::io::net::ip::SocketAddr;
use rfc2616::{CR, LF, SP};
use headers;
use buffer::{BufferedStream, BufTcpStream};
use common::read_http_version;

use headers::{HeaderLineErr, EndOfFile, EndOfHeaders, MalformedHeaderSyntax, MalformedHeaderValue};

/// Line/header can't be more than 4KB long (note that with the compacting of LWS the actual source
/// data could be longer than 4KB)
static MAX_LINE_LEN: uint = 0x1000;

static MAX_REQUEST_URI_LEN: uint = 1024;
pub static MAX_METHOD_LEN: uint = 64;
static MAX_HTTP_VERSION_LEN: uint = 1024;

/// Moderately arbitrary figure: read in 64KB chunks. GET requests should never be this large.
static BUF_SIZE: uint = 0x10000;  // Let's try 64KB chunks

pub struct RequestBuffer<'self, S> {
    /// The socket connection to read from
    stream: &'self mut BufferedStream<S>,

    /// A working space for
    line_bytes: ~[u8],
}

impl<'self, S: Reader + Writer> RequestBuffer<'self, S> {
    pub fn new<'a>(stream: &'a mut BufferedStream<S>) -> RequestBuffer<'a, S> {
        RequestBuffer {
            stream: stream,
            line_bytes: ~[0u8, ..MAX_LINE_LEN],
        }
    }

    pub fn read_request_line(&mut self) -> Result<(Method, RequestUri, (uint, uint)),
                                                  status::Status> {
        let method = match self.read_method() {
            Some(m) => m,
            // TODO: this is a very common case, if a connection is kept open but then closed or
            // timed out. We should handle that case specially if we can improve perf—check if the
            // peer is still there and just drop the request if it is not
            None => return Err(status::BadRequest),
        };

        let request_uri = match self.read_request_uri() {
            Ok(m) => m,
            Err(e) => return Err(e),
        };

        match (read_http_version(self.stream, CR), self.stream.read_byte()) {
            (Some(vv), Some(b)) if b == LF => Ok((method, request_uri, vv)),
            _ => return Err(status::BadRequest),
        }
    }

    #[inline]
    fn read_method(&mut self) -> Option<Method> {
        include!("../generated/read_method.rs");
    }

    #[inline]
    fn read_request_uri(&mut self) -> Result<RequestUri, status::Status> {
        // Got that, including consuming the SP; now get the request_uri
        let mut request_uri = ~"";
        loop {
            match self.stream.read_byte() {
                None => return Err(status::BadRequest),
                Some(b) if b == SP => break,
                Some(b) => {
                    if request_uri.len() == MAX_REQUEST_URI_LEN {
                        return Err(status::RequestUriTooLong)
                    }
                    request_uri.push_char(b as char);
                }
            }
        }
        match FromStr::from_str(request_uri) {
            Some(r) => Ok(r),
            None => Err(status::BadRequest),
        }
    }

    /// Read a header (name, value) pair.
    ///
    /// This is not necessarily just a line ending with CRLF; there are much fancier rules at work.
    /// Where appropriate (TODO, it's everywhere at present) linear whitespace is collapsed into a
    /// single space.
    ///
    /// # Error values
    ///
    /// - `EndOfHeaders`: I have no more headers to give; go forth and conquer on the body!
    /// - `EndOfFile`: socket was closed unexpectedly; probable best behavour is to drop the request
    /// - `MalformedHeaderValue`: header's value is invalid; normally, ignore it.
    /// - `MalformedHeaderSyntax`: bad request; you could drop it or try returning 400 Bad Request
    pub fn read_header<T: headers::HeaderEnum>(&mut self) -> Result<T, HeaderLineErr> {
        match headers::header_enum_from_stream(self.stream) {
        //match headers::HeaderEnum::from_stream(self.stream) {
            (Err(m), None) => Err(m),
            (Err(m), Some(b)) => {
                self.stream.poke_byte(b);
                Err(m)
            },
            (Ok(header), Some(b)) => {
                self.stream.poke_byte(b);
                Ok(header)
            }
            (Ok(_header), None) => unreachable!()
        }
    }
}

/// An HTTP request sent to the server.
pub struct Request {
    /// The originating IP address of the request.
    remote_addr: Option<SocketAddr>,

    /// The host name and IP address that the request was sent to; this must always be specified for
    /// HTTP/1.1 requests (or the request will be rejected), but for HTTP/1.0 requests the Host
    /// header was not defined, and so this field will probably be None in such cases.
    //host: Option<Host>,  // Now in headers.host

    /// The headers sent with the request.
    headers: ~headers::request::HeaderCollection,

    /// The body of the request; empty for such methods as GET.
    body: ~str,

    /// The HTTP method for the request.
    method: Method,

    /// The URI that was requested, as found in the Request-URI of the Request-Line.
    /// You will almost never need to use this; you should prefer the `url` field instead.
    request_uri: RequestUri,

    /// Whether to close the TCP connection when the request has been served.
    /// The alternative is keeping the connection open and waiting for another request.
    close_connection: bool,

    /// The HTTP version number; typically `(1, 1)` or, less commonly, `(1, 0)`.
    version: (uint, uint)
}

/// The URI (Request-URI in RFC 2616) as specified in the Status-Line of an HTTP request
#[deriving(Eq)]
pub enum RequestUri {
    /// 'The asterisk "*" means that the request does not apply to a particular resource, but to the
    /// server itself, and is only allowed when the method used does not necessarily apply to a
    /// resource. One example would be "OPTIONS * HTTP/1.1" '
    Star,

    /// 'The absoluteURI form is REQUIRED when the request is being made to a proxy. The proxy is
    /// requested to forward the request or service it from a valid cache, and return the response.
    /// Note that the proxy MAY forward the request on to another proxy or directly to the server
    /// specified by the absoluteURI. In order to avoid request loops, a proxy MUST be able to
    /// recognize all of its server names, including any aliases, local variations, and the numeric
    /// IP address. An example Request-Line would be:
    /// "GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1"'
    AbsoluteUri(Url),

    /// 'To allow for transition to absoluteURIs in all requests in future versions of HTTP, all
    /// HTTP/1.1 servers MUST accept the absoluteURI form in requests, even though HTTP/1.1 clients
    /// will only generate them in requests to proxies.'
    ///
    /// TODO: this shouldn't be a string; it should be further parsed. `extra::net::url` has some
    /// stuff which might help, but isn't public.
    AbsolutePath(~str),

    /// 'The authority form is only used by the CONNECT method (CONNECT).'
    ///
    /// TODO: this shouldn't be a string; it should be further parsed. `extra::net::url` has some
    /// stuff which might help, but isn't public.
    Authority(~str),
}

impl FromStr for RequestUri {
    /// Interpret a RFC2616 Request-URI
    fn from_str(request_uri: &str) -> Option<RequestUri> {
        if request_uri == "*" {
            Some(Star)
        } else if request_uri.starts_with("/") {
            Some(AbsolutePath(request_uri.to_owned()))
        } else if request_uri.contains("/") {
            // An authority can't have a slash in it
            match FromStr::from_str(request_uri) {
                Some(url) => Some(AbsoluteUri(url)),
                None => None,
            }
        } else {
            // TODO: parse authority with extra::net::url
            Some(Authority(request_uri.to_owned()))
        }
    }
}

impl Request {

    /// Get a response from an open socket.
    pub fn load(stream: &mut BufTcpStream) -> (~Request, Result<(), status::Status>) {
        let mut buffer = RequestBuffer::new(stream);

        // Start out with dummy values
        let mut request = ~Request {
            remote_addr: buffer.stream.wrapped.peer_name(),
            headers: ~headers::request::HeaderCollection::new(),
            body: ~"",
            method: Options,
            request_uri: Star,
            close_connection: true,
            version: (0, 0),
        };

        let (method, request_uri, version) = match buffer.read_request_line() {
            Ok(vals) => vals,
            Err(err) => return (request, Err(err)),
        };
        request.method = method;
        request.request_uri = request_uri;
        request.version = version;

        // request.close_connection is deliberately left set to true so that in case of a bad
        // request we can close the connection
        let close_connection = match version {
            (1, 0) => true,
            (1, 1) => false,
            _ => return (request, Err(status::HttpVersionNotSupported)),
        };

        loop {
            match buffer.read_header() {
                Err(EndOfFile) => fail!("client disconnected, nowhere to send response"),
                Err(EndOfHeaders) => break,
                Err(MalformedHeaderSyntax) => {
                    println("BAD REQUEST: malformed header (TODO: is this right?)");
                    return (request, Err(status::BadRequest));
                },
                Err(MalformedHeaderValue) => {
                    println("Bad header encountered. TODO: handle this better.");
                    // Now just ignore the header
                },
                Ok(header) => {
                    request.headers.insert(header);
                },
            }
        }

        // HTTP/1.0 doesn't have Host, but HTTP/1.1 requires it
        if request.version == (1, 1) && request.headers.host.is_none() {
            println("BAD REQUEST: host is none for HTTP/1.1 request");
            return (request, Err(status::BadRequest));
        }

        request.close_connection = close_connection;
        match request.headers.connection {
            Some(ref h) => for v in h.iter() {
                match *v {
                    headers::connection::Close => {
                        request.close_connection = true;
                        break;
                    },
                    headers::connection::Token(ref s) if s.as_slice() == "keep-alive" => {
                        request.close_connection = false;
                        // No break; let it be overridden by close should some weird person do that
                    },
                    headers::connection::Token(_) => (),
                }
            },
            None => (),
        }

        (request, Ok(()))
    }
}

/* What follows is most of Go's net/http module's definition of Request.

pub struct Request {
    // GET, POST, etc.
    method: ~Method,

    // The URL requested, constructed from the request line and (if available)
    // the Host header.
    url: ~Url,

    // The HTTP protocol version used; typically (1, 1)
    protocol: (uint, uint),

    // Request headers, all nicely and correctly parsed.
    headers: ~Headers,

    // The message body.
    body: Reader,

    // ContentLength records the length of the associated content.
    // The value -1 indicates that the length is unknown.
    // Values >= 0 indicate that the given number of bytes may
    // be read from Body.
    // For outgoing requests, a value of 0 means unknown if Body is not nil.
    content_length: i64,

    // TransferEncoding lists the transfer encodings from outermost to
    // innermost. An empty list denotes the "identity" encoding.
    // TransferEncoding can usually be ignored; chunked encoding is
    // automatically added and removed as necessary when sending and
    // receiving requests.
    transfer_encoding: ~[~str],

    // Close indicates whether to close the connection after
    // replying to this request.
    close: bool,

    // The host on which the URL is sought.
    // Per RFC 2616, this is either the value of the Host: header
    // or the host name given in the URL itself.
    // It may be of the form "host:port".
    host: ~str,

    // Form contains the parsed form data, including both the URL
    // field's query parameters and the POST or PUT form data.
    // This field is only available after ParseForm is called.
    // The HTTP client ignores Form and uses Body instead.
    form: url.Values,

    // PostForm contains the parsed form data from POST or PUT
    // body parameters.
    // This field is only available after ParseForm is called.
    // The HTTP client ignores PostForm and uses Body instead.
    post_form: url.Values,

    // MultipartForm is the parsed multipart form, including file uploads.
    // This field is only available after ParseMultipartForm is called.
    // The HTTP client ignores MultipartForm and uses Body instead.
    multipart_form: *multipart.Form,

    // Trailer maps trailer keys to values.  Like for Header, if the
    // response has multiple trailer lines with the same key, they will be
    // concatenated, delimited by commas.
    // For server requests, Trailer is only populated after Body has been
    // closed or fully consumed.
    // Trailer support is only partially complete.
    trailer: ~Headers,

    // RemoteAddr allows HTTP servers and other software to record
    // the network address that sent the request, usually for
    // logging. This field is not filled in by ReadRequest and
    // has no defined format. The HTTP server in this package
    // sets RemoteAddr to an "IP:port" address before invoking a
    // handler.
    // This field is ignored by the HTTP client.
    remote_addr: string,

    // RequestURI is the unmodified Request-URI of the
    // Request-Line (RFC 2616, Section 5.1) as sent by the client
    // to a server. Usually the URL field should be used instead.
    // It is an error to set this field in an HTTP client request.
    request_uri: string,

    // TLS allows HTTP servers and other software to record
    // information about the TLS connection on which the request
    // was received. This field is not filled in by ReadRequest.
    // The HTTP server in this package sets the field for
    // TLS-enabled connections before invoking a handler;
    // otherwise it leaves the field nil.
    // This field is ignored by the HTTP client.
    tls: *tls.ConnectionState,
}*/
<commit_msg>Degrade some unreachable header code to a logged error.<commit_after>use extra::url::Url;
use method::{Method, Options};
use status;
use std::rt::io::{Reader, Writer};
use std::rt::io::net::ip::SocketAddr;
use rfc2616::{CR, LF, SP};
use headers;
use buffer::{BufferedStream, BufTcpStream};
use common::read_http_version;

use headers::{HeaderLineErr, EndOfFile, EndOfHeaders, MalformedHeaderSyntax, MalformedHeaderValue};

/// Line/header can't be more than 4KB long (note that with the compacting of LWS the actual source
/// data could be longer than 4KB)
static MAX_LINE_LEN: uint = 0x1000;

static MAX_REQUEST_URI_LEN: uint = 1024;
pub static MAX_METHOD_LEN: uint = 64;
static MAX_HTTP_VERSION_LEN: uint = 1024;

/// Moderately arbitrary figure: read in 64KB chunks. GET requests should never be this large.
static BUF_SIZE: uint = 0x10000;  // Let's try 64KB chunks

pub struct RequestBuffer<'self, S> {
    /// The socket connection to read from
    stream: &'self mut BufferedStream<S>,

    /// A working space for
    line_bytes: ~[u8],
}

impl<'self, S: Reader + Writer> RequestBuffer<'self, S> {
    pub fn new<'a>(stream: &'a mut BufferedStream<S>) -> RequestBuffer<'a, S> {
        RequestBuffer {
            stream: stream,
            line_bytes: ~[0u8, ..MAX_LINE_LEN],
        }
    }

    pub fn read_request_line(&mut self) -> Result<(Method, RequestUri, (uint, uint)),
                                                  status::Status> {
        let method = match self.read_method() {
            Some(m) => m,
            // TODO: this is a very common case, if a connection is kept open but then closed or
            // timed out. We should handle that case specially if we can improve perf—check if the
            // peer is still there and just drop the request if it is not
            None => return Err(status::BadRequest),
        };

        let request_uri = match self.read_request_uri() {
            Ok(m) => m,
            Err(e) => return Err(e),
        };

        match (read_http_version(self.stream, CR), self.stream.read_byte()) {
            (Some(vv), Some(b)) if b == LF => Ok((method, request_uri, vv)),
            _ => return Err(status::BadRequest),
        }
    }

    #[inline]
    fn read_method(&mut self) -> Option<Method> {
        include!("../generated/read_method.rs");
    }

    #[inline]
    fn read_request_uri(&mut self) -> Result<RequestUri, status::Status> {
        // Got that, including consuming the SP; now get the request_uri
        let mut request_uri = ~"";
        loop {
            match self.stream.read_byte() {
                None => return Err(status::BadRequest),
                Some(b) if b == SP => break,
                Some(b) => {
                    if request_uri.len() == MAX_REQUEST_URI_LEN {
                        return Err(status::RequestUriTooLong)
                    }
                    request_uri.push_char(b as char);
                }
            }
        }
        match FromStr::from_str(request_uri) {
            Some(r) => Ok(r),
            None => Err(status::BadRequest),
        }
    }

    /// Read a header (name, value) pair.
    ///
    /// This is not necessarily just a line ending with CRLF; there are much fancier rules at work.
    /// Where appropriate (TODO, it's everywhere at present) linear whitespace is collapsed into a
    /// single space.
    ///
    /// # Error values
    ///
    /// - `EndOfHeaders`: I have no more headers to give; go forth and conquer on the body!
    /// - `EndOfFile`: socket was closed unexpectedly; probable best behavour is to drop the request
    /// - `MalformedHeaderValue`: header's value is invalid; normally, ignore it.
    /// - `MalformedHeaderSyntax`: bad request; you could drop it or try returning 400 Bad Request
    pub fn read_header<T: headers::HeaderEnum>(&mut self) -> Result<T, HeaderLineErr> {
        match headers::header_enum_from_stream(self.stream) {
        //match headers::HeaderEnum::from_stream(self.stream) {
            (Err(m), None) => Err(m),
            (Err(m), Some(b)) => {
                self.stream.poke_byte(b);
                Err(m)
            },
            (Ok(header), Some(b)) => {
                self.stream.poke_byte(b);
                Ok(header)
            }
            (Ok(header), None) => {
                // This should have read an extra byte, on account of the CR LF SP possibility
                error!("header with no next byte, did reading go wrong?");
                Ok(header)
            }
        }
    }
}

/// An HTTP request sent to the server.
pub struct Request {
    /// The originating IP address of the request.
    remote_addr: Option<SocketAddr>,

    /// The host name and IP address that the request was sent to; this must always be specified for
    /// HTTP/1.1 requests (or the request will be rejected), but for HTTP/1.0 requests the Host
    /// header was not defined, and so this field will probably be None in such cases.
    //host: Option<Host>,  // Now in headers.host

    /// The headers sent with the request.
    headers: ~headers::request::HeaderCollection,

    /// The body of the request; empty for such methods as GET.
    body: ~str,

    /// The HTTP method for the request.
    method: Method,

    /// The URI that was requested, as found in the Request-URI of the Request-Line.
    /// You will almost never need to use this; you should prefer the `url` field instead.
    request_uri: RequestUri,

    /// Whether to close the TCP connection when the request has been served.
    /// The alternative is keeping the connection open and waiting for another request.
    close_connection: bool,

    /// The HTTP version number; typically `(1, 1)` or, less commonly, `(1, 0)`.
    version: (uint, uint)
}

/// The URI (Request-URI in RFC 2616) as specified in the Status-Line of an HTTP request
#[deriving(Eq)]
pub enum RequestUri {
    /// 'The asterisk "*" means that the request does not apply to a particular resource, but to the
    /// server itself, and is only allowed when the method used does not necessarily apply to a
    /// resource. One example would be "OPTIONS * HTTP/1.1" '
    Star,

    /// 'The absoluteURI form is REQUIRED when the request is being made to a proxy. The proxy is
    /// requested to forward the request or service it from a valid cache, and return the response.
    /// Note that the proxy MAY forward the request on to another proxy or directly to the server
    /// specified by the absoluteURI. In order to avoid request loops, a proxy MUST be able to
    /// recognize all of its server names, including any aliases, local variations, and the numeric
    /// IP address. An example Request-Line would be:
    /// "GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1"'
    AbsoluteUri(Url),

    /// 'To allow for transition to absoluteURIs in all requests in future versions of HTTP, all
    /// HTTP/1.1 servers MUST accept the absoluteURI form in requests, even though HTTP/1.1 clients
    /// will only generate them in requests to proxies.'
    ///
    /// TODO: this shouldn't be a string; it should be further parsed. `extra::net::url` has some
    /// stuff which might help, but isn't public.
    AbsolutePath(~str),

    /// 'The authority form is only used by the CONNECT method (CONNECT).'
    ///
    /// TODO: this shouldn't be a string; it should be further parsed. `extra::net::url` has some
    /// stuff which might help, but isn't public.
    Authority(~str),
}

impl FromStr for RequestUri {
    /// Interpret a RFC2616 Request-URI
    fn from_str(request_uri: &str) -> Option<RequestUri> {
        if request_uri == "*" {
            Some(Star)
        } else if request_uri.starts_with("/") {
            Some(AbsolutePath(request_uri.to_owned()))
        } else if request_uri.contains("/") {
            // An authority can't have a slash in it
            match FromStr::from_str(request_uri) {
                Some(url) => Some(AbsoluteUri(url)),
                None => None,
            }
        } else {
            // TODO: parse authority with extra::net::url
            Some(Authority(request_uri.to_owned()))
        }
    }
}

impl Request {

    /// Get a response from an open socket.
    pub fn load(stream: &mut BufTcpStream) -> (~Request, Result<(), status::Status>) {
        let mut buffer = RequestBuffer::new(stream);

        // Start out with dummy values
        let mut request = ~Request {
            remote_addr: buffer.stream.wrapped.peer_name(),
            headers: ~headers::request::HeaderCollection::new(),
            body: ~"",
            method: Options,
            request_uri: Star,
            close_connection: true,
            version: (0, 0),
        };

        let (method, request_uri, version) = match buffer.read_request_line() {
            Ok(vals) => vals,
            Err(err) => return (request, Err(err)),
        };
        request.method = method;
        request.request_uri = request_uri;
        request.version = version;

        // request.close_connection is deliberately left set to true so that in case of a bad
        // request we can close the connection
        let close_connection = match version {
            (1, 0) => true,
            (1, 1) => false,
            _ => return (request, Err(status::HttpVersionNotSupported)),
        };

        loop {
            match buffer.read_header() {
                Err(EndOfFile) => fail!("client disconnected, nowhere to send response"),
                Err(EndOfHeaders) => break,
                Err(MalformedHeaderSyntax) => {
                    println("BAD REQUEST: malformed header (TODO: is this right?)");
                    return (request, Err(status::BadRequest));
                },
                Err(MalformedHeaderValue) => {
                    println("Bad header encountered. TODO: handle this better.");
                    // Now just ignore the header
                },
                Ok(header) => {
                    request.headers.insert(header);
                },
            }
        }

        // HTTP/1.0 doesn't have Host, but HTTP/1.1 requires it
        if request.version == (1, 1) && request.headers.host.is_none() {
            println("BAD REQUEST: host is none for HTTP/1.1 request");
            return (request, Err(status::BadRequest));
        }

        request.close_connection = close_connection;
        match request.headers.connection {
            Some(ref h) => for v in h.iter() {
                match *v {
                    headers::connection::Close => {
                        request.close_connection = true;
                        break;
                    },
                    headers::connection::Token(ref s) if s.as_slice() == "keep-alive" => {
                        request.close_connection = false;
                        // No break; let it be overridden by close should some weird person do that
                    },
                    headers::connection::Token(_) => (),
                }
            },
            None => (),
        }

        (request, Ok(()))
    }
}

/* What follows is most of Go's net/http module's definition of Request.

pub struct Request {
    // GET, POST, etc.
    method: ~Method,

    // The URL requested, constructed from the request line and (if available)
    // the Host header.
    url: ~Url,

    // The HTTP protocol version used; typically (1, 1)
    protocol: (uint, uint),

    // Request headers, all nicely and correctly parsed.
    headers: ~Headers,

    // The message body.
    body: Reader,

    // ContentLength records the length of the associated content.
    // The value -1 indicates that the length is unknown.
    // Values >= 0 indicate that the given number of bytes may
    // be read from Body.
    // For outgoing requests, a value of 0 means unknown if Body is not nil.
    content_length: i64,

    // TransferEncoding lists the transfer encodings from outermost to
    // innermost. An empty list denotes the "identity" encoding.
    // TransferEncoding can usually be ignored; chunked encoding is
    // automatically added and removed as necessary when sending and
    // receiving requests.
    transfer_encoding: ~[~str],

    // Close indicates whether to close the connection after
    // replying to this request.
    close: bool,

    // The host on which the URL is sought.
    // Per RFC 2616, this is either the value of the Host: header
    // or the host name given in the URL itself.
    // It may be of the form "host:port".
    host: ~str,

    // Form contains the parsed form data, including both the URL
    // field's query parameters and the POST or PUT form data.
    // This field is only available after ParseForm is called.
    // The HTTP client ignores Form and uses Body instead.
    form: url.Values,

    // PostForm contains the parsed form data from POST or PUT
    // body parameters.
    // This field is only available after ParseForm is called.
    // The HTTP client ignores PostForm and uses Body instead.
    post_form: url.Values,

    // MultipartForm is the parsed multipart form, including file uploads.
    // This field is only available after ParseMultipartForm is called.
    // The HTTP client ignores MultipartForm and uses Body instead.
    multipart_form: *multipart.Form,

    // Trailer maps trailer keys to values.  Like for Header, if the
    // response has multiple trailer lines with the same key, they will be
    // concatenated, delimited by commas.
    // For server requests, Trailer is only populated after Body has been
    // closed or fully consumed.
    // Trailer support is only partially complete.
    trailer: ~Headers,

    // RemoteAddr allows HTTP servers and other software to record
    // the network address that sent the request, usually for
    // logging. This field is not filled in by ReadRequest and
    // has no defined format. The HTTP server in this package
    // sets RemoteAddr to an "IP:port" address before invoking a
    // handler.
    // This field is ignored by the HTTP client.
    remote_addr: string,

    // RequestURI is the unmodified Request-URI of the
    // Request-Line (RFC 2616, Section 5.1) as sent by the client
    // to a server. Usually the URL field should be used instead.
    // It is an error to set this field in an HTTP client request.
    request_uri: string,

    // TLS allows HTTP servers and other software to record
    // information about the TLS connection on which the request
    // was received. This field is not filled in by ReadRequest.
    // The HTTP server in this package sets the field for
    // TLS-enabled connections before invoking a handler;
    // otherwise it leaves the field nil.
    // This field is ignored by the HTTP client.
    tls: *tls.ConnectionState,
}*/
<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use env;
use fmt;
use io::prelude::*;
use sync::atomic::{self, Ordering};
use sys::stdio::Stderr;
use thread;

pub fn min_stack() -> usize {
    static MIN: atomic::AtomicUsize = atomic::AtomicUsize::new(0);
    match MIN.load(Ordering::SeqCst) {
        0 => {}
        n => return n - 1,
    }
    let amt = env::var("RUST_MIN_STACK").ok().and_then(|s| s.parse().ok());
    let amt = amt.unwrap_or(2 * 1024 * 1024);
    // 0 is our sentinel value, so ensure that we'll never see 0 after
    // initialization has run
    MIN.store(amt + 1, Ordering::SeqCst);
    amt
}

pub fn dumb_print(args: fmt::Arguments) {
    let _ = Stderr::new().map(|mut stderr| stderr.write_fmt(args));
}

// On Unix-like platforms, libc::abort will unregister signal handlers
// including the SIGABRT handler, preventing the abort from being blocked, and
// fclose streams, with the side effect of flushing them so libc bufferred
// output will be printed.  Additionally the shell will generally print a more
// understandable error message like "Abort trap" rather than "Illegal
// instruction" that intrinsics::abort would cause, as intrinsics::abort is
// implemented as an illegal instruction.
#[cfg(unix)]
unsafe fn abort_internal() -> ! {
    use libc;
    libc::abort()
}

// On Windows, we want to avoid using libc, and there isn't a direct
// equivalent of libc::abort.  The __failfast intrinsic may be a reasonable
// substitute, but desireability of using it over the abort instrinsic is
// debateable; see https://github.com/rust-lang/rust/pull/31519 for details.
#[cfg(not(unix))]
unsafe fn abort_internal() -> ! {
    use intrinsics;
    intrinsics::abort()
}

pub fn abort(args: fmt::Arguments) -> ! {
    dumb_print(format_args!("fatal runtime error: {}\n", args));
    unsafe { abort_internal(); }
}

#[allow(dead_code)] // stack overflow detection not enabled on all platforms
pub unsafe fn report_overflow() {
    dumb_print(format_args!("\nthread '{}' has overflowed its stack\n",
                            thread::current().name().unwrap_or("<unknown>")));
}
<commit_msg>Open code the __fastfail intrinsic for rtabort! on windows<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use env;
use fmt;
use io::prelude::*;
use sync::atomic::{self, Ordering};
use sys::stdio::Stderr;
use thread;

pub fn min_stack() -> usize {
    static MIN: atomic::AtomicUsize = atomic::AtomicUsize::new(0);
    match MIN.load(Ordering::SeqCst) {
        0 => {}
        n => return n - 1,
    }
    let amt = env::var("RUST_MIN_STACK").ok().and_then(|s| s.parse().ok());
    let amt = amt.unwrap_or(2 * 1024 * 1024);
    // 0 is our sentinel value, so ensure that we'll never see 0 after
    // initialization has run
    MIN.store(amt + 1, Ordering::SeqCst);
    amt
}

pub fn dumb_print(args: fmt::Arguments) {
    let _ = Stderr::new().map(|mut stderr| stderr.write_fmt(args));
}

// On Unix-like platforms, libc::abort will unregister signal handlers
// including the SIGABRT handler, preventing the abort from being blocked, and
// fclose streams, with the side effect of flushing them so libc bufferred
// output will be printed.  Additionally the shell will generally print a more
// understandable error message like "Abort trap" rather than "Illegal
// instruction" that intrinsics::abort would cause, as intrinsics::abort is
// implemented as an illegal instruction.
#[cfg(unix)]
unsafe fn abort_internal() -> ! {
    ::libc::abort()
}

// On Windows, use the processor-specific __fastfail mechanism.  In Windows 8
// and later, this will terminate the process immediately without running any
// in-process exception handlers.  In earlier versions of Windows, this
// sequence of instructions will be treated as an access violation,
// terminating the process but without necessarily bypassing all exception
// handlers.
//
// https://msdn.microsoft.com/en-us/library/dn774154.aspx
#[cfg(all(windows, any(target_arch = "x86", target_arch = "x86_64")))]
unsafe fn abort_internal() -> ! {
    asm!("int $$0x29" :: "{ecx}"(7) ::: volatile); // 7 is FAST_FAIL_FATAL_APP_EXIT
    ::intrinsics::unreachable();
}

// Other platforms should use the appropriate platform-specific mechanism for
// aborting the process.  If no platform-specific mechanism is available,
// ::intrinsics::abort() may be used instead.  The above implementations cover
// all targets currently supported by libstd.

pub fn abort(args: fmt::Arguments) -> ! {
    dumb_print(format_args!("fatal runtime error: {}\n", args));
    unsafe { abort_internal(); }
}

#[allow(dead_code)] // stack overflow detection not enabled on all platforms
pub unsafe fn report_overflow() {
    dumb_print(format_args!("\nthread '{}' has overflowed its stack\n",
                            thread::current().name().unwrap_or("<unknown>")));
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-lexer-test FIXME #15877

//! Windows specific console TTY implementation
//!
//! This module contains the implementation of a Windows specific console TTY.
//! Also converts between UTF-16 and UTF-8. Windows has very poor support for
//! UTF-8 and some functions will panic. In particular ReadFile and ReadConsole
//! will panic when the codepage is set to UTF-8 and a Unicode character is
//! entered.
//!
//! FIXME
//! This implementation does not account for codepoints that are split across
//! multiple reads and writes. Also, this implementation does not expose a way
//! to read/write UTF-16 directly. When/if Rust receives a Reader/Writer
//! wrapper that performs encoding/decoding, this implementation should switch
//! to working in raw UTF-16, with such a wrapper around it.

use prelude::v1::*;

use old_io::{self, IoError, IoResult, MemReader};
use iter::repeat;
use libc::types::os::arch::extra::LPCVOID;
use libc::{c_int, HANDLE, LPDWORD, DWORD, LPVOID};
use libc::{get_osfhandle, CloseHandle};
use mem;
use ptr;
use str::from_utf8;
use super::c::{ENABLE_ECHO_INPUT, ENABLE_EXTENDED_FLAGS};
use super::c::{ENABLE_INSERT_MODE, ENABLE_LINE_INPUT};
use super::c::{ENABLE_PROCESSED_INPUT, ENABLE_QUICK_EDIT_MODE};
use super::c::{CONSOLE_SCREEN_BUFFER_INFO};
use super::c::{ReadConsoleW, WriteConsoleW, GetConsoleMode, SetConsoleMode};
use super::c::{GetConsoleScreenBufferInfo};

fn invalid_encoding() -> IoError {
    IoError {
        kind: old_io::InvalidInput,
        desc: "text was not valid unicode",
        detail: None,
    }
}

pub fn is_tty(fd: c_int) -> bool {
    let mut out: DWORD = 0;
    // If this function doesn't panic then fd is a TTY
    match unsafe { GetConsoleMode(get_osfhandle(fd) as HANDLE,
                                  &mut out as LPDWORD) } {
        0 => false,
        _ => true,
    }
}

pub struct TTY {
    closeme: bool,
    handle: HANDLE,
    utf8: MemReader,
}

impl TTY {
    pub fn new(fd: c_int) -> IoResult<TTY> {
        if is_tty(fd) {
            // If the file descriptor is one of stdin, stderr, or stdout
            // then it should not be closed by us
            let closeme = match fd {
                0...2 => false,
                _ => true,
            };
            let handle = unsafe { get_osfhandle(fd) as HANDLE };
            Ok(TTY {
                handle: handle,
                utf8: MemReader::new(Vec::new()),
                closeme: closeme,
            })
        } else {
            Err(IoError {
                kind: old_io::MismatchedFileTypeForOperation,
                desc: "invalid handle provided to function",
                detail: None,
            })
        }
    }

    pub fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        // Read more if the buffer is empty
        if self.utf8.eof() {
            let mut utf16: Vec<u16> = repeat(0u16).take(0x1000).collect();
            let mut num: DWORD = 0;
            match unsafe { ReadConsoleW(self.handle,
                                         utf16.as_mut_ptr() as LPVOID,
                                         utf16.len() as u32,
                                         &mut num as LPDWORD,
                                         ptr::null_mut()) } {
                0 => return Err(super::last_error()),
                _ => (),
            };
            utf16.truncate(num as uint);
            let utf8 = match String::from_utf16(&utf16) {
                Ok(utf8) => utf8.into_bytes(),
                Err(..) => return Err(invalid_encoding()),
            };
            self.utf8 = MemReader::new(utf8);
        }
        // MemReader shouldn't error here since we just filled it
        Ok(self.utf8.read(buf).unwrap())
    }

    pub fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        let utf16 = match from_utf8(buf).ok() {
            Some(utf8) => {
                utf8.utf16_units().collect::<Vec<u16>>()
            }
            None => return Err(invalid_encoding()),
        };
        let mut num: DWORD = 0;
        match unsafe { WriteConsoleW(self.handle,
                                     utf16.as_ptr() as LPCVOID,
                                     utf16.len() as u32,
                                     &mut num as LPDWORD,
                                     ptr::null_mut()) } {
            0 => Err(super::last_error()),
            _ => Ok(()),
        }
    }

    pub fn set_raw(&mut self, raw: bool) -> IoResult<()> {
        // FIXME
        // Somebody needs to decide on which of these flags we want
        match unsafe { SetConsoleMode(self.handle,
            match raw {
                true => 0,
                false => ENABLE_ECHO_INPUT | ENABLE_EXTENDED_FLAGS |
                         ENABLE_INSERT_MODE | ENABLE_LINE_INPUT |
                         ENABLE_PROCESSED_INPUT | ENABLE_QUICK_EDIT_MODE,
            }) } {
            0 => Err(super::last_error()),
            _ => Ok(()),
        }
    }

    pub fn get_winsize(&mut self) -> IoResult<(int, int)> {
        let mut info: CONSOLE_SCREEN_BUFFER_INFO = unsafe { mem::zeroed() };
        match unsafe { GetConsoleScreenBufferInfo(self.handle, &mut info as *mut _) } {
            0 => Err(super::last_error()),
            _ => Ok(((info.srWindow.Right + 1 - info.srWindow.Left) as int,
                     (info.srWindow.Bottom + 1 - info.srWindow.Top) as int)),
        }
    }
}

impl Drop for TTY {
    fn drop(&mut self) {
        if self.closeme {
            // Nobody cares about the return value
            let _ = unsafe { CloseHandle(self.handle) };
        }
    }
}
<commit_msg>Rollup merge of #22772 - tbu-:pr_panic_fail, r=alexcrichton<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-lexer-test FIXME #15877

//! Windows specific console TTY implementation
//!
//! This module contains the implementation of a Windows specific console TTY.
//! Also converts between UTF-16 and UTF-8. Windows has very poor support for
//! UTF-8 and some functions will panic. In particular ReadFile and ReadConsole
//! will panic when the codepage is set to UTF-8 and a Unicode character is
//! entered.
//!
//! FIXME
//! This implementation does not account for codepoints that are split across
//! multiple reads and writes. Also, this implementation does not expose a way
//! to read/write UTF-16 directly. When/if Rust receives a Reader/Writer
//! wrapper that performs encoding/decoding, this implementation should switch
//! to working in raw UTF-16, with such a wrapper around it.

use prelude::v1::*;

use old_io::{self, IoError, IoResult, MemReader};
use iter::repeat;
use libc::types::os::arch::extra::LPCVOID;
use libc::{c_int, HANDLE, LPDWORD, DWORD, LPVOID};
use libc::{get_osfhandle, CloseHandle};
use mem;
use ptr;
use str::from_utf8;
use super::c::{ENABLE_ECHO_INPUT, ENABLE_EXTENDED_FLAGS};
use super::c::{ENABLE_INSERT_MODE, ENABLE_LINE_INPUT};
use super::c::{ENABLE_PROCESSED_INPUT, ENABLE_QUICK_EDIT_MODE};
use super::c::{CONSOLE_SCREEN_BUFFER_INFO};
use super::c::{ReadConsoleW, WriteConsoleW, GetConsoleMode, SetConsoleMode};
use super::c::{GetConsoleScreenBufferInfo};

fn invalid_encoding() -> IoError {
    IoError {
        kind: old_io::InvalidInput,
        desc: "text was not valid unicode",
        detail: None,
    }
}

pub fn is_tty(fd: c_int) -> bool {
    let mut out: DWORD = 0;
    // If this function doesn't return an error, then fd is a TTY
    match unsafe { GetConsoleMode(get_osfhandle(fd) as HANDLE,
                                  &mut out as LPDWORD) } {
        0 => false,
        _ => true,
    }
}

pub struct TTY {
    closeme: bool,
    handle: HANDLE,
    utf8: MemReader,
}

impl TTY {
    pub fn new(fd: c_int) -> IoResult<TTY> {
        if is_tty(fd) {
            // If the file descriptor is one of stdin, stderr, or stdout
            // then it should not be closed by us
            let closeme = match fd {
                0...2 => false,
                _ => true,
            };
            let handle = unsafe { get_osfhandle(fd) as HANDLE };
            Ok(TTY {
                handle: handle,
                utf8: MemReader::new(Vec::new()),
                closeme: closeme,
            })
        } else {
            Err(IoError {
                kind: old_io::MismatchedFileTypeForOperation,
                desc: "invalid handle provided to function",
                detail: None,
            })
        }
    }

    pub fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        // Read more if the buffer is empty
        if self.utf8.eof() {
            let mut utf16: Vec<u16> = repeat(0u16).take(0x1000).collect();
            let mut num: DWORD = 0;
            match unsafe { ReadConsoleW(self.handle,
                                         utf16.as_mut_ptr() as LPVOID,
                                         utf16.len() as u32,
                                         &mut num as LPDWORD,
                                         ptr::null_mut()) } {
                0 => return Err(super::last_error()),
                _ => (),
            };
            utf16.truncate(num as uint);
            let utf8 = match String::from_utf16(&utf16) {
                Ok(utf8) => utf8.into_bytes(),
                Err(..) => return Err(invalid_encoding()),
            };
            self.utf8 = MemReader::new(utf8);
        }
        // MemReader shouldn't error here since we just filled it
        Ok(self.utf8.read(buf).unwrap())
    }

    pub fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        let utf16 = match from_utf8(buf).ok() {
            Some(utf8) => {
                utf8.utf16_units().collect::<Vec<u16>>()
            }
            None => return Err(invalid_encoding()),
        };
        let mut num: DWORD = 0;
        match unsafe { WriteConsoleW(self.handle,
                                     utf16.as_ptr() as LPCVOID,
                                     utf16.len() as u32,
                                     &mut num as LPDWORD,
                                     ptr::null_mut()) } {
            0 => Err(super::last_error()),
            _ => Ok(()),
        }
    }

    pub fn set_raw(&mut self, raw: bool) -> IoResult<()> {
        // FIXME
        // Somebody needs to decide on which of these flags we want
        match unsafe { SetConsoleMode(self.handle,
            match raw {
                true => 0,
                false => ENABLE_ECHO_INPUT | ENABLE_EXTENDED_FLAGS |
                         ENABLE_INSERT_MODE | ENABLE_LINE_INPUT |
                         ENABLE_PROCESSED_INPUT | ENABLE_QUICK_EDIT_MODE,
            }) } {
            0 => Err(super::last_error()),
            _ => Ok(()),
        }
    }

    pub fn get_winsize(&mut self) -> IoResult<(int, int)> {
        let mut info: CONSOLE_SCREEN_BUFFER_INFO = unsafe { mem::zeroed() };
        match unsafe { GetConsoleScreenBufferInfo(self.handle, &mut info as *mut _) } {
            0 => Err(super::last_error()),
            _ => Ok(((info.srWindow.Right + 1 - info.srWindow.Left) as int,
                     (info.srWindow.Bottom + 1 - info.srWindow.Top) as int)),
        }
    }
}

impl Drop for TTY {
    fn drop(&mut self) {
        if self.closeme {
            // Nobody cares about the return value
            let _ = unsafe { CloseHandle(self.handle) };
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

extern crate num;

use self::num::complex::{Complex, Complex32, Complex64};
use std::cmp;
use pointer::CPtr;
use scalar::Scalar;
use vector;
use vector::BlasVector;

pub trait Copy {
    fn copy(x: &BlasVector<Self>, y: &mut BlasVector<Self>);
}

macro_rules! copy_impl(
    ($t: ty, $copy_fn: ident) => (
        impl Copy for $t {
            fn copy(x: &BlasVector<$t>, y: &mut BlasVector<$t>) {
                unsafe {
                    vector::ll::$copy_fn(x.len(),
                        x.as_ptr().as_c_ptr(),  x.inc(),
                        y.as_mut_ptr().as_c_ptr(), y.inc());
                }
            }
        }
    );
)

copy_impl!(f32,       cblas_scopy)
copy_impl!(f64,       cblas_dcopy)
copy_impl!(Complex32, cblas_ccopy)
copy_impl!(Complex64, cblas_zcopy)

pub trait Axpy {
    fn axpy(alpha: Self, x: &BlasVector<Self>, y: &mut BlasVector<Self>);
}

macro_rules! axpy_impl(
    ($t: ty, $update_fn: ident) => (
        impl Axpy for $t {
            fn axpy(alpha: $t, x: &BlasVector<$t>, y: &mut BlasVector<$t>) {
                unsafe {
                    let n = cmp::min(x.len(), y.len());

                    vector::ll::$update_fn(n,
                        (&alpha).as_const(),
                        x.as_ptr().as_c_ptr(), x.inc(),
                        y.as_mut_ptr().as_c_ptr(), y.inc());
                }
            }
        }
    );
)

axpy_impl!(f32,       cblas_saxpy)
axpy_impl!(f64,       cblas_daxpy)
axpy_impl!(Complex32, cblas_caxpy)
axpy_impl!(Complex64, cblas_zaxpy)

#[cfg(test)]
mod axpy_tests {
    extern crate num;
    extern crate test;

    use self::num::complex::Complex;
    use vector::ops::Axpy;

    #[test]
    fn real() {
        let x = vec![1f32,-2f32,3f32,4f32];
        let y = vec![3f32,7f32,-2f32,2f32];
        let mut z = y.clone();

        Axpy::axpy(1f32, &y, &mut z);
        Axpy::axpy(1f32, &x, &mut z);
        assert_eq!(z, vec![7f32,12f32,-1f32,8f32]);
    }

    #[test]
    fn complex() {
        let x = vec![Complex::new(1f32, 1f32), Complex::new(1f32, 3f32)];
        let y = vec![Complex::new(3f32, -2f32), Complex::new(2f32, 3f32)];
        let mut z = x.clone();

        Axpy::axpy(Complex::new(-1f32, 1f32), &y, &mut z);
        assert_eq!(z, vec![Complex::new(0f32, 6f32), Complex::new(-4f32, 2f32)]);
    }

}
<commit_msg>Add Scal trait<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

extern crate num;

use self::num::complex::{Complex, Complex32, Complex64};
use std::cmp;
use pointer::CPtr;
use scalar::Scalar;
use vector;
use vector::BlasVector;

pub trait Copy {
    fn copy(x: &BlasVector<Self>, y: &mut BlasVector<Self>);
}

macro_rules! copy_impl(
    ($t: ty, $copy_fn: ident) => (
        impl Copy for $t {
            fn copy(x: &BlasVector<$t>, y: &mut BlasVector<$t>) {
                unsafe {
                    vector::ll::$copy_fn(x.len(),
                        x.as_ptr().as_c_ptr(),  x.inc(),
                        y.as_mut_ptr().as_c_ptr(), y.inc());
                }
            }
        }
    );
)

copy_impl!(f32,       cblas_scopy)
copy_impl!(f64,       cblas_dcopy)
copy_impl!(Complex32, cblas_ccopy)
copy_impl!(Complex64, cblas_zcopy)

pub trait Axpy {
    fn axpy(alpha: Self, x: &BlasVector<Self>, y: &mut BlasVector<Self>);
}

macro_rules! axpy_impl(
    ($t: ty, $update_fn: ident) => (
        impl Axpy for $t {
            fn axpy(alpha: $t, x: &BlasVector<$t>, y: &mut BlasVector<$t>) {
                unsafe {
                    let n = cmp::min(x.len(), y.len());

                    vector::ll::$update_fn(n,
                        (&alpha).as_const(),
                        x.as_ptr().as_c_ptr(), x.inc(),
                        y.as_mut_ptr().as_c_ptr(), y.inc());
                }
            }
        }
    );
)

axpy_impl!(f32,       cblas_saxpy)
axpy_impl!(f64,       cblas_daxpy)
axpy_impl!(Complex32, cblas_caxpy)
axpy_impl!(Complex64, cblas_zaxpy)

#[cfg(test)]
mod axpy_tests {
    extern crate num;
    extern crate test;

    use self::num::complex::Complex;
    use vector::ops::Axpy;

    #[test]
    fn real() {
        let x = vec![1f32,-2f32,3f32,4f32];
        let y = vec![3f32,7f32,-2f32,2f32];
        let mut z = y.clone();

        Axpy::axpy(1f32, &y, &mut z);
        Axpy::axpy(1f32, &x, &mut z);
        assert_eq!(z, vec![7f32,12f32,-1f32,8f32]);
    }

    #[test]
    fn complex() {
        let x = vec![Complex::new(1f32, 1f32), Complex::new(1f32, 3f32)];
        let y = vec![Complex::new(3f32, -2f32), Complex::new(2f32, 3f32)];
        let mut z = x.clone();

        Axpy::axpy(Complex::new(-1f32, 1f32), &y, &mut z);
        assert_eq!(z, vec![Complex::new(0f32, 6f32), Complex::new(-4f32, 2f32)]);
    }

}

pub trait Scal {
    fn scal(alpha: Self, x: &mut BlasVector<Self>);
}

macro_rules! scal_impl(
    ($t: ty, $scal_fn: ident) => (
        impl Scal for $t {
            #[inline]
            fn scal(alpha: $t, x: &mut BlasVector<$t>) {
                unsafe {
                    vector::ll::$scal_fn(x.len(),
                        alpha,
                        x.as_mut_ptr().as_c_ptr(), x.inc());
                }
            }
        }
    );

    ($t: ty, $scal_fn: ident, $real_scal_fn: ident) => (
        impl Scal for $t {
            #[inline]
            fn scal(alpha: $t, x: &mut BlasVector<$t>) {
                if alpha.im == 0.0 {
                    unsafe {
                        vector::ll::$real_scal_fn(x.len(),
                            alpha.re,
                            x.as_mut_ptr().as_c_ptr(), x.inc());
                    }
                } else {
                    unsafe {
                        vector::ll::$scal_fn(x.len(),
                            (&alpha).as_const(),
                            x.as_mut_ptr().as_c_ptr(), x.inc());
                    }
                }
            }
        }
    );
)

scal_impl!(f32, cblas_sscal)
scal_impl!(f64, cblas_dscal)
scal_impl!(Complex32, cblas_cscal, cblas_csscal)
scal_impl!(Complex64, cblas_zscal, cblas_zdscal)

#[cfg(test)]
mod scal_tests {
    extern crate num;
    extern crate test;

    use self::num::complex::Complex;
    use vector::ops::Scal;

    #[test]
    fn real() {
        let mut x = vec![1f32,-2f32,3f32,4f32];

        Scal::scal(-2f32, &mut x);
        assert_eq!(x, vec![-2f32, 4f32, -6f32, -8f32]);
    }

    #[test]
    fn complex() {
        let mut x = vec![Complex::new(1f32, 1f32), Complex::new(1f32, 3f32)];

        Scal::scal(Complex::new(1f32, 1f32), &mut x);
        assert_eq!(x, vec![Complex::new(0f32, 2f32), Complex::new(-2f32, 4f32)]);
    }

    #[test]
    fn complex_real() {
        let mut x = vec![Complex::new(1f32, 1f32), Complex::new(1f32, 3f32)];

        Scal::scal(Complex::new(2f32, 0f32), &mut x);
        assert_eq!(x, vec![Complex::new(2f32, 2f32), Complex::new(2f32, 6f32)]);
    }

}
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

#[phase(plugin)]
extern crate gl_generator;

extern crate glutin;
extern crate cgmath;
extern crate serialize;

use self::glutin::{Event, VirtualKeyCode}; // TODO: why 'self'?
use core_types::{Size2, MInt};
use visualizer_types::{Color3};
use mgl::Mgl;
use mgl;
use std::mem;

// TODO: remove 'gl'
use gl;
use gl::types::{GLfloat, GLuint};

// TODO: fix indent
static VS_SRC: &'static str =
   "#version 100\n\
    attribute vec2 position;\n\
    void main() {\n\
        gl_Position = vec4(position, 0.0, 1.0);\n\
    }";

static FS_SRC: &'static str =
   "#version 100\n\
    void main() {\n\
        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n\
    }";

pub struct Visualizer {
    mgl: Mgl,
    window: glutin::Window,
    should_close: bool,
    color_counter: i32, // TODO: remove
    program: GLuint,
}

impl Visualizer {
    pub fn new() -> Visualizer {
        let window = glutin::Window::new().unwrap(); // TODO: unwrap -> expect
        unsafe {
            window.make_current();
        };
        let mgl = Mgl::new(|s| window.get_proc_address(s));
        println!("OpenGL version {}", mgl.get_info(gl::VERSION));
        println!("GLSL ES version {}", mgl.get_info(gl::SHADING_LANGUAGE_VERSION));
        let vs = mgl::compile_shader(&mgl.gl, VS_SRC, gl::VERTEX_SHADER);
        let fs = mgl::compile_shader(&mgl.gl, FS_SRC, gl::FRAGMENT_SHADER);
        let program = mgl::link_program(&mgl.gl, vs, fs);
        Visualizer {
            mgl: mgl,
            window: window,
            should_close: false,
            color_counter: 0,
            program: program,
        }
    }

    pub fn is_running(&self) -> bool {
        !self.should_close
    }

    fn handle_events(&mut self) {
        let events = self.window.poll_events().collect::<Vec<_>>();
        if !events.is_empty() {
            println!("{}", events);
        }
        for event in events.iter() {
            match *event {
                Event::KeyboardInput(_, _, Some(VirtualKeyCode::Escape))
                    | Event::Closed =>
                {
                    self.should_close = true;
                },
                _ => {},
            }
        }
    }

    fn draw(&mut self) {
        match self.color_counter {
            0 => self.mgl.set_clear_color(Color3{r: 0.5, g: 0.0, b: 0.0}),
            30 => self.mgl.set_clear_color(Color3{r: 0.0, g: 0.5, b: 0.0}),
            60 => self.mgl.set_clear_color(Color3{r: 0.0, g: 0.0, b: 0.5}),
            _ => if self.color_counter > 90 {
                self.color_counter = -1;
            },
        }
        self.color_counter += 1;
        self.mgl.clear_screen();
        unsafe {
            let vertices: [GLfloat, ..3 * 3] = [
                0.0,  0.5, 0.0,
                0.5, -0.5, 0.0,
                -0.5, -0.5, 0.0,
            ];
            let (w, h) = self.window.get_inner_size().unwrap(); // TODO: unwrap -> expect
            self.mgl.set_viewport(Size2{w: w as MInt, h: h as MInt});
            self.mgl.gl.UseProgram(self.program);
            self.mgl.gl.VertexAttribPointer(
                0, 3, gl::FLOAT, gl::FALSE, 0, mem::transmute(&vertices));
            self.mgl.gl.EnableVertexAttribArray(0);
            self.mgl.gl.DrawArrays(gl::TRIANGLES, 0, 3);
        }
        self.window.swap_buffers();
    }

    pub fn tick(&mut self) {
        self.handle_events();
        // self.logic();
        self.draw();
        // self.update_time();
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>Visualizer: Added info about GL_VENDOR and GL_RENDERER<commit_after>// See LICENSE file for copyright and license details.

#[phase(plugin)]
extern crate gl_generator;

extern crate glutin;
extern crate cgmath;
extern crate serialize;

use self::glutin::{Event, VirtualKeyCode}; // TODO: why 'self'?
use core_types::{Size2, MInt};
use visualizer_types::{Color3};
use mgl::Mgl;
use mgl;
use std::mem;

// TODO: remove 'gl'
use gl;
use gl::types::{GLfloat, GLuint};

// TODO: fix indent
static VS_SRC: &'static str =
   "#version 100\n\
    attribute vec2 position;\n\
    void main() {\n\
        gl_Position = vec4(position, 0.0, 1.0);\n\
    }";

static FS_SRC: &'static str =
   "#version 100\n\
    void main() {\n\
        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n\
    }";

pub struct Visualizer {
    mgl: Mgl,
    window: glutin::Window,
    should_close: bool,
    color_counter: i32, // TODO: remove
    program: GLuint,
}

impl Visualizer {
    pub fn new() -> Visualizer {
        let window = glutin::Window::new().unwrap(); // TODO: unwrap -> expect
        unsafe {
            window.make_current();
        };
        let mgl = Mgl::new(|s| window.get_proc_address(s));
        println!("GL_VERSION: {}", mgl.get_info(gl::VERSION));
        println!("GL_SHADING_LANGUAGE_VERSION: {}", mgl.get_info(gl::SHADING_LANGUAGE_VERSION));
        println!("GL_VENDOR: {}", mgl.get_info(gl::VENDOR));
        println!("GL_RENDERER: {}", mgl.get_info(gl::RENDERER));
        // println!("GL_EXTENSIONS: {}", mgl.get_info(gl::EXTENSIONS));
        let vs = mgl::compile_shader(&mgl.gl, VS_SRC, gl::VERTEX_SHADER);
        let fs = mgl::compile_shader(&mgl.gl, FS_SRC, gl::FRAGMENT_SHADER);
        let program = mgl::link_program(&mgl.gl, vs, fs);
        Visualizer {
            mgl: mgl,
            window: window,
            should_close: false,
            color_counter: 0,
            program: program,
        }
    }

    pub fn is_running(&self) -> bool {
        !self.should_close
    }

    fn handle_events(&mut self) {
        let events = self.window.poll_events().collect::<Vec<_>>();
        if !events.is_empty() {
            println!("{}", events);
        }
        for event in events.iter() {
            match *event {
                Event::KeyboardInput(_, _, Some(VirtualKeyCode::Escape))
                    | Event::Closed =>
                {
                    self.should_close = true;
                },
                _ => {},
            }
        }
    }

    fn draw(&mut self) {
        match self.color_counter {
            0 => self.mgl.set_clear_color(Color3{r: 0.5, g: 0.0, b: 0.0}),
            30 => self.mgl.set_clear_color(Color3{r: 0.0, g: 0.5, b: 0.0}),
            60 => self.mgl.set_clear_color(Color3{r: 0.0, g: 0.0, b: 0.5}),
            _ => if self.color_counter > 90 {
                self.color_counter = -1;
            },
        }
        self.color_counter += 1;
        self.mgl.clear_screen();
        unsafe {
            let vertices: [GLfloat, ..3 * 3] = [
                0.0,  0.5, 0.0,
                0.5, -0.5, 0.0,
                -0.5, -0.5, 0.0,
            ];
            let (w, h) = self.window.get_inner_size().unwrap(); // TODO: unwrap -> expect
            self.mgl.set_viewport(Size2{w: w as MInt, h: h as MInt});
            self.mgl.gl.UseProgram(self.program);
            self.mgl.gl.VertexAttribPointer(
                0, 3, gl::FLOAT, gl::FALSE, 0, mem::transmute(&vertices));
            self.mgl.gl.EnableVertexAttribArray(0);
            self.mgl.gl.DrawArrays(gl::TRIANGLES, 0, 3);
        }
        self.window.swap_buffers();
    }

    pub fn tick(&mut self) {
        self.handle_events();
        // self.logic();
        self.draw();
        // self.update_time();
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>