<commit_before>// Copyright 2012 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 llvm;
use llvm::{SetUnnamedAddr};
use llvm::{ValueRef, True};
use rustc::hir::def_id::DefId;
use rustc::hir::map as hir_map;
use rustc::middle::const_val::ConstEvalErr;
use debuginfo;
use base;
use trans_item::{TransItem, TransItemExt};
use common::{self, CrateContext, val_ty};
use declare;
use monomorphize::Instance;
use type_::Type;
use type_of::LayoutLlvmExt;
use rustc::ty;
use rustc::ty::layout::{Align, LayoutOf};

use rustc::hir;

use std::ffi::{CStr, CString};
use syntax::ast;
use syntax::attr;

pub fn ptrcast(val: ValueRef, ty: Type) -> ValueRef {
    unsafe {
        llvm::LLVMConstPointerCast(val, ty.to_ref())
    }
}

pub fn bitcast(val: ValueRef, ty: Type) -> ValueRef {
    unsafe {
        llvm::LLVMConstBitCast(val, ty.to_ref())
    }
}

fn set_global_alignment(ccx: &CrateContext,
                        gv: ValueRef,
                        mut align: Align) {
    // The target may require greater alignment for globals than the type does.
    // Note: GCC and Clang also allow `__attribute__((aligned))` on variables,
    // which can force it to be smaller.  Rust doesn't support this yet.
    if let Some(min) = ccx.sess().target.target.options.min_global_align {
        match ty::layout::Align::from_bits(min, min) {
            Ok(min) => align = align.max(min),
            Err(err) => {
                ccx.sess().err(&format!("invalid minimum global alignment: {}", err));
            }
        }
    }
    unsafe {
        llvm::LLVMSetAlignment(gv, align.abi() as u32);
    }
}

pub fn addr_of_mut(ccx: &CrateContext,
                   cv: ValueRef,
                   align: Align,
                   kind: &str)
                    -> ValueRef {
    unsafe {
        let name = ccx.generate_local_symbol_name(kind);
        let gv = declare::define_global(ccx, &name[..], val_ty(cv)).unwrap_or_else(||{
            bug!("symbol `{}` is already defined", name);
        });
        llvm::LLVMSetInitializer(gv, cv);
        set_global_alignment(ccx, gv, align);
        llvm::LLVMRustSetLinkage(gv, llvm::Linkage::InternalLinkage);
        SetUnnamedAddr(gv, true);
        gv
    }
}

pub fn addr_of(ccx: &CrateContext,
               cv: ValueRef,
               align: Align,
               kind: &str)
               -> ValueRef {
    if let Some(&gv) = ccx.const_globals().borrow().get(&cv) {
        unsafe {
            // Upgrade the alignment in cases where the same constant is used with different
            // alignment requirements
            let llalign = align.abi() as u32;
            if llalign > llvm::LLVMGetAlignment(gv) {
                llvm::LLVMSetAlignment(gv, llalign);
            }
        }
        return gv;
    }
    let gv = addr_of_mut(ccx, cv, align, kind);
    unsafe {
        llvm::LLVMSetGlobalConstant(gv, True);
    }
    ccx.const_globals().borrow_mut().insert(cv, gv);
    gv
}

pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
    let instance = Instance::mono(ccx.tcx(), def_id);
    if let Some(&g) = ccx.instances().borrow().get(&instance) {
        return g;
    }

    let ty = common::instance_ty(ccx.tcx(), &instance);
    let g = if let Some(id) = ccx.tcx().hir.as_local_node_id(def_id) {

        let llty = ccx.layout_of(ty).llvm_type(ccx);
        let (g, attrs) = match ccx.tcx().hir.get(id) {
            hir_map::NodeItem(&hir::Item {
                ref attrs, span, node: hir::ItemStatic(..), ..
            }) => {
                let sym = TransItem::Static(id).symbol_name(ccx.tcx());

                let defined_in_current_codegen_unit = ccx.codegen_unit()
                                                         .items()
                                                         .contains_key(&TransItem::Static(id));
                assert!(!defined_in_current_codegen_unit);

                if declare::get_declared_value(ccx, &sym[..]).is_some() {
                    span_bug!(span, "trans: Conflicting symbol names for static?");
                }

                let g = declare::define_global(ccx, &sym[..], llty).unwrap();

                if !ccx.tcx().is_exported_symbol(def_id) {
                    unsafe {
                        llvm::LLVMRustSetVisibility(g, llvm::Visibility::Hidden);
                    }
                }

                (g, attrs)
            }

            hir_map::NodeForeignItem(&hir::ForeignItem {
                ref attrs, span, node: hir::ForeignItemStatic(..), ..
            }) => {
                let sym = ccx.tcx().symbol_name(instance);
                let g = if let Some(name) =
                        attr::first_attr_value_str_by_name(&attrs, "linkage") {
                    // If this is a static with a linkage specified, then we need to handle
                    // it a little specially. The typesystem prevents things like &T and
                    // extern "C" fn() from being non-null, so we can't just declare a
                    // static and call it a day. Some linkages (like weak) will make it such
                    // that the static actually has a null value.
                    let linkage = match base::linkage_by_name(&name.as_str()) {
                        Some(linkage) => linkage,
                        None => {
                            ccx.sess().span_fatal(span, "invalid linkage specified");
                        }
                    };
                    let llty2 = match ty.sty {
                        ty::TyRawPtr(ref mt) => ccx.layout_of(mt.ty).llvm_type(ccx),
                        _ => {
                            ccx.sess().span_fatal(span, "must have type `*const T` or `*mut T`");
                        }
                    };
                    unsafe {
                        // Declare a symbol `foo` with the desired linkage.
                        let g1 = declare::declare_global(ccx, &sym, llty2);
                        llvm::LLVMRustSetLinkage(g1, base::linkage_to_llvm(linkage));

                        // Declare an internal global `extern_with_linkage_foo` which
                        // is initialized with the address of `foo`.  If `foo` is
                        // discarded during linking (for example, if `foo` has weak
                        // linkage and there are no definitions), then
                        // `extern_with_linkage_foo` will instead be initialized to
                        // zero.
                        let mut real_name = "_rust_extern_with_linkage_".to_string();
                        real_name.push_str(&sym);
                        let g2 = declare::define_global(ccx, &real_name, llty).unwrap_or_else(||{
                            ccx.sess().span_fatal(span,
                                &format!("symbol `{}` is already defined", &sym))
                        });
                        llvm::LLVMRustSetLinkage(g2, llvm::Linkage::InternalLinkage);
                        llvm::LLVMSetInitializer(g2, g1);
                        g2
                    }
                } else {
                    // Generate an external declaration.
                    declare::declare_global(ccx, &sym, llty)
                };

                (g, attrs)
            }

            item => bug!("get_static: expected static, found {:?}", item)
        };

        for attr in attrs {
            if attr.check_name("thread_local") {
                llvm::set_thread_local_mode(g, ccx.tls_model());
            }
        }

        g
    } else {
        let sym = ccx.tcx().symbol_name(instance);

        // FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow?
        // FIXME(nagisa): investigate whether it can be changed into define_global
        let g = declare::declare_global(ccx, &sym, ccx.layout_of(ty).llvm_type(ccx));
        // Thread-local statics in some other crate need to *always* be linked
        // against in a thread-local fashion, so we need to be sure to apply the
        // thread-local attribute locally if it was present remotely. If we
        // don't do this then linker errors can be generated where the linker
        // complains that one object files has a thread local version of the
        // symbol and another one doesn't.
        for attr in ccx.tcx().get_attrs(def_id).iter() {
            if attr.check_name("thread_local") {
                llvm::set_thread_local_mode(g, ccx.tls_model());
            }
        }
        if ccx.use_dll_storage_attrs() && !ccx.tcx().is_foreign_item(def_id) {
            // This item is external but not foreign, i.e. it originates from an external Rust
            // crate. Since we don't know whether this crate will be linked dynamically or
            // statically in the final application, we always mark such symbols as 'dllimport'.
            // If final linkage happens to be static, we rely on compiler-emitted __imp_ stubs to
            // make things work.
            unsafe {
                llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport);
            }
        }
        g
    };

    if ccx.use_dll_storage_attrs() && ccx.tcx().is_dllimport_foreign_item(def_id) {
        // For foreign (native) libs we know the exact storage type to use.
        unsafe {
            llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport);
        }
    }

    ccx.instances().borrow_mut().insert(instance, g);
    ccx.statics().borrow_mut().insert(g, def_id);
    g
}

pub fn trans_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                              m: hir::Mutability,
                              id: ast::NodeId,
                              attrs: &[ast::Attribute])
                              -> Result<ValueRef, ConstEvalErr<'tcx>> {
    unsafe {
        let def_id = ccx.tcx().hir.local_def_id(id);
        let g = get_static(ccx, def_id);

        let v = ::mir::trans_static_initializer(ccx, def_id)?;

        // boolean SSA values are i1, but they have to be stored in i8 slots,
        // otherwise some LLVM optimization passes don't work as expected
        let mut val_llty = val_ty(v);
        let v = if val_llty == Type::i1(ccx) {
            val_llty = Type::i8(ccx);
            llvm::LLVMConstZExt(v, val_llty.to_ref())
        } else {
            v
        };

        let instance = Instance::mono(ccx.tcx(), def_id);
        let ty = common::instance_ty(ccx.tcx(), &instance);
        let llty = ccx.layout_of(ty).llvm_type(ccx);
        let g = if val_llty == llty {
            g
        } else {
            // If we created the global with the wrong type,
            // correct the type.
            let empty_string = CString::new("").unwrap();
            let name_str_ref = CStr::from_ptr(llvm::LLVMGetValueName(g));
            let name_string = CString::new(name_str_ref.to_bytes()).unwrap();
            llvm::LLVMSetValueName(g, empty_string.as_ptr());

            let linkage = llvm::LLVMRustGetLinkage(g);
            let visibility = llvm::LLVMRustGetVisibility(g);

            let new_g = llvm::LLVMRustGetOrInsertGlobal(
                ccx.llmod(), name_string.as_ptr(), val_llty.to_ref());

            llvm::LLVMRustSetLinkage(new_g, linkage);
            llvm::LLVMRustSetVisibility(new_g, visibility);

            // To avoid breaking any invariants, we leave around the old
            // global for the moment; we'll replace all references to it
            // with the new global later. (See base::trans_crate.)
            ccx.statics_to_rauw().borrow_mut().push((g, new_g));
            new_g
        };
        set_global_alignment(ccx, g, ccx.align_of(ty));
        llvm::LLVMSetInitializer(g, v);

        // As an optimization, all shared statics which do not have interior
        // mutability are placed into read-only memory.
        if m != hir::MutMutable {
            if ccx.shared().type_is_freeze(ty) {
                llvm::LLVMSetGlobalConstant(g, llvm::True);
            }
        }

        debuginfo::create_global_var_metadata(ccx, id, g);

        if attr::contains_name(attrs, "thread_local") {
            llvm::set_thread_local_mode(g, ccx.tls_model());
        }

        base::set_link_section(ccx, g, attrs);

        if attr::contains_name(attrs, "used") {
            // This static will be stored in the llvm.used variable which is an array of i8*
            let cast = llvm::LLVMConstPointerCast(g, Type::i8p(ccx).to_ref());
            ccx.used_statics().borrow_mut().push(cast);
        }

        Ok(g)
    }
}
<commit_msg>Auto merge of #46563 - michaelwoerister:make-anon-globals-private, r=alexcrichton<commit_after>// Copyright 2012 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 llvm;
use llvm::{SetUnnamedAddr};
use llvm::{ValueRef, True};
use rustc::hir::def_id::DefId;
use rustc::hir::map as hir_map;
use rustc::middle::const_val::ConstEvalErr;
use debuginfo;
use base;
use trans_item::{TransItem, TransItemExt};
use common::{self, CrateContext, val_ty};
use declare;
use monomorphize::Instance;
use type_::Type;
use type_of::LayoutLlvmExt;
use rustc::ty;
use rustc::ty::layout::{Align, LayoutOf};

use rustc::hir;

use std::ffi::{CStr, CString};
use syntax::ast;
use syntax::attr;

pub fn ptrcast(val: ValueRef, ty: Type) -> ValueRef {
    unsafe {
        llvm::LLVMConstPointerCast(val, ty.to_ref())
    }
}

pub fn bitcast(val: ValueRef, ty: Type) -> ValueRef {
    unsafe {
        llvm::LLVMConstBitCast(val, ty.to_ref())
    }
}

