<commit_before>//! RMD files are sort of data pointers for the Objects and
//! Tiles and include things like which file they are in and
//! if they are a part of an animation or so.
//!
//! [HEADER]
//! String
//! 12 empty bytes
//! String
//! int animation parts (this is for object animations)
//! int animation rows
//! String
//! int rmd rows
//!
//! [RMD Row]
//! int ImageCount (How many images this row contains,
//!                 like an image from sadad for example can
//!                 contain: Body, color hair, color body, weapon)
//!
//! [RMD Row - Images]
//! int SourceX
//! int SourceY
//! int SourceWidth
//! int SourceHeight
//! int empty
//! int renderz
//! int DestX
//! int DestY
//! int Draw Type (Shadow, skill, normal)
//! int ImageIDCount
//!
//! [RMD Row - Images - Image ID]
//! int ImageID (Lst row pointer,
//!              this is a array so different weapons can be used)
//!
//! int AnimationsCount
//!
//! [RMD Animation]
//! int AnimationFrames
//!
//! [RMD Animation - Frame]
//! int RMDRowPointer (points to a row of the RMD)

use std::str::from_utf8;
use std::io::Cursor;
use std::io::Seek;
use std::io::SeekFrom;

use byteorder::ReadBytesExt;
use byteorder::LittleEndian as LE;

use error::Error;

#[derive(Debug)]
pub struct RmdImage {
    source_x: i32,
    source_y: i32,
    source_width: i32,
    source_height: i32,
    empty: u32,
    render_z: i32,
    dest_x: i32,
    dest_y: i32,
    draw_type: i32, // enum { Shadow, skill, normal }
    image_id_count: i32,
    image_id: Vec<i32> // Lst row pointer
}

impl RmdImage {
    fn new() -> RmdImage {
        RmdImage {
            source_x: 0,
            source_y: 0,
            source_width: 0,
            source_height: 0,
            empty: 0,
            render_z: 0,
            dest_x: 0,
            dest_y: 0,
            draw_type: 0,
            image_id_count: 0,
            image_id: Vec::new(),
        }
    }
}

#[derive(Debug)]
pub struct RmdAnimation {
    frame_count: i32,
    frames: Vec<i32> // Rmd row pointer
}

#[derive(Debug)]
pub struct RmdRow {
    image_count: i32,
    images: Vec<RmdImage>,
    animation_count: i32,
    animations: Vec<RmdAnimation>,
}

impl RmdRow {
    fn new() -> RmdRow {
        RmdRow {
            image_count: 0,
            images: Vec::new(),
            animation_count: 0,
            animations: Vec::new(),
        }
    }
}

#[derive(Debug)]
pub struct Rmd {
    string: String,
    animation_parts: i32, // for object animaitons
    animation_rows: i32,
    row_count: i32,
    rows: Vec<RmdRow>,
    animation_count: i32,
    animations: Vec<RmdAnimation>,
}

impl Rmd {
    pub fn new() -> Rmd {
        Rmd {
            string: String::new(),
            animation_parts: 0,
            animation_rows: 0,
            row_count: 0,
            rows: Vec::new(),
            animation_count: 0,
            animations: Vec::new(),
        }
    }

    pub fn load(data: &[u8]) -> Result<Rmd, Error> {

        // This is just because tests always have a tab on the first line :-/
        println!("");

        let mut cursor = Cursor::new(data);
        let mut rmd = Rmd::new();

        // filetype string: Equal to ""
        let string_1 = parse_string(&mut cursor)?;
        println!("{:?}", string_1);

        let file_number = cursor.read_u32::<LE>()?; // 4
        println!("file_number: {}", file_number);

        // 8 empty bytes
        let padding = cursor.read_u32::<LE>()?; // 8
        if padding != 0 { println!("p2: {}", padding); }
        let padding = cursor.read_u32::<LE>()?; // 12
        if padding != 0 { println!("p3: {}", padding); }

        // let string = parse_string(&mut cursor)?;
        let string = parse_u8_vec(&mut cursor)?;
        println!("str 1: `{:?}`", string);

        rmd.animation_parts = cursor.read_i32::<LE>()?;
        rmd.animation_rows = cursor.read_i32::<LE>()?;

        let string = parse_string(&mut cursor)?;
        println!("str 2: `{}`", string);

        rmd.row_count = cursor.read_i32::<LE>()?;

        println!("read header: {:?}", rmd);

        // read the Rmd rows
        // for _ in 0..rmd.row_count {
        for _ in 0..2 {
            let mut row = RmdRow::new();
            row.image_count = cursor.read_i32::<LE>()?;

            for _ in 0..row.image_count {
                let mut img = RmdImage::new();
                img.source_x = cursor.read_i32::<LE>()?;
                img.source_y = cursor.read_i32::<LE>()?;
                img.source_width = cursor.read_i32::<LE>()?;
                img.source_height = cursor.read_i32::<LE>()?;
                img.empty = cursor.read_u32::<LE>()?;
                img.render_z = cursor.read_i32::<LE>()?;
                img.dest_x = cursor.read_i32::<LE>()?;
                img.dest_y = cursor.read_i32::<LE>()?;
                img.draw_type = cursor.read_i32::<LE>()?;
                img.image_id_count = cursor.read_i32::<LE>()?;
                for _ in 0..img.image_id_count {
                    let id = cursor.read_i32::<LE>()?;
                    img.image_id.push(id);
                }
                println!("{:?}", &img);

            }

            rmd.rows.push(row);
        }

        rmd.animation_count = cursor.read_i32::<LE>()?;
        for _ in 0..rmd.animation_count {
            let mut ani = RmdAnimation {
                frame_count: cursor.read_i32::<LE>()?,
                frames: Vec::new(),
            };
            for _ in 0..ani.frame_count {
                let ptr = cursor.read_i32::<LE>()?;
                ani.frames.push(ptr);
            }
            rmd.animations.push(ani);
        }

        // println!("{:?}", rmd);
        Ok(rmd)
    }
}

fn parse_string(cursor: &mut Cursor<&[u8]>) -> Result<String, Error> {
    let string_length = cursor.read_u8()?;
    let mut str_vec = Vec::<u8>::new();
    for _ in 0..string_length {
        let chr = cursor.read_u8()?;
        str_vec.push(chr);
    }
    let string = String::from_utf8(str_vec)?;
    Ok(string)
}

fn parse_u8_vec(cursor: &mut Cursor<&[u8]>) -> Result<Vec<u8>, Error> {
    let string_length = cursor.read_u8()?;
    let mut vec = Vec::<u8>::new();
    for _ in 0..string_length {
        let chr = cursor.read_u8()?;
        vec.push(chr);
    }
    Ok(vec)
}

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

    #[test]
    fn test_tle_00001() {
        let data = include_bytes!("../../data/DATAs/Tle/tle00001.rmd");
        let rmd = Rmd::load(data).unwrap();
        assert!(false);
    }

    #[test]
    fn test_obj_00001() {
        let data = include_bytes!("../../data/DATAs/Obj/obj00001.rmd");
        let rmd = Rmd::load(data).unwrap();
        assert!(false);
    }

    #[test]
    fn test_chr_00001() {
        let data = include_bytes!("../../data/DATAs/Chr/chr00001.rmd");
        let rmd = Rmd::load(data).unwrap();
        assert!(false);
    }
}<commit_msg>update rmd<commit_after>//! RMD files are sort of data pointers for the Objects and
//! Tiles and include things like which file they are in and
//! if they are a part of an animation or so.
//!
//! [HEADER]
//! String
//! 12 empty bytes
//! String
//! int animation parts (this is for object animations)
//! int animation rows
//! String
//! int rmd rows
//!
//! [RMD Row]
//! int ImageCount (How many images this row contains,
//!                 like an image from sadad for example can
//!                 contain: Body, color hair, color body, weapon)
//!
//! [RMD Row - Images]
//! int SourceX
//! int SourceY
//! int SourceWidth
//! int SourceHeight
//! int empty
//! int renderz
//! int DestX
//! int DestY
//! int Draw Type (Shadow, skill, normal)
//! int ImageIDCount
//!
//! [RMD Row - Images - Image ID]
//! int ImageID (Lst row pointer,
//!              this is a array so different weapons can be used)
//!
//! int AnimationsCount
//!
//! [RMD Animation]
//! int AnimationFrames
//!
//! [RMD Animation - Frame]
//! int RMDRowPointer (points to a row of the RMD)

use std::str::from_utf8;
use std::io::Cursor;
use std::io::Seek;
use std::io::SeekFrom;

use byteorder::ReadBytesExt;
use byteorder::LittleEndian as LE;

use error::Error;

#[derive(Debug)]
pub struct RmdImage {
    source_x: i32,
    source_y: i32,
    source_width: i32,
    source_height: i32,
    empty_1: u32,
    empty_2: u32,
    render_z: i32,
    dest_x: i32,
    dest_y: i32,
    draw_type: i32, // enum { Shadow, skill, normal }
    image_id_count: i32,
    image_id: Vec<i32> // Lst row pointer
}

impl RmdImage {
    fn new() -> RmdImage {
        RmdImage {
            source_x: 0,
            source_y: 0,
            source_width: 0,
            source_height: 0,
            empty_1: 0,
            empty_2: 0,
            render_z: 0,
            dest_x: 0,
            dest_y: 0,
            draw_type: 0,
            image_id_count: 0,
            image_id: Vec::new(),
        }
    }
}

#[derive(Debug)]
pub struct RmdAnimation {
    frame_count: i32,
    frames: Vec<i32> // Rmd row pointer
}

#[derive(Debug)]
pub struct RmdRow {
    image_count: i32,
    images: Vec<RmdImage>,
    animation_count: i32,
    animations: Vec<RmdAnimation>,
}

impl RmdRow {
    fn new() -> RmdRow {
        RmdRow {
            image_count: 0,
            images: Vec::new(),
            animation_count: 0,
            animations: Vec::new(),
        }
    }
}

#[derive(Debug)]
pub struct Rmd {
    string: String,
    animation_parts: i32, // for object animaitons
    animation_rows: i32,
    row_count: i32,
    rows: Vec<RmdRow>,
    animation_count: i32,
    animations: Vec<RmdAnimation>,
}

impl Rmd {
    pub fn new() -> Rmd {
        Rmd {
            string: String::new(),
            animation_parts: 0,
            animation_rows: 0,
            row_count: 0,
            rows: Vec::new(),
            animation_count: 0,
            animations: Vec::new(),
        }
    }

