<commit_before>// Copyright (c) 2016 The vulkano developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::error;
use std::fmt;
use std::mem;
use std::ptr;
use std::sync::Arc;

use descriptor::PipelineLayoutRef;
use descriptor::descriptor_set::UnsafeDescriptorSetLayout;
use descriptor::pipeline_layout::PipelineLayout;
use descriptor::pipeline_layout::PipelineLayoutSys;
use descriptor::pipeline_layout::PipelineLayoutDescNames;
use descriptor::pipeline_layout::PipelineLayoutSuperset;
use pipeline::shader::ComputeShaderEntryPoint;
use pipeline::shader::SpecializationConstants;

use device::Device;
use Error;
use OomError;
use VulkanObject;
use VulkanPointers;
use check_errors;
use vk;

/// A pipeline object that describes to the Vulkan implementation how it should perform compute
/// operations.
///
/// The template parameter contains the descriptor set to use with this pipeline.
pub struct ComputePipeline<Pl> {
    pipeline: vk::Pipeline,
    device: Arc<Device>,
    pipeline_layout: Pl,
}

impl ComputePipeline<()> {
    /// Builds a new `ComputePipeline`.
    pub fn new<Css, Csl>(device: &Arc<Device>, shader: &ComputeShaderEntryPoint<Css, Csl>,
                         specialization: &Css)
                         -> Result<Arc<ComputePipeline<PipelineLayout<Csl>>>, ComputePipelineCreationError>
        where Csl: PipelineLayoutDescNames + Clone,
              Css: SpecializationConstants
    {
        let vk = device.pointers();

        let pipeline_layout = shader.layout().clone().build(device).unwrap();     // TODO: error

        // TODO: more details in the error
        if !PipelineLayoutSuperset::is_superset_of(pipeline_layout.desc(), shader.layout()) {
            return Err(ComputePipelineCreationError::IncompatiblePipelineLayout);
        }

        let pipeline = unsafe {
            let spec_descriptors = <Css as SpecializationConstants>::descriptors();
            let specialization = vk::SpecializationInfo {
                mapEntryCount: spec_descriptors.len() as u32,
                pMapEntries: spec_descriptors.as_ptr() as *const _,
                dataSize: mem::size_of_val(specialization),
                pData: specialization as *const Css as *const _,
            };

            let stage = vk::PipelineShaderStageCreateInfo {
                sType: vk::STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,
                stage: vk::SHADER_STAGE_COMPUTE_BIT,
                module: shader.module().internal_object(),
                pName: shader.name().as_ptr(),
                pSpecializationInfo: if specialization.dataSize == 0 {
                    ptr::null()
                } else {
                    &specialization
                },
            };

            let infos = vk::ComputePipelineCreateInfo {
                sType: vk::STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,
                stage: stage,
                layout: PipelineLayoutRef::sys(&pipeline_layout).internal_object(),
                basePipelineHandle: 0,
                basePipelineIndex: 0,
            };

            let mut output = mem::uninitialized();
            try!(check_errors(vk.CreateComputePipelines(device.internal_object(), 0,
                                                        1, &infos, ptr::null(), &mut output)));
            output
        };

        Ok(Arc::new(ComputePipeline {
            device: device.clone(),
            pipeline: pipeline,
            pipeline_layout: pipeline_layout,
        }))
    }
}

impl<Pl> ComputePipeline<Pl> {
    /// Returns the `Device` this compute pipeline was created with.
    #[inline]
    pub fn device(&self) -> &Arc<Device> {
        &self.device
    }

    /// Returns the pipeline layout used in this compute pipeline.
    #[inline]
    pub fn layout(&self) -> &Pl {
        &self.pipeline_layout
    }
}

unsafe impl<Pl> PipelineLayoutRef for ComputePipeline<Pl> where Pl: PipelineLayoutRef {
    #[inline]
    fn sys(&self) -> PipelineLayoutSys {
        self.layout().sys()
    }

    #[inline]
    fn desc(&self) -> &PipelineLayoutDescNames {
        self.layout().desc()
    }

    #[inline]
    fn device(&self) -> &Arc<Device> {
        self.device()
    }

    #[inline]
    fn descriptor_set_layout(&self, index: usize) -> Option<&Arc<UnsafeDescriptorSetLayout>> {
        self.layout().descriptor_set_layout(index)
    }
}

unsafe impl<Pl> VulkanObject for ComputePipeline<Pl> {
    type Object = vk::Pipeline;

    #[inline]
    fn internal_object(&self) -> vk::Pipeline {
        self.pipeline
    }
}

impl<Pl> Drop for ComputePipeline<Pl> {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.device.pointers();
            vk.DestroyPipeline(self.device.internal_object(), self.pipeline, ptr::null());
        }
    }
}

/// Error that can happen when creating a compute pipeline.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ComputePipelineCreationError {
    /// Not enough memory.
    OomError(OomError),
    /// The pipeline layout is not compatible with what the shader expects.
    IncompatiblePipelineLayout,
}

impl error::Error for ComputePipelineCreationError {
    #[inline]
    fn description(&self) -> &str {
        match *self {
            ComputePipelineCreationError::OomError(_) => "not enough memory available",
            ComputePipelineCreationError::IncompatiblePipelineLayout => "the pipeline layout is \
                                                                         not compatible with what \
                                                                         the shader expects",
        }
    }

    #[inline]
    fn cause(&self) -> Option<&error::Error> {
        match *self {
            ComputePipelineCreationError::OomError(ref err) => Some(err),
            _ => None
        }
    }
}

impl fmt::Display for ComputePipelineCreationError {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "{}", error::Error::description(self))
    }
}

impl From<OomError> for ComputePipelineCreationError {
    #[inline]
    fn from(err: OomError) -> ComputePipelineCreationError {
        ComputePipelineCreationError::OomError(err)
    }
}

impl From<Error> for ComputePipelineCreationError {
    #[inline]
    fn from(err: Error) -> ComputePipelineCreationError {
        match err {
            err @ Error::OutOfHostMemory => {
                ComputePipelineCreationError::OomError(OomError::from(err))
            },
            err @ Error::OutOfDeviceMemory => {
                ComputePipelineCreationError::OomError(OomError::from(err))
            },
            _ => panic!("unexpected error: {:?}", err)
        }
    }
}

#[cfg(test)]
mod tests {
    // TODO: test for basic creation
    // TODO: test for pipeline layout error
}
<commit_msg>No longer return an Arc in ComputePipeline::new<commit_after>// Copyright (c) 2016 The vulkano developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::error;
use std::fmt;
use std::mem;
use std::ptr;
use std::sync::Arc;

use descriptor::PipelineLayoutRef;
use descriptor::descriptor_set::UnsafeDescriptorSetLayout;
use descriptor::pipeline_layout::PipelineLayout;
use descriptor::pipeline_layout::PipelineLayoutSys;
use descriptor::pipeline_layout::PipelineLayoutDescNames;
use descriptor::pipeline_layout::PipelineLayoutSuperset;
use pipeline::shader::ComputeShaderEntryPoint;
use pipeline::shader::SpecializationConstants;

use device::Device;
use Error;
use OomError;
use VulkanObject;
use VulkanPointers;
use check_errors;
use vk;

/// A pipeline object that describes to the Vulkan implementation how it should perform compute
/// operations.
///
/// The template parameter contains the descriptor set to use with this pipeline.
pub struct ComputePipeline<Pl> {
    pipeline: vk::Pipeline,
    device: Arc<Device>,
    pipeline_layout: Pl,
}

impl ComputePipeline<()> {
    /// Builds a new `ComputePipeline`.
    pub fn new<Css, Csl>(device: &Arc<Device>, shader: &ComputeShaderEntryPoint<Css, Csl>,
                         specialization: &Css)
                         -> Result<ComputePipeline<PipelineLayout<Csl>>, ComputePipelineCreationError>
        where Csl: PipelineLayoutDescNames + Clone,
              Css: SpecializationConstants
    {
        let vk = device.pointers();

        let pipeline_layout = shader.layout().clone().build(device).unwrap();     // TODO: error

        // TODO: more details in the error
        if !PipelineLayoutSuperset::is_superset_of(pipeline_layout.desc(), shader.layout()) {
            return Err(ComputePipelineCreationError::IncompatiblePipelineLayout);
        }

        let pipeline = unsafe {
            let spec_descriptors = <Css as SpecializationConstants>::descriptors();
            let specialization = vk::SpecializationInfo {
                mapEntryCount: spec_descriptors.len() as u32,
                pMapEntries: spec_descriptors.as_ptr() as *const _,
                dataSize: mem::size_of_val(specialization),
                pData: specialization as *const Css as *const _,
            };

            let stage = vk::PipelineShaderStageCreateInfo {
                sType: vk::STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,
                stage: vk::SHADER_STAGE_COMPUTE_BIT,
                module: shader.module().internal_object(),
                pName: shader.name().as_ptr(),
                pSpecializationInfo: if specialization.dataSize == 0 {
                    ptr::null()
                } else {
                    &specialization
                },
            };

            let infos = vk::ComputePipelineCreateInfo {
                sType: vk::STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
                pNext: ptr::null(),
                flags: 0,
                stage: stage,
                layout: PipelineLayoutRef::sys(&pipeline_layout).internal_object(),
                basePipelineHandle: 0,
                basePipelineIndex: 0,
            };

            let mut output = mem::uninitialized();
            try!(check_errors(vk.CreateComputePipelines(device.internal_object(), 0,
                                                        1, &infos, ptr::null(), &mut output)));
            output
        };

        Ok(ComputePipeline {
            device: device.clone(),
            pipeline: pipeline,
            pipeline_layout: pipeline_layout,
        })
    }
}

impl<Pl> ComputePipeline<Pl> {
    /// Returns the `Device` this compute pipeline was created with.
    #[inline]
    pub fn device(&self) -> &Arc<Device> {
        &self.device
    }

    /// Returns the pipeline layout used in this compute pipeline.
    #[inline]
    pub fn layout(&self) -> &Pl {
        &self.pipeline_layout
    }
}

unsafe impl<Pl> PipelineLayoutRef for ComputePipeline<Pl> where Pl: PipelineLayoutRef {
    #[inline]
    fn sys(&self) -> PipelineLayoutSys {
        self.layout().sys()
    }

    #[inline]
    fn desc(&self) -> &PipelineLayoutDescNames {
        self.layout().desc()
    }

