<commit_before>extern crate getopts;
use getopts::Options;
use std::env;
use std::fs::File;
use std::io;
use std::io::Read;

fn read_blend_file(inp: &str) -> io::Result<()> {
    // open file
    let file = try!(File::open(inp));
    // read 12 bytes from the Blender file
    let mut take = file.take(12u64);
    let mut header = String::new();
    try!(take.read_to_string(&mut header));
    println!("header = \"{}\"", header);
    // compare first 7 chars to "BLENDER"
    if header.len() >= 7 {
        // create copy of header without moving value
        let mut blender = String::new();
        blender = blender + &header;
        blender.truncate(7); // first 7 chars
        if blender == "BLENDER" {
            println!("starts with \"BLENDER\" ...");
            // TODO: check version (next 5 chars in header)

            // switch to byte copy of String representation
            let bytes = header.into_bytes();
            // check 7th char of header
            println!("7th char of header = '{}'", bytes[7] as char);
            // TODO: check for 32-bit pointers vs. 64-bit pointers
        }
    } else {
        println!("WARNING: FILE is not a Blender file");
    }
    Ok(())
}

fn do_work(inp: &str, out: Option<String>) {
    println!("FILE = {}", inp);
    match out {
        Some(x) => println!("output file name: {}", x),
        None => println!("no output file name"),
    }
    read_blend_file(inp);
}

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} FILE [options]", program);
    print!("{}", opts.usage(&brief));
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();

    let mut opts = Options::new();
    opts.optopt("o", "", "set output file name", "NAME");
    opts.optflag("h", "help", "print this help menu");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => { panic!(f.to_string()) }
    };
    if matches.opt_present("h") {
        print_usage(&program, opts);
        return;
    }
    let output = matches.opt_str("o");
    let input = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        print_usage(&program, opts);
        return;
    };
    do_work(&input, output);
}
<commit_msg>Detect 32- vs. 64-bit platform and which pointer size we expect in file.<commit_after>extern crate getopts;
use getopts::Options;
use std::env;
use std::fs::File;
use std::io;
use std::io::Read;
use std::mem;

fn pointer_size() -> usize {
    let tmp = 0u8;
    let boxed = Box::new(tmp);
    mem::size_of_val(&boxed)
}

fn read_blend_file(inp: &str) -> io::Result<()> {
    // open file
    let file = try!(File::open(inp));
    // read 12 bytes from the Blender file
    let mut take = file.take(12u64);
    let mut header = String::new();
    try!(take.read_to_string(&mut header));
    println!("header = \"{}\"", header);
    // compare first 7 chars to "BLENDER"
    if header.len() >= 7 {
        // create copy of header without moving value
        let mut blender = String::new();
        blender = blender + &header;
        blender.truncate(7); // first 7 chars
        if blender == "BLENDER" {
            println!("starts with \"BLENDER\" ...");
            // TODO: check version (next 5 chars in header)

            // switch to byte copy of String representation
            let bytes = header.into_bytes();
            // check 7th char of header
            println!("7th char of header = '{}'", bytes[7] as char);
            // check for 32-bit pointers vs. 64-bit pointers
            let ptr_size = pointer_size();
            println!("size of pointer in bytes: {}", ptr_size);
            let mut ptr_size_differs = false;
            if bytes[7] as char == '_' {
                // 32-bit pointers expected
                if ptr_size != 4 {
                    ptr_size_differs = true;
                }
                println!("32-bit pointers in file, pointer size differs? {}",
                         ptr_size_differs);
            } else {
                // 64-bit pointers expected
                if ptr_size != 8 {
                        ptr_size_differs = true;
                }
                println!("64-bit pointers in file, pointer size differs? {}",
                         ptr_size_differs);
            }
        }
    } else {
        println!("WARNING: FILE is not a Blender file");
    }
    Ok(())
}

fn do_work(inp: &str, out: Option<String>) {
    println!("FILE = {}", inp);
    match out {
        Some(x) => println!("output file name: {}", x),
        None => println!("no output file name"),
    }
    read_blend_file(inp);
}

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} FILE [options]", program);
    print!("{}", opts.usage(&brief));
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();

    let mut opts = Options::new();
    opts.optopt("o", "", "set output file name", "NAME");
    opts.optflag("h", "help", "print this help menu");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => { panic!(f.to_string()) }
    };
    if matches.opt_present("h") {
        print_usage(&program, opts);
        return;
    }
    let output = matches.opt_str("o");
    let input = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        print_usage(&program, opts);
        return;
    };
    do_work(&input, output);
}
<|endoftext|>


<commit_before>// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(lang_items, start, compiler_builtins_lib)]
#![no_std]

extern crate libc;
extern crate compiler_builtins;

#[start]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
    0
}

#[lang = "eh_personality"]
#[no_mangle]
pub extern fn rust_eh_personality() {}

#[lang = "eh_unwind_resume"]
#[no_mangle]
pub extern fn rust_eh_unwind_resume() {}

#[lang = "panic_fmt"]
#[no_mangle]
pub extern fn rust_begin_panic(_msg: core::fmt::Arguments,
                               _file: &'static str,
                               _line: u32) -> ! {
    unsafe {
        libc::abort()
    }
}

//////////////////////////////////////////////////////////////////////////////

#[macro_use]
extern crate serde_derive;

#[derive(Serialize, Deserialize)]
struct Unit;

#[derive(Serialize, Deserialize)]
struct Newtype(u8);

#[derive(Serialize, Deserialize)]
struct Tuple(u8, u8);

#[derive(Serialize, Deserialize)]
struct Struct { f: u8 }

#[derive(Serialize, Deserialize)]
enum Enum {
    Unit,
    Newtype(u8),
    Tuple(u8, u8),
    Struct { f: u8 },
}
<commit_msg>Ignore warning in no_std test<commit_after>// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(lang_items, start, compiler_builtins_lib)]
#![no_std]

// https://github.com/rust-lang/rust/issues/47311
#![cfg_attr(feature = "cargo-clippy", allow(double_parens))]

extern crate libc;
extern crate compiler_builtins;

#[start]
fn start(_argc: isize, _argv: *const *const u8) -> isize {
    0
}

#[lang = "eh_personality"]
#[no_mangle]
pub extern fn rust_eh_personality() {}

#[lang = "eh_unwind_resume"]
#[no_mangle]
pub extern fn rust_eh_unwind_resume() {}

#[lang = "panic_fmt"]
#[no_mangle]
pub extern fn rust_begin_panic(_msg: core::fmt::Arguments,
                               _file: &'static str,
                               _line: u32) -> ! {
    unsafe {
        libc::abort()
    }
}

//////////////////////////////////////////////////////////////////////////////

#[macro_use]
extern crate serde_derive;

#[derive(Serialize, Deserialize)]
struct Unit;

#[derive(Serialize, Deserialize)]
struct Newtype(u8);

#[derive(Serialize, Deserialize)]
struct Tuple(u8, u8);

#[derive(Serialize, Deserialize)]
struct Struct { f: u8 }

#[derive(Serialize, Deserialize)]
enum Enum {
    Unit,
    Newtype(u8),
    Tuple(u8, u8),
    Struct { f: u8 },
}
<|endoftext|>


<commit_before>use lsp_types::{Diagnostic, DiagnosticSeverity, Position, Url};

use crate::{
    compiler::error::CompilerError,
    database::Database,
    input::{Input, InputReference},
};

impl CompilerError {
    pub fn to_diagnostic(self, db: &Database, input_reference: InputReference) -> Diagnostic {
        Diagnostic {
            range: lsp_types::Range {
                start: db
                    .utf8_byte_offset_to_lsp(self.span.start, input_reference.clone())
                    .to_position(),
                end: db
                    .utf8_byte_offset_to_lsp(self.span.end, input_reference)
                    .to_position(),
            },
            severity: Some(DiagnosticSeverity::ERROR),
            code: None,
            code_description: None,
            source: Some("🍭 Candy".to_owned()),
            message: self.message,
            related_information: None,
            tags: None,
            data: None,
        }
    }
}

impl From<Url> for InputReference {
    fn from(uri: Url) -> InputReference {
        match uri.scheme() {
            "file" => InputReference::File(uri.to_file_path().unwrap()),
            "untitled" => InputReference::Untitled(uri.to_string()["untitled:".len()..].to_owned()),
            _ => panic!("Unsupported URI scheme: {}", uri.scheme()),
        }
    }
}

impl From<InputReference> for Url {
    fn from(input_reference: InputReference) -> Url {
        match input_reference {
            InputReference::File(path) => Url::from_file_path(path).unwrap(),
            InputReference::Untitled(id) => Url::parse(&format!("untitled:{}", id)).unwrap(),
        }
    }
}

// UTF-8 Byte Offset ↔ LSP Position/Range

#[salsa::query_group(LspPositionConversionStorage)]
pub trait LspPositionConversion: Input {
    // `lsp_types::Range` and `::Position` don't implement `Hash`, so they can't be
    // used as query keys directly.
    fn position_to_utf8_byte_offset(
        &self,
        line: u32,
        character: u32,
        input_reference: InputReference,
    ) -> usize;
    fn utf8_byte_offset_to_lsp(
        &self,
        position: usize,
        input_reference: InputReference,
    ) -> (u32, u32);

    fn line_start_utf8_byte_offsets(&self, input_reference: InputReference) -> Vec<usize>;
}

fn position_to_utf8_byte_offset(
    db: &dyn LspPositionConversion,
    line: u32,
    character: u32,
    input_reference: InputReference,
) -> usize {
    let text = db.get_input(input_reference.clone()).unwrap();
    let line_start_offsets = db.line_start_utf8_byte_offsets(input_reference);

    let line_offset = line_start_offsets[line as usize];
    let line_length = if line as usize == line_start_offsets.len() - 1 {
        text.len()
    } else {
        line_start_offsets[(line + 1) as usize] - line_offset
    };

    let line = &text[line_offset..line_offset + line_length];

    let words = line.encode_utf16().collect::<Vec<_>>();
    let char_offset = if character as usize >= words.len() {
        line_length
    } else {
        String::from_utf16(&words[0..character as usize])
            .unwrap()
            .len()
    };

    line_offset + char_offset
}

fn utf8_byte_offset_to_lsp(
    db: &dyn LspPositionConversion,
    offset: usize,
    input_reference: InputReference,
) -> (u32, u32) {
    let text = db.get_input(input_reference.clone()).unwrap();
    let line_start_offsets = db.line_start_utf8_byte_offsets(input_reference);

    let line = line_start_offsets
        .binary_search(&offset)
        .unwrap_or_else(|i| i - 1);

    let line_start = line_start_offsets[line];
    let character_utf16_offset = text[line_start..offset.to_owned()].encode_utf16().count();
    (line as u32, character_utf16_offset as u32)
}

