<commit_before>// http://stackoverflow.com/questions/25877285/how-to-disable-unused-code-warnings-in-rust
// https://users.rust-lang.org/t/turning-off-compiler-warning-messages/4975/2
#![allow(non_snake_case)]

// mod api;
// mod cors;
// mod files;

extern crate actix;
extern crate actix_web;
extern crate env_logger;

extern crate postgres;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;

extern crate dotenv;
use dotenv::dotenv;
use std::env;

use actix_web::{middleware, server, App, HttpRequest};

#[derive(Serialize)]
struct TemplateContext {
    parent: String,
    name: String,
    content: String,
    items: Vec<String>,
}

fn index(_req: &HttpRequest) -> &'static str {
    "Hello world"
}

use std::path::Path;
use std::process::Command;

// #[get("/template/<ssr>")]
// fn template(ssr: bool) -> CORS<Template> {
//     println!("ssr {}", ssr);
//     let s2 = getStr();
//     println!("s2 {}", s2);
//     let s: String = if ssr { s2 } else { "".to_owned() };
//     let context = TemplateContext {
//         parent: "index".to_owned(),
//         name: "Roman".to_owned(),
//         content: s.to_owned(),
//         items: vec!["One", "Two", "Three"]
//             .iter()
//             .map(|s| s.to_string())
//             .collect(),
//     };
//     CORS::any(Template::render("template", &context))
// }

use std::fs;
use std::fs::OpenOptions;
use std::io::prelude::*;
extern crate time;

fn getStr() -> String {
    fs::copy(
        "../client/src/elm/Main.elm",
        "../client/src/elm/Main.elm.bak",
    )
    .expect("file not copied");
    let stdout: Vec<u8>;
    {
        let mut main_file = OpenOptions::new()
            .append(true)
            .open("../client/src/elm/Main.elm")
            .expect("file not opened");

        let str1 = format!(
            r#"
view : Html Msg
view =
    viewWithModel <|
        Model [] HomeRoute <|
            Flags "" {time} ""
"#,
            time = time::get_time().sec
        );

        main_file
            .write(str1.as_bytes())
            .expect("file content not saved");

        stdout = Command::new("node")
            .current_dir(&Path::new("../client"))
            .arg("./node_modules/elm-static-html/index.js")
            .arg("-f")
            .arg("src/elm/Main.elm")
            .output()
            .expect("elm-static-html command failed to start")
            .stdout;
    }
    fs::rename(
        "../client/src/elm/Main.elm.bak",
        "../client/src/elm/Main.elm",
    )
    .expect("file not renamed");

    String::from_utf8_lossy(&*stdout)
        .lines()
        .skip_while(|x| x.find("id=\"content\"").is_none())
        .collect()
}

// #[error(404)]
// fn not_found(req: &Request) -> CORS<Template> {
//     let mut map = std::collections::HashMap::new();
//     map.insert("path", req.uri().as_str());
//     CORS::any(Template::render("error/404", &map))
// }

fn main() {
    dotenv().ok();
    env::set_var("RUST_LOG", "actix_web=info");
    env_logger::init();
    let sys = actix::System::new("hello-world");

    server::new(|| {
        App::new()
            .middleware(middleware::Logger::default())
            .resource("/", |r| r.f(index))
    })
    .bind("127.0.0.1:8080")
    .unwrap()
    .start();

    println!("Starting http server: 127.0.0.1:8080");

    let _ = sys.run();

    // println!("{:?}", env::var("data_server").unwrap());
    // rocket::ignite()
    //     .mount(
    //         "/",
    //         routes![
    //             template,
    //             files::favicon,
    //             files::index,
    //             files::redirect_to_index,
    //             files::js,
    //             files::styles,
    //             files::styles_with_query,
    //             files::images
    //         ],
    //     )
    //     .mount(
    //         "/api",
    //         routes![
    //             api::user_information,
    //             api::data_sets,
    //             api::data_set,
    //             api::data_set_category,
    //             api::data_sets_categories,
    //             api::data_sets_new
    //         ],
    //     )
    //     .catch(errors![not_found])
    //     .launch();
}
<commit_msg>fn template wip<commit_after>// http://stackoverflow.com/questions/25877285/how-to-disable-unused-code-warnings-in-rust
// https://users.rust-lang.org/t/turning-off-compiler-warning-messages/4975/2
#![allow(non_snake_case)]

// mod api;
// mod cors;
// mod files;

extern crate actix;
extern crate actix_web;
extern crate env_logger;

extern crate postgres;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;

extern crate dotenv;
use dotenv::dotenv;
use std::env;

use actix_web::{middleware, server, App, FromRequest, HttpRequest, Path};

#[derive(Serialize)]
struct TemplateContext {
    parent: String,
    name: String,
    content: String,
    items: Vec<String>,
}

fn index(_req: &HttpRequest) -> &'static str {
    "Hello world"
}

use std::path;
use std::process::Command;

#[derive(Deserialize)]
struct TemplateParams {
    ssr: bool,
}

fn template(req: &HttpRequest) -> String {
    let params = actix_web::Path::<TemplateParams>::extract(req).unwrap();
    format!("ssr {}", params.ssr)
    // let s2 = getStr();
    // println!("s2 {}", s2);
    // let s: String = if ssr { s2 } else { "".to_owned() };
    // let context = TemplateContext {
    //     parent: "index".to_owned(),
    //     name: "Roman".to_owned(),
    //     content: s.to_owned(),
    //     items: vec!["One", "Two", "Three"]
    //         .iter()
    //         .map(|s| s.to_string())
    //         .collect(),
    // };
    // CORS::any(Template::render("template", &context))
}

use std::fs;
use std::fs::OpenOptions;
use std::io::prelude::*;
extern crate time;

fn getStr() -> String {
    fs::copy(
        "../client/src/elm/Main.elm",
        "../client/src/elm/Main.elm.bak",
    )
    .expect("file not copied");
    let stdout: Vec<u8>;
    {
        let mut main_file = OpenOptions::new()
            .append(true)
            .open("../client/src/elm/Main.elm")
            .expect("file not opened");

        let str1 = format!(
            r#"
view : Html Msg
view =
    viewWithModel <|
        Model [] HomeRoute <|
            Flags "" {time} ""
"#,
            time = time::get_time().sec
        );

        main_file
            .write(str1.as_bytes())
            .expect("file content not saved");

        stdout = Command::new("node")
            .current_dir(&path::Path::new("../client"))
            .arg("./node_modules/elm-static-html/index.js")
            .arg("-f")
            .arg("src/elm/Main.elm")
            .output()
            .expect("elm-static-html command failed to start")
            .stdout;
    }
    fs::rename(
        "../client/src/elm/Main.elm.bak",
        "../client/src/elm/Main.elm",
    )
    .expect("file not renamed");

    String::from_utf8_lossy(&*stdout)
        .lines()
        .skip_while(|x| x.find("id=\"content\"").is_none())
        .collect()
}

// #[error(404)]
// fn not_found(req: &Request) -> CORS<Template> {
//     let mut map = std::collections::HashMap::new();
//     map.insert("path", req.uri().as_str());
//     CORS::any(Template::render("error/404", &map))
// }

fn main() {
    dotenv().ok();
    env::set_var("RUST_LOG", "actix_web=info");
    env_logger::init();
    let sys = actix::System::new("hello-world");

    server::new(|| {
        App::new()
            .middleware(middleware::Logger::default())
            .resource("/", |r| r.f(index))
            .resource("/template/{ssr}", |r| r.f(template))
    })
    .bind("127.0.0.1:8080")
    .unwrap()
    .start();

    println!("Starting http server: 127.0.0.1:8080");

    let _ = sys.run();

    // println!("{:?}", env::var("data_server").unwrap());
    // rocket::ignite()
    //     .mount(
    //         "/",
    //         routes![
    //             template,
    //             files::favicon,
    //             files::index,
    //             files::redirect_to_index,
    //             files::js,
    //             files::styles,
    //             files::styles_with_query,
    //             files::images
    //         ],
    //     )
    //     .mount(
    //         "/api",
    //         routes![
    //             api::user_information,
    //             api::data_sets,
    //             api::data_set,
    //             api::data_set_category,
    //             api::data_sets_categories,
    //             api::data_sets_new
    //         ],
    //     )
    //     .catch(errors![not_found])
    //     .launch();
}
<|endoftext|>


<commit_before>use shell_child::ShellChild;
use result::ShellResult;
use result::ShellError;
use std::path::Path;
use std::process::Command;

pub struct ShellCommand {
    line: String,
    command: Command,
    has_group: bool
}

impl ShellCommand {
    pub fn new(line: String, command: Command) -> ShellCommand {
        ShellCommand {
            line: line,
            command: command,
            has_group: false,
        }
    }

    pub fn set_has_group(mut self) -> Self {
        self.has_group = true;
        self
    }

    pub fn current_dir(self, _path: &Path) -> Self {
        unimplemented!()
    }

    pub fn env(self, _name: &str, _value: &str) -> Self {
        unimplemented!()
    }

    pub fn run(self) -> ShellResult {
        self.spawn().and_then(|job| job.wait())
    }

    pub fn spawn(self) -> Result<ShellChild, ShellError> {
        ShellChild::new(self.line, self.command, self.has_group)
    }
}

#[test]
fn test_shell_command_2() {
    use std::process::Command;
    let mut command = Command::new("echo");
    command.arg("The command was run");
    ShellCommand::new(String::from("echo The command was run"), command)
        .set_has_group();
}
<commit_msg>update shell test<commit_after>use shell_child::ShellChild;
use result::ShellResult;
use result::ShellError;
use std::path::Path;
use std::process::Command;

pub struct ShellCommand {
    line: String,
    pub command: Command,
    has_group: bool
}

impl ShellCommand {
    pub fn new(line: String, command: Command) -> ShellCommand {
        ShellCommand {
            line: line,
            command: command,
            has_group: false,
        }
    }

    pub fn set_has_group(mut self) -> Self {
        self.has_group = true;
        self
    }

    pub fn current_dir(self, _path: &Path) -> Self {
        unimplemented!()
    }

    pub fn env(self, _name: &str, _value: &str) -> Self {
        unimplemented!()
    }

    pub fn run(self) -> ShellResult {
        self.spawn().and_then(|job| job.wait())
    }

    pub fn spawn(self) -> Result<ShellChild, ShellError> {
        ShellChild::new(self.line, self.command, self.has_group)
    }
}

#[test]
fn test_shell_command() {
    assert!(cmd!("test 1 = 1").run().is_ok());
    assert!(cmd!("test 1 = 0").run().is_err());
}

#[test]
fn test_shell_command_output() {
    assert_eq!(
        &String::from_utf8_lossy(&cmd!("echo Test").command.output()
                                 .unwrap().stdout),
        "Test\n");
}
<|endoftext|>


<commit_before>// Rust source (c) 2016 by the Rayon developers. This is ported from
// [JavaScript sources][1] developed by Intel as part of the Parallel
// JS project. The copyright for the original source is reproduced
// below.
//
// Copyright (c) 2011, Intel Corporation
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// - Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
// - Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE.
//
// [1]: https://github.com/IntelLabs/RiverTrail/blob/master/examples/nbody-webgl/NBody.js

use cgmath::{EuclideanVector, Point3, Vector, Vector3};
use rayon::par_iter::*;
use rand::{Rand, Rng};
use std::f64::NEG_INFINITY;
use std::f64::consts::PI;

