<commit_before>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// 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.

use syntax::ext::base::ExtCtxt;
use syntax::parse::new_parse_sess_special_handler;
use syntax::ext::expand::ExpansionConfig;
use syntax::ext::quote::rt::ExtParseUtils;
use syntax::diagnostic::{Emitter, RenderSpan, Level, mk_span_handler, mk_handler};
use syntax::codemap;
use syntax::codemap::{Span, CodeMap};
use std::gc::Gc;

use parser::Parser;
use node;

#[test]
fn parse_anonymous_node() {
  with_parsed_node("root {}", |node| {
    assert!(node.name == None);
    assert!(node.path == "root".to_str());
    assert!(node.attributes.len() == 0);
    assert!(node.subnodes.len() == 0);
  });
}

#[test]
fn parse_node_with_name() {
  with_parsed_node("test@root {}", |node| {
    assert!(node.name == Some("test".to_str()));
    assert!(node.path == "root".to_str());
    assert!(node.attributes.len() == 0);
    assert!(node.subnodes.len() == 0);
  });
}

#[test]
fn fails_to_parse_node_with_bad_name() {
  fails_to_parse("1@root {}");
  fails_to_parse("@root {}");
  fails_to_parse("+@root {}");
}

#[test]
fn fails_to_parse_node_with_bad_path() {
  fails_to_parse("test root {}");
  fails_to_parse("test@ {}");
  fails_to_parse("test@- {}");
}

#[test]
fn parse_node_with_no_body() {
  with_parsed_node("test@root;", |_| {
    assert!(true);
  });
}

#[test]
fn parse_node_with_numeric_path() {
  with_parsed_node("test@1 {}", |node| {
    assert!(node.path == "1".to_str());
  });
}

#[test]
fn parse_attributes() {
  with_parsed_node("test@root { a = \"value\"; b = 1; c = &ref; }", |node| {
    assert!(node.get_string_attr("a") == Some(&"value".to_str()));
    assert!(node.get_int_attr("b")    == Some(1));
    assert!(node.get_ref_attr("c")    == Some(&"ref".to_str()));
  });
}

#[test]
fn parse_string_attribute() {
  with_parsed_node("test@root { key = \"value\"; }", |node| {
    assert!(node.get_string_attr("key") == Some(&"value".to_str()));
  });
}

#[test]
fn parse_integer_attribute() {
  with_parsed_node("test@root { key = 10; }", |node| {
    assert!(node.get_int_attr("key") == Some(10));
  });
}

#[test]
fn parse_ref_attribute() {
  with_parsed_node("test@root { key = &ref; }", |node| {
    assert!(node.get_ref_attr("key") == Some(&"ref".to_str()));
  });
}

#[test]
fn fails_to_parse_duplicate_attributes() {
  fails_to_parse("test@root { a = 1; a = \"2\"; }");
}

#[test]
fn fails_to_parse_malformed_attibute() {
  fails_to_parse("test@root { k = \"value\" }");
  fails_to_parse("test@root { 1 = \"value\"; }");
  fails_to_parse("test@root { k = v; }");
  fails_to_parse("test@root { k = 10u8; }");
  fails_to_parse("test@root { k = 10i8; }");
  fails_to_parse("test@root { k = -42; }");
  fails_to_parse("test@root { k = &1; }");
  fails_to_parse("test@root { k = &\"q\"; }");
}

#[test]
fn parse_named_subnode() {
  with_parsed_node("test@root { child; }", |node| {
    assert!(node.subnodes.len() == 1);
  });
}

#[test]
fn parse_anonymous_subnode() {
  with_parsed_node("test@root { sub@child; }", |node| {
    assert!(node.subnodes.len() == 1);
  });
}

// helpers
fn fails_to_parse(src: &str) {
  with_parsed_tts(src, |failed, pt| {
    assert!(failed == true);
    assert!(pt.is_none());
  });
}

fn with_parsed(src: &str, block: |node: &node::PlatformTree|) {
  with_parsed_tts(src, |failed, pt| {
    assert!(failed == false);
    block(&pt.unwrap());
  });
}

fn with_parsed_node(src: &str, block: |node: &Gc<node::Node>|) {
  with_parsed(src, |pt| {
    assert!(pt.nodes.len() == 1);
    block(pt.nodes.get(0));
  });
}

fn with_parsed_tts(src: &str, block: |bool, Option<node::PlatformTree>|) {
  let mut failed = false;
  let failptr = &mut failed as *mut bool;
  let ce = box CustomEmmiter::new(failptr);
  let sh = mk_span_handler(mk_handler(ce), CodeMap::new());
  let parse_sess = new_parse_sess_special_handler(sh);
  let cfg = Vec::new();
  let ecfg = ExpansionConfig {
    deriving_hash_type_parameter: false,
    crate_id: from_str("test").unwrap(),
  };
  let cx = ExtCtxt::new(&parse_sess, cfg, ecfg);
  let tts = cx.parse_tts(src.to_str());

  let mut parser = Parser::new(&cx, tts.as_slice());
  let nodes = parser.parse_platformtree();

  block(failed, nodes);
}

struct CustomEmmiter {
  failed: *mut bool
}

impl CustomEmmiter {
  pub fn new(fp: *mut bool) -> CustomEmmiter {
    CustomEmmiter {
      failed: fp,
    }
  }
}

impl Emitter for CustomEmmiter {
  fn emit(&mut self, _: Option<(&codemap::CodeMap, Span)>, m: &str, l: Level) {
    unsafe { *self.failed = true };
    println!("{} {}", l, m);
  }
  fn custom_emit(&mut self, _: &codemap::CodeMap, _: RenderSpan, _: &str,
      _: Level) {
    fail!();
  }
}
<commit_msg>Added tests for subnodes with body.<commit_after>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// 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.

use syntax::ext::base::ExtCtxt;
use syntax::parse::new_parse_sess_special_handler;
use syntax::ext::expand::ExpansionConfig;
use syntax::ext::quote::rt::ExtParseUtils;
use syntax::diagnostic::{Emitter, RenderSpan, Level, mk_span_handler, mk_handler};
use syntax::codemap;
use syntax::codemap::{Span, CodeMap};
use std::gc::Gc;

use parser::Parser;
use node;

#[test]
fn parse_anonymous_node() {
  with_parsed_node("root {}", |node| {
    assert!(node.name == None);
    assert!(node.path == "root".to_str());
    assert!(node.attributes.len() == 0);
    assert!(node.subnodes.len() == 0);
  });
}

#[test]
fn parse_node_with_name() {
  with_parsed_node("test@root {}", |node| {
    assert!(node.name == Some("test".to_str()));
    assert!(node.path == "root".to_str());
    assert!(node.attributes.len() == 0);
    assert!(node.subnodes.len() == 0);
  });
}

#[test]
fn fails_to_parse_node_with_bad_name() {
  fails_to_parse("1@root {}");
  fails_to_parse("@root {}");
  fails_to_parse("+@root {}");
}

#[test]
fn fails_to_parse_node_with_bad_path() {
  fails_to_parse("test root {}");
  fails_to_parse("test@ {}");
  fails_to_parse("test@- {}");
}

#[test]
fn parse_node_with_no_body() {
  with_parsed_node("test@root;", |_| {
    assert!(true);
  });
}

#[test]
fn parse_node_with_numeric_path() {
  with_parsed_node("test@1 {}", |node| {
    assert!(node.path == "1".to_str());
  });
}

#[test]
fn parse_attributes() {
  with_parsed_node("test@root { a = \"value\"; b = 1; c = &ref; }", |node| {
    assert!(node.get_string_attr("a") == Some(&"value".to_str()));
    assert!(node.get_int_attr("b")    == Some(1));
    assert!(node.get_ref_attr("c")    == Some(&"ref".to_str()));
  });
}

#[test]
fn parse_string_attribute() {
  with_parsed_node("test@root { key = \"value\"; }", |node| {
    assert!(node.get_string_attr("key") == Some(&"value".to_str()));
  });
}

#[test]
fn parse_integer_attribute() {
  with_parsed_node("test@root { key = 10; }", |node| {
    assert!(node.get_int_attr("key") == Some(10));
  });
}

#[test]
fn parse_ref_attribute() {
  with_parsed_node("test@root { key = &ref; }", |node| {
    assert!(node.get_ref_attr("key") == Some(&"ref".to_str()));
  });
}

#[test]
fn fails_to_parse_duplicate_attributes() {
  fails_to_parse("test@root { a = 1; a = \"2\"; }");
}

#[test]
fn fails_to_parse_malformed_attibute() {
  fails_to_parse("test@root { k = \"value\" }");
  fails_to_parse("test@root { 1 = \"value\"; }");
  fails_to_parse("test@root { k = v; }");
  fails_to_parse("test@root { k = 10u8; }");
  fails_to_parse("test@root { k = 10i8; }");
  fails_to_parse("test@root { k = -42; }");
  fails_to_parse("test@root { k = &1; }");
  fails_to_parse("test@root { k = &\"q\"; }");
}

#[test]
fn parse_named_subnode() {
  with_parsed_node("test@root { child; }", |node| {
    assert!(node.subnodes.len() == 1);
  });
  with_parsed_node("test@root { child {} }", |node| {
    assert!(node.subnodes.len() == 1);
  });
}

#[test]
fn parse_anonymous_subnode() {
  with_parsed_node("test@root { sub@child; }", |node| {
    assert!(node.subnodes.len() == 1);
  });
  with_parsed_node("test@root { sub@child {} }", |node| {
    assert!(node.subnodes.len() == 1);
  });
}

// helpers
fn fails_to_parse(src: &str) {
  with_parsed_tts(src, |failed, pt| {
    assert!(failed == true);
    assert!(pt.is_none());
  });
}

fn with_parsed(src: &str, block: |node: &node::PlatformTree|) {
  with_parsed_tts(src, |failed, pt| {
    assert!(failed == false);
    block(&pt.unwrap());
  });
}

fn with_parsed_node(src: &str, block: |node: &Gc<node::Node>|) {
  with_parsed(src, |pt| {
    assert!(pt.nodes.len() == 1);
    block(pt.nodes.get(0));
  });
}

fn with_parsed_tts(src: &str, block: |bool, Option<node::PlatformTree>|) {
  let mut failed = false;
  let failptr = &mut failed as *mut bool;
  let ce = box CustomEmmiter::new(failptr);
  let sh = mk_span_handler(mk_handler(ce), CodeMap::new());
  let parse_sess = new_parse_sess_special_handler(sh);
  let cfg = Vec::new();
  let ecfg = ExpansionConfig {
    deriving_hash_type_parameter: false,
    crate_id: from_str("test").unwrap(),
  };
  let cx = ExtCtxt::new(&parse_sess, cfg, ecfg);
  let tts = cx.parse_tts(src.to_str());

  let mut parser = Parser::new(&cx, tts.as_slice());
  let nodes = parser.parse_platformtree();

  block(failed, nodes);
}

struct CustomEmmiter {
  failed: *mut bool
}

impl CustomEmmiter {
  pub fn new(fp: *mut bool) -> CustomEmmiter {
    CustomEmmiter {
      failed: fp,
    }
  }
}

impl Emitter for CustomEmmiter {
  fn emit(&mut self, _: Option<(&codemap::CodeMap, Span)>, m: &str, l: Level) {
    unsafe { *self.failed = true };
    println!("{} {}", l, m);
  }
  fn custom_emit(&mut self, _: &codemap::CodeMap, _: RenderSpan, _: &str,
      _: Level) {
    fail!();
  }
}
<|endoftext|>


<commit_before>use gltf_json as json;

use std::{fs, mem};

use json::validation::Checked::Valid;
use std::borrow::Cow;
use std::io::Write;

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
enum Output {
    /// Output standard glTF.
    Standard,

    /// Output binary glTF.
    Binary,
}