pub trait TupleToPosition {
    fn to_position(&self) -> Position;
}
impl TupleToPosition for (u32, u32) {
    fn to_position(&self) -> Position {
        Position {
            line: self.0,
            character: self.1,
        }
    }
}

fn line_start_utf8_byte_offsets(
    db: &dyn LspPositionConversion,
    input_reference: InputReference,
) -> Vec<usize> {
    let text = db.get_input(input_reference).unwrap();
    let mut offsets = vec![0];
    offsets.append(
        &mut text
            .bytes()
            .enumerate()
            .filter(|(_, it)| it == &b'\n')
            .map(|(index, _)| index + 1)
            .collect(),
    );
    offsets
}
<commit_msg>perf(compiler): don't cache LSP position conversion results<commit_after>use lsp_types::{Diagnostic, DiagnosticSeverity, Position, Url};

use crate::{
    compiler::error::CompilerError,
    database::Database,
    input::{Input, InputReference},
};

impl CompilerError {
    pub fn to_diagnostic(self, db: &Database, input_reference: InputReference) -> Diagnostic {
        Diagnostic {
            range: lsp_types::Range {
                start: db
                    .utf8_byte_offset_to_lsp(self.span.start, input_reference.clone())
                    .to_position(),
                end: db
                    .utf8_byte_offset_to_lsp(self.span.end, input_reference)
                    .to_position(),
            },
            severity: Some(DiagnosticSeverity::ERROR),
            code: None,
            code_description: None,
            source: Some("🍭 Candy".to_owned()),
            message: self.message,
            related_information: None,
            tags: None,
            data: None,
        }
    }
}

impl From<Url> for InputReference {
    fn from(uri: Url) -> InputReference {
        match uri.scheme() {
            "file" => InputReference::File(uri.to_file_path().unwrap()),
            "untitled" => InputReference::Untitled(uri.to_string()["untitled:".len()..].to_owned()),
            _ => panic!("Unsupported URI scheme: {}", uri.scheme()),
        }
    }
}

impl From<InputReference> for Url {
    fn from(input_reference: InputReference) -> Url {
        match input_reference {
            InputReference::File(path) => Url::from_file_path(path).unwrap(),
            InputReference::Untitled(id) => Url::parse(&format!("untitled:{}", id)).unwrap(),
        }
    }
}

// UTF-8 Byte Offset ↔ LSP Position/Range

#[salsa::query_group(LspPositionConversionStorage)]
pub trait LspPositionConversion: Input {
    // `lsp_types::Range` and `::Position` don't implement `Hash`, so they can't
    // be used as query keys directly.
    //
    // As its unlikely that a conversion is called multiple times with the same
    // key, we shouldn't loose much performance by not caching the individual
    // results.
    #[salsa::transparent]
    fn position_to_utf8_byte_offset(
        &self,
        line: u32,
        character: u32,
        input_reference: InputReference,
    ) -> usize;
    #[salsa::transparent]
    fn utf8_byte_offset_to_lsp(
        &self,
        position: usize,
        input_reference: InputReference,
    ) -> (u32, u32);

    fn line_start_utf8_byte_offsets(&self, input_reference: InputReference) -> Vec<usize>;
}

fn position_to_utf8_byte_offset(
    db: &dyn LspPositionConversion,
    line: u32,
    character: u32,
    input_reference: InputReference,
) -> usize {
    let text = db.get_input(input_reference.clone()).unwrap();
    let line_start_offsets = db.line_start_utf8_byte_offsets(input_reference);

    let line_offset = line_start_offsets[line as usize];
    let line_length = if line as usize == line_start_offsets.len() - 1 {
        text.len()
    } else {
        line_start_offsets[(line + 1) as usize] - line_offset
    };

    let line = &text[line_offset..line_offset + line_length];

    let words = line.encode_utf16().collect::<Vec<_>>();
    let char_offset = if character as usize >= words.len() {
        line_length
    } else {
        String::from_utf16(&words[0..character as usize])
            .unwrap()
            .len()
    };

    line_offset + char_offset
}

fn utf8_byte_offset_to_lsp(
    db: &dyn LspPositionConversion,
    offset: usize,
    input_reference: InputReference,
) -> (u32, u32) {
    let text = db.get_input(input_reference.clone()).unwrap();
    let line_start_offsets = db.line_start_utf8_byte_offsets(input_reference);

    let line = line_start_offsets
        .binary_search(&offset)
        .unwrap_or_else(|i| i - 1);

    let line_start = line_start_offsets[line];
    let character_utf16_offset = text[line_start..offset.to_owned()].encode_utf16().count();
    (line as u32, character_utf16_offset as u32)
}

pub trait TupleToPosition {
    fn to_position(&self) -> Position;
}
impl TupleToPosition for (u32, u32) {
    fn to_position(&self) -> Position {
        Position {
            line: self.0,
            character: self.1,
        }
    }
}

fn line_start_utf8_byte_offsets(
    db: &dyn LspPositionConversion,
    input_reference: InputReference,
) -> Vec<usize> {
    let text = db.get_input(input_reference).unwrap();
    let mut offsets = vec![0];
    offsets.append(
        &mut text
            .bytes()
            .enumerate()
            .filter(|(_, it)| it == &b'\n')
            .map(|(index, _)| index + 1)
            .collect(),
    );
    offsets
}
<|endoftext|>


<commit_before>
// This is a bit of a nightmare

use std::fmt;
use std::marker::PhantomData;
use serde::{Serialize, Deserialize, Serializer, Deserializer};
use serde::ser::SerializeTuple;
use serde::de::{Visitor, SeqAccess, Error};

use quat::Quaternion;
use vec::{Vec2, Vec3, Vec4};
use mat::{Mat3, Mat4};

impl<T: Serialize> Serialize for Vec2<T> {
    fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
        let mut tuple = s.serialize_tuple(2)?;
        tuple.serialize_element(&self.x)?;
        tuple.serialize_element(&self.y)?;
        tuple.end()
    }
}

impl<T: Serialize> Serialize for Vec3<T> {
    fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
        let mut tuple = s.serialize_tuple(3)?;
        tuple.serialize_element(&self.x)?;
        tuple.serialize_element(&self.y)?;
        tuple.serialize_element(&self.z)?;
        tuple.end()
    }
}

impl<T: Serialize> Serialize for Vec4<T> {
    fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
        let mut tuple = s.serialize_tuple(4)?;
        tuple.serialize_element(&self.x)?;
        tuple.serialize_element(&self.y)?;
        tuple.serialize_element(&self.z)?;
        tuple.serialize_element(&self.w)?;
        tuple.end()
    }
}

impl<T: Serialize> Serialize for Quaternion<T>
    where T: Num + Float + Copy,
{
    fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
        let mut tuple = s.serialize_tuple(4)?;
        tuple.serialize_element(&self.x)?;
        tuple.serialize_element(&self.y)?;
        tuple.serialize_element(&self.z)?;
        tuple.serialize_element(&self.w)?;
        tuple.end()
    }
}

impl<T: Serialize> Serialize for Mat4<T> {
    fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
        let mut tuple = s.serialize_tuple(16)?;
        tuple.serialize_element(&self.a11)?;
        tuple.serialize_element(&self.a12)?;
        tuple.serialize_element(&self.a13)?;
        tuple.serialize_element(&self.a14)?;
        tuple.serialize_element(&self.a21)?;
        tuple.serialize_element(&self.a22)?;
        tuple.serialize_element(&self.a23)?;
        tuple.serialize_element(&self.a24)?;
        tuple.serialize_element(&self.a31)?;
        tuple.serialize_element(&self.a32)?;
        tuple.serialize_element(&self.a33)?;
        tuple.serialize_element(&self.a34)?;
        tuple.serialize_element(&self.a41)?;
        tuple.serialize_element(&self.a42)?;
        tuple.serialize_element(&self.a43)?;
        tuple.serialize_element(&self.a44)?;
        tuple.end()
    }
}

impl<T: Serialize> Serialize for Mat3<T> {
    fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
        let mut tuple = s.serialize_tuple(9)?;
        tuple.serialize_element(&self.a11)?;
        tuple.serialize_element(&self.a12)?;
        tuple.serialize_element(&self.a13)?;
        tuple.serialize_element(&self.a21)?;
        tuple.serialize_element(&self.a22)?;
        tuple.serialize_element(&self.a23)?;
        tuple.serialize_element(&self.a31)?;
        tuple.serialize_element(&self.a32)?;
        tuple.serialize_element(&self.a33)?;
        tuple.end()
    }
}

impl<'de, T: Deserialize<'de>> Deserialize<'de> for Vec2<T> {
    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
        d.deserialize_tuple(2, Vec2Visitor::new())
    }
}

impl<'de, T: Deserialize<'de>> Deserialize<'de> for Vec3<T> {
    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
        d.deserialize_tuple(3, Vec3Visitor::new())
    }
}

impl<'de, T: Deserialize<'de>> Deserialize<'de> for Vec4<T> {
    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
        d.deserialize_tuple(4, Vec4Visitor::new())
    }
}

impl<'de, T> Deserialize<'de> for Quaternion<T>
    where T: Deserialize<'de>,
          T: Num + Float + Copy,
{
    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
        d.deserialize_tuple(4, QuaternionVisitor::new())
    }
}

impl<'de, T: Deserialize<'de>> Deserialize<'de> for Mat4<T>
    where T: Deserialize<'de>,
          T: Num + Float + Copy,
{
    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
        d.deserialize_tuple(16, Mat4Visitor::new())
    }
}

impl<'de, T: Deserialize<'de>> Deserialize<'de> for Mat3<T>
    where T: Deserialize<'de>,
          T: Num + Float + Copy,
{
    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
        d.deserialize_tuple(9, Mat3Visitor::new())
    }
}

struct Vec2Visitor<T>(PhantomData<T>);
impl<T> Vec2Visitor<T> {
    fn new() -> Self { Vec2Visitor(PhantomData) }
}
impl<'de, T: Deserialize<'de>> Visitor<'de> for Vec2Visitor<T> {
    type Value = Vec2<T>;

    fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("A sequence of length 2")
    }

    fn visit_seq<A>(self, mut a: A) -> Result<Self::Value, A::Error>
        where A: SeqAccess<'de>,
    {
        let x: Option<T> = a.next_element()?;
        let y: Option<T> = a.next_element()?;
        let z: Option<T> = a.next_element()?;

        match (x, y, z) {
            (Some(x), Some(y), None) =>     Ok(Vec2::new(x, y)),
            (Some(_), None, None) =>        Err(A::Error::invalid_length(1, &"Sequence of length 2")),
            (Some(_), Some(_), Some(_)) =>  Err(A::Error::invalid_length(3, &"Sequence of length 2")),
            _ =>                            Err(A::Error::custom("Expected array of length 2, found nothing")),
        }
    }
}