const INITIAL_VELOCITY: f64 = 8.0; // set to 0.0 to turn off.

pub struct NBodyBenchmark {
    time: usize,
    bodies: (Vec<Body>, Vec<Body>),
}

#[derive(Copy, Clone, Debug)]
pub struct Body {
    pub position: Point3<f64>,
    pub velocity: Vector3<f64>,
    pub velocity2: Vector3<f64>,
}

impl NBodyBenchmark {
    pub fn new<R: Rng>(num_bodies: usize, rng: &mut R) -> NBodyBenchmark {
        let bodies0: Vec<_> =
            (0..num_bodies)
            .map(|_| {
                let position = Point3 {
                    x: f64::rand(rng).floor() * 40_000.0,
                    y: f64::rand(rng).floor() * 20_000.0,
                    z: (f64::rand(rng).floor() - 0.25) * 50_000.0,
                };

                let velocity = Vector3 {
                    x: (f64::rand(rng) - 0.5) * INITIAL_VELOCITY,
                    y: (f64::rand(rng) - 0.5) * INITIAL_VELOCITY,
                    z: f64::rand(rng) * INITIAL_VELOCITY + 10.0,
                };

                let velocity2 = Vector3 {
                    x: (f64::rand(rng) - 0.5) * INITIAL_VELOCITY,
                    y: (f64::rand(rng) - 0.5) * INITIAL_VELOCITY,
                    z: f64::rand(rng) * INITIAL_VELOCITY,
                };

                Body { position: position, velocity: velocity, velocity2: velocity2 }
            })
            .collect();

        let bodies1 = bodies0.clone();

        NBodyBenchmark {
            time: 0,
            bodies: (bodies0, bodies1),
        }
    }

    pub fn tick_par(&mut self) -> &[Body] {
        let (in_bodies, out_bodies) = if (self.time & 1) == 0 {
            (&self.bodies.0, &mut self.bodies.1)
        } else {
            (&self.bodies.1, &mut self.bodies.0)
        };

        let time = self.time;
        out_bodies.par_iter_mut()
                  .weight(200.0)
                  .zip(&in_bodies[..])
                  .for_each(|(out, prev)| {
                      let (vel, vel2) = next_velocity_par(time, prev, in_bodies);
                      out.velocity = vel;
                      out.velocity2 = vel2;

                      let next_velocity = vel - vel2;
                      out.position = prev.position + next_velocity;
                  });

        self.time += 1;

        out_bodies
    }

    pub fn tick_seq(&mut self) -> &[Body] {
        let (in_bodies, out_bodies) = if (self.time & 1) == 0 {
            (&self.bodies.0, &mut self.bodies.1)
        } else {
            (&self.bodies.1, &mut self.bodies.0)
        };

        let time = self.time;
        for (out, prev) in out_bodies.iter_mut().zip(&in_bodies[..]) {
            let (vel, vel2) = next_velocity(time, prev, in_bodies);
            out.velocity = vel;
            out.velocity2 = vel2;

            let next_velocity = vel - vel2;
            out.position = prev.position + next_velocity;
        }

        self.time += 1;

        out_bodies
    }
}

/// Compute next velocity of `prev`
fn next_velocity(time: usize, prev: &Body, bodies: &[Body]) -> (Vector3<f64>, Vector3<f64>) {
    let time = time as f64;
    let center = Point3 {
        x: (time / 22.0).cos() * -4200.0,
        y: (time / 14.0).sin() * 9200.0,
        z: (time / 27.0).sin() * 6000.0,
    };

    // pull to center
    let max_distance = 3400.0;
    let pull_strength = 0.042;

    // zones
    let zone = 400.0;
    let repel = 100.0;
    let align = 300.0;
    let attract = 100.0;

    let (speed_limit, attract_power);
    if time < 500.0 {
        speed_limit = 2000.0;
        attract_power = 100.9;
    } else {
        speed_limit = 0.2;
        attract_power = 20.9;
    }

    let zone_sqrd = 3.0 * (zone * zone);

    let mut acc = Vector3::zero();
    let mut acc2 = Vector3::zero();

    let dir_to_center = center - prev.position;
    let dist_to_center = dir_to_center.length();

    // orient to center
    if dist_to_center > max_distance {
        let velc = if time < 200.0 {
            0.2
        } else {
            (dist_to_center - max_distance) * pull_strength
        };

        let diff = (dir_to_center / dist_to_center) * velc;
        acc += diff;
    }

    // TODO -- parallelize this loop too? would be easy enough, it's just a reduction
    // Just have to factor things so that `tick_seq` doesn't do it in parallel.
    for body in bodies {
        let r = body.position - prev.position;

        // make sure we are not testing the particle against its own position
        let are_same = r == Vector3::zero();

        let dist_sqrd = r.length2();

        if dist_sqrd < zone_sqrd && !are_same {
            let length = dist_sqrd.sqrt();
            let percent = dist_sqrd / zone_sqrd;

            if dist_sqrd < repel {
                let f = (repel / percent - 1.0) * 0.025;
                let normal = (r / length) * f;
                acc += normal;
                acc2 += normal;
            } else if dist_sqrd < align {
                let thresh_delta = align - repel;
                let adjusted_percent = (percent - repel) / thresh_delta;
                let q = (0.5 - (adjusted_percent * PI * 2.0).cos() * 0.5 + 0.5) * 100.9;

                // normalize vel2 and multiply by factor
                let vel2_length = body.velocity2.length();
                let vel2 = (body.velocity2 / vel2_length) * q;

                // normalize own velocity
                let vel_length = prev.velocity.length();
                let vel = (prev.velocity / vel_length) * q;

                acc += vel2;
                acc2 += vel;
            }

            if dist_sqrd > attract { // attract
                let thresh_delta2 = 1.0 - attract;
                let adjusted_percent2 = (percent - attract) / thresh_delta2;
                let c = (1.0 - ((adjusted_percent2 * PI * 2.0).cos() * 0.5 + 0.5)) * attract_power;

                // normalize the distance vector
                let d = (r / length) * c;

                acc += d;
                acc2 -= d;
            }
        }
    }

    // Speed limits
    if time > 500.0 {
        let acc_squared = acc.length2();
        if acc_squared > speed_limit {
            acc *= 0.015;
        }

        let acc_squared2 = acc2.length2();
        if acc_squared2 > speed_limit {
            acc2 *= 0.015;
        }
    }

    let mut new = prev.velocity + acc;
    let mut new2 = prev.velocity2 + acc2;

    if time < 500.0 {
        let acs = new2.length2();
        if acs > speed_limit {
            new2 *= 0.15;
        }

        let acs2 = new.length2();
        if acs2 > speed_limit {
            new *= 0.15;
        }
    }

    (new, new2)
}

/// Compute next velocity of `prev`
fn next_velocity_par(time: usize, prev: &Body, bodies: &[Body])
                     -> (Vector3<f64>, Vector3<f64>) {
    let time = time as f64;
    let center = Point3 {
        x: (time / 22.0).cos() * -4200.0,
        y: (time / 14.0).sin() * 9200.0,
        z: (time / 27.0).sin() * 6000.0,
    };

    // pull to center
    let max_distance = 3400.0;
    let pull_strength = 0.042;

    // zones
    let zone = 400.0;
    let repel = 100.0;
    let align = 300.0;
    let attract = 100.0;

    let (speed_limit, attract_power);
    if time < 500.0 {
        speed_limit = 2000.0;
        attract_power = 100.9;
    } else {
        speed_limit = 0.2;
        attract_power = 20.9;
    }

    let zone_sqrd = 3.0 * (zone * zone);

    let mut acc = Vector3::zero();
    let mut acc2 = Vector3::zero();

    let dir_to_center = center - prev.position;
    let dist_to_center = dir_to_center.length();

    // orient to center
    if dist_to_center > max_distance {
        let velc = if time < 200.0 {
            0.2
        } else {
            (dist_to_center - max_distance) * pull_strength
        };

        let diff = (dir_to_center / dist_to_center) * velc;
        acc += diff;
    }

    let (diff, diff2) =
        bodies.par_iter()
              .map(|body| {
                  let r = body.position - prev.position;

                  let mut diff = Vector3::zero();
                  let mut diff2 = Vector3::zero();

                  // make sure we are not testing the particle against its own position
                  let are_same = r == Vector3::zero();

                  let dist_sqrd = r.length2();

                  if dist_sqrd < zone_sqrd && !are_same {
                      let length = dist_sqrd.sqrt();
                      let percent = dist_sqrd / zone_sqrd;

                      if dist_sqrd < repel {
                          let f = (repel / percent - 1.0) * 0.025;
                          let normal = (r / length) * f;
                          diff += normal;
                          diff2 += normal;
                      } else if dist_sqrd < align {
                          let thresh_delta = align - repel;
                          let adjusted_percent = (percent - repel) / thresh_delta;
                          let q = (0.5 - (adjusted_percent * PI * 2.0).cos() * 0.5 + 0.5) * 100.9;

                          // normalize vel2 and multiply by factor
                          let vel2_length = body.velocity2.length();
                          let vel2 = (body.velocity2 / vel2_length) * q;

                          // normalize own velocity
                          let vel_length = prev.velocity.length();
                          let vel = (prev.velocity / vel_length) * q;

                          diff += vel2;
                          diff2 += vel;
                      }

                      if dist_sqrd > attract { // attract
                          let thresh_delta2 = 1.0 - attract;
                          let adjusted_percent2 = (percent - attract) / thresh_delta2;
                          let c = (1.0 - ((adjusted_percent2 * PI * 2.0).cos() * 0.5 + 0.5)) * attract_power;

                          // normalize the distance vector
                          let d = (r / length) * c;

                          diff += d;
                          diff2 -= d;
                      }
                  }

                  (diff, diff2)
              })
              .weight(NEG_INFINITY)
              .reduce_with_identity(
                  (Vector3::zero(), Vector3::zero()),
                  |(diffa, diff2a), (diffb, diff2b)| (diffa + diffb, diff2a + diff2b));

    acc += diff;
    acc2 += diff2;

    // Speed limits
    if time > 500.0 {
        let acc_squared = acc.length2();
        if acc_squared > speed_limit {
            acc *= 0.015;
        }

        let acc_squared2 = acc2.length2();
        if acc_squared2 > speed_limit {
            acc2 *= 0.015;
        }
    }

    let mut new = prev.velocity + acc;
    let mut new2 = prev.velocity2 + acc2;

    if time < 500.0 {
        let acs = new2.length2();
        if acs > speed_limit {
            new2 *= 0.15;
        }

        let acs2 = new.length2();
        if acs2 > speed_limit {
            new *= 0.15;
        }
    }

    (new, new2)
}
<commit_msg>Make the reduce version optional<commit_after>// Rust source (c) 2016 by the Rayon developers. This is ported from
// [JavaScript sources][1] developed by Intel as part of the Parallel
// JS project. The copyright for the original source is reproduced
// below.
//
// Copyright (c) 2011, Intel Corporation
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// - Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
// - Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE.
//
// [1]: https://github.com/IntelLabs/RiverTrail/blob/master/examples/nbody-webgl/NBody.js

use cgmath::{EuclideanVector, Point3, Vector, Vector3};
use rayon::par_iter::*;
use rand::{Rand, Rng};
use std::f64::NEG_INFINITY;
use std::f64::consts::PI;