    #[inline]
    fn device(&self) -> &Arc<Device> {
        self.device()
    }

    #[inline]
    fn descriptor_set_layout(&self, index: usize) -> Option<&Arc<UnsafeDescriptorSetLayout>> {
        self.layout().descriptor_set_layout(index)
    }
}

unsafe impl<Pl> VulkanObject for ComputePipeline<Pl> {
    type Object = vk::Pipeline;

    #[inline]
    fn internal_object(&self) -> vk::Pipeline {
        self.pipeline
    }
}

impl<Pl> Drop for ComputePipeline<Pl> {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let vk = self.device.pointers();
            vk.DestroyPipeline(self.device.internal_object(), self.pipeline, ptr::null());
        }
    }
}

/// Error that can happen when creating a compute pipeline.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ComputePipelineCreationError {
    /// Not enough memory.
    OomError(OomError),
    /// The pipeline layout is not compatible with what the shader expects.
    IncompatiblePipelineLayout,
}

impl error::Error for ComputePipelineCreationError {
    #[inline]
    fn description(&self) -> &str {
        match *self {
            ComputePipelineCreationError::OomError(_) => "not enough memory available",
            ComputePipelineCreationError::IncompatiblePipelineLayout => "the pipeline layout is \
                                                                         not compatible with what \
                                                                         the shader expects",
        }
    }

    #[inline]
    fn cause(&self) -> Option<&error::Error> {
        match *self {
            ComputePipelineCreationError::OomError(ref err) => Some(err),
            _ => None
        }
    }
}

impl fmt::Display for ComputePipelineCreationError {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "{}", error::Error::description(self))
    }
}

impl From<OomError> for ComputePipelineCreationError {
    #[inline]
    fn from(err: OomError) -> ComputePipelineCreationError {
        ComputePipelineCreationError::OomError(err)
    }
}

impl From<Error> for ComputePipelineCreationError {
    #[inline]
    fn from(err: Error) -> ComputePipelineCreationError {
        match err {
            err @ Error::OutOfHostMemory => {
                ComputePipelineCreationError::OomError(OomError::from(err))
            },
            err @ Error::OutOfDeviceMemory => {
                ComputePipelineCreationError::OomError(OomError::from(err))
            },
            _ => panic!("unexpected error: {:?}", err)
        }
    }
}

#[cfg(test)]
mod tests {
    // TODO: test for basic creation
    // TODO: test for pipeline layout error
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![crate_name="vgrs-memcheck-test"]
#![crate_type="bin"]

extern crate vgrs;
extern crate test;
extern crate libc;

use vgrs::{valgrind, memcheck};

use std::intrinsics;
use libc::c_void;
use test::black_box;

unsafe fn assert_error(errors: &mut uint) {
    let e = valgrind::count_errors();
    assert!(e > *errors);
    *errors = e;
}

unsafe fn assert_no_error(errors: uint) {
    let e = valgrind::count_errors();
    assert_eq!(e, errors);
}

unsafe fn test() {
    assert_eq!(valgrind::running_on_valgrind(), 1);

    let mut errors = 0;
    assert_no_error(errors);

    let x: u8 = intrinsics::uninit();
    assert!(memcheck::check_is_addressable(&x).is_none());
    assert!(memcheck::check_is_defined(&x).is_some());
    black_box(x);
    assert_error(&mut errors);

    // Noaccess memory stays noaccess
    let mut x: u8 = 0;
    memcheck::make_noaccess(&x);
    assert!(memcheck::check_is_addressable(&x).is_some());
    assert!(memcheck::check_is_defined(&x).is_some());
    black_box(x);
    assert_error(&mut errors);
    x = 1;
    assert_error(&mut errors);
    black_box(x);
    assert_error(&mut errors);

    // Undefined memory becomes defined after a write
    let mut x: u8 = 0;
    memcheck::make_undefined(&x);
    assert!(memcheck::check_is_addressable(&x).is_none());
    assert!(memcheck::check_is_defined(&x).is_some());
    black_box(x);
    assert_error(&mut errors);
    x = 1;
    assert!(memcheck::check_is_addressable(&x).is_none());
    assert!(memcheck::check_is_defined(&x).is_none());
    assert_no_error(errors);
    black_box(x);
    assert_no_error(errors);

    let x: u8 = intrinsics::uninit();
    memcheck::make_defined(&x);
    assert!(memcheck::check_is_addressable(&x).is_none());
    assert!(memcheck::check_is_defined(&x).is_none());
    black_box(x);
    assert_no_error(errors);

    let mut x: *mut c_void = libc::malloc(42);
    assert_eq!(memcheck::count_leaks().leaked, 0);
    memcheck::do_leak_check();
    assert_eq!(memcheck::count_leaks().leaked, 0);

    // Make the malloc'd pointer live to here, then leak it
    black_box(&x);
    x = 0 as *mut c_void;

    assert_eq!(memcheck::count_leaks().leaked, 0);
    assert_eq!(memcheck::count_leak_blocks().leaked, 0);
    assert_no_error(errors);

    memcheck::do_leak_check();
    assert_error(&mut errors);
    assert_eq!(memcheck::count_leaks().leaked, 42);
    assert_eq!(memcheck::count_leak_blocks().leaked, 1);

    // Make sure the above assignment isn't dead
    black_box(&x);
}

fn main() {
    unsafe { test() }
}
<commit_msg>Rust upgrade<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![crate_name="vgrs-memcheck-test"]
#![crate_type="bin"]

extern crate vgrs;
extern crate test;
extern crate libc;

use vgrs::{valgrind, memcheck};

use std::intrinsics;
use libc::c_void;
use test::black_box;

unsafe fn assert_error(errors: &mut uint) {
    let e = valgrind::count_errors();
    assert!(e > *errors);
    *errors = e;
}

unsafe fn assert_no_error(errors: uint) {
    let e = valgrind::count_errors();
    assert_eq!(e, errors);
}

unsafe fn do_test() {
    assert_eq!(valgrind::running_on_valgrind(), 1);

    let mut errors = 0;
    assert_no_error(errors);

    let x: u8 = intrinsics::uninit();
    assert!(memcheck::check_is_addressable(&x).is_none());
    assert!(memcheck::check_is_defined(&x).is_some());
    black_box(x);
    assert_error(&mut errors);

    // Noaccess memory stays noaccess
    let mut x: u8 = 0;
    memcheck::make_noaccess(&x);
    assert!(memcheck::check_is_addressable(&x).is_some());
    assert!(memcheck::check_is_defined(&x).is_some());
    black_box(x);
    assert_error(&mut errors);
    x = 1;
    assert_error(&mut errors);
    black_box(x);
    assert_error(&mut errors);

    // Undefined memory becomes defined after a write
    let mut x: u8 = 0;
    memcheck::make_undefined(&x);
    assert!(memcheck::check_is_addressable(&x).is_none());
    assert!(memcheck::check_is_defined(&x).is_some());
    black_box(x);
    assert_error(&mut errors);
    x = 1;
    assert!(memcheck::check_is_addressable(&x).is_none());
    assert!(memcheck::check_is_defined(&x).is_none());
    assert_no_error(errors);
    black_box(x);
    assert_no_error(errors);

    let x: u8 = intrinsics::uninit();
    memcheck::make_defined(&x);
    assert!(memcheck::check_is_addressable(&x).is_none());
    assert!(memcheck::check_is_defined(&x).is_none());
    black_box(x);
    assert_no_error(errors);

    let mut x: *mut c_void = libc::malloc(42);
    assert_eq!(memcheck::count_leaks().leaked, 0);
    memcheck::do_leak_check();
    assert_eq!(memcheck::count_leaks().leaked, 0);

    // Make the malloc'd pointer live to here, then leak it
    black_box(&x);
    x = 0 as *mut c_void;

    assert_eq!(memcheck::count_leaks().leaked, 0);
    assert_eq!(memcheck::count_leak_blocks().leaked, 0);
    assert_no_error(errors);

    memcheck::do_leak_check();
    assert_error(&mut errors);
    assert_eq!(memcheck::count_leaks().leaked, 42);
    assert_eq!(memcheck::count_leak_blocks().leaked, 1);

    // Make sure the above assignment isn't dead
    black_box(&x);
}

fn main() {
    unsafe { do_test() }
}
<|endoftext|>


<commit_before>extern crate scroll;
extern crate goblin;
use goblin::archive::*;
use goblin::elf;
use scroll::Pread;
use std::path::Path;
use std::fs::File;

#[test]
fn parse_file_header() {
    let file_header: [u8; SIZEOF_HEADER] = [0x2f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
                                            0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
                                            0x20, 0x20, 0x30, 0x20, 0x20, 0x20, 0x20,
                                            0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
                                            0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30,
                                            0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x20,
                                            0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38,
                                            0x32, 0x34, 0x34, 0x20, 0x20, 0x20, 0x20,
                                            0x20, 0x20, 0x60, 0x0a];
    let buffer = &file_header[..];
    match buffer.pread::<MemberHeader>(0) {
        Err(_) => assert!(false),
        Ok(file_header2) => {
            let file_header = MemberHeader {
                identifier: [0x2f,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,],
                timestamp: [48, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32],
                owner_id: [48, 32, 32, 32, 32, 32],
                group_id: [48, 32, 32, 32, 32, 32],
                mode: [48, 32, 32, 32, 32, 32, 32, 32],
                file_size: [56, 50, 52, 52, 32, 32, 32, 32, 32, 32],
                terminator: [96, 10] };
            assert_eq!(file_header, file_header2)
        }
    }
}

#[test]
fn parse_archive() {
    let crt1a: Vec<u8> = include!("../etc/crt1a.rs");
    const START: &'static str = "_start";
    match Archive::parse(&crt1a) {
        Ok(archive) => {
            assert_eq!(archive.member_of_symbol(START), Some("crt1.o"));
            if let Some(member) = archive.get("crt1.o") {
                assert_eq!(member.offset, 194);
                assert_eq!(member.size(), 1928)
            } else {
                println!("could not get crt1.o");
                assert!(false)
            }
        },
        Err(err) => {println!("could not parse archive: {:?}", err); assert!(false)}
    };
}

#[test]
fn parse_self() {
    use std::io::Read;
    let path = Path::new("target").join("debug").join("libgoblin.rlib");
    match File::open(path) {
        Ok(mut fd) => {
            let buffer = { let mut v = Vec::new(); fd.read_to_end(&mut v).unwrap(); v};
            match Archive::parse(&buffer) {
                Ok(archive) => {
                    let mut found = false;
                    for member in archive.members() {
                        println!("member: {:?}", member);
                        if member.starts_with("goblin") &&
                            // pre 1.18
                            (member.ends_with("0.o") ||
                             // >= 1.18
                             member.ends_with("goblin-archive.o")) {
                            match archive.extract(member.as_str(), &buffer) {
                                Ok(bytes) => {
                                    match elf::Elf::parse(&bytes) {
                                        Ok(elf) => {
                                            assert!(elf.entry == 0);
                                            assert!(elf.bias == 0);
                                            found = true;
                                            break;
                                        },
                                        Err(err) => {
                                            println!("{:?}", err);
                                            #[cfg(target_os="linux")]
                                            assert!(false)
                                        }
                                    }
                                },
                                Err(_) => assert!(false)
                            }
                        }
                    }
                    if !found {
                        println!("goblin-<hash>.0.o not found");
                        assert!(false)
                    }
                },
                Err(err) => {println!("{:?}", err); assert!(false)}
            }
        },
        Err(err) => {println!("{:?}", err); assert!(false)}
    }
}
<commit_msg>Skip parse_self() test on MacOS pending #26<commit_after>extern crate scroll;
extern crate goblin;
use goblin::archive::*;
use goblin::elf;
use scroll::Pread;
use std::path::Path;
use std::fs::File;

#[test]
fn parse_file_header() {
    let file_header: [u8; SIZEOF_HEADER] = [0x2f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
                                            0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
                                            0x20, 0x20, 0x30, 0x20, 0x20, 0x20, 0x20,
                                            0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
                                            0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30,
                                            0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x20,
                                            0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38,
                                            0x32, 0x34, 0x34, 0x20, 0x20, 0x20, 0x20,
                                            0x20, 0x20, 0x60, 0x0a];
    let buffer = &file_header[..];
    match buffer.pread::<MemberHeader>(0) {
        Err(_) => assert!(false),
        Ok(file_header2) => {
            let file_header = MemberHeader {
                identifier: [0x2f,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,],
                timestamp: [48, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32],
                owner_id: [48, 32, 32, 32, 32, 32],
                group_id: [48, 32, 32, 32, 32, 32],
                mode: [48, 32, 32, 32, 32, 32, 32, 32],
                file_size: [56, 50, 52, 52, 32, 32, 32, 32, 32, 32],
                terminator: [96, 10] };
            assert_eq!(file_header, file_header2)
        }
    }
}

#[test]
fn parse_archive() {
    let crt1a: Vec<u8> = include!("../etc/crt1a.rs");
    const START: &'static str = "_start";
    match Archive::parse(&crt1a) {
        Ok(archive) => {
            assert_eq!(archive.member_of_symbol(START), Some("crt1.o"));
            if let Some(member) = archive.get("crt1.o") {
                assert_eq!(member.offset, 194);
                assert_eq!(member.size(), 1928)
            } else {
                println!("could not get crt1.o");
                assert!(false)
            }
        },
        Err(err) => {println!("could not parse archive: {:?}", err); assert!(false)}
    };
}

#[test]
#[cfg(not(target_os="macos"))]  // pending https://github.com/m4b/goblin/issues/26
fn parse_self() {
    use std::io::Read;
    let path = Path::new("target").join("debug").join("libgoblin.rlib");
    match File::open(path) {
        Ok(mut fd) => {
            let buffer = { let mut v = Vec::new(); fd.read_to_end(&mut v).unwrap(); v};
            match Archive::parse(&buffer) {
                Ok(archive) => {
                    let mut found = false;
                    for member in archive.members() {
                        println!("member: {:?}", member);
                        if member.starts_with("goblin") &&
                            // pre 1.18
                            (member.ends_with("0.o") ||
                             // >= 1.18
                             member.ends_with("goblin-archive.o")) {
                            match archive.extract(member.as_str(), &buffer) {
                                Ok(bytes) => {
                                    match elf::Elf::parse(&bytes) {
                                        Ok(elf) => {
                                            assert!(elf.entry == 0);
                                            assert!(elf.bias == 0);
                                            found = true;
                                            break;
                                        },
                                        Err(err) => {
                                            println!("{:?}", err);
                                            #[cfg(target_os="linux")]
                                            assert!(false)
                                        }
                                    }
                                },
                                Err(_) => assert!(false)
                            }
                        }
                    }
                    if !found {
                        println!("goblin-<hash>.0.o not found");
                        assert!(false)
                    }
                },
                Err(err) => {println!("{:?}", err); assert!(false)}
            }
        },
        Err(err) => {println!("{:?}", err); assert!(false)}
    }
}
<|endoftext|>


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

use board::Board;
use game_elements::{SnakeElement, new_snake_element};

pub struct Snake {
    head  : Rc<RefCell<SnakeElement>>,
    tail  : Rc<RefCell<SnakeElement>>,
    board : Rc<RefCell<Board>>
}

impl Snake {
    pub fn move_up(&mut self) -> bool {
        let new_x;
        let new_y;
        {
            let head  = self.head.borrow();
            let board = self.board.borrow();
            new_x = head.get_x();
            let mut y = head.get_y();
            if y == 0 { y = board.get_height(); }
            new_y = y - 1;
        }
        self.do_move(new_snake_element(new_x, new_y))
    }