fn set_global_alignment(ccx: &CrateContext,
                        gv: ValueRef,
                        mut align: Align) {
    // The target may require greater alignment for globals than the type does.
    // Note: GCC and Clang also allow `__attribute__((aligned))` on variables,
    // which can force it to be smaller.  Rust doesn't support this yet.
    if let Some(min) = ccx.sess().target.target.options.min_global_align {
        match ty::layout::Align::from_bits(min, min) {
            Ok(min) => align = align.max(min),
            Err(err) => {
                ccx.sess().err(&format!("invalid minimum global alignment: {}", err));
            }
        }
    }
    unsafe {
        llvm::LLVMSetAlignment(gv, align.abi() as u32);
    }
}

pub fn addr_of_mut(ccx: &CrateContext,
                   cv: ValueRef,
                   align: Align,
                   kind: &str)
                    -> ValueRef {
    unsafe {
        let name = ccx.generate_local_symbol_name(kind);
        let gv = declare::define_global(ccx, &name[..], val_ty(cv)).unwrap_or_else(||{
            bug!("symbol `{}` is already defined", name);
        });
        llvm::LLVMSetInitializer(gv, cv);
        set_global_alignment(ccx, gv, align);
        llvm::LLVMRustSetLinkage(gv, llvm::Linkage::PrivateLinkage);
        SetUnnamedAddr(gv, true);
        gv
    }
}

pub fn addr_of(ccx: &CrateContext,
               cv: ValueRef,
               align: Align,
               kind: &str)
               -> ValueRef {
    if let Some(&gv) = ccx.const_globals().borrow().get(&cv) {
        unsafe {
            // Upgrade the alignment in cases where the same constant is used with different
            // alignment requirements
            let llalign = align.abi() as u32;
            if llalign > llvm::LLVMGetAlignment(gv) {
                llvm::LLVMSetAlignment(gv, llalign);
            }
        }
        return gv;
    }
    let gv = addr_of_mut(ccx, cv, align, kind);
    unsafe {
        llvm::LLVMSetGlobalConstant(gv, True);
    }
    ccx.const_globals().borrow_mut().insert(cv, gv);
    gv
}

pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
    let instance = Instance::mono(ccx.tcx(), def_id);
    if let Some(&g) = ccx.instances().borrow().get(&instance) {
        return g;
    }

    let ty = common::instance_ty(ccx.tcx(), &instance);
    let g = if let Some(id) = ccx.tcx().hir.as_local_node_id(def_id) {

        let llty = ccx.layout_of(ty).llvm_type(ccx);
        let (g, attrs) = match ccx.tcx().hir.get(id) {
            hir_map::NodeItem(&hir::Item {
                ref attrs, span, node: hir::ItemStatic(..), ..
            }) => {
                let sym = TransItem::Static(id).symbol_name(ccx.tcx());

                let defined_in_current_codegen_unit = ccx.codegen_unit()
                                                         .items()
                                                         .contains_key(&TransItem::Static(id));
                assert!(!defined_in_current_codegen_unit);

                if declare::get_declared_value(ccx, &sym[..]).is_some() {
                    span_bug!(span, "trans: Conflicting symbol names for static?");
                }

                let g = declare::define_global(ccx, &sym[..], llty).unwrap();

                if !ccx.tcx().is_exported_symbol(def_id) {
                    unsafe {
                        llvm::LLVMRustSetVisibility(g, llvm::Visibility::Hidden);
                    }
                }

                (g, attrs)
            }

            hir_map::NodeForeignItem(&hir::ForeignItem {
                ref attrs, span, node: hir::ForeignItemStatic(..), ..
            }) => {
                let sym = ccx.tcx().symbol_name(instance);
                let g = if let Some(name) =
                        attr::first_attr_value_str_by_name(&attrs, "linkage") {
                    // If this is a static with a linkage specified, then we need to handle
                    // it a little specially. The typesystem prevents things like &T and
                    // extern "C" fn() from being non-null, so we can't just declare a
                    // static and call it a day. Some linkages (like weak) will make it such
                    // that the static actually has a null value.
                    let linkage = match base::linkage_by_name(&name.as_str()) {
                        Some(linkage) => linkage,
                        None => {
                            ccx.sess().span_fatal(span, "invalid linkage specified");
                        }
                    };
                    let llty2 = match ty.sty {
                        ty::TyRawPtr(ref mt) => ccx.layout_of(mt.ty).llvm_type(ccx),
                        _ => {
                            ccx.sess().span_fatal(span, "must have type `*const T` or `*mut T`");
                        }
                    };
                    unsafe {
                        // Declare a symbol `foo` with the desired linkage.
                        let g1 = declare::declare_global(ccx, &sym, llty2);
                        llvm::LLVMRustSetLinkage(g1, base::linkage_to_llvm(linkage));

                        // Declare an internal global `extern_with_linkage_foo` which
                        // is initialized with the address of `foo`.  If `foo` is
                        // discarded during linking (for example, if `foo` has weak
                        // linkage and there are no definitions), then
                        // `extern_with_linkage_foo` will instead be initialized to
                        // zero.
                        let mut real_name = "_rust_extern_with_linkage_".to_string();
                        real_name.push_str(&sym);
                        let g2 = declare::define_global(ccx, &real_name, llty).unwrap_or_else(||{
                            ccx.sess().span_fatal(span,
                                &format!("symbol `{}` is already defined", &sym))
                        });
                        llvm::LLVMRustSetLinkage(g2, llvm::Linkage::InternalLinkage);
                        llvm::LLVMSetInitializer(g2, g1);
                        g2
                    }
                } else {
                    // Generate an external declaration.
                    declare::declare_global(ccx, &sym, llty)
                };

                (g, attrs)
            }

            item => bug!("get_static: expected static, found {:?}", item)
        };

        for attr in attrs {
            if attr.check_name("thread_local") {
                llvm::set_thread_local_mode(g, ccx.tls_model());
            }
        }

        g
    } else {
        let sym = ccx.tcx().symbol_name(instance);

        // FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow?
        // FIXME(nagisa): investigate whether it can be changed into define_global
        let g = declare::declare_global(ccx, &sym, ccx.layout_of(ty).llvm_type(ccx));
        // Thread-local statics in some other crate need to *always* be linked
        // against in a thread-local fashion, so we need to be sure to apply the
        // thread-local attribute locally if it was present remotely. If we
        // don't do this then linker errors can be generated where the linker
        // complains that one object files has a thread local version of the
        // symbol and another one doesn't.
        for attr in ccx.tcx().get_attrs(def_id).iter() {
            if attr.check_name("thread_local") {
                llvm::set_thread_local_mode(g, ccx.tls_model());
            }
        }
        if ccx.use_dll_storage_attrs() && !ccx.tcx().is_foreign_item(def_id) {
            // This item is external but not foreign, i.e. it originates from an external Rust
            // crate. Since we don't know whether this crate will be linked dynamically or
            // statically in the final application, we always mark such symbols as 'dllimport'.
            // If final linkage happens to be static, we rely on compiler-emitted __imp_ stubs to
            // make things work.
            unsafe {
                llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport);
            }
        }
        g
    };

    if ccx.use_dll_storage_attrs() && ccx.tcx().is_dllimport_foreign_item(def_id) {
        // For foreign (native) libs we know the exact storage type to use.
        unsafe {
            llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport);
        }
    }

    ccx.instances().borrow_mut().insert(instance, g);
    ccx.statics().borrow_mut().insert(g, def_id);
    g
}

pub fn trans_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                              m: hir::Mutability,
                              id: ast::NodeId,
                              attrs: &[ast::Attribute])
                              -> Result<ValueRef, ConstEvalErr<'tcx>> {
    unsafe {
        let def_id = ccx.tcx().hir.local_def_id(id);
        let g = get_static(ccx, def_id);

        let v = ::mir::trans_static_initializer(ccx, def_id)?;

        // boolean SSA values are i1, but they have to be stored in i8 slots,
        // otherwise some LLVM optimization passes don't work as expected
        let mut val_llty = val_ty(v);
        let v = if val_llty == Type::i1(ccx) {
            val_llty = Type::i8(ccx);
            llvm::LLVMConstZExt(v, val_llty.to_ref())
        } else {
            v
        };

        let instance = Instance::mono(ccx.tcx(), def_id);
        let ty = common::instance_ty(ccx.tcx(), &instance);
        let llty = ccx.layout_of(ty).llvm_type(ccx);
        let g = if val_llty == llty {
            g
        } else {
            // If we created the global with the wrong type,
            // correct the type.
            let empty_string = CString::new("").unwrap();
            let name_str_ref = CStr::from_ptr(llvm::LLVMGetValueName(g));
            let name_string = CString::new(name_str_ref.to_bytes()).unwrap();
            llvm::LLVMSetValueName(g, empty_string.as_ptr());

            let linkage = llvm::LLVMRustGetLinkage(g);
            let visibility = llvm::LLVMRustGetVisibility(g);

            let new_g = llvm::LLVMRustGetOrInsertGlobal(
                ccx.llmod(), name_string.as_ptr(), val_llty.to_ref());

            llvm::LLVMRustSetLinkage(new_g, linkage);
            llvm::LLVMRustSetVisibility(new_g, visibility);

            // To avoid breaking any invariants, we leave around the old
            // global for the moment; we'll replace all references to it
            // with the new global later. (See base::trans_crate.)
            ccx.statics_to_rauw().borrow_mut().push((g, new_g));
            new_g
        };
        set_global_alignment(ccx, g, ccx.align_of(ty));
        llvm::LLVMSetInitializer(g, v);

        // As an optimization, all shared statics which do not have interior
        // mutability are placed into read-only memory.
        if m != hir::MutMutable {
            if ccx.shared().type_is_freeze(ty) {
                llvm::LLVMSetGlobalConstant(g, llvm::True);
            }
        }

        debuginfo::create_global_var_metadata(ccx, id, g);

        if attr::contains_name(attrs, "thread_local") {
            llvm::set_thread_local_mode(g, ccx.tls_model());
        }

        base::set_link_section(ccx, g, attrs);

        if attr::contains_name(attrs, "used") {
            // This static will be stored in the llvm.used variable which is an array of i8*
            let cast = llvm::LLVMConstPointerCast(g, Type::i8p(ccx).to_ref());
            ccx.used_statics().borrow_mut().push(cast);
        }

        Ok(g)
    }
}
<|endoftext|>


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

use std;
use gl;
use gl::types::{
  GLfloat,
  GLint,
  GLuint,
  GLchar,
  GLenum,
};
use cgmath::matrix::{
  Matrix,
  Mat4,
  Mat3,
  ToMat4,
};
use cgmath::vector::{
  Vec3,
  Vec2,
};
use cgmath::angle;
use stb_image::image;
use misc::{
  c_str,
  deg_to_rad,
};
use color::Color3;

pub fn compile_shader(src: &str, shader_type: GLenum) -> GLuint {
  let shader = gl::CreateShader(shader_type);
  unsafe {
    gl::ShaderSource(shader, 1, &c_str(src), std::ptr::null());
    gl::CompileShader(shader);
    let mut status = gl::FALSE as GLint;
    gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);
    if status != (gl::TRUE as GLint) {
      let mut len = 0;
      gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
      // subtract 1 to skip the trailing null character
      let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
      gl::GetShaderInfoLog(shader, len, std::ptr::mut_null(),
        buf.as_mut_ptr() as *mut GLchar
      );
      fail!("compile_shader(): " + std::str::raw::from_utf8(buf));
    }
  }
  shader
}

pub fn link_program(vertex_shader: GLuint, fragment_shader: GLuint) -> GLuint {
  let program = gl::CreateProgram();
  gl::AttachShader(program, vertex_shader);
  gl::AttachShader(program, fragment_shader);
  gl::LinkProgram(program);
  unsafe {
    let mut status = gl::FALSE as GLint;
    gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);
    if status != (gl::TRUE as GLint) {
      let mut len = 0;
      gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
      // subtract 1 to skip the trailing null character
      let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
      gl::GetProgramInfoLog(program, len, std::ptr::mut_null(),
        buf.as_mut_ptr() as *mut GLchar
      );
      fail!("link_program(): " + std::str::raw::from_utf8(buf));
    }
  }
  program
}