struct Vec3Visitor<T>(PhantomData<T>);
impl<T> Vec3Visitor<T> {
    fn new() -> Self { Vec3Visitor(PhantomData) }
}
impl<'de, T: Deserialize<'de>> Visitor<'de> for Vec3Visitor<T> {
    type Value = Vec3<T>;

    fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("A sequence of length 3")
    }

    fn visit_seq<A>(self, mut a: A) -> Result<Self::Value, A::Error>
        where A: SeqAccess<'de>,
    {
        let x: Option<T> = a.next_element()?;
        let y: Option<T> = a.next_element()?;
        let z: Option<T> = a.next_element()?;
        let w: Option<T> = a.next_element()?;

        match (x, y, z, w) {
            (Some(x), Some(y), Some(z), None) =>    Ok(Vec3::new(x, y, z)),
            (Some(_), None, None, None) =>          Err(A::Error::invalid_length(1, &"Sequence of length 3")),
            (Some(_), Some(_), None, None) =>       Err(A::Error::invalid_length(2, &"Sequence of length 3")),
            (Some(_), Some(_), Some(_), Some(_)) => Err(A::Error::invalid_length(4, &"Sequence of length 3")),
            _ =>                                    Err(A::Error::custom("Expected array of length 3, found nothing")),
        }
    }
}

struct Vec4Visitor<T>(PhantomData<T>);
impl<T> Vec4Visitor<T> {
    fn new() -> Self { Vec4Visitor(PhantomData) }
}
impl<'de, T: Deserialize<'de>> Visitor<'de> for Vec4Visitor<T> {
    type Value = Vec4<T>;

    fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("A sequence of length 4")
    }

    fn visit_seq<A>(self, mut a: A) -> Result<Self::Value, A::Error>
        where A: SeqAccess<'de>,
    {
        let x: Option<T> = a.next_element()?;
        let y: Option<T> = a.next_element()?;
        let z: Option<T> = a.next_element()?;
        let w: Option<T> = a.next_element()?;
        let q: Option<T> = a.next_element()?;

        match (x, y, z, w, q) {
            (Some(x), Some(y), Some(z), Some(w), None) =>       Ok(Vec4::new(x, y, z, w)),
            (Some(_), None, None, None, None) =>                Err(A::Error::invalid_length(1, &"Sequence of length 4")),
            (Some(_), Some(_), None, None, None) =>             Err(A::Error::invalid_length(2, &"Sequence of length 4")),
            (Some(_), Some(_), Some(_), None, None) =>          Err(A::Error::invalid_length(3, &"Sequence of length 4")),
            (Some(_), Some(_), Some(_), Some(_), Some(_)) =>    Err(A::Error::invalid_length(5, &"Sequence of length 4")),
            _ =>                                                Err(A::Error::custom("Expected array of length 4, found nothing")),
        }
    }
}

struct QuaternionVisitor<T>(PhantomData<T>);
impl<T> QuaternionVisitor<T>
    where T: Num + Float + Copy,
{
    fn new() -> Self { QuaternionVisitor(PhantomData) }
}

impl<'de, T: Deserialize<'de>> Visitor<'de> for QuaternionVisitor<T>
    where T: Deserialize<'de>,
          T: Num + Float + Copy,
{
    type Value = Quaternion<T>;

    fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("A sequence of length 4")
    }

    fn visit_seq<A>(self, mut a: A) -> Result<Self::Value, A::Error>
        where A: SeqAccess<'de>,
    {
        let x: Option<T> = a.next_element()?;
        let y: Option<T> = a.next_element()?;
        let z: Option<T> = a.next_element()?;
        let w: Option<T> = a.next_element()?;
        let q: Option<T> = a.next_element()?;

        match (x, y, z, w, q) {
            (Some(x), Some(y), Some(z), Some(w), None) =>       Ok(Quaternion { x: x, y: y, z: z, w: w }),
            (Some(_), None, None, None, None) =>                Err(A::Error::invalid_length(1, &"Sequence of length 4")),
            (Some(_), Some(_), None, None, None) =>             Err(A::Error::invalid_length(2, &"Sequence of length 4")),
            (Some(_), Some(_), Some(_), None, None) =>          Err(A::Error::invalid_length(3, &"Sequence of length 4")),
            (Some(_), Some(_), Some(_), Some(_), Some(_)) =>    Err(A::Error::invalid_length(5, &"Sequence of length 4")),
            _ =>                                                Err(A::Error::custom("Expected array of length 4, found nothing")),
        }
    }
}

struct Mat4Visitor<T>(PhantomData<T>);
impl<T> Mat4Visitor<T> {
    fn new() -> Self { Mat4Visitor(PhantomData) }
}
impl<'de, T> Visitor<'de> for Mat4Visitor<T>
    where T: Deserialize<'de>,
          T: Num + Float + Copy,
{
    type Value = Mat4<T>;

    fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("A sequence of length 16")
    }

    fn visit_seq<A>(self, mut a: A) -> Result<Self::Value, A::Error>
        where A: SeqAccess<'de>,
    {
        let mut values = [T::zero(); 16];
        for i in 0..values.len() {
            match a.next_element()? {
                Some(x) => values[i] = x,
                None => return Err(A::Error::invalid_length(i, &"Sequence of length 16")),
            }
        }
        Ok(Mat4::from_row_flat(values))
    }
}

struct Mat3Visitor<T>(PhantomData<T>);
impl<T> Mat3Visitor<T> {
    fn new() -> Self { Mat3Visitor(PhantomData) }
}
impl<'de, T> Visitor<'de> for Mat3Visitor<T>
    where T: Deserialize<'de>,
          T: Num + Float + Copy,
{
    type Value = Mat3<T>;

    fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("A sequence of length 9")
    }

    fn visit_seq<A>(self, mut a: A) -> Result<Self::Value, A::Error>
        where A: SeqAccess<'de>,
    {
        let mut values = [T::zero(); 9];
        for i in 0..values.len() {
            match a.next_element()? {
                Some(x) => values[i] = x,
                None => return Err(A::Error::invalid_length(i, &"Sequence of length 9")),
            }
        }
        Ok(Mat3::from_row_flat(values))
    }
}
<commit_msg>Fix cable-math serialization code<commit_after>
// This is a bit of a nightmare

use std::fmt;
use std::marker::PhantomData;
use serde::{Serialize, Deserialize, Serializer, Deserializer};
use serde::ser::SerializeTuple;
use serde::de::{Visitor, SeqAccess, Error};

use quat::Quaternion;
use vec::{Vec2, Vec3, Vec4};
use mat::{Mat3, Mat4};
use traits::{Number, Float};

impl<T: Serialize> Serialize for Vec2<T> {
    fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
        let mut tuple = s.serialize_tuple(2)?;
        tuple.serialize_element(&self.x)?;
        tuple.serialize_element(&self.y)?;
        tuple.end()
    }
}

impl<T: Serialize> Serialize for Vec3<T> {
    fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
        let mut tuple = s.serialize_tuple(3)?;
        tuple.serialize_element(&self.x)?;
        tuple.serialize_element(&self.y)?;
        tuple.serialize_element(&self.z)?;
        tuple.end()
    }
}

impl<T: Serialize> Serialize for Vec4<T> {
    fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
        let mut tuple = s.serialize_tuple(4)?;
        tuple.serialize_element(&self.x)?;
        tuple.serialize_element(&self.y)?;
        tuple.serialize_element(&self.z)?;
        tuple.serialize_element(&self.w)?;
        tuple.end()
    }
}

impl<T: Serialize> Serialize for Quaternion<T>
    where T: Number + Float + Copy,
{
    fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
        let mut tuple = s.serialize_tuple(4)?;
        tuple.serialize_element(&self.x)?;
        tuple.serialize_element(&self.y)?;
        tuple.serialize_element(&self.z)?;
        tuple.serialize_element(&self.w)?;
        tuple.end()
    }
}

impl<T: Serialize> Serialize for Mat4<T> {
    fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
        let mut tuple = s.serialize_tuple(16)?;
        tuple.serialize_element(&self.a11)?;
        tuple.serialize_element(&self.a12)?;
        tuple.serialize_element(&self.a13)?;
        tuple.serialize_element(&self.a14)?;
        tuple.serialize_element(&self.a21)?;
        tuple.serialize_element(&self.a22)?;
        tuple.serialize_element(&self.a23)?;
        tuple.serialize_element(&self.a24)?;
        tuple.serialize_element(&self.a31)?;
        tuple.serialize_element(&self.a32)?;
        tuple.serialize_element(&self.a33)?;
        tuple.serialize_element(&self.a34)?;
        tuple.serialize_element(&self.a41)?;
        tuple.serialize_element(&self.a42)?;
        tuple.serialize_element(&self.a43)?;
        tuple.serialize_element(&self.a44)?;
        tuple.end()
    }
}

impl<T: Serialize> Serialize for Mat3<T> {
    fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
        let mut tuple = s.serialize_tuple(9)?;
        tuple.serialize_element(&self.a11)?;
        tuple.serialize_element(&self.a12)?;
        tuple.serialize_element(&self.a13)?;
        tuple.serialize_element(&self.a21)?;
        tuple.serialize_element(&self.a22)?;
        tuple.serialize_element(&self.a23)?;
        tuple.serialize_element(&self.a31)?;
        tuple.serialize_element(&self.a32)?;
        tuple.serialize_element(&self.a33)?;
        tuple.end()
    }
}

impl<'de, T: Deserialize<'de>> Deserialize<'de> for Vec2<T> {
    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
        d.deserialize_tuple(2, Vec2Visitor::new())
    }
}

impl<'de, T: Deserialize<'de>> Deserialize<'de> for Vec3<T> {
    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
        d.deserialize_tuple(3, Vec3Visitor::new())
    }
}

impl<'de, T: Deserialize<'de>> Deserialize<'de> for Vec4<T> {
    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
        d.deserialize_tuple(4, Vec4Visitor::new())
    }
}

impl<'de, T> Deserialize<'de> for Quaternion<T>
    where T: Deserialize<'de>,
          T: Number + Float + Copy,
{
    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
        d.deserialize_tuple(4, QuaternionVisitor::new())
    }
}