    pub fn move_down(&mut self) -> bool {
        let new_x;
        let new_y;
        {
            let head  = self.head.borrow();
            let board = self.board.borrow();
            new_x = head.get_x();
            let mut y = head.get_y() + 1;
            if y == board.get_height() { y = 0; }
            new_y = y;
        }
        self.do_move(new_snake_element(new_x, new_y))
    }

    pub fn move_left(&mut self) -> bool {
        let new_x;
        let new_y;
        {
            let head  = self.head.borrow();
            let board = self.board.borrow();
            let mut x = head.get_x();
            if x == 0 { x = board.get_width() }
            new_x = x - 1;
            new_y = head.get_y();
        }
        self.do_move(new_snake_element(new_x, new_y))
    }

    pub fn move_right(&mut self) -> bool {
        let new_x;
        let new_y;
        {
            let head  = self.head.borrow();
            let board = self.board.borrow();
            let mut x = head.get_x() + 1;
            if x == board.get_width() { x = 0; }
            new_x = x;
            new_y = head.get_y();
        }
        self.do_move(new_snake_element(new_x, new_y))
    }

    fn do_move(&mut self, new_head: Rc<RefCell<SnakeElement>>) -> bool {
        let x;
        let y;
        {
            let mut nh = new_head.borrow_mut();
            x = nh.get_x();
            y = nh.get_y();
        }
        {
            let mut head = self.head.borrow_mut();
            head.set_prev(new_head.clone());
        }
        self.head = new_head.clone();

        let mut board = self.board.borrow_mut();

        let is_apple = board.is_apple(x, y);
        if is_apple {
            board.add_apple();
        } else {
            if board.is_snake(x, y) {
                return false;
            }

            board.remove(self.tail.clone());
            let prev;
            {
                let tail = self.tail.borrow();
                prev = tail.get_prev().unwrap();
            }
            self.tail = prev;
            let mut tail = self.tail.borrow_mut();
            tail.set_prev_to_none();
        }

        board.add(new_head.clone());

        true
    }
}

pub fn new(x: usize, y: usize, board: Rc<RefCell<Board>>) -> Snake {
    let snake_start = new_snake_element(x, y);
    let snake = Snake {head:  snake_start.clone(),
                       tail:  snake_start.clone(),
                       board: board.clone()};
    let b = board.borrow();
    b.add(snake_start);
    snake
}
<commit_msg>Simplify<commit_after>use std::cell::RefCell;
use std::rc::Rc;

use board::Board;
use game_elements::{SnakeElement, new_snake_element};

pub struct Snake {
    head  : Rc<RefCell<SnakeElement>>,
    tail  : Rc<RefCell<SnakeElement>>,
    board : Rc<RefCell<Board>>
}

impl Snake {
    pub fn move_up(&mut self) -> bool {
        let new_x;
        let new_y;
        {
            let head  = self.head.borrow();
            let board = self.board.borrow();
            new_x = head.get_x();
            let mut y = head.get_y();
            if y == 0 { y = board.get_height(); }
            new_y = y - 1;
        }
        self.do_move(new_snake_element(new_x, new_y))
    }

    pub fn move_down(&mut self) -> bool {
        let new_x;
        let new_y;
        {
            let head  = self.head.borrow();
            let board = self.board.borrow();
            new_x = head.get_x();
            let mut y = head.get_y() + 1;
            if y == board.get_height() { y = 0; }
            new_y = y;
        }
        self.do_move(new_snake_element(new_x, new_y))
    }

    pub fn move_left(&mut self) -> bool {
        let new_x;
        let new_y;
        {
            let head  = self.head.borrow();
            let board = self.board.borrow();
            let mut x = head.get_x();
            if x == 0 { x = board.get_width() }
            new_x = x - 1;
            new_y = head.get_y();
        }
        self.do_move(new_snake_element(new_x, new_y))
    }

    pub fn move_right(&mut self) -> bool {
        let new_x;
        let new_y;
        {
            let head  = self.head.borrow();
            let board = self.board.borrow();
            let mut x = head.get_x() + 1;
            if x == board.get_width() { x = 0; }
            new_x = x;
            new_y = head.get_y();
        }
        self.do_move(new_snake_element(new_x, new_y))
    }

    fn do_move(&mut self, new_head: Rc<RefCell<SnakeElement>>) -> bool {
        let x;
        let y;
        {
            let mut nh = new_head.borrow_mut();
            x = nh.get_x();
            y = nh.get_y();
        }
        {
            let mut head = self.head.borrow_mut();
            head.set_prev(new_head.clone());
        }
        self.head = new_head.clone();

        let mut board = self.board.borrow_mut();

        if board.is_apple(x, y) {
            board.add_apple();
        } else {
            if board.is_snake(x, y) {
                return false;
            }

            board.remove(self.tail.clone());
            let prev;
            {
                let tail = self.tail.borrow();
                prev = tail.get_prev().unwrap();
            }
            self.tail = prev;
            let mut tail = self.tail.borrow_mut();
            tail.set_prev_to_none();
        }

        board.add(new_head.clone());

        true
    }
}

pub fn new(x: usize, y: usize, board: Rc<RefCell<Board>>) -> Snake {
    let snake_start = new_snake_element(x, y);
    let snake = Snake {head:  snake_start.clone(),
                       tail:  snake_start.clone(),
                       board: board.clone()};
    let b = board.borrow();
    b.add(snake_start);
    snake
}
<|endoftext|>


<commit_before>// Copyright 2018 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.

#![feature(const_fn)]
#![allow(const_err)]

use std::env;
use std::process::{Command, Stdio};

const fn bar() -> usize { 0 - 1 }

fn foo() {
    let _: &'static _ = &bar();
}

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() > 1 && args[1] == "test" {
        foo();
        return;
    }