pub fn compile_program(
  vertex_shader_src: &str,
  frag_shader_src: &str,
) -> GLuint {
  let vertex_shader = compile_shader(
    vertex_shader_src, gl::VERTEX_SHADER);
  let fragment_shader = compile_shader(
    frag_shader_src, gl::FRAGMENT_SHADER);
  let program = link_program(vertex_shader, fragment_shader);
  // mark shaders for deletion after program deletion
  gl::DeleteShader(fragment_shader);
  gl::DeleteShader(vertex_shader);
  program
}

pub fn get_attr(program_id: GLuint, name: &str) -> GLuint {
  unsafe {
    gl::GetAttribLocation(program_id, c_str(name)) as GLuint
  }
}

pub fn get_uniform(program: GLuint, name: &str) -> GLint {
  unsafe {
    gl::GetUniformLocation(program, c_str(name))
  }
}

pub fn draw_mesh(faces_count: int) {
  let starting_index = 0;
  let vertices_count = faces_count as i32 * 3;
  gl::DrawArrays(gl::TRIANGLES, starting_index, vertices_count);
}

pub fn uniform_mat4f(mat_id: GLint, mat: &Mat4<GLfloat>) {
  unsafe {
    gl::UniformMatrix4fv(mat_id, 1, gl::FALSE, mat.cr(0, 0));
  }
}

pub fn tr(m: Mat4<f32>, v: Vec3<f32>) -> Mat4<f32> {
  let mut t = Mat4::<f32>::identity();
  *t.mut_cr(3, 0) = v.x;
  *t.mut_cr(3, 1) = v.y;
  *t.mut_cr(3, 2) = v.z;
  m.mul_m(&t)
}

pub fn rot_x(m: Mat4<f32>, angle: f32) -> Mat4<f32> {
  let rad = angle::rad(deg_to_rad(angle));
  let r = Mat3::from_angle_x(rad).to_mat4();
  m.mul_m(&r)
}

pub fn rot_z(m: Mat4<f32>, angle: f32) -> Mat4<f32> {
  let rad = angle::rad(deg_to_rad(angle));
  let r = Mat3::from_angle_z(rad).to_mat4();
  m.mul_m(&r)
}

pub fn fill_current_coord_vbo(data: &[Vec3<GLfloat>]) {
  let glfloat_size = std::mem::size_of::<GLfloat>();
  let buffer_size = (data.len() * 3 * glfloat_size) as gl::types::GLsizeiptr;
  unsafe {
    gl::BufferData(
      gl::ARRAY_BUFFER,
      buffer_size,
      std::cast::transmute(&data[0]),
      gl::STATIC_DRAW,
    );
  }
}

pub fn gen_buffer() -> GLuint {
  let mut n = 0 as GLuint;
  unsafe {
    gl::GenBuffers(1, &mut n);
  }
  n
}

pub fn delete_buffer(buffer: GLuint) {
  unsafe {
    gl::DeleteBuffers(1, &buffer);
  }
}

pub fn fill_current_color_vbo(data: &[Color3]) {
  let color3_size = std::mem::size_of::<Color3>();
  let buffer_size = (data.len() * color3_size) as gl::types::GLsizeiptr;
  unsafe {
    gl::BufferData(
      gl::ARRAY_BUFFER,
      buffer_size,
      std::cast::transmute(&data[0]),
      gl::STATIC_DRAW,
    );
  }
}

pub fn fill_current_vt_vbo(data: &[Vec2<GLfloat>]) {
  let glfloat_size = std::mem::size_of::<GLfloat>();
  let buffer_size = (data.len() * 2 * glfloat_size) as gl::types::GLsizeiptr;
  unsafe {
    gl::BufferData(
      gl::ARRAY_BUFFER,
      buffer_size,
      std::cast::transmute(&data[0]),
      gl::STATIC_DRAW,
    );
  }
}

pub fn vertex_attrib_pointer(attr: GLuint, components_count: i32) {
  let normalized = gl::FALSE;
  let stride = 0;
  unsafe {
    gl::VertexAttribPointer(
      attr,
      components_count,
      gl::FLOAT,
      normalized,
      stride,
      std::ptr::null(),
    );
  }
}

fn load_image(path: ~str) -> image::Image<u8> {
  let load_result = image::load(path);
  match load_result {
    image::ImageU8(image) => {
      image
    },
    image::Error(message) => {
      fail!("{}", message);
    },
    _ => {
      fail!("unkn");
    }
  }
}

pub fn load_texture(path: ~str) -> GLuint {
  let image = load_image(path);
  let mut id = 0;
  unsafe {
    gl::GenTextures(1, &mut id)
  };
  gl::ActiveTexture(gl::TEXTURE0);
  gl::BindTexture(gl::TEXTURE_2D, id);
  let format = match image.depth {
    4 => gl::RGBA,
    3 => gl::RGB,
    _ => fail!("wrong depth"),
  };
  unsafe {
    let level = 0;
    let border = 0;
    gl::TexImage2D(
      gl::TEXTURE_2D,
      level,
      format as GLint,
      image.width as gl::types::GLsizei,
      image.height as gl::types::GLsizei,
      border,
      format,
      gl::UNSIGNED_BYTE,
      std::cast::transmute(&image.data[0]),
    );
  }
  gl::TexParameteri(gl::TEXTURE_2D,
    gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as GLint);
  gl::TexParameteri(gl::TEXTURE_2D,
    gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as GLint);
  gl::TexParameteri(gl::TEXTURE_2D,
    gl::TEXTURE_MIN_FILTER, gl::LINEAR as GLint);
  gl::TexParameteri(gl::TEXTURE_2D,
    gl::TEXTURE_MAG_FILTER, gl::LINEAR as GLint);
  id
}

// vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab:
<commit_msg>gl_helpers.rs: Added fill_buffer<T>(size, data)<commit_after>// See LICENSE file for copyright and license details.

use std;
use gl;
use gl::types::{
  GLfloat,
  GLint,
  GLuint,
  GLchar,
  GLenum,
  GLsizeiptr,
};
use cgmath::matrix::{
  Matrix,
  Mat4,
  Mat3,
  ToMat4,
};
use cgmath::vector::{
  Vec3,
  Vec2,
};
use cgmath::angle;
use stb_image::image;
use misc::{
  c_str,
  deg_to_rad,
};
use color::Color3;

pub fn compile_shader(src: &str, shader_type: GLenum) -> GLuint {
  let shader = gl::CreateShader(shader_type);
  unsafe {
    gl::ShaderSource(shader, 1, &c_str(src), std::ptr::null());
    gl::CompileShader(shader);
    let mut status = gl::FALSE as GLint;
    gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);
    if status != (gl::TRUE as GLint) {
      let mut len = 0;
      gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
      // subtract 1 to skip the trailing null character
      let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
      gl::GetShaderInfoLog(shader, len, std::ptr::mut_null(),
        buf.as_mut_ptr() as *mut GLchar
      );
      fail!("compile_shader(): " + std::str::raw::from_utf8(buf));
    }
  }
  shader
}

pub fn link_program(vertex_shader: GLuint, fragment_shader: GLuint) -> GLuint {
  let program = gl::CreateProgram();
  gl::AttachShader(program, vertex_shader);
  gl::AttachShader(program, fragment_shader);
  gl::LinkProgram(program);
  unsafe {
    let mut status = gl::FALSE as GLint;
    gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);
    if status != (gl::TRUE as GLint) {
      let mut len = 0;
      gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
      // subtract 1 to skip the trailing null character
      let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
      gl::GetProgramInfoLog(program, len, std::ptr::mut_null(),
        buf.as_mut_ptr() as *mut GLchar
      );
      fail!("link_program(): " + std::str::raw::from_utf8(buf));
    }
  }
  program
}

pub fn compile_program(
  vertex_shader_src: &str,
  frag_shader_src: &str,
) -> GLuint {
  let vertex_shader = compile_shader(
    vertex_shader_src, gl::VERTEX_SHADER);
  let fragment_shader = compile_shader(
    frag_shader_src, gl::FRAGMENT_SHADER);
  let program = link_program(vertex_shader, fragment_shader);
  // mark shaders for deletion after program deletion
  gl::DeleteShader(fragment_shader);
  gl::DeleteShader(vertex_shader);
  program
}

pub fn get_attr(program_id: GLuint, name: &str) -> GLuint {
  unsafe {
    gl::GetAttribLocation(program_id, c_str(name)) as GLuint
  }
}

pub fn get_uniform(program: GLuint, name: &str) -> GLint {
  unsafe {
    gl::GetUniformLocation(program, c_str(name))
  }
}

pub fn draw_mesh(faces_count: int) {
  let starting_index = 0;
  let vertices_count = faces_count as i32 * 3;
  gl::DrawArrays(gl::TRIANGLES, starting_index, vertices_count);
}

pub fn uniform_mat4f(mat_id: GLint, mat: &Mat4<GLfloat>) {
  unsafe {
    gl::UniformMatrix4fv(mat_id, 1, gl::FALSE, mat.cr(0, 0));
  }
}

pub fn tr(m: Mat4<f32>, v: Vec3<f32>) -> Mat4<f32> {
  let mut t = Mat4::<f32>::identity();
  *t.mut_cr(3, 0) = v.x;
  *t.mut_cr(3, 1) = v.y;
  *t.mut_cr(3, 2) = v.z;
  m.mul_m(&t)
}

pub fn rot_x(m: Mat4<f32>, angle: f32) -> Mat4<f32> {
  let rad = angle::rad(deg_to_rad(angle));
  let r = Mat3::from_angle_x(rad).to_mat4();
  m.mul_m(&r)
}

pub fn rot_z(m: Mat4<f32>, angle: f32) -> Mat4<f32> {
  let rad = angle::rad(deg_to_rad(angle));
  let r = Mat3::from_angle_z(rad).to_mat4();
  m.mul_m(&r)
}

fn fill_buffer<T>(buffer_size: i64, data: &[T]) {
  unsafe {
    let data_ptr = std::cast::transmute(&data[0]);
    gl::BufferData(gl::ARRAY_BUFFER, buffer_size, data_ptr, gl::STATIC_DRAW);
  }
}

pub fn fill_current_coord_vbo(data: &[Vec3<GLfloat>]) {
  let glfloat_size = std::mem::size_of::<GLfloat>();
  let buffer_size = (data.len() * 3 * glfloat_size) as GLsizeiptr;
  fill_buffer(buffer_size, data);
}

pub fn gen_buffer() -> GLuint {
  let mut n = 0 as GLuint;
  unsafe {
    gl::GenBuffers(1, &mut n);
  }
  n
}

pub fn delete_buffer(buffer: GLuint) {
  unsafe {
    gl::DeleteBuffers(1, &buffer);
  }
}

pub fn fill_current_color_vbo(data: &[Color3]) {
  let color3_size = std::mem::size_of::<Color3>();
  let buffer_size = (data.len() * color3_size) as GLsizeiptr;
  fill_buffer(buffer_size, data);
}

pub fn fill_current_vt_vbo(data: &[Vec2<GLfloat>]) {
  let glfloat_size = std::mem::size_of::<GLfloat>();
  let buffer_size = (data.len() * 2 * glfloat_size) as GLsizeiptr;
  fill_buffer(buffer_size, data);
}

pub fn vertex_attrib_pointer(attr: GLuint, components_count: i32) {
  let normalized = gl::FALSE;
  let stride = 0;
  unsafe {
    gl::VertexAttribPointer(
      attr,
      components_count,
      gl::FLOAT,
      normalized,
      stride,
      std::ptr::null(),
    );
  }
}

fn load_image(path: ~str) -> image::Image<u8> {
  let load_result = image::load(path);
  match load_result {
    image::ImageU8(image) => {
      image
    },
    image::Error(message) => {
      fail!("{}", message);
    },
    _ => {
      fail!("unkn");
    }
  }
}

pub fn load_texture(path: ~str) -> GLuint {
  let image = load_image(path);
  let mut id = 0;
  unsafe {
    gl::GenTextures(1, &mut id)
  };
  gl::ActiveTexture(gl::TEXTURE0);
  gl::BindTexture(gl::TEXTURE_2D, id);
  let format = match image.depth {
    4 => gl::RGBA,
    3 => gl::RGB,
    _ => fail!("wrong depth"),
  };
  unsafe {
    let level = 0;
    let border = 0;
    gl::TexImage2D(
      gl::TEXTURE_2D,
      level,
      format as GLint,
      image.width as gl::types::GLsizei,
      image.height as gl::types::GLsizei,
      border,
      format,
      gl::UNSIGNED_BYTE,
      std::cast::transmute(&image.data[0]),
    );
  }
  gl::TexParameteri(gl::TEXTURE_2D,
    gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as GLint);
  gl::TexParameteri(gl::TEXTURE_2D,
    gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as GLint);
  gl::TexParameteri(gl::TEXTURE_2D,
    gl::TEXTURE_MIN_FILTER, gl::LINEAR as GLint);
  gl::TexParameteri(gl::TEXTURE_2D,
    gl::TEXTURE_MAG_FILTER, gl::LINEAR as GLint);
  id
}

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