impl<'de, T: Deserialize<'de>> Deserialize<'de> for Mat4<T>
    where T: Deserialize<'de>,
          T: Number + Float + Copy,
{
    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
        d.deserialize_tuple(16, Mat4Visitor::new())
    }
}

impl<'de, T: Deserialize<'de>> Deserialize<'de> for Mat3<T>
    where T: Deserialize<'de>,
          T: Number + Float + Copy,
{
    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
        d.deserialize_tuple(9, Mat3Visitor::new())
    }
}

struct Vec2Visitor<T>(PhantomData<T>);
impl<T> Vec2Visitor<T> {
    fn new() -> Self { Vec2Visitor(PhantomData) }
}
impl<'de, T: Deserialize<'de>> Visitor<'de> for Vec2Visitor<T> {
    type Value = Vec2<T>;

    fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("A sequence of length 2")
    }

    fn visit_seq<A>(self, mut a: A) -> Result<Self::Value, A::Error>
        where A: SeqAccess<'de>,
    {
        let x: Option<T> = a.next_element()?;
        let y: Option<T> = a.next_element()?;
        let z: Option<T> = a.next_element()?;

        match (x, y, z) {
            (Some(x), Some(y), None) =>     Ok(Vec2::new(x, y)),
            (Some(_), None, None) =>        Err(A::Error::invalid_length(1, &"Sequence of length 2")),
            (Some(_), Some(_), Some(_)) =>  Err(A::Error::invalid_length(3, &"Sequence of length 2")),
            _ =>                            Err(A::Error::custom("Expected array of length 2, found nothing")),
        }
    }
}

struct Vec3Visitor<T>(PhantomData<T>);
impl<T> Vec3Visitor<T> {
    fn new() -> Self { Vec3Visitor(PhantomData) }
}
impl<'de, T: Deserialize<'de>> Visitor<'de> for Vec3Visitor<T> {
    type Value = Vec3<T>;

    fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("A sequence of length 3")
    }

    fn visit_seq<A>(self, mut a: A) -> Result<Self::Value, A::Error>
        where A: SeqAccess<'de>,
    {
        let x: Option<T> = a.next_element()?;
        let y: Option<T> = a.next_element()?;
        let z: Option<T> = a.next_element()?;
        let w: Option<T> = a.next_element()?;

        match (x, y, z, w) {
            (Some(x), Some(y), Some(z), None) =>    Ok(Vec3::new(x, y, z)),
            (Some(_), None, None, None) =>          Err(A::Error::invalid_length(1, &"Sequence of length 3")),
            (Some(_), Some(_), None, None) =>       Err(A::Error::invalid_length(2, &"Sequence of length 3")),
            (Some(_), Some(_), Some(_), Some(_)) => Err(A::Error::invalid_length(4, &"Sequence of length 3")),
            _ =>                                    Err(A::Error::custom("Expected array of length 3, found nothing")),
        }
    }
}

struct Vec4Visitor<T>(PhantomData<T>);
impl<T> Vec4Visitor<T> {
    fn new() -> Self { Vec4Visitor(PhantomData) }
}
impl<'de, T: Deserialize<'de>> Visitor<'de> for Vec4Visitor<T> {
    type Value = Vec4<T>;

    fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("A sequence of length 4")
    }

    fn visit_seq<A>(self, mut a: A) -> Result<Self::Value, A::Error>
        where A: SeqAccess<'de>,
    {
        let x: Option<T> = a.next_element()?;
        let y: Option<T> = a.next_element()?;
        let z: Option<T> = a.next_element()?;
        let w: Option<T> = a.next_element()?;
        let q: Option<T> = a.next_element()?;

        match (x, y, z, w, q) {
            (Some(x), Some(y), Some(z), Some(w), None) =>       Ok(Vec4::new(x, y, z, w)),
            (Some(_), None, None, None, None) =>                Err(A::Error::invalid_length(1, &"Sequence of length 4")),
            (Some(_), Some(_), None, None, None) =>             Err(A::Error::invalid_length(2, &"Sequence of length 4")),
            (Some(_), Some(_), Some(_), None, None) =>          Err(A::Error::invalid_length(3, &"Sequence of length 4")),
            (Some(_), Some(_), Some(_), Some(_), Some(_)) =>    Err(A::Error::invalid_length(5, &"Sequence of length 4")),
            _ =>                                                Err(A::Error::custom("Expected array of length 4, found nothing")),
        }
    }
}

struct QuaternionVisitor<T>(PhantomData<T>);
impl<T> QuaternionVisitor<T>
    where T: Number + Float + Copy,
{
    fn new() -> Self { QuaternionVisitor(PhantomData) }
}

impl<'de, T: Deserialize<'de>> Visitor<'de> for QuaternionVisitor<T>
    where T: Deserialize<'de>,
          T: Number + Float + Copy,
{
    type Value = Quaternion<T>;

    fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("A sequence of length 4")
    }

    fn visit_seq<A>(self, mut a: A) -> Result<Self::Value, A::Error>
        where A: SeqAccess<'de>,
    {
        let x: Option<T> = a.next_element()?;
        let y: Option<T> = a.next_element()?;
        let z: Option<T> = a.next_element()?;
        let w: Option<T> = a.next_element()?;
        let q: Option<T> = a.next_element()?;

        match (x, y, z, w, q) {
            (Some(x), Some(y), Some(z), Some(w), None) =>       Ok(Quaternion { x: x, y: y, z: z, w: w }),
            (Some(_), None, None, None, None) =>                Err(A::Error::invalid_length(1, &"Sequence of length 4")),
            (Some(_), Some(_), None, None, None) =>             Err(A::Error::invalid_length(2, &"Sequence of length 4")),
            (Some(_), Some(_), Some(_), None, None) =>          Err(A::Error::invalid_length(3, &"Sequence of length 4")),
            (Some(_), Some(_), Some(_), Some(_), Some(_)) =>    Err(A::Error::invalid_length(5, &"Sequence of length 4")),
            _ =>                                                Err(A::Error::custom("Expected array of length 4, found nothing")),
        }
    }
}

struct Mat4Visitor<T>(PhantomData<T>);
impl<T> Mat4Visitor<T> {
    fn new() -> Self { Mat4Visitor(PhantomData) }
}
impl<'de, T> Visitor<'de> for Mat4Visitor<T>
    where T: Deserialize<'de>,
          T: Number + Float + Copy,
{
    type Value = Mat4<T>;

    fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("A sequence of length 16")
    }

    fn visit_seq<A>(self, mut a: A) -> Result<Self::Value, A::Error>
        where A: SeqAccess<'de>,
    {
        let mut values = [T::ZERO; 16];
        for i in 0..values.len() {
            match a.next_element()? {
                Some(x) => values[i] = x,
                None => return Err(A::Error::invalid_length(i, &"Sequence of length 16")),
            }
        }
        Ok(Mat4::from_row_flat(values))
    }
}

struct Mat3Visitor<T>(PhantomData<T>);
impl<T> Mat3Visitor<T> {
    fn new() -> Self { Mat3Visitor(PhantomData) }
}
impl<'de, T> Visitor<'de> for Mat3Visitor<T>
    where T: Deserialize<'de>,
          T: Number + Float + Copy,
{
    type Value = Mat3<T>;

    fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("A sequence of length 9")
    }

    fn visit_seq<A>(self, mut a: A) -> Result<Self::Value, A::Error>
        where A: SeqAccess<'de>,
    {
        let mut values = [T::ZERO; 9];
        for i in 0..values.len() {
            match a.next_element()? {
                Some(x) => values[i] = x,
                None => return Err(A::Error::invalid_length(i, &"Sequence of length 9")),
            }
        }
        Ok(Mat3::from_row_flat(values))
    }
}
<|endoftext|>


<commit_before>// CITA
// Copyright 2016-2017 Cryptape Technologies LLC.

// This program is free software: you can redistribute it
// and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any
// later version.

// This program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

use error::ErrorCode;
use jsonrpc_types::rpctypes::TxResponse;
use libproto::{BatchRequest, Message, Request, Response};
use libproto::blockchain::{AccountGasLimit, BlockBody, BlockTxs, SignedTransaction};
use libproto::router::{MsgType, RoutingKey, SubModules};
use protobuf::RepeatedField;
use serde_json;

use std::cell::RefCell;
use std::collections::HashSet;
use std::convert::{Into, TryInto};
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::mpsc::Sender;
use std::thread;
use std::time::SystemTime;
use tx_pool;
use txwal::TxWal;
use util::{H256, ToPretty};
use uuid::Uuid;

pub struct Dispatcher {
    txs_pool: RefCell<tx_pool::Pool>,
    tx_pool_cap: Arc<AtomicUsize>,
    wal: TxWal,
    wal_enable: bool,
    pool_limit: usize,
    data_from_pool: AtomicBool,
    batch_forward_info: BatchForwardInfo,
    response_jsonrpc_cnt: u64,
    start_verify_time: SystemTime,
    add_to_pool_cnt: u64,
}

pub struct BatchForwardInfo {
    count_per_batch: usize,
    buffer_duration: u32, //in unit of ns
    forward_stamp: SystemTime,
    new_tx_request_buffer: Vec<Request>,
}

impl Dispatcher {
    pub fn new(
        package_limit: usize,
        limit: usize,
        count_per_batch: usize,
        buffer_duration: u32,
        wal_enable: bool,
    ) -> Self {
        let batch_forward_info = BatchForwardInfo {
            count_per_batch: count_per_batch,
            buffer_duration: buffer_duration,
            forward_stamp: SystemTime::now(),
            new_tx_request_buffer: Vec::new(),
        };

        let mut dispatch = Dispatcher {
            txs_pool: RefCell::new(tx_pool::Pool::new(package_limit)),
            tx_pool_cap: Arc::new(AtomicUsize::new(limit)),
            wal: TxWal::new("/txwal"),
            wal_enable: wal_enable,
            pool_limit: limit,
            data_from_pool: AtomicBool::new(false),
            batch_forward_info: batch_forward_info,
            response_jsonrpc_cnt: 0,
            start_verify_time: SystemTime::now(),
            add_to_pool_cnt: 0,
        };
        if wal_enable {
            let num = dispatch.read_tx_from_wal();
            if num > 0 {
                dispatch.data_from_pool.store(true, Ordering::SeqCst);
            }
        }
        dispatch
    }

    /// Clean transaction pool and regenerate an pool cache db
    pub fn clear_txs_pool(&mut self, package_limit: usize) {
        self.txs_pool = RefCell::new(tx_pool::Pool::new(package_limit));
        self.wal.regenerate("/txwal");
    }