const INITIAL_VELOCITY: f64 = 8.0; // set to 0.0 to turn off.

pub struct NBodyBenchmark {
    time: usize,
    bodies: (Vec<Body>, Vec<Body>),
}

#[derive(Copy, Clone, Debug)]
pub struct Body {
    pub position: Point3<f64>,
    pub velocity: Vector3<f64>,
    pub velocity2: Vector3<f64>,
}

impl NBodyBenchmark {
    pub fn new<R: Rng>(num_bodies: usize, rng: &mut R) -> NBodyBenchmark {
        let bodies0: Vec<_> =
            (0..num_bodies)
            .map(|_| {
                let position = Point3 {
                    x: f64::rand(rng).floor() * 40_000.0,
                    y: f64::rand(rng).floor() * 20_000.0,
                    z: (f64::rand(rng).floor() - 0.25) * 50_000.0,
                };

                let velocity = Vector3 {
                    x: (f64::rand(rng) - 0.5) * INITIAL_VELOCITY,
                    y: (f64::rand(rng) - 0.5) * INITIAL_VELOCITY,
                    z: f64::rand(rng) * INITIAL_VELOCITY + 10.0,
                };

                let velocity2 = Vector3 {
                    x: (f64::rand(rng) - 0.5) * INITIAL_VELOCITY,
                    y: (f64::rand(rng) - 0.5) * INITIAL_VELOCITY,
                    z: f64::rand(rng) * INITIAL_VELOCITY,
                };

                Body { position: position, velocity: velocity, velocity2: velocity2 }
            })
            .collect();

        let bodies1 = bodies0.clone();

        NBodyBenchmark {
            time: 0,
            bodies: (bodies0, bodies1),
        }
    }

    pub fn tick_par(&mut self) -> &[Body] {
        let (in_bodies, out_bodies) = if (self.time & 1) == 0 {
            (&self.bodies.0, &mut self.bodies.1)
        } else {
            (&self.bodies.1, &mut self.bodies.0)
        };

        let time = self.time;
        out_bodies.par_iter_mut()
                  .weight(200.0)
                  .zip(&in_bodies[..])
                  .for_each(|(out, prev)| {
                      let (vel, vel2) = next_velocity(time, prev, in_bodies);
                      out.velocity = vel;
                      out.velocity2 = vel2;

                      let next_velocity = vel - vel2;
                      out.position = prev.position + next_velocity;
                  });

        self.time += 1;

        out_bodies
    }

    pub fn tick_reduce(&mut self) -> &[Body] {
        let (in_bodies, out_bodies) = if (self.time & 1) == 0 {
            (&self.bodies.0, &mut self.bodies.1)
        } else {
            (&self.bodies.1, &mut self.bodies.0)
        };

        let time = self.time;
        out_bodies.par_iter_mut()
                  .weight(200.0)
                  .zip(&in_bodies[..])
                  .for_each(|(out, prev)| {
                      let (vel, vel2) = next_velocity_par(time, prev, in_bodies);
                      out.velocity = vel;
                      out.velocity2 = vel2;

                      let next_velocity = vel - vel2;
                      out.position = prev.position + next_velocity;
                  });

        self.time += 1;

        out_bodies
    }

    pub fn tick_seq(&mut self) -> &[Body] {
        let (in_bodies, out_bodies) = if (self.time & 1) == 0 {
            (&self.bodies.0, &mut self.bodies.1)
        } else {
            (&self.bodies.1, &mut self.bodies.0)
        };

        let time = self.time;
        for (out, prev) in out_bodies.iter_mut().zip(&in_bodies[..]) {
            let (vel, vel2) = next_velocity(time, prev, in_bodies);
            out.velocity = vel;
            out.velocity2 = vel2;

            let next_velocity = vel - vel2;
            out.position = prev.position + next_velocity;
        }

        self.time += 1;

        out_bodies
    }
}

/// Compute next velocity of `prev`
fn next_velocity(time: usize, prev: &Body, bodies: &[Body]) -> (Vector3<f64>, Vector3<f64>) {
    let time = time as f64;
    let center = Point3 {
        x: (time / 22.0).cos() * -4200.0,
        y: (time / 14.0).sin() * 9200.0,
        z: (time / 27.0).sin() * 6000.0,
    };

    // pull to center
    let max_distance = 3400.0;
    let pull_strength = 0.042;

    // zones
    let zone = 400.0;
    let repel = 100.0;
    let align = 300.0;
    let attract = 100.0;

    let (speed_limit, attract_power);
    if time < 500.0 {
        speed_limit = 2000.0;
        attract_power = 100.9;
    } else {
        speed_limit = 0.2;
        attract_power = 20.9;
    }

    let zone_sqrd = 3.0 * (zone * zone);

    let mut acc = Vector3::zero();
    let mut acc2 = Vector3::zero();

    let dir_to_center = center - prev.position;
    let dist_to_center = dir_to_center.length();

    // orient to center
    if dist_to_center > max_distance {
        let velc = if time < 200.0 {
            0.2
        } else {
            (dist_to_center - max_distance) * pull_strength
        };

        let diff = (dir_to_center / dist_to_center) * velc;
        acc += diff;
    }

    // TODO -- parallelize this loop too? would be easy enough, it's just a reduction
    // Just have to factor things so that `tick_seq` doesn't do it in parallel.
    for body in bodies {
        let r = body.position - prev.position;

        // make sure we are not testing the particle against its own position
        let are_same = r == Vector3::zero();

        let dist_sqrd = r.length2();

        if dist_sqrd < zone_sqrd && !are_same {
            let length = dist_sqrd.sqrt();
            let percent = dist_sqrd / zone_sqrd;

            if dist_sqrd < repel {
                let f = (repel / percent - 1.0) * 0.025;
                let normal = (r / length) * f;
                acc += normal;
                acc2 += normal;
            } else if dist_sqrd < align {
                let thresh_delta = align - repel;
                let adjusted_percent = (percent - repel) / thresh_delta;
                let q = (0.5 - (adjusted_percent * PI * 2.0).cos() * 0.5 + 0.5) * 100.9;

                // normalize vel2 and multiply by factor
                let vel2_length = body.velocity2.length();
                let vel2 = (body.velocity2 / vel2_length) * q;

                // normalize own velocity
                let vel_length = prev.velocity.length();
                let vel = (prev.velocity / vel_length) * q;

                acc += vel2;
                acc2 += vel;
            }

            if dist_sqrd > attract { // attract
                let thresh_delta2 = 1.0 - attract;
                let adjusted_percent2 = (percent - attract) / thresh_delta2;
                let c = (1.0 - ((adjusted_percent2 * PI * 2.0).cos() * 0.5 + 0.5)) * attract_power;

                // normalize the distance vector
                let d = (r / length) * c;

                acc += d;
                acc2 -= d;
            }
        }
    }

    // Speed limits
    if time > 500.0 {
        let acc_squared = acc.length2();
        if acc_squared > speed_limit {
            acc *= 0.015;
        }

        let acc_squared2 = acc2.length2();
        if acc_squared2 > speed_limit {
            acc2 *= 0.015;
        }
    }

    let mut new = prev.velocity + acc;
    let mut new2 = prev.velocity2 + acc2;

    if time < 500.0 {
        let acs = new2.length2();
        if acs > speed_limit {
            new2 *= 0.15;
        }

        let acs2 = new.length2();
        if acs2 > speed_limit {
            new *= 0.15;
        }
    }

    (new, new2)
}

/// Compute next velocity of `prev`
fn next_velocity_par(time: usize, prev: &Body, bodies: &[Body])
                     -> (Vector3<f64>, Vector3<f64>) {
    let time = time as f64;
    let center = Point3 {
        x: (time / 22.0).cos() * -4200.0,
        y: (time / 14.0).sin() * 9200.0,
        z: (time / 27.0).sin() * 6000.0,
    };

    // pull to center
    let max_distance = 3400.0;
    let pull_strength = 0.042;

    // zones
    let zone = 400.0;
    let repel = 100.0;
    let align = 300.0;
    let attract = 100.0;

    let (speed_limit, attract_power);
    if time < 500.0 {
        speed_limit = 2000.0;
        attract_power = 100.9;
    } else {
        speed_limit = 0.2;
        attract_power = 20.9;
    }

    let zone_sqrd = 3.0 * (zone * zone);

    let mut acc = Vector3::zero();
    let mut acc2 = Vector3::zero();

    let dir_to_center = center - prev.position;
    let dist_to_center = dir_to_center.length();

    // orient to center
    if dist_to_center > max_distance {
        let velc = if time < 200.0 {
            0.2
        } else {
            (dist_to_center - max_distance) * pull_strength
        };

        let diff = (dir_to_center / dist_to_center) * velc;
        acc += diff;
    }

    let (diff, diff2) =
        bodies.par_iter()
              .map(|body| {
                  let r = body.position - prev.position;

                  let mut diff = Vector3::zero();
                  let mut diff2 = Vector3::zero();

                  // make sure we are not testing the particle against its own position
                  let are_same = r == Vector3::zero();

                  let dist_sqrd = r.length2();

                  if dist_sqrd < zone_sqrd && !are_same {
                      let length = dist_sqrd.sqrt();
                      let percent = dist_sqrd / zone_sqrd;

                      if dist_sqrd < repel {
                          let f = (repel / percent - 1.0) * 0.025;
                          let normal = (r / length) * f;
                          diff += normal;
                          diff2 += normal;
                      } else if dist_sqrd < align {
                          let thresh_delta = align - repel;
                          let adjusted_percent = (percent - repel) / thresh_delta;
                          let q = (0.5 - (adjusted_percent * PI * 2.0).cos() * 0.5 + 0.5) * 100.9;

                          // normalize vel2 and multiply by factor
                          let vel2_length = body.velocity2.length();
                          let vel2 = (body.velocity2 / vel2_length) * q;

                          // normalize own velocity
                          let vel_length = prev.velocity.length();
                          let vel = (prev.velocity / vel_length) * q;

                          diff += vel2;
                          diff2 += vel;
                      }

                      if dist_sqrd > attract { // attract
                          let thresh_delta2 = 1.0 - attract;
                          let adjusted_percent2 = (percent - attract) / thresh_delta2;
                          let c = (1.0 - ((adjusted_percent2 * PI * 2.0).cos() * 0.5 + 0.5)) * attract_power;

                          // normalize the distance vector
                          let d = (r / length) * c;

                          diff += d;
                          diff2 -= d;
                      }
                  }

                  (diff, diff2)
              })
              .weight(NEG_INFINITY)
              .reduce_with_identity(
                  (Vector3::zero(), Vector3::zero()),
                  |(diffa, diff2a), (diffb, diff2b)| (diffa + diffb, diff2a + diff2b));

    acc += diff;
    acc2 += diff2;

    // Speed limits
    if time > 500.0 {
        let acc_squared = acc.length2();
        if acc_squared > speed_limit {
            acc *= 0.015;
        }

        let acc_squared2 = acc2.length2();
        if acc_squared2 > speed_limit {
            acc2 *= 0.015;
        }
    }

    let mut new = prev.velocity + acc;
    let mut new2 = prev.velocity2 + acc2;

    if time < 500.0 {
        let acs = new2.length2();
        if acs > speed_limit {
            new2 *= 0.15;
        }

        let acs2 = new.length2();
        if acs2 > speed_limit {
            new *= 0.15;
        }
    }

    (new, new2)
}
<|endoftext|>