<commit_before>use std::fmt;
use std::marker;

use crate::message_dyn::MessageDyn;
use crate::message_field::MessageField;
use crate::message_full::MessageFull;
use crate::reflect::acc::v2::AccessorV2;
use crate::reflect::acc::FieldAccessor;
use crate::reflect::runtime_types::RuntimeTypeWithDeref;
use crate::reflect::value::value_ref::ReflectValueMut;
use crate::reflect::ProtobufValue;
use crate::reflect::ReflectValueBox;
use crate::reflect::ReflectValueRef;
use crate::EnumFull;
use crate::EnumOrUnknown;

pub(crate) mod oneof;

/// Option-like objects
#[doc(hidden)]
trait OptionLike<T> {
    fn as_option_ref(&self) -> Option<&T>;
    fn as_option_mut(&mut self) -> Option<&mut T>;
    fn set_value(&mut self, value: T);
}

impl<T> OptionLike<T> for Option<T> {
    fn as_option_ref(&self) -> Option<&T> {
        self.as_ref()
    }

    fn as_option_mut(&mut self) -> Option<&mut T> {
        self.as_mut()
    }

    fn set_value(&mut self, value: T) {
        *self = Some(value);
    }
}

impl<T> OptionLike<T> for MessageField<T> {
    fn as_option_ref(&self) -> Option<&T> {
        self.as_ref()
    }

    fn as_option_mut(&mut self) -> Option<&mut T> {
        self.as_mut()
    }

    fn set_value(&mut self, value: T) {
        *self = MessageField::some(value);
    }
}

/// This trait should not be used directly, use `FieldDescriptor` instead
pub(crate) trait SingularFieldAccessor: Send + Sync + 'static {
    fn get_field<'a>(&self, m: &'a dyn MessageDyn) -> Option<ReflectValueRef<'a>>;
    fn mut_field_or_default<'a>(&self, m: &'a mut dyn MessageDyn) -> ReflectValueMut<'a>;
    fn set_field(&self, m: &mut dyn MessageDyn, value: ReflectValueBox);
}

pub(crate) struct SingularFieldAccessorHolder {
    pub accessor: Box<dyn SingularFieldAccessor>,
}

impl SingularFieldAccessorHolder {
    fn new<M>(
        get_field: impl for<'a> Fn(&'a M) -> Option<ReflectValueRef<'a>> + Send + Sync + 'static,
        mut_field_or_default: impl for<'a> Fn(&'a mut M) -> ReflectValueMut<'a> + Send + Sync + 'static,
        set_field: impl Fn(&mut M, ReflectValueBox) + Send + Sync + 'static,
    ) -> SingularFieldAccessorHolder
    where
        M: MessageFull,
    {
        struct Impl<M, G, H, S> {
            get_field: G,
            mut_field_or_default: H,
            set_field: S,
            _marker: marker::PhantomData<M>,
        }

        impl<M, G, H, S> SingularFieldAccessor for Impl<M, G, H, S>
        where
            M: MessageFull,
            G: for<'a> Fn(&'a M) -> Option<ReflectValueRef<'a>> + Send + Sync + 'static,
            H: for<'a> Fn(&'a mut M) -> ReflectValueMut<'a> + Send + Sync + 'static,
            S: Fn(&mut M, ReflectValueBox) + Send + Sync + 'static,
        {
            fn get_field<'a>(&self, m: &'a dyn MessageDyn) -> Option<ReflectValueRef<'a>> {
                (self.get_field)(m.downcast_ref::<M>().unwrap())
            }

            fn mut_field_or_default<'a>(&self, m: &'a mut dyn MessageDyn) -> ReflectValueMut<'a> {
                (self.mut_field_or_default)(m.downcast_mut::<M>().unwrap())
            }

            fn set_field(&self, m: &mut dyn MessageDyn, value: ReflectValueBox) {
                (self.set_field)(m.downcast_mut::<M>().unwrap(), value);
            }
        }

        SingularFieldAccessorHolder {
            accessor: Box::new(Impl {
                get_field,
                mut_field_or_default,
                set_field,
                _marker: marker::PhantomData,
            }),
        }
    }

    fn new_get_mut<M, V>(
        get_field: for<'a> fn(&'a M) -> &'a V,
        mut_field: for<'a> fn(&'a mut M) -> &'a mut V,
    ) -> SingularFieldAccessorHolder
    where
        M: MessageFull,
        V: ProtobufValue,
    {
        Self::new(
            move |m| {
                let v = (get_field)(m);
                if V::is_non_zero(v) {
                    Some(V::as_ref(v))
                } else {
                    None
                }
            },
            move |m| V::as_mut((mut_field)(m)),
            move |m, value| V::set_from_value_box((mut_field)(m), value),
        )
    }

    fn new_get_option_mut_option<M, V>(
        get_field: for<'a> fn(&'a M) -> &'a Option<V>,
        mut_field: for<'a> fn(&'a mut M) -> &'a mut Option<V>,
    ) -> SingularFieldAccessorHolder
    where
        M: MessageFull,
        V: ProtobufValue,
    {
        Self::new(
            move |m| (get_field)(m).as_option_ref().map(V::as_ref),
            move |_m| unimplemented!(),
            move |m, value| (mut_field)(m).set_value(V::from_value_box(value).expect("wrong type")),
        )
    }

    fn new_get_mut_message<M, V>(
        get_field: for<'a> fn(&'a M) -> &'a MessageField<V>,
        mut_field: for<'a> fn(&'a mut M) -> &'a mut MessageField<V>,
    ) -> SingularFieldAccessorHolder
    where
        M: MessageFull,
        V: MessageFull,
    {
        Self::new(
            move |m| (get_field)(m).as_option_ref().map(V::as_ref),
            move |m| {
                let option = (mut_field)(m);
                if option.as_option_ref().is_none() {
                    option.set_value(V::default());
                }
                V::as_mut(option.as_option_mut().unwrap())
            },
            move |m, value| (mut_field)(m).set_value(V::from_value_box(value).expect("wrong type")),
        )
    }

    pub(crate) fn new_get_option_set_enum<M, E>(
        get: fn(&M) -> Option<EnumOrUnknown<E>>,
        set: fn(&mut M, EnumOrUnknown<E>),
    ) -> SingularFieldAccessorHolder
    where
        M: MessageFull,
        E: EnumFull,
    {
        Self::new(
            move |m| {
                let value = (get)(m);
                value.map(|v| ReflectValueRef::Enum(E::enum_descriptor_static(), v.value()))
            },
            |_m| panic!("cannot get mutable pointer"),
            move |m, value| match value {
                ReflectValueBox::Enum(e, v) => {
                    assert_eq!(E::enum_descriptor_static(), e);
                    (set)(m, EnumOrUnknown::from_i32(v));
                }
                _ => panic!("expecting enum value"),
            },
        )
    }

    pub(crate) fn new_has_get_set<M, V>(
        has: fn(&M) -> bool,
        get: fn(&M) -> V,
        set: fn(&mut M, V),
    ) -> SingularFieldAccessorHolder
    where
        M: MessageFull,
        V: ProtobufValue + Copy,
    {
        Self::new(
            move |m| {
                if (has)(m) {
                    Some(V::into_static_value_ref((get)(m)))
                } else {
                    None
                }
            },
            |_m| unimplemented!(),
            move |m, value| (set)(m, value.downcast::<V>().expect("wrong type")),
        )
    }

    pub(crate) fn new_has_get_set_deref<M, V>(
        has: fn(&M) -> bool,
        get: for<'a> fn(&'a M) -> &'a <V::RuntimeType as RuntimeTypeWithDeref>::DerefTarget,
        set: fn(&mut M, V),
    ) -> SingularFieldAccessorHolder
    where
        M: MessageFull,
        V: ProtobufValue,
        V::RuntimeType: RuntimeTypeWithDeref,
    {
        struct Impl<M, V>
        where
            M: MessageFull,
            V: ProtobufValue,
            V::RuntimeType: RuntimeTypeWithDeref,
        {
            has: fn(&M) -> bool,
            get: for<'a> fn(&'a M) -> &'a <V::RuntimeType as RuntimeTypeWithDeref>::DerefTarget,
            set: fn(&mut M, V),
        }

        impl<M, V> SingularFieldAccessor for Impl<M, V>
        where
            M: MessageFull,
            V: ProtobufValue,
            V::RuntimeType: RuntimeTypeWithDeref,
        {
            fn get_field<'a>(&self, m: &'a dyn MessageDyn) -> Option<ReflectValueRef<'a>> {
                let m = m.downcast_ref().unwrap();
                if (self.has)(m) {
                    Some(<V::RuntimeType as RuntimeTypeWithDeref>::defef_as_ref(
                        (self.get)(m),
                    ))
                } else {
                    None
                }
            }

            fn mut_field_or_default<'a>(&self, _m: &'a mut dyn MessageDyn) -> ReflectValueMut<'a> {
                unimplemented!()
            }

            fn set_field(&self, m: &mut dyn MessageDyn, value: ReflectValueBox) {
                let m = m.downcast_mut().unwrap();
                (self.set)(m, value.downcast::<V>().expect("message"))
            }
        }

        SingularFieldAccessorHolder {
            accessor: Box::new(Impl { has, get, set }),
        }
    }

    pub(crate) fn new_has_get_mut_set<M, F>(
        has_field: fn(&M) -> bool,
        get_field: for<'a> fn(&'a M) -> &'a F,
        mut_field: for<'a> fn(&'a mut M) -> &'a mut F,
        set_field: fn(&mut M, F),
    ) -> SingularFieldAccessorHolder
    where
        M: MessageFull,
        F: MessageFull,
    {
        struct Impl<M, F> {
            has_field: fn(&M) -> bool,
            get_field: for<'a> fn(&'a M) -> &'a F,
            mut_field: for<'a> fn(&'a mut M) -> &'a mut F,
            set_field: fn(&mut M, F),
        }

        impl<M, F> SingularFieldAccessor for Impl<M, F>
        where
            M: MessageFull,
            F: MessageFull,
        {
            fn get_field<'a>(&self, m: &'a dyn MessageDyn) -> Option<ReflectValueRef<'a>> {
                let m = m.downcast_ref().unwrap();
                if (self.has_field)(m) {
                    Some(F::as_ref((self.get_field)(m)))
                } else {
                    None
                }
            }

            fn mut_field_or_default<'a>(&self, m: &'a mut dyn MessageDyn) -> ReflectValueMut<'a> {
                let m = m.downcast_mut().unwrap();
                F::as_mut((self.mut_field)(m))
            }

            fn set_field(&self, m: &mut dyn MessageDyn, value: ReflectValueBox) {
                let m = m.downcast_mut().unwrap();
                (self.set_field)(m, value.downcast::<F>().expect("message"))
            }
        }

        SingularFieldAccessorHolder {
            accessor: Box::new(Impl {
                has_field,
                get_field,
                mut_field,
                set_field,
            }),
        }
    }
}

impl<'a> fmt::Debug for SingularFieldAccessorHolder {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("SingularFieldAccessorHolder").finish()
    }
}

trait GetOptionImpl<M>: Send + Sync + 'static {
    fn get_reflect_impl<'a>(&self, m: &'a M) -> Option<ReflectValueRef<'a>>;
}

trait GetOrDefaultImpl<M>: Send + Sync + 'static {
    fn get_singular_field_or_default_impl<'a>(&self, m: &'a M) -> ReflectValueRef<'a>;
}

trait MutOrDefaultImpl<M>: Send + Sync + 'static {
    fn mut_singular_field_or_default_impl<'a>(&self, m: &'a mut M) -> ReflectValueMut<'a>;
}

trait SetImpl<M>: Send + Sync + 'static {
    fn set_singular_field(&self, m: &mut M, value: ReflectValueBox);
}

/// Make accessor for `SingularPtrField`
pub fn make_message_field_accessor<M, V>(
    name: &'static str,
    get_field: for<'a> fn(&'a M) -> &'a MessageField<V>,
    mut_field: for<'a> fn(&'a mut M) -> &'a mut MessageField<V>,
) -> FieldAccessor
where
    M: MessageFull,
    V: MessageFull,
{
    FieldAccessor::new(
        name,
        AccessorV2::Singular(SingularFieldAccessorHolder::new_get_mut_message(
            get_field, mut_field,
        )),
    )
}