    pub fn tx_pool_capacity(&self) -> Arc<AtomicUsize> {
        self.tx_pool_cap.clone()
    }

    fn update_capacity(&mut self) {
        let tx_pool_len = self.txs_pool.borrow().len();
        if self.pool_limit >= tx_pool_len {
            let capacity = self.pool_limit - tx_pool_len;
            self.tx_pool_cap.store(capacity, Ordering::SeqCst);
        } else {
            self.tx_pool_cap.store(0, Ordering::SeqCst);
        }
    }

    /// Add new transaction to pool, response jsonrpc request
    /// package buffer request forward to peer
    pub fn deal_tx(
        &mut self,
        key: String,
        req_id: Vec<u8>,
        tx_response: TxResponse,
        tx: &SignedTransaction,
        mq_pub: &Sender<(String, Vec<u8>)>,
    ) {
        let mut error_msg: Option<String> = None;
        if self.add_tx_to_pool(tx) {
            self.update_capacity();
        } else {
            error_msg = Some(String::from("Dup"));
        }

        if RoutingKey::from(&key).is_sub_module(SubModules::Jsonrpc) {
            let mut response = Response::new();
            response.set_request_id(req_id);

            if error_msg.is_some() {
                response.set_code(ErrorCode::tx_auth_error());
                response.set_error_msg(error_msg.unwrap());
            } else {
                let tx_state = serde_json::to_string(&tx_response).unwrap();
                response.set_tx_state(tx_state);

                let request_id = Uuid::new_v4().as_bytes().to_vec();
                trace!("send auth.tx with request_id {:?}", request_id);
                let mut request = Request::new();
                request.set_un_tx(tx.get_transaction_with_sig().clone());
                request.set_request_id(request_id);
                self.batch_forward_info.new_tx_request_buffer.push(request);

                let count_buffered = self.batch_forward_info.new_tx_request_buffer.len();
                let time_elapsed = self.batch_forward_info
                    .forward_stamp
                    .elapsed()
                    .unwrap()
                    .subsec_nanos();

                if count_buffered > self.batch_forward_info.count_per_batch
                    || time_elapsed > self.batch_forward_info.buffer_duration
                {
                    trace!(
                        "Going to send new tx batch to peer auth with {} new tx and buffer {} ns",
                        count_buffered,
                        time_elapsed
                    );

                    self.batch_forward_tx_to_peer(mq_pub);
                }
            }
            self.response_jsonrpc_cnt += 1;
            trace!(
                "response new tx {:?}, with response_jsonrpc_cnt = {}",
                response,
                self.response_jsonrpc_cnt
            );

            let msg: Message = response.into();
            mq_pub
                .send((
                    routing_key!(Auth >> Response).into(),
                    msg.try_into().unwrap(),
                ))
                .unwrap();
        }
        if 0 == self.add_to_pool_cnt {
            self.start_verify_time = SystemTime::now();
        }
        self.add_to_pool_cnt += 1;
    }

    /// Delete transactions from pool, and then package a block with new transactions,
    /// send to cita-bft
    pub fn deal_txs(
        &mut self,
        height: usize,
        txs: &HashSet<H256>,
        mq_pub: &Sender<(String, Vec<u8>)>,
        block_gas_limit: u64,
        account_gas_limit: AccountGasLimit,
    ) {
        let mut block_txs = BlockTxs::new();
        let mut body = BlockBody::new();

        trace!("deal_txs inner txs height {} ", txs.len());
        if !txs.is_empty() {
            self.del_txs_from_pool_with_hash(txs);
        }

        let out_txs = self.get_txs_from_pool(height as u64, block_gas_limit, account_gas_limit);
        debug!(
            "public block txs height {} with {:?} txs on timestamp: {:?}",
            height,
            out_txs.len(),
            SystemTime::now()
        );
        {
            let duration = self.start_verify_time.elapsed().unwrap();
            let time_duration_in_usec = duration.as_secs() * 1_000_000 + (duration.subsec_nanos() / 1_000) as u64;
            if 0 != time_duration_in_usec {
                debug!(
                    "{} txs have been added into tx_pool, and time cost is {:?}, tps: {:?}",
                    self.add_to_pool_cnt,
                    duration,
                    self.add_to_pool_cnt * 1_000_000 / time_duration_in_usec
                );
            }
            self.add_to_pool_cnt = 0;
        }

        self.update_capacity();
        if !out_txs.is_empty() {
            body.set_transactions(RepeatedField::from_vec(out_txs));
        }
        block_txs.set_height(height as u64);
        block_txs.set_body(body);
        trace!("deal_txs send height {}", height);
        let msg: Message = block_txs.into();
        mq_pub
            .send((
                routing_key!(Auth >> BlockTxs).into(),
                msg.try_into().unwrap(),
            ))
            .unwrap();
    }

    pub fn wait_timeout_process(&mut self, mq_pub: &Sender<(String, Vec<u8>)>) {
        let time_elapsed = self.batch_forward_info
            .forward_stamp
            .elapsed()
            .unwrap()
            .subsec_nanos();
        let count_buffered = self.batch_forward_info.new_tx_request_buffer.len();
        if !self.batch_forward_info.new_tx_request_buffer.is_empty() {
            trace!(
                "wait_timeout_process is going to send new tx batch to peer auth with {} new tx and buffer {} ns",
                count_buffered,
                time_elapsed
            );
            self.batch_forward_tx_to_peer(mq_pub);
        }
    }

    pub fn add_tx_to_pool(&self, tx: &SignedTransaction) -> bool {
        // 交易放入pool，
        // 放入pool完成后，持久化
        trace!("add tx {} to pool", tx.get_tx_hash().pretty());
        let txs_pool = &mut self.txs_pool.borrow_mut();
        let success = txs_pool.enqueue(tx.clone());
        if self.wal_enable {
            if success {
                self.wal.write(tx);
            } else {
                warn!(
                    "the transaction {} is already exist",
                    tx.get_tx_hash().pretty()
                );
            }
        }
        success
    }

    pub fn get_txs_from_pool(
        &self,
        height: u64,
        block_gas_limit: u64,
        account_gas_limit: AccountGasLimit,
    ) -> Vec<SignedTransaction> {
        if self.data_from_pool.load(Ordering::SeqCst) {
            self.data_from_pool.store(false, Ordering::SeqCst);
            Vec::new()
        } else {
            let txs_pool = &mut self.txs_pool.borrow_mut();
            txs_pool.package(height, block_gas_limit, account_gas_limit)
        }
    }

    pub fn del_txs_from_pool_with_hash(&self, txs: &HashSet<H256>) {
        //收到删除通知，从pool中删除vec中的交易
        {
            self.txs_pool.borrow_mut().update_with_hash(txs);
        }
        //改成多线程删除数据
        if self.wal_enable {
            let mut wal = self.wal.clone();
            let txs = txs.clone();
            thread::spawn(move || {
                for tx in txs {
                    wal.delete_with_hash(&tx);
                }
            });
        }
    }

    pub fn del_txs_from_pool(&self, txs: Vec<SignedTransaction>) {
        //收到删除通知，从pool中删除vec中的交易
        {
            self.txs_pool.borrow_mut().update(&txs);
        }
        //改成多线程删除数据
        if self.wal_enable {
            let mut wal = self.wal.clone();
            thread::spawn(move || {
                for tx in txs {
                    wal.delete(&tx);
                }
            });
        }
    }

    pub fn read_tx_from_wal(&mut self) -> u64 {
        let size = self.wal.read(&mut self.txs_pool.borrow_mut());
        self.update_capacity();
        size
    }

    fn batch_forward_tx_to_peer(&mut self, mq_pub: &Sender<(String, Vec<u8>)>) {
        trace!(
            "batch_forward_tx_to_peer is going to send {} new tx to peer",
            self.batch_forward_info.new_tx_request_buffer.len()
        );
        let mut batch_request = BatchRequest::new();
        batch_request.set_new_tx_requests(RepeatedField::from_slice(
            &self.batch_forward_info.new_tx_request_buffer[..],
        ));

        let request_id = Uuid::new_v4().as_bytes().to_vec();
        let mut request = Request::new();
        request.set_batch_req(batch_request);
        request.set_request_id(request_id);

        let msg: Message = request.into();
        mq_pub
            .send((
                routing_key!(Auth >> Request).into(),
                msg.try_into().unwrap(),
            ))
            .unwrap();

        self.batch_forward_info.forward_stamp = SystemTime::now();
        self.batch_forward_info.new_tx_request_buffer.clear();
    }
}
<commit_msg>Fixed broadcast tx<commit_after>// CITA
// Copyright 2016-2017 Cryptape Technologies LLC.

// This program is free software: you can redistribute it
// and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any
// later version.

// This program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

use error::ErrorCode;
use jsonrpc_types::rpctypes::TxResponse;
use libproto::{BatchRequest, Message, Request, Response};
use libproto::blockchain::{AccountGasLimit, BlockBody, BlockTxs, SignedTransaction};
use libproto::router::{MsgType, RoutingKey, SubModules};
use protobuf::RepeatedField;
use serde_json;

use std::cell::RefCell;
use std::collections::HashSet;
use std::convert::{Into, TryInto};
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::mpsc::Sender;
use std::thread;
use std::time::SystemTime;
use tx_pool;
use txwal::TxWal;
use util::{H256, ToPretty};
use uuid::Uuid;

pub struct Dispatcher {
    txs_pool: RefCell<tx_pool::Pool>,
    tx_pool_cap: Arc<AtomicUsize>,
    wal: TxWal,
    wal_enable: bool,
    pool_limit: usize,
    data_from_pool: AtomicBool,
    batch_forward_info: BatchForwardInfo,
    response_jsonrpc_cnt: u64,
    start_verify_time: SystemTime,
    add_to_pool_cnt: u64,
}

pub struct BatchForwardInfo {
    count_per_batch: usize,
    buffer_duration: u32, //in unit of ns
    forward_stamp: SystemTime,
    new_tx_request_buffer: Vec<Request>,
}