#[derive(Copy, Clone, Debug)]
#[repr(C)]
struct Vertex {
    position: [f32; 3],
    color: [f32; 3],
}

fn align_to_multiple_of_four(n: &mut u32) {
    *n = (*n + 3) & !3;
}

fn to_padded_byte_vector<T>(vec: Vec<T>) -> Vec<u8> {
    let byte_length = vec.len() * mem::size_of::<T>();
    let byte_capacity = vec.capacity() * mem::size_of::<T>();
    let alloc = vec.into_boxed_slice();
    let ptr = Box::<[T]>::into_raw(alloc) as *mut u8;
    let mut new_vec = unsafe { Vec::from_raw_parts(ptr, byte_length, byte_capacity) };
    while new_vec.len() % 4 != 0 {
        new_vec.push(0); // pad to multiple of four bytes
    }
    new_vec
}

fn export(output: Output) {
    let triangle_vertices = vec![
        Vertex {
            position: [0.0, 0.5, 0.0],
            color: [1.0, 0.0, 0.0],
        },
        Vertex {
            position: [-0.5, -0.5, 0.0],
            color: [0.0, 1.0, 0.0],
        },
        Vertex {
            position: [0.5, -0.5, 0.0],
            color: [0.0, 0.0, 1.0],
        },
    ];

    let buffer_length = (triangle_vertices.len() * mem::size_of::<Vertex>()) as u32;
    let buffer = json::Buffer {
        byte_length: buffer_length,
        extensions: Default::default(),
        extras: Default::default(),
        name: None,
        uri: if output == Output::Standard {
            Some("buffer0.bin".into())
        } else {
            None
        },
    };
    let buffer_view = json::buffer::View {
        buffer: json::Index::new(0),
        byte_length: buffer.byte_length,
        byte_offset: None,
        byte_stride: Some(mem::size_of::<Vertex>() as u32),
        extensions: Default::default(),
        extras: Default::default(),
        name: None,
        target: Some(Valid(json::buffer::Target::ArrayBuffer)),
    };
    let positions = json::Accessor {
        buffer_view: Some(json::Index::new(0)),
        byte_offset: 0,
        count: triangle_vertices.len() as u32,
        component_type: Valid(json::accessor::GenericComponentType(
            json::accessor::ComponentType::F32,
        )),
        extensions: Default::default(),
        extras: Default::default(),
        type_: Valid(json::accessor::Type::Vec3),
        min: Some(json::Value::from(vec![-0.5f32, -0.5f32, 0.0f32])),
        max: Some(json::Value::from(vec![0.5f32, 0.5f32, 0.0f32])),
        name: None,
        normalized: false,
        sparse: None,
    };
    let colors = json::Accessor {
        buffer_view: Some(json::Index::new(0)),
        byte_offset: (3 * mem::size_of::<f32>()) as u32,
        count: triangle_vertices.len() as u32,
        component_type: Valid(json::accessor::GenericComponentType(
            json::accessor::ComponentType::F32,
        )),
        extensions: Default::default(),
        extras: Default::default(),
        type_: Valid(json::accessor::Type::Vec3),
        min: None,
        max: None,
        name: None,
        normalized: false,
        sparse: None,
    };

    let primitive = json::mesh::Primitive {
        attributes: {
            let mut map = std::collections::HashMap::new();
            map.insert(Valid(json::mesh::Semantic::Positions), json::Index::new(0));
            map.insert(Valid(json::mesh::Semantic::Colors(0)), json::Index::new(1));
            map
        },
        extensions: Default::default(),
        extras: Default::default(),
        indices: None,
        material: None,
        mode: Valid(json::mesh::Mode::Triangles),
        targets: None,
    };

    let mesh = json::Mesh {
        extensions: Default::default(),
        extras: Default::default(),
        name: None,
        primitives: vec![primitive],
        weights: None,
    };

    let node = json::Node {
        camera: None,
        children: None,
        extensions: Default::default(),
        extras: Default::default(),
        matrix: None,
        mesh: Some(json::Index::new(0)),
        name: None,
        rotation: None,
        scale: None,
        translation: None,
        skin: None,
        weights: None,
    };

    let root = json::Root {
        accessors: vec![positions, colors],
        buffers: vec![buffer],
        buffer_views: vec![buffer_view],
        meshes: vec![mesh],
        nodes: vec![node],
        scenes: vec![json::Scene {
            extensions: Default::default(),
            extras: Default::default(),
            name: None,
            nodes: vec![json::Index::new(0)],
        }],
        ..Default::default()
    };

    match output {
        Output::Standard => {
            let _ = fs::create_dir("triangle");

            let writer = fs::File::create("triangle/triangle.gltf").expect("I/O error");
            json::serialize::to_writer_pretty(writer, &root).expect("Serialization error");

            let bin = to_padded_byte_vector(triangle_vertices);
            let mut writer = fs::File::create("triangle/buffer0.bin").expect("I/O error");
            writer.write_all(&bin).expect("I/O error");
        }
        Output::Binary => {
            let json_string = json::serialize::to_string(&root).expect("Serialization error");
            let mut json_offset = json_string.len() as u32;
            align_to_multiple_of_four(&mut json_offset);
            let glb = gltf::binary::Glb {
                header: gltf::binary::Header {
                    magic: *b"glTF",
                    version: 2,
                    length: json_offset + buffer_length,
                },
                bin: Some(Cow::Owned(to_padded_byte_vector(triangle_vertices))),
                json: Cow::Owned(json_string.into_bytes()),
            };
            let writer = std::fs::File::create("triangle.glb").expect("I/O error");
            glb.to_writer(writer).expect("glTF binary output error");
        }
    }
}

fn main() {
    export(Output::Standard);
    export(Output::Binary);
}
<commit_msg>Export example: calculate bounding coordinates instead of using hardcoded values<commit_after>use gltf_json as json;

use std::{fs, mem};

use json::validation::Checked::Valid;
use std::borrow::Cow;
use std::io::Write;

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
enum Output {
    /// Output standard glTF.
    Standard,

    /// Output binary glTF.
    Binary,
}

#[derive(Copy, Clone, Debug)]
#[repr(C)]
struct Vertex {
    position: [f32; 3],
    color: [f32; 3],
}

/// Calculate bounding coordinates of a list of vertices, used for the clipping distance of the model
fn bounding_coords(points: &[Vertex]) -> ([f32; 3], [f32; 3]) {
    let mut min = [0., 0., 0.];
    let mut max = [0., 0., 0.];

    for point in points {
        let p = point.position;
        for i in 0..3 {
            min[i] = f32::min(min[i], p[i]);
            max[i] = f32::max(max[i], p[i]);
        }
    }
    (min, max)
}

fn align_to_multiple_of_four(n: &mut u32) {
    *n = (*n + 3) & !3;
}

fn to_padded_byte_vector<T>(vec: Vec<T>) -> Vec<u8> {
    let byte_length = vec.len() * mem::size_of::<T>();
    let byte_capacity = vec.capacity() * mem::size_of::<T>();
    let alloc = vec.into_boxed_slice();
    let ptr = Box::<[T]>::into_raw(alloc) as *mut u8;
    let mut new_vec = unsafe { Vec::from_raw_parts(ptr, byte_length, byte_capacity) };
    while new_vec.len() % 4 != 0 {
        new_vec.push(0); // pad to multiple of four bytes
    }
    new_vec
}

fn export(output: Output) {
    let triangle_vertices = vec![
        Vertex {
            position: [0.0, 0.5, 0.0],
            color: [1.0, 0.0, 0.0],
        },
        Vertex {
            position: [-0.5, -0.5, 0.0],
            color: [0.0, 1.0, 0.0],
        },
        Vertex {
            position: [0.5, -0.5, 0.0],
            color: [0.0, 0.0, 1.0],
        },
    ];

    let (min, max) = bounding_coords(&triangle_vertices);

    let buffer_length = (triangle_vertices.len() * mem::size_of::<Vertex>()) as u32;
    let buffer = json::Buffer {
        byte_length: buffer_length,
        extensions: Default::default(),
        extras: Default::default(),
        name: None,
        uri: if output == Output::Standard {
            Some("buffer0.bin".into())
        } else {
            None
        },
    };
    let buffer_view = json::buffer::View {
        buffer: json::Index::new(0),
        byte_length: buffer.byte_length,
        byte_offset: None,
        byte_stride: Some(mem::size_of::<Vertex>() as u32),
        extensions: Default::default(),
        extras: Default::default(),
        name: None,
        target: Some(Valid(json::buffer::Target::ArrayBuffer)),
    };
    let positions = json::Accessor {
        buffer_view: Some(json::Index::new(0)),
        byte_offset: 0,
        count: triangle_vertices.len() as u32,
        component_type: Valid(json::accessor::GenericComponentType(
            json::accessor::ComponentType::F32,
        )),
        extensions: Default::default(),
        extras: Default::default(),
        type_: Valid(json::accessor::Type::Vec3),
        min: Some(json::Value::from(Vec::from(min))),
        max: Some(json::Value::from(Vec::from(max))),
        name: None,
        normalized: false,
        sparse: None,
    };
    let colors = json::Accessor {
        buffer_view: Some(json::Index::new(0)),
        byte_offset: (3 * mem::size_of::<f32>()) as u32,
        count: triangle_vertices.len() as u32,
        component_type: Valid(json::accessor::GenericComponentType(
            json::accessor::ComponentType::F32,
        )),
        extensions: Default::default(),
        extras: Default::default(),
        type_: Valid(json::accessor::Type::Vec3),
        min: None,
        max: None,
        name: None,
        normalized: false,
        sparse: None,
    };

    let primitive = json::mesh::Primitive {
        attributes: {
            let mut map = std::collections::HashMap::new();
            map.insert(Valid(json::mesh::Semantic::Positions), json::Index::new(0));
            map.insert(Valid(json::mesh::Semantic::Colors(0)), json::Index::new(1));
            map
        },
        extensions: Default::default(),
        extras: Default::default(),
        indices: None,
        material: None,
        mode: Valid(json::mesh::Mode::Triangles),
        targets: None,
    };

    let mesh = json::Mesh {
        extensions: Default::default(),
        extras: Default::default(),
        name: None,
        primitives: vec![primitive],
        weights: None,
    };

    let node = json::Node {
        camera: None,
        children: None,
        extensions: Default::default(),
        extras: Default::default(),
        matrix: None,
        mesh: Some(json::Index::new(0)),
        name: None,
        rotation: None,
        scale: None,
        translation: None,
        skin: None,
        weights: None,
    };

    let root = json::Root {
        accessors: vec![positions, colors],
        buffers: vec![buffer],
        buffer_views: vec![buffer_view],
        meshes: vec![mesh],
        nodes: vec![node],
        scenes: vec![json::Scene {
            extensions: Default::default(),
            extras: Default::default(),
            name: None,
            nodes: vec![json::Index::new(0)],
        }],
        ..Default::default()
    };

    match output {
        Output::Standard => {
            let _ = fs::create_dir("triangle");

            let writer = fs::File::create("triangle/triangle.gltf").expect("I/O error");
            json::serialize::to_writer_pretty(writer, &root).expect("Serialization error");

            let bin = to_padded_byte_vector(triangle_vertices);
            let mut writer = fs::File::create("triangle/buffer0.bin").expect("I/O error");
            writer.write_all(&bin).expect("I/O error");
        }
        Output::Binary => {
            let json_string = json::serialize::to_string(&root).expect("Serialization error");
            let mut json_offset = json_string.len() as u32;
            align_to_multiple_of_four(&mut json_offset);
            let glb = gltf::binary::Glb {
                header: gltf::binary::Header {
                    magic: *b"glTF",
                    version: 2,
                    length: json_offset + buffer_length,
                },
                bin: Some(Cow::Owned(to_padded_byte_vector(triangle_vertices))),
                json: Cow::Owned(json_string.into_bytes()),
            };
            let writer = std::fs::File::create("triangle.glb").expect("I/O error");
            glb.to_writer(writer).expect("glTF binary output error");
        }
    }
}