    let mut p = Command::new(&args[0])
        .stdout(Stdio::piped())
        .stdin(Stdio::piped())
        .arg("test").output().unwrap();
    assert!(!p.status.success());
}<commit_msg>Add trailing newline<commit_after>// Copyright 2018 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.

#![feature(const_fn)]
#![allow(const_err)]

use std::env;
use std::process::{Command, Stdio};

const fn bar() -> usize { 0 - 1 }

fn foo() {
    let _: &'static _ = &bar();
}

fn main() {
    let args: Vec<String> = env::args().collect();
    if args.len() > 1 && args[1] == "test" {
        foo();
        return;
    }

    let mut p = Command::new(&args[0])
        .stdout(Stdio::piped())
        .stdin(Stdio::piped())
        .arg("test").output().unwrap();
    assert!(!p.status.success());
}
<|endoftext|>


<commit_before>use hir::db::AstDatabase;
use ide_db::source_change::SourceChange;
use syntax::{ast, AstNode};
use text_edit::TextEdit;

use crate::{fix, Assist, Diagnostic, DiagnosticsContext};

// Diagnostic: remove-this-semicolon
//
// This diagnostic is triggered when there's an erroneous `;` at the end of the block.
pub(crate) fn remove_this_semicolon(
    ctx: &DiagnosticsContext<'_>,
    d: &hir::RemoveThisSemicolon,
) -> Diagnostic {
    Diagnostic::new(
        "remove-this-semicolon",
        "remove this semicolon",
        ctx.sema.diagnostics_display_range(d.expr.clone().map(|it| it.into())).range,
    )
    .with_fixes(fixes(ctx, d))
}

fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::RemoveThisSemicolon) -> Option<Vec<Assist>> {
    let root = ctx.sema.db.parse_or_expand(d.expr.file_id)?;

    let semicolon = d
        .expr
        .value
        .to_node(&root)
        .syntax()
        .parent()
        .and_then(ast::ExprStmt::cast)
        .and_then(|expr| expr.semicolon_token())?
        .text_range();

    let edit = TextEdit::delete(semicolon);
    let source_change =
        SourceChange::from_text_edit(d.expr.file_id.original_file(ctx.sema.db), edit);

    Some(vec![fix("remove_semicolon", "Remove this semicolon", source_change, semicolon)])
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_diagnostics, check_fix};

    #[test]
    fn missing_semicolon() {
        check_diagnostics(
            r#"
fn test() -> i32 { 123; }
                 //^^^ 💡 error: remove this semicolon
"#,
        );
    }

    #[test]
    fn remove_semicolon() {
        check_fix(r#"fn f() -> i32 { 92$0; }"#, r#"fn f() -> i32 { 92 }"#);
    }
}
<commit_msg>fix: remove semicolon diagnostics only highlights the semi<commit_after>use ide_db::{
    base_db::{FileLoader, FileRange},
    source_change::SourceChange,
};
use syntax::{TextRange, TextSize};
use text_edit::TextEdit;

use crate::{fix, Assist, Diagnostic, DiagnosticsContext};

// Diagnostic: remove-this-semicolon
//
// This diagnostic is triggered when there's an erroneous `;` at the end of the block.
pub(crate) fn remove_this_semicolon(
    ctx: &DiagnosticsContext<'_>,
    d: &hir::RemoveThisSemicolon,
) -> Diagnostic {
    Diagnostic::new(
        "remove-this-semicolon",
        "remove this semicolon",
        semicolon_range(ctx, d).unwrap_or_else(|it| it).range,
    )
    .with_fixes(fixes(ctx, d))
}

fn semicolon_range(
    ctx: &DiagnosticsContext<'_>,
    d: &hir::RemoveThisSemicolon,
) -> Result<FileRange, FileRange> {
    let expr_range = ctx.sema.diagnostics_display_range(d.expr.clone().map(|it| it.into()));
    let file_text = ctx.sema.db.file_text(expr_range.file_id);
    let range_end: usize = expr_range.range.end().into();
    // FIXME: This doesn't handle whitespace and comments, but handling those in
    // the presence of macros might prove tricky...
    if file_text[range_end..].starts_with(';') {
        Ok(FileRange {
            file_id: expr_range.file_id,
            range: TextRange::at(expr_range.range.end(), TextSize::of(';')),
        })
    } else {
        Err(expr_range)
    }
}

fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::RemoveThisSemicolon) -> Option<Vec<Assist>> {
    let semicolon_range = semicolon_range(ctx, d).ok()?;

    let edit = TextEdit::delete(semicolon_range.range);
    let source_change = SourceChange::from_text_edit(semicolon_range.file_id, edit);

    Some(vec![fix(
        "remove_semicolon",
        "Remove this semicolon",
        source_change,
        semicolon_range.range,
    )])
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_diagnostics, check_fix};

    #[test]
    fn missing_semicolon() {
        check_diagnostics(
            r#"
fn test() -> i32 { 123; }
                    //^ 💡 error: remove this semicolon
"#,
        );
    }

    #[test]
    fn remove_semicolon() {
        check_fix(r#"fn f() -> i32 { 92$0; }"#, r#"fn f() -> i32 { 92 }"#);
    }
}
<|endoftext|>


<commit_before>use winit::{WindowBuilder, get_available_monitors, get_primary_monitor};
use vulkano_win::{Window, VkSurfaceBuild, required_extensions};
use vulkano::instance::Instance;

use config::Config;
use config::WindowConfig;

pub struct Engine {
    window: Window,
}

impl Engine {
    pub fn new(config: Config) -> Engine {

        let window_builder = create_window(config.window);

        // @TODO - Pass window to renderer specific initializer...

        let instance = {
            let extensions = required_extensions();
            Instance::new(None, &extensions, None).expect("Failed to create Vulkan instance.")
        };

        let window = window_builder.build_vk_surface(&instance).unwrap();

        Engine { window }
    }

    pub fn io(&self) {}

    pub fn update(&self) -> bool {
        false
    }

    pub fn render(&self) {}
}

/// Creates a window builder with a given window configuration.
pub fn create_window(config: WindowConfig) -> WindowBuilder  {

    let window_manager = WindowBuilder::new()
        .with_title("CodeVR")
        .with_dimensions(config.resolution[0], config.resolution[1]);

    let mut w = get_primary_monitor();

    if config.fullscreen {
        for (i, monitor) in get_available_monitors().enumerate() {
            if i == config.display as usize {
                w = monitor;
            }
        }
    }

    window_manager.with_fullscreen(w)
}
<commit_msg>Hooking up Vulkan renderer to engine<commit_after>use winit::{WindowBuilder, get_available_monitors, get_primary_monitor};
use vulkano_win::{Window, VkSurfaceBuild, required_extensions};
use vulkano::instance::{Instance, PhysicalDevice};
use vulkano::device::{Queue, Device, DeviceExtensions};
use vulkano::swapchain::{Swapchain, SurfaceTransform};

use config::Config;
use config::WindowConfig;

use std::sync::Arc;

pub struct Engine {
    window: Window,
    instance: Arc<Instance>,
    device: Arc<Device>,
    swapchain: Arc<Swapchain>,
    queue: Arc<Queue>

}

impl Engine {
    pub fn new(config: Config) -> Engine {

        let window_builder = create_window(config.window);

        // @TODO - Pass window to renderer specific initializer...

        let instance = {
            let extensions = required_extensions();
            Instance::new(None, &extensions, None).expect("Failed to create Vulkan instance.")
        };

        let physical_device = PhysicalDevice::enumerate(&instance)
            .next()
            .expect("No vulkan device is available.");

        let window = window_builder.build_vk_surface(&instance).unwrap();

        let queue = physical_device
            .queue_families()
            .find(|q| q.supports_graphics() && window.surface().is_supported(q).unwrap_or(false))
            .expect("Couldn't find a graphical queue family.");

        // Logical Device, Queues
        let (device, mut queues) = {
            let device_ext = DeviceExtensions {
                khr_swapchain: true,
                ..DeviceExtensions::none()
            };

            Device::new(&physical_device,
                        physical_device.supported_features(),
                        &device_ext,
                        [(queue, 0.5)].iter().cloned())
                    .expect("failed to create device")
        };

        // Device Queue
        let queue = queues.next().unwrap();

        // Swapchain, Swapchain Images
        let (swapchain, images) = {

            let caps = window
                .surface()
                .get_capabilities(&physical_device)
                .expect("failed to get surface capabilities");

            let dimensions = caps.current_extent.unwrap_or([1280, 720]);

            let present = caps.present_modes.iter().next().unwrap();

            let alpha = caps.supported_composite_alpha.iter().next().unwrap();

            let format = caps.supported_formats[0].0;

            Swapchain::new(&device,
                           &window.surface(),
                           caps.min_image_count,
                           format,
                           dimensions,
                           1,
                           &caps.supported_usage_flags,
                           &queue,
                           SurfaceTransform::Identity,
                           alpha,
                           present,
                           true,
                           None)
                    .expect("failed to create swapchain")
        };

        Engine {
            window: window,
            instance: instance.clone(),
            device,
            swapchain,
            queue
        }
    }

    pub fn io(&self) {}

    pub fn update(&self) -> bool {
        false
    }

    pub fn render(&self) {}
}

/// Creates a window builder with a given window configuration.
pub fn create_window(config: WindowConfig) -> WindowBuilder {

    let window_manager = WindowBuilder::new()
        .with_title("CodeVR")
        .with_dimensions(config.resolution[0], config.resolution[1]);

    let mut w = get_primary_monitor();

    if config.fullscreen {
        for (i, monitor) in get_available_monitors().enumerate() {
            if i == config.display as usize {
                w = monitor;
            }
        }
    }

    window_manager.with_fullscreen(w)
}

<|endoftext|>