impl Dispatcher {
    pub fn new(
        package_limit: usize,
        limit: usize,
        count_per_batch: usize,
        buffer_duration: u32,
        wal_enable: bool,
    ) -> Self {
        let batch_forward_info = BatchForwardInfo {
            count_per_batch: count_per_batch,
            buffer_duration: buffer_duration,
            forward_stamp: SystemTime::now(),
            new_tx_request_buffer: Vec::new(),
        };

        let mut dispatch = Dispatcher {
            txs_pool: RefCell::new(tx_pool::Pool::new(package_limit)),
            tx_pool_cap: Arc::new(AtomicUsize::new(limit)),
            wal: TxWal::new("/txwal"),
            wal_enable: wal_enable,
            pool_limit: limit,
            data_from_pool: AtomicBool::new(false),
            batch_forward_info: batch_forward_info,
            response_jsonrpc_cnt: 0,
            start_verify_time: SystemTime::now(),
            add_to_pool_cnt: 0,
        };
        if wal_enable {
            let num = dispatch.read_tx_from_wal();
            if num > 0 {
                dispatch.data_from_pool.store(true, Ordering::SeqCst);
            }
        }
        dispatch
    }

    /// Clean transaction pool and regenerate an pool cache db
    pub fn clear_txs_pool(&mut self, package_limit: usize) {
        self.txs_pool = RefCell::new(tx_pool::Pool::new(package_limit));
        self.wal.regenerate("/txwal");
    }

    pub fn tx_pool_capacity(&self) -> Arc<AtomicUsize> {
        self.tx_pool_cap.clone()
    }

    fn update_capacity(&mut self) {
        let tx_pool_len = self.txs_pool.borrow().len();
        if self.pool_limit >= tx_pool_len {
            let capacity = self.pool_limit - tx_pool_len;
            self.tx_pool_cap.store(capacity, Ordering::SeqCst);
        } else {
            self.tx_pool_cap.store(0, Ordering::SeqCst);
        }
    }

    /// Add new transaction to pool, response jsonrpc request
    /// package buffer request forward to peer
    pub fn deal_tx(
        &mut self,
        key: String,
        req_id: Vec<u8>,
        tx_response: TxResponse,
        tx: &SignedTransaction,
        mq_pub: &Sender<(String, Vec<u8>)>,
    ) {
        let mut error_msg: Option<String> = None;
        if self.add_tx_to_pool(tx) {
            self.update_capacity();
        } else {
            error_msg = Some(String::from("Dup"));
        }

        if error_msg.is_none() {
            let request_id = Uuid::new_v4().as_bytes().to_vec();
            trace!("send auth.tx with request_id {:?}", request_id);
            let mut request = Request::new();
            request.set_un_tx(tx.get_transaction_with_sig().clone());
            request.set_request_id(request_id);
            self.batch_forward_info.new_tx_request_buffer.push(request);

            let count_buffered = self.batch_forward_info.new_tx_request_buffer.len();
            let time_elapsed = self.batch_forward_info
                .forward_stamp
                .elapsed()
                .unwrap()
                .subsec_nanos();

            if count_buffered > self.batch_forward_info.count_per_batch
                || time_elapsed > self.batch_forward_info.buffer_duration
            {
                trace!(
                    "Going to send new tx batch to peer auth with {} new tx and buffer {} ns",
                    count_buffered,
                    time_elapsed
                );

                self.batch_forward_tx_to_peer(mq_pub);
            }
        }

        // RPC response
        if RoutingKey::from(&key).is_sub_module(SubModules::Jsonrpc) {
            let mut response = Response::new();
            response.set_request_id(req_id);
            if error_msg.is_some() {
                response.set_code(ErrorCode::tx_auth_error());
                response.set_error_msg(error_msg.unwrap());
            } else {
                let tx_state = serde_json::to_string(&tx_response).unwrap();
                response.set_tx_state(tx_state);
            }

            self.response_jsonrpc_cnt += 1;
            trace!(
                "response new tx {:?}, with response_jsonrpc_cnt = {}",
                response,
                self.response_jsonrpc_cnt
            );

            let msg: Message = response.into();
            mq_pub
                .send((
                    routing_key!(Auth >> Response).into(),
                    msg.try_into().unwrap(),
                ))
                .unwrap();
        }

        if 0 == self.add_to_pool_cnt {
            self.start_verify_time = SystemTime::now();
        }
        self.add_to_pool_cnt += 1;
    }

    /// Delete transactions from pool, and then package a block with new transactions,
    /// send to cita-bft
    pub fn deal_txs(
        &mut self,
        height: usize,
        txs: &HashSet<H256>,
        mq_pub: &Sender<(String, Vec<u8>)>,
        block_gas_limit: u64,
        account_gas_limit: AccountGasLimit,
    ) {
        let mut block_txs = BlockTxs::new();
        let mut body = BlockBody::new();

        trace!("deal_txs inner txs height {} ", txs.len());
        if !txs.is_empty() {
            self.del_txs_from_pool_with_hash(txs);
        }

        let out_txs = self.get_txs_from_pool(height as u64, block_gas_limit, account_gas_limit);
        debug!(
            "public block txs height {} with {:?} txs on timestamp: {:?}",
            height,
            out_txs.len(),
            SystemTime::now()
        );
        {
            let duration = self.start_verify_time.elapsed().unwrap();
            let time_duration_in_usec = duration.as_secs() * 1_000_000 + (duration.subsec_nanos() / 1_000) as u64;
            if 0 != time_duration_in_usec {
                debug!(
                    "{} txs have been added into tx_pool, and time cost is {:?}, tps: {:?}",
                    self.add_to_pool_cnt,
                    duration,
                    self.add_to_pool_cnt * 1_000_000 / time_duration_in_usec
                );
            }
            self.add_to_pool_cnt = 0;
        }

        self.update_capacity();
        if !out_txs.is_empty() {
            body.set_transactions(RepeatedField::from_vec(out_txs));
        }
        block_txs.set_height(height as u64);
        block_txs.set_body(body);
        trace!("deal_txs send height {}", height);
        let msg: Message = block_txs.into();
        mq_pub
            .send((
                routing_key!(Auth >> BlockTxs).into(),
                msg.try_into().unwrap(),
            ))
            .unwrap();
    }

    pub fn wait_timeout_process(&mut self, mq_pub: &Sender<(String, Vec<u8>)>) {
        let time_elapsed = self.batch_forward_info
            .forward_stamp
            .elapsed()
            .unwrap()
            .subsec_nanos();
        let count_buffered = self.batch_forward_info.new_tx_request_buffer.len();
        if !self.batch_forward_info.new_tx_request_buffer.is_empty() {
            trace!(
                "wait_timeout_process is going to send new tx batch to peer auth with {} new tx and buffer {} ns",
                count_buffered,
                time_elapsed
            );
            self.batch_forward_tx_to_peer(mq_pub);
        }
    }

    pub fn add_tx_to_pool(&self, tx: &SignedTransaction) -> bool {
        // 交易放入pool，
        // 放入pool完成后，持久化
        trace!("add tx {} to pool", tx.get_tx_hash().pretty());
        let txs_pool = &mut self.txs_pool.borrow_mut();
        let success = txs_pool.enqueue(tx.clone());
        if self.wal_enable {
            if success {
                self.wal.write(tx);
            } else {
                warn!(
                    "the transaction {} is already exist",
                    tx.get_tx_hash().pretty()
                );
            }
        }
        success
    }

    pub fn get_txs_from_pool(
        &self,
        height: u64,
        block_gas_limit: u64,
        account_gas_limit: AccountGasLimit,
    ) -> Vec<SignedTransaction> {
        if self.data_from_pool.load(Ordering::SeqCst) {
            self.data_from_pool.store(false, Ordering::SeqCst);
            Vec::new()
        } else {
            let txs_pool = &mut self.txs_pool.borrow_mut();
            txs_pool.package(height, block_gas_limit, account_gas_limit)
        }
    }

    pub fn del_txs_from_pool_with_hash(&self, txs: &HashSet<H256>) {
        //收到删除通知，从pool中删除vec中的交易
        {
            self.txs_pool.borrow_mut().update_with_hash(txs);
        }
        //改成多线程删除数据
        if self.wal_enable {
            let mut wal = self.wal.clone();
            let txs = txs.clone();
            thread::spawn(move || {
                for tx in txs {
                    wal.delete_with_hash(&tx);
                }
            });
        }
    }

    pub fn del_txs_from_pool(&self, txs: Vec<SignedTransaction>) {
        //收到删除通知，从pool中删除vec中的交易
        {
            self.txs_pool.borrow_mut().update(&txs);
        }
        //改成多线程删除数据
        if self.wal_enable {
            let mut wal = self.wal.clone();
            thread::spawn(move || {
                for tx in txs {
                    wal.delete(&tx);
                }
            });
        }
    }

    pub fn read_tx_from_wal(&mut self) -> u64 {
        let size = self.wal.read(&mut self.txs_pool.borrow_mut());
        self.update_capacity();
        size
    }

    fn batch_forward_tx_to_peer(&mut self, mq_pub: &Sender<(String, Vec<u8>)>) {
        trace!(
            "batch_forward_tx_to_peer is going to send {} new tx to peer",
            self.batch_forward_info.new_tx_request_buffer.len()
        );
        let mut batch_request = BatchRequest::new();
        batch_request.set_new_tx_requests(RepeatedField::from_slice(
            &self.batch_forward_info.new_tx_request_buffer[..],
        ));

        let request_id = Uuid::new_v4().as_bytes().to_vec();
        let mut request = Request::new();
        request.set_batch_req(batch_request);
        request.set_request_id(request_id);

        let msg: Message = request.into();
        mq_pub
            .send((
                routing_key!(Auth >> Request).into(),
                msg.try_into().unwrap(),
            ))
            .unwrap();

        self.batch_forward_info.forward_stamp = SystemTime::now();
        self.batch_forward_info.new_tx_request_buffer.clear();
    }
}
<|endoftext|>


<commit_before>use rustc::lint::*;
use syntax::ast::*;
use syntax::codemap::{Span, Spanned};
use syntax::visit::FnKind;

use utils::{span_note_and_lint, span_lint_and_then, snippet_opt, match_path_ast, in_external_macro};

/// **What it does:** Checks for return statements at the end of a block.
///
/// **Why is this bad?** Removing the `return` and semicolon will make the code
/// more rusty.
///
/// **Known problems:** Following this lint's advice may currently run afoul of
/// Rust issue [#31439](https://github.com/rust-lang/rust/issues/31439), so if
/// you get lifetime errors, please roll back the change until that issue is
/// fixed.
///
/// **Example:**
/// ```rust
/// fn foo(x: usize) { return x; }
/// ```
declare_lint! {
    pub NEEDLESS_RETURN,
    Warn,
    "using a return statement like `return expr;` where an expression would suffice"
}