fn main() {
    export(Output::Standard);
    export(Output::Binary);
}
<|endoftext|>


<commit_before>//! Complete system.

use std::collections::BinaryHeap;

use Result;
use platform::Platform;
use schedule::Schedule;
use traffic::Traffic;
use workload::Workload;

mod event;
mod history;
mod job;

pub use self::event::{Event, EventKind};
pub use self::history::History;
pub use self::job::Job;

/// A complete system.
pub struct System<P, S, T, W> where P: Platform, S: Schedule, T: Traffic, W: Workload {
    platform: P,
    schedule: S,
    traffic: T,
    workload: W,
    queue: BinaryHeap<Event>,
    history: History,
}

impl<P, S, T, W> System<P, S, T, W> where P: Platform, S: Schedule, T: Traffic, W: Workload {
    /// Create a system.
    pub fn new(platform: P, schedule: S, traffic: T, workload: W) -> Result<System<P, S, T, W>> {
        Ok(System {
            platform: platform,
            schedule: schedule,
            traffic: traffic,
            workload: workload,
            queue: BinaryHeap::new(),
            history: History::default(),
        })
    }

    /// Return the platform.
    #[inline(always)]
    pub fn platform(&self) -> &P {
        &self.platform
    }

    /// Return the history.
    #[inline(always)]
    pub fn history(&self) -> &History {
        &self.history
    }

    fn tick(&mut self) -> Result<()> {
        match (self.traffic.peek(), self.queue.peek()) {
            (Some(_), None) => {}
            (Some(&arrival), Some(&Event { time, .. })) if arrival < time => {},
            _ => return Ok(()),
        }

        let job = {
            let id = self.history.created;
            let arrival = some!(self.traffic.next(), "failed to generate an arrival");
            let pattern = some!(self.workload.next(arrival), "failed to generate a workload");
            self.history.created += 1;
            Job::new(id, arrival, pattern)
        };

        self.queue.push(Event::arrival(job.arrival, job.clone()));

        let decision = try!(self.schedule.push(&job));
        try!(self.platform.push(&job, &decision));

        self.queue.push(Event::start(decision.start, job.clone()));
        self.queue.push(Event::finish(decision.finish, job));

        Ok(())
    }
}

impl<P, S, T, W> Iterator for System<P, S, T, W>
    where P: Platform, S: Schedule, T: Traffic, W: Workload
{
    type Item = (Event, P::Data);

    fn next(&mut self) -> Option<Self::Item> {
        if let Err(error ) = self.tick() {
            error!(target: "System", "Failed to update the state ({}).", error);
            return None;
        }
        let event = match self.queue.pop() {
            Some(event) => event,
            _ => return None,
        };
        self.schedule.tick(event.time);
        self.history.remember(&event);
        self.platform.next(event.time).map(|data| (event, data))
    }
}
<commit_msg>A cosmetic change<commit_after>//! Complete system.

use std::collections::BinaryHeap;

use Result;
use platform::Platform;
use schedule::Schedule;
use traffic::Traffic;
use workload::Workload;

mod event;
mod history;
mod job;

pub use self::event::{Event, EventKind};
pub use self::history::History;
pub use self::job::Job;

/// A complete system.
pub struct System<P, S, T, W> where P: Platform, S: Schedule, T: Traffic, W: Workload {
    platform: P,
    schedule: S,
    traffic: T,
    workload: W,
    history: History,
    queue: BinaryHeap<Event>,
}

impl<P, S, T, W> System<P, S, T, W> where P: Platform, S: Schedule, T: Traffic, W: Workload {
    /// Create a system.
    pub fn new(platform: P, schedule: S, traffic: T, workload: W) -> Result<System<P, S, T, W>> {
        Ok(System {
            platform: platform,
            schedule: schedule,
            traffic: traffic,
            workload: workload,
            history: History::default(),
            queue: BinaryHeap::new(),
        })
    }

    /// Return the platform.
    #[inline(always)]
    pub fn platform(&self) -> &P {
        &self.platform
    }

    /// Return the history.
    #[inline(always)]
    pub fn history(&self) -> &History {
        &self.history
    }

    fn tick(&mut self) -> Result<()> {
        match (self.traffic.peek(), self.queue.peek()) {
            (Some(_), None) => {}
            (Some(&arrival), Some(&Event { time, .. })) if arrival < time => {},
            _ => return Ok(()),
        }

        let job = {
            let id = self.history.created;
            let arrival = some!(self.traffic.next(), "failed to generate an arrival");
            let pattern = some!(self.workload.next(arrival), "failed to generate a workload");
            self.history.created += 1;
            Job::new(id, arrival, pattern)
        };

        self.queue.push(Event::arrival(job.arrival, job.clone()));

        let decision = try!(self.schedule.push(&job));
        try!(self.platform.push(&job, &decision));

        self.queue.push(Event::start(decision.start, job.clone()));
        self.queue.push(Event::finish(decision.finish, job));

        Ok(())
    }
}

impl<P, S, T, W> Iterator for System<P, S, T, W>
    where P: Platform, S: Schedule, T: Traffic, W: Workload
{
    type Item = (Event, P::Data);

    fn next(&mut self) -> Option<Self::Item> {
        if let Err(error ) = self.tick() {
            error!(target: "System", "Failed to update the state ({}).", error);
            return None;
        }
        let event = match self.queue.pop() {
            Some(event) => event,
            _ => return None,
        };
        self.schedule.tick(event.time);
        self.history.remember(&event);
        self.platform.next(event.time).map(|data| (event, data))
    }
}
<|endoftext|>


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

//! Supports dynamic assertions in about what sort of thread is running and
//! what state it's in.

#![deny(missing_docs)]

use std::cell::RefCell;

bitflags! {
    /// A thread state flag, used for multiple assertions.
    pub flags ThreadState: u32 {
        /// Whether we're in a script thread.
        const SCRIPT          = 0x01,
        /// Whether we're in a layout thread.
        const LAYOUT          = 0x02,

        /// Whether we're in a script worker thread (actual web workers), or in
        /// a layout worker thread.
        const IN_WORKER       = 0x0100,

        /// Whether the current thread is going through a GC.
        const IN_GC           = 0x0200,
    }
}

macro_rules! thread_types ( ( $( $fun:ident = $flag:ident ; )* ) => (
    impl ThreadState {
        /// Whether the current thread is a worker thread.
        pub fn is_worker(self) -> bool {
            self.contains(IN_WORKER)
        }

        $(
            #[allow(missing_docs)]
            pub fn $fun(self) -> bool {
                self.contains($flag)
            }
        )*
    }
));

thread_types! {
    is_script = SCRIPT;
    is_layout = LAYOUT;
}

thread_local!(static STATE: RefCell<Option<ThreadState>> = RefCell::new(None));

/// Initializes the current thread state.
pub fn initialize(x: ThreadState) {
    STATE.with(|ref k| {
        if let Some(ref s) = *k.borrow() {
            panic!("Thread state already initialized as {:?}", s);
        }
        *k.borrow_mut() = Some(x);
    });
}

/// Initializes the current thread as a layout worker thread.
pub fn initialize_layout_worker_thread() {
    initialize(LAYOUT | IN_WORKER);
}

/// Gets the current thread state.
pub fn get() -> ThreadState {
    let state = STATE.with(|ref k| {
        match *k.borrow() {
            None => ThreadState::empty(), // Unknown thread.
            Some(s) => s,
        }
    });

    state
}

/// Enters into a given temporary state. Panics if re-entring.
pub fn enter(x: ThreadState) {
    let state = get();
    debug_assert!(!state.intersects(x));
    STATE.with(|ref k| {
        *k.borrow_mut() = Some(state | x);
    })
}

/// Exits a given temporary state.
pub fn exit(x: ThreadState) {
    let state = get();
    debug_assert!(state.contains(x));
    STATE.with(|ref k| {
        *k.borrow_mut() = Some(state & !x);
    })
}
<commit_msg>style: allow re-initializing thread_state as long as it's with the same value.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Supports dynamic assertions in about what sort of thread is running and
//! what state it's in.

#![deny(missing_docs)]

use std::cell::RefCell;

bitflags! {
    /// A thread state flag, used for multiple assertions.
    pub flags ThreadState: u32 {
        /// Whether we're in a script thread.
        const SCRIPT          = 0x01,
        /// Whether we're in a layout thread.
        const LAYOUT          = 0x02,

        /// Whether we're in a script worker thread (actual web workers), or in
        /// a layout worker thread.
        const IN_WORKER       = 0x0100,

        /// Whether the current thread is going through a GC.
        const IN_GC           = 0x0200,
    }
}

macro_rules! thread_types ( ( $( $fun:ident = $flag:ident ; )* ) => (
    impl ThreadState {
        /// Whether the current thread is a worker thread.
        pub fn is_worker(self) -> bool {
            self.contains(IN_WORKER)
        }

        $(
            #[allow(missing_docs)]
            pub fn $fun(self) -> bool {
                self.contains($flag)
            }
        )*
    }
));

thread_types! {
    is_script = SCRIPT;
    is_layout = LAYOUT;
}

thread_local!(static STATE: RefCell<Option<ThreadState>> = RefCell::new(None));

/// Initializes the current thread state.
pub fn initialize(x: ThreadState) {
    STATE.with(|ref k| {
        if let Some(ref s) = *k.borrow() {
            if x != *s {
                panic!("Thread state already initialized as {:?}", s);
            }
        }
        *k.borrow_mut() = Some(x);
    });
}

/// Initializes the current thread as a layout worker thread.
pub fn initialize_layout_worker_thread() {
    initialize(LAYOUT | IN_WORKER);
}

/// Gets the current thread state.
pub fn get() -> ThreadState {
    let state = STATE.with(|ref k| {
        match *k.borrow() {
            None => ThreadState::empty(), // Unknown thread.
            Some(s) => s,
        }
    });

    state
}

/// Enters into a given temporary state. Panics if re-entring.
pub fn enter(x: ThreadState) {
    let state = get();
    debug_assert!(!state.intersects(x));
    STATE.with(|ref k| {
        *k.borrow_mut() = Some(state | x);
    })
}

/// Exits a given temporary state.
pub fn exit(x: ThreadState) {
    let state = get();
    debug_assert!(state.contains(x));
    STATE.with(|ref k| {
        *k.borrow_mut() = Some(state & !x);
    })
}
<|endoftext|>


<commit_before>use prost_build;

use tempfile;

use std::{collections::HashMap,
          fs,
          io::{Error,
               ErrorKind,
               Read,
               Result,
               Write},
          path::{Path,
                 PathBuf},
          process::Command};

use heck::SnakeCase;
use prost::Message;
use prost_build::{protoc,
                  protoc_include};
use prost_types::{DescriptorProto,
                  FileDescriptorProto,
                  FileDescriptorSet};

type Module = Vec<String>;

fn main() { generate_protocols(); }

fn generate_protocols() {
    let mut config = prost_build::Config::new();
    config.type_attribute(".", "#[derive(Serialize, Deserialize)]");
    config.type_attribute(".", "#[serde(rename_all = \"kebab-case\")]");
    config.compile_protos(&protocol_files(), &protocol_includes())
          .expect("protocols");
    compile_proto_impls(&protocol_files(), &protocol_includes()).expect("protocol-impls");
}

fn protocol_files() -> Vec<String> {
    let mut files = vec![];
    for entry in fs::read_dir("protocols").unwrap() {
        let file = entry.unwrap();
        // skip vim temp files
        if file.file_name().to_str().unwrap().starts_with('.') {
            continue;
        }
        if file.metadata().unwrap().is_file() {
            files.push(file.path().to_string_lossy().into_owned());
        }
    }
    files
}