<commit_before>extern crate cc;
extern crate regex;

fn main() {
    build::main()
}

#[cfg(feature = "docs-only")]
mod build {
    pub fn main() {}
}

#[cfg(not(feature = "docs-only"))]
mod build {
    use std::process::Command;
    use std::env;
    use std::fs;
    use std::path::Path;
    use regex::Regex;

    pub fn main() {
        let out_dir = env::var("OUT_DIR").unwrap();
        let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();

        let out_dir = Path::new(&out_dir);
        let native_from = Path::new(&crate_dir).join("native");
        let native_to = Path::new(&out_dir).join("native");

        // 1. Copy the native runtime library into the build directory.
        copy_native_library(&native_from, &native_to);

        // 2. Build the object file from source using node-gyp.
        build_object_file(&native_to);

        // 3. Link the library from the object file using gcc.
        link_library(&native_to);

        // 4. Copy native build artifacts
        copy_build_artifacts(&native_to, &out_dir);

        // Rebuild if any of these environment variables change
        println!("cargo:rerun-if-env-changed=npm_config_target");
        println!("cargo:rerun-if-env-changed=npm_config_arch");
        println!("cargo:rerun-if-env-changed=npm_config_target_arch");
    }

    fn copy_files(dir_from: impl AsRef<Path>, dir_to: impl AsRef<Path>) {
        for entry in fs::read_dir(dir_from.as_ref()).unwrap() {
            let entry = entry.unwrap();

            if entry.file_type().unwrap().is_dir() {
                continue;
            }

            let file_name = entry.file_name();

            let from = dir_from.as_ref().join(&file_name);
            let to = dir_to.as_ref().join(&file_name);

            fs::copy(from, to).unwrap();
        }
    }

    fn copy_native_library(native_from: impl AsRef<Path>, native_to: impl AsRef<Path>) {
        let native_from = native_from.as_ref();
        let native_to = native_to.as_ref();

        let src_from = native_from.join("src");
        let src_to = native_to.join("src");

        fs::create_dir_all(&src_to).unwrap();

        copy_files(&native_from, &native_to);
        copy_files(&src_from, &src_to);
    }

    #[cfg(unix)]
    fn npm(cwd: &Path) -> Command {
        let mut cmd = Command::new("npm");
        cmd.current_dir(cwd);
        cmd
    }

    #[cfg(windows)]
    fn npm(cwd: &Path) -> Command {
        let mut cmd = Command::new("cmd.exe");
        cmd.args(&["/C", "npm"]);
        cmd.current_dir(cwd);
        cmd
    }

    // The node-gyp output includes platform information in a string
    // that looks like:
    //
    //     gyp info using node@8.3.0 | win32 | x64
    fn parse_node_arch(node_gyp_output: &str) -> String {
        let version_regex = Regex::new(r"node@(?P<version>\d+\.\d+\.\d+)\s+\|\s+(?P<platform>\w+)\s+\|\s(?P<arch>ia32|x64)").unwrap();
        let captures = version_regex.captures(&node_gyp_output).unwrap();
        String::from(&captures["arch"])
    }

    // The node-gyp output includes the root directory of shared resources
    // for the Node installation in a string that looks like:
    //
    //     '-Dnode_root_dir=C:\\Users\\dherman\\.node-gyp\\8.3.0'
    fn parse_node_root_dir(node_gyp_output: &str) -> &str {
        let node_root_dir_flag_pattern = "'-Dnode_root_dir=";
        let node_root_dir_start_index = node_gyp_output
            .find(node_root_dir_flag_pattern)
            .map(|i| i + node_root_dir_flag_pattern.len())
            .expect("Couldn't find node_root_dir in node-gyp output.");
        let node_root_dir_end_index = node_gyp_output[node_root_dir_start_index..].find("'").unwrap() + node_root_dir_start_index;
        &node_gyp_output[node_root_dir_start_index..node_root_dir_end_index]
    }

    // The node-gyp output includes the name of the shared Node library file.
    // In NPM versions <= v5.0.3, this was just the filename by itself, e.g.:
    //
    //     '-Dnode_lib_file=node.lib'
    //
    // In NPM versions >= v5.3.0, this was a templated absolute path with a
    // reference to a gyp variable, e.g.:
    //
    //     '-Dnode_lib_file=C:\\Users\\dherman\\.node-gyp\\8.3.0\\<(target_arch)\\node.lib'
    //
    // Either way, we simply extract the value here. The `neon-build` crate
    // processes it further.
    fn parse_node_lib_file(node_gyp_output: &str) -> &str {
        let node_lib_file_flag_pattern = "'-Dnode_lib_file=";
        let node_lib_file_start_index = node_gyp_output
            .find(node_lib_file_flag_pattern)
            .map(|i| i + node_lib_file_flag_pattern.len())
            .expect("Couldn't find node_lib_file in node-gyp output.");
        let node_lib_file_end_index = node_gyp_output[node_lib_file_start_index..].find("'").unwrap() + node_lib_file_start_index;
        &node_gyp_output[node_lib_file_start_index..node_lib_file_end_index]
    }

    fn build_object_file(native_dir: &Path) {
        if cfg!(windows) {
            // Downcase all the npm environment variables to ensure they are read by node-gyp.
            for (key, value) in env::vars() {
                if key.starts_with("NPM_CONFIG") {
                    env::remove_var(&key);
                    env::set_var(key.to_lowercase(), value);
                }
            }
        }

        // Ensure that all package.json dependencies and dev dependencies are installed.
        npm(native_dir).args(&["install", "--silent"]).status().ok().expect("Failed to run \"npm install\" for neon-sys!");

        // Run `node-gyp configure` in verbose mode to read node_root_dir on Windows.
        let output = npm(native_dir)
            .args(&["run", if debug() { "configure-debug" } else { "configure-release" }])
            .output()
            .expect("Failed to run \"node-gyp configure\" for neon-sys!");

        if !output.status.success() {
            panic!(format!(
                "Failed to run \"node-gyp configure\" for neon-sys!\n Out: {}\n Err: {}",
                String::from_utf8_lossy(&output.stdout),
                String::from_utf8_lossy(&output.stderr)
            ));
        }

        if cfg!(windows) {
            let node_gyp_output = String::from_utf8_lossy(&output.stderr);
            println!("cargo:node_arch={}", parse_node_arch(&node_gyp_output));
            println!("cargo:node_root_dir={}", parse_node_root_dir(&node_gyp_output));
            println!("cargo:node_lib_file={}", parse_node_lib_file(&node_gyp_output));
        }

        // Run `node-gyp build`.
        npm(native_dir)
            .args(&["run", if debug() { "build-debug" } else { "build-release" }])
            .status()
            .ok()
            .expect("Failed to run \"node-gyp build\" for neon-sys!");
    }

    // Link the built object file into a static library.
    fn link_library(native_dir: &Path) {
        let configuration = if debug() { "Debug" } else { "Release" };

        let object_path = if cfg!(unix) {
            native_dir
                .join("build")
                .join(configuration)
                .join("obj.target")
                .join("neon")
                .join("src")
                .join("neon.o")
        } else {
            native_dir
                .join("build")
                .join(configuration)
                .join("obj")
                .join("neon")
                .join("neon.obj")
        };

        cc::Build::new().cpp(true).object(object_path).compile("libneon.a");
    }

    #[cfg(unix)]
    fn copy_build_artifacts(_native_dir: &Path, _out_dir: &Path) {}

    #[cfg(windows)]
    fn copy_build_artifacts(native_dir: &Path, out_dir: &Path) {
        let configuration = if debug() { "Debug" } else { "Release" };
        let win_delay_file = "win_delay_load_hook.obj";
        let win_delay_dest = out_dir.join(win_delay_file);
        let win_delay_source = native_dir
            .join("build")
            .join(configuration)
            .join("obj")
            .join("neon")
            .join(win_delay_file);

        // Win delay hook is only needed for electron, warn instead of crash if not found
        if let Err(err) = fs::copy(win_delay_source, win_delay_dest) {
            if err.kind() == std::io::ErrorKind::NotFound {
                eprintln!("warning: {} could not be found", win_delay_file);
            } else {
                panic!("{:?}", err);
            }
        }
    }

    fn debug() -> bool {
        match env::var("DEBUG") {
            Ok(s) => s == "true",
            Err(_) => false
        }
    }
}
<commit_msg>Attempt to fix architecture detection<commit_after>extern crate cc;
extern crate regex;

fn main() {
    build::main()
}

#[cfg(feature = "docs-only")]
mod build {
    pub fn main() {}
}

#[cfg(not(feature = "docs-only"))]
mod build {
    use std::process::Command;
    use std::env;
    use std::fs;
    use std::path::Path;
    use regex::Regex;

    pub fn main() {
        let out_dir = env::var("OUT_DIR").unwrap();
        let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();

        let out_dir = Path::new(&out_dir);
        let native_from = Path::new(&crate_dir).join("native");
        let native_to = Path::new(&out_dir).join("native");

        // 1. Copy the native runtime library into the build directory.
        copy_native_library(&native_from, &native_to);

        // 2. Build the object file from source using node-gyp.
        build_object_file(&native_to);

        // 3. Link the library from the object file using gcc.
        link_library(&native_to);

        // 4. Copy native build artifacts
        copy_build_artifacts(&native_to, &out_dir);

        // Rebuild if any of these environment variables change
        println!("cargo:rerun-if-env-changed=npm_config_target");
        println!("cargo:rerun-if-env-changed=npm_config_arch");
        println!("cargo:rerun-if-env-changed=npm_config_target_arch");
    }

    fn copy_files(dir_from: impl AsRef<Path>, dir_to: impl AsRef<Path>) {
        for entry in fs::read_dir(dir_from.as_ref()).unwrap() {
            let entry = entry.unwrap();

            if entry.file_type().unwrap().is_dir() {
                continue;
            }

            let file_name = entry.file_name();

            let from = dir_from.as_ref().join(&file_name);
            let to = dir_to.as_ref().join(&file_name);

            fs::copy(from, to).unwrap();
        }
    }

    fn copy_native_library(native_from: impl AsRef<Path>, native_to: impl AsRef<Path>) {
        let native_from = native_from.as_ref();
        let native_to = native_to.as_ref();

        let src_from = native_from.join("src");
        let src_to = native_to.join("src");

        fs::create_dir_all(&src_to).unwrap();

        copy_files(&native_from, &native_to);
        copy_files(&src_from, &src_to);
    }