    pub fn load(data: &[u8]) -> Result<Rmd, Error> {

        // This is just because tests always have a tab on the first line :-/
        println!("");

        let mut cursor = Cursor::new(data);
        let mut rmd = Rmd::new();

        // filetype string: Equal to ""
        let string_1 = parse_string(&mut cursor)?;
        println!("{:?}", string_1);

        let file_number = cursor.read_u32::<LE>()?; // 4
        println!("file_number: {}", file_number);

        // 8 empty bytes
        let padding = cursor.read_u32::<LE>()?; // 8
        if padding != 0 { println!("p2: {}", padding); }
        let padding = cursor.read_u32::<LE>()?; // 12
        if padding != 0 { println!("p3: {}", padding); }

        // let string = parse_string(&mut cursor)?;
        let string = parse_u8_vec(&mut cursor)?;
        println!("str 1: `{:?}`", string);

        rmd.animation_parts = cursor.read_i32::<LE>()?;
        rmd.animation_rows = cursor.read_i32::<LE>()?;

        let string = parse_string(&mut cursor)?;
        println!("str 2: `{}`", string);

        rmd.row_count = cursor.read_i32::<LE>()?;

        println!("read header: {:?}", rmd);

        // read the Rmd rows
        for _ in 0..rmd.row_count {
        // for _ in 0..2 {
            let mut row = RmdRow::new();
            row.image_count = cursor.read_i32::<LE>()?;

            for _ in 0..row.image_count {
                let mut img = RmdImage::new();
                img.source_x = cursor.read_i32::<LE>()?;
                img.source_y = cursor.read_i32::<LE>()?;
                img.source_width = cursor.read_i32::<LE>()?;
                img.source_height = cursor.read_i32::<LE>()?;
                img.empty_1 = cursor.read_u32::<LE>()?;
                img.dest_x = cursor.read_i32::<LE>()?;
                img.dest_y = cursor.read_i32::<LE>()?;
                img.empty_2 = cursor.read_u32::<LE>()?;
                img.render_z = cursor.read_i32::<LE>()?;
                img.draw_type = cursor.read_i32::<LE>()?;
                img.image_id_count = cursor.read_i32::<LE>()?;
                for _ in 0..img.image_id_count {
                    let id = cursor.read_i32::<LE>()?;
                    img.image_id.push(id);
                }
                println!("{:?}", &img);

            }

            rmd.rows.push(row);
        }

        rmd.animation_count = cursor.read_i32::<LE>()?;
        for _ in 0..rmd.animation_count {
            let mut ani = RmdAnimation {
                frame_count: cursor.read_i32::<LE>()?,
                frames: Vec::new(),
            };
            for _ in 0..ani.frame_count {
                let ptr = cursor.read_i32::<LE>()?;
                ani.frames.push(ptr);
            }
            rmd.animations.push(ani);
        }

        // println!("{:?}", rmd);
        Ok(rmd)
    }
}

fn parse_string(cursor: &mut Cursor<&[u8]>) -> Result<String, Error> {
    let string_length = cursor.read_u8()?;
    let mut str_vec = Vec::<u8>::new();
    for _ in 0..string_length {
        let chr = cursor.read_u8()?;
        str_vec.push(chr);
    }
    let string = String::from_utf8(str_vec)?;
    Ok(string)
}

fn parse_u8_vec(cursor: &mut Cursor<&[u8]>) -> Result<Vec<u8>, Error> {
    let string_length = cursor.read_u8()?;
    let mut vec = Vec::<u8>::new();
    for _ in 0..string_length {
        let chr = cursor.read_u8()?;
        vec.push(chr);
    }
    Ok(vec)
}

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

    #[test]
    fn test_tle_00001() {
        let data = include_bytes!("../../data/DATAs/Tle/tle00001.rmd");
        let rmd = Rmd::load(data).unwrap();
        assert!(false);
    }

    #[test]
    fn test_obj_00001() {
        let data = include_bytes!("../../data/DATAs/Obj/obj00001.rmd");
        let rmd = Rmd::load(data).unwrap();
        assert!(false);
    }

    #[test]
    fn test_chr_00001() {
        let data = include_bytes!("../../data/DATAs/Chr/chr00001.rmd");
        let rmd = Rmd::load(data).unwrap();
        assert!(false);
    }
}<|endoftext|>


<commit_before>use std::env;
use std::error::Error;
use std::fs::{DirEntry, File};
use std::io::Write;
use std::path::Path;
use std::process::Command;

use turingarena_core::contest::graphql_schema::generate_schema;

trait CheckedCommand {
    fn check(&mut self) -> Result<(), Box<dyn Error>>;
}

impl CheckedCommand for Command {
    fn check(&mut self) -> Result<(), Box<dyn Error>> {
        if !self.status().unwrap().success() {
            return Err(format!("command {:?} failed", self).into());
        }
        Ok(())
    }
}

fn traverse_dir<P: AsRef<Path>, F: Fn(&DirEntry) -> () + Copy>(p: P, f: F) {
    for x in std::fs::read_dir(p).unwrap() {
        let x = x.unwrap();
        f(&x);
        if x.file_type().unwrap().is_dir() {
            traverse_dir(x.path(), f)
        }
    }
}

fn main() -> Result<(), Box<dyn Error>> {
    // Unless otherwise specified, do not re-run this script
    println!("cargo:rerun-if-changed=build.rs");

    let out_dir = env::var("OUT_DIR")?;
    let out_path = Path::new(&out_dir);

    let src_dir = env::var("CARGO_MANIFEST_DIR")?;
    let src_path = Path::new(&src_dir);

    let out_web_path = out_path.join("web");

    let build_web_env = "TURINGARENA_BUILD_WEB_CLIENT";
    println!("cargo:rerun-if-env-changed={}", build_web_env);

    if env::var_os(build_web_env).is_some() {
        traverse_dir(src_path.join("web").join("projects"), |x| {
            println!("cargo:rerun-if-changed={}", x.path().to_str().unwrap());
        });

        {
            let mut options = fs_extra::dir::CopyOptions::new();
            options.overwrite = true;
            fs_extra::dir::copy(src_path.join("web"), out_path, &options)?;
        }

        Command::new("npm")
            .current_dir(&out_web_path)
            .args(&["ci", "--ignore-scripts"])
            .check()?;

        std::fs::create_dir_all(&out_web_path.join("__generated__"))?;

        let schema_path = out_web_path
            .join("__generated__")
            .join("graphql-schema.json");
        let mut schema_file = File::create(&schema_path)?;
        write!(schema_file, "{}", generate_schema())?;

        Command::new("npm")
            .current_dir(&out_web_path)
            .args(&["run", "prepare"])
            .check()?;

        Command::new("npm")
            .current_dir(&out_web_path)
            .args(&["run", "build"])
            .check()?;
    } else {
        let dist_path = out_web_path.join("dist").join("turingarena-contest");
        let index_path = dist_path.join("index.html");
        std::fs::create_dir_all(dist_path)?;
        if !index_path.exists() {
            std::fs::copy(src_path.join("dummy-index.html"), index_path)?;
        }
    }

    Ok(())
}
<commit_msg>Fix `permission denied` error in web build<commit_after>use std::env;
use std::error::Error;
use std::fs::{DirEntry, File};
use std::io::Write;
use std::path::Path;
use std::process::Command;

use turingarena_core::contest::graphql_schema::generate_schema;

trait CheckedCommand {
    fn check(&mut self) -> Result<(), Box<dyn Error>>;
}

impl CheckedCommand for Command {
    fn check(&mut self) -> Result<(), Box<dyn Error>> {
        if !self.status().unwrap().success() {
            return Err(format!("command {:?} failed", self).into());
        }
        Ok(())
    }
}

fn traverse_dir<P: AsRef<Path>, F: Fn(&DirEntry) -> () + Copy>(p: P, f: F) {
    for x in std::fs::read_dir(p).unwrap() {
        let x = x.unwrap();
        f(&x);
        if x.file_type().unwrap().is_dir() {
            traverse_dir(x.path(), f)
        }
    }
}