<commit_before>extern crate termion;

use self::termion::event;
use self::termion::raw::{RawTerminal, IntoRawMode};
use self::termion::screen::AlternateScreen;
use self::termion::input::TermRead;
use self::termion::cursor;
use self::termion::color;
use std::io::{self, Write};
use std::iter;

use super::base::*;

macro_rules! decode_color {
    ($x:expr, $c:expr) => {{
        match $c {
            Color::Reset => format!("{}", $x(color::Reset)),
            Color::Black => format!("{}", $x(color::Black)),
            Color::White => format!("{}", $x(color::White)),
            Color::Grey => format!("{}", $x(color::LightBlack)),
        }
    }}
}

impl From<event::Key> for Key {
    fn from(k: event::Key) -> Key {
        match k {
            event::Key::Backspace => Key::Backspace,
            event::Key::Left => Key::Left,
            event::Key::Right => Key::Right,
            event::Key::Up => Key::Up,
            event::Key::Down => Key::Down,
            event::Key::Home => Key::Home,
            event::Key::End => Key::End,
            event::Key::PageUp => Key::PageUp,
            event::Key::PageDown => Key::PageDown,
            event::Key::Delete => Key::Delete,
            event::Key::Insert => Key::Insert,
            event::Key::F(n) => Key::F(n),
            event::Key::Char(c) => Key::Char(c),
            event::Key::Alt(c) => Key::Alt(c),
            event::Key::Ctrl(c) => Key::Ctrl(c),
            event::Key::Null => Key::Null,
            event::Key::Esc => Key::Esc,
            event::Key::__IsNotComplete => panic!("got a weird key from termios"),
        }
    }
}

impl From<event::MouseEvent> for MouseEvent {
    fn from(e: event::MouseEvent) -> MouseEvent {
        match e {
            event::MouseEvent::Press(b, x, y) => MouseEvent::Press(MouseButton::from(b), x as i32, y as i32),
            event::MouseEvent::Release(x, y) => MouseEvent::Release(x as i32, y as i32),
            event::MouseEvent::Hold(x, y) => MouseEvent::Hold(x as i32, y as i32),
        }
    }
}

impl From<event::MouseButton> for MouseButton {
    fn from(b: event::MouseButton) -> MouseButton {
        match b {
            event::MouseButton::Left => MouseButton::Left,
            event::MouseButton::Right => MouseButton::Right,
            event::MouseButton::Middle => MouseButton::Middle,
            event::MouseButton::WheelUp => MouseButton::WheelUp,
            event::MouseButton::WheelDown => MouseButton::WheelDown,
        }
    }
}

impl From<event::Event> for Event {
    fn from(e: event::Event) -> Event {
        match e {
            event::Event::Key(k) => Event::Key(k.into()),
            event::Event::Mouse(m) => Event::Mouse(m.into()),
            event::Event::Unsupported(v) => Event::Unsupported(v.iter().map(|x| *x as u32).collect()),
        }
    }
}

pub struct Terminal {
    out: AlternateScreen<RawTerminal<io::Stdout>>,
}

impl Terminal {
    pub fn keys(&mut self) -> iter::Map<termion::input::Events<io::Stdin>, fn(io::Result<event::Event>) -> Event> {
        fn extract(e: io::Result<event::Event>) -> Event { Event::from(e.unwrap()) }
        io::stdin().events().map(extract)
    }
}

impl Write for Terminal {
    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
        self.out.write(data)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.out.flush()
    }
}

impl Default for Terminal {
    fn default() -> Terminal {
        Terminal {
            out: AlternateScreen::from(io::stdout().into_raw_mode().unwrap()),
        }
    }
}

impl TermImpl for Terminal {
    fn get_size(&self) -> (i32, i32) {
        let (x, y) = termion::terminal_size().unwrap();
        (x as i32, y as i32)
    }

    fn goto(&mut self, (x, y): (i32, i32)) {
        write!(self.out, "{}", cursor::Goto(x as u16, y as u16)).unwrap();
    }

    fn set_color_fg(&mut self, c: Color) {
        write!(self.out, "{}", decode_color!(color::Fg, c)).unwrap();
    }

    fn set_color_bg(&mut self, c: Color) {
        write!(self.out, "{}", decode_color!(color::Bg, c)).unwrap();
    }

    fn clear(&mut self) {
        write!(self.out, "{}", termion::clear::All).unwrap();
    }
}
<commit_msg>Lazily fix UNIX modifier keys<commit_after>extern crate termion;

use self::termion::event;
use self::termion::raw::{RawTerminal, IntoRawMode};
use self::termion::screen::AlternateScreen;
use self::termion::input::TermRead;
use self::termion::cursor;
use self::termion::color;
use std::io::{self, Write};
use std::iter;

use super::base::*;

macro_rules! decode_color {
    ($x:expr, $c:expr) => {{
        match $c {
            Color::Reset => format!("{}", $x(color::Reset)),
            Color::Black => format!("{}", $x(color::Black)),
            Color::White => format!("{}", $x(color::White)),
            Color::Grey => format!("{}", $x(color::LightBlack)),
        }
    }}
}

impl From<event::Key> for Key {
    fn from(k: event::Key) -> Key {
        match k {
            event::Key::Backspace => Key::Backspace,
            event::Key::Left => Key::Left,
            event::Key::Right => Key::Right,
            event::Key::Up => Key::Up,
            event::Key::Down => Key::Down,
            event::Key::Home => Key::Home,
            event::Key::End => Key::End,
            event::Key::PageUp => Key::PageUp,
            event::Key::PageDown => Key::PageDown,
            event::Key::Delete => Key::Delete,
            event::Key::Insert => Key::Insert,
            event::Key::F(n) => Key::F(n),
            event::Key::Char(c) => Key::Char(c),
            event::Key::Alt(c) => Key::Alt(Box::new(Key::Char(c))),
            event::Key::Ctrl(c) => Key::Ctrl(Box::new(Key::Char(c))),
            event::Key::Null => Key::Null,
            event::Key::Esc => Key::Esc,
            event::Key::__IsNotComplete => panic!("got a weird key from termios"),
        }
    }
}

impl From<event::MouseEvent> for MouseEvent {
    fn from(e: event::MouseEvent) -> MouseEvent {
        match e {
            event::MouseEvent::Press(b, x, y) => MouseEvent::Press(MouseButton::from(b), x as i32, y as i32),
            event::MouseEvent::Release(x, y) => MouseEvent::Release(x as i32, y as i32),
            event::MouseEvent::Hold(x, y) => MouseEvent::Hold(x as i32, y as i32),
        }
    }
}

impl From<event::MouseButton> for MouseButton {
    fn from(b: event::MouseButton) -> MouseButton {
        match b {
            event::MouseButton::Left => MouseButton::Left,
            event::MouseButton::Right => MouseButton::Right,
            event::MouseButton::Middle => MouseButton::Middle,
            event::MouseButton::WheelUp => MouseButton::WheelUp,
            event::MouseButton::WheelDown => MouseButton::WheelDown,
        }
    }
}

impl From<event::Event> for Event {
    fn from(e: event::Event) -> Event {
        match e {
            event::Event::Key(k) => Event::Key(k.into()),
            event::Event::Mouse(m) => Event::Mouse(m.into()),
            event::Event::Unsupported(v) => Event::Unsupported(v.iter().map(|x| *x as u32).collect()),
        }
    }
}

pub struct Terminal {
    out: AlternateScreen<RawTerminal<io::Stdout>>,
}

impl Terminal {
    pub fn keys(&mut self) -> iter::Map<termion::input::Events<io::Stdin>, fn(io::Result<event::Event>) -> Event> {
        fn extract(e: io::Result<event::Event>) -> Event { Event::from(e.unwrap()) }
        io::stdin().events().map(extract)
    }
}

impl Write for Terminal {
    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
        self.out.write(data)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.out.flush()
    }
}

impl Default for Terminal {
    fn default() -> Terminal {
        Terminal {
            out: AlternateScreen::from(io::stdout().into_raw_mode().unwrap()),
        }
    }
}

impl TermImpl for Terminal {
    fn get_size(&self) -> (i32, i32) {
        let (x, y) = termion::terminal_size().unwrap();
        (x as i32, y as i32)
    }

    fn goto(&mut self, (x, y): (i32, i32)) {
        write!(self.out, "{}", cursor::Goto(x as u16, y as u16)).unwrap();
    }

    fn set_color_fg(&mut self, c: Color) {
        write!(self.out, "{}", decode_color!(color::Fg, c)).unwrap();
    }

    fn set_color_bg(&mut self, c: Color) {
        write!(self.out, "{}", decode_color!(color::Bg, c)).unwrap();
    }