fn protocol_includes() -> Vec<String> { vec!["protocols".to_string()] }

fn compile_proto_impls<P>(protos: &[P], includes: &[P]) -> Result<()>
    where P: AsRef<Path>
{
    let target = PathBuf::from("src/generated");
    let tmp = tempfile::TempDir::new()?;
    let descriptor_set = tmp.path().join("prost-descriptor-set");

    let mut cmd = Command::new(protoc());
    cmd.arg("--include_imports")
       .arg("--include_source_info")
       .arg("-o")
       .arg(&descriptor_set);

    for include in includes {
        cmd.arg("-I").arg(include.as_ref());
    }

    // Set the protoc include after the user includes in case the user wants to
    // override one of the built-in .protos.
    cmd.arg("-I").arg(protoc_include());

    for proto in protos {
        cmd.arg(proto.as_ref());
    }

    let output = cmd.output()?;
    if !output.status.success() {
        return Err(Error::new(ErrorKind::Other,
                              format!("protoc failed: {}",
                                      String::from_utf8_lossy(&output.stderr))));
    }

    let mut buf = Vec::new();
    fs::File::open(descriptor_set)?.read_to_end(&mut buf)?;
    let descriptor_set = FileDescriptorSet::decode(buf.as_slice())?;

    let modules = generate(descriptor_set.file);
    for (module, content) in modules {
        let mut filename = module.join(".");
        filename.push_str(".impl.rs");
        let mut file = fs::File::create(target.join(filename))?;
        file.write_all(content.as_bytes())?;
        file.flush()?;
    }

    Ok(())
}

fn generate(files: Vec<FileDescriptorProto>) -> HashMap<Module, String> {
    let mut modules = HashMap::new();
    for file in files {
        let module = module(&file);
        let mut buf = modules.entry(module).or_insert_with(String::new);
        buf.push_str("use crate::message;\n\n");
        for msg in file.message_type.iter() {
            add_message(msg, &mut buf);
        }
    }
    modules
}

pub fn module(file: &FileDescriptorProto) -> Module {
    file.package()
        .split('.')
        .filter(|s| !s.is_empty())
        .map(to_snake)
        .collect()
}

fn add_message(msg: &DescriptorProto, buf: &mut String) {
    if msg.name() != "ApplicationEnvironment" {
        buf.push_str(&format!("impl message::MessageStatic for {} {{\n", msg.name()));
        buf.push_str(&format!("    const MESSAGE_ID: &'static str = \"{}\";\n", msg.name()));
        buf.push_str("}\n");
    }
}

/// Converts a `camelCase` or `SCREAMING_SNAKE_CASE` identifier to a `lower_snake` case Rust field
/// identifier.
pub fn to_snake(s: &str) -> String {
    let mut ident = s.to_snake_case();

    // Add a trailing underscore if the identifier matches a Rust keyword
    // (https://doc.rust-lang.org/grammar.html#keywords).
    match &ident[..] {
        "abstract" | "alignof" | "as" | "become" | "box" | "break" | "const" | "continue"
        | "crate" | "do" | "else" | "enum" | "extern" | "false" | "final" | "fn" | "for" | "if"
        | "impl" | "in" | "let" | "loop" | "macro" | "match" | "mod" | "move" | "mut"
        | "offsetof" | "override" | "priv" | "proc" | "pub" | "pure" | "ref" | "return"
        | "self" | "sizeof" | "static" | "struct" | "super" | "trait" | "true" | "type"
        | "typeof" | "unsafe" | "unsized" | "use" | "virtual" | "where" | "while" | "yield" => {
            ident.push('_');
        }
        _ => (),
    }
    ident
}
<commit_msg>sup-protocol: Inline generate_protocols function<commit_after>use prost_build;

use tempfile;

use std::{collections::HashMap,
          fs,
          io::{Error,
               ErrorKind,
               Read,
               Result,
               Write},
          path::{Path,
                 PathBuf},
          process::Command};

use heck::SnakeCase;
use prost::Message;
use prost_build::{protoc,
                  protoc_include};
use prost_types::{DescriptorProto,
                  FileDescriptorProto,
                  FileDescriptorSet};

type Module = Vec<String>;

fn main() {
    let mut config = prost_build::Config::new();
    config.type_attribute(".", "#[derive(Serialize, Deserialize)]");
    config.type_attribute(".", "#[serde(rename_all = \"kebab-case\")]");
    config.compile_protos(&protocol_files(), &protocol_includes())
          .expect("protocols");
    compile_proto_impls(&protocol_files(), &protocol_includes()).expect("protocol-impls");
}

fn protocol_files() -> Vec<String> {
    let mut files = vec![];
    for entry in fs::read_dir("protocols").unwrap() {
        let file = entry.unwrap();
        // skip vim temp files
        if file.file_name().to_str().unwrap().starts_with('.') {
            continue;
        }
        if file.metadata().unwrap().is_file() {
            files.push(file.path().to_string_lossy().into_owned());
        }
    }
    files
}

fn protocol_includes() -> Vec<String> { vec!["protocols".to_string()] }

fn compile_proto_impls<P>(protos: &[P], includes: &[P]) -> Result<()>
    where P: AsRef<Path>
{
    let target = PathBuf::from("src/generated");
    let tmp = tempfile::TempDir::new()?;
    let descriptor_set = tmp.path().join("prost-descriptor-set");

    let mut cmd = Command::new(protoc());
    cmd.arg("--include_imports")
       .arg("--include_source_info")
       .arg("-o")
       .arg(&descriptor_set);

    for include in includes {
        cmd.arg("-I").arg(include.as_ref());
    }

    // Set the protoc include after the user includes in case the user wants to
    // override one of the built-in .protos.
    cmd.arg("-I").arg(protoc_include());

    for proto in protos {
        cmd.arg(proto.as_ref());
    }

    let output = cmd.output()?;
    if !output.status.success() {
        return Err(Error::new(ErrorKind::Other,
                              format!("protoc failed: {}",
                                      String::from_utf8_lossy(&output.stderr))));
    }

    let mut buf = Vec::new();
    fs::File::open(descriptor_set)?.read_to_end(&mut buf)?;
    let descriptor_set = FileDescriptorSet::decode(buf.as_slice())?;

    let modules = generate(descriptor_set.file);
    for (module, content) in modules {
        let mut filename = module.join(".");
        filename.push_str(".impl.rs");
        let mut file = fs::File::create(target.join(filename))?;
        file.write_all(content.as_bytes())?;
        file.flush()?;
    }

    Ok(())
}

fn generate(files: Vec<FileDescriptorProto>) -> HashMap<Module, String> {
    let mut modules = HashMap::new();
    for file in files {
        let module = module(&file);
        let mut buf = modules.entry(module).or_insert_with(String::new);
        buf.push_str("use crate::message;\n\n");
        for msg in file.message_type.iter() {
            add_message(msg, &mut buf);
        }
    }
    modules
}

pub fn module(file: &FileDescriptorProto) -> Module {
    file.package()
        .split('.')
        .filter(|s| !s.is_empty())
        .map(to_snake)
        .collect()
}

fn add_message(msg: &DescriptorProto, buf: &mut String) {
    if msg.name() != "ApplicationEnvironment" {
        buf.push_str(&format!("impl message::MessageStatic for {} {{\n", msg.name()));
        buf.push_str(&format!("    const MESSAGE_ID: &'static str = \"{}\";\n", msg.name()));
        buf.push_str("}\n");
    }
}

/// Converts a `camelCase` or `SCREAMING_SNAKE_CASE` identifier to a `lower_snake` case Rust field
/// identifier.
pub fn to_snake(s: &str) -> String {
    let mut ident = s.to_snake_case();

    // Add a trailing underscore if the identifier matches a Rust keyword
    // (https://doc.rust-lang.org/grammar.html#keywords).
    match &ident[..] {
        "abstract" | "alignof" | "as" | "become" | "box" | "break" | "const" | "continue"
        | "crate" | "do" | "else" | "enum" | "extern" | "false" | "final" | "fn" | "for" | "if"
        | "impl" | "in" | "let" | "loop" | "macro" | "match" | "mod" | "move" | "mut"
        | "offsetof" | "override" | "priv" | "proc" | "pub" | "pure" | "ref" | "return"
        | "self" | "sizeof" | "static" | "struct" | "super" | "trait" | "true" | "type"
        | "typeof" | "unsafe" | "unsized" | "use" | "virtual" | "where" | "while" | "yield" => {
            ident.push('_');
        }
        _ => (),
    }
    ident
}
<|endoftext|>


<commit_before>use std::fmt::{Debug, Display, Formatter};
use std::rc::Rc;
use std::cell::RefCell;
use std::fmt;
use std::ops::Deref;
use std::process::exit;

use clap::ArgMatches;
use regex::Regex;

use runtime::Runtime;
use module::Module;

use storage::Store;
use storage::file::hash::FileHash;
use storage::file::id::FileID;
use storage::file::File;
use storage::parser::FileHeaderParser;
use storage::parser::Parser;
use storage::json::parser::JsonHeaderParser;

mod header;

use self::header::get_url_from_header;
use self::header::get_tags_from_header;

pub struct BM<'a> {
    rt: &'a Runtime<'a>,
}

impl<'a> BM<'a> {