    #[cfg(unix)]
    fn npm(cwd: &Path) -> Command {
        let mut cmd = Command::new("npm");
        cmd.current_dir(cwd);
        cmd
    }

    #[cfg(windows)]
    fn npm(cwd: &Path) -> Command {
        let mut cmd = Command::new("cmd.exe");
        cmd.args(&["/C", "npm"]);
        cmd.current_dir(cwd);
        cmd
    }

    // The node-gyp build output includes platform information in a string
    // that looks like:
    //
    //     gyp verb architecture ia32
    fn parse_node_arch(node_gyp_output: &str) -> String {
        let version_regex = Regex::new(r"gyp verb architecture (?P<arch>ia32|x64)").unwrap();
        let captures = version_regex.captures(&node_gyp_output).unwrap();
        String::from(&captures["arch"])
    }

    // The node-gyp output includes the root directory of shared resources
    // for the Node installation in a string that looks like:
    //
    //     '-Dnode_root_dir=C:\\Users\\dherman\\.node-gyp\\8.3.0'
    fn parse_node_root_dir(node_gyp_output: &str) -> &str {
        let node_root_dir_flag_pattern = "'-Dnode_root_dir=";
        let node_root_dir_start_index = node_gyp_output
            .find(node_root_dir_flag_pattern)
            .map(|i| i + node_root_dir_flag_pattern.len())
            .expect("Couldn't find node_root_dir in node-gyp output.");
        let node_root_dir_end_index = node_gyp_output[node_root_dir_start_index..].find("'").unwrap() + node_root_dir_start_index;
        &node_gyp_output[node_root_dir_start_index..node_root_dir_end_index]
    }

    // The node-gyp output includes the name of the shared Node library file.
    // In NPM versions <= v5.0.3, this was just the filename by itself, e.g.:
    //
    //     '-Dnode_lib_file=node.lib'
    //
    // In NPM versions >= v5.3.0, this was a templated absolute path with a
    // reference to a gyp variable, e.g.:
    //
    //     '-Dnode_lib_file=C:\\Users\\dherman\\.node-gyp\\8.3.0\\<(target_arch)\\node.lib'
    //
    // Either way, we simply extract the value here. The `neon-build` crate
    // processes it further.
    fn parse_node_lib_file(node_gyp_output: &str) -> &str {
        let node_lib_file_flag_pattern = "'-Dnode_lib_file=";
        let node_lib_file_start_index = node_gyp_output
            .find(node_lib_file_flag_pattern)
            .map(|i| i + node_lib_file_flag_pattern.len())
            .expect("Couldn't find node_lib_file in node-gyp output.");
        let node_lib_file_end_index = node_gyp_output[node_lib_file_start_index..].find("'").unwrap() + node_lib_file_start_index;
        &node_gyp_output[node_lib_file_start_index..node_lib_file_end_index]
    }

    fn build_object_file(native_dir: &Path) {
        if cfg!(windows) {
            // Downcase all the npm environment variables to ensure they are read by node-gyp.
            for (key, value) in env::vars() {
                if key.starts_with("NPM_CONFIG") {
                    env::remove_var(&key);
                    env::set_var(key.to_lowercase(), value);
                }
            }
        }

        // Ensure that all package.json dependencies and dev dependencies are installed.
        npm(native_dir).args(&["install", "--silent"]).status().ok().expect("Failed to run \"npm install\" for neon-sys!");

        // Run `node-gyp configure` in verbose mode to read node_root_dir on Windows.
        let output = npm(native_dir)
            .args(&["run", if debug() { "configure-debug" } else { "configure-release" }])
            .output()
            .expect("Failed to run \"node-gyp configure\" for neon-sys!");

        if !output.status.success() {
            panic!(format!(
                "Failed to run \"node-gyp configure\" for neon-sys!\n Out: {}\n Err: {}",
                String::from_utf8_lossy(&output.stdout),
                String::from_utf8_lossy(&output.stderr)
            ));
        }

        if cfg!(windows) {
            println!("cargo:node_root_dir={}", parse_node_root_dir(&node_gyp_output));
            println!("cargo:node_lib_file={}", parse_node_lib_file(&node_gyp_output));
        }

        // Run `node-gyp build`.
        let build_output = npm(native_dir)
            .args(&["run", if debug() { "build-debug" } else { "build-release" }])
            .output()
            .ok()
            .expect("Failed to run \"node-gyp build\" for neon-sys!");

        let node_gyp_build_output = String::from_utf8_lossy(&build_output.stderr);
        println!("cargo:node_arch={}", parse_node_arch(&node_gyp_build_output));
    }

    // Link the built object file into a static library.
    fn link_library(native_dir: &Path) {
        let configuration = if debug() { "Debug" } else { "Release" };

        let object_path = if cfg!(unix) {
            native_dir
                .join("build")
                .join(configuration)
                .join("obj.target")
                .join("neon")
                .join("src")
                .join("neon.o")
        } else {
            native_dir
                .join("build")
                .join(configuration)
                .join("obj")
                .join("neon")
                .join("neon.obj")
        };

        cc::Build::new().cpp(true).object(object_path).compile("libneon.a");
    }

    #[cfg(unix)]
    fn copy_build_artifacts(_native_dir: &Path, _out_dir: &Path) {}

    #[cfg(windows)]
    fn copy_build_artifacts(native_dir: &Path, out_dir: &Path) {
        let configuration = if debug() { "Debug" } else { "Release" };
        let win_delay_file = "win_delay_load_hook.obj";
        let win_delay_dest = out_dir.join(win_delay_file);
        let win_delay_source = native_dir
            .join("build")
            .join(configuration)
            .join("obj")
            .join("neon")
            .join(win_delay_file);

        // Win delay hook is only needed for electron, warn instead of crash if not found
        if let Err(err) = fs::copy(win_delay_source, win_delay_dest) {
            if err.kind() == std::io::ErrorKind::NotFound {
                eprintln!("warning: {} could not be found", win_delay_file);
            } else {
                panic!("{:?}", err);
            }
        }
    }

    fn debug() -> bool {
        match env::var("DEBUG") {
            Ok(s) => s == "true",
            Err(_) => false
        }
    }
}
<|endoftext|>


<commit_before>#![feature(track_caller)]
use std::fmt::Debug;

// Helper function to avoid promotion so that this tests "run-time" casts, not CTFE.
// Doesn't make a big difference when running this in Miri, but when running this in
// rustc (with -Zmir-opt-level=0) for comparison it means we use LLVM casts.
#[track_caller]
#[inline(never)]
fn assert_eq<T: PartialEq + Debug>(x: T, y: T) {
    assert_eq!(x, y);
}

fn main() {
    // basic arithmetic
    assert_eq(6.0_f32*6.0_f32, 36.0_f32);
    assert_eq(6.0_f64*6.0_f64, 36.0_f64);
    assert_eq(-{5.0_f32}, -5.0_f32);
    assert_eq(-{5.0_f64}, -5.0_f64);
    // infinities, NaN
    assert!((5.0_f32/0.0).is_infinite());
    assert!((5.0_f64/0.0).is_infinite());
    assert!((-5.0_f32).sqrt().is_nan());
    assert!((-5.0_f64).sqrt().is_nan());
    // byte-level transmute
    let x: u64 = unsafe { std::mem::transmute(42.0_f64) };
    let y: f64 = unsafe { std::mem::transmute(x) };
    assert_eq(y, 42.0_f64);
    let x: u32 = unsafe { std::mem::transmute(42.0_f32) };
    let y: f32 = unsafe { std::mem::transmute(x) };
    assert_eq(y, 42.0_f32);

    // f32-to-int casts
    assert_eq(5.0f32 as u32, 5);
    assert_eq(-5.0f32 as u32, 0);
    assert_eq(5.0f32 as i32, 5);
    assert_eq(-5.0f32 as i32, -5);
    assert_eq(std::f32::MAX as i32, i32::MAX);
    assert_eq(std::f32::INFINITY as i32, i32::MAX);
    assert_eq(std::f32::MAX as u32, u32::MAX);
    assert_eq(std::f32::INFINITY as u32, u32::MAX);
    assert_eq(std::f32::MIN as i32, i32::MIN);
    assert_eq(std::f32::NEG_INFINITY as i32, i32::MIN);
    assert_eq(std::f32::MIN as u32, 0);
    assert_eq(std::f32::NEG_INFINITY as u32, 0);
    assert_eq(std::f32::NAN as i32, 0);
    assert_eq(std::f32::NAN as u32, 0);
    assert_eq(u128::MAX as f32, std::f32::INFINITY);
    assert_eq((u32::MAX-127) as f32 as u32, u32::MAX); // rounding loss
    assert_eq((u32::MAX-128) as f32 as u32, u32::MAX-255); // rounding loss

    // f64-to-int casts
    assert_eq(5.0f64 as u64, 5);
    assert_eq(-5.0f64 as u64, 0);
    assert_eq(5.0f64 as i64, 5);
    assert_eq(-5.0f64 as i64, -5);
    assert_eq(std::f64::MAX as i64, i64::MAX);
    assert_eq(std::f64::INFINITY as i64, i64::MAX);
    assert_eq(std::f64::MAX as u64, u64::MAX);
    assert_eq(std::f64::INFINITY as u64, u64::MAX);
    assert_eq(std::f64::MIN as i64, i64::MIN);
    assert_eq(std::f64::NEG_INFINITY as i64, i64::MIN);
    assert_eq(std::f64::MIN as u64, 0);
    assert_eq(std::f64::NEG_INFINITY as u64, 0);
    assert_eq(std::f64::NAN as i64, 0);
    assert_eq(std::f64::NAN as u64, 0);
    assert_eq(u128::MAX as f64 as u128, u128::MAX);
    assert_eq((u64::MAX-1023) as f64 as u64, u64::MAX); // rounding loss
    assert_eq((u64::MAX-1024) as f64 as u64, u64::MAX-2047); // rounding loss

    // f32 <-> f64 casts
    assert_eq(5.0f64 as f32, 5.0f32);
    assert_eq(5.0f32 as f64, 5.0f64);
    assert_eq(std::f64::MAX as f32, std::f32::INFINITY);
    assert_eq(std::f64::MIN as f32, std::f32::NEG_INFINITY);
    assert_eq(std::f32::INFINITY as f64, std::f64::INFINITY);
    assert_eq(std::f32::NEG_INFINITY as f64, std::f64::NEG_INFINITY);

    // f32 min/max
    assert_eq((1.0 as f32).max(-1.0), 1.0);
    assert_eq((1.0 as f32).min(-1.0), -1.0);
    assert_eq(std::f32::NAN.min(9.0), 9.0);
    assert_eq(std::f32::NAN.max(-9.0), -9.0);
    assert_eq((9.0 as f32).min(std::f32::NAN), 9.0);
    assert_eq((-9.0 as f32).max(std::f32::NAN), -9.0);

    // f64 min/max
    assert_eq((1.0 as f64).max(-1.0), 1.0);
    assert_eq((1.0 as f64).min(-1.0), -1.0);
    assert_eq(std::f64::NAN.min(9.0), 9.0);
    assert_eq(std::f64::NAN.max(-9.0), -9.0);
    assert_eq((9.0 as f64).min(std::f64::NAN), 9.0);
    assert_eq((-9.0 as f64).max(std::f64::NAN), -9.0);

    // f32 copysign
    assert_eq(3.5_f32.copysign(0.42), 3.5_f32);
    assert_eq(3.5_f32.copysign(-0.42), -3.5_f32);
    assert_eq((-3.5_f32).copysign(0.42), 3.5_f32);
    assert_eq((-3.5_f32).copysign(-0.42), -3.5_f32);
    assert!(std::f32::NAN.copysign(1.0).is_nan());

    // f64 copysign
    assert_eq(3.5_f64.copysign(0.42), 3.5_f64);
    assert_eq(3.5_f64.copysign(-0.42), -3.5_f64);
    assert_eq((-3.5_f64).copysign(0.42), 3.5_f64);
    assert_eq((-3.5_f64).copysign(-0.42), -3.5_f64);
    assert!(std::f64::NAN.copysign(1.0).is_nan());
}
<commit_msg>Auto merge of #1274 - RalfJung:float-cast, r=RalfJung<commit_after>#![feature(track_caller)]
use std::fmt::Debug;