fn main() -> Result<(), Box<dyn Error>> {
    // Unless otherwise specified, do not re-run this script
    println!("cargo:rerun-if-changed=build.rs");

    let out_dir = env::var("OUT_DIR")?;
    let out_path = Path::new(&out_dir);

    let src_dir = env::var("CARGO_MANIFEST_DIR")?;
    let src_path = Path::new(&src_dir);

    let out_web_path = out_path.join("web");

    let build_web_env = "TURINGARENA_BUILD_WEB_CLIENT";
    println!("cargo:rerun-if-env-changed={}", build_web_env);

    if env::var_os(build_web_env).is_some() {
        traverse_dir(src_path.join("web").join("projects"), |x| {
            println!("cargo:rerun-if-changed={}", x.path().to_str().unwrap());
        });

        {
            std::fs::remove_dir_all(&out_web_path)?;
            let mut options = fs_extra::dir::CopyOptions::new();
            options.overwrite = true;
            fs_extra::dir::copy(src_path.join("web"), out_path, &options)?;
        }

        Command::new("npm")
            .current_dir(&out_web_path)
            .args(&["ci", "--ignore-scripts"])
            .check()?;

        std::fs::create_dir_all(&out_web_path.join("__generated__"))?;

        let schema_path = out_web_path
            .join("__generated__")
            .join("graphql-schema.json");
        let mut schema_file = File::create(&schema_path)?;
        write!(schema_file, "{}", generate_schema())?;

        Command::new("npm")
            .current_dir(&out_web_path)
            .args(&["run", "prepare"])
            .check()?;

        Command::new("npm")
            .current_dir(&out_web_path)
            .args(&["run", "build"])
            .check()?;
    } else {
        let dist_path = out_web_path.join("dist").join("turingarena-contest");
        let index_path = dist_path.join("index.html");
        std::fs::create_dir_all(dist_path)?;
        if !index_path.exists() {
            std::fs::copy(src_path.join("dummy-index.html"), index_path)?;
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before>
fn generate_table () {

    let pi: f64 = 3.1415926536897932384626;
    let k1: f64 = 0.6072529350088812561694; // 1/k
    let num_bits: uint = 32;
    //let num_elms: uint = num_bits;
    let mul: uint = 1<<(num_bits-2);

    println!("Cordic sin in rust");
    println!("num bits {}", num_bits);
    println!("mul {}", mul);
    println!("1<<(num_bits-2) {}", ((1i << (num_bits-2)) as f64));
    println!("pi is {}", pi);
    println!("k1 is {}", k1);

    println!("let cordic_tab = [");

    let shift: f64 = 2.0;
    for ii in range(0, num_bits) {
        let ipow: f64 = 1f64/shift.powi(ii as i32);
        let cur: f64 = ipow.atan() * (mul as f64);

        if ii % 4 == 0 && ii > 0 {
            println!("");
        }
        if ii == 0 {
            print!("0x{}, ", std::f64::to_str_hex(cur.floor()));
        } else {
            print!("0x{}, ", std::f64::to_str_hex(cur.floor()));
        }
    }

    println!("];");
}

fn int_to_f64 (lhs: int) -> f64 {
    let rhs: f64 = unsafe {
        std::mem::transmute(lhs)
    };
    return rhs;
}

fn f64_to_int (lhs: f64) -> int {
    let rhs: int = unsafe {
        std::mem::transmute(lhs)
    };
    return rhs;
}

fn sin(theta: f64) {

    let num_bits: uint = 32;

    //let k1: int = f64_to_int(0.6072529350088812561694); // 1/k
    //let mul: int = 1<<(num_bits-2);
    let mut x: int = 0x26DD3B6A; // todo derive this k1 and mul
    let mut y: int = 0;
    let mut z: int = theta.floor() as int;
    let mut tx: int;
    let mut ty: int ;
    let mut tz: int;

    let mut d: int;
    let cordic_tab = [
        0x3243f6a8, 0x1dac6705, 0xfadbafc, 0x7f56ea6,
        0x3feab76, 0x1ffd55b, 0xfffaaa, 0x7fff55,
        0x3fffea, 0x1ffffd, 0xfffff, 0x7ffff,
        0x3ffff, 0x1ffff, 0xffff, 0x7fff,
        0x3fff, 0x1fff, 0xfff, 0x7ff,
        0x3ff, 0x1ff, 0xff, 0x7f,
        0x3f, 0x1f, 0xf, 0x8,
        0x4, 0x2, 0x1, 0x0, ];

    for k in range(0, num_bits) {
        if z >= 0 {
            d = 0;
        } else {
            d = -1;
        }

        println!("z {}", z);

        tx = x - (((y>>k) ^ d) - d);
        ty = y + (((x>>k) ^ d) - d);
        tz = z - ((cordic_tab[k] ^ d) - d);
        println!("{} {} {} {} {} {}", k, x, y, tx, ty, tz);
        x = tx; y = ty; z = tz;
    }
}

fn main() {
    let i: int = 42882;
    let f: f64 = 3498043.4824;
    assert!(int_to_f64(f64_to_int(f)) == f);
    assert!(f64_to_int(int_to_f64(i)) == i);

    generate_table();

    let theta: f64 = 33732594.261305;
    sin(theta);
}
<commit_msg>derive cordic_k1 and initial value of x<commit_after>
fn generate_table () {

    let pi: f64 = 3.1415926536897932384626;
    let k1: f64 = 0.6072529350088812561694; // 1/k
    let num_bits: uint = 32;
    //let num_elms: uint = num_bits;
    let mul: uint = 1<<(num_bits-2);

    println!("Cordic sin in rust");
    println!("num bits {}", num_bits);
    println!("mul {}", mul);
    println!("1<<(num_bits-2) {}", ((1i << (num_bits-2)) as f64));
    println!("pi is {}", pi);
    println!("k1 is {}", k1);

    println!("let cordic_tab = [");

    let shift: f64 = 2.0;
    for ii in range(0, num_bits) {
        let ipow: f64 = 1f64/shift.powi(ii as i32);
        let cur: f64 = ipow.atan() * (mul as f64);

        if ii % 4 == 0 && ii > 0 {
            println!("");
        }
        if ii == 0 {
            print!("0x{}, ", std::f64::to_str_hex(cur.floor()));
        } else {
            print!("0x{}, ", std::f64::to_str_hex(cur.floor()));
        }
    }

    println!("];");
}

fn int_to_f64 (lhs: int) -> f64 {
    let rhs: f64 = unsafe {
        std::mem::transmute(lhs)
    };
    return rhs;
}

fn f64_to_int (lhs: f64) -> int {
    let rhs: int = unsafe {
        std::mem::transmute(lhs)
    };
    return rhs;
}

fn sin(theta: f64) {

    let num_bits: uint = 32;

    let k1: f64 = 0.6072529350088812561694; // 1/k
    let mul: int = 1<<(num_bits-2);
    let cordic_k1: f64 = k1 * (mul as f64);
    //println!("k1 - {}, mul - {}, cordic_k1 - {:X}", k1, mul, cordic_k1);

    let mut x: int = cordic_k1.floor() as int; //0x26DD3B6A;
    let mut y: int = 0;
    let mut z: int = theta.floor() as int;
    let mut tx: int;
    let mut ty: int ;
    let mut tz: int;

    let mut d: int;
    let cordic_tab = [
        0x3243f6a8, 0x1dac6705, 0xfadbafc, 0x7f56ea6,
        0x3feab76, 0x1ffd55b, 0xfffaaa, 0x7fff55,
        0x3fffea, 0x1ffffd, 0xfffff, 0x7ffff,
        0x3ffff, 0x1ffff, 0xffff, 0x7fff,
        0x3fff, 0x1fff, 0xfff, 0x7ff,
        0x3ff, 0x1ff, 0xff, 0x7f,
        0x3f, 0x1f, 0xf, 0x8,
        0x4, 0x2, 0x1, 0x0, ];

    for k in range(0, num_bits) {
        if z >= 0 {
            d = 0;
        } else {
            d = -1;
        }

        println!("z {}", z);

        tx = x - (((y>>k) ^ d) - d);
        ty = y + (((x>>k) ^ d) - d);
        tz = z - ((cordic_tab[k] ^ d) - d);
        println!("{} {} {} {} {} {}", k, x, y, tx, ty, tz);
        x = tx; y = ty; z = tz;
    }
}

fn main() {
    let i: int = 42882;
    let f: f64 = 3498043.4824;
    assert!(int_to_f64(f64_to_int(f)) == f);
    assert!(f64_to_int(int_to_f64(i)) == i);

    generate_table();

    let theta: f64 = 33732594.261305;
    sin(theta);
}
<|endoftext|>


<commit_before>/**
use the taylor series to caculate tan^-1 (x) where |x| <= 1, x >= 0
**/
fn taylor_atan (x: f64) -> f64 {
    let mut a: f64 = 0.0;
    let mut s: f64 = 1.0;
    let mut xpow: f64;

    // by definition
    if x == 0.0 {
        return 0.0;
    }

    // this is well known, and the taylor series we are using explictly assumes |x| < 1
    if x == 1.0 {
        return std::f64::consts::PI/4.0;
    }

    for ii in range(1i, 60) {
        if ii % 2 == 0 {
            continue;
        }
        xpow = 1.0;
        for jj in range(0i, ii) {
            xpow *= x;
        }
        a += s * xpow / (ii as f64);
        s = -1.0*s;
    }

    return a;
}

fn generate_table () {

    let pi: f64 = 3.1415926536897932384626;
    let k1: f64 = 0.6072529350088812561694; // 1/k
    let num_bits: uint = 32;
    let mul: uint = 1<<(num_bits-2);

    println!("Cordic sin in rust");
    println!("num bits {}", num_bits);
    println!("mul {}", mul);
    println!("1<<(num_bits-2) {}", ((1i << (num_bits-2)) as f64));
    println!("pi is {}", pi);
    println!("k1 is {}", k1);

    println!("let cordic_tab = [");

    let shift: f64 = 2.0;
    for ii in range(0, num_bits) {
        let ipow: f64 = 1f64/shift.powi(ii as i32);
        let cur: f64 = taylor_atan(ipow) * (mul as f64);

        if ii % 4 == 0 && ii > 0 {
            println!("");
        }
        if ii == 0 {
            print!("0x{}, ", std::f64::to_str_hex(cur.floor()));
        } else {
            print!("0x{}, ", std::f64::to_str_hex(cur.floor()));
        }
    }

    println!("];");
}

fn sin(theta: f64) -> f64 {

    let num_bits: uint = 32;

    let k1: f64 = 0.6072529350088812561694; // 1/k
    let mul: f64 = (1i << (num_bits-2)) as f64;
    let cordic_k1: f64 = k1 * mul;
    let mut x: int = cordic_k1.floor() as int; //0x26DD3B6A;
    let mut y: int = 0;
    let mut z: int = (mul * theta).floor() as int;
    let mut tx: int;
    let mut ty: int;
    let mut tz: int;

    let mut d: int;

    let cordic_tab = [
        0x3243f6a8, 0x1dac6705, 0xfadbafc, 0x7f56ea6,
        0x3feab76, 0x1ffd55b, 0xfffaaa, 0x7fff55,
        0x3fffea, 0x1ffffd, 0xfffff, 0x7ffff,
        0x3ffff, 0x1ffff, 0xffff, 0x7fff,
        0x3fff, 0x1fff, 0xfff, 0x7ff,
        0x3ff, 0x1ff, 0xff, 0x7f,
        0x3f, 0x1f, 0xf, 0x8,
        0x4, 0x2, 0x1, 0x0, ];

    for k in range(0, num_bits) {
        if z >= 0 {
            d = 0;
        } else {
            d = -1;
        }

        tx = x - (((y>>k) ^ d) - d);
        ty = y + (((x>>k) ^ d) - d);
        tz = z - ((cordic_tab[k] ^ d) - d);
        x = tx; y = ty; z = tz;
    }

    let s: f64 = (y as f64)/(mul as f64);

    return s;

}

fn main() {
    generate_table();

    let frac_pi_2: f64 = std::f64::consts::FRAC_PI_2; //pi/2.0;

    for ii in range(0i, 50) {
        let cur: f64 = ii as f64;
        let theta: f64 = cur/50.0 * frac_pi_2;
        let s: f64 = sin(theta);
            println!("s {}", s);
    }
}
<commit_msg>use FRAC_PI_4<commit_after>/**
use the taylor series to caculate tan^-1 (x) where |x| <= 1, x >= 0
**/
fn taylor_atan (x: f64) -> f64 {
    let mut a: f64 = 0.0;
    let mut s: f64 = 1.0;
    let mut xpow: f64;

    // by definition
    if x == 0.0 {
        return 0.0;
    }

    // this is well known, and the taylor series we are using explictly assumes |x| < 1
    if x == 1.0 {
        return std::f64::consts::FRAC_PI_4;
    }

    for ii in range(1i, 60) {
        if ii % 2 == 0 {
            continue;
        }
        xpow = 1.0;
        for jj in range(0i, ii) {
            xpow *= x;
        }
        a += s * xpow / (ii as f64);
        s = -1.0*s;
    }

    return a;
}

fn generate_table () {

    let pi: f64 = 3.1415926536897932384626;
    let k1: f64 = 0.6072529350088812561694; // 1/k
    let num_bits: uint = 32;
    let mul: uint = 1<<(num_bits-2);

    println!("Cordic sin in rust");
    println!("num bits {}", num_bits);
    println!("mul {}", mul);
    println!("1<<(num_bits-2) {}", ((1i << (num_bits-2)) as f64));
    println!("pi is {}", pi);
    println!("k1 is {}", k1);

    println!("let cordic_tab = [");

    let shift: f64 = 2.0;
    for ii in range(0, num_bits) {
        let ipow: f64 = 1f64/shift.powi(ii as i32);
        let cur: f64 = taylor_atan(ipow) * (mul as f64);

        if ii % 4 == 0 && ii > 0 {
            println!("");
        }
        if ii == 0 {
            print!("0x{}, ", std::f64::to_str_hex(cur.floor()));
        } else {
            print!("0x{}, ", std::f64::to_str_hex(cur.floor()));
        }
    }

    println!("];");
}

fn sin(theta: f64) -> f64 {

    let num_bits: uint = 32;

    let k1: f64 = 0.6072529350088812561694; // 1/k
    let mul: f64 = (1i << (num_bits-2)) as f64;
    let cordic_k1: f64 = k1 * mul;
    let mut x: int = cordic_k1.floor() as int; //0x26DD3B6A;
    let mut y: int = 0;
    let mut z: int = (mul * theta).floor() as int;
    let mut tx: int;
    let mut ty: int;
    let mut tz: int;

    let mut d: int;

    let cordic_tab = [
        0x3243f6a8, 0x1dac6705, 0xfadbafc, 0x7f56ea6,
        0x3feab76, 0x1ffd55b, 0xfffaaa, 0x7fff55,
        0x3fffea, 0x1ffffd, 0xfffff, 0x7ffff,
        0x3ffff, 0x1ffff, 0xffff, 0x7fff,
        0x3fff, 0x1fff, 0xfff, 0x7ff,
        0x3ff, 0x1ff, 0xff, 0x7f,
        0x3f, 0x1f, 0xf, 0x8,
        0x4, 0x2, 0x1, 0x0, ];

    for k in range(0, num_bits) {
        if z >= 0 {
            d = 0;
        } else {
            d = -1;
        }

        tx = x - (((y>>k) ^ d) - d);
        ty = y + (((x>>k) ^ d) - d);
        tz = z - ((cordic_tab[k] ^ d) - d);
        x = tx; y = ty; z = tz;
    }

    let s: f64 = (y as f64)/(mul as f64);

    return s;

}

fn main() {
    generate_table();

    let frac_pi_2: f64 = std::f64::consts::FRAC_PI_2; //pi/2.0;

    for ii in range(0i, 50) {
        let cur: f64 = ii as f64;
        let theta: f64 = cur/50.0 * frac_pi_2;
        let s: f64 = sin(theta);
            println!("s {}", s);
    }
}
<|endoftext|>


<commit_before>//! Construct version in the `commit-hash date chanel` format

use std::{env, path::PathBuf, process::Command};

fn main() {
    set_rerun();
    set_commit_info();
    if option_env!("CFG_RELEASE").is_none() {
        println!("cargo:rustc-env=POKE_RA_DEVS=1");
    }
}

fn set_rerun() {
    println!("cargo:rerun-if-env-changed=CFG_RELEASE");

    let mut manifest_dir = PathBuf::from(
        env::var("CARGO_MANIFEST_DIR").expect("`CARGO_MANIFEST_DIR` is always set by cargo."),
    );

    while manifest_dir.parent().is_some() {
        let head_ref = manifest_dir.join(".git/HEAD");
        if head_ref.exists() {
            println!("cargo:rerun-if-changed={}", head_ref.display());
            return;
        }

        manifest_dir.pop();
    }

    println!("cargo:warning=Could not find `.git/HEAD` from manifest dir!");
}

fn set_commit_info() {
    let output = match Command::new("git")
        .arg("log")
        .arg("-1")
        .arg("--date=short")
        .arg("--format=%H %h %cd")
        .output()
    {
        Ok(output) if output.status.success() => output,
        _ => return,
    };
    let stdout = String::from_utf8(output.stdout).unwrap();
    let mut parts = stdout.split_whitespace();
    let mut next = || parts.next().unwrap();
    println!("cargo:rustc-env=RA_COMMIT_HASH={}", next());
    println!("cargo:rustc-env=RA_COMMIT_SHORT_HASH={}", next());
    println!("cargo:rustc-env=RA_COMMIT_DATE={}", next())
}
<commit_msg>Fix typo in build.rs<commit_after>//! Construct version in the `commit-hash date channel` format

use std::{env, path::PathBuf, process::Command};

fn main() {
    set_rerun();
    set_commit_info();
    if option_env!("CFG_RELEASE").is_none() {
        println!("cargo:rustc-env=POKE_RA_DEVS=1");
    }
}

fn set_rerun() {
    println!("cargo:rerun-if-env-changed=CFG_RELEASE");

    let mut manifest_dir = PathBuf::from(
        env::var("CARGO_MANIFEST_DIR").expect("`CARGO_MANIFEST_DIR` is always set by cargo."),
    );

    while manifest_dir.parent().is_some() {
        let head_ref = manifest_dir.join(".git/HEAD");
        if head_ref.exists() {
            println!("cargo:rerun-if-changed={}", head_ref.display());
            return;
        }

        manifest_dir.pop();
    }

    println!("cargo:warning=Could not find `.git/HEAD` from manifest dir!");
}

fn set_commit_info() {
    let output = match Command::new("git")
        .arg("log")
        .arg("-1")
        .arg("--date=short")
        .arg("--format=%H %h %cd")
        .output()
    {
        Ok(output) if output.status.success() => output,
        _ => return,
    };
    let stdout = String::from_utf8(output.stdout).unwrap();
    let mut parts = stdout.split_whitespace();
    let mut next = || parts.next().unwrap();
    println!("cargo:rustc-env=RA_COMMIT_HASH={}", next());
    println!("cargo:rustc-env=RA_COMMIT_SHORT_HASH={}", next());
    println!("cargo:rustc-env=RA_COMMIT_DATE={}", next())
}
<|endoftext|>


<commit_before>#![feature(test)]
extern crate test;

extern crate onmf;

extern crate nalgebra;
use self::nalgebra::{DMat};

extern crate rand;
use rand::{StdRng, SeedableRng};

extern crate num;
use num::{Float};

macro_rules! bench_ortho_nmf {
    ($bencher:expr, $float:ty, $nhidden:expr, $nobserved:expr, $nsamples:expr) => {{
        let seed: &[_] = &[1, 2, 3, 4];
        let mut rng: StdRng = SeedableRng::from_seed(seed);

        let mut ortho_nmf = onmf::OrthogonalNMF::<$float>::init_random01(
            $nhidden, $nobserved, $nsamples, &mut rng);

        let samples = DMat::<$float>::new_ones($nsamples, $nobserved);

        let alpha: $float = 0.1 * 1.01.powi(0);
        $bencher.iter(|| {
            ortho_nmf.iterate(alpha, &samples);
        });
    }}
}

#[bench]
fn bench_ortho_nmf_f64_10_256_11(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f64, 10, 256, 11);
}

#[bench]
fn bench_ortho_nmf_f32_10_256_11(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f32, 10, 256, 11);
}

#[bench]
fn bench_ortho_nmf_f64_10_512_11(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f64, 10, 512, 11);
}