    pub fn new(rt: &'a Runtime<'a>) -> BM<'a> {
        BM {
            rt: rt,
        }
    }

    fn runtime(&self) -> &Runtime {
        &self.rt
    }

    fn command_add(&self, matches: &ArgMatches) -> bool {
        use std::process::exit;
        use self::header::build_header;

        let parser = Parser::new(JsonHeaderParser::new(None));

        let url    = matches.value_of("url").map(String::from).unwrap(); // clap ensures this is present

        if !self.validate_url(&url, &parser) {
            error!("URL validation failed, exiting.");
            exit(1);
        } else {
            debug!("Verification succeeded");
        }

        let tags   = matches.value_of("tags").and_then(|s| {
            Some(s.split(",").map(String::from).collect())
        }).unwrap_or(vec![]);

        debug!("Building header with");
        debug!("    url  = '{:?}'", url);
        debug!("    tags = '{:?}'", tags);
        let header = build_header(url, tags);

        let fileid = self.rt.store().new_file_with_header(self, header);
        self.rt.store().load(&fileid).and_then(|file| {
            info!("Created file in memory: {}", fileid);
            Some(self.rt.store().persist(&parser, file))
        }).unwrap_or(false)
    }

    fn validate_url<HP>(&self, url: &String, parser: &Parser<HP>) -> bool
        where HP: FileHeaderParser
    {
        use util::is_url;

        if !is_url(url) {
            error!("Url '{}' is not a valid URL. Will not store.", url);
            return false;
        }

        let is_in_store = self.rt
            .store()
            .load_for_module(self, parser)
            .iter()
            .any(|file| {
                let f = file.deref().borrow();
                get_url_from_header(f.header()).map(|url_in_store| {
                    &url_in_store == url
                }).unwrap_or(false)
            });

        if is_in_store {
            error!("URL '{}' seems to be in the store already", url);
            return false;
        }

        return true;
    }

    fn command_list(&self, matches: &ArgMatches) -> bool {
        use ui::file::{FilePrinter, TablePrinter};
        use std::ops::Deref;

        let parser = Parser::new(JsonHeaderParser::new(None));
        let files  = self.rt.store().load_for_module(self, &parser);
        let printer = TablePrinter::new(self.rt.is_verbose(), self.rt.is_debugging());

        printer.print_files_custom(files.into_iter(),
            &|file| {
                let fl = file.deref().borrow();
                let hdr = fl.header();
                let url = get_url_from_header(hdr).unwrap_or(String::from("Parser error"));
                let tags = get_tags_from_header(hdr);

                debug!("Custom printer field: url  = '{:?}'", url);
                debug!("Custom printer field: tags = '{:?}'", tags);

                vec![url, tags.join(", ")]
            }
        );
        true
    }

    fn command_remove(&self, matches: &ArgMatches) -> bool {
        use std::process::exit;

        let result =
            if matches.is_present("id") {
                debug!("Removing by ID (Hash)");
                let hash = FileHash::from(matches.value_of("id").unwrap());
                self.remove_by_hash(hash)
            } else if matches.is_present("tags") {
                debug!("Removing by tags");
                let tags = matches.value_of("tags")
                                  .unwrap()
                                  .split(",")
                                  .map(String::from)
                                  .collect::<Vec<String>>();
                self.remove_by_tags(tags)
            } else if matches.is_present("match") {
                debug!("Removing by match");
                self.remove_by_match(String::from(matches.value_of("match").unwrap()))
            } else {
                error!("Unexpected error. Exiting");
                exit(1);
                false
            };

        if result {
            info!("Removing succeeded");
        } else {
            info!("Removing failed");
        }

        return result;
    }

    fn remove_by_hash(&self, hash: FileHash) -> bool {
        debug!("Removing for hash = '{:?}'", hash);

        self.get_files_by_id(hash)
            .iter()
            .map(|file| {
                debug!("File loaded, can remove now: {:?}", file);
                let f = file.deref().borrow();
                self.rt.store().remove(f.id().clone())
            })
            .all(|x| x)
    }

    fn remove_by_tags(&self, tags: Vec<String>) -> bool {
        use std::fs::remove_file;

        let parser = Parser::new(JsonHeaderParser::new(None));
        self.get_files_by_tags(tags)
            .iter()
            .map(|file| {
                let f = file.deref().borrow();
                self.rt.store().remove(f.id().clone())
            }).all(|x| x)
    }

    fn remove_by_match(&self, matcher: String) -> bool {
        use std::fs::remove_file;

        self.get_files_by_match(matcher)
            .iter()
            .map(|file| {
                let f = file.deref().borrow();
                self.rt.store().remove(f.id().clone())
            }).all(|x| x)
    }

    fn get_files(&self,
                 matches: &ArgMatches,
                 id_key: &'static str,
                 match_key: &'static str,
                 tag_key:   &'static str)
        -> Vec<Rc<RefCell<File>>>
    {
        if matches.is_present(id_key) {
            let hash = FileHash::from(matches.value_of(id_key).unwrap());
            self.get_files_by_id(hash)
        } else if matches.is_present(match_key) {
            let matcher = String::from(matches.value_of(match_key).unwrap());
            self.get_files_by_match(matcher)
        } else if matches.is_present(tag_key) {
            let tags = matches.value_of(tag_key)
                              .unwrap()
                              .split(",")
                              .map(String::from)
                              .collect::<Vec<String>>();
            self.get_files_by_tags(tags)
        } else {
            // get all files
            let parser = Parser::new(JsonHeaderParser::new(None));
            self.rt.store().load_for_module(self, &parser)
        }
    }

    fn get_files_by_id(&self, hash: FileHash) -> Vec<Rc<RefCell<File>>> {
        let parser = Parser::new(JsonHeaderParser::new(None));
        self.rt
            .store()
            .load_by_hash(self, &parser, hash)
            .map(|f| vec![f])
            .unwrap_or(vec![])
    }

    fn get_files_by_match(&self, matcher: String) -> Vec<Rc<RefCell<File>>> {
        let parser = Parser::new(JsonHeaderParser::new(None));
        let re = Regex::new(&matcher[..]).unwrap_or_else(|e| {
            error!("Cannot build regex out of '{}'", matcher);
            error!("{}", e);
            exit(1);
        });

        debug!("Compiled '{}' to regex: '{:?}'", matcher, re);

        self.rt
            .store()
            .load_for_module(self, &parser)
            .into_iter()
            .filter(|file| {
                let f   = file.deref().borrow();
                let url = get_url_from_header(f.header());
                debug!("url = {:?}", url);
                url.map(|u| {
                    debug!("Matching '{}' ~= '{}'", re.as_str(), u);
                    re.is_match(&u[..])
                }).unwrap_or(false)
            })
            .collect()
    }

    fn get_files_by_tags(&self, tags: Vec<String>) -> Vec<Rc<RefCell<File>>> {
        let parser = Parser::new(JsonHeaderParser::new(None));
        self.rt
            .store()
            .load_for_module(self, &parser)
            .into_iter()
            .filter(|file| {
                let f = file.deref().borrow();
                get_tags_from_header(f.header()).iter().any(|tag| {
                    tags.iter().any(|remtag| remtag == tag)
                })
            })
            .collect()
    }

}

impl<'a> Module<'a> for BM<'a> {

    fn exec(&self, matches: &ArgMatches) -> bool {
        match matches.subcommand_name() {
            Some("add") => {
                self.command_add(matches.subcommand_matches("add").unwrap())
            },

            Some("list") => {
                self.command_list(matches.subcommand_matches("list").unwrap())
            },

            Some("remove") => {
                self.command_remove(matches.subcommand_matches("remove").unwrap())
            },

            Some(_) | None => {
                info!("No command given, doing nothing");
                false
            },
        }
    }

    fn name(&self) -> &'static str {
        "bookmark"
    }
}

impl<'a> Debug for BM<'a> {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "BM");
        Ok(())
    }

}

<commit_msg>Use get_files() to filter files, remove afterwards<commit_after>use std::fmt::{Debug, Display, Formatter};
use std::rc::Rc;
use std::cell::RefCell;
use std::fmt;
use std::ops::Deref;
use std::process::exit;

use clap::ArgMatches;
use regex::Regex;

use runtime::Runtime;
use module::Module;

use storage::Store;
use storage::file::hash::FileHash;
use storage::file::id::FileID;
use storage::file::File;
use storage::parser::FileHeaderParser;
use storage::parser::Parser;
use storage::json::parser::JsonHeaderParser;

mod header;

use self::header::get_url_from_header;
use self::header::get_tags_from_header;

pub struct BM<'a> {
    rt: &'a Runtime<'a>,
}

impl<'a> BM<'a> {

    pub fn new(rt: &'a Runtime<'a>) -> BM<'a> {
        BM {
            rt: rt,
        }
    }

    fn runtime(&self) -> &Runtime {
        &self.rt
    }

    fn command_add(&self, matches: &ArgMatches) -> bool {
        use std::process::exit;
        use self::header::build_header;

        let parser = Parser::new(JsonHeaderParser::new(None));

        let url    = matches.value_of("url").map(String::from).unwrap(); // clap ensures this is present

        if !self.validate_url(&url, &parser) {
            error!("URL validation failed, exiting.");
            exit(1);
        } else {
            debug!("Verification succeeded");
        }

        let tags   = matches.value_of("tags").and_then(|s| {
            Some(s.split(",").map(String::from).collect())
        }).unwrap_or(vec![]);

        debug!("Building header with");
        debug!("    url  = '{:?}'", url);
        debug!("    tags = '{:?}'", tags);
        let header = build_header(url, tags);

        let fileid = self.rt.store().new_file_with_header(self, header);
        self.rt.store().load(&fileid).and_then(|file| {
            info!("Created file in memory: {}", fileid);
            Some(self.rt.store().persist(&parser, file))
        }).unwrap_or(false)
    }

    fn validate_url<HP>(&self, url: &String, parser: &Parser<HP>) -> bool
        where HP: FileHeaderParser
    {
        use util::is_url;

        if !is_url(url) {
            error!("Url '{}' is not a valid URL. Will not store.", url);
            return false;
        }

        let is_in_store = self.rt
            .store()
            .load_for_module(self, parser)
            .iter()
            .any(|file| {
                let f = file.deref().borrow();
                get_url_from_header(f.header()).map(|url_in_store| {
                    &url_in_store == url
                }).unwrap_or(false)
            });

        if is_in_store {
            error!("URL '{}' seems to be in the store already", url);
            return false;
        }

        return true;
    }

    fn command_list(&self, matches: &ArgMatches) -> bool {
        use ui::file::{FilePrinter, TablePrinter};
        use std::ops::Deref;

        let parser = Parser::new(JsonHeaderParser::new(None));
        let files  = self.rt.store().load_for_module(self, &parser);
        let printer = TablePrinter::new(self.rt.is_verbose(), self.rt.is_debugging());

        printer.print_files_custom(files.into_iter(),
            &|file| {
                let fl = file.deref().borrow();
                let hdr = fl.header();
                let url = get_url_from_header(hdr).unwrap_or(String::from("Parser error"));
                let tags = get_tags_from_header(hdr);

                debug!("Custom printer field: url  = '{:?}'", url);
                debug!("Custom printer field: tags = '{:?}'", tags);

                vec![url, tags.join(", ")]
            }
        );
        true
    }

    fn command_remove(&self, matches: &ArgMatches) -> bool {
        use std::process::exit;

        let (filtered, files) = self.get_files(matches, "id", "match", "tags");

        if !filtered {
            error!("Unexpected error. Exiting");
            exit(1);
        }

        let result = files
            .iter()
            .map(|file| {
                debug!("File loaded, can remove now: {:?}", file);
                let f = file.deref().borrow();
                self.rt.store().remove(f.id().clone())
            })
            .all(|x| x);

        if result {
            info!("Removing succeeded");
        } else {
            info!("Removing failed");
        }

        return result;
    }

    fn get_files(&self,
                 matches: &ArgMatches,
                 id_key: &'static str,
                 match_key: &'static str,
                 tag_key:   &'static str)
        -> (bool, Vec<Rc<RefCell<File>>>)
    {
        if matches.is_present(id_key) {
            let hash = FileHash::from(matches.value_of(id_key).unwrap());
            (true, self.get_files_by_id(hash))
        } else if matches.is_present(match_key) {
            let matcher = String::from(matches.value_of(match_key).unwrap());
            (true, self.get_files_by_match(matcher))
        } else if matches.is_present(tag_key) {
            let tags = matches.value_of(tag_key)
                              .unwrap()
                              .split(",")
                              .map(String::from)
                              .collect::<Vec<String>>();
            (true, self.get_files_by_tags(tags))
        } else {
            // get all files
            let parser = Parser::new(JsonHeaderParser::new(None));
            (false, self.rt.store().load_for_module(self, &parser))
        }
    }

    fn get_files_by_id(&self, hash: FileHash) -> Vec<Rc<RefCell<File>>> {
        let parser = Parser::new(JsonHeaderParser::new(None));
        self.rt
            .store()
            .load_by_hash(self, &parser, hash)
            .map(|f| vec![f])
            .unwrap_or(vec![])
    }

    fn get_files_by_match(&self, matcher: String) -> Vec<Rc<RefCell<File>>> {
        let parser = Parser::new(JsonHeaderParser::new(None));
        let re = Regex::new(&matcher[..]).unwrap_or_else(|e| {
            error!("Cannot build regex out of '{}'", matcher);
            error!("{}", e);
            exit(1);
        });

        debug!("Compiled '{}' to regex: '{:?}'", matcher, re);

        self.rt
            .store()
            .load_for_module(self, &parser)
            .into_iter()
            .filter(|file| {
                let f   = file.deref().borrow();
                let url = get_url_from_header(f.header());
                debug!("url = {:?}", url);
                url.map(|u| {
                    debug!("Matching '{}' ~= '{}'", re.as_str(), u);
                    re.is_match(&u[..])
                }).unwrap_or(false)
            })
            .collect()
    }

    fn get_files_by_tags(&self, tags: Vec<String>) -> Vec<Rc<RefCell<File>>> {
        let parser = Parser::new(JsonHeaderParser::new(None));
        self.rt
            .store()
            .load_for_module(self, &parser)
            .into_iter()
            .filter(|file| {
                let f = file.deref().borrow();
                get_tags_from_header(f.header()).iter().any(|tag| {
                    tags.iter().any(|remtag| remtag == tag)
                })
            })
            .collect()
    }

}