// Helper function to avoid promotion so that this tests "run-time" casts, not CTFE.
// Doesn't make a big difference when running this in Miri, but it means we can compare this
// with the LLVM backend by running `rustc -Zmir-opt-level=0 -Zsaturating-float-casts`.
#[track_caller]
#[inline(never)]
fn assert_eq<T: PartialEq + Debug>(x: T, y: T) {
    assert_eq!(x, y);
}

fn main() {
    // basic arithmetic
    assert_eq(6.0_f32*6.0_f32, 36.0_f32);
    assert_eq(6.0_f64*6.0_f64, 36.0_f64);
    assert_eq(-{5.0_f32}, -5.0_f32);
    assert_eq(-{5.0_f64}, -5.0_f64);
    // infinities, NaN
    assert!((5.0_f32/0.0).is_infinite());
    assert!((5.0_f64/0.0).is_infinite());
    assert!((-5.0_f32).sqrt().is_nan());
    assert!((-5.0_f64).sqrt().is_nan());
    // byte-level transmute
    let x: u64 = unsafe { std::mem::transmute(42.0_f64) };
    let y: f64 = unsafe { std::mem::transmute(x) };
    assert_eq(y, 42.0_f64);
    let x: u32 = unsafe { std::mem::transmute(42.0_f32) };
    let y: f32 = unsafe { std::mem::transmute(x) };
    assert_eq(y, 42.0_f32);

    // f32 <-> int casts
    assert_eq(5.0f32 as u32, 5);
    assert_eq(-5.0f32 as u32, 0);
    assert_eq(5.0f32 as i32, 5);
    assert_eq(-5.0f32 as i32, -5);
    assert_eq(std::f32::MAX as i32, i32::MAX);
    assert_eq(std::f32::INFINITY as i32, i32::MAX);
    assert_eq(std::f32::MAX as u32, u32::MAX);
    assert_eq(std::f32::INFINITY as u32, u32::MAX);
    assert_eq(std::f32::MIN as i32, i32::MIN);
    assert_eq(std::f32::NEG_INFINITY as i32, i32::MIN);
    assert_eq(std::f32::MIN as u32, 0);
    assert_eq(std::f32::NEG_INFINITY as u32, 0);
    assert_eq(std::f32::NAN as i32, 0);
    assert_eq(std::f32::NAN as u32, 0);
    assert_eq((u32::MAX-127) as f32 as u32, u32::MAX); // rounding loss
    assert_eq((u32::MAX-128) as f32 as u32, u32::MAX-255); // rounding loss
    assert_eq(127i8 as f32, 127.0f32);
    assert_eq(i128::MIN as f32, -170141183460469231731687303715884105728.0f32);
    assert_eq(u128::MAX as f32, std::f32::INFINITY); // saturation

    // f64 <-> int casts
    assert_eq(5.0f64 as u64, 5);
    assert_eq(-5.0f64 as u64, 0);
    assert_eq(5.0f64 as i64, 5);
    assert_eq(-5.0f64 as i64, -5);
    assert_eq(std::f64::MAX as i64, i64::MAX);
    assert_eq(std::f64::INFINITY as i64, i64::MAX);
    assert_eq(std::f64::MAX as u64, u64::MAX);
    assert_eq(std::f64::INFINITY as u64, u64::MAX);
    assert_eq(std::f64::MIN as i64, i64::MIN);
    assert_eq(std::f64::NEG_INFINITY as i64, i64::MIN);
    assert_eq(std::f64::MIN as u64, 0);
    assert_eq(std::f64::NEG_INFINITY as u64, 0);
    assert_eq(std::f64::NAN as i64, 0);
    assert_eq(std::f64::NAN as u64, 0);
    assert_eq((u64::MAX-1023) as f64 as u64, u64::MAX); // rounding loss
    assert_eq((u64::MAX-1024) as f64 as u64, u64::MAX-2047); // rounding loss
    assert_eq(u128::MAX as f64 as u128, u128::MAX);
    assert_eq(i16::MIN as f64, -32768.0f64);
    assert_eq(u128::MAX as f64, 340282366920938463463374607431768211455.0f64); // even that fits...

    // f32 <-> f64 casts
    assert_eq(5.0f64 as f32, 5.0f32);
    assert_eq(5.0f32 as f64, 5.0f64);
    assert_eq(std::f64::MAX as f32, std::f32::INFINITY);
    assert_eq(std::f64::MIN as f32, std::f32::NEG_INFINITY);
    assert_eq(std::f32::INFINITY as f64, std::f64::INFINITY);
    assert_eq(std::f32::NEG_INFINITY as f64, std::f64::NEG_INFINITY);

    // f32 min/max
    assert_eq((1.0 as f32).max(-1.0), 1.0);
    assert_eq((1.0 as f32).min(-1.0), -1.0);
    assert_eq(std::f32::NAN.min(9.0), 9.0);
    assert_eq(std::f32::NAN.max(-9.0), -9.0);
    assert_eq((9.0 as f32).min(std::f32::NAN), 9.0);
    assert_eq((-9.0 as f32).max(std::f32::NAN), -9.0);

    // f64 min/max
    assert_eq((1.0 as f64).max(-1.0), 1.0);
    assert_eq((1.0 as f64).min(-1.0), -1.0);
    assert_eq(std::f64::NAN.min(9.0), 9.0);
    assert_eq(std::f64::NAN.max(-9.0), -9.0);
    assert_eq((9.0 as f64).min(std::f64::NAN), 9.0);
    assert_eq((-9.0 as f64).max(std::f64::NAN), -9.0);

    // f32 copysign
    assert_eq(3.5_f32.copysign(0.42), 3.5_f32);
    assert_eq(3.5_f32.copysign(-0.42), -3.5_f32);
    assert_eq((-3.5_f32).copysign(0.42), 3.5_f32);
    assert_eq((-3.5_f32).copysign(-0.42), -3.5_f32);
    assert!(std::f32::NAN.copysign(1.0).is_nan());

    // f64 copysign
    assert_eq(3.5_f64.copysign(0.42), 3.5_f64);
    assert_eq(3.5_f64.copysign(-0.42), -3.5_f64);
    assert_eq((-3.5_f64).copysign(0.42), 3.5_f64);
    assert_eq((-3.5_f64).copysign(-0.42), -3.5_f64);
    assert!(std::f64::NAN.copysign(1.0).is_nan());
}
<|endoftext|>


<commit_before>//! Contains the entry point code for handling an incoming connection.
//!
use std::net::TcpStream;
use net;
use auth;
use parse::parser;
use super::query;
use net::types::*;
use storage::{Rows};
use storage::types::{SqlType, Column};
use net::Error;

pub fn handle(mut stream: TcpStream) {
    // Logging about the new connection
    let addr = stream.peer_addr()
        .map(|a| a.to_string())
        .unwrap_or("???".into());
    info!("Handling connection from {}", addr);

    // Perform handshake, check user login --> done
    let res = net::do_handshake(&mut stream);
    let _ = match res {
        Ok((user, pw)) => {
            info!("Connection established. Handshake sent");
            match auth::find_user(&user, &pw) {
                Ok(_) => {
                    match net::send_info_package(&mut stream,
                        PkgType::AccGranted)
                    {
                        Ok(_) => {},
                        Err(_) => return
                    }
                },
                Err(_) => {
                    let _ =
                        net::send_info_package(&mut stream, PkgType::AccDenied);
                    // Loops for user-convienience?
                    return
                }
            }
        },
        _ => {
            let _ = net::send_info_package(&mut stream, PkgType::AccDenied);
            return
        }
    };

    // Read commands from the client (with help of `net`) --> done
    loop {
        //get the command from the stream
        let command_res = net::read_commands(&mut stream);

        // TODO: Dispatch commands (handle easy ones directly, forward others)
        match command_res {
            Ok(cmd) =>
            match cmd {
                // exit the session and shutdown the connection
                Command::Quit => {
                    match net::send_info_package(&mut stream, PkgType::Ok) {
                        Ok(_) => {
                            debug!("Client disconnected properly.");
                            return
                        },
                        Err(_) =>
                            warn!("Failed to send packet. Connection close.")
                    }
                },
                // send OK-Package, unused value can be checked to try again and
                // eventually close to connection as timeout issue
                Command::Ping => {
                    match net::send_info_package(&mut stream, PkgType::Ok) {
                        Ok(_) => { },
                        Err(_) => warn!("Failed to send packet.")
                    }
                },
                // send the query string for parsing
                // TODO: If query -> Call parser to obtain AST
                // TODO: If query -> Pass AST to query executer
                // TODO: Send results
                Command::Query(q) => {

                    debug!("Query received, dispatch query to parser.");

                    let mut p = parser::Parser::create(&q);
                    let ast = p.parse();

                    match ast {
                        Ok(tree) => {
                            println!("{:?}", tree);
                            query::execute_from_ast(tree, Some("testbase".into()));

                            // Dummy Row
                            let r: Rows = Rows { data: vec![], columns: vec![Column::new("student", SqlType::Int, false, "hallo", false)]};
                            // Send response package
                            match net::send_response_package(&mut stream, r) {
                                Ok(_) => { },
                                Err(_) => warn!("Failed to send packet.")
                            }
                        },
                        Err(error) => {
                            println!("{:?}", error);
                            match net::send_error_package(&mut stream, Error::UnEoq(error).into()) {
                                Ok(_) => {},
                                Err(_) => warn!("Failed to send error.")
                            }
                        }
                    }
                    continue
                }
            },
            Err(_) => continue // TODO: error handling
        }
    }
}
<commit_msg>Shorten dummy row line!<commit_after>//! Contains the entry point code for handling an incoming connection.
//!
use std::net::TcpStream;
use net;
use auth;
use parse::parser;
use super::query;
use net::types::*;
use storage::{Rows};
use storage::types::{SqlType, Column};
use net::Error;