/// Make accessor for `Option<C>` field
pub fn make_option_accessor<M, V>(
    name: &'static str,
    get_field: for<'a> fn(&'a M) -> &'a Option<V>,
    mut_field: for<'a> fn(&'a mut M) -> &'a mut Option<V>,
) -> FieldAccessor
where
    M: MessageFull,
    V: ProtobufValue,
{
    FieldAccessor::new(
        name,
        AccessorV2::Singular(SingularFieldAccessorHolder::new_get_option_mut_option(
            get_field, mut_field,
        )),
    )
}

/// Make accessor for simple field
pub fn make_simpler_field_accessor<M, V>(
    name: &'static str,
    get_field: for<'a> fn(&'a M) -> &'a V,
    mut_field: for<'a> fn(&'a mut M) -> &'a mut V,
) -> FieldAccessor
where
    M: MessageFull,
    V: ProtobufValue,
{
    FieldAccessor::new(
        name,
        AccessorV2::Singular(SingularFieldAccessorHolder::new_get_mut(
            get_field, mut_field,
        )),
    )
}
<commit_msg>Simplify accessors<commit_after>use std::fmt;
use std::marker;

use crate::message_dyn::MessageDyn;
use crate::message_field::MessageField;
use crate::message_full::MessageFull;
use crate::reflect::acc::v2::AccessorV2;
use crate::reflect::acc::FieldAccessor;
use crate::reflect::runtime_types::RuntimeTypeWithDeref;
use crate::reflect::value::value_ref::ReflectValueMut;
use crate::reflect::ProtobufValue;
use crate::reflect::ReflectValueBox;
use crate::reflect::ReflectValueRef;
use crate::EnumFull;
use crate::EnumOrUnknown;

pub(crate) mod oneof;

/// Option-like objects
#[doc(hidden)]
trait OptionLike<T> {
    fn as_option_ref(&self) -> Option<&T>;
    fn as_option_mut(&mut self) -> Option<&mut T>;
    fn set_value(&mut self, value: T);
}

impl<T> OptionLike<T> for Option<T> {
    fn as_option_ref(&self) -> Option<&T> {
        self.as_ref()
    }

    fn as_option_mut(&mut self) -> Option<&mut T> {
        self.as_mut()
    }

    fn set_value(&mut self, value: T) {
        *self = Some(value);
    }
}

impl<T> OptionLike<T> for MessageField<T> {
    fn as_option_ref(&self) -> Option<&T> {
        self.as_ref()
    }

    fn as_option_mut(&mut self) -> Option<&mut T> {
        self.as_mut()
    }

    fn set_value(&mut self, value: T) {
        *self = MessageField::some(value);
    }
}

/// This trait should not be used directly, use `FieldDescriptor` instead
pub(crate) trait SingularFieldAccessor: Send + Sync + 'static {
    fn get_field<'a>(&self, m: &'a dyn MessageDyn) -> Option<ReflectValueRef<'a>>;
    fn mut_field_or_default<'a>(&self, m: &'a mut dyn MessageDyn) -> ReflectValueMut<'a>;
    fn set_field(&self, m: &mut dyn MessageDyn, value: ReflectValueBox);
}

pub(crate) struct SingularFieldAccessorHolder {
    pub accessor: Box<dyn SingularFieldAccessor>,
}

impl SingularFieldAccessorHolder {
    fn new<M>(
        get_field: impl for<'a> Fn(&'a M) -> Option<ReflectValueRef<'a>> + Send + Sync + 'static,
        mut_field_or_default: impl for<'a> Fn(&'a mut M) -> ReflectValueMut<'a> + Send + Sync + 'static,
        set_field: impl Fn(&mut M, ReflectValueBox) + Send + Sync + 'static,
    ) -> SingularFieldAccessorHolder
    where
        M: MessageFull,
    {
        struct Impl<M, G, H, S> {
            get_field: G,
            mut_field_or_default: H,
            set_field: S,
            _marker: marker::PhantomData<M>,
        }

        impl<M, G, H, S> SingularFieldAccessor for Impl<M, G, H, S>
        where
            M: MessageFull,
            G: for<'a> Fn(&'a M) -> Option<ReflectValueRef<'a>> + Send + Sync + 'static,
            H: for<'a> Fn(&'a mut M) -> ReflectValueMut<'a> + Send + Sync + 'static,
            S: Fn(&mut M, ReflectValueBox) + Send + Sync + 'static,
        {
            fn get_field<'a>(&self, m: &'a dyn MessageDyn) -> Option<ReflectValueRef<'a>> {
                (self.get_field)(m.downcast_ref::<M>().unwrap())
            }

            fn mut_field_or_default<'a>(&self, m: &'a mut dyn MessageDyn) -> ReflectValueMut<'a> {
                (self.mut_field_or_default)(m.downcast_mut::<M>().unwrap())
            }

            fn set_field(&self, m: &mut dyn MessageDyn, value: ReflectValueBox) {
                (self.set_field)(m.downcast_mut::<M>().unwrap(), value);
            }
        }

        SingularFieldAccessorHolder {
            accessor: Box::new(Impl {
                get_field,
                mut_field_or_default,
                set_field,
                _marker: marker::PhantomData,
            }),
        }
    }

    fn new_get_mut<M, V>(
        get_field: for<'a> fn(&'a M) -> &'a V,
        mut_field: for<'a> fn(&'a mut M) -> &'a mut V,
    ) -> SingularFieldAccessorHolder
    where
        M: MessageFull,
        V: ProtobufValue,
    {
        Self::new(
            move |m| {
                let v = (get_field)(m);
                if V::is_non_zero(v) {
                    Some(V::as_ref(v))
                } else {
                    None
                }
            },
            move |m| V::as_mut((mut_field)(m)),
            move |m, value| V::set_from_value_box((mut_field)(m), value),
        )
    }

    fn new_get_option_mut_option<M, V>(
        get_field: for<'a> fn(&'a M) -> &'a Option<V>,
        mut_field: for<'a> fn(&'a mut M) -> &'a mut Option<V>,
    ) -> SingularFieldAccessorHolder
    where
        M: MessageFull,
        V: ProtobufValue,
    {
        Self::new(
            move |m| (get_field)(m).as_option_ref().map(V::as_ref),
            move |_m| unimplemented!(),
            move |m, value| (mut_field)(m).set_value(V::from_value_box(value).expect("wrong type")),
        )
    }

    fn new_get_mut_message<M, V>(
        get_field: for<'a> fn(&'a M) -> &'a MessageField<V>,
        mut_field: for<'a> fn(&'a mut M) -> &'a mut MessageField<V>,
    ) -> SingularFieldAccessorHolder
    where
        M: MessageFull,
        V: MessageFull,
    {
        Self::new(
            move |m| (get_field)(m).as_option_ref().map(V::as_ref),
            move |m| {
                let option = (mut_field)(m);
                if option.as_option_ref().is_none() {
                    option.set_value(V::default());
                }
                V::as_mut(option.as_option_mut().unwrap())
            },
            move |m, value| (mut_field)(m).set_value(V::from_value_box(value).expect("wrong type")),
        )
    }

    pub(crate) fn new_get_option_set_enum<M, E>(
        get: fn(&M) -> Option<EnumOrUnknown<E>>,
        set: fn(&mut M, EnumOrUnknown<E>),
    ) -> SingularFieldAccessorHolder
    where
        M: MessageFull,
        E: EnumFull,
    {
        Self::new(
            move |m| {
                let value = (get)(m);
                value.map(|v| ReflectValueRef::Enum(E::enum_descriptor_static(), v.value()))
            },
            |_m| panic!("cannot get mutable pointer"),
            move |m, value| match value {
                ReflectValueBox::Enum(e, v) => {
                    assert_eq!(E::enum_descriptor_static(), e);
                    (set)(m, EnumOrUnknown::from_i32(v));
                }
                _ => panic!("expecting enum value"),
            },
        )
    }

    pub(crate) fn new_has_get_set<M, V>(
        has: fn(&M) -> bool,
        get: fn(&M) -> V,
        set: fn(&mut M, V),
    ) -> SingularFieldAccessorHolder
    where
        M: MessageFull,
        V: ProtobufValue + Copy,
    {
        Self::new(
            move |m| {
                if (has)(m) {
                    Some(V::into_static_value_ref((get)(m)))
                } else {
                    None
                }
            },
            |_m| unimplemented!(),
            move |m, value| (set)(m, value.downcast::<V>().expect("wrong type")),
        )
    }

    pub(crate) fn new_has_get_set_deref<M, V>(
        has: fn(&M) -> bool,
        get: for<'a> fn(&'a M) -> &'a <V::RuntimeType as RuntimeTypeWithDeref>::DerefTarget,
        set: fn(&mut M, V),
    ) -> SingularFieldAccessorHolder
    where
        M: MessageFull,
        V: ProtobufValue,
        V::RuntimeType: RuntimeTypeWithDeref,
    {
        Self::new(
            move |m| {
                if (has)(m) {
                    Some(<V::RuntimeType as RuntimeTypeWithDeref>::defef_as_ref(
                        (get)(m),
                    ))
                } else {
                    None
                }
            },
            |_m| unimplemented!(),
            move |m, value| (set)(m, value.downcast::<V>().expect("message")),
        )
    }

    pub(crate) fn new_has_get_mut_set<M, F>(
        has_field: fn(&M) -> bool,
        get_field: for<'a> fn(&'a M) -> &'a F,
        mut_field: for<'a> fn(&'a mut M) -> &'a mut F,
        set_field: fn(&mut M, F),
    ) -> SingularFieldAccessorHolder
    where
        M: MessageFull,
        F: MessageFull,
    {
        struct Impl<M, F> {
            has_field: fn(&M) -> bool,
            get_field: for<'a> fn(&'a M) -> &'a F,
            mut_field: for<'a> fn(&'a mut M) -> &'a mut F,
            set_field: fn(&mut M, F),
        }

        impl<M, F> SingularFieldAccessor for Impl<M, F>
        where
            M: MessageFull,
            F: MessageFull,
        {
            fn get_field<'a>(&self, m: &'a dyn MessageDyn) -> Option<ReflectValueRef<'a>> {
                let m = m.downcast_ref().unwrap();
                if (self.has_field)(m) {
                    Some(F::as_ref((self.get_field)(m)))
                } else {
                    None
                }
            }

            fn mut_field_or_default<'a>(&self, m: &'a mut dyn MessageDyn) -> ReflectValueMut<'a> {
                let m = m.downcast_mut().unwrap();
                F::as_mut((self.mut_field)(m))
            }

            fn set_field(&self, m: &mut dyn MessageDyn, value: ReflectValueBox) {
                let m = m.downcast_mut().unwrap();
                (self.set_field)(m, value.downcast::<F>().expect("message"))
            }
        }

        SingularFieldAccessorHolder {
            accessor: Box::new(Impl {
                has_field,
                get_field,
                mut_field,
                set_field,
            }),
        }
    }
}

impl<'a> fmt::Debug for SingularFieldAccessorHolder {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("SingularFieldAccessorHolder").finish()
    }
}

trait GetOptionImpl<M>: Send + Sync + 'static {
    fn get_reflect_impl<'a>(&self, m: &'a M) -> Option<ReflectValueRef<'a>>;
}

trait GetOrDefaultImpl<M>: Send + Sync + 'static {
    fn get_singular_field_or_default_impl<'a>(&self, m: &'a M) -> ReflectValueRef<'a>;
}

trait MutOrDefaultImpl<M>: Send + Sync + 'static {
    fn mut_singular_field_or_default_impl<'a>(&self, m: &'a mut M) -> ReflectValueMut<'a>;
}

trait SetImpl<M>: Send + Sync + 'static {
    fn set_singular_field(&self, m: &mut M, value: ReflectValueBox);
}

/// Make accessor for `SingularPtrField`
pub fn make_message_field_accessor<M, V>(
    name: &'static str,
    get_field: for<'a> fn(&'a M) -> &'a MessageField<V>,
    mut_field: for<'a> fn(&'a mut M) -> &'a mut MessageField<V>,
) -> FieldAccessor
where
    M: MessageFull,
    V: MessageFull,
{
    FieldAccessor::new(
        name,
        AccessorV2::Singular(SingularFieldAccessorHolder::new_get_mut_message(
            get_field, mut_field,
        )),
    )
}