impl<'a> Module<'a> for BM<'a> {

    fn exec(&self, matches: &ArgMatches) -> bool {
        match matches.subcommand_name() {
            Some("add") => {
                self.command_add(matches.subcommand_matches("add").unwrap())
            },

            Some("list") => {
                self.command_list(matches.subcommand_matches("list").unwrap())
            },

            Some("remove") => {
                self.command_remove(matches.subcommand_matches("remove").unwrap())
            },

            Some(_) | None => {
                info!("No command given, doing nothing");
                false
            },
        }
    }

    fn name(&self) -> &'static str {
        "bookmark"
    }
}

impl<'a> Debug for BM<'a> {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "BM");
        Ok(())
    }

}

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2017 Genymobile
 *
 * 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.
 */

use std::cell::RefCell;
use std::io;
use std::ptr;
use std::rc::{Rc, Weak};
use log::Level;

use super::binary;
use super::client::{Client, ClientChannel};
use super::connection::{Connection, ConnectionId};
use super::ipv4_header::Protocol;
use super::ipv4_packet::Ipv4Packet;
use super::selector::Selector;
use super::tcp_connection::TcpConnection;
use super::udp_connection::UdpConnection;

const TAG: &'static str = "Router";

pub struct Router {
    client: Weak<RefCell<Client>>,
    // there are typically only few connections per client, HashMap would be less efficient
    connections: Vec<Rc<RefCell<Connection>>>,
}

impl Router {
    pub fn new() -> Self {
        Self {
            client: Weak::new(),
            connections: Vec::new(),
        }
    }

    // expose client initialization after construction to break cyclic initialization dependencies
    pub fn set_client(&mut self, client: Weak<RefCell<Client>>) {
        self.client = client;
    }

    pub fn send_to_network(
        &mut self,
        selector: &mut Selector,
        client_channel: &mut ClientChannel,
        ipv4_packet: &Ipv4Packet,
    ) {
        if ipv4_packet.is_valid() {
            match self.connection(selector, ipv4_packet) {
                Ok(index) => {
                    let closed = {
                        let connection_ref = self.connections.get_mut(index).unwrap();
                        let mut connection = connection_ref.borrow_mut();
                        connection.send_to_network(selector, client_channel, ipv4_packet);
                        connection.is_closed()
                    };
                    if closed {
                        // the connection is closed, remove it
                        self.connections.swap_remove(index);
                    }
                }
                Err(err) => error!(target: TAG, "Cannot create route, dropping packet: {}", err),
            }
        } else {
            warn!(target: TAG, "Dropping invalid packet");
            if log_enabled!(target: TAG, Level::Trace) {
                trace!(target: TAG, "{}", binary::to_string(ipv4_packet.raw()));
            }
        }
    }

    fn connection(
        &mut self,
        selector: &mut Selector,
        ipv4_packet: &Ipv4Packet,
    ) -> io::Result<usize> {
        let (ipv4_header_data, transport_header_data) = ipv4_packet.headers_data();
        let transport_header_data = transport_header_data.expect("No transport");
        let id = ConnectionId::from_headers(ipv4_header_data, transport_header_data);
        let index = match self.find_index(&id) {
            Some(index) => index,
            None => {
                let connection =
                    Self::create_connection(selector, id, self.client.clone(), ipv4_packet)?;
                let index = self.connections.len();
                self.connections.push(connection);
                index
            }
        };
        Ok(index)
    }

    fn create_connection(
        selector: &mut Selector,
        id: ConnectionId,
        client: Weak<RefCell<Client>>,
        ipv4_packet: &Ipv4Packet,
    ) -> io::Result<Rc<RefCell<Connection>>> {
        let (ipv4_header, transport_header) = ipv4_packet.headers();
        let transport_header = transport_header.expect("No transport");
        match id.protocol() {
            Protocol::Tcp => Ok(TcpConnection::new(
                selector,
                id,
                client,
                ipv4_header,
                transport_header,
            )?),
            Protocol::Udp => Ok(UdpConnection::new(
                selector,
                id,
                client,
                ipv4_header,
                transport_header,
            )?),
            p => Err(io::Error::new(
                io::ErrorKind::Other,
                format!("Unsupported protocol: {:?}", p),
            )),
        }
    }

    fn find_index(&self, id: &ConnectionId) -> Option<usize> {
        self.connections.iter().position(|connection| {
            connection.borrow().id() == id
        })
    }

    pub fn remove(&mut self, connection: &Connection) {
        let index = self.connections.iter().position(|item| {
            // compare pointers to find the connection to remove
            ptr::eq(connection, item.as_ptr())
        });
        // the connection may have already been removed by send_to_network()
        if let Some(index) = index {
            self.connections.swap_remove(index);
        }
    }

    pub fn clear(&mut self, selector: &mut Selector) {
        for connection in &mut self.connections {
            connection.borrow_mut().close(selector);
        }
        self.connections.clear();
    }

    pub fn clean_expired_connections(&mut self, selector: &mut Selector) {
        // remove the last items first, otherwise i might not be less than len() on swap_remove(i)
        for i in (0..self.connections.len()).rev() {
            let expired = {
                let mut connection = self.connections[i].borrow_mut();
                if connection.is_expired() {
                    debug!(
                        target: TAG,
                        "Removed expired connection: {}",
                        connection.id()
                    );
                    connection.close(selector);
                    true
                } else {
                    false
                }
            };
            if expired {
                self.connections.swap_remove(i);
            }
        }
    }
}
<commit_msg>Revert "Ignore double-removal of a connection"<commit_after>/*
 * Copyright (C) 2017 Genymobile
 *
 * 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.
 */

use std::cell::RefCell;
use std::io;
use std::ptr;
use std::rc::{Rc, Weak};
use log::Level;

use super::binary;
use super::client::{Client, ClientChannel};
use super::connection::{Connection, ConnectionId};
use super::ipv4_header::Protocol;
use super::ipv4_packet::Ipv4Packet;
use super::selector::Selector;
use super::tcp_connection::TcpConnection;
use super::udp_connection::UdpConnection;

const TAG: &'static str = "Router";

pub struct Router {
    client: Weak<RefCell<Client>>,
    // there are typically only few connections per client, HashMap would be less efficient
    connections: Vec<Rc<RefCell<Connection>>>,
}

impl Router {
    pub fn new() -> Self {
        Self {
            client: Weak::new(),
            connections: Vec::new(),
        }
    }

    // expose client initialization after construction to break cyclic initialization dependencies
    pub fn set_client(&mut self, client: Weak<RefCell<Client>>) {
        self.client = client;
    }

    pub fn send_to_network(
        &mut self,
        selector: &mut Selector,
        client_channel: &mut ClientChannel,
        ipv4_packet: &Ipv4Packet,
    ) {
        if ipv4_packet.is_valid() {
            match self.connection(selector, ipv4_packet) {
                Ok(index) => {
                    let closed = {
                        let connection_ref = self.connections.get_mut(index).unwrap();
                        let mut connection = connection_ref.borrow_mut();
                        connection.send_to_network(selector, client_channel, ipv4_packet);
                        connection.is_closed()
                    };
                    if closed {
                        // the connection is closed, remove it
                        self.connections.swap_remove(index);
                    }
                }
                Err(err) => error!(target: TAG, "Cannot create route, dropping packet: {}", err),
            }
        } else {
            warn!(target: TAG, "Dropping invalid packet");
            if log_enabled!(target: TAG, Level::Trace) {
                trace!(target: TAG, "{}", binary::to_string(ipv4_packet.raw()));
            }
        }
    }

    fn connection(
        &mut self,
        selector: &mut Selector,
        ipv4_packet: &Ipv4Packet,
    ) -> io::Result<usize> {
        let (ipv4_header_data, transport_header_data) = ipv4_packet.headers_data();
        let transport_header_data = transport_header_data.expect("No transport");
        let id = ConnectionId::from_headers(ipv4_header_data, transport_header_data);
        let index = match self.find_index(&id) {
            Some(index) => index,
            None => {
                let connection =
                    Self::create_connection(selector, id, self.client.clone(), ipv4_packet)?;
                let index = self.connections.len();
                self.connections.push(connection);
                index
            }
        };
        Ok(index)
    }

    fn create_connection(
        selector: &mut Selector,
        id: ConnectionId,
        client: Weak<RefCell<Client>>,
        ipv4_packet: &Ipv4Packet,
    ) -> io::Result<Rc<RefCell<Connection>>> {
        let (ipv4_header, transport_header) = ipv4_packet.headers();
        let transport_header = transport_header.expect("No transport");
        match id.protocol() {
            Protocol::Tcp => Ok(TcpConnection::new(
                selector,
                id,
                client,
                ipv4_header,
                transport_header,
            )?),
            Protocol::Udp => Ok(UdpConnection::new(
                selector,
                id,
                client,
                ipv4_header,
                transport_header,
            )?),
            p => Err(io::Error::new(
                io::ErrorKind::Other,
                format!("Unsupported protocol: {:?}", p),
            )),
        }
    }

    fn find_index(&self, id: &ConnectionId) -> Option<usize> {
        self.connections.iter().position(|connection| {
            connection.borrow().id() == id
        })
    }

    pub fn remove(&mut self, connection: &Connection) {
        let index = self.connections
            .iter()
            .position(|item| {
                // compare pointers to find the connection to remove
                ptr::eq(connection, item.as_ptr())
            })
            .expect("Removing an unknown connection");
        self.connections.swap_remove(index);
    }

    pub fn clear(&mut self, selector: &mut Selector) {
        for connection in &mut self.connections {
            connection.borrow_mut().close(selector);
        }
        self.connections.clear();
    }

    pub fn clean_expired_connections(&mut self, selector: &mut Selector) {
        // remove the last items first, otherwise i might not be less than len() on swap_remove(i)
        for i in (0..self.connections.len()).rev() {
            let expired = {
                let mut connection = self.connections[i].borrow_mut();
                if connection.is_expired() {
                    debug!(
                        target: TAG,
                        "Removed expired connection: {}",
                        connection.id()
                    );
                    connection.close(selector);
                    true
                } else {
                    false
                }
            };
            if expired {
                self.connections.swap_remove(i);
            }
        }
    }
}
<|endoftext|>


<commit_before>use fake::locales::{EN, FR_FR, ZH_CN, ZH_TW};
use fake::Fake;

fn lorem_faker() {
    use fake::faker::lorem::raw::*;

    let val: String = Word(EN).fake();
    println!("{:?}", val);

    let val: Vec<String> = Words(EN, 3..5).fake();
    println!("{:?}", val);

    let val: String = Sentence(EN, 3..5).fake();
    println!("{:?}", val);

    let val: Vec<String> = Sentences(EN, 3..5).fake();
    println!("{:?}", val);

    let val: String = Paragraph(EN, 3..5).fake();
    println!("{:?}", val);

    let val: Vec<String> = Paragraphs(EN, 3..5).fake();
    println!("{:?}", val);
}

fn name_faker() {
    use fake::faker::name::raw::*;

    let val: String = FirstName(EN).fake();
    println!("{:?}", val);

    let val: String = LastName(EN).fake();
    println!("{:?}", val);

    let val: String = Title(EN).fake();
    println!("{:?}", val);

    let val: String = Suffix(EN).fake();
    println!("{:?}", val);

    let val: String = Name(EN).fake();
    println!("{:?}", val);

    let val: String = NameWithTitle(EN).fake();
    println!("{:?}", val);

    let val: String = Name(ZH_TW).fake();
    println!("{:?}", val);

    let val: String = NameWithTitle(ZH_TW).fake();
    println!("{:?}", val);

    let val: String = Name(ZH_CN).fake();
    println!("{:?}", val);

    let val: String = NameWithTitle(ZH_CN).fake();
    println!("{:?}", val);
}