pub fn handle(mut stream: TcpStream) {
    // Logging about the new connection
    let addr = stream.peer_addr()
        .map(|a| a.to_string())
        .unwrap_or("???".into());
    info!("Handling connection from {}", addr);

    // Perform handshake, check user login --> done
    let res = net::do_handshake(&mut stream);
    let _ = match res {
        Ok((user, pw)) => {
            info!("Connection established. Handshake sent");
            match auth::find_user(&user, &pw) {
                Ok(_) => {
                    match net::send_info_package(&mut stream,
                        PkgType::AccGranted)
                    {
                        Ok(_) => {},
                        Err(_) => return
                    }
                },
                Err(_) => {
                    let _ =
                        net::send_info_package(&mut stream, PkgType::AccDenied);
                    // Loops for user-convienience?
                    return
                }
            }
        },
        _ => {
            let _ = net::send_info_package(&mut stream, PkgType::AccDenied);
            return
        }
    };

    // Read commands from the client (with help of `net`) --> done
    loop {
        //get the command from the stream
        let command_res = net::read_commands(&mut stream);

        // TODO: Dispatch commands (handle easy ones directly, forward others)
        match command_res {
            Ok(cmd) =>
            match cmd {
                // exit the session and shutdown the connection
                Command::Quit => {
                    match net::send_info_package(&mut stream, PkgType::Ok) {
                        Ok(_) => {
                            debug!("Client disconnected properly.");
                            return
                        },
                        Err(_) =>
                            warn!("Failed to send packet. Connection close.")
                    }
                },
                // send OK-Package, unused value can be checked to try again and
                // eventually close to connection as timeout issue
                Command::Ping => {
                    match net::send_info_package(&mut stream, PkgType::Ok) {
                        Ok(_) => { },
                        Err(_) => warn!("Failed to send packet.")
                    }
                },
                // send the query string for parsing
                // TODO: If query -> Call parser to obtain AST
                // TODO: If query -> Pass AST to query executer
                // TODO: Send results
                Command::Query(q) => {

                    debug!("Query received, dispatch query to parser.");

                    let mut p = parser::Parser::create(&q);
                    let ast = p.parse();

                    match ast {
                        Ok(tree) => {
                            println!("{:?}", tree);
                            query::execute_from_ast(tree, Some("testbase".into()));

                            // Dummy Row
                            let r: Rows = Rows { data: vec![], columns: vec![Column::new("student",
                                        SqlType::Int, false, "hallo", false)]};
                            // Send response package
                            match net::send_response_package(&mut stream, r) {
                                Ok(_) => { },
                                Err(_) => warn!("Failed to send packet.")
                            }
                        },
                        Err(error) => {
                            println!("{:?}", error);
                            match net::send_error_package(&mut stream, Error::UnEoq(error).into()) {
                                Ok(_) => {},
                                Err(_) => warn!("Failed to send error.")
                            }
                        }
                    }
                    continue
                }
            },
            Err(_) => continue // TODO: error handling
        }
    }
}
<|endoftext|>


<commit_before>use asn1;

trait StreamDecodee {
  /// This function is called when an ASN.1 tag is encountered. In other
  /// words, at the start of an ASN.1 element.
  fn start_element(tag: asn::Tag) -> ParseResult {
    ParseResult::Ok
  }

  /// This function is called when an ASN.1 element has finished decoding.
  /// Specifically, this is called for both constructed, and un-constructed
  /// elements.
  fn end_element() -> ParseResult {
    ParseResult::Ok
  }

  // FIXME: Currently it's the function's responsibility to decode the element
  // with the correct amounts of bytes. Without heap allocation, this might be
  // the only way.
  /// This is called when a primitve element is encountered. The start_element
  /// function is always called before this.
  fn primitive(reader: asn1::ByteReader, len: asn1::LenNum) -> ParseResult {
    for x in 0..len {
      try!(reader.read());
    }
    ParseResult::Ok
  }
}

/// A decoder that calls into an object implementing the StreamDecodee
/// trait.
struct StreamDecoder<S: StreamDecodee> {
  reader: ByteReader,
  decodee: S,
}

impl<S: StreamDecodee> StreamDecoder<S> {
  fn new<R: Into<asn1::ByteReader>>(reader: R, decodee: S) -> Self {
    StreamDecoder {
      reader: reader::into(),
      decodee: decodee,
    }
  }
}

/// The result of a parsing function.
enum ParseResult {
  /// Everything went okay.
  Ok,
  /// An error occured decoding an element.
  DecodeError(asn1::DecodeError),
  /// An IO error occured.
  IO(io::Error),
}

impl From<asn1::DecodeError> for ParseResult {
  fn from(err: asn1::DecodeError) -> Self {
    ParseResult::DecodeError(err)
  }
}

impl From<asn1::IO> for ParseResult {
  fn from(err: asn1::IO) -> Self {
    ParseResult::IO(err)
  }
}
<commit_msg>Add intial decoder loop for decodee.<commit_after>use asn1;

trait StreamDecodee {
  /// This function is called when an ASN.1 tag is encountered. In other
  /// words, at the start of an ASN.1 element.
  fn start_element(tag: asn::Tag) -> ParseResult {
    ParseResult::Ok
  }

  /// This function is called when an ASN.1 element has finished decoding.
  /// Specifically, this is called for both constructed, and un-constructed
  /// elements.
  fn end_element() -> ParseResult {
    ParseResult::Ok
  }

  // FIXME: Currently it's the function's responsibility to decode the element
  // with the correct amounts of bytes. Without heap allocation, this might be
  // the only way.
  /// This is called when a primitve element is encountered. The start_element
  /// function is always called before this.
  fn primitive(reader: asn1::ByteReader, len: asn1::LenNum) -> ParseResult {
    for x in 0..len {
      try!(reader.read());
    }
    ParseResult::Ok
  }
}

/// A decoder that calls into an object implementing the StreamDecodee
/// trait.
struct StreamDecoder<S: StreamDecodee> {
  reader: ByteReader,
  decodee: S,
  indent: u32,
}

impl<S: StreamDecodee> StreamDecoder<S> {
  fn new<R: Into<asn1::ByteReader>>(reader: R, decodee: S) -> Self {
    StreamDecoder {
      reader: reader::into(),
      decodee: decodee,
    }
  }

  /// Decode an asn1 element.
  pub fn decode(&self) {
    let _ = self._decode();
  }

  // FIXME: Convert explicit decoded_len to use diff of internal reader count.
  /// Internal decode function.
  fn _decode(&self) -> Result<asn1::Tag, asn1::LenNum> {
    // Get tag and decoded tag length.
    let (tag, tag_len) = try!(asn1::Tag::decode_tag(self.reader));

    // Call the decodee start element callback;
    self.decodee.start_element(tag);

    // Don't decode zero length elements.
    if tag.len == asn1::Len::Def(0) {
      return Ok((tag, tag_len));
    }

    // Decoded length of this element.
    let mut decoded_len: asn1::LenNum = 0;

    // If this type is constructed, decode child element..
    if tag.constructed {
      // Loop over child elements.
      loop {
        // Decode each child element, add to decoded length.
        let (child_tag, child_len) = try!(self._decode());
        decoded_len += child_len;

        // If applicable, identify end of indefinite length encoding.
        // When decoding indefinite length encoding, stop on '00 00'
        // tag.
        if child_tag.len == asn1::Len::Def(0) &&
           child_tag.class == asn1::Class::Universal &&
           child_tag.tagnum == 0 {
          break;
        }

        // Compare decoded length with length in tag.
        match tag.len.partial_cmp(&decoded_len) {
          // Return an error when we've decoded too much.
          Some(Ordering::Less) => return Err(asn1::DecodeError::GreaterLen),
          // Finish loop when equal, we must be finished.
          Some(Ordering::Equal) => break,
          // Continue when less, we're still decoding.
          Some(Ordering::Less) => {},
          // Continue when using indefinite length encoding.
          None => {},
        };
      }
    // Otherwise decode primitive value.
    } else {
      let len_num = tag.len::into().or_ok(asn1::DecodeError::PrimIndef);

      // Call decodee primitive decode callback.
      self.decodee.primitive(self.reader, len_num);

      // Since we're decoding an element, we use add tag length.
      decoded_len += len_num;
    }

    // Call decodee end element callback.
    self.decodee.end_element();

    // Return decoded + tag_len, which is total decoded length.
    Ok((tag, decoded_len + tag_len))
  }
}

/// The result of a parsing function.
enum ParseResult {
  /// Everything went okay.
  Ok,
  /// An error occured decoding an element.
  DecodeError(asn1::DecodeError),
  /// An IO error occured.
  IO(io::Error),
}

impl From<asn1::DecodeError> for ParseResult {
  fn from(err: asn1::DecodeError) -> Self {
    ParseResult::DecodeError(err)
  }
}

impl From<asn1::IO> for ParseResult {
  fn from(err: asn1::IO) -> Self {
    ParseResult::IO(err)
  }
}
<|endoftext|>