#[bench]
fn bench_ortho_nmf_f32_10_512_11(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f32, 10, 512, 11);
}

#[bench]
fn bench_ortho_nmf_f64_20_512_30(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f64, 20, 512, 30);
}

#[bench]
fn bench_ortho_nmf_f32_20_512_30(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f32, 20, 512, 30);
}
<commit_msg>add more benchmarks for entire ortho nmf<commit_after>#![feature(test)]
extern crate test;

extern crate onmf;

extern crate nalgebra;
use self::nalgebra::{DMat};

extern crate rand;
use rand::{StdRng, SeedableRng};

extern crate num;
use num::{Float};

macro_rules! bench_ortho_nmf {
    ($bencher:expr, $float:ty, $nhidden:expr, $nobserved:expr, $nsamples:expr) => {{
        let seed: &[_] = &[1, 2, 3, 4];
        let mut rng: StdRng = SeedableRng::from_seed(seed);

        let mut ortho_nmf = onmf::OrthogonalNMF::<$float>::init_random01(
            $nhidden, $nobserved, $nsamples, &mut rng);

        let samples = DMat::<$float>::new_ones($nsamples, $nobserved);

        let alpha: $float = 0.1 * 1.01.powi(0);
        $bencher.iter(|| {
            ortho_nmf.iterate(alpha, &samples);
        });
    }}
}

#[bench]
fn bench_ortho_nmf_f64_10_256_11(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f64, 10, 256, 11);
}
#[bench]
fn bench_ortho_nmf_f32_10_256_11(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f32, 10, 256, 11);
}

#[bench]
fn bench_ortho_nmf_f64_10_256_20(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f64, 10, 256, 20);
}
#[bench]
fn bench_ortho_nmf_f32_10_256_20(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f32, 10, 256, 20);
}

#[bench]
fn bench_ortho_nmf_f64_10_256_30(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f64, 10, 256, 30);
}
#[bench]
fn bench_ortho_nmf_f32_10_256_30(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f32, 10, 256, 30);
}

#[bench]
fn bench_ortho_nmf_f64_10_512_11(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f64, 10, 512, 11);
}
#[bench]
fn bench_ortho_nmf_f32_10_512_11(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f32, 10, 512, 11);
}

#[bench]
fn bench_ortho_nmf_f64_20_512_30(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f64, 20, 512, 30);
}
#[bench]
fn bench_ortho_nmf_f32_20_512_30(bencher: &mut test::Bencher) {
    bench_ortho_nmf!(bencher, f32, 20, 512, 30);
}
<|endoftext|>


<commit_before>extern crate ar;

use std::{env, path::PathBuf, process::Command};