    fn clear(&mut self) {
        write!(self.out, "{}", termion::clear::All).unwrap();
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use std::{fmt, hash::Hash};

use common::WithLocation;
use dashmap::DashMap;
use fnv::FnvBuildHasher;
use intern::string_key::{Intern, StringKey};
use ouroboros::self_referencing;

use crate::{
    Argument, ArgumentDefinitions, Directive, Enum, EnumID, Field, FieldID, InputObject,
    InputObjectID, Interface, InterfaceID, Object, ObjectID, Scalar, ScalarID, Schema, Type,
    TypeReference, Union, UnionID,
};

use super::FlatBufferSchema;

#[self_referencing]
struct OwnedFlatBufferSchema {
    #[allow(dead_code)]
    data: Vec<u8>,

    #[borrows(data)]
    #[covariant]
    pub schema: FlatBufferSchema<'this>,
}

const CLIENTID_FIELD_ID: FieldID = FieldID(10_000_000);
const TYPENAME_FIELD_ID: FieldID = FieldID(10_000_001);
const FETCH_TOKEN_FIELD_ID: FieldID = FieldID(10_000_002);
const STRONGID_FIELD_ID: FieldID = FieldID(10_000_003);
const IS_FULFILLED_FIELD_ID: FieldID = FieldID(10_000_004);

pub struct SchemaWrapper {
    clientid_field_name: StringKey,
    strongid_field_name: StringKey,
    typename_field_name: StringKey,
    fetch_token_field_name: StringKey,
    is_fulfilled_field_name: StringKey,
    unchecked_argument_type_sentinel: Option<TypeReference>,

    directives: Cache<StringKey, Option<Directive>>,
    interfaces: Cache<InterfaceID, Interface>,
    unions: Cache<UnionID, Union>,
    input_objects: Cache<InputObjectID, InputObject>,
    enums: Cache<EnumID, Enum>,
    scalars: Cache<ScalarID, Scalar>,
    fields: Cache<FieldID, Field>,
    objects: Cache<ObjectID, Object>,
    fb: OwnedFlatBufferSchema,
}
impl fmt::Debug for SchemaWrapper {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Schema").finish()
    }
}

fn _assert_send_sync(_: impl Send + Sync) {}
fn _assert_send_sync2(s: &SchemaWrapper) {
    _assert_send_sync(s)
}

impl SchemaWrapper {
    pub fn from_vec(data: Vec<u8>) -> Self {
        let fb = OwnedFlatBufferSchemaBuilder {
            data,
            schema_builder: |data| FlatBufferSchema::build(data),
        }
        .build();

        let mut result = Self {
            clientid_field_name: "__id".intern(),
            strongid_field_name: "strong_id__".intern(),
            typename_field_name: "__typename".intern(),
            fetch_token_field_name: "__token".intern(),
            is_fulfilled_field_name: "is_fulfilled__".intern(),
            unchecked_argument_type_sentinel: None,
            directives: Cache::new(),
            unions: Cache::new(),
            interfaces: Cache::new(),
            input_objects: Cache::new(),
            enums: Cache::new(),
            scalars: Cache::new(),
            fields: Cache::new(),
            objects: Cache::new(),
            fb,
        };

        // prepopulate special fields
        result.fields.get(TYPENAME_FIELD_ID, || Field {
            name: WithLocation::generated(result.typename_field_name),
            is_extension: false,
            arguments: ArgumentDefinitions::new(Default::default()),
            type_: TypeReference::NonNull(Box::new(TypeReference::Named(
                result.get_type("String".intern()).unwrap(),
            ))),
            directives: Vec::new(),
            parent_type: None,
            description: None,
        });
        result.fields.get(CLIENTID_FIELD_ID, || Field {
            name: WithLocation::generated(result.clientid_field_name),
            is_extension: true,
            arguments: ArgumentDefinitions::new(Default::default()),
            type_: TypeReference::NonNull(Box::new(TypeReference::Named(
                result.get_type("ID".intern()).unwrap(),
            ))),
            directives: Vec::new(),
            parent_type: None,
            description: None,
        });
        result.fields.get(STRONGID_FIELD_ID, || Field {
            name: WithLocation::generated(result.strongid_field_name),
            is_extension: true,
            arguments: ArgumentDefinitions::new(Default::default()),
            type_: TypeReference::Named(result.get_type("ID".intern()).unwrap()),
            directives: Vec::new(),
            parent_type: None,
            description: None,
        });
        result.fields.get(FETCH_TOKEN_FIELD_ID, || Field {
            name: WithLocation::generated(result.fetch_token_field_name),
            is_extension: false,
            arguments: ArgumentDefinitions::new(Default::default()),
            type_: TypeReference::NonNull(Box::new(TypeReference::Named(
                result.get_type("ID".intern()).unwrap(),
            ))),
            directives: Vec::new(),
            parent_type: None,
            description: None,
        });
        result.fields.get(IS_FULFILLED_FIELD_ID, || Field {
            name: WithLocation::generated(result.is_fulfilled_field_name),
            is_extension: true,
            arguments: ArgumentDefinitions::new(vec![Argument {
                name: "name".intern(),
                type_: TypeReference::NonNull(Box::new(TypeReference::Named(
                    result.get_type("String".intern()).unwrap(),
                ))),
                default_value: None,
                description: None,
                directives: Default::default(),
            }]),
            type_: TypeReference::NonNull(Box::new(TypeReference::Named(
                result.get_type("Boolean".intern()).unwrap(),
            ))),
            directives: Vec::new(),
            parent_type: None,
            description: None,
        });

        result.unchecked_argument_type_sentinel = Some(TypeReference::Named(
            result.get_type("Boolean".intern()).unwrap(),
        ));

        result
    }

    pub fn has_type(&self, type_name: StringKey) -> bool {
        self.flatbuffer_schema().has_type(type_name)
    }

    pub fn has_directive(&self, name: StringKey) -> bool {
        self.get_directive(name).is_some()
    }

    pub fn get_directives(&self) -> Vec<&Directive> {
        todo!()
    }

    pub fn get_type_map(&self) -> impl Iterator<Item = (&StringKey, &Type)> {
        if true {
            todo!();
        }
        (vec![]).into_iter()
    }

    fn flatbuffer_schema(&self) -> &FlatBufferSchema<'_> {
        self.fb.borrow_schema()
    }
}

impl Schema for SchemaWrapper {
    fn query_type(&self) -> Option<Type> {
        Some(self.flatbuffer_schema().query_type())
    }

    fn mutation_type(&self) -> Option<Type> {
        self.flatbuffer_schema().mutation_type()
    }

    fn subscription_type(&self) -> Option<Type> {
        self.flatbuffer_schema().subscription_type()
    }

    fn clientid_field(&self) -> FieldID {
        CLIENTID_FIELD_ID
    }

    fn strongid_field(&self) -> FieldID {
        STRONGID_FIELD_ID
    }

    fn typename_field(&self) -> FieldID {
        TYPENAME_FIELD_ID
    }

    fn fetch_token_field(&self) -> FieldID {
        FETCH_TOKEN_FIELD_ID
    }

    fn is_fulfilled_field(&self) -> FieldID {
        IS_FULFILLED_FIELD_ID
    }

    fn get_type(&self, type_name: StringKey) -> Option<Type> {
        self.flatbuffer_schema().get_type(type_name)
    }

    fn get_directive(&self, name: StringKey) -> Option<&Directive> {
        self.directives
            .get(name, || {
                match (name.lookup(), self.flatbuffer_schema().get_directive(name)) {
                    ("defer", Some(mut directive)) | ("stream", Some(mut directive)) => {
                        let mut next_args: Vec<_> = directive.arguments.iter().cloned().collect();
                        for arg in next_args.iter_mut() {
                            if arg.name.lookup() == "label" {
                                if let TypeReference::NonNull(of) = &arg.type_ {
                                    arg.type_ = *of.clone()
                                };
                            }
                        }
                        directive.arguments = ArgumentDefinitions::new(next_args);
                        Some(directive)
                    }
                    (_, result) => result,
                }
            })
            .as_ref()
    }

    fn input_object(&self, id: InputObjectID) -> &InputObject {
        self.input_objects
            .get(id, || self.flatbuffer_schema().input_object(id))
    }

    fn enum_(&self, id: EnumID) -> &Enum {
        self.enums.get(id, || self.flatbuffer_schema().enum_(id))
    }

    fn scalar(&self, id: ScalarID) -> &Scalar {
        self.scalars.get(id, || self.flatbuffer_schema().scalar(id))
    }

    fn field(&self, id: FieldID) -> &Field {
        self.fields.get(id, || self.flatbuffer_schema().field(id))
    }

    fn object(&self, id: ObjectID) -> &Object {
        self.objects.get(id, || self.flatbuffer_schema().object(id))
    }

    fn union(&self, id: UnionID) -> &Union {
        self.unions.get(id, || self.flatbuffer_schema().union(id))
    }

    fn interface(&self, id: InterfaceID) -> &Interface {
        self.interfaces
            .get(id, || self.flatbuffer_schema().interface(id))
    }

    fn get_type_name(&self, type_: Type) -> StringKey {
        match type_ {
            Type::Enum(id) => self.enum_(id).name.item,
            Type::InputObject(id) => self.input_object(id).name.item,
            Type::Interface(id) => self.interface(id).name.item,
            Type::Object(id) => self.object(id).name.item,
            Type::Scalar(id) => self.scalar(id).name.item,
            Type::Union(id) => self.union(id).name.item,
        }
    }

    fn is_extension_type(&self, type_: Type) -> bool {
        match type_ {
            Type::Enum(id) => self.enum_(id).is_extension,
            Type::Interface(id) => self.interface(id).is_extension,
            Type::Object(id) => self.object(id).is_extension,
            Type::Scalar(id) => self.scalar(id).is_extension,
            Type::Union(id) => self.union(id).is_extension,
            Type::InputObject(_) => false,
        }
    }

    fn is_string(&self, type_: Type) -> bool {
        match type_ {
            Type::Scalar(id) => self.scalar(id).name.item.lookup() == "String",
            _ => false,
        }
    }

    fn is_id(&self, type_: Type) -> bool {
        match type_ {
            Type::Scalar(id) => self.scalar(id).name.item.lookup() == "ID",
            _ => false,
        }
    }

    fn named_field(&self, parent_type: Type, name: StringKey) -> Option<FieldID> {
        // Special case for __typename and __id fields, which should not be in the list of type fields
        // but should be fine to select.
        let can_have_typename = matches!(
            parent_type,
            Type::Object(_) | Type::Interface(_) | Type::Union(_)
        );
        if can_have_typename {
            if name == self.typename_field_name {
                return Some(TYPENAME_FIELD_ID);
            }
            // TODO(inanc): Also check if the parent type is fetchable?
            if name == self.fetch_token_field_name {
                return Some(FETCH_TOKEN_FIELD_ID);
            }
            if name == self.clientid_field_name {
                return Some(CLIENTID_FIELD_ID);
            }
            if name == self.strongid_field_name {
                return Some(STRONGID_FIELD_ID);
            }
            if name == self.is_fulfilled_field_name {
                return Some(IS_FULFILLED_FIELD_ID);
            }
        }

        let fields = match parent_type {
            Type::Object(id) => {
                let object = self.object(id);
                &object.fields
            }
            Type::Interface(id) => {
                let interface = self.interface(id);
                &interface.fields
            }
            // Unions don't have any fields, but can have selections like __typename
            // or a field with @fixme_fat_interface
            Type::Union(_) => return None,
            _ => panic!(
                "Cannot get field {} on type '{:?}', this type does not have fields",
                name,
                self.get_type_name(parent_type)
            ),
        };
        fields
            .iter()
            .find(|field_id| {
                let field = self.field(**field_id);
                field.name.item == name
            })
            .cloned()
    }

    fn unchecked_argument_type_sentinel(&self) -> &TypeReference {
        self.unchecked_argument_type_sentinel.as_ref().unwrap()
    }

    fn snapshot_print(&self) -> String {
        todo!()
    }

    fn input_objects<'a>(&'a self) -> Box<dyn Iterator<Item = &'a InputObject> + 'a> {
        Box::new(self.input_objects.map.iter().map(|ref_| *ref_.value()))
    }

    fn enums<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Enum> + 'a> {
        Box::new(self.enums.map.iter().map(|ref_| *ref_.value()))
    }

    fn scalars<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Scalar> + 'a> {
        Box::new(self.scalars.map.iter().map(|ref_| *ref_.value()))
    }

    fn fields<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Field> + 'a> {
        Box::new(self.fields.map.iter().map(|ref_| *ref_.value()))
    }

    fn objects<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Object> + 'a> {
        Box::new(self.objects.map.iter().map(|ref_| *ref_.value()))
    }

    fn unions<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Union> + 'a> {
        Box::new(self.unions.map.iter().map(|ref_| *ref_.value()))
    }

    fn interfaces<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Interface> + 'a> {
        Box::new(self.interfaces.map.iter().map(|ref_| *ref_.value()))
    }
}

struct Cache<K: Hash + Eq, V: 'static> {
    map: DashMap<K, &'static V, FnvBuildHasher>,
}
impl<K: Hash + Eq, V> Cache<K, V> {
    fn new() -> Self {
        Self {
            map: DashMap::with_hasher(FnvBuildHasher::default()),
        }
    }

    fn get(&self, key: K, f: impl FnOnce() -> V) -> &V {
        *self
            .map
            .entry(key)
            .or_insert_with(|| Box::leak(Box::new(f())))
    }
}
<commit_msg>Fix input_objects api so it won't return empty objects<commit_after>/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use std::{fmt, hash::Hash};

use common::WithLocation;
use dashmap::DashMap;
use fnv::FnvBuildHasher;
use intern::string_key::{Intern, StringKey};
use ouroboros::self_referencing;