fn job_faker() {
    use fake::faker::job::raw::*;
    let val: String = Seniority(EN).fake();
    println!("{:?}", val);

    let val: String = Field(EN).fake();
    println!("{:?}", val);

    let val: String = Position(EN).fake();
    println!("{:?}", val);

    let val: String = Title(EN).fake();
    println!("{:?}", val);

    let val: Vec<String> = (Title(EN), 2..4).fake();
    println!("{:?}", val);
}

fn address_faker() {
    use fake::faker::address::raw::*;

    let val: String = CityPrefix(EN).fake();
    println!("{:?}", val);

    let val: String = CitySuffix(EN).fake();
    println!("{:?}", val);

    let val: String = CityName(EN).fake();
    println!("{:?}", val);

    let val: String = CountryName(EN).fake();
    println!("{:?}", val);

    let val: String = CountryCode(EN).fake();
    println!("{:?}", val);

    let val: String = StateName(EN).fake();
    println!("{:?}", val);

    let val: String = StateAbbr(EN).fake();
    println!("{:?}", val);

    let val: String = StreetSuffix(EN).fake();
    println!("{:?}", val);

    let val: String = StreetName(EN).fake();
    println!("{:?}", val);

    let val: String = SecondaryAddressType(EN).fake();
    println!("{:?}", val);

    let val: String = SecondaryAddress(EN).fake();
    println!("{:?}", val);

    let val: String = ZipCode(EN).fake();
    println!("{:?}", val);

    let val: String = PostCode(EN).fake();
    println!("{:?}", val);

    let val: String = BuildingNumber(EN).fake();
    println!("{:?}", val);

    let val: String = TimeZone(EN).fake();
    println!("{:?}", val);

    let val: f32 = Latitude(EN).fake();
    println!("{:?}", val);

    let val: f64 = Latitude(EN).fake();
    println!("{:?}", val);

    let val: f32 = Longitude(EN).fake();
    println!("{:?}", val);

    let val: f64 = Longitude(EN).fake();
    println!("{:?}", val);

    let val: String = Geohash(EN, 11).fake();
    println!("{:?}", val);
}

fn automotive_faker() {
    use fake::faker::automotive::raw::*;

    let val: String = LicencePlate(FR_FR).fake();
    println!("{:?}", val);
}

fn bool_faker() {
    use fake::faker::boolean::raw::*;

    use fake::faker::boolean::en;
    let b = en::Boolean(50);
    for _ in 0..5 {
        let val: bool = b.fake();
        println!("{:?}", val);
    }

    //50% true
    let b = Boolean(EN, 50);
    for _ in 0..5 {
        let val: bool = b.fake();
        println!("{:?}", val);
    }

    // 0% true
    let b = Boolean(EN, 0);
    for _ in 0..5 {
        let val: bool = b.fake();
        println!("{:?}", val);
    }

    // 100% true
    let b = Boolean(EN, 100);
    for _ in 0..5 {
        let val: bool = b.fake();
        println!("{:?}", val);
    }
}

fn company_faker() {
    use fake::faker::company::raw::*;

    let val: String = CompanySuffix(EN).fake();
    println!("{:?}", val);

    let val: String = CompanyName(EN).fake();
    println!("{:?}", val);

    let val: String = Buzzword(EN).fake();
    println!("{:?}", val);

    let val: String = BuzzwordMiddle(EN).fake();
    println!("{:?}", val);

    let val: String = BuzzwordTail(EN).fake();
    println!("{:?}", val);

    let val: String = CatchPhase(EN).fake();
    println!("{:?}", val);

    let val: String = BsVerb(EN).fake();
    println!("{:?}", val);

    let val: String = BsAdj(EN).fake();
    println!("{:?}", val);

    let val: String = BsNoun(EN).fake();
    println!("{:?}", val);

    let val: String = Bs(EN).fake();
    println!("{:?}", val);

    let val: String = Profession(EN).fake();
    println!("{:?}", val);

    let val: String = Industry(EN).fake();
    println!("{:?}", val);
}

fn internet_faker() {
    use fake::faker::internet::raw::*;

    let val: String = FreeEmailProvider(EN).fake();
    println!("{:?}", val);

    let val: String = DomainSuffix(EN).fake();
    println!("{:?}", val);

    let val: String = FreeEmail(EN).fake();
    println!("{:?}", val);

    let val: String = SafeEmail(EN).fake();
    println!("{:?}", val);

    let val: String = Username(EN).fake();
    println!("{:?}", val);

    let val: String = Password(EN, 8..20).fake();
    println!("{:?}", val);

    let val: String = IPv4(EN).fake();
    println!("{:?}", val);

    let val: String = IPv6(EN).fake();
    println!("{:?}", val);

    let val: String = IP(EN).fake();
    println!("{:?}", val);

    let val: String = MACAddress(EN).fake();
    println!("{:?}", val);

    let val: String = Color(EN).fake();
    println!("{:?}", val);

    let val: String = UserAgent(EN).fake();
    println!("{:?}", val);
}

fn number_faker() {
    use fake::faker::number::raw::*;

    let val: String = Digit(EN).fake();
    println!("{:?}", val);

    // ^: 1-9, #: 0-9
    let val: String = NumberWithFormat(EN, "^###").fake();
    println!("{:?}", val);

    let val: String = NumberWithFormat(EN, "FLAT 0# ^#/F").fake();
    println!("{:?}", val);
}

fn phone_number_faker() {
    use fake::faker::number::raw::NumberWithFormat;
    use fake::faker::phone_number::raw::*;

    let val: String = PhoneNumber(EN).fake();
    println!("{:?}", val);

    let val: String = CellNumber(EN).fake();
    println!("{:?}", val);

    // custom phone number format
    let val: String = NumberWithFormat(EN, "(+852) 6### ####").fake();
    println!("{:?}", val);
}

#[cfg(feature = "http")]
fn http_faker() {
    use fake::faker::http::raw::*;
    use fake::Faker;
    use http::status::{InvalidStatusCode, StatusCode};

    let val: String = RfcStatusCode(EN).fake();
    println!("{:?}", val);

    let val: String = ValidStatusCode(EN).fake();
    println!("{:?}", val);

    let val: StatusCode = RfcStatusCode(EN).fake();
    println!("{:?}", val);

    let val: StatusCode = ValidStatusCode(EN).fake();
    println!("{:?}", val);

    let codes = [200, 401, 404, 500].as_ref();
    let val: StatusCode = codes.fake();
    println!("{:?}", val);

    let codes = [200, 401, 404, 500, 611].as_ref();
    let val: Result<StatusCode, InvalidStatusCode> = codes.fake();
    println!("{:?}", val);

    let val: StatusCode = Faker.fake();
    println!("{:?}", val);

    let val: http::Version = Faker.fake();
    println!("{:?}", val);
}

#[cfg(feature = "chrono")]
fn chrono_faker() {
    use chrono::Utc;
    use fake::faker::chrono::raw::*;
    use fake::Faker;

    let val: chrono::NaiveTime = Time(EN).fake();
    println!("{:?}", val);

    let val: String = Time(EN).fake();
    println!("{:?}", val);

    let val: chrono::NaiveDate = Date(EN).fake();
    println!("{:?}", val);

    let val: String = Date(EN).fake();
    println!("{:?}", val);

    let val: chrono::NaiveDateTime = DateTime(EN).fake();
    println!("{:?}", val);

    let val: chrono::DateTime<Utc> = DateTime(EN).fake();
    println!("{:?}", val);

    let val: String = DateTime(EN).fake();
    println!("{:?}", val);

    let val: chrono::Duration = Duration(EN).fake();
    println!("{}", val);

    let val: chrono::Duration = Faker.fake();
    println!("{}", val);

    let start_dt: chrono::DateTime<Utc> = DateTimeBefore(EN, Utc::now()).fake();
    println!("{}", start_dt);

    let end_dt: chrono::DateTime<Utc> = DateTimeAfter(EN, Utc::now()).fake();
    println!("{}", end_dt);

    let between: chrono::DateTime<Utc> = DateTimeBetween(EN, start_dt, end_dt).fake();
    println!("{}", between);
}

fn filesystem_faker() {
    use fake::faker::filesystem::raw::*;
    use std::path::PathBuf;

    let val: String = FilePath(EN).fake();
    println!("{:?}", val);

    let val: PathBuf = FilePath(EN).fake();
    println!("{:?}", val);

    let val: String = FileName(EN).fake();
    println!("{:?}", val);

    let val: String = FileExtension(EN).fake();
    println!("{:?}", val);

    let val: String = DirPath(EN).fake();
    println!("{:?}", val);

    let val: PathBuf = DirPath(EN).fake();
    println!("{:?}", val);
}

fn currency_faker() {
    use fake::faker::currency::raw::*;

    let val: String = CurrencyCode(EN).fake();
    println!("{:?}", val);

    let val: String = CurrencyName(EN).fake();
    println!("{:?}", val);

    let val: String = CurrencySymbol(EN).fake();
    println!("{:?}", val);
}

fn creditcard_faker() {
    use fake::faker::creditcard::raw::*;

    let val: String = CreditCardNumber(EN).fake();
    println!("{:?}", val);
}

fn barecode_faker() {
    use fake::faker::barecode::raw::*;

    let val: String = Isbn13(EN).fake();
    println!("{}", val);

    let val: String = Isbn10(EN).fake();
    println!("{}", val);

    let val: String = Isbn(EN).fake();
    println!("{}", val);
}

fn uuid_faker() {
    use fake::faker::uuid::raw::*;
    use uuid::Uuid;

    let val: Uuid = UuidV1(EN).fake();
    println!("{} (v1)", val);

    let val: Uuid = UuidV3(EN).fake();
    println!("{} (v3)", val);

    let val: Uuid = UuidV4(EN).fake();
    println!("{} (v4)", val);

    let val: Uuid = UuidV5(EN).fake();
    println!("{} (v5)", val);
}

fn main() {
    lorem_faker();
    name_faker();
    job_faker();
    address_faker();
    automotive_faker();
    bool_faker();
    company_faker();
    internet_faker();
    number_faker();
    phone_number_faker();
    filesystem_faker();
    currency_faker();
    creditcard_faker();
    barecode_faker();

    #[cfg(feature = "http")]
    http_faker();

    #[cfg(feature = "chrono")]
    chrono_faker();

    #[cfg(feature = "uuid")]
    uuid_faker();
}
<commit_msg>add missing feature flag<commit_after>use fake::locales::{EN, FR_FR, ZH_CN, ZH_TW};
use fake::Fake;

fn lorem_faker() {
    use fake::faker::lorem::raw::*;

    let val: String = Word(EN).fake();
    println!("{:?}", val);

    let val: Vec<String> = Words(EN, 3..5).fake();
    println!("{:?}", val);

    let val: String = Sentence(EN, 3..5).fake();
    println!("{:?}", val);

    let val: Vec<String> = Sentences(EN, 3..5).fake();
    println!("{:?}", val);

    let val: String = Paragraph(EN, 3..5).fake();
    println!("{:?}", val);

    let val: Vec<String> = Paragraphs(EN, 3..5).fake();
    println!("{:?}", val);
}

fn name_faker() {
    use fake::faker::name::raw::*;

    let val: String = FirstName(EN).fake();
    println!("{:?}", val);

    let val: String = LastName(EN).fake();
    println!("{:?}", val);

    let val: String = Title(EN).fake();
    println!("{:?}", val);

    let val: String = Suffix(EN).fake();
    println!("{:?}", val);

    let val: String = Name(EN).fake();
    println!("{:?}", val);

    let val: String = NameWithTitle(EN).fake();
    println!("{:?}", val);

    let val: String = Name(ZH_TW).fake();
    println!("{:?}", val);

    let val: String = NameWithTitle(ZH_TW).fake();
    println!("{:?}", val);

    let val: String = Name(ZH_CN).fake();
    println!("{:?}", val);

    let val: String = NameWithTitle(ZH_CN).fake();
    println!("{:?}", val);
}