use ar::Builder;
use std::fs::File;

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

  let output = Command::new(concat!(
    env!("CARGO_MANIFEST_DIR"),
    "/src/build_test_graph.py"
  )).arg(&out_dir)
    .output()
    .expect("Failed to execute command");
  if output.stderr.len() > 0 {
    panic!(String::from_utf8(output.stderr).unwrap());
  }

  let in_path: PathBuf = [&out_dir, "graph.o"].iter().collect();
  let out_path: PathBuf = [&out_dir, "libgraph.a"].iter().collect();
  let mut builder = Builder::new(File::create(out_path.to_str().unwrap()).unwrap());
  builder.append_path(in_path.to_str().unwrap()).unwrap();

  println!("cargo:rustc-link-lib=static=graph");
  println!("cargo:rustc-link-search=native={}", out_dir);
}
<commit_msg>Fix rust tests (#2482)<commit_after>extern crate ar;

use std::{
  env,
  fs::File,
  path::{Path, PathBuf},
  process::Command,
};

use ar::Builder;

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

  let output = Command::new(concat!(
    env!("CARGO_MANIFEST_DIR"),
    "/src/build_test_graph.py"
  ))
  .arg(&out_dir)
  .output()
  .expect("Failed to execute command");
  assert!(
    Path::new(&format!("{}/graph.o", out_dir)).exists(),
    "Could not build graph lib: {}",
    String::from_utf8(output.stderr)
      .unwrap()
      .trim()
      .split("\n")
      .last()
      .unwrap_or("")
  );

  let in_path: PathBuf = [&out_dir, "graph.o"].iter().collect();
  let out_path: PathBuf = [&out_dir, "libgraph.a"].iter().collect();
  let mut builder = Builder::new(File::create(out_path.to_str().unwrap()).unwrap());
  builder.append_path(in_path.to_str().unwrap()).unwrap();

  println!("cargo:rustc-link-lib=static=graph");
  println!("cargo:rustc-link-search=native={}", out_dir);
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate test;
extern crate bulletrs;

use test::Bencher;

use bulletrs::*;

#[bench]
fn get_base_position_and_orientation_bench(b: &mut Bencher) {
    let bodies_count = 2000;

    let bullet = Bullet::connect(ConnectMethod::Direct).unwrap();
    let client = bullet.physics_client_handle();

    client.reset_simulation();
    client.set_gravity(0.0, 0.0, -10.0);
    client.set_realtime_simulation(false);
    let plane_shape = client
        .create_collision_shape(ShapeType::Plane {
            normal: Vector3::from([0.0, 0.0, 1.0]),
            constant: 0.0,
        })
        .unwrap();

    let plane = client
        .create_rigid_body(
            plane_shape,
            0.0,
            Vector3::from([0.0, 0.0, 0.0]),
            Vector4::from([0.0, 0.0, 0.0, 1.0]),
        )
        .unwrap();

    client.change_dynamics_info(
        plane,
        DynamicsInfo {
            restitution : Some(0.9),
            ..Default::default()
        },
        );

    let sphere_shape = client
        .create_collision_shape(ShapeType::Sphere { radius: 0.1 })
        .unwrap();

    let bodies = (0..bodies_count).map(|i| {
        let body = client
            .create_rigid_body(
                sphere_shape.clone(),
                0.1,
                Vector3::from([i as f64 / 1000.0, i as f64 / 1000.0, 2.0 + i as f64 / 10.0]),
                Vector4::from([0.0, 0.0, 0.0, 1.0]),
            )
            .unwrap();

        client.change_dynamics_info(
            body.clone(),
            DynamicsInfo {
                restitution : Some(0.9),
                ..Default::default()
            },
        );
        body.clone()
    }).collect::<Vec<_>>();

    b.iter(move || {
        for body in bodies.iter() {
            client.get_base_position_and_orientation(body.clone()).unwrap();
        }
    })
}
<commit_msg>bench updated<commit_after>#![feature(test)]

extern crate test;
extern crate bulletrs;

use test::Bencher;

use bulletrs::*;

#[bench]
fn get_base_position_and_orientation_bench(b: &mut Bencher) {
    let bodies_count = 2000;

    let bullet = Bullet::connect(ConnectMethod::Direct).unwrap();
    let client = bullet.physics_client_handle();

    client.reset_simulation();
    client.set_gravity(0.0, 0.0, -10.0);
    client.set_realtime_simulation(false);
    let plane_shape = client
        .create_collision_shape(ShapeType::Plane {
            normal: Vector3::from([0.0, 0.0, 1.0]),
            constant: 0.0,
        })
        .unwrap();

    let plane = client
        .create_rigid_body(
            plane_shape,
            0.0,
            Vector3::from([0.0, 0.0, 0.0]),
            Vector4::from([0.0, 0.0, 0.0, 1.0]),
        )
        .unwrap();

    client.change_dynamics_info(
        plane,
        DynamicsInfo {
            restitution : Some(0.9),
            ..Default::default()
        },
        );

    let sphere_shape = client
        .create_collision_shape(ShapeType::Sphere { radius: 0.1 })
        .unwrap();

    let bodies = (0..bodies_count).map(|i| {
        let body = client
            .create_rigid_body(
                sphere_shape.clone(),
                0.1,
                Vector3::from([i as f64 / 1000.0, i as f64 / 1000.0, 2.0 + i as f64 / 10.0]),
                Vector4::from([0.0, 0.0, 0.0, 1.0]),
            )
            .unwrap();

        client.change_dynamics_info(
            body.clone(),
            DynamicsInfo {
                restitution : Some(0.9),
                ..Default::default()
            },
        );
        body.clone()
    }).collect::<Vec<_>>();

    b.iter(move || {
        for body in bodies.iter() {
            body.get_base_position_and_orientation().unwrap();
        }
    })
}
<|endoftext|>


<commit_before>use iron::{Listening, status};
use iron::prelude::*;
use std::net::ToSocketAddrs;
use std::ops::Drop;
use mount::Mount;
use router::Router;
use staticfile::Static;
use std::sync::{Weak, RwLock, Arc, Mutex};
use ::toyunda_player::state::State as ToyundaState;
use ::toyunda_player::command::*;
use ::toyunda_player::yaml_meta::*;
use ::toyunda_player::video_meta::*;

use ::utils::for_each_in_dir;
use std::path::{Path, PathBuf};
use std::fs;
use std::ops::Deref;
use std::sync::mpsc::{channel, Sender, Receiver};
use serde_json;
use bodyparser;

#[derive(Debug,Deserialize,Clone)]
enum WebCommandType {
    #[serde(rename = "play_next")]
    PlayNext,
    #[serde(rename = "add_to_queue")]
    AddToQueue,
    #[serde(rename = "clear_queue")]
    ClearQueue,
    #[serde(rename = "pause")]
    Pause,
    #[serde(rename = "unpause")]
    Unpause,
    #[serde(rename = "quit")]
    Quit,
    #[serde(rename = "stop")]
    Stop,
    #[serde(rename = "quit_on_finish")]
    QuitOnFinish,
    #[serde(rename = "toggle_subtitles")]
    ToggleSubtitles,
}

#[derive(Debug,Deserialize)]
struct WebCommand {
    command: WebCommandType,
    id: Option<u32>,
}

pub struct Manager {
    listening: Listening,
    toyunda_state: Weak<RwLock<ToyundaState>>,
    pub receiver: Receiver<Command>,
    yaml_files: Arc<Vec<YamlMeta>>,
}

impl Manager {
    fn log(&self, message: &str) {
        match self.toyunda_state.upgrade() {
            Some(toy_state_arc) => {
                toy_state_arc.write().unwrap().logs.push(String::from(message));
            }
            None => {}
        }
    }

    fn add_yaml_file<P: AsRef<Path>>(yaml_files: &mut Vec<YamlMeta>,
                                     file: P)
                                     -> Result<(), String> {
        let file = file.as_ref();

        match VideoMeta::from_yaml(file) {
            Ok(video_meta) => {
                yaml_files.push(YamlMeta {
                    yaml_path: PathBuf::from(file),
                    video_meta: video_meta.fix_paths(file),
                });
                Ok(())
            }
            Err(e) => Err(format!("Error when loading yaml file '{}' : {}", file.display(), e)),
        }
    }

    fn parse_yaml_directory<P: AsRef<Path>>(directory: P) -> Result<Vec<YamlMeta>, String> {
        let mut yaml_files: Vec<YamlMeta> = Vec::new();
        let (paths, errs) = for_each_in_dir(directory,
                                            3,
                                            &|path| {
                                                match path.extension() {
                                                    Some(s) if s == "yaml" => true,
                                                    _ => false,
                                                }
                                            });
        for err in errs {
            let _tmp_str = format!("IoError '{}' when parsing yaml dir", err);
            error!("{}", _tmp_str);
            // self.log(_tmp_str.as_str());
        }
        for path in paths {
            match Self::add_yaml_file(&mut yaml_files, &path) {
                Ok(()) => {}
                Err(err_string) => {
                    error!("{}", err_string);
                    // self.log(err_string.as_str());
                }
            }
        }
        Ok(yaml_files)
    }

    fn state_request(toyunda_state: Weak<RwLock<ToyundaState>>) -> IronResult<Response> {
        use iron::mime::Mime;
        match toyunda_state.upgrade() {
            Some(arc_t) => {
                let json_mime: Mime = "application/json".parse().unwrap();
                let toy_state = arc_t.deref().read().unwrap();
                let json_answer = serde_json::to_string_pretty(&*toy_state).unwrap();
                Ok(Response::with((status::Ok, json_answer, json_mime)))
            }
            None => Ok(Response::with(status::ServiceUnavailable)),
        }
    }

    fn list_request(list: Weak<Vec<YamlMeta>>) -> IronResult<Response> {
        use iron::mime::Mime;
        let json_mime: Mime = "application/json".parse().unwrap();
        match list.upgrade() {
            Some(list) => {
                let json_answer = serde_json::to_string_pretty(list.as_ref()).unwrap();
                Ok(Response::with((status::Ok, json_answer, json_mime)))
            }
            None => Ok(Response::with((status::Gone, "{}", json_mime))),
        }
    }

    fn command(request: &mut Request,
               tx: Sender<Command>,
               list: Weak<Vec<YamlMeta>>)
               -> IronResult<Response> {
        let web_command = request.get_ref::<bodyparser::Struct<WebCommand>>();
        match web_command {
            Ok(&Some(ref web_command)) => {
                let command: Result<Command, String> = match web_command.command {
                    WebCommandType::PlayNext => Ok(Command::PlayNext),
                    WebCommandType::ClearQueue => Ok(Command::ClearQueue),
                    WebCommandType::AddToQueue => {
                        if let Some(id) = web_command.id {
                            if let Some(list) = list.upgrade() {
                                if let Some(ref yaml_meta) = list.get(id as usize) {
                                    Ok(Command::AddToQueue(yaml_meta.video_meta.clone()))
                                } else {
                                    Err(format!("Bad Index {}", id))
                                }
                            } else {
                                Err(String::from("Gone"))
                            }
                        } else {
                            Err(String::from("'id' field is needed"))
                        }
                    }
                    _ => unimplemented!(),
                };
                println!("command : {:?}", command);
                if let Ok(command) = command {
                    tx.send(command);
                    Ok(Response::with(status::Ok))
                } else {
                    Ok(Response::with(status::BadRequest))
                }
            }
            Ok(&None) => Ok(Response::with(status::BadRequest)),
            Err(err) => Err(IronError::new(err, status::BadRequest)),
        }
    }

    pub fn new<A: ToSocketAddrs>(address: A,
                                 toyunda_state: Weak<RwLock<ToyundaState>>,
                                 yaml_directories: Vec<PathBuf>)
                                 -> IronResult<Manager> {
        let mut yaml_files: Vec<YamlMeta> = Vec::new();
        for dir in yaml_directories {
            if yaml_files.is_empty() {
                yaml_files = Self::parse_yaml_directory(&dir).unwrap();
            } else {
                yaml_files.extend(Self::parse_yaml_directory(&dir).unwrap());
            }
        }
        let yaml_files = Arc::new(yaml_files);
        let (tx, rx) = channel();
        let toyunda_state_cloned = toyunda_state.clone();
        let mut api_handler = Router::new();
        api_handler.get("state", move |request: &mut Request| {
            Self::state_request(toyunda_state_cloned.clone())
        });
        let tx_command = Mutex::new(tx);
        let weak_list = Arc::downgrade(&yaml_files);
        let weak_list2 = weak_list.clone();
        api_handler.post("command", move |request: &mut Request| {
            let tx_command = tx_command.lock().unwrap().clone();
            Self::command(request, tx_command, weak_list2.clone())
        });
        api_handler.get("listing",
                        move |request: &mut Request| Self::list_request(weak_list.clone()));
        let mut mount = Mount::new();
        mount.mount("/", Static::new("web/"));
        mount.mount("/api", api_handler);
        let listening = Iron::new(mount).http(address).unwrap();
        Ok(Manager {
            listening: listening,
            toyunda_state: toyunda_state,
            yaml_files: yaml_files,
            receiver: rx,
        })
    }
}

impl Drop for Manager {
    fn drop(&mut self) {
        self.listening.close().unwrap();
    }
}
<commit_msg>api: +pause +stop commands<commit_after>use iron::{Listening, status};
use iron::prelude::*;
use std::net::ToSocketAddrs;
use std::ops::Drop;
use mount::Mount;
use router::Router;
use staticfile::Static;
use std::sync::{Weak, RwLock, Arc, Mutex};
use ::toyunda_player::state::State as ToyundaState;
use ::toyunda_player::command::*;
use ::toyunda_player::yaml_meta::*;
use ::toyunda_player::video_meta::*;

use ::utils::for_each_in_dir;
use std::path::{Path, PathBuf};
use std::fs;
use std::ops::Deref;
use std::sync::mpsc::{channel, Sender, Receiver};
use serde_json;
use bodyparser;

#[derive(Debug,Deserialize,Clone)]
enum WebCommandType {
    #[serde(rename = "play_next")]
    PlayNext,
    #[serde(rename = "add_to_queue")]
    AddToQueue,
    #[serde(rename = "clear_queue")]
    ClearQueue,
    #[serde(rename = "pause")]
    Pause,
    #[serde(rename = "quit")]
    Quit,
    #[serde(rename = "stop")]
    Stop,
    #[serde(rename = "quit_on_finish")]
    QuitOnFinish,
    #[serde(rename = "toggle_subtitles")]
    ToggleSubtitles,
}

#[derive(Debug,Deserialize)]
struct WebCommand {
    command: WebCommandType,
    id: Option<u32>,
}

pub struct Manager {
    listening: Listening,
    toyunda_state: Weak<RwLock<ToyundaState>>,
    pub receiver: Receiver<Command>,
    yaml_files: Arc<Vec<YamlMeta>>,
}

impl Manager {
    fn log(&self, message: &str) {
        match self.toyunda_state.upgrade() {
            Some(toy_state_arc) => {
                toy_state_arc.write().unwrap().logs.push(String::from(message));
            }
            None => {}
        }
    }

    fn add_yaml_file<P: AsRef<Path>>(yaml_files: &mut Vec<YamlMeta>,
                                     file: P)
                                     -> Result<(), String> {
        let file = file.as_ref();

        match VideoMeta::from_yaml(file) {
            Ok(video_meta) => {
                yaml_files.push(YamlMeta {
                    yaml_path: PathBuf::from(file),
                    video_meta: video_meta.fix_paths(file),
                });
                Ok(())
            }
            Err(e) => Err(format!("Error when loading yaml file '{}' : {}", file.display(), e)),
        }
    }

    fn parse_yaml_directory<P: AsRef<Path>>(directory: P) -> Result<Vec<YamlMeta>, String> {
        let mut yaml_files: Vec<YamlMeta> = Vec::new();
        let (paths, errs) = for_each_in_dir(directory,
                                            3,
                                            &|path| {
                                                match path.extension() {
                                                    Some(s) if s == "yaml" => true,
                                                    _ => false,
                                                }
                                            });
        for err in errs {
            let _tmp_str = format!("IoError '{}' when parsing yaml dir", err);
            error!("{}", _tmp_str);
            // self.log(_tmp_str.as_str());
        }
        for path in paths {
            match Self::add_yaml_file(&mut yaml_files, &path) {
                Ok(()) => {}
                Err(err_string) => {
                    error!("{}", err_string);
                    // self.log(err_string.as_str());
                }
            }
        }
        Ok(yaml_files)
    }

    fn state_request(toyunda_state: Weak<RwLock<ToyundaState>>) -> IronResult<Response> {
        use iron::mime::Mime;
        match toyunda_state.upgrade() {
            Some(arc_t) => {
                let json_mime: Mime = "application/json".parse().unwrap();
                let toy_state = arc_t.deref().read().unwrap();
                let json_answer = serde_json::to_string_pretty(&*toy_state).unwrap();
                Ok(Response::with((status::Ok, json_answer, json_mime)))
            }
            None => Ok(Response::with(status::ServiceUnavailable)),
        }
    }

    fn list_request(list: Weak<Vec<YamlMeta>>) -> IronResult<Response> {
        use iron::mime::Mime;
        let json_mime: Mime = "application/json".parse().unwrap();
        match list.upgrade() {
            Some(list) => {
                let json_answer = serde_json::to_string_pretty(list.as_ref()).unwrap();
                Ok(Response::with((status::Ok, json_answer, json_mime)))
            }
            None => Ok(Response::with((status::Gone, "{}", json_mime))),
        }
    }

    fn command(request: &mut Request,
               tx: Sender<Command>,
               list: Weak<Vec<YamlMeta>>)
               -> IronResult<Response> {
        let web_command = request.get_ref::<bodyparser::Struct<WebCommand>>();
        match web_command {
            Ok(&Some(ref web_command)) => {
                let command: Result<Command, String> = match web_command.command {
                    WebCommandType::PlayNext => Ok(Command::PlayNext),
                    WebCommandType::ClearQueue => Ok(Command::ClearQueue),
                    WebCommandType::Stop => Ok(Command::Stop),
                    WebCommandType::Pause => Ok(Command::TogglePause),
                    WebCommandType::AddToQueue => {
                        if let Some(id) = web_command.id {
                            if let Some(list) = list.upgrade() {
                                if let Some(ref yaml_meta) = list.get(id as usize) {
                                    Ok(Command::AddToQueue(yaml_meta.video_meta.clone()))
                                } else {
                                    Err(format!("Bad Index {}", id))
                                }
                            } else {
                                Err(String::from("Gone"))
                            }
                        } else {
                            Err(String::from("'id' field is needed"))
                        }
                    }
                    _ => unimplemented!(),
                };
                println!("command : {:?}", command);
                if let Ok(command) = command {
                    tx.send(command);
                    Ok(Response::with(status::Ok))
                } else {
                    Ok(Response::with(status::BadRequest))
                }
            }
            Ok(&None) => Ok(Response::with(status::BadRequest)),
            Err(err) => Err(IronError::new(err, status::BadRequest)),
        }
    }

    pub fn new<A: ToSocketAddrs>(address: A,
                                 toyunda_state: Weak<RwLock<ToyundaState>>,
                                 yaml_directories: Vec<PathBuf>)
                                 -> IronResult<Manager> {
        let mut yaml_files: Vec<YamlMeta> = Vec::new();
        for dir in yaml_directories {
            if yaml_files.is_empty() {
                yaml_files = Self::parse_yaml_directory(&dir).unwrap();
            } else {
                yaml_files.extend(Self::parse_yaml_directory(&dir).unwrap());
            }
        }
        let yaml_files = Arc::new(yaml_files);
        let (tx, rx) = channel();
        let toyunda_state_cloned = toyunda_state.clone();
        let mut api_handler = Router::new();
        api_handler.get("state", move |request: &mut Request| {
            Self::state_request(toyunda_state_cloned.clone())
        });
        let tx_command = Mutex::new(tx);
        let weak_list = Arc::downgrade(&yaml_files);
        let weak_list2 = weak_list.clone();
        api_handler.post("command", move |request: &mut Request| {
            let tx_command = tx_command.lock().unwrap().clone();
            Self::command(request, tx_command, weak_list2.clone())
        });
        api_handler.get("listing",
                        move |request: &mut Request| Self::list_request(weak_list.clone()));
        let mut mount = Mount::new();
        mount.mount("/", Static::new("web/"));
        mount.mount("/api", api_handler);
        let listening = Iron::new(mount).http(address).unwrap();
        Ok(Manager {
            listening: listening,
            toyunda_state: toyunda_state,
            yaml_files: yaml_files,
            receiver: rx,
        })
    }
}

impl Drop for Manager {
    fn drop(&mut self) {
        self.listening.close().unwrap();
    }
}
<|endoftext|>


<commit_before>//! Rust simulator code generation.

mod compiler;
mod ir;

use compiler::*;
use ir::*;

use typed_arena::Arena;

use crate::code_writer;
use crate::graph;

use std::io::{Result, Write};
use std::ptr;

// TODO: Note that mutable writer reference can be passed, see https://rust-lang.github.io/api-guidelines/interoperability.html#c-rw-value
pub fn generate<'a, W: Write>(m: &'a graph::Module<'a>, w: W) -> Result<()> {
    let module_stack_frame = ModuleStackFrame {
        parent: None,
        module: m,
    };
    validate_module_hierarchy(m, &module_stack_frame, m);

    let context_arena = Arena::new();
    let root_context = context_arena.alloc(ModuleContext::new(None));
    let mut c = Compiler::new(&context_arena);

    for (_, output) in m.outputs.borrow().iter() {
        c.gather_regs(&output, root_context);
    }

    for (name, output) in m.outputs.borrow().iter() {
        let expr = c.compile_signal(&output, root_context);
        c.prop_assignments.push(Assignment {
            target_scope: TargetScope::Member,
            target_name: name.clone(),
            expr,
        });
    }

    // TODO: Can we get rid of this clone?
    for ((context, reg), names) in c.reg_names.clone().iter() {
        let context = unsafe { &**context as &ModuleContext };
        let reg = unsafe { &**reg as &graph::Signal };
        match reg.data {
            graph::SignalData::Reg { ref next, .. } => {
                let expr = c.compile_signal(next.borrow().unwrap(), context);
                c.prop_assignments.push(Assignment {
                    target_scope: TargetScope::Member,
                    target_name: names.next_name.clone(),
                    expr,
                });
            }
            _ => unreachable!(),
        }
    }

    let mut w = code_writer::CodeWriter::new(w);

    w.append_line("#[allow(non_camel_case_types)]")?;
    w.append_line("#[derive(Default)]")?;
    w.append_line(&format!("pub struct {} {{", m.name))?;
    w.indent();

    let inputs = m.inputs.borrow();
    if inputs.len() > 0 {
        w.append_line("// Inputs")?;
        for (name, input) in inputs.iter() {
            w.append_line(&format!(
                "pub {}: {}, // {} bit(s)",
                name,
                ValueType::from_bit_width(input.bit_width()).name(),
                input.bit_width()
            ))?;
        }
    }

    let outputs = m.outputs.borrow();
    if outputs.len() > 0 {
        w.append_line("// Outputs")?;
        for (name, output) in outputs.iter() {
            w.append_line(&format!(
                "pub {}: {}, // {} bit(s)",
                name,
                ValueType::from_bit_width(output.bit_width()).name(),
                output.bit_width()
            ))?;
        }
    }

    if c.reg_names.len() > 0 {
        w.append_line("// Regs")?;
        for ((_, reg), names) in c.reg_names.iter() {
            let reg = unsafe { &**reg as &graph::Signal };
            let type_name = ValueType::from_bit_width(reg.bit_width()).name();
            w.append_line(&format!(
                "{}: {}, // {} bit(s)",
                names.value_name,
                type_name,
                reg.bit_width()
            ))?;
            w.append_line(&format!("{}: {},", names.next_name, type_name))?;
        }
    }

    w.unindent()?;
    w.append_line("}")?;
    w.append_newline()?;

    w.append_line(&format!("impl {} {{", m.name))?;
    w.indent();

    if c.reg_names.len() > 0 {
        w.append_line("pub fn reset(&mut self) {")?;
        w.indent();

        // TODO: Consider using assignments/exprs instead of generating statement strings
        for ((_, reg), names) in c.reg_names.iter() {
            let reg = unsafe { &**reg as &graph::Signal };
            match reg.data {
                graph::SignalData::Reg {
                    ref initial_value,
                    bit_width,
                    ..
                } => {
                    if let Some(ref initial_value) = *initial_value.borrow() {
                        w.append_indent()?;
                        w.append(&format!("self.{} = ", names.value_name))?;
                        let type_name = ValueType::from_bit_width(bit_width).name();
                        w.append(&match initial_value {
                            graph::Value::Bool(value) => {
                                if bit_width == 1 {
                                    format!("{}", value)
                                } else {
                                    format!("0x{:x}{}", if *value { 1 } else { 0 }, type_name)
                                }
                            }
                            graph::Value::U32(value) => format!("0x{:x}{}", value, type_name),
                            graph::Value::U64(value) => format!("0x{:x}{}", value, type_name),
                            graph::Value::U128(value) => format!("0x{:x}{}", value, type_name),
                        })?;
                        w.append(";")?;
                        w.append_newline()?;
                    }
                }
                _ => unreachable!(),
            }
        }

        w.unindent()?;
        w.append_line("}")?;
        w.append_newline()?;

        w.append_line("pub fn posedge_clk(&mut self) {")?;
        w.indent();

        for names in c.reg_names.values() {
            w.append_line(&format!(
                "self.{} = self.{};",
                names.value_name, names.next_name
            ))?;
        }

        w.unindent()?;
        w.append_line("}")?;
        w.append_newline()?;
    }

    w.append_line("pub fn prop(&mut self) {")?;
    w.indent();

    for assignment in c.prop_assignments.iter() {
        w.append_indent()?;
        assignment.write(&mut w)?;
    }

    w.unindent()?;
    w.append_line("}")?;

    w.unindent()?;
    w.append_line("}")?;
    w.append_newline()?;

    Ok(())
}