/// **What it does:** Checks for `let`-bindings, which are subsequently returned.
///
/// **Why is this bad?** It is just extraneous code. Remove it to make your code
/// more rusty.
///
/// **Known problems:** Following this lint's advice may currently run afoul of
/// Rust issue [#31439](https://github.com/rust-lang/rust/issues/31439), so if
/// you get lifetime errors, please roll back the change until that issue is
/// fixed.
///
/// **Example:**
/// ```rust
/// { let x = ..; x }
/// ```
declare_lint! {
    pub LET_AND_RETURN,
    Warn,
    "creating a let-binding and then immediately returning it like `let x = expr; x` at \
     the end of a block"
}

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

impl ReturnPass {
    // Check the final stmt or expr in a block for unnecessary return.
    fn check_block_return(&mut self, cx: &EarlyContext, block: &Block) {
        if let Some(stmt) = block.stmts.last() {
            match stmt.node {
                StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => {
                    self.check_final_expr(cx, expr, Some(stmt.span));
                }
                _ => (),
            }
        }
    }

    // Check a the final expression in a block if it's a return.
    fn check_final_expr(&mut self, cx: &EarlyContext, expr: &Expr, span: Option<Span>) {
        match expr.node {
            // simple return is always "bad"
            ExprKind::Ret(Some(ref inner)) => {
                self.emit_return_lint(cx, span.expect("`else return` is not possible"), inner.span);
            }
            // a whole block? check it!
            ExprKind::Block(ref block) => {
                self.check_block_return(cx, block);
            }
            // an if/if let expr, check both exprs
            // note, if without else is going to be a type checking error anyways
            // (except for unit type functions) so we don't match it
            ExprKind::If(_, ref ifblock, Some(ref elsexpr)) => {
                self.check_block_return(cx, ifblock);
                self.check_final_expr(cx, elsexpr, None);
            }
            // a match expr, check all arms
            ExprKind::Match(_, ref arms) => {
                for arm in arms {
                    self.check_final_expr(cx, &arm.body, Some(arm.body.span));
                }
            }
            _ => (),
        }
    }

    fn emit_return_lint(&mut self, cx: &EarlyContext, ret_span: Span, inner_span: Span) {
        if in_external_macro(cx, inner_span) {
            return;
        }
        span_lint_and_then(cx, NEEDLESS_RETURN, ret_span, "unneeded return statement", |db| {
            if let Some(snippet) = snippet_opt(cx, inner_span) {
                db.span_suggestion(ret_span, "remove `return` as shown:", snippet);
            }
        });
    }

    // Check for "let x = EXPR; x"
    fn check_let_return(&mut self, cx: &EarlyContext, block: &Block) {
        let mut it = block.stmts.iter();

        // we need both a let-binding stmt and an expr
        if_let_chain! {[
            let Some(ref retexpr) = it.next_back(),
            let StmtKind::Expr(ref retexpr) = retexpr.node,
            let Some(stmt) = it.next_back(),
            let StmtKind::Local(ref local) = stmt.node,
            let Some(ref initexpr) = local.init,
            let PatKind::Ident(_, Spanned { node: id, .. }, _) = local.pat.node,
            let ExprKind::Path(_, ref path) = retexpr.node,
            match_path_ast(path, &[&id.name.as_str()]),
            !in_external_macro(cx, initexpr.span),
        ], {
                span_note_and_lint(cx,
                                   LET_AND_RETURN,
                                   retexpr.span,
                                   "returning the result of a let binding from a block. \
                                   Consider returning the expression directly.",
                                   initexpr.span,
                                   "this expression can be directly returned");
        }}
    }
}

impl LintPass for ReturnPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(NEEDLESS_RETURN, LET_AND_RETURN)
    }
}

impl EarlyLintPass for ReturnPass {
    fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, _: &FnDecl, block: &Block, _: Span, _: NodeId) {
        self.check_block_return(cx, block);
    }

    fn check_block(&mut self, cx: &EarlyContext, block: &Block) {
        self.check_let_return(cx, block);
    }
}
<commit_msg>Remove "known problem" that only occurs without MIR.<commit_after>use rustc::lint::*;
use syntax::ast::*;
use syntax::codemap::{Span, Spanned};
use syntax::visit::FnKind;

use utils::{span_note_and_lint, span_lint_and_then, snippet_opt, match_path_ast, in_external_macro};

/// **What it does:** Checks for return statements at the end of a block.
///
/// **Why is this bad?** Removing the `return` and semicolon will make the code
/// more rusty.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// fn foo(x: usize) { return x; }
/// ```
declare_lint! {
    pub NEEDLESS_RETURN,
    Warn,
    "using a return statement like `return expr;` where an expression would suffice"
}

/// **What it does:** Checks for `let`-bindings, which are subsequently returned.
///
/// **Why is this bad?** It is just extraneous code. Remove it to make your code
/// more rusty.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// { let x = ..; x }
/// ```
declare_lint! {
    pub LET_AND_RETURN,
    Warn,
    "creating a let-binding and then immediately returning it like `let x = expr; x` at \
     the end of a block"
}

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

impl ReturnPass {
    // Check the final stmt or expr in a block for unnecessary return.
    fn check_block_return(&mut self, cx: &EarlyContext, block: &Block) {
        if let Some(stmt) = block.stmts.last() {
            match stmt.node {
                StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => {
                    self.check_final_expr(cx, expr, Some(stmt.span));
                }
                _ => (),
            }
        }
    }

    // Check a the final expression in a block if it's a return.
    fn check_final_expr(&mut self, cx: &EarlyContext, expr: &Expr, span: Option<Span>) {
        match expr.node {
            // simple return is always "bad"
            ExprKind::Ret(Some(ref inner)) => {
                self.emit_return_lint(cx, span.expect("`else return` is not possible"), inner.span);
            }
            // a whole block? check it!
            ExprKind::Block(ref block) => {
                self.check_block_return(cx, block);
            }
            // an if/if let expr, check both exprs
            // note, if without else is going to be a type checking error anyways
            // (except for unit type functions) so we don't match it
            ExprKind::If(_, ref ifblock, Some(ref elsexpr)) => {
                self.check_block_return(cx, ifblock);
                self.check_final_expr(cx, elsexpr, None);
            }
            // a match expr, check all arms
            ExprKind::Match(_, ref arms) => {
                for arm in arms {
                    self.check_final_expr(cx, &arm.body, Some(arm.body.span));
                }
            }
            _ => (),
        }
    }

    fn emit_return_lint(&mut self, cx: &EarlyContext, ret_span: Span, inner_span: Span) {
        if in_external_macro(cx, inner_span) {
            return;
        }
        span_lint_and_then(cx, NEEDLESS_RETURN, ret_span, "unneeded return statement", |db| {
            if let Some(snippet) = snippet_opt(cx, inner_span) {
                db.span_suggestion(ret_span, "remove `return` as shown:", snippet);
            }
        });
    }

    // Check for "let x = EXPR; x"
    fn check_let_return(&mut self, cx: &EarlyContext, block: &Block) {
        let mut it = block.stmts.iter();

        // we need both a let-binding stmt and an expr
        if_let_chain! {[
            let Some(ref retexpr) = it.next_back(),
            let StmtKind::Expr(ref retexpr) = retexpr.node,
            let Some(stmt) = it.next_back(),
            let StmtKind::Local(ref local) = stmt.node,
            let Some(ref initexpr) = local.init,
            let PatKind::Ident(_, Spanned { node: id, .. }, _) = local.pat.node,
            let ExprKind::Path(_, ref path) = retexpr.node,
            match_path_ast(path, &[&id.name.as_str()]),
            !in_external_macro(cx, initexpr.span),
        ], {
                span_note_and_lint(cx,
                                   LET_AND_RETURN,
                                   retexpr.span,
                                   "returning the result of a let binding from a block. \
                                   Consider returning the expression directly.",
                                   initexpr.span,
                                   "this expression can be directly returned");
        }}
    }
}

impl LintPass for ReturnPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(NEEDLESS_RETURN, LET_AND_RETURN)
    }
}

impl EarlyLintPass for ReturnPass {
    fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, _: &FnDecl, block: &Block, _: Span, _: NodeId) {
        self.check_block_return(cx, block);
    }

    fn check_block(&mut self, cx: &EarlyContext, block: &Block) {
        self.check_let_return(cx, block);
    }
}
<|endoftext|>


<commit_before>use std::boxed::Box;
use std::f64;
use std::u64;

use interface::i_spatial_accel;
use interface::i_bound::{ IBound, BoundType };

use implement::math::bound::AxisAlignedBBox;

/// implementation of spatial acceleration using bounding volume hierarchy with surface area heuristic
pub struct Bvh {
    _root: NodeBvh,
    _bins: u32,
}

///internal node structure for Bvh
pub struct NodeBvh {
    _bound: AxisAlignedBBox,
    _left: BvhBranch,
    _right: BvhBranch,
    _obj: u64, //leaf data
}

pub enum BvhBranch {
    CHILD(Box< NodeBvh >),
    EMPTY,
}

impl Default for NodeBvh {
    fn default() -> NodeBvh {
        NodeBvh {
            _bound: AxisAlignedBBox {
                _bound_lower: [ f64::NEG_INFINITY; 3 ],
                _bound_upper: [ f64::INFINITY; 3 ],
            },
            _left: BvhBranch::EMPTY,
            _right: BvhBranch::EMPTY,
            _obj: u64::MAX,
        }
    }
}

impl NodeBvh {
    pub fn init_branches( b: AxisAlignedBBox, l: BvhBranch, r: BvhBranch ) -> NodeBvh {
        NodeBvh {
            _bound: b,
            _left: l,
            _right: r,
            _obj: u64::MAX,
        }
    }
    pub fn init_leaf( b: AxisAlignedBBox, o: u64 ) -> NodeBvh {
        NodeBvh {
            _bound: b,
            _left: BvhBranch::EMPTY,
            _right: BvhBranch::EMPTY,
            _obj: o,
        }
    }
    pub fn build_node( & mut self, num_bins: u32, objs: &[ (u64, &IBound) ] ) -> Result< (), & 'static str > {
        for i in objs {
            match i.1.get_type() {
                BoundType::AxisAlignBox => (),
                _ => return Err( "unsupported bound type" )
            }
        }
        let b = objs.iter().cloned().map( |x| x.1 ).collect::<Vec< &IBound > >();
        let mut u : AxisAlignedBBox = Default::default();
        u.get_union( &b[..] );

        println!( "bound union: {:?}", u );

        //check for leaf condition
        if objs.len() == 1 {
            self._bound = u;
            self._obj = objs[0].0;
            return Ok( () )
        }

        //todo: execute alternative branch when number of objects are low