use crate::{
    Argument, ArgumentDefinitions, Directive, Enum, EnumID, Field, FieldID, InputObject,
    InputObjectID, Interface, InterfaceID, Object, ObjectID, Scalar, ScalarID, Schema, Type,
    TypeReference, Union, UnionID,
};

use super::FlatBufferSchema;

#[self_referencing]
struct OwnedFlatBufferSchema {
    #[allow(dead_code)]
    data: Vec<u8>,

    #[borrows(data)]
    #[covariant]
    pub schema: FlatBufferSchema<'this>,
}

const CLIENTID_FIELD_ID: FieldID = FieldID(10_000_000);
const TYPENAME_FIELD_ID: FieldID = FieldID(10_000_001);
const FETCH_TOKEN_FIELD_ID: FieldID = FieldID(10_000_002);
const STRONGID_FIELD_ID: FieldID = FieldID(10_000_003);
const IS_FULFILLED_FIELD_ID: FieldID = FieldID(10_000_004);

pub struct SchemaWrapper {
    clientid_field_name: StringKey,
    strongid_field_name: StringKey,
    typename_field_name: StringKey,
    fetch_token_field_name: StringKey,
    is_fulfilled_field_name: StringKey,
    unchecked_argument_type_sentinel: Option<TypeReference>,

    directives: Cache<StringKey, Option<Directive>>,
    interfaces: Cache<InterfaceID, Interface>,
    unions: Cache<UnionID, Union>,
    input_objects: Cache<InputObjectID, InputObject>,
    enums: Cache<EnumID, Enum>,
    scalars: Cache<ScalarID, Scalar>,
    fields: Cache<FieldID, Field>,
    objects: Cache<ObjectID, Object>,
    fb: OwnedFlatBufferSchema,
}
impl fmt::Debug for SchemaWrapper {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Schema").finish()
    }
}

fn _assert_send_sync(_: impl Send + Sync) {}
fn _assert_send_sync2(s: &SchemaWrapper) {
    _assert_send_sync(s)
}

impl SchemaWrapper {
    pub fn from_vec(data: Vec<u8>) -> Self {
        let fb = OwnedFlatBufferSchemaBuilder {
            data,
            schema_builder: |data| FlatBufferSchema::build(data),
        }
        .build();

        let mut result = Self {
            clientid_field_name: "__id".intern(),
            strongid_field_name: "strong_id__".intern(),
            typename_field_name: "__typename".intern(),
            fetch_token_field_name: "__token".intern(),
            is_fulfilled_field_name: "is_fulfilled__".intern(),
            unchecked_argument_type_sentinel: None,
            directives: Cache::new(),
            unions: Cache::new(),
            interfaces: Cache::new(),
            input_objects: Cache::new(),
            enums: Cache::new(),
            scalars: Cache::new(),
            fields: Cache::new(),
            objects: Cache::new(),
            fb,
        };

        // prepopulate special fields
        result.fields.get(TYPENAME_FIELD_ID, || Field {
            name: WithLocation::generated(result.typename_field_name),
            is_extension: false,
            arguments: ArgumentDefinitions::new(Default::default()),
            type_: TypeReference::NonNull(Box::new(TypeReference::Named(
                result.get_type("String".intern()).unwrap(),
            ))),
            directives: Vec::new(),
            parent_type: None,
            description: None,
        });
        result.fields.get(CLIENTID_FIELD_ID, || Field {
            name: WithLocation::generated(result.clientid_field_name),
            is_extension: true,
            arguments: ArgumentDefinitions::new(Default::default()),
            type_: TypeReference::NonNull(Box::new(TypeReference::Named(
                result.get_type("ID".intern()).unwrap(),
            ))),
            directives: Vec::new(),
            parent_type: None,
            description: None,
        });
        result.fields.get(STRONGID_FIELD_ID, || Field {
            name: WithLocation::generated(result.strongid_field_name),
            is_extension: true,
            arguments: ArgumentDefinitions::new(Default::default()),
            type_: TypeReference::Named(result.get_type("ID".intern()).unwrap()),
            directives: Vec::new(),
            parent_type: None,
            description: None,
        });
        result.fields.get(FETCH_TOKEN_FIELD_ID, || Field {
            name: WithLocation::generated(result.fetch_token_field_name),
            is_extension: false,
            arguments: ArgumentDefinitions::new(Default::default()),
            type_: TypeReference::NonNull(Box::new(TypeReference::Named(
                result.get_type("ID".intern()).unwrap(),
            ))),
            directives: Vec::new(),
            parent_type: None,
            description: None,
        });
        result.fields.get(IS_FULFILLED_FIELD_ID, || Field {
            name: WithLocation::generated(result.is_fulfilled_field_name),
            is_extension: true,
            arguments: ArgumentDefinitions::new(vec![Argument {
                name: "name".intern(),
                type_: TypeReference::NonNull(Box::new(TypeReference::Named(
                    result.get_type("String".intern()).unwrap(),
                ))),
                default_value: None,
                description: None,
                directives: Default::default(),
            }]),
            type_: TypeReference::NonNull(Box::new(TypeReference::Named(
                result.get_type("Boolean".intern()).unwrap(),
            ))),
            directives: Vec::new(),
            parent_type: None,
            description: None,
        });

        result.unchecked_argument_type_sentinel = Some(TypeReference::Named(
            result.get_type("Boolean".intern()).unwrap(),
        ));

        result
    }

    pub fn has_type(&self, type_name: StringKey) -> bool {
        self.flatbuffer_schema().has_type(type_name)
    }

    pub fn has_directive(&self, name: StringKey) -> bool {
        self.get_directive(name).is_some()
    }

    pub fn get_directives(&self) -> Vec<&Directive> {
        todo!()
    }

    pub fn get_type_map(&self) -> impl Iterator<Item = (&StringKey, &Type)> {
        if true {
            todo!();
        }
        (vec![]).into_iter()
    }

    fn flatbuffer_schema(&self) -> &FlatBufferSchema<'_> {
        self.fb.borrow_schema()
    }
}

impl Schema for SchemaWrapper {
    fn query_type(&self) -> Option<Type> {
        Some(self.flatbuffer_schema().query_type())
    }

    fn mutation_type(&self) -> Option<Type> {
        self.flatbuffer_schema().mutation_type()
    }

    fn subscription_type(&self) -> Option<Type> {
        self.flatbuffer_schema().subscription_type()
    }

    fn clientid_field(&self) -> FieldID {
        CLIENTID_FIELD_ID
    }

    fn strongid_field(&self) -> FieldID {
        STRONGID_FIELD_ID
    }

    fn typename_field(&self) -> FieldID {
        TYPENAME_FIELD_ID
    }

    fn fetch_token_field(&self) -> FieldID {
        FETCH_TOKEN_FIELD_ID
    }

    fn is_fulfilled_field(&self) -> FieldID {
        IS_FULFILLED_FIELD_ID
    }

    fn get_type(&self, type_name: StringKey) -> Option<Type> {
        self.flatbuffer_schema().get_type(type_name)
    }

    fn get_directive(&self, name: StringKey) -> Option<&Directive> {
        self.directives
            .get(name, || {
                match (name.lookup(), self.flatbuffer_schema().get_directive(name)) {
                    ("defer", Some(mut directive)) | ("stream", Some(mut directive)) => {
                        let mut next_args: Vec<_> = directive.arguments.iter().cloned().collect();
                        for arg in next_args.iter_mut() {
                            if arg.name.lookup() == "label" {
                                if let TypeReference::NonNull(of) = &arg.type_ {
                                    arg.type_ = *of.clone()
                                };
                            }
                        }
                        directive.arguments = ArgumentDefinitions::new(next_args);
                        Some(directive)
                    }
                    (_, result) => result,
                }
            })
            .as_ref()
    }

    fn input_object(&self, id: InputObjectID) -> &InputObject {
        self.input_objects
            .get(id, || self.flatbuffer_schema().input_object(id))
    }

    fn enum_(&self, id: EnumID) -> &Enum {
        self.enums.get(id, || self.flatbuffer_schema().enum_(id))
    }

    fn scalar(&self, id: ScalarID) -> &Scalar {
        self.scalars.get(id, || self.flatbuffer_schema().scalar(id))
    }

    fn field(&self, id: FieldID) -> &Field {
        self.fields.get(id, || self.flatbuffer_schema().field(id))
    }

    fn object(&self, id: ObjectID) -> &Object {
        self.objects.get(id, || self.flatbuffer_schema().object(id))
    }

    fn union(&self, id: UnionID) -> &Union {
        self.unions.get(id, || self.flatbuffer_schema().union(id))
    }

    fn interface(&self, id: InterfaceID) -> &Interface {
        self.interfaces
            .get(id, || self.flatbuffer_schema().interface(id))
    }

    fn get_type_name(&self, type_: Type) -> StringKey {
        match type_ {
            Type::Enum(id) => self.enum_(id).name.item,
            Type::InputObject(id) => self.input_object(id).name.item,
            Type::Interface(id) => self.interface(id).name.item,
            Type::Object(id) => self.object(id).name.item,
            Type::Scalar(id) => self.scalar(id).name.item,
            Type::Union(id) => self.union(id).name.item,
        }
    }

    fn is_extension_type(&self, type_: Type) -> bool {
        match type_ {
            Type::Enum(id) => self.enum_(id).is_extension,
            Type::Interface(id) => self.interface(id).is_extension,
            Type::Object(id) => self.object(id).is_extension,
            Type::Scalar(id) => self.scalar(id).is_extension,
            Type::Union(id) => self.union(id).is_extension,
            Type::InputObject(_) => false,
        }
    }

    fn is_string(&self, type_: Type) -> bool {
        match type_ {
            Type::Scalar(id) => self.scalar(id).name.item.lookup() == "String",
            _ => false,
        }
    }

    fn is_id(&self, type_: Type) -> bool {
        match type_ {
            Type::Scalar(id) => self.scalar(id).name.item.lookup() == "ID",
            _ => false,
        }
    }

    fn named_field(&self, parent_type: Type, name: StringKey) -> Option<FieldID> {
        // Special case for __typename and __id fields, which should not be in the list of type fields
        // but should be fine to select.
        let can_have_typename = matches!(
            parent_type,
            Type::Object(_) | Type::Interface(_) | Type::Union(_)
        );
        if can_have_typename {
            if name == self.typename_field_name {
                return Some(TYPENAME_FIELD_ID);
            }
            // TODO(inanc): Also check if the parent type is fetchable?
            if name == self.fetch_token_field_name {
                return Some(FETCH_TOKEN_FIELD_ID);
            }
            if name == self.clientid_field_name {
                return Some(CLIENTID_FIELD_ID);
            }
            if name == self.strongid_field_name {
                return Some(STRONGID_FIELD_ID);
            }
            if name == self.is_fulfilled_field_name {
                return Some(IS_FULFILLED_FIELD_ID);
            }
        }

        let fields = match parent_type {
            Type::Object(id) => {
                let object = self.object(id);
                &object.fields
            }
            Type::Interface(id) => {
                let interface = self.interface(id);
                &interface.fields
            }
            // Unions don't have any fields, but can have selections like __typename
            // or a field with @fixme_fat_interface
            Type::Union(_) => return None,
            _ => panic!(
                "Cannot get field {} on type '{:?}', this type does not have fields",
                name,
                self.get_type_name(parent_type)
            ),
        };
        fields
            .iter()
            .find(|field_id| {
                let field = self.field(**field_id);
                field.name.item == name
            })
            .cloned()
    }