struct ModuleStackFrame<'graph, 'frame> {
    parent: Option<&'frame ModuleStackFrame<'graph, 'frame>>,
    module: &'graph graph::Module<'graph>,
}

fn validate_module_hierarchy<'graph, 'frame>(
    m: &graph::Module<'graph>,
    module_stack_frame: &ModuleStackFrame<'graph, 'frame>,
    root: &graph::Module<'graph>,
) {
    for instance in m.instances.borrow().iter() {
        let instantiated_module = instance.instantiated_module;

        if ptr::eq(instantiated_module, m) {
            panic!("Cannot generate code for module \"{}\" because it has a recursive definition formed by an instance of itself called \"{}\".", m.name, instance.name);
        }

        let mut frame = module_stack_frame;
        loop {
            if ptr::eq(instantiated_module, frame.module) {
                panic!("Cannot generate code for module \"{}\" because it has a recursive definition formed by an instance of itself called \"{}\" in module \"{}\".", root.name, instance.name, m.name);
            }

            if let Some(parent) = frame.parent {
                frame = parent;
            } else {
                break;
            }
        }

        for input_name in instantiated_module.inputs.borrow().keys() {
            if !instance.driven_inputs.borrow().contains_key(input_name) {
                panic!("Cannot generate code for module \"{}\" because module \"{}\" contains an instance of module \"{}\" called \"{}\" whose input \"{}\" is not driven.", root.name, m.name, instantiated_module.name, instance.name, input_name);
            }
        }

        validate_module_hierarchy(
            instantiated_module,
            &ModuleStackFrame {
                parent: Some(module_stack_frame),
                module: instantiated_module,
            },
            root,
        );
    }
}

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

    use crate::*;

    #[test]
    #[should_panic(
        expected = "Cannot generate code for module \"a\" because it has a recursive definition formed by an instance of itself called \"a1\"."
    )]
    fn recursive_module_definition_error1() {
        let c = Context::new();

        let a = c.module("a");

        let _ = a.instance("a", "a1");

        // Panic
        generate(a, Vec::new()).unwrap();
    }

    #[test]
    #[should_panic(
        expected = "Cannot generate code for module \"a\" because it has a recursive definition formed by an instance of itself called \"a1\" in module \"b\"."
    )]
    fn recursive_module_definition_error2() {
        let c = Context::new();

        let a = c.module("a");
        let b = c.module("b");

        let _ = a.instance("b", "b1");
        let _ = b.instance("a", "a1");

        // Panic
        generate(a, Vec::new()).unwrap();
    }

    #[test]
    #[should_panic(
        expected = "Cannot generate code for module \"a\" because module \"a\" contains an instance of module \"b\" called \"b1\" whose input \"i\" is not driven."
    )]
    fn undriven_instance_input_error() {
        let c = Context::new();

        let a = c.module("a");
        let b = c.module("b");
        let _ = b.input("i", 1);

        let _ = a.instance("b", "b1");

        // Panic
        generate(a, Vec::new()).unwrap();
    }
}
<commit_msg>Tiny cleanup<commit_after>//! Rust simulator code generation.