/// Make accessor for `Option<C>` field
pub fn make_option_accessor<M, V>(
    name: &'static str,
    get_field: for<'a> fn(&'a M) -> &'a Option<V>,
    mut_field: for<'a> fn(&'a mut M) -> &'a mut Option<V>,
) -> FieldAccessor
where
    M: MessageFull,
    V: ProtobufValue,
{
    FieldAccessor::new(
        name,
        AccessorV2::Singular(SingularFieldAccessorHolder::new_get_option_mut_option(
            get_field, mut_field,
        )),
    )
}

/// Make accessor for simple field
pub fn make_simpler_field_accessor<M, V>(
    name: &'static str,
    get_field: for<'a> fn(&'a M) -> &'a V,
    mut_field: for<'a> fn(&'a mut M) -> &'a mut V,
) -> FieldAccessor
where
    M: MessageFull,
    V: ProtobufValue,
{
    FieldAccessor::new(
        name,
        AccessorV2::Singular(SingularFieldAccessorHolder::new_get_mut(
            get_field, mut_field,
        )),
    )
}
<|endoftext|>


<commit_before>use {Errno, Error, Result};
use libc;
use void::Void;
use std::mem::drop;

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum RebootMode {
    Halt,
    kexec,
    PowerOff,
    Restart,
    // we do not support Restart2,
    Suspend,
}

pub fn reboot(how: RebootMode) -> Result<Void> {
    let cmd = match how {
        RebootMode::Halt => libc::RB_HALT_SYSTEM,
        RebootMode::kexec => libc::RB_KEXEC,
        RebootMode::PowerOff => libc::RB_POWER_OFF,
        RebootMode::Restart => libc::RB_AUTOBOOT,
        // we do not support Restart2,
        RebootMode::Suspend => libc::RB_SW_SUSPEND,
    };
    unsafe {
        libc::reboot(cmd)
    };
    Err(Error::Sys(Errno::last()))
}

/// Enable or disable the reboot keystroke (Ctrl-Alt-Delete).
///
/// Corresponds to calling `reboot(RB_ENABLE_CAD)` or `reboot(RB_DISABLE_CAD)` in C.
pub fn set_cad_enabled(enable: bool) -> Result<()> {
    let cmd = if enable {
        libc::RB_ENABLE_CAD
    } else {
        libc::RB_DISABLE_CAD
    };
    let res = unsafe {
        libc::reboot(cmd)
    };
    Errno::result(res).map(drop)
}
<commit_msg>Switch Clone and Copy<commit_after>use {Errno, Error, Result};
use libc;
use void::Void;
use std::mem::drop;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum RebootMode {
    Halt,
    kexec,
    PowerOff,
    Restart,
    // we do not support Restart2,
    Suspend,
}

pub fn reboot(how: RebootMode) -> Result<Void> {
    let cmd = match how {
        RebootMode::Halt => libc::RB_HALT_SYSTEM,
        RebootMode::kexec => libc::RB_KEXEC,
        RebootMode::PowerOff => libc::RB_POWER_OFF,
        RebootMode::Restart => libc::RB_AUTOBOOT,
        // we do not support Restart2,
        RebootMode::Suspend => libc::RB_SW_SUSPEND,
    };
    unsafe {
        libc::reboot(cmd)
    };
    Err(Error::Sys(Errno::last()))
}

/// Enable or disable the reboot keystroke (Ctrl-Alt-Delete).
///
/// Corresponds to calling `reboot(RB_ENABLE_CAD)` or `reboot(RB_DISABLE_CAD)` in C.
pub fn set_cad_enabled(enable: bool) -> Result<()> {
    let cmd = if enable {
        libc::RB_ENABLE_CAD
    } else {
        libc::RB_DISABLE_CAD
    };
    let res = unsafe {
        libc::reboot(cmd)
    };
    Errno::result(res).map(drop)
}
<|endoftext|>


<commit_before>/**
 * Reads NMEA messages from the GPS.
 */

/**
 * GGA: Global positioning system fix data.
 */
#[derive(PartialEq)]
pub struct GgaMessage {
    pub latitude_degrees: f64,
    pub longitude_degrees: f64,
    pub horizontal_dilution_of_precision: f32,
}

/**
 * VTG: Course over ground and ground speed.
 */
#[derive(PartialEq)]
pub struct VtgMessage {
    pub course_d: f32,
    pub speed_m_s: f32,
}

#[derive(PartialEq)]
pub enum NmeaMessage {
    Gga(GgaMessage),
    Vtg(VtgMessage),
}