    fn unchecked_argument_type_sentinel(&self) -> &TypeReference {
        self.unchecked_argument_type_sentinel.as_ref().unwrap()
    }

    fn snapshot_print(&self) -> String {
        todo!()
    }

    fn input_objects<'a>(&'a self) -> Box<dyn Iterator<Item = &'a InputObject> + 'a> {
        if self.input_objects.map.is_empty() {
            for i in 0..self.flatbuffer_schema().input_objects.len() {
                let id = InputObjectID(i.try_into().unwrap());
                self.input_object(id);
            }
        }

        Box::new(self.input_objects.map.iter().map(|ref_| *ref_.value()))
    }

    fn enums<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Enum> + 'a> {
        if self.enums.map.is_empty() {
            for i in 0..self.flatbuffer_schema().enums.len() {
                let id = EnumID(i.try_into().unwrap());
                self.enum_(id);
            }
        }

        Box::new(self.enums.map.iter().map(|ref_| *ref_.value()))
    }

    fn scalars<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Scalar> + 'a> {
        if self.scalars.map.is_empty() {
            for i in 0..self.flatbuffer_schema().scalars.len() {
                let id = ScalarID(i.try_into().unwrap());
                self.scalar(id);
            }
        }

        Box::new(self.scalars.map.iter().map(|ref_| *ref_.value()))
    }

    fn fields<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Field> + 'a> {
        if self.fields.map.is_empty() {
            for i in 0..self.flatbuffer_schema().fields.len() {
                let id = FieldID(i.try_into().unwrap());
                self.field(id);
            }
        }

        Box::new(self.fields.map.iter().map(|ref_| *ref_.value()))
    }

    fn objects<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Object> + 'a> {
        if self.objects.map.is_empty() {
            for i in 0..self.flatbuffer_schema().objects.len() {
                let id = ObjectID(i.try_into().unwrap());
                self.object(id);
            }
        }

        Box::new(self.objects.map.iter().map(|ref_| *ref_.value()))
    }

    fn unions<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Union> + 'a> {
        if self.unions.map.is_empty() {
            for i in 0..self.flatbuffer_schema().unions.len() {
                let id = UnionID(i.try_into().unwrap());
                self.union(id);
            }
        }

        Box::new(self.unions.map.iter().map(|ref_| *ref_.value()))
    }

    fn interfaces<'a>(&'a self) -> Box<dyn Iterator<Item = &'a Interface> + 'a> {
        if self.interfaces.map.is_empty() {
            for i in 0..self.flatbuffer_schema().interfaces.len() {
                let id = InterfaceID(i.try_into().unwrap());
                self.interface(id);
            }
        }

        Box::new(self.interfaces.map.iter().map(|ref_| *ref_.value()))
    }
}

struct Cache<K: Hash + Eq, V: 'static> {
    map: DashMap<K, &'static V, FnvBuildHasher>,
}
impl<K: Hash + Eq, V> Cache<K, V> {
    fn new() -> Self {
        Self {
            map: DashMap::with_hasher(FnvBuildHasher::default()),
        }
    }

    fn get(&self, key: K, f: impl FnOnce() -> V) -> &V {
        *self
            .map
            .entry(key)
            .or_insert_with(|| Box::leak(Box::new(f())))
    }
}
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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::mem::{size_of, transmute_copy};
use std::cmp;

/// Read `$size` of bytes from `$src`, and reinterpret them
/// as type `$ty`, in little-endian order. `$ty` must implement
/// the `Default` trait. Otherwise this won't compile.
/// This is copied and modified from byteorder crate.
macro_rules! read_num_bytes {
  ($ty:ty, $size:expr, $src:expr) => ({
    assert!($size <= $src.len());
    let mut data: $ty = Default::default();
    unsafe {
      ::std::ptr::copy_nonoverlapping(
        $src.as_ptr(),
        &mut data as *mut $ty as *mut u8,
        $size);
    }
    data
  });
}

/// Return the ceil of value/divisor
#[inline]
pub fn ceil(value: i64, divisor: i64) -> i64 {
  let mut result = value / divisor;
  if value % divisor != 0 { result += 1 };
  result
}

/// Returns the `num_bits` least-significant bits of `v`
#[inline]
pub fn trailing_bits(v: u64, num_bits: usize) -> u64 {
  if num_bits == 0 {
    return 0;
  }
  if num_bits >= 64 {
    return v;
  }
  let n = 64 - num_bits;
  (v << n) >> n
}

#[inline]
pub fn set_array_bit(bits: &mut [u8], i: usize) {
  bits[i / 8] |= 1 << (i % 8);
}

#[inline]
pub fn unset_array_bit(bits: &mut [u8], i: usize) {
  bits[i / 8] &= !(1 << (i % 8));
}

pub struct BitReader<'a> {
  /// The byte buffer to read from, passed in by client
  buffer: &'a [u8],

  /// Bytes are memcpy'd from `buffer` and values are read from this variable.
  /// This is faster than reading values byte by byte directly from `buffer`
  buffered_values: u64,

  /// Current byte offset in `buffer`
  byte_offset: usize,

  /// Current bit offset in `buffered_values`
  bit_offset: usize,

  /// Total number of bytes in `buffer`
  total_bytes: usize
}

impl<'a> BitReader<'a> {
  pub fn new(buffer: &'a [u8]) -> Self {
    let total_bytes = buffer.len();
    let num_bytes = cmp::min(8, total_bytes);
    let buffered_values = read_num_bytes!(u64, num_bytes, buffer);
    BitReader {
      buffer: buffer, buffered_values: buffered_values,
      byte_offset: 0, bit_offset: 0, total_bytes: total_bytes
    }
  }

  #[inline]
  pub fn reset(&mut self, buffer: &'a [u8]) {
    self.buffer = buffer;
    self.byte_offset = 0;
    self.bit_offset = 0;
  }

  #[inline]
  pub fn get_value<T: Default>(&mut self, num_bits: usize) -> Option<T> {
    assert!(num_bits <= 32);
    assert!(num_bits <= size_of::<T>() * 8);

    if self.byte_offset * 8 + self.bit_offset + num_bits > self.total_bytes * 8 {
      return None;
    }

    let mut v = trailing_bits(self.buffered_values, self.bit_offset + num_bits) >> self.bit_offset;
    self.bit_offset += num_bits;

    if self.bit_offset >= 64 {
      self.byte_offset += 8;
      self.bit_offset -= 64;

      let bytes_to_read = cmp::min(self.total_bytes - self.byte_offset, 8);
      self.buffered_values = read_num_bytes!(
        u64, bytes_to_read, self.buffer[self.byte_offset..]);

      v |= trailing_bits(self.buffered_values, self.bit_offset) << (num_bits - self.bit_offset);
    }

    // TODO: better to avoid copying here
    let result: T = unsafe {
      transmute_copy::<u64, T>(&v)
    };
    Some(result)
  }

  /// Read a `num_bytes`-sized value from this buffer and return it.
  /// `T` needs to be a little-endian native type. The value is assumed to
  /// be byte aligned so the bit reader will be advanced to the start of
  /// the next byte before reading the value. Return `None` if there's not
  /// enough bytes left.
  #[inline]
  pub fn get_aligned<T: Default>(&mut self, num_bytes: usize) -> Option<T> {
    let bytes_read = ceil(self.bit_offset as i64, 8) as usize;
    if self.byte_offset + bytes_read + num_bytes > self.total_bytes {
      // Not enough bytes left
      return None
    }

    // Advance byte_offset to next unread byte and read num_bytes
    self.byte_offset += bytes_read;
    let v = read_num_bytes!(T, num_bytes, self.buffer[self.byte_offset..]);
    self.byte_offset += num_bytes;

    // Reset buffered_values
    self.bit_offset = 0;
    let bytes_remaining = cmp::min(self.total_bytes - self.byte_offset, 8);
    self.buffered_values = read_num_bytes!(
      u64, bytes_remaining, self.buffer[self.byte_offset..]);
    Some(v)
  }
}

#[cfg(test)]
mod tests {
  use super::*;

  #[test]
  fn test_ceil() {
    assert_eq!(ceil(0, 1), 0);
    assert_eq!(ceil(1, 1), 1);
    assert_eq!(ceil(1, 2), 1);
    assert_eq!(ceil(1, 8), 1);
    assert_eq!(ceil(7, 8), 1);
    assert_eq!(ceil(8, 8), 1);
    assert_eq!(ceil(9, 8), 2);
    assert_eq!(ceil(9, 9), 1);
    assert_eq!(ceil(10000000000, 10), 1000000000);
    assert_eq!(ceil(10, 10000000000), 1);
    assert_eq!(ceil(10000000000, 1000000000), 10);
  }

  #[test]
  fn test_bit_reader_get_value() {
    let mut buffer = vec![255, 0];
    let mut bit_reader = BitReader::new(&buffer);
    let v1 = bit_reader.get_value::<i32>(1);
    assert!(v1.is_some());
    assert_eq!(v1.unwrap(), 1);
    let v2 = bit_reader.get_value::<i32>(2);
    assert!(v2.is_some());
    assert_eq!(v2.unwrap(), 3);
    let v3 = bit_reader.get_value::<i32>(3);
    assert!(v3.is_some());
    assert_eq!(v3.unwrap(), 7);
    let v4 = bit_reader.get_value::<i32>(4);
    assert!(v4.is_some());
    assert_eq!(v4.unwrap(), 3);
  }

  #[test]
  fn test_bit_reader_get_value_boundary() {
    let mut buffer = vec![10, 0, 0, 0, 20, 0, 30, 0, 0, 0, 40, 0];
    let mut bit_reader = BitReader::new(&buffer);
    let v1 = bit_reader.get_value::<i64>(32);
    assert!(v1.is_some());
    assert_eq!(v1.unwrap(), 10);
    let v2 = bit_reader.get_value::<i16>(16);
    assert!(v2.is_some());
    assert_eq!(v2.unwrap(), 20);
    let v3 = bit_reader.get_value::<i32>(32);
    assert!(v3.is_some());
    assert_eq!(v3.unwrap(), 30);
    let v4 = bit_reader.get_value::<i32>(16);
    assert!(v4.is_some());
    assert_eq!(v4.unwrap(), 40);
  }

  #[test]
  fn test_bit_reader_get_aligned() {
    // 0 1 1 1 0 1 0 1  1 1 0 0 1 0 1 1
    let mut buffer: Vec<u8> = vec!(117, 203);
    let mut bit_reader = BitReader::new(&buffer);
    let v1 = bit_reader.get_value::<i32>(3);
    assert!(v1.is_some());
    assert_eq!(v1.unwrap(), 5);
    let v2 = bit_reader.get_aligned::<i32>(1);
    assert!(v2.is_some());
    assert_eq!(v2.unwrap(), 203);
    let v3 = bit_reader.get_value::<i32>(1);
    assert!(v3.is_none());

    bit_reader.reset(&buffer);
    let v4 = bit_reader.get_aligned::<i32>(3);
    assert!(v4.is_none());
  }