mod compiler;
mod ir;

use compiler::*;
use ir::*;

use typed_arena::Arena;

use crate::code_writer;
use crate::graph;

use std::io::{Result, Write};
use std::ptr;

// TODO: Note that mutable writer reference can be passed, see https://rust-lang.github.io/api-guidelines/interoperability.html#c-rw-value
pub fn generate<'a, W: Write>(m: &'a graph::Module<'a>, w: W) -> Result<()> {
    validate_module_hierarchy(
        m,
        &ModuleStackFrame {
            parent: None,
            module: m,
        },
        m,
    );

    let context_arena = Arena::new();
    let root_context = context_arena.alloc(ModuleContext::new(None));
    let mut c = Compiler::new(&context_arena);

    for (_, output) in m.outputs.borrow().iter() {
        c.gather_regs(&output, root_context);
    }

    for (name, output) in m.outputs.borrow().iter() {
        let expr = c.compile_signal(&output, root_context);
        c.prop_assignments.push(Assignment {
            target_scope: TargetScope::Member,
            target_name: name.clone(),
            expr,
        });
    }

    // TODO: Can we get rid of this clone?
    for ((context, reg), names) in c.reg_names.clone().iter() {
        let context = unsafe { &**context as &ModuleContext };
        let reg = unsafe { &**reg as &graph::Signal };
        match reg.data {
            graph::SignalData::Reg { ref next, .. } => {
                let expr = c.compile_signal(next.borrow().unwrap(), context);
                c.prop_assignments.push(Assignment {
                    target_scope: TargetScope::Member,
                    target_name: names.next_name.clone(),
                    expr,
                });
            }
            _ => unreachable!(),
        }
    }

    let mut w = code_writer::CodeWriter::new(w);

    w.append_line("#[allow(non_camel_case_types)]")?;
    w.append_line("#[derive(Default)]")?;
    w.append_line(&format!("pub struct {} {{", m.name))?;
    w.indent();

    let inputs = m.inputs.borrow();
    if inputs.len() > 0 {
        w.append_line("// Inputs")?;
        for (name, input) in inputs.iter() {
            w.append_line(&format!(
                "pub {}: {}, // {} bit(s)",
                name,
                ValueType::from_bit_width(input.bit_width()).name(),
                input.bit_width()
            ))?;
        }
    }

    let outputs = m.outputs.borrow();
    if outputs.len() > 0 {
        w.append_line("// Outputs")?;
        for (name, output) in outputs.iter() {
            w.append_line(&format!(
                "pub {}: {}, // {} bit(s)",
                name,
                ValueType::from_bit_width(output.bit_width()).name(),
                output.bit_width()
            ))?;
        }
    }

    if c.reg_names.len() > 0 {
        w.append_line("// Regs")?;
        for ((_, reg), names) in c.reg_names.iter() {
            let reg = unsafe { &**reg as &graph::Signal };
            let type_name = ValueType::from_bit_width(reg.bit_width()).name();
            w.append_line(&format!(
                "{}: {}, // {} bit(s)",
                names.value_name,
                type_name,
                reg.bit_width()
            ))?;
            w.append_line(&format!("{}: {},", names.next_name, type_name))?;
        }
    }

    w.unindent()?;
    w.append_line("}")?;
    w.append_newline()?;

    w.append_line(&format!("impl {} {{", m.name))?;
    w.indent();

    if c.reg_names.len() > 0 {
        w.append_line("pub fn reset(&mut self) {")?;
        w.indent();

        // TODO: Consider using assignments/exprs instead of generating statement strings
        for ((_, reg), names) in c.reg_names.iter() {
            let reg = unsafe { &**reg as &graph::Signal };
            match reg.data {
                graph::SignalData::Reg {
                    ref initial_value,
                    bit_width,
                    ..
                } => {
                    if let Some(ref initial_value) = *initial_value.borrow() {
                        w.append_indent()?;
                        w.append(&format!("self.{} = ", names.value_name))?;
                        let type_name = ValueType::from_bit_width(bit_width).name();
                        w.append(&match initial_value {
                            graph::Value::Bool(value) => {
                                if bit_width == 1 {
                                    format!("{}", value)
                                } else {
                                    format!("0x{:x}{}", if *value { 1 } else { 0 }, type_name)
                                }
                            }
                            graph::Value::U32(value) => format!("0x{:x}{}", value, type_name),
                            graph::Value::U64(value) => format!("0x{:x}{}", value, type_name),
                            graph::Value::U128(value) => format!("0x{:x}{}", value, type_name),
                        })?;
                        w.append(";")?;
                        w.append_newline()?;
                    }
                }
                _ => unreachable!(),
            }
        }

        w.unindent()?;
        w.append_line("}")?;
        w.append_newline()?;

        w.append_line("pub fn posedge_clk(&mut self) {")?;
        w.indent();

        for names in c.reg_names.values() {
            w.append_line(&format!(
                "self.{} = self.{};",
                names.value_name, names.next_name
            ))?;
        }

        w.unindent()?;
        w.append_line("}")?;
        w.append_newline()?;
    }

    w.append_line("pub fn prop(&mut self) {")?;
    w.indent();

    for assignment in c.prop_assignments.iter() {
        w.append_indent()?;
        assignment.write(&mut w)?;
    }

    w.unindent()?;
    w.append_line("}")?;

    w.unindent()?;
    w.append_line("}")?;
    w.append_newline()?;

    Ok(())
}