impl NmeaMessage {
    fn parse(message: &str) -> Option<NmeaMessage> {
        if message.starts_with("$GPGGA") {
            // $GPGGA,hhmmss.sss,ddmm.mmmm,a,dddmm.mmmm,a,x,xx,x.x,x.x,M,,,,xxxx*hh<CR><LF>
            let mut iterator = message.split(',');

            iterator.next();  // Skip the message type
            iterator.next();  // Skip the timestamp since midnight UTC

            let latitude_degrees = {
                let string = iterator.next().unwrap();
                let degrees: i32 = string[0..2].parse().unwrap();
                let minutes: f64 = string[2..].parse().unwrap();

                let north = iterator.next().unwrap() == "N";
                let d = degrees as f64 + minutes / 60.0f64;
                if north { d } else { -d }
            };

            let longitude_degrees = {
                let string = iterator.next().unwrap();
                let degrees: i32 = string[0..2].parse().unwrap();
                let minutes: f64 = string[2..].parse().unwrap();

                let east = iterator.next().unwrap() == "E";
                let d = degrees as f64 + minutes / 60.0f64;
                if east { d } else { -d }
            };

            iterator.next();  // Skip the GPS quality indicator
            iterator.next();  // Skip the satellites used

            let hdop: f32 = iterator.next().unwrap().parse().unwrap();

            Some(
                NmeaMessage::Gga (
                    GgaMessage {
                        latitude_degrees: latitude_degrees,
                        longitude_degrees: longitude_degrees,
                        horizontal_dilution_of_precision: hdop,
                    }
                )
            )

        } else if message.starts_with("$GPVTG") {
            // GPVTG,x.x,T,x.x,M,x.x,N,x.x,K,a*hh<CR><LF>
            let mut iterator = message.split(',');

            iterator.next();  // Skip the message type

            let course_d: f32 = iterator.next().unwrap().parse().unwrap();
            iterator.next();  // Skip the letter T indicating true course

            iterator.next();  // Skip the magnetic course
            iterator.next();  // Skip the letter M indicating magnetic course

            iterator.next();  // Skip speed in knots
            iterator.next();  // Skip the letter N indicating knots

            let speed_km_h: f32 = iterator.next().unwrap().parse().unwrap();

            Some(
                NmeaMessage::Vtg (
                    VtgMessage {
                        course_d: course_d,
                        speed_m_s: speed_km_h * 1000.0 / (60.0 * 60.0),
                    }
                )
            )
        } else {
            // TODO: Log a warning
            None
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{NmeaMessage, GgaMessage, VtgMessage};
    use super::NmeaMessage::{Gga, Vtg};

    #[test]
    fn test_parse_gga() {
        let message = "$GPGGA,033403.456,0102.3456,N,0102.3456,W,1,11,0.8,108.2,M,,,,0000*01\r\n";
        let expected = GgaMessage {
            latitude_degrees: 1.0390933333333334f64,
            longitude_degrees: -1.0390933333333334f64,
            horizontal_dilution_of_precision: 0.8f32,
        };
        match NmeaMessage::parse(message).unwrap() {
            Gga(gga) => {
                assert!(expected == gga);
            }
            _ => assert!(false),
        }
    }

    #[test]
    fn test_parse_vtg() {
        // 36 k/h = 10 m/s
        let message = "$GPVTG,123.4,T,356.1,M,000.0,N,0036.0,K,A*32\r\n";
        let expected = VtgMessage {
            course_d: 123.4,
            speed_m_s: 10.0,
        };
        match NmeaMessage::parse(message).unwrap() {
            Vtg(vtg) => {
                assert!(expected == vtg);
            },
            _ => assert!(false),
        }
    }
}
<commit_msg>Use macros to detect and bail on error<commit_after>/**
 * Reads NMEA messages from the GPS.
 */

use std::error::Error;

/**
 * GGA: Global positioning system fix data.
 */
#[derive(PartialEq)]
pub struct GgaMessage {
    pub latitude_degrees: f64,
    pub longitude_degrees: f64,
    pub horizontal_dilution_of_precision: f32,
}

/**
 * VTG: Course over ground and ground speed.
 */
#[derive(PartialEq)]
pub struct VtgMessage {
    pub course_d: f32,
    pub speed_m_s: f32,
}

#[derive(PartialEq)]
pub enum NmeaMessage {
    Gga(GgaMessage),
    Vtg(VtgMessage),
}

macro_rules! bail_err {
    ($option:expr) => (
        match $option {
            Ok(s) => s,
            Err(e) => return Err(e.description().to_string()),
        };
    );
}
macro_rules! bail_none {
    ($option:expr) => (
        match $option {
            Some(s) => s,
            None => return Err("Message too short".to_string()),
        };
    );
}
impl NmeaMessage {
    fn parse(message: &str) -> Result<NmeaMessage, String> {
        if message.starts_with("$GPGGA") {
            // $GPGGA,hhmmss.sss,ddmm.mmmm,a,dddmm.mmmm,a,x,xx,x.x,x.x,M,,,,xxxx*hh<CR><LF>
            let mut iterator = message.split(',');

            iterator.next();  // Skip the message type
            iterator.next();  // Skip the timestamp since midnight UTC

            let latitude_degrees = {
                let string = bail_none!(iterator.next());
                let degrees: i32 = bail_err!(string[0..2].parse());
                let minutes: f64 = bail_err!(string[2..].parse());

                let north_indicator = bail_none!(iterator.next());
                let north = north_indicator == "N";
                let d = degrees as f64 + minutes / 60.0f64;
                if north { d } else { -d }
            };

            let longitude_degrees = {
                let string = bail_none!(iterator.next());
                let degrees: i32 = bail_err!(string[0..2].parse());
                let minutes: f64 = bail_err!(string[2..].parse());

                let east_indicator = bail_none!(iterator.next());
                let east = east_indicator == "E";
                let d = degrees as f64 + minutes / 60.0f64;
                if east { d } else { -d }
            };

            iterator.next();  // Skip the GPS quality indicator
            iterator.next();  // Skip the satellites used

            let hdop_str = bail_none!(iterator.next());
            let hdop: f32 = bail_err!(hdop_str.parse());

            Ok(
                NmeaMessage::Gga (
                    GgaMessage {
                        latitude_degrees: latitude_degrees,
                        longitude_degrees: longitude_degrees,
                        horizontal_dilution_of_precision: hdop,
                    }
                )
            )

        } else if message.starts_with("$GPVTG") {
            // GPVTG,x.x,T,x.x,M,x.x,N,x.x,K,a*hh<CR><LF>
            let mut iterator = message.split(',');

            iterator.next();  // Skip the message type

            let course_d_str = bail_none!(iterator.next());
            let course_d: f32 = bail_err!(course_d_str.parse());
            iterator.next();  // Skip the letter T indicating true course

            iterator.next();  // Skip the magnetic course
            iterator.next();  // Skip the letter M indicating magnetic course

            iterator.next();  // Skip speed in knots
            iterator.next();  // Skip the letter N indicating knots

            let speed_km_h_str = bail_none!(iterator.next());
            let speed_km_h: f32 = bail_err!(speed_km_h_str.parse());

            Ok(
                NmeaMessage::Vtg (
                    VtgMessage {
                        course_d: course_d,
                        speed_m_s: speed_km_h * 1000.0 / (60.0 * 60.0),
                    }
                )
            )
        } else {
            Err("Unknown NMEA message type".to_string())
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{NmeaMessage, GgaMessage, VtgMessage};
    use super::NmeaMessage::{Gga, Vtg};

    #[test]
    fn test_parse_gga() {
        let message = "$GPGGA,033403.456,0102.3456,N,0102.3456,W,1,11,0.8,108.2,M,,,,0000*01\r\n";
        let expected = GgaMessage {
            latitude_degrees: 1.0390933333333334f64,
            longitude_degrees: -1.0390933333333334f64,
            horizontal_dilution_of_precision: 0.8f32,
        };
        match NmeaMessage::parse(message).unwrap() {
            Gga(gga) => {
                assert!(expected == gga);
            }
            _ => assert!(false),
        }
    }

    #[test]
    fn test_parse_vtg() {
        // 36 km/h = 10 m/s
        let message = "$GPVTG,123.4,T,356.1,M,000.0,N,0036.0,K,A*32\r\n";
        let expected = VtgMessage {
            course_d: 123.4,
            speed_m_s: 10.0,
        };
        match NmeaMessage::parse(message).unwrap() {
            Vtg(vtg) => {
                assert!(expected == vtg);
            },
            _ => assert!(false),
        }
    }
}
<|endoftext|>


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

extern crate base64;
extern crate clap;
extern crate habitat_common as common;
extern crate habitat_core as hcore;
extern crate habitat_pkg_export_docker as export_docker;
extern crate handlebars;
#[macro_use]
extern crate serde_json;

extern crate failure;
#[macro_use]
extern crate failure_derive;

use std::fs::File;
use std::io;
use std::io::prelude::*;

use common::ui::UI;

pub mod error;
pub mod manifest;
pub mod manifestjson;
pub mod service_bind;
pub mod topology;
pub mod cli;

use export_docker::Result;

pub use cli::Cli;
pub use error::Error;
pub use manifest::Manifest;
pub use manifestjson::ManifestJson;

// Synced with the version of the Habitat operator.
pub const VERSION: &'static str = "0.1.0";

/// Convenient do-it-all function. You give it the CLI arguments from the user and it generates the
/// Kubernetes manifest. If user passed an `--output` argument with a value that is not "`-`", the
/// manifest is written to the provided file; otherwise, it is written to the standard output.
pub fn export_for_cli_matches(ui: &mut UI, matches: &clap::ArgMatches) -> Result<()> {
    let image = if !matches.is_present("NO_DOCKER_IMAGE") {
        export_docker::export_for_cli_matches(ui, &matches)?
    } else {
        None
    };
    let mut manifest = Manifest::new_from_cli_matches(ui, &matches, image)?;

    let mut write: Box<Write> = match matches.value_of("OUTPUT") {
        Some(o) if o != "-" => Box::new(File::create(o)?),
        _ => Box::new(io::stdout()),
    };
    manifest.generate(&mut write)
}
<commit_msg>pkg-export-k8s: Add status reporting<commit_after>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate base64;
extern crate clap;
extern crate habitat_common as common;
extern crate habitat_core as hcore;
extern crate habitat_pkg_export_docker as export_docker;
extern crate handlebars;
#[macro_use]
extern crate serde_json;

extern crate failure;
#[macro_use]
extern crate failure_derive;

use std::fs::File;
use std::io;
use std::io::prelude::*;

use common::ui::{UI, Status};

pub mod error;
pub mod manifest;
pub mod manifestjson;
pub mod service_bind;
pub mod topology;
pub mod cli;

use export_docker::Result;

pub use cli::Cli;
pub use error::Error;
pub use manifest::Manifest;
pub use manifestjson::ManifestJson;

// Synced with the version of the Habitat operator.
pub const VERSION: &'static str = "0.1.0";

/// Convenient do-it-all function. You give it the CLI arguments from the user and it generates the
/// Kubernetes manifest. If user passed an `--output` argument with a value that is not "`-`", the
/// manifest is written to the provided file; otherwise, it is written to the standard output.
pub fn export_for_cli_matches(ui: &mut UI, matches: &clap::ArgMatches) -> Result<()> {
    let image = if !matches.is_present("NO_DOCKER_IMAGE") {
        export_docker::export_for_cli_matches(ui, &matches)?
    } else {
        ui.status(
            Status::Custom('☛', String::from("Skipping")),
            "Docker image generation",
        )?;
        None
    };
    let mut manifest = Manifest::new_from_cli_matches(ui, &matches, image)?;

    let mut write: Box<Write> = match matches.value_of("OUTPUT") {
        Some(o) if o != "-" => {
            ui.status(
                Status::Creating,
                format!("Kubernetes manifest file {}", o),
            )?;
            let file = Box::new(File::create(o)?);
            ui.status(
                Status::Created,
                format!("Kubernetes manifest file {}", o),
            )?;

            file
        }
        _ => {
            let stdout = Box::new(io::stdout());
            ui.status(
                Status::Custom('→', String::from("Writing")),
                "Kubernetes manifest to stdout",
            )?;

            stdout
        }
    };
    manifest.generate(&mut write)
}
<|endoftext|>


<commit_before>//! Simple parsing of ASN.1 DER

use timmy::tup::*;

use num::bigint::{BigInt, Sign};

#[derive(Debug)]
pub enum ASN1Error {
    MissingData(String),
}

pub type ASN1Result<T> = Result<T, ASN1Error>;

#[derive(Debug)]
pub enum ASN1Type {
    Unknown,
    Cont(u8, Box<ASN1Type>),
    Null,
    Boolean(bool),
    Sequence(Vec<ASN1Type>),
    Set(Vec<ASN1Type>),
    Object(TupT<u32>),
    Integer(BigInt),
    BitString(Vec<u8>),
    OctetString(Vec<u8>),
    PrintableString(String),
    UTF8String(String),
    UTCTime(String),
}

pub fn asn1_to_raw_string(obj: &ASN1Type) -> Option<String> {
    match obj {
        &ASN1Type::PrintableString(ref string) => Some(string.clone()),
        &ASN1Type::UTF8String(ref string) => Some(string.clone()),
        _ => None,
    }
}

pub fn asn1_to_raw_integer(obj: &ASN1Type) -> Option<BigInt> {
    match obj {
        &ASN1Type::Integer(ref bigint) => Some(bigint.clone()),
        _ => None,
    }
}

pub struct DerParser {
    buf: Vec<u8>,
    idx: usize,
}

impl DerParser {
    pub fn new(der: &Vec<u8>) -> DerParser {
        DerParser {
            buf: der.clone(),
            idx: 0,
        }
    }

    fn get_length(&mut self) -> ASN1Result<usize> {
        if self.idx >= self.buf.len() {
            return Err(ASN1Error::MissingData("length".to_string()));
        }
        let len_tmp = self.buf[self.idx];
        if len_tmp <= 127 {
            self.idx += 1;
            return Ok(len_tmp as usize);
        }

        let len_octets = len_tmp & 127;
        assert!(len_octets <= 3);
        let mut length = 0 as usize;
        self.idx += 1;
        for _ in 0..len_octets {
            length <<= 8;
            if self.idx >= self.buf.len() {
                return Err(ASN1Error::MissingData("length".to_string()));
            }
            length |= self.buf[self.idx] as usize;
            self.idx += 1;
        }
        Ok(length)
    }

    fn parse_header(&mut self) -> ASN1Result<(u8, bool, u8, usize)> {
        let c = self.buf[self.idx];
        if self.idx >= self.buf.len() {
            return Err(ASN1Error::MissingData("header".to_string()));
        }

        let tag = c & 31;
        let p_c = (c >> 5) & 1;
        let class_ = (c >> 6) & 3;
        assert!(tag != 31);
        self.idx += 1;
        let length = try!(self.get_length());

        Ok((class_ as u8, p_c == 1, tag as u8, length as usize))
    }

    pub fn parse_entry(&mut self) -> ASN1Result<ASN1Type> {
        if self.idx >= self.buf.len() {
            return Err(ASN1Error::MissingData("entry".to_string()));
        }

        let (class_bits, constructed, tag, length) = try!(self.parse_header());

        assert!(class_bits == 0 || class_bits == 2);

        match class_bits {
            0 => {
            }
            2 => {
                let pos = self.idx;
                self.idx += length;

                let sub_buf = self.buf[pos..pos+length].iter().cloned().collect();
                let mut sub_parser = DerParser::new(&sub_buf);
                let sub_entry = try!(sub_parser.parse_entry());
                return Ok(ASN1Type::Cont(tag, Box::new(sub_entry)));
            }
            _ => {
                panic!("Parsing this not implemented.");
            }
        }

        let pos = self.idx;
        self.idx += length;

        let raw = self.buf[pos..pos+length].iter().cloned().collect();

        let entry = match tag {
            5 => ASN1Type::Null,
            1 => {
                let buf: Vec<u8> = raw;
                ASN1Type::Boolean(buf[0] == 0xff)
            }
            16 => {
                let mut sub_parser = DerParser::new(&raw);
                let mut sequence = Vec::<ASN1Type>::new();
                loop {
                    let sub_ent = sub_parser.parse_entry();
                    match sub_ent {
                        Err(ASN1Error::MissingData(_)) => { break },
                        Ok(ent) => { sequence.push(ent) }
                    }
                }
                ASN1Type::Sequence(sequence)
            },
            17 => {
                let mut sub_parser = DerParser::new(&raw);
                let mut sequence = Vec::<ASN1Type>::new();
                loop {
                    let sub_ent = sub_parser.parse_entry();
                    match sub_ent {
                        Err(ASN1Error::MissingData(_)) => { break },
                        Ok(ent) => { sequence.push(ent) }
                    }
                }
                ASN1Type::Set(sequence)
            },
            2 => ASN1Type::Integer(BigInt::from_bytes_be(Sign::Plus, &raw)),
            6 => {
                let mut oi = Vec::<u32>::new();
                let obj_bytes = raw;
                oi.push((obj_bytes[0] / 40) as u32);
                oi.push((obj_bytes[0] % 40) as u32);
                let mut i = 1;
                while i < obj_bytes.len() {
                    if obj_bytes[i] <= 127 {
                        oi.push(obj_bytes[i] as u32);
                        i += 1;
                    } else {
                        let mut next_sub_id: u32 = obj_bytes[i] as u32;
                        let mut sub_id: u32 = 0;
                        i += 1;
                        while next_sub_id > 127 {
                            sub_id <<= 7;
                            sub_id |= next_sub_id & 127;
                            next_sub_id = obj_bytes[i] as u32;
                            i += 1;
                        }
                        oi.push((sub_id << 7) | next_sub_id);
                    }
                }
                ASN1Type::Object(vec_to_tup(&oi).expect("..."))
            },
            3 => ASN1Type::BitString(raw),
            4 => ASN1Type::OctetString(raw),
            19 => ASN1Type::PrintableString(String::from_utf8(raw).unwrap()),
            23 => ASN1Type::UTCTime(String::from_utf8(raw).unwrap()),
            12 => ASN1Type::UTF8String(String::from_utf8(raw).unwrap()),
            _ => {
                println!("Got Unknown ASN1 Type {} {} {} {}", class_bits, constructed, tag, length);
                ASN1Type::Unknown
            }
        };

        Ok(entry)
    }
}
<commit_msg>Further work on ASN1 parser.<commit_after>//! Simple parsing of ASN.1 DER

use timmy::tup::*;

use num::bigint::{BigInt, Sign};

#[derive(Debug)]
pub enum ASN1Error {
    MissingData(String),
}

pub type ASN1Result<T> = Result<T, ASN1Error>;

#[derive(Debug)]
pub enum ASN1Type {
    Unknown,
    Cont(u8, Box<ASN1Type>),
    Null,
    Boolean(bool),
    Sequence(Vec<ASN1Type>),
    Set(Vec<ASN1Type>),
    Object(TupT<u32>),
    Integer(BigInt),
    BitString(Vec<u8>),
    OctetString(Vec<u8>),
    PrintableString(String),
    UTF8String(String),
    UTCTime(String),
}

pub fn asn1_to_raw_string(obj: &ASN1Type) -> Option<String> {
    match obj {
        &ASN1Type::PrintableString(ref string) => Some(string.clone()),
        &ASN1Type::UTF8String(ref string) => Some(string.clone()),
        _ => None,
    }
}

pub fn asn1_to_raw_integer(obj: &ASN1Type) -> Option<BigInt> {
    match obj {
        &ASN1Type::Integer(ref bigint) => Some(bigint.clone()),
        _ => None,
    }
}

pub struct DerParser {
    buf: Vec<u8>,
    idx: usize,
}

impl DerParser {
    pub fn new(der: &Vec<u8>) -> DerParser {
        DerParser {
            buf: der.clone(),
            idx: 0,
        }
    }

    fn check_buffer(&mut self) -> ASN1Result<()> {
        if self.idx >= self.buf.len() {
            return Err(ASN1Error::MissingData("length".to_string()));
        }
        Ok(())
    }

    fn get_length(&mut self) -> ASN1Result<usize> {
        try!(self.check_buffer());

        let len_tmp = self.buf[self.idx];
        if len_tmp <= 127 {
            self.idx += 1;
            return Ok(len_tmp as usize);
        }

        let len_octets = len_tmp & 127;
        assert!(len_octets <= 3);
        let mut length = 0 as usize;
        self.idx += 1;
        for _ in 0..len_octets {
            length <<= 8;
            try!(self.check_buffer());
            length |= self.buf[self.idx] as usize;
            self.idx += 1;
        }
        Ok(length)
    }

    fn parse_header(&mut self) -> ASN1Result<(u8, bool, u8, usize)> {
        try!(self.check_buffer());

        let c = self.buf[self.idx];
        let tag = c & 31;
        let p_c = (c >> 5) & 1;
        let class_ = (c >> 6) & 3;
        assert!(tag != 31);
        self.idx += 1;
        let length = try!(self.get_length());

        Ok((class_ as u8, p_c == 1, tag as u8, length as usize))
    }

    pub fn parse_entry(&mut self) -> ASN1Result<ASN1Type> {
        try!(self.check_buffer());

        let (class_bits, constructed, tag, length) = try!(self.parse_header());

        assert!(class_bits == 0 || class_bits == 2);

        match class_bits {
            0 => {
            }
            2 => {
                let pos = self.idx;
                self.idx += length;

                assert!(pos + length <= self.buf.len());

                let sub_buf = self.buf[pos..pos+length].iter().cloned().collect();
                let mut sub_parser = DerParser::new(&sub_buf);
                let sub_entry = try!(sub_parser.parse_entry());
                return Ok(ASN1Type::Cont(tag, Box::new(sub_entry)));
            }
            _ => {
                panic!("Parsing this not implemented.");
            }
        }

        let pos = self.idx;
        self.idx += length;

        assert!(pos + length <= self.buf.len());

        let raw = self.buf[pos..pos+length].iter().cloned().collect();

        let entry = match tag {
            5 => ASN1Type::Null,
            1 => {
                let buf: Vec<u8> = raw;
                ASN1Type::Boolean(buf[0] == 0xff)
            }
            16 => {
                let mut sub_parser = DerParser::new(&raw);
                let mut sequence = Vec::<ASN1Type>::new();
                loop {
                    let sub_ent = sub_parser.parse_entry();
                    match sub_ent {
                        Err(ASN1Error::MissingData(_)) => { break },
                        Ok(ent) => { sequence.push(ent) }
                    }
                }
                ASN1Type::Sequence(sequence)
            },
            17 => {
                let mut sub_parser = DerParser::new(&raw);
                let mut sequence = Vec::<ASN1Type>::new();
                loop {
                    let sub_ent = sub_parser.parse_entry();
                    match sub_ent {
                        Err(ASN1Error::MissingData(_)) => { break },
                        Ok(ent) => { sequence.push(ent) }
                    }
                }
                ASN1Type::Set(sequence)
            },
            2 => ASN1Type::Integer(BigInt::from_bytes_be(Sign::Plus, &raw)),
            6 => {
                let mut oi = Vec::<u32>::new();
                let obj_bytes = raw;
                oi.push((obj_bytes[0] / 40) as u32);
                oi.push((obj_bytes[0] % 40) as u32);
                let mut i = 1;
                while i < obj_bytes.len() {
                    if obj_bytes[i] <= 127 {
                        oi.push(obj_bytes[i] as u32);
                        i += 1;
                    } else {
                        let mut next_sub_id: u32 = obj_bytes[i] as u32;
                        let mut sub_id: u32 = 0;
                        i += 1;
                        while next_sub_id > 127 {
                            sub_id <<= 7;
                            sub_id |= next_sub_id & 127;
                            next_sub_id = obj_bytes[i] as u32;
                            i += 1;
                        }
                        oi.push((sub_id << 7) | next_sub_id);
                    }
                }
                ASN1Type::Object(vec_to_tup(&oi).expect("..."))
            },
            3 => ASN1Type::BitString(raw),
            4 => ASN1Type::OctetString(raw),
            19 => ASN1Type::PrintableString(String::from_utf8(raw).unwrap()),
            23 => ASN1Type::UTCTime(String::from_utf8(raw).unwrap()),
            12 => ASN1Type::UTF8String(String::from_utf8(raw).unwrap()),
            _ => {
                println!("Got Unknown ASN1 Type {} {} {} {}", class_bits, constructed, tag, length);
                ASN1Type::Unknown
            }
        };

        Ok(entry)
    }
}
<|endoftext|>


<commit_before>use std::sync::mpsc::{channel, Receiver, Sender};
use std::net::TcpStream;
use std::io::{Read, Write};
use std::sync::{Arc, RwLock};
use std::io;
use std::thread;

pub enum NeedsAck {
    Yes,
    No,
}

#[derive(Copy, Clone, PartialEq)]
pub enum State {
    Disconnected,
    Connected,
    SendingData,
    WaitingForData,
    Close,
}

pub struct GdbRemote {
    pub needs_ack: NeedsAck,
    pub writer: Sender<Vec<u8>>,
    pub reader: Receiver<Vec<u8>>,
    temp_data: Vec<u8>,
    state: Arc<RwLock<State>>,
}

pub struct Memory {
    pub address: u64,
    pub data: Vec<u8>
}

static HEX_CHARS: &'static [u8; 16] = b"0123456789abcdef";

impl GdbRemote {
    pub fn new(needs_ack: NeedsAck) -> GdbRemote {
        let (tx, rx) = channel::<Vec<u8>>();

        GdbRemote {
            writer: tx,
            reader: rx,
            needs_ack: needs_ack,
            temp_data: Vec::new(),
            state: Arc::new(RwLock::new(State::Disconnected)),
        }
    }

    fn read_write_data(reader: &Receiver<Vec<u8>>, writer: &Sender<Vec<u8>>, stream: &mut TcpStream) -> io::Result<()> {
        match reader.recv() {
            Ok(data) => {
                // TODO: Less allocs
                let mut buffer = [0; 1024];
                let mut t = Vec::new();
                try!(stream.write_all(&data.into_boxed_slice()));
                let len = try!(stream.read(&mut buffer));
                for i in 0..len { t.push(buffer[i]); }
                match writer.send(t) {
                    Ok(()) => Ok(()),
                    Err(_) => Err(io::Error::new(io::ErrorKind::Other, "channel write failed")),
                }
            }

            Err(_) => Err(io::Error::new(io::ErrorKind::Other, "channel reade error")),
        }
    }

    fn set_state(&mut self, state: State) {
        *(*self.state).write().unwrap() = state
    }

    pub fn connect(&mut self, addr: &str) -> io::Result<()> {
        let mut stream = try!(TcpStream::connect(addr));

        self.set_state(State::Connected);

        let (main_tx, main_rx) = channel::<Vec<u8>>();
        let (thread_tx, thread_rx) = channel::<Vec<u8>>();

        self.writer = main_tx;
        self.reader = thread_rx;

        let state = self.state.clone();

        thread::spawn(move || {
            loop {
                match Self::read_write_data(&main_rx, &thread_tx, &mut stream) {
                    Err(e) => {
                        *(*state).write().unwrap() = State::Disconnected;
                        println!("Error reading/sending data {:?}", e);
                        break;
                    }

                    _ => (),
                }
            }
        });

        Ok(())
    }

    pub fn update(&mut self) {
        match self.reader.try_recv() {
            Ok(data) => {
                println!("got data {}", String::from_utf8(data).unwrap());
            }

            _ => (),
        }
    }

    #[inline]
    fn calc_checksum(data: &[u8]) -> u8 {
        let mut checksum = 0u32;
        for i in data {
            checksum += *i as u32;
        }
        (checksum & 0xff) as u8
    }

    #[inline]
    pub fn get_checksum_array(checksum: u8) -> [u8; 2] {
        let cs_string: [u8; 2] = [HEX_CHARS[((checksum >> 4) & 0xf) as usize],
                                  HEX_CHARS[(checksum & 0xf) as usize]];
        cs_string
    }

    pub fn get_processed_string(data: &str) -> String {
        let checksum = Self::calc_checksum(data.as_bytes());
        let cs_array = Self::get_checksum_array(checksum);

        // len + 4 = # <string> $xx (4 bytes extra needed)
        let mut gdb_string = String::with_capacity(data.len() + 4);

        gdb_string.push('$');
        gdb_string.push_str(data);
        gdb_string.push('#');
        gdb_string.push(cs_array[0] as char);
        gdb_string.push(cs_array[1] as char);

        gdb_string
    }

    pub fn send_command(&mut self, data: &str) -> io::Result<usize> {
        let command = Self::get_processed_string(data);
        self.send_command_raw(&command)
    }

    pub fn send_command_raw(&mut self, data: &str) -> io::Result<usize> {
        // TEMP fix me:
        self.temp_data.clear();
        for i in data.as_bytes().iter() { self.temp_data.push(*i) }
        let _ = self.writer.send(self.temp_data.clone());
        Ok((0))
    }

    fn get_state(&mut self) -> State {
        *(*self.state).read().unwrap()
    }

    pub fn send_no_ack_request(&mut self)-> io::Result<usize> {
        self.send_command_raw("+$QStartNoAckMode+#db")
    }

    fn from_hex(ch: u8) -> u8 {
        if (ch >= b'a') && (ch <= b'f') {
            return ch - b'a' + 10;
        }

        if (ch >= b'0') && (ch <= b'9') {
            return ch - b'0';
        }

        if (ch >= b'A') && (ch <= b'F') {
            return ch - b'A' + 10;
        }

        return 0;
    }

    pub fn get_data_sync(&mut self) -> Option<Vec<u8>> {
        match self.reader.recv() {
            Ok(data) => {
                self.temp_data.clear();
                for i in &data { self.temp_data.push(*i) }
                Some(self.temp_data.clone())
            }

            Err(_) => None,
        }
    }

    pub fn send_command_sync(&mut self, command: &str) -> Option<Vec<u8>> {
        if self.get_state() == State::Connected {
            self.send_command(command).unwrap();
            println!("waiting for data");
            let data = self.get_data_sync();
            println!("got data {}", data.as_ref().unwrap().len());
            data
        } else {
            None
        }
    }

    pub fn step_sync(&mut self) -> Option<Vec<u8>> {
        self.send_command_sync("s")
    }

    pub fn get_registers_sync(&mut self) -> Option<Vec<u8>> {
        self.send_command_sync("g")
    }

    // TODO: 64-bit addresses
    pub fn get_memory_sync(&mut self, address: u32, size: u32) -> Option<Memory> {
        let mem_req = format!("m{:x},{:x}", address, size);

        if let Some(data) = self.send_command_sync(&mem_req) {
            let mut memory = Vec::with_capacity((data.len() - 2) / 2);
            let mut index = 1;

            for _ in 0..((data.len() - 2) / 2) {
                let v0 = data[index + 0];
                let v1 = data[index + 1];
                let v = (Self::from_hex(v0) << 4) | (Self::from_hex(v1));
                memory.push(v);
                index += 2;
            }

            Some(Memory {
                address: address as u64,
                data: memory,
            })
        } else {
            None
        }
    }
}

#[test]
fn test_checksum_calc() {
    let data: [u8; 8] = [32, 32, 32, 32, 64, 64, 64, 64];
    assert_eq!(GdbRemote::calc_checksum(&data), 128);
}

#[test]
fn test_process_string() {
    assert_eq!(GdbRemote::get_processed_string("f"), "$f#66");
}

<commit_msg>Removed unused code<commit_after><|endoftext|>


<commit_before>//! A reimplementation of dcmdump in Rust
//! WIP
extern crate dicom_core;

use dicom_core::{DicomElement, DicomObject};
use std::fs::File;
use std::path::Path;

fn main() {
    println!("Sorry, this tool is not implemented yet.");
}

fn dump<P: AsRef<Path>>(path: P) {
    let file = File::open(path).unwrap();
    //let obj = DicomLoader.load(file).unwrap();

    //for elem in obj {
    //    dump_element(&elem);
    //}
}

fn dump_element(elem: &DicomElement) {}
<commit_msg>Update dump.rs for CI to pass<commit_after>//! A reimplementation of dcmdump in Rust
//! WIP
extern crate dicom_core;

use dicom_core::{DicomElement, DicomObject};
use std::fs::File;
use std::path::Path;

fn main() {
    println!("Sorry, this tool is not implemented yet.");
}

fn dump<P: AsRef<Path>>(path: P) {
    let file = File::open(path).unwrap();
    //let obj = DicomLoader.load(file).unwrap();

    //for elem in obj {
    //    dump_element(&elem);
    //}
}
<|endoftext|>