  #[test]
  fn test_set_array_bit() {
    let mut buffer = vec![0, 0, 0];
    set_array_bit(&mut buffer[..], 1);
    assert_eq!(buffer, vec![2, 0, 0]);
    set_array_bit(&mut buffer[..], 4);
    assert_eq!(buffer, vec![18, 0, 0]);
    unset_array_bit(&mut buffer[..], 1);
    assert_eq!(buffer, vec![16, 0, 0]);
    set_array_bit(&mut buffer[..], 10);
    assert_eq!(buffer, vec![16, 4, 0]);
    set_array_bit(&mut buffer[..], 10);
    assert_eq!(buffer, vec![16, 4, 0]);
    set_array_bit(&mut buffer[..], 11);
    assert_eq!(buffer, vec![16, 12, 0]);
    unset_array_bit(&mut buffer[..], 10);
    assert_eq!(buffer, vec![16, 8, 0]);
  }

}
<commit_msg>Add get_vlq_int() for BitReader<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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::mem::{size_of, transmute_copy};
use std::cmp;

/// Read `$size` of bytes from `$src`, and reinterpret them
/// as type `$ty`, in little-endian order. `$ty` must implement
/// the `Default` trait. Otherwise this won't compile.
/// This is copied and modified from byteorder crate.
macro_rules! read_num_bytes {
  ($ty:ty, $size:expr, $src:expr) => ({
    assert!($size <= $src.len());
    let mut data: $ty = Default::default();
    unsafe {
      ::std::ptr::copy_nonoverlapping(
        $src.as_ptr(),
        &mut data as *mut $ty as *mut u8,
        $size);
    }
    data
  });
}

/// Return the ceil of value/divisor
#[inline]
pub fn ceil(value: i64, divisor: i64) -> i64 {
  let mut result = value / divisor;
  if value % divisor != 0 { result += 1 };
  result
}

/// Returns the `num_bits` least-significant bits of `v`
#[inline]
pub fn trailing_bits(v: u64, num_bits: usize) -> u64 {
  if num_bits == 0 {
    return 0;
  }
  if num_bits >= 64 {
    return v;
  }
  let n = 64 - num_bits;
  (v << n) >> n
}

#[inline]
pub fn set_array_bit(bits: &mut [u8], i: usize) {
  bits[i / 8] |= 1 << (i % 8);
}

#[inline]
pub fn unset_array_bit(bits: &mut [u8], i: usize) {
  bits[i / 8] &= !(1 << (i % 8));
}

/// Maximum byte length for a VLQ encoded integer
const MAX_VLQ_BYTE_LEN: usize = 5;

pub struct BitReader<'a> {
  /// The byte buffer to read from, passed in by client
  buffer: &'a [u8],

  /// Bytes are memcpy'd from `buffer` and values are read from this variable.
  /// This is faster than reading values byte by byte directly from `buffer`
  buffered_values: u64,

  /// Current byte offset in `buffer`
  byte_offset: usize,

  /// Current bit offset in `buffered_values`
  bit_offset: usize,

  /// Total number of bytes in `buffer`
  total_bytes: usize
}

impl<'a> BitReader<'a> {
  pub fn new(buffer: &'a [u8]) -> Self {
    let total_bytes = buffer.len();
    let num_bytes = cmp::min(8, total_bytes);
    let buffered_values = read_num_bytes!(u64, num_bytes, buffer);
    BitReader {
      buffer: buffer, buffered_values: buffered_values,
      byte_offset: 0, bit_offset: 0, total_bytes: total_bytes
    }
  }

  #[inline]
  pub fn reset(&mut self, buffer: &'a [u8]) {
    self.buffer = buffer;
    self.byte_offset = 0;
    self.bit_offset = 0;
  }

  #[inline]
  pub fn get_value<T: Default>(&mut self, num_bits: usize) -> Option<T> {
    assert!(num_bits <= 32);
    assert!(num_bits <= size_of::<T>() * 8);

    if self.byte_offset * 8 + self.bit_offset + num_bits > self.total_bytes * 8 {
      return None;
    }

    let mut v = trailing_bits(self.buffered_values, self.bit_offset + num_bits) >> self.bit_offset;
    self.bit_offset += num_bits;

    if self.bit_offset >= 64 {
      self.byte_offset += 8;
      self.bit_offset -= 64;

      let bytes_to_read = cmp::min(self.total_bytes - self.byte_offset, 8);
      self.buffered_values = read_num_bytes!(
        u64, bytes_to_read, self.buffer[self.byte_offset..]);

      v |= trailing_bits(self.buffered_values, self.bit_offset) << (num_bits - self.bit_offset);
    }

    // TODO: better to avoid copying here
    let result: T = unsafe {
      transmute_copy::<u64, T>(&v)
    };
    Some(result)
  }

  /// Read a `num_bytes`-sized value from this buffer and return it.
  /// `T` needs to be a little-endian native type. The value is assumed to
  /// be byte aligned so the bit reader will be advanced to the start of
  /// the next byte before reading the value. Return `None` if there's not
  /// enough bytes left.
  #[inline]
  pub fn get_aligned<T: Default>(&mut self, num_bytes: usize) -> Option<T> {
    let bytes_read = ceil(self.bit_offset as i64, 8) as usize;
    if self.byte_offset + bytes_read + num_bytes > self.total_bytes {
      // Not enough bytes left
      return None
    }

    // Advance byte_offset to next unread byte and read num_bytes
    self.byte_offset += bytes_read;
    let v = read_num_bytes!(T, num_bytes, self.buffer[self.byte_offset..]);
    self.byte_offset += num_bytes;

    // Reset buffered_values
    self.bit_offset = 0;
    let bytes_remaining = cmp::min(self.total_bytes - self.byte_offset, 8);
    self.buffered_values = read_num_bytes!(
      u64, bytes_remaining, self.buffer[self.byte_offset..]);
    Some(v)
  }

  /// Read a VLQ encoded (in little endian order) int from the stream.
  /// The encoded int must start at the beginning of a byte.
  /// Returns `None` if the number of bytes exceed `MAX_VLQ_BYTE_LEN`, or
  /// there's not enough bytes in the stream.
  #[inline]
  pub fn get_vlq_int(&mut self) -> Option<i64> {
    let mut num_bytes = 0;
    let mut shift = 0;
    let mut v: i64 = 0;
    while let Some(byte) = self.get_aligned::<u8>(1) {
      num_bytes += 1;
      if num_bytes >= MAX_VLQ_BYTE_LEN {
        return None
      }
      v |= ((byte & 0x7F) as i64) << shift;
      shift += 7;
      if byte & 0x80 == 0 {
        return Some(v);
      }
    }
    return None;
  }
}

#[cfg(test)]
mod tests {
  use super::*;

  #[test]
  fn test_ceil() {
    assert_eq!(ceil(0, 1), 0);
    assert_eq!(ceil(1, 1), 1);
    assert_eq!(ceil(1, 2), 1);
    assert_eq!(ceil(1, 8), 1);
    assert_eq!(ceil(7, 8), 1);
    assert_eq!(ceil(8, 8), 1);
    assert_eq!(ceil(9, 8), 2);
    assert_eq!(ceil(9, 9), 1);
    assert_eq!(ceil(10000000000, 10), 1000000000);
    assert_eq!(ceil(10, 10000000000), 1);
    assert_eq!(ceil(10000000000, 1000000000), 10);
  }

  #[test]
  fn test_bit_reader_get_value() {
    let buffer = vec![255, 0];
    let mut bit_reader = BitReader::new(&buffer);
    let v1 = bit_reader.get_value::<i32>(1);
    assert!(v1.is_some());
    assert_eq!(v1.unwrap(), 1);
    let v2 = bit_reader.get_value::<i32>(2);
    assert!(v2.is_some());
    assert_eq!(v2.unwrap(), 3);
    let v3 = bit_reader.get_value::<i32>(3);
    assert!(v3.is_some());
    assert_eq!(v3.unwrap(), 7);
    let v4 = bit_reader.get_value::<i32>(4);
    assert!(v4.is_some());
    assert_eq!(v4.unwrap(), 3);
  }

  #[test]
  fn test_bit_reader_get_value_boundary() {
    let buffer = vec![10, 0, 0, 0, 20, 0, 30, 0, 0, 0, 40, 0];
    let mut bit_reader = BitReader::new(&buffer);
    let v1 = bit_reader.get_value::<i64>(32);
    assert!(v1.is_some());
    assert_eq!(v1.unwrap(), 10);
    let v2 = bit_reader.get_value::<i16>(16);
    assert!(v2.is_some());
    assert_eq!(v2.unwrap(), 20);
    let v3 = bit_reader.get_value::<i32>(32);
    assert!(v3.is_some());
    assert_eq!(v3.unwrap(), 30);
    let v4 = bit_reader.get_value::<i32>(16);
    assert!(v4.is_some());
    assert_eq!(v4.unwrap(), 40);
  }

  #[test]
  fn test_bit_reader_get_aligned() {
    // 01110101 11001011
    let buffer: Vec<u8> = vec!(0x75, 0xCB);
    let mut bit_reader = BitReader::new(&buffer);
    let v1 = bit_reader.get_value::<i32>(3);
    assert!(v1.is_some());
    assert_eq!(v1.unwrap(), 5);
    let v2 = bit_reader.get_aligned::<i32>(1);
    assert!(v2.is_some());
    assert_eq!(v2.unwrap(), 203);
    let v3 = bit_reader.get_value::<i32>(1);
    assert!(v3.is_none());

    bit_reader.reset(&buffer);
    let v4 = bit_reader.get_aligned::<i32>(3);
    assert!(v4.is_none());
  }

  #[test]
  fn test_bit_reader_get_vlq_int() {
    // 10001001 00000001 11110010 10110101 00000110
    let buffer: Vec<u8> = vec!(0x89, 0x01, 0xF2, 0xB5, 0x06);
    let mut bit_reader = BitReader::new(&buffer);
    let v1 = bit_reader.get_vlq_int();
    assert!(v1.is_some());
    assert_eq!(v1.unwrap(), 137);
    println!("reading v2");
    let v2 = bit_reader.get_vlq_int();
    assert!(v2.is_some());
    assert_eq!(v2.unwrap(), 105202);
  }

  #[test]
  fn test_set_array_bit() {
    let mut buffer = vec![0, 0, 0];
    set_array_bit(&mut buffer[..], 1);
    assert_eq!(buffer, vec![2, 0, 0]);
    set_array_bit(&mut buffer[..], 4);
    assert_eq!(buffer, vec![18, 0, 0]);
    unset_array_bit(&mut buffer[..], 1);
    assert_eq!(buffer, vec![16, 0, 0]);
    set_array_bit(&mut buffer[..], 10);
    assert_eq!(buffer, vec![16, 4, 0]);
    set_array_bit(&mut buffer[..], 10);
    assert_eq!(buffer, vec![16, 4, 0]);
    set_array_bit(&mut buffer[..], 11);
    assert_eq!(buffer, vec![16, 12, 0]);
    unset_array_bit(&mut buffer[..], 10);
    assert_eq!(buffer, vec![16, 8, 0]);
  }

}
<|endoftext|>


<commit_before>// thread2.rs
use std::thread;

fn main() {
    let name = "dolly".to_string();
    let t = thread::spawn(|| {
        println!("hello {}",name);
    });
    println!("wait {:?}", t.join());
}
<commit_msg>issue #43: make example code consistent with text<commit_after>// thread2.rs
use std::thread;

fn main() {
    let t = thread::spawn(|| {
        println!("hello");
    });
    println!("wait {:?}", t.join());
}

<|endoftext|>