fn job_faker() {
    use fake::faker::job::raw::*;
    let val: String = Seniority(EN).fake();
    println!("{:?}", val);

    let val: String = Field(EN).fake();
    println!("{:?}", val);

    let val: String = Position(EN).fake();
    println!("{:?}", val);

    let val: String = Title(EN).fake();
    println!("{:?}", val);

    let val: Vec<String> = (Title(EN), 2..4).fake();
    println!("{:?}", val);
}

fn address_faker() {
    use fake::faker::address::raw::*;

    let val: String = CityPrefix(EN).fake();
    println!("{:?}", val);

    let val: String = CitySuffix(EN).fake();
    println!("{:?}", val);

    let val: String = CityName(EN).fake();
    println!("{:?}", val);

    let val: String = CountryName(EN).fake();
    println!("{:?}", val);

    let val: String = CountryCode(EN).fake();
    println!("{:?}", val);

    let val: String = StateName(EN).fake();
    println!("{:?}", val);

    let val: String = StateAbbr(EN).fake();
    println!("{:?}", val);

    let val: String = StreetSuffix(EN).fake();
    println!("{:?}", val);

    let val: String = StreetName(EN).fake();
    println!("{:?}", val);

    let val: String = SecondaryAddressType(EN).fake();
    println!("{:?}", val);

    let val: String = SecondaryAddress(EN).fake();
    println!("{:?}", val);

    let val: String = ZipCode(EN).fake();
    println!("{:?}", val);

    let val: String = PostCode(EN).fake();
    println!("{:?}", val);

    let val: String = BuildingNumber(EN).fake();
    println!("{:?}", val);

    let val: String = TimeZone(EN).fake();
    println!("{:?}", val);

    let val: f32 = Latitude(EN).fake();
    println!("{:?}", val);

    let val: f64 = Latitude(EN).fake();
    println!("{:?}", val);

    let val: f32 = Longitude(EN).fake();
    println!("{:?}", val);

    let val: f64 = Longitude(EN).fake();
    println!("{:?}", val);

    let val: String = Geohash(EN, 11).fake();
    println!("{:?}", val);
}

fn automotive_faker() {
    use fake::faker::automotive::raw::*;

    let val: String = LicencePlate(FR_FR).fake();
    println!("{:?}", val);
}

fn bool_faker() {
    use fake::faker::boolean::raw::*;

    use fake::faker::boolean::en;
    let b = en::Boolean(50);
    for _ in 0..5 {
        let val: bool = b.fake();
        println!("{:?}", val);
    }

    //50% true
    let b = Boolean(EN, 50);
    for _ in 0..5 {
        let val: bool = b.fake();
        println!("{:?}", val);
    }

    // 0% true
    let b = Boolean(EN, 0);
    for _ in 0..5 {
        let val: bool = b.fake();
        println!("{:?}", val);
    }

    // 100% true
    let b = Boolean(EN, 100);
    for _ in 0..5 {
        let val: bool = b.fake();
        println!("{:?}", val);
    }
}

fn company_faker() {
    use fake::faker::company::raw::*;

    let val: String = CompanySuffix(EN).fake();
    println!("{:?}", val);

    let val: String = CompanyName(EN).fake();
    println!("{:?}", val);

    let val: String = Buzzword(EN).fake();
    println!("{:?}", val);

    let val: String = BuzzwordMiddle(EN).fake();
    println!("{:?}", val);

    let val: String = BuzzwordTail(EN).fake();
    println!("{:?}", val);

    let val: String = CatchPhase(EN).fake();
    println!("{:?}", val);

    let val: String = BsVerb(EN).fake();
    println!("{:?}", val);

    let val: String = BsAdj(EN).fake();
    println!("{:?}", val);

    let val: String = BsNoun(EN).fake();
    println!("{:?}", val);

    let val: String = Bs(EN).fake();
    println!("{:?}", val);

    let val: String = Profession(EN).fake();
    println!("{:?}", val);

    let val: String = Industry(EN).fake();
    println!("{:?}", val);
}

fn internet_faker() {
    use fake::faker::internet::raw::*;

    let val: String = FreeEmailProvider(EN).fake();
    println!("{:?}", val);

    let val: String = DomainSuffix(EN).fake();
    println!("{:?}", val);

    let val: String = FreeEmail(EN).fake();
    println!("{:?}", val);

    let val: String = SafeEmail(EN).fake();
    println!("{:?}", val);

    let val: String = Username(EN).fake();
    println!("{:?}", val);

    let val: String = Password(EN, 8..20).fake();
    println!("{:?}", val);

    let val: String = IPv4(EN).fake();
    println!("{:?}", val);

    let val: String = IPv6(EN).fake();
    println!("{:?}", val);

    let val: String = IP(EN).fake();
    println!("{:?}", val);

    let val: String = MACAddress(EN).fake();
    println!("{:?}", val);

    let val: String = Color(EN).fake();
    println!("{:?}", val);

    let val: String = UserAgent(EN).fake();
    println!("{:?}", val);
}

fn number_faker() {
    use fake::faker::number::raw::*;

    let val: String = Digit(EN).fake();
    println!("{:?}", val);

    // ^: 1-9, #: 0-9
    let val: String = NumberWithFormat(EN, "^###").fake();
    println!("{:?}", val);

    let val: String = NumberWithFormat(EN, "FLAT 0# ^#/F").fake();
    println!("{:?}", val);
}

fn phone_number_faker() {
    use fake::faker::number::raw::NumberWithFormat;
    use fake::faker::phone_number::raw::*;

    let val: String = PhoneNumber(EN).fake();
    println!("{:?}", val);

    let val: String = CellNumber(EN).fake();
    println!("{:?}", val);

    // custom phone number format
    let val: String = NumberWithFormat(EN, "(+852) 6### ####").fake();
    println!("{:?}", val);
}

#[cfg(feature = "http")]
fn http_faker() {
    use fake::faker::http::raw::*;
    use fake::Faker;
    use http::status::{InvalidStatusCode, StatusCode};

    let val: String = RfcStatusCode(EN).fake();
    println!("{:?}", val);

    let val: String = ValidStatusCode(EN).fake();
    println!("{:?}", val);

    let val: StatusCode = RfcStatusCode(EN).fake();
    println!("{:?}", val);

    let val: StatusCode = ValidStatusCode(EN).fake();
    println!("{:?}", val);

    let codes = [200, 401, 404, 500].as_ref();
    let val: StatusCode = codes.fake();
    println!("{:?}", val);

    let codes = [200, 401, 404, 500, 611].as_ref();
    let val: Result<StatusCode, InvalidStatusCode> = codes.fake();
    println!("{:?}", val);

    let val: StatusCode = Faker.fake();
    println!("{:?}", val);

    let val: http::Version = Faker.fake();
    println!("{:?}", val);
}

#[cfg(feature = "chrono")]
fn chrono_faker() {
    use chrono::Utc;
    use fake::faker::chrono::raw::*;
    use fake::Faker;

    let val: chrono::NaiveTime = Time(EN).fake();
    println!("{:?}", val);

    let val: String = Time(EN).fake();
    println!("{:?}", val);

    let val: chrono::NaiveDate = Date(EN).fake();
    println!("{:?}", val);

    let val: String = Date(EN).fake();
    println!("{:?}", val);

    let val: chrono::NaiveDateTime = DateTime(EN).fake();
    println!("{:?}", val);

    let val: chrono::DateTime<Utc> = DateTime(EN).fake();
    println!("{:?}", val);

    let val: String = DateTime(EN).fake();
    println!("{:?}", val);

    let val: chrono::Duration = Duration(EN).fake();
    println!("{}", val);

    let val: chrono::Duration = Faker.fake();
    println!("{}", val);

    let start_dt: chrono::DateTime<Utc> = DateTimeBefore(EN, Utc::now()).fake();
    println!("{}", start_dt);

    let end_dt: chrono::DateTime<Utc> = DateTimeAfter(EN, Utc::now()).fake();
    println!("{}", end_dt);

    let between: chrono::DateTime<Utc> = DateTimeBetween(EN, start_dt, end_dt).fake();
    println!("{}", between);
}

fn filesystem_faker() {
    use fake::faker::filesystem::raw::*;
    use std::path::PathBuf;

    let val: String = FilePath(EN).fake();
    println!("{:?}", val);

    let val: PathBuf = FilePath(EN).fake();
    println!("{:?}", val);

    let val: String = FileName(EN).fake();
    println!("{:?}", val);

    let val: String = FileExtension(EN).fake();
    println!("{:?}", val);

    let val: String = DirPath(EN).fake();
    println!("{:?}", val);

    let val: PathBuf = DirPath(EN).fake();
    println!("{:?}", val);
}

fn currency_faker() {
    use fake::faker::currency::raw::*;

    let val: String = CurrencyCode(EN).fake();
    println!("{:?}", val);

    let val: String = CurrencyName(EN).fake();
    println!("{:?}", val);

    let val: String = CurrencySymbol(EN).fake();
    println!("{:?}", val);
}

fn creditcard_faker() {
    use fake::faker::creditcard::raw::*;

    let val: String = CreditCardNumber(EN).fake();
    println!("{:?}", val);
}

fn barecode_faker() {
    use fake::faker::barecode::raw::*;

    let val: String = Isbn13(EN).fake();
    println!("{}", val);

    let val: String = Isbn10(EN).fake();
    println!("{}", val);

    let val: String = Isbn(EN).fake();
    println!("{}", val);
}

#[cfg(feature = "uuid")]
fn uuid_faker() {
    use fake::faker::uuid::raw::*;
    use uuid::Uuid;

    let val: Uuid = UuidV1(EN).fake();
    println!("{} (v1)", val);

    let val: Uuid = UuidV3(EN).fake();
    println!("{} (v3)", val);

    let val: Uuid = UuidV4(EN).fake();
    println!("{} (v4)", val);

    let val: Uuid = UuidV5(EN).fake();
    println!("{} (v5)", val);
}

fn main() {
    lorem_faker();
    name_faker();
    job_faker();
    address_faker();
    automotive_faker();
    bool_faker();
    company_faker();
    internet_faker();
    number_faker();
    phone_number_faker();
    filesystem_faker();
    currency_faker();
    creditcard_faker();
    barecode_faker();

    #[cfg(feature = "http")]
    http_faker();

    #[cfg(feature = "chrono")]
    chrono_faker();

    #[cfg(feature = "uuid")]
    uuid_faker();
}
<|endoftext|>


<commit_before>extern crate find_folder;

use std::path::PathBuf;

pub struct Loader {
    assets_path: PathBuf,
}

impl Loader {
    pub fn new() -> Self {
        Loader { assets_path: find_folder::Search::KidsThenParents(3, 5).for_folder("assets").unwrap() }
    }

    pub fn get_asset_path(&self, name: &str) -> PathBuf {
        self.assets_path.join(name)
    }
}
<commit_msg>get_font function<commit_after>extern crate find_folder;

use std::path::PathBuf;

pub struct Loader {
    assets_path: PathBuf,
}

impl Loader {
    pub fn new() -> Self {
        Loader { assets_path: find_folder::Search::KidsThenParents(3, 5).for_folder("assets").unwrap() }
    }

    pub fn get_asset_path(&self, name: &str) -> PathBuf {
        self.assets_path.join(name)
    }

    pub fn get_font() -> PathBuf {
        self.assets_path.join("NotoSans-Regular.ttf")
    }
}
<|endoftext|>