        //get the longest axis of the bounding box
        let ( ref axis, ref length ) = u.get_longest_axis();

        self._bound = u;

        println!( "axis length: {}", length );

        let c = self._bound.get_centroid();
        let bin_len = length / num_bins as f64;

        let mut bin_offsets = vec![];
        for i in 0..num_bins {
            match axis {
                X => bin_offsets.push( i as f64 * bin_len + self._bound._bound_lower[0] ),
                Y => bin_offsets.push( i as f64 * bin_len + self._bound._bound_lower[1] ),
                Z => bin_offsets.push( i as f64 * bin_len + self._bound._bound_lower[2] ),
            }
        }

        //bin objects using their centroids in the direction of the longest axis
        let mut bins = vec![ 0; num_bins as usize ];
        let mut obj_bin = vec![];
        let epsilon = 0.001f64;
        for i in objs {
            let c = i.1.get_centroid();
            println!("centroid: {:?}", c );
            let bin_id = match axis {
                X => {
                    ( ( c[0] - self._bound._bound_lower[0] ) / length * (num_bins as f64) * ( 1.0 - epsilon ) ) as usize
                },
                Y => {
                    ( ( c[1] - self._bound._bound_lower[1] ) / length * (num_bins as f64) * ( 1.0 - epsilon ) ) as usize
                },
                Z => {
                    ( ( c[2] - self._bound._bound_lower[2] ) / length * (num_bins as f64) * ( 1.0 - epsilon ) ) as usize
                },
            };
            if bin_id >= ( num_bins as usize ) {
                println!("bin_id: {}, bin_len: {}", bin_id, num_bins );
                assert!( bin_id < ( num_bins as usize ) );
            }
            bins[bin_id] += 1;
            obj_bin.push( bin_id );
        }

        println!( "bins: {:?}", bins );

        let m = bins.iter().enumerate().max_by_key( | &x | x.1 ).unwrap();
        let split_bin_idx = m.0;

        println!( "split_bin_idx: {}", split_bin_idx );

        let mut bin_left : Vec< ( u64, &IBound ) > = vec![];
        let mut bin_right : Vec< ( u64, &IBound ) > = vec![];
        let mut idx_obj = 0;
        for i in obj_bin {
            let obj = objs[ idx_obj ];
            if i < split_bin_idx {
                bin_left.push( obj );
            } else {
                bin_right.push( obj );
            }
            idx_obj += 1;
        }

        if bin_left.len() > 0 {
            let mut l : NodeBvh = Default::default();
            println!("num left children: {}", bin_left.len() );
            l.build_node( num_bins, &bin_left[..] );
            self._left = BvhBranch::CHILD( Box::new( l ) );
        } else {
            self._left = BvhBranch::EMPTY;
        }

        if bin_right.len() > 0 {
            let mut r : NodeBvh = Default::default();
            println!("num right children: {}", bin_right.len() );
            r.build_node( num_bins, &bin_right[..] );
            self._right = BvhBranch::CHILD( Box::new( r ) );
        } else {
            self._right = BvhBranch::EMPTY;
        }

        Ok( () )
    }
}

impl i_spatial_accel::ISpatialAccel for Bvh {
    fn query( & self, input: &IBound ) -> Vec< u64 >
    {
        unimplemented!();
    }
    fn build_all( & mut self, objs: &[ (u64, &IBound) ] ) -> Result< (), & 'static str >
    {
        //initiate top down construction
        self._root.build_node( self._bins, objs )
    }
}

impl Bvh {
    pub fn init( bins: u32 ) -> Bvh {
        assert!( bins != 0 );
        Bvh {
            _root: NodeBvh {
                _bound: AxisAlignedBBox {
                    _bound_lower: [ f64::NEG_INFINITY; 3 ],
                    _bound_upper: [ f64::INFINITY; 3 ],
                },
                _left: BvhBranch::EMPTY,
                _right: BvhBranch::EMPTY,
                _obj: u64::MAX,
            },
            _bins: bins,
        }
    }
}
<commit_msg>corrected bvh median bin splitting logic.<commit_after>use std::boxed::Box;
use std::f64;
use std::u64;

use interface::i_spatial_accel;
use interface::i_bound::{ IBound, BoundType };

use implement::math::bound::AxisAlignedBBox;

/// implementation of spatial acceleration using bounding volume hierarchy with surface area heuristic
pub struct Bvh {
    _root: NodeBvh,
    _bins: u32,
}

///internal node structure for Bvh
pub struct NodeBvh {
    _bound: AxisAlignedBBox,
    _left: BvhBranch,
    _right: BvhBranch,
    _obj: u64, //leaf data
}

pub enum BvhBranch {
    CHILD(Box< NodeBvh >),
    EMPTY,
}

impl Default for NodeBvh {
    fn default() -> NodeBvh {
        NodeBvh {
            _bound: AxisAlignedBBox {
                _bound_lower: [ f64::NEG_INFINITY; 3 ],
                _bound_upper: [ f64::INFINITY; 3 ],
            },
            _left: BvhBranch::EMPTY,
            _right: BvhBranch::EMPTY,
            _obj: u64::MAX,
        }
    }
}

impl NodeBvh {
    pub fn init_branches( b: AxisAlignedBBox, l: BvhBranch, r: BvhBranch ) -> NodeBvh {
        NodeBvh {
            _bound: b,
            _left: l,
            _right: r,
            _obj: u64::MAX,
        }
    }
    pub fn init_leaf( b: AxisAlignedBBox, o: u64 ) -> NodeBvh {
        NodeBvh {
            _bound: b,
            _left: BvhBranch::EMPTY,
            _right: BvhBranch::EMPTY,
            _obj: o,
        }
    }
    pub fn build_node( & mut self, num_bins: u32, objs: &[ (u64, &IBound) ] ) -> Result< (), & 'static str > {
        for i in objs {
            match i.1.get_type() {
                BoundType::AxisAlignBox => (),
                _ => return Err( "unsupported bound type" )
            }
        }
        let b = objs.iter().cloned().map( |x| x.1 ).collect::<Vec< &IBound > >();
        let mut u : AxisAlignedBBox = Default::default();
        u.get_union( &b[..] );

        println!( "bound union: {:?}", u );

        //check for leaf condition
        if objs.len() == 1 {
            self._bound = u;
            self._obj = objs[0].0;
            return Ok( () )
        }

        //todo: execute alternative branch when number of objects are low
        //todo: surface area heuristic

        //get the longest axis of the bounding box
        let ( ref axis, ref length ) = u.get_longest_axis();

        self._bound = u;

        println!( "axis length: {}", length );

        let c = self._bound.get_centroid();
        let bin_len = length / num_bins as f64;

        let mut bin_offsets = vec![];
        for i in 0..num_bins {
            match axis {
                X => bin_offsets.push( i as f64 * bin_len + self._bound._bound_lower[0] ),
                Y => bin_offsets.push( i as f64 * bin_len + self._bound._bound_lower[1] ),
                Z => bin_offsets.push( i as f64 * bin_len + self._bound._bound_lower[2] ),
            }
        }

        //bin objects using their centroids in the direction of the longest axis
        let mut bins = vec![ 0; num_bins as usize ];
        let mut obj_bin = vec![];
        let epsilon = 0.001f64;
        for i in objs {
            let c = i.1.get_centroid();
            println!("centroid: {:?}", c );
            let bin_id = match axis {
                X => {
                    ( ( c[0] - self._bound._bound_lower[0] ) / length * (num_bins as f64) * ( 1.0 - epsilon ) ) as usize
                },
                Y => {
                    ( ( c[1] - self._bound._bound_lower[1] ) / length * (num_bins as f64) * ( 1.0 - epsilon ) ) as usize
                },
                Z => {
                    ( ( c[2] - self._bound._bound_lower[2] ) / length * (num_bins as f64) * ( 1.0 - epsilon ) ) as usize
                },
            };
            if bin_id >= ( num_bins as usize ) {
                println!("bin_id: {}, bin_len: {}", bin_id, num_bins );
                assert!( bin_id < ( num_bins as usize ) );
            }
            bins[bin_id] += 1;
            obj_bin.push( bin_id );
        }

        println!( "bins: {:?}", bins );

        let sum = bins.iter_mut().fold( 0, | acc, x | {
            let s = acc + *x;
            *x += acc;
            s
        }
        );
        let median = sum / 2;

        let mut split_bin_idx = 0;
        for (idx, i) in bins.iter().enumerate() {
            if *i > median {
                break;
            }
            split_bin_idx += 1;
        }

        println!( "split_bin_idx: {}", split_bin_idx );

        let mut bin_left : Vec< ( u64, &IBound ) > = vec![];
        let mut bin_right : Vec< ( u64, &IBound ) > = vec![];
        let mut idx_obj = 0;
        for i in obj_bin {
            let obj = objs[ idx_obj ];
            if i < split_bin_idx {
                bin_left.push( obj );
            } else {
                bin_right.push( obj );
            }
            idx_obj += 1;
        }

        if bin_left.len() > 0 {
            let mut l : NodeBvh = Default::default();
            println!("num left children: {}", bin_left.len() );
            l.build_node( num_bins, &bin_left[..] );
            self._left = BvhBranch::CHILD( Box::new( l ) );
        } else {
            self._left = BvhBranch::EMPTY;
        }

        if bin_right.len() > 0 {
            let mut r : NodeBvh = Default::default();
            println!("num right children: {}", bin_right.len() );
            r.build_node( num_bins, &bin_right[..] );
            self._right = BvhBranch::CHILD( Box::new( r ) );
        } else {
            self._right = BvhBranch::EMPTY;
        }

        Ok( () )
    }
}

impl i_spatial_accel::ISpatialAccel for Bvh {
    fn query( & self, input: &IBound ) -> Vec< u64 >
    {
        unimplemented!();
    }
    fn build_all( & mut self, objs: &[ (u64, &IBound) ] ) -> Result< (), & 'static str >
    {
        //initiate top down construction
        if self._bins == 0 {
            return Err( "bvh bin count cannot be zero" )
        }
        self._root.build_node( self._bins, objs )
    }
}

impl Bvh {
    pub fn init( bins: u32 ) -> Bvh {
        assert!( bins != 0 );
        Bvh {
            _root: NodeBvh {
                _bound: AxisAlignedBBox {
                    _bound_lower: [ f64::NEG_INFINITY; 3 ],
                    _bound_upper: [ f64::INFINITY; 3 ],
                },
                _left: BvhBranch::EMPTY,
                _right: BvhBranch::EMPTY,
                _obj: u64::MAX,
            },
            _bins: bins,
        }
    }
}
<|endoftext|>