struct ModuleStackFrame<'graph, 'frame> {
    parent: Option<&'frame ModuleStackFrame<'graph, 'frame>>,
    module: &'graph graph::Module<'graph>,
}

fn validate_module_hierarchy<'graph, 'frame>(
    m: &graph::Module<'graph>,
    module_stack_frame: &ModuleStackFrame<'graph, 'frame>,
    root: &graph::Module<'graph>,
) {
    for instance in m.instances.borrow().iter() {
        let instantiated_module = instance.instantiated_module;

        if ptr::eq(instantiated_module, m) {
            panic!("Cannot generate code for module \"{}\" because it has a recursive definition formed by an instance of itself called \"{}\".", m.name, instance.name);
        }

        let mut frame = module_stack_frame;
        loop {
            if ptr::eq(instantiated_module, frame.module) {
                panic!("Cannot generate code for module \"{}\" because it has a recursive definition formed by an instance of itself called \"{}\" in module \"{}\".", root.name, instance.name, m.name);
            }

            if let Some(parent) = frame.parent {
                frame = parent;
            } else {
                break;
            }
        }

        for input_name in instantiated_module.inputs.borrow().keys() {
            if !instance.driven_inputs.borrow().contains_key(input_name) {
                panic!("Cannot generate code for module \"{}\" because module \"{}\" contains an instance of module \"{}\" called \"{}\" whose input \"{}\" is not driven.", root.name, m.name, instantiated_module.name, instance.name, input_name);
            }
        }

        validate_module_hierarchy(
            instantiated_module,
            &ModuleStackFrame {
                parent: Some(module_stack_frame),
                module: instantiated_module,
            },
            root,
        );
    }
}

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

    use crate::*;

    #[test]
    #[should_panic(
        expected = "Cannot generate code for module \"a\" because it has a recursive definition formed by an instance of itself called \"a1\"."
    )]
    fn recursive_module_definition_error1() {
        let c = Context::new();

        let a = c.module("a");

        let _ = a.instance("a", "a1");

        // Panic
        generate(a, Vec::new()).unwrap();
    }

    #[test]
    #[should_panic(
        expected = "Cannot generate code for module \"a\" because it has a recursive definition formed by an instance of itself called \"a1\" in module \"b\"."
    )]
    fn recursive_module_definition_error2() {
        let c = Context::new();

        let a = c.module("a");
        let b = c.module("b");

        let _ = a.instance("b", "b1");
        let _ = b.instance("a", "a1");

        // Panic
        generate(a, Vec::new()).unwrap();
    }

    #[test]
    #[should_panic(
        expected = "Cannot generate code for module \"a\" because module \"a\" contains an instance of module \"b\" called \"b1\" whose input \"i\" is not driven."
    )]
    fn undriven_instance_input_error() {
        let c = Context::new();

        let a = c.module("a");
        let b = c.module("b");
        let _ = b.input("i", 1);

        let _ = a.instance("b", "b1");

        // Panic
        generate(a, Vec::new()).unwrap();
    }
}
<|endoftext|>


<commit_before>// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use super::{INTERRUPT_STATUS_CONFIG_CHANGED, INTERRUPT_STATUS_USED_RING, VIRTIO_MSI_NO_VECTOR};
use crate::pci::MsixConfig;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use sync::Mutex;
use sys_util::EventFd;

pub struct Interrupt {
    interrupt_status: Arc<AtomicUsize>,
    interrupt_evt: EventFd,
    interrupt_resample_evt: EventFd,
    msix_config: Option<Arc<Mutex<MsixConfig>>>,
}

impl Interrupt {
    pub fn new(
        interrupt_status: Arc<AtomicUsize>,
        interrupt_evt: EventFd,
        interrupt_resample_evt: EventFd,
        msix_config: Option<Arc<Mutex<MsixConfig>>>,
    ) -> Interrupt {
        Interrupt {
            interrupt_status,
            interrupt_evt,
            interrupt_resample_evt,
            msix_config,
        }
    }

    /// Virtqueue Interrupts From The Device
    ///
    /// If MSI-X is enabled in this device, MSI-X interrupt is preferred.
    /// Write to the irqfd to VMM to deliver virtual interrupt to the guest
    pub fn signal_used_queue(&self, vector: u16) {
        // Don't need to set ISR for MSI-X interrupts
        if let Some(msix_config) = &self.msix_config {
            let mut msix_config = msix_config.lock();
            if msix_config.enabled() {
                if vector != VIRTIO_MSI_NO_VECTOR {
                    msix_config.trigger(vector);
                }
                return;
            }
        }

        // Set BIT0 in ISR and inject the interrupt if it was not already pending.
        // Don't need to inject the interrupt if the guest hasn't processed it.
        if self
            .interrupt_status
            .fetch_or(INTERRUPT_STATUS_USED_RING as usize, Ordering::SeqCst)
            == 0
        {
            // Write to irqfd to inject INTx interrupt
            self.interrupt_evt.write(1).unwrap();
        }
    }

    /// Notification of Device Configuration Changes
    /// Set BIT1 in ISR and write to irqfd
    pub fn signal_config_changed(&self) {
        self.interrupt_status
            .fetch_or(INTERRUPT_STATUS_CONFIG_CHANGED as usize, Ordering::SeqCst);
        self.interrupt_evt.write(1).unwrap();
    }

    /// Handle interrupt resampling event
    pub fn interrupt_resample(&self) {
        let _ = self.interrupt_resample_evt.read();
        if self.interrupt_status.load(Ordering::SeqCst) != 0 {
            self.interrupt_evt.write(1).unwrap();
        }
    }

    /// Return the reference of interrupt_resample_evt
    /// To keep the interface clean, this member is private.
    pub fn get_resample_evt(&self) -> &EventFd {
        &self.interrupt_resample_evt
    }
}
<commit_msg>devices: virtio: factor out interrupt signal function<commit_after>// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use super::{INTERRUPT_STATUS_CONFIG_CHANGED, INTERRUPT_STATUS_USED_RING, VIRTIO_MSI_NO_VECTOR};
use crate::pci::MsixConfig;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use sync::Mutex;
use sys_util::EventFd;

pub struct Interrupt {
    interrupt_status: Arc<AtomicUsize>,
    interrupt_evt: EventFd,
    interrupt_resample_evt: EventFd,
    msix_config: Option<Arc<Mutex<MsixConfig>>>,
}

impl Interrupt {
    pub fn new(
        interrupt_status: Arc<AtomicUsize>,
        interrupt_evt: EventFd,
        interrupt_resample_evt: EventFd,
        msix_config: Option<Arc<Mutex<MsixConfig>>>,
    ) -> Interrupt {
        Interrupt {
            interrupt_status,
            interrupt_evt,
            interrupt_resample_evt,
            msix_config,
        }
    }

    /// Virtqueue Interrupts From The Device
    ///
    /// If MSI-X is enabled in this device, MSI-X interrupt is preferred.
    /// Write to the irqfd to VMM to deliver virtual interrupt to the guest
    fn signal(&self, vector: u16, interrupt_status_mask: u32) {
        // Don't need to set ISR for MSI-X interrupts
        if let Some(msix_config) = &self.msix_config {
            let mut msix_config = msix_config.lock();
            if msix_config.enabled() {
                if vector != VIRTIO_MSI_NO_VECTOR {
                    msix_config.trigger(vector);
                }
                return;
            }
        }

        // Set bit in ISR and inject the interrupt if it was not already pending.
        // Don't need to inject the interrupt if the guest hasn't processed it.
        if self
            .interrupt_status
            .fetch_or(interrupt_status_mask as usize, Ordering::SeqCst)
            == 0
        {
            // Write to irqfd to inject INTx interrupt
            self.interrupt_evt.write(1).unwrap();
        }
    }

    /// Notify the driver that buffers have been placed in the used queue.
    pub fn signal_used_queue(&self, vector: u16) {
        self.signal(vector, INTERRUPT_STATUS_USED_RING)
    }

    /// Notification of Device Configuration Changes
    /// Set BIT1 in ISR and write to irqfd
    pub fn signal_config_changed(&self) {
        self.interrupt_status
            .fetch_or(INTERRUPT_STATUS_CONFIG_CHANGED as usize, Ordering::SeqCst);
        self.interrupt_evt.write(1).unwrap();
    }

    /// Handle interrupt resampling event
    pub fn interrupt_resample(&self) {
        let _ = self.interrupt_resample_evt.read();
        if self.interrupt_status.load(Ordering::SeqCst) != 0 {
            self.interrupt_evt.write(1).unwrap();
        }
    }

    /// Return the reference of interrupt_resample_evt
    /// To keep the interface clean, this member is private.
    pub fn get_resample_evt(&self) -> &EventFd {
        &self.interrupt_resample_evt
    }
}
<|endoftext|>