<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2014 J.C. Moyer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#![allow(non_camel_case_types)]
#![allow(non_snake_case)]

// This is more or less in the order it appears in the Lua manual, with the
// exception of constants, which appear scattered throughout the manual text.

// luaconf.h functions
pub use self::luaconf::lua_numtointeger;

// C API types
pub use self::lua::{
  lua_Alloc,
  lua_CFunction,
  lua_Ctx,
  lua_Debug,
  lua_Hook,
  lua_Integer,
  lua_KFunction,
  lua_Number,
  lua_Reader,
  lua_State,
  lua_Unsigned,
  lua_Writer
};

// C API functions
pub use self::lua::{
  lua_absindex,
  lua_arith,
  lua_atpanic,
  lua_call,
  lua_callk,
  lua_checkstack,
  lua_close,
  lua_compare,
  lua_concat,
  lua_copy,
  lua_createtable,
  lua_dump,
  lua_error,
  lua_gc,
  lua_getallocf,
  lua_getextraspace,
  lua_getfield,
  lua_getglobal,
  lua_gethook,
  lua_gethookcount,
  lua_gethookmask,
  lua_getinfo,
  lua_getlocal,
  lua_getmetatable,
  lua_getstack,
  lua_gettable,
  lua_gettop,
  lua_getupvalue,
  lua_getuservalue,
  lua_insert,
  lua_isboolean,
  lua_iscfunction,
  lua_isfunction,
  lua_isinteger,
  lua_islightuserdata,
  lua_isnil,
  lua_isnone,
  lua_isnoneornil,
  lua_isnumber,
  lua_isstring,
  lua_istable,
  lua_isthread,
  lua_isuserdata,
  lua_isyieldable,
  lua_len,
  lua_load,
  lua_newstate,
  lua_newtable,
  lua_newthread,
  lua_newuserdata,
  lua_next,
  lua_pcall,
  lua_pcallk,
  lua_pop,
  lua_pushboolean,
  lua_pushcclosure,
  lua_pushcfunction,
  lua_pushfstring,
  lua_pushglobaltable,
  lua_pushinteger,
  lua_pushlightuserdata,
  lua_pushliteral,
  lua_pushlstring,
  lua_pushnil,
  lua_pushnumber,
  lua_pushstring,
  lua_pushthread,
  lua_pushvalue,
  // omitted: lua_pushvfstring
  lua_rawequal,
  lua_rawget,
  lua_rawgeti,
  lua_rawgetp,
  lua_rawlen,
  lua_rawset,
  lua_rawseti,
  lua_rawsetp,
  lua_register,
  lua_remove,
  lua_replace,
  lua_resume,
  lua_rotate,
  lua_setallocf,
  lua_setfield,
  lua_setglobal,
  lua_sethook,
  lua_setlocal,
  lua_setmetatable,
  lua_settable,
  lua_settop,
  lua_setupvalue,
  lua_setuservalue,
  lua_status,
  lua_strtonum,
  lua_toboolean,
  lua_tocfunction,
  lua_tointeger,
  lua_tointegerx,
  lua_tolstring,
  lua_tonumber,
  lua_tonumberx,
  lua_topointer,
  lua_tostring,
  lua_tothread,
  lua_touserdata,
  lua_type,
  lua_typename,
  lua_upvalueid,
  lua_upvalueindex,
  lua_upvaluejoin,
  lua_version,
  lua_xmove,
  lua_yield,
  lua_yieldk
};

// auxiliary library types
pub use self::lauxlib::{
  luaL_Buffer,
  luaL_Reg,
  luaL_Stream
};

// auxiliary library functions
pub use self::lauxlib::{
  luaL_addchar,
  luaL_addlstring,
  luaL_addsize,
  luaL_addstring,
  luaL_addvalue,
  luaL_argcheck,
  luaL_argerror,
  luaL_buffinit,
  luaL_buffinitsize,
  luaL_callmeta,
  luaL_checkany,
  luaL_checkint,
  luaL_checkinteger,
  luaL_checklong,
  luaL_checklstring,
  luaL_checknumber,
  luaL_checkoption,
  luaL_checkstack,
  luaL_checkstring,
  luaL_checktype,
  luaL_checkudata,
  luaL_checkversion,
  luaL_dofile,
  luaL_dostring,
  luaL_error,
  luaL_execresult,
  luaL_fileresult,
  luaL_getmetafield,
  luaL_getmetatable,
  luaL_getsubtable,
  luaL_gsub,
  luaL_len,
  luaL_loadbuffer,
  luaL_loadbufferx,
  luaL_loadfile,
  luaL_loadfilex,
  luaL_loadstring,
  luaL_newlib,
  luaL_newlibtable,
  luaL_newmetatable,
  luaL_newstate,
  luaL_optint,
  luaL_optinteger,
  luaL_optlong,
  luaL_optlstring,
  luaL_optnumber,
  luaL_optstring,
  luaL_prepbuffer,
  luaL_prepbuffsize,
  luaL_pushresult,
  luaL_pushresultsize,
  luaL_ref,
  luaL_requiref,
  luaL_setfuncs,
  luaL_setmetatable,
  luaL_testudata,
  luaL_tolstring,
  luaL_traceback,
  luaL_typename,
  luaL_unref,
  luaL_where
};

// lualib.h functions
pub use self::lualib::{
  luaL_openlibs
};

// constants from lua.h
pub use self::lua::{
  LUA_MULTRET,
  LUA_REGISTRYINDEX,

  LUA_RIDX_MAINTHREAD, LUA_RIDX_GLOBALS,

  LUA_OPADD, LUA_OPSUB, LUA_OPMUL, LUA_OPDIV, LUA_OPIDIV,
  LUA_OPMOD, LUA_OPPOW, LUA_OPUNM,
  LUA_OPBNOT, LUA_OPBAND, LUA_OPBOR, LUA_OPBXOR, LUA_OPSHL, LUA_OPSHR,
  LUA_OPEQ, LUA_OPLT, LUA_OPLE,

  LUA_OK, LUA_ERRRUN, LUA_ERRMEM, LUA_ERRERR, LUA_ERRGCMM,

  LUA_TNONE, LUA_TNIL, LUA_TNUMBER, LUA_TBOOLEAN, LUA_TSTRING, LUA_TTABLE,
  LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD, LUA_TLIGHTUSERDATA,

  LUA_HOOKCALL, LUA_HOOKRET, LUA_HOOKTAILCALL, LUA_HOOKLINE, LUA_HOOKCOUNT,

  LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, LUA_GCCOUNT, LUA_GCCOUNTB,
  LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, LUA_GCISRUNNING
};

// constants from lauxlib.h
pub use self::lauxlib::{
  LUA_REFNIL, LUA_NOREF,
  LUA_ERRFILE,
  LUA_FILEHANDLE
};

// constants from lualib.h
pub use self::lualib::{
  LUA_COLIBNAME, LUA_TABLIBNAME, LUA_IOLIBNAME, LUA_OSLIBNAME, LUA_STRLIBNAME,
  LUA_UTF8LIBNAME, LUA_BITLIBNAME, LUA_MATHLIBNAME, LUA_DBLIBNAME, LUA_LOADLIBNAME
};

mod glue;
pub mod luaconf;
pub mod lua;
pub mod lauxlib;
pub mod lualib;

<commit_msg>Re-export all lualib.h functions<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2014 J.C. Moyer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#![allow(non_camel_case_types)]
#![allow(non_snake_case)]

// This is more or less in the order it appears in the Lua manual, with the
// exception of constants, which appear scattered throughout the manual text.

// luaconf.h functions
pub use self::luaconf::lua_numtointeger;

// C API types
pub use self::lua::{
  lua_Alloc,
  lua_CFunction,
  lua_Ctx,
  lua_Debug,
  lua_Hook,
  lua_Integer,
  lua_KFunction,
  lua_Number,
  lua_Reader,
  lua_State,
  lua_Unsigned,
  lua_Writer
};

// C API functions
pub use self::lua::{
  lua_absindex,
  lua_arith,
  lua_atpanic,
  lua_call,
  lua_callk,
  lua_checkstack,
  lua_close,
  lua_compare,
  lua_concat,
  lua_copy,
  lua_createtable,
  lua_dump,
  lua_error,
  lua_gc,
  lua_getallocf,
  lua_getextraspace,
  lua_getfield,
  lua_getglobal,
  lua_gethook,
  lua_gethookcount,
  lua_gethookmask,
  lua_getinfo,
  lua_getlocal,
  lua_getmetatable,
  lua_getstack,
  lua_gettable,
  lua_gettop,
  lua_getupvalue,
  lua_getuservalue,
  lua_insert,
  lua_isboolean,
  lua_iscfunction,
  lua_isfunction,
  lua_isinteger,
  lua_islightuserdata,
  lua_isnil,
  lua_isnone,
  lua_isnoneornil,
  lua_isnumber,
  lua_isstring,
  lua_istable,
  lua_isthread,
  lua_isuserdata,
  lua_isyieldable,
  lua_len,
  lua_load,
  lua_newstate,
  lua_newtable,
  lua_newthread,
  lua_newuserdata,
  lua_next,
  lua_pcall,
  lua_pcallk,
  lua_pop,
  lua_pushboolean,
  lua_pushcclosure,
  lua_pushcfunction,
  lua_pushfstring,
  lua_pushglobaltable,
  lua_pushinteger,
  lua_pushlightuserdata,
  lua_pushliteral,
  lua_pushlstring,
  lua_pushnil,
  lua_pushnumber,
  lua_pushstring,
  lua_pushthread,
  lua_pushvalue,
  // omitted: lua_pushvfstring
  lua_rawequal,
  lua_rawget,
  lua_rawgeti,
  lua_rawgetp,
  lua_rawlen,
  lua_rawset,
  lua_rawseti,
  lua_rawsetp,
  lua_register,
  lua_remove,
  lua_replace,
  lua_resume,
  lua_rotate,
  lua_setallocf,
  lua_setfield,
  lua_setglobal,
  lua_sethook,
  lua_setlocal,
  lua_setmetatable,
  lua_settable,
  lua_settop,
  lua_setupvalue,
  lua_setuservalue,
  lua_status,
  lua_strtonum,
  lua_toboolean,
  lua_tocfunction,
  lua_tointeger,
  lua_tointegerx,
  lua_tolstring,
  lua_tonumber,
  lua_tonumberx,
  lua_topointer,
  lua_tostring,
  lua_tothread,
  lua_touserdata,
  lua_type,
  lua_typename,
  lua_upvalueid,
  lua_upvalueindex,
  lua_upvaluejoin,
  lua_version,
  lua_xmove,
  lua_yield,
  lua_yieldk
};

// auxiliary library types
pub use self::lauxlib::{
  luaL_Buffer,
  luaL_Reg,
  luaL_Stream
};

// auxiliary library functions
pub use self::lauxlib::{
  luaL_addchar,
  luaL_addlstring,
  luaL_addsize,
  luaL_addstring,
  luaL_addvalue,
  luaL_argcheck,
  luaL_argerror,
  luaL_buffinit,
  luaL_buffinitsize,
  luaL_callmeta,
  luaL_checkany,
  luaL_checkint,
  luaL_checkinteger,
  luaL_checklong,
  luaL_checklstring,
  luaL_checknumber,
  luaL_checkoption,
  luaL_checkstack,
  luaL_checkstring,
  luaL_checktype,
  luaL_checkudata,
  luaL_checkversion,
  luaL_dofile,
  luaL_dostring,
  luaL_error,
  luaL_execresult,
  luaL_fileresult,
  luaL_getmetafield,
  luaL_getmetatable,
  luaL_getsubtable,
  luaL_gsub,
  luaL_len,
  luaL_loadbuffer,
  luaL_loadbufferx,
  luaL_loadfile,
  luaL_loadfilex,
  luaL_loadstring,
  luaL_newlib,
  luaL_newlibtable,
  luaL_newmetatable,
  luaL_newstate,
  luaL_optint,
  luaL_optinteger,
  luaL_optlong,
  luaL_optlstring,
  luaL_optnumber,
  luaL_optstring,
  luaL_prepbuffer,
  luaL_prepbuffsize,
  luaL_pushresult,
  luaL_pushresultsize,
  luaL_ref,
  luaL_requiref,
  luaL_setfuncs,
  luaL_setmetatable,
  luaL_testudata,
  luaL_tolstring,
  luaL_traceback,
  luaL_typename,
  luaL_unref,
  luaL_where
};

// lualib.h functions
pub use self::lualib::{
  luaopen_base,
  luaopen_coroutine,
  luaopen_table,
  luaopen_io,
  luaopen_os,
  luaopen_string,
  luaopen_utf8,
  luaopen_bit32,
  luaopen_math,
  luaopen_debug,
  luaopen_package,

  luaL_openlibs
};

// constants from lua.h
pub use self::lua::{
  LUA_MULTRET,
  LUA_REGISTRYINDEX,

  LUA_RIDX_MAINTHREAD, LUA_RIDX_GLOBALS,

  LUA_OPADD, LUA_OPSUB, LUA_OPMUL, LUA_OPDIV, LUA_OPIDIV,
  LUA_OPMOD, LUA_OPPOW, LUA_OPUNM,
  LUA_OPBNOT, LUA_OPBAND, LUA_OPBOR, LUA_OPBXOR, LUA_OPSHL, LUA_OPSHR,
  LUA_OPEQ, LUA_OPLT, LUA_OPLE,

  LUA_OK, LUA_ERRRUN, LUA_ERRMEM, LUA_ERRERR, LUA_ERRGCMM,

  LUA_TNONE, LUA_TNIL, LUA_TNUMBER, LUA_TBOOLEAN, LUA_TSTRING, LUA_TTABLE,
  LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD, LUA_TLIGHTUSERDATA,

  LUA_HOOKCALL, LUA_HOOKRET, LUA_HOOKTAILCALL, LUA_HOOKLINE, LUA_HOOKCOUNT,

  LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, LUA_GCCOUNT, LUA_GCCOUNTB,
  LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, LUA_GCISRUNNING
};

// constants from lauxlib.h
pub use self::lauxlib::{
  LUA_REFNIL, LUA_NOREF,
  LUA_ERRFILE,
  LUA_FILEHANDLE
};

// constants from lualib.h
pub use self::lualib::{
  LUA_COLIBNAME, LUA_TABLIBNAME, LUA_IOLIBNAME, LUA_OSLIBNAME, LUA_STRLIBNAME,
  LUA_UTF8LIBNAME, LUA_BITLIBNAME, LUA_MATHLIBNAME, LUA_DBLIBNAME, LUA_LOADLIBNAME
};

mod glue;
pub mod luaconf;
pub mod lua;
pub mod lauxlib;
pub mod lualib;

<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// TODO tests

use strings::string_buffer::StringBuffer;
use std::collections::HashMap;
use std::fs::File;
use std::io::{Write, stdout};
use WriteMode;
use NewlineStyle;
use config::Config;

// A map of the files of a crate, with their new content
pub type FileMap = HashMap<String, StringBuffer>;

// Append a newline to the end of each file.
pub fn append_newlines(file_map: &mut FileMap) {
    for (_, s) in file_map.iter_mut() {
        s.push_str("\n");
    }
}

pub fn write_all_files(file_map: &FileMap,
                       mode: WriteMode,
                       config: &Config)
                       -> Result<(HashMap<String, String>), ::std::io::Error> {
    let mut result = HashMap::new();
    for filename in file_map.keys() {
        let one_result = try!(write_file(file_map, filename, mode, config));
        if let Some(r) = one_result {
            result.insert(filename.clone(), r);
        }
    }

    Ok(result)
}

fn write_file(file_map: &FileMap,
              filename: &str,
              mode: WriteMode,
              config: &Config)
              -> Result<Option<String>, ::std::io::Error> {
    let text = &file_map[filename];

        // prints all newlines either as `\n` or as `\r\n`
    fn write_system_newlines<T>(mut writer: T,
                                text: &StringBuffer,
                                config: &Config)
                                -> Result<(), ::std::io::Error>
        where T: Write
    {
        match config.newline_style {
                NewlineStyle::Unix => write!(writer, "{}", text),
                NewlineStyle::Windows => {
                    for (c, _) in text.chars() {
                        match c {
                            '\n' => try!(write!(writer, "\r\n")),
                            '\r' => continue,
                            c => try!(write!(writer, "{}", c)),
                        }
                    }
                    Ok(())
                },
            }
    }

    match mode {
            WriteMode::Overwrite => {
                // Do a little dance to make writing safer - write to a temp file
                // rename the original to a .bk, then rename the temp file to the
                // original.
                let tmp_name = filename.to_owned() + ".tmp";
                let bk_name = filename.to_owned() + ".bk";
                {
                    // Write text to temp file
                    let tmp_file = try!(File::create(&tmp_name));
                    try!(write_system_newlines(tmp_file, text, config));
                }

                try!(::std::fs::rename(filename, bk_name));
                try!(::std::fs::rename(tmp_name, filename));
            }
            WriteMode::NewFile(extn) => {
                let filename = filename.to_owned() + "." + extn;
                let file = try!(File::create(&filename));
                try!(write_system_newlines(file, text, config));
            }
            WriteMode::Display => {
                println!("{}:\n", filename);
                let stdout = stdout();
                let stdout_lock = stdout.lock();
                try!(write_system_newlines(stdout_lock, text, config));
            }
            WriteMode::Return(_) => {
                // io::Write is not implemented for String, working around with Vec<u8>
                let mut v = Vec::new();
                try!(write_system_newlines(&mut v, text, config));
                // won't panic, we are writing correct utf8
                return Ok(Some(String::from_utf8(v).unwrap()));
            }
        }

    Ok(None)
}
<commit_msg>Fix nits for filemap<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// TODO tests

use strings::string_buffer::StringBuffer;
use std::collections::HashMap;
use std::fs::{self, File};
use std::io::{self, Write, stdout};
use WriteMode;
use NewlineStyle;
use config::Config;

// A map of the files of a crate, with their new content
pub type FileMap = HashMap<String, StringBuffer>;

// Append a newline to the end of each file.
pub fn append_newlines(file_map: &mut FileMap) {
    for (_, s) in file_map.iter_mut() {
        s.push_str("\n");
    }
}

pub fn write_all_files(file_map: &FileMap,
                       mode: WriteMode,
                       config: &Config)
                       -> Result<(HashMap<String, String>), io::Error> {
    let mut result = HashMap::new();
    for filename in file_map.keys() {
        let one_result = try!(write_file(&file_map[filename], filename, mode, config));
        if let Some(r) = one_result {
            result.insert(filename.clone(), r);
        }
    }

    Ok(result)
}

fn write_file(text: &StringBuffer,
              filename: &str,
              mode: WriteMode,
              config: &Config)
              -> Result<Option<String>, io::Error> {

    // prints all newlines either as `\n` or as `\r\n`
    fn write_system_newlines<T>(mut writer: T,
                                text: &StringBuffer,
                                config: &Config)
                                -> Result<(), io::Error>
        where T: Write
    {
        match config.newline_style {
                NewlineStyle::Unix => write!(writer, "{}", text),
                NewlineStyle::Windows => {
                    for (c, _) in text.chars() {
                        match c {
                            '\n' => try!(write!(writer, "\r\n")),
                            '\r' => continue,
                            c => try!(write!(writer, "{}", c)),
                        }
                    }
                    Ok(())
                },
            }
    }

    match mode {
            WriteMode::Overwrite => {
                // Do a little dance to make writing safer - write to a temp file
                // rename the original to a .bk, then rename the temp file to the
                // original.
                let tmp_name = filename.to_owned() + ".tmp";
                let bk_name = filename.to_owned() + ".bk";
                {
                    // Write text to temp file
                    let tmp_file = try!(File::create(&tmp_name));
                    try!(write_system_newlines(tmp_file, text, config));
                }

                try!(fs::rename(filename, bk_name));
                try!(fs::rename(tmp_name, filename));
            }
            WriteMode::NewFile(extn) => {
                let filename = filename.to_owned() + "." + extn;
                let file = try!(File::create(&filename));
                try!(write_system_newlines(file, text, config));
            }
            WriteMode::Display => {
                println!("{}:\n", filename);
                let stdout = stdout();
                let stdout_lock = stdout.lock();
                try!(write_system_newlines(stdout_lock, text, config));
            }
            WriteMode::Return(_) => {
                // io::Write is not implemented for String, working around with Vec<u8>
                let mut v = Vec::new();
                try!(write_system_newlines(&mut v, text, config));
                // won't panic, we are writing correct utf8
                return Ok(Some(String::from_utf8(v).unwrap()));
            }
        }

    Ok(None)
}
<|endoftext|>


<commit_before>//! A dummy flash client to test flashcalw functionality at the platform level.
/// It can be used to 'kick-off' flashcalw tests by issuing only ONE command that
/// will generate an interrupt.

use sam4l::flashcalw;
use hil::flash::{FlashController, Client, Error};
use core::mem;
use core::cell::Cell;

// ======================================
//  Test the flash controller (using interrupts).
//  This is essentially a state-machine.
//  Note: This assumes that all the buses in the config function is on for the
//  entire time.
// ======================================

#[derive(Copy,Clone,PartialEq)]
enum FlashClientState {
    Enabling,
    ClearPageBuffer,
    WritePageBuffer,
    Writing,
    Reading,
    Erasing,
    EWRCycleStart   /* Start of the Erase, Write, Read Cycle */
}

struct FlashClient {
    state : Cell<FlashClientState>,
    page: Cell<i32>,
    region_unlocked: Cell<u32>,
    num_cycle_per_page: u32,
    val_data: Cell<u8>,
    cycles_finished: Cell<u32>
}

static mut FLASH_CLIENT : FlashClient = FlashClient {
    state: Cell::new(FlashClientState::Enabling),
    page: Cell::new(53), // Page to start
    region_unlocked: Cell::new(0),
    num_cycle_per_page: 2,  // How many times to repeat a Erase/Write/Read cycle on a page
    val_data: Cell::new(2), // Data to write to the page.
    cycles_finished: Cell::new(0)
};

const MAX_PAGE_NUM: i32 = 80;   // Page to go up to

impl Client for FlashClient {

    fn command_complete(&self, error : Error) {

        print!("Client Notified that job done in state {}", self.state.get() as u32);

        let dev = unsafe { &mut flashcalw::flash_controller };

        match self.state.get() {
            FlashClientState::Enabling => {
                    self.state.set(FlashClientState::EWRCycleStart);
                    println!("===========Transitioning \
                        to Erasing/Writing/Reading========");
                    dev.enable_ws1_read_opt(true);
                    // This enabled High Speed Mode using a command
                    // which generates the interrupt for the next stage.
                    dev.set_flash_waitstate_and_readmode(48000000, 0, false);
            },
            FlashClientState::Writing => {
                println!("\tWriting page {}", self.page.get());
                let data : [u8;512] = [self.val_data.get(); 512];
                dev.write_page(self.page.get(), &data);
                self.state.set(FlashClientState::Reading);
            },
            FlashClientState::Reading => {
                //  Again like WritePageBuffer, this isn't a command. But should be
                //  triggered after the write (hopefully).
                let mut pass = true;

                //  Prints out any differences in the flash page.
                println!("\treading page {}", self.page.get());
                let mut data : [u8; 512] = [0;512];
                dev.read(self.page.get() as usize * 512, 512, &mut data);

                //verify what we expect
                for i in 0..512 {
                    if( data[i] != self.val_data.get()) {
                        pass = false;
                        println!("\t\t======bit:{} expected {}, got {}========", i,
                           self.val_data.get(), data[i]);

                    }
                }

                if(!pass) {
                    for j in 0..3 {
                        println!("\treading page {}", self.page.get());
                        let mut data : [u8; 512] = [0;512];
                        dev.read(self.page.get() as usize * 512, 512, &mut data);
                        //verify what we expect
                        for i in 0..512 {
                            if data[i] != self.val_data.get() {
                            println!("\t\t\t======bit:{} expected {}, got {}========", i,
                               self.val_data.get(), data[i]);

                            }
                        }
                    }
                }

                //start cycle again
                self.state.set(FlashClientState::EWRCycleStart);
            },
            FlashClientState::Erasing => {
                println!("\tErasing page {}", self.page.get());
                dev.erase_page(self.page.get());
                self.state.set(FlashClientState::Writing);
            },
            FlashClientState::EWRCycleStart => {
                if self.page.get() <= MAX_PAGE_NUM {
                    if self.cycles_finished.get() >= self.num_cycle_per_page {
                        //reset count
                        self.cycles_finished.set(1);
                        //increment pg num
                        self.page.set(self.page.get() + 1);
                        //increment val_data
                        self.val_data.set(self.val_data.get() + 1);
                        //start new cycle
                        if self.page.get() <= MAX_PAGE_NUM {
                            self.state.set(FlashClientState::Erasing);
                            println!("==============Starting work on page {} \
                                =================", self.page.get());
                            self.command_complete(Error::CommandComplete);
                        }
                    } else {
                        println!("\t Still Cycling page {}", self.page.get());
                        //increment cycle count
                        self.cycles_finished.set(self.cycles_finished.get() + 1);
                        //increment val_data
                        self.val_data.set(self.val_data.get() + 1);
                        //continue cycle
                        self.state.set(FlashClientState::Erasing);
                        self.command_complete(Error::CommandComplete);
                    }
                }
            },
            _ => { panic!("Should never reach here!"); }

        }
    }

    /*  // This is the old state-machine controller (pre-interal interrupts)
        // Might be useful to have if debugging...
    fn command_complete(&self, error : Error) {

        print!("Client Notified that job done in state {}", self.state.get() as u32);

        let dev = unsafe { &mut flashcalw::flash_controller };

        match self.state.get() {
            FlashClientState::Enabling => {
                if self.region_unlocked.get() == 16 {
                    self.state.set(FlashClientState::EWRCycleStart);
                    println!("\t All Regions unlocked");
                    println!("===========Transitioning \
                        to Erasing/Writing/Reading========");
                    dev.enable_ws1_read_opt(true);
                    // This enabled High Speed Mode using a command
                    // which generates the interrupt for the next stage.
                    dev.set_flash_waitstate_and_readmode(48000000, 0, false);
                } else {
                    dev.lock_region(self.region_unlocked.get(), false);
                    println!("\t Unlocking Region {}", self.region_unlocked.get());
                    self.region_unlocked.set(self.region_unlocked.get() + 1);
                }
            },
            FlashClientState::Writing => {
                println!("\tWriting page {}", self.page.get());
                dev.flashcalw_write_page(self.page.get());
                self.state.set(FlashClientState::Reading);
            },
            FlashClientState::Reading => {
                //  Again like WritePageBuffer, this isn't a command. But should be
                //  triggered after the write (hopefully).
                let mut pass = true;

                //  Prints out any differences in the flash page.
                println!("\treading page {}", self.page.get());
                let mut data : [u8; 512] = [0;512];
                dev.read(self.page.get() as usize * 512, 512, &mut data);

                //verify what we expect
                for i in 0..512 {
                    if( data[i] != self.val_data.get()) {
                        pass = false;
                        println!("\t\t======bit:{} expected {}, got {}========", i,
                           self.val_data.get(), data[i]);

                    }
                }

                if(!pass) {
                    for j in 0..3 {
                        println!("\treading page {}", self.page.get());
                        let mut data : [u8; 512] = [0;512];
                        dev.read(self.page.get() as usize * 512, 512, &mut data);
                        //verify what we expect
                        for i in 0..512 {
                            if data[i] != self.val_data.get() {
                            println!("\t\t\t======bit:{} expected {}, got {}========", i,
                               self.val_data.get(), data[i]);

                            }
                        }
                    }
                }

                //start cycle again
                self.state.set(FlashClientState::EWRCycleStart);
            },
            FlashClientState::Erasing => {
                println!("\tErasing page {}", self.page.get());
                dev.flashcalw_erase_page(self.page.get(), true);
                self.state.set(FlashClientState::ClearPageBuffer);
            },
            FlashClientState::ClearPageBuffer => {
                println!("\tClearing page buffer");
                dev.clear_page_buffer();
                self.state.set(FlashClientState::WritePageBuffer);
            },
            FlashClientState::WritePageBuffer => {
                println!("\tWriting to page buffer");
                let data : [u8;512] = [self.val_data.get(); 512];
                // TODO: note this won't work b/c of the no writing to page buffer.
                //dev.write_to_page_buffer(&data, (self.page.get() * 512) as usize);
                self.state.set(FlashClientState::Writing);
                self.command_complete(Error::CommandComplete); // we need to call this here as
                                         // write_to_page_buffer isn't really a
                                         // command (thus no interrupt generated).
            },
            FlashClientState::EWRCycleStart => {
                if self.page.get() <= MAX_PAGE_NUM {
                    if self.cycles_finished.get() >= self.num_cycle_per_page {
                        //reset count
                        self.cycles_finished.set(1);
                        //increment pg num
                        self.page.set(self.page.get() + 1);
                        //increment val_data
                        self.val_data.set(self.val_data.get() + 1);
                        //start new cycle
                        if self.page.get() <= MAX_PAGE_NUM {
                            self.state.set(FlashClientState::Erasing);
                            println!("==============Starting work on page {} \
                                =================", self.page.get());
                            self.command_complete(Error::CommandComplete);
                        }
                    } else {
                        println!("\t Still Cycling page {}", self.page.get());
                        //increment cycle count
                        self.cycles_finished.set(self.cycles_finished.get() + 1);
                        //increment val_data
                        self.val_data.set(self.val_data.get() + 1);
                        //continue cycle
                        self.state.set(FlashClientState::Erasing);
                        self.command_complete(Error::CommandComplete);
                    }
                }
            }

        }
    } */

}

// Sets up the testing for the flash driver.
pub fn set_read_write_test() {
    let flashClient = unsafe { &mut FLASH_CLIENT };
    let dev = unsafe { &mut flashcalw::flash_controller };

    dev.set_client(flashClient);
    print!("Calling configure...");
    dev.configure();

    //  By default the picocache ( a cache only for the flash) is turned off.
    //  However the bootloader turns it on. I will explicitly turn it on here.
    //  So if the bootloader changes, nothing breaks.
    println!("Is the picocache on? {}", flashcalw::pico_enabled());
    print!("Turning it on then...");
    flashcalw::enable_picocache(true);
    println!("It's on? {}", flashcalw::pico_enabled());

    //kicks off the interrupts
    dev.lock_page_region(0, false);
    //dev.clear_page_buffer();

}

/// This function primarily tests meta information for the chip on the
/// the FireStorm - ATSAM4LC8C. For other ATSAM4L chips, calculations using the
/// flash size asserts might fail (as they might not have the same flash size).
pub unsafe fn meta_test() {
    println!("Testing Meta Info...");
    assert_eq!(flashcalw::flash_controller.get_page_size(), 512);
    assert_eq!(flashcalw::flash_controller.get_flash_size(), 512 << 10);
    assert_eq!(flashcalw::flash_controller.get_number_pages(), 1024);
    assert_eq!(flashcalw::flash_controller.get_page_count_per_region(), 64);
    let mut pg_num = 0u32;
    for i in 0..16 {
        assert_eq!(flashcalw::flash_controller.get_page_region(pg_num as i32), i);
        assert_eq!(flashcalw::flash_controller.get_region_first_page_number(i),
            pg_num);
        pg_num += 64;
    }
    println!("Passed Meta Info...");
}
<commit_msg>Cleaning up flash dummy test<commit_after>//! A dummy flash client to test flashcalw functionality at the platform level.
/// It can be used to 'kick-off' flashcalw tests by issuing only ONE command that
/// will generate an interrupt.

use sam4l::flashcalw;
use hil::flash::{FlashController, Client, Error};
use core::cell::Cell;

// ======================================
//  Test the flash controller (using interrupts).
//  This is essentially a state-machine.
//  Note: This assumes that all the buses in the config function is on for the
//  entire time.
// ======================================

#[allow(dead_code)]
#[derive(Copy,Clone,PartialEq)]
enum FlashClientState {
    Enabling,
    ClearPageBuffer,
    WritePageBuffer,
    Writing,
    Reading,
    Erasing,
    EWRCycleStart   /* Start of the Erase, Write, Read Cycle */
}

struct FlashClient {
    state : Cell<FlashClientState>,
    page: Cell<i32>,
    region_unlocked: Cell<u32>,
    num_cycle_per_page: u32,
    val_data: Cell<u8>,
    cycles_finished: Cell<u32>
}

static mut FLASH_CLIENT : FlashClient = FlashClient {
    state: Cell::new(FlashClientState::Enabling),
    page: Cell::new(53), // Page to start
    region_unlocked: Cell::new(0),
    num_cycle_per_page: 2,  // How many times to repeat a Erase/Write/Read cycle on a page
    val_data: Cell::new(2), // Data to write to the page.
    cycles_finished: Cell::new(0)
};

const MAX_PAGE_NUM: i32 = 80;   // Page to go up to

impl Client for FlashClient {

    fn command_complete(&self, error : Error) {

        print!("Client Notified that job done in state {}", self.state.get() as u32);

        let dev = unsafe { &mut flashcalw::flash_controller };

        match self.state.get() {
            FlashClientState::Enabling => {
                    /*use support;
                    for i in 0..92_000_000 {
                        support::nop();
                    }*/
                    self.state.set(FlashClientState::EWRCycleStart);
                    println!("===========Transitioning \
                        to Erasing/Writing/Reading========");
                    dev.enable_ws1_read_opt(true);
                    // This enabled High Speed Mode using a command
                    // which generates the interrupt for the next stage.
                    dev.set_flash_waitstate_and_readmode(48000000, 0, false);
            },
            FlashClientState::Writing => {
                println!("\tWriting page {}", self.page.get());
                let data : [u8;512] = [self.val_data.get(); 512];
                dev.write_page(self.page.get(), &data);
                self.state.set(FlashClientState::Reading);
            },
            FlashClientState::Reading => {
                //  Again like WritePageBuffer, this isn't a command. But should be
                //  triggered after the write (hopefully).
                let mut pass = true;

                //  Prints out any differences in the flash page.
                println!("\treading page {}", self.page.get());
                let mut data : [u8; 512] = [0;512];
                dev.read(self.page.get() as usize * 512, 512, &mut data);

                //verify what we expect
                for i in 0..512 {
                    if data[i] != self.val_data.get() {
                        pass = false;
                        println!("\t\t======bit:{} expected {}, got {}========", i,
                           self.val_data.get(), data[i]);

                    }
                }

                if !pass {
                    for j in 0..3 {
                        println!("\treading page {}", self.page.get());
                        let mut data : [u8; 512] = [0;512];
                        dev.read(self.page.get() as usize * 512, 512, &mut data);
                        //verify what we expect
                        for i in 0..512 {
                            if data[i] != self.val_data.get() {
                            println!("\t\t\t======bit:{} expected {}, got {}========", i,
                               self.val_data.get(), data[i]);

                            }
                        }
                    }
                }

                //start cycle again
                self.state.set(FlashClientState::EWRCycleStart);
            },
            FlashClientState::Erasing => {
                println!("\tErasing page {}", self.page.get());
                dev.erase_page(self.page.get());
                self.state.set(FlashClientState::Writing);
            },
            FlashClientState::EWRCycleStart => {
                if self.page.get() <= MAX_PAGE_NUM {
                    if self.cycles_finished.get() >= self.num_cycle_per_page {
                        //reset count
                        self.cycles_finished.set(1);
                        //increment pg num
                        self.page.set(self.page.get() + 1);
                        //increment val_data
                        self.val_data.set(self.val_data.get() + 1);
                        //start new cycle
                        if self.page.get() <= MAX_PAGE_NUM {
                            self.state.set(FlashClientState::Erasing);
                            println!("==============Starting work on page {} \
                                =================", self.page.get());
                            self.command_complete(Error::CommandComplete);
                        }
                    } else {
                        println!("\t Still Cycling page {}", self.page.get());
                        //increment cycle count
                        self.cycles_finished.set(self.cycles_finished.get() + 1);
                        //increment val_data
                        self.val_data.set(self.val_data.get() + 1);
                        //continue cycle
                        self.state.set(FlashClientState::Erasing);
                        self.command_complete(Error::CommandComplete);
                    }
                }
            },
            _ => { panic!("Should never reach here!"); }

        }
    }

    /*  // This is the old state-machine controller (pre-interal interrupts)
        // Might be useful to have if debugging...
    fn command_complete(&self, error : Error) {

        print!("Client Notified that job done in state {}", self.state.get() as u32);

        let dev = unsafe { &mut flashcalw::flash_controller };

        match self.state.get() {
            FlashClientState::Enabling => {
                if self.region_unlocked.get() == 16 {
                    self.state.set(FlashClientState::EWRCycleStart);
                    println!("\t All Regions unlocked");
                    println!("===========Transitioning \
                        to Erasing/Writing/Reading========");
                    dev.enable_ws1_read_opt(true);
                    // This enabled High Speed Mode using a command
                    // which generates the interrupt for the next stage.
                    dev.set_flash_waitstate_and_readmode(48000000, 0, false);
                } else {
                    dev.lock_region(self.region_unlocked.get(), false);
                    println!("\t Unlocking Region {}", self.region_unlocked.get());
                    self.region_unlocked.set(self.region_unlocked.get() + 1);
                }
            },
            FlashClientState::Writing => {
                println!("\tWriting page {}", self.page.get());
                dev.flashcalw_write_page(self.page.get());
                self.state.set(FlashClientState::Reading);
            },
            FlashClientState::Reading => {
                //  Again like WritePageBuffer, this isn't a command. But should be
                //  triggered after the write (hopefully).
                let mut pass = true;

                //  Prints out any differences in the flash page.
                println!("\treading page {}", self.page.get());
                let mut data : [u8; 512] = [0;512];
                dev.read(self.page.get() as usize * 512, 512, &mut data);

                //verify what we expect
                for i in 0..512 {
                    if( data[i] != self.val_data.get()) {
                        pass = false;
                        println!("\t\t======bit:{} expected {}, got {}========", i,
                           self.val_data.get(), data[i]);

                    }
                }

                if(!pass) {
                    for j in 0..3 {
                        println!("\treading page {}", self.page.get());
                        let mut data : [u8; 512] = [0;512];
                        dev.read(self.page.get() as usize * 512, 512, &mut data);
                        //verify what we expect
                        for i in 0..512 {
                            if data[i] != self.val_data.get() {
                            println!("\t\t\t======bit:{} expected {}, got {}========", i,
                               self.val_data.get(), data[i]);

                            }
                        }
                    }
                }

                //start cycle again
                self.state.set(FlashClientState::EWRCycleStart);
            },
            FlashClientState::Erasing => {
                println!("\tErasing page {}", self.page.get());
                dev.flashcalw_erase_page(self.page.get(), true);
                self.state.set(FlashClientState::ClearPageBuffer);
            },
            FlashClientState::ClearPageBuffer => {
                println!("\tClearing page buffer");
                dev.clear_page_buffer();
                self.state.set(FlashClientState::WritePageBuffer);
            },
            FlashClientState::WritePageBuffer => {
                println!("\tWriting to page buffer");
                let data : [u8;512] = [self.val_data.get(); 512];
                // TODO: note this won't work b/c of the no writing to page buffer.
                //dev.write_to_page_buffer(&data, (self.page.get() * 512) as usize);
                self.state.set(FlashClientState::Writing);
                self.command_complete(Error::CommandComplete); // we need to call this here as
                                         // write_to_page_buffer isn't really a
                                         // command (thus no interrupt generated).
            },
            FlashClientState::EWRCycleStart => {
                if self.page.get() <= MAX_PAGE_NUM {
                    if self.cycles_finished.get() >= self.num_cycle_per_page {
                        //reset count
                        self.cycles_finished.set(1);
                        //increment pg num
                        self.page.set(self.page.get() + 1);
                        //increment val_data
                        self.val_data.set(self.val_data.get() + 1);
                        //start new cycle
                        if self.page.get() <= MAX_PAGE_NUM {
                            self.state.set(FlashClientState::Erasing);
                            println!("==============Starting work on page {} \
                                =================", self.page.get());
                            self.command_complete(Error::CommandComplete);
                        }
                    } else {
                        println!("\t Still Cycling page {}", self.page.get());
                        //increment cycle count
                        self.cycles_finished.set(self.cycles_finished.get() + 1);
                        //increment val_data
                        self.val_data.set(self.val_data.get() + 1);
                        //continue cycle
                        self.state.set(FlashClientState::Erasing);
                        self.command_complete(Error::CommandComplete);
                    }
                }
            }

        }
    } */

}

// Sets up the testing for the flash driver.
pub fn set_read_write_test() {
    let flashClient = unsafe { &mut FLASH_CLIENT };
    let dev = unsafe { &mut flashcalw::flash_controller };

    dev.set_client(flashClient);
    print!("Calling configure...");
    dev.configure();

    //  By default the picocache ( a cache only for the flash) is turned off.
    //  However the bootloader turns it on. I will explicitly turn it on here.
    //  So if the bootloader changes, nothing breaks.
    println!("Is the picocache on? {}", flashcalw::pico_enabled());
    print!("Turning it on then...");
    flashcalw::enable_picocache(true);
    println!("It's on? {}", flashcalw::pico_enabled());

    //kicks off the interrupts
    dev.lock_page_region(0, false);
    //dev.clear_page_buffer();

}

/// This function primarily tests meta information for the chip on the
/// the FireStorm - ATSAM4LC8C. For other ATSAM4L chips, calculations using the
/// flash size asserts might fail (as they might not have the same flash size).
pub unsafe fn meta_test() {
    println!("Testing Meta Info...");
    assert_eq!(flashcalw::flash_controller.get_page_size(), 512);
    assert_eq!(flashcalw::flash_controller.get_flash_size(), 512 << 10);
    assert_eq!(flashcalw::flash_controller.get_number_pages(), 1024);
    assert_eq!(flashcalw::flash_controller.get_page_count_per_region(), 64);
    let mut pg_num = 0u32;
    for i in 0..16 {
        assert_eq!(flashcalw::flash_controller.get_page_region(pg_num as i32), i);
        assert_eq!(flashcalw::flash_controller.get_region_first_page_number(i),
            pg_num);
        pg_num += 64;
    }
    println!("Passed Meta Info...");
}
<|endoftext|>


<commit_before>
use std::sync::Arc;
use std::io;

use connection::Connection;

//will implement later
//to integrete with the codec module
//or just self-define it.
pub trait MessageCodec {
    fn encode(&self, _: Arc<Vec<u8>>);

    fn decode(&self, _: Arc<Vec<u8>>);
}

//message handler, is a interface to
//process the coming message
pub trait MessageHandler {
    //this function defines that the callback function
    //while there is new message received
    //general logic, is parse it, then use context.send_message(token, message);
    //to response the client.
    fn on_message_received(&self, _: &Connection, _: &Arc<Vec<u8>>) -> io::Result<()>;
}
<commit_msg>Update serialize.rs<commit_after>
use std::sync::Arc;
use std::io;

use connection::Connection;

//will implement later
//to integrete with the codec module
//or just self-define it.
pub trait MessageCodec {
    fn encode(&self, _: Arc<Vec<u8>>);

    fn decode(&self, _: Arc<Vec<u8>>);
}

//message handler, is a interface to
//process the coming message

pub trait MessageHandler {
    //this function defines that the callback function
    //while there is new message received
    //general logic, is parse it, then use context.send_message(token, message);
    //to response the client.
    fn on_message_received(&self, _: &Connection, _: &Arc<Vec<u8>>) -> io::Result<()>;
}
<|endoftext|>


<commit_before>use nom::IResult;

#[derive(Debug)]
struct ZWord {
    first: u8,
    second: u8,
    third: u8,
    last_bit: u8
}

named!( take_5_bits<u8>, bits!( take_bits!( u8, 5 ) ) );

named!( take_z_word<&[u8],ZWord>,
    bits!(
        do_parse!(
            first: take_bits!( u8, 5 ) >>
            second: take_bits!( u8, 5 ) >>
            third: take_bits!( u8, 5 ) >>
            last_bit: take_bits!( u8, 1 ) >>
            (
                ZWord {
                    first: first,
                    second: second,
                    third: third,
                    last_bit: last_bit
                }
            )
        )
    )
);

fn char_from_5_bits(fiver: u8) -> char {
    let alphabet_table: Vec<char> = vec![
        ' ', '?', '?', '?', '?', '?', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
        'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' ];
    alphabet_table[fiver as usize]
}

/* The other two alphabet tables
[| " "; "?"; "?"; "?"; "?"; "?"; "A"; "B"; "C"; "D"; "E"; "F"; "G"; "H"; "I"; "J";
   "K"; "L"; "M"; "N"; "O"; "P"; "Q"; "R"; "S"; "T"; "U"; "V"; "W"; "X"; "Y"; "Z" |];
[| " "; "?"; "?"; "?"; "?"; "?"; "?"; "\n"; "0"; "1"; "2"; "3"; "4"; "5"; "6"; "7";
   "8"; "9"; "."; ","; "!"; "?"; "_"; "#"; "'"; "\""; "/"; "\\"; "-"; ":"; "("; ")" |] |]
*/

fn z_string_fragment(bytes: &[u8]) -> String {
    if let IResult::Done(_, word) = take_z_word(bytes) {
        let ZWord { first: a, second: b, third: c, last_bit: _ } = word;
        let chars = vec![
            char_from_5_bits(a),
            char_from_5_bits(b),
            char_from_5_bits(c)
        ];
        let s : String = chars.into_iter().collect();
        return s;
    }
    //TODO handle error case
    "NOT IMPLEMENTED".to_string()
}

#[test]
fn it_takes_bits() {
    let input = vec![0b10101010, 0b11110000, 0b00110011];
    let sl    = &input[..];
    assert_eq!(take_5_bits( sl ), IResult::Done(&sl[1..], 21) );
}

#[test]
fn it_can_get_letter() {
    let starts_with_six = vec! [0b00110111, 0b11110000, 0b11110001];
    let sl = &starts_with_six[..];
    let expected = 'a';
    let actual = char_from_5_bits( take_5_bits(sl).to_result().unwrap() );
    assert_eq!(expected, actual);
}

#[test]
fn it_can_parse_the() {
    let bytes_for_the = vec! [0b1100_1011u8, 0b0101_0101u8];
    let sl = &bytes_for_the[..];
    let expected = "the".to_string();
    let actual = z_string_fragment(sl);
    assert_eq!(expected, actual);
}<commit_msg>Linting and cleanup<commit_after>#![allow(dead_code)]

use nom::IResult;

#[derive(Debug)]
struct ZWord {
    first: u8,
    second: u8,
    third: u8,
    last_bit: u8
}

named!( take_5_bits<u8>, bits!( take_bits!( u8, 5 ) ) );

named!( take_z_word<&[u8],ZWord>,
    bits!(
        do_parse!(
            first: take_bits!( u8, 5 ) >>
            second: take_bits!( u8, 5 ) >>
            third: take_bits!( u8, 5 ) >>
            last_bit: take_bits!( u8, 1 ) >>
            (
                ZWord {
                    first: first,
                    second: second,
                    third: third,
                    last_bit: last_bit
                }
            )
        )
    )
);

fn char_from_5_bits(fiver: u8) -> char {
    let alphabet_table: Vec<char> = vec![
        ' ', '?', '?', '?', '?', '?', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
        'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' ];
    alphabet_table[fiver as usize]
}

/* The other two alphabet tables
[| " "; "?"; "?"; "?"; "?"; "?"; "A"; "B"; "C"; "D"; "E"; "F"; "G"; "H"; "I"; "J";
   "K"; "L"; "M"; "N"; "O"; "P"; "Q"; "R"; "S"; "T"; "U"; "V"; "W"; "X"; "Y"; "Z" |];
[| " "; "?"; "?"; "?"; "?"; "?"; "?"; "\n"; "0"; "1"; "2"; "3"; "4"; "5"; "6"; "7";
   "8"; "9"; "."; ","; "!"; "?"; "_"; "#"; "'"; "\""; "/"; "\\"; "-"; ":"; "("; ")" |] |]
*/

fn z_string_fragment(bytes: &[u8]) -> String {
    if let IResult::Done(_, word) = take_z_word(bytes) {
        let ZWord { first: a, second: b, third: c, .. } = word;
        let chars = vec![
            char_from_5_bits(a),
            char_from_5_bits(b),
            char_from_5_bits(c)
        ];
        let s : String = chars.into_iter().collect();
        return s;
    }
    //TODO handle error case
    "NOT IMPLEMENTED".to_string()
}

#[test]
fn it_takes_bits() {
    let input = vec![0b10101010, 0b11110000, 0b00110011];
    let sl    = &input[..];
    assert_eq!(take_5_bits( sl ), IResult::Done(&sl[1..], 21) );
}

#[test]
fn it_can_get_letter() {
    let starts_with_six = vec! [0b00110111, 0b11110000, 0b11110001];
    let sl = &starts_with_six[..];
    let expected = 'a';
    let actual = char_from_5_bits( take_5_bits(sl).to_result().unwrap() );
    assert_eq!(expected, actual);
}

#[test]
fn it_can_parse_the() {
    let bytes_for_the = vec! [0b1100_1011u8, 0b0101_0101u8];
    let sl = &bytes_for_the[..];
    let expected = "the".to_string();
    let actual = z_string_fragment(sl);
    assert_eq!(expected, actual);
}<|endoftext|>


<commit_before>
// This pass generates x86-64 assembly from IR.

#![allow(non_upper_case_globals)]

use crate::util::*;
use crate::*;
use std::cell::RefCell;
use std::collections::HashMap;

macro_rules! p {
    ($fmt:expr) => {
        println!($fmt);
    };
    ($fmt:expr,$($x:tt)*) => {
        println!($fmt, $( $x )*);
    };
}

macro_rules! emit {
    ($fmt:expr) => {
        print!("\t");
        println!($fmt);
    };
    ($fmt:expr,$($x:tt)*) => {
        print!("\t");
        println!($fmt, $( $x )*);
    };
}

thread_local! {
    static ESCAPED: RefCell<HashMap<char,char>> = RefCell::new(HashMap::new());
}

pub const regs: [&'static str; 7] = ["r10", "r11", "rbx", "r12", "r13", "r14", "r15"];
pub const regs8: [&'static str; 7] = ["r10b", "r11b", "bl", "r12b", "r13b", "r14b", "r15b"];
pub const regs32: [&'static str; 7] = ["r10d", "r11d", "ebx", "r12d", "r13d", "r14d", "r15d"];

pub fn num_regs() -> usize {
    return regs.len();
}

const argregs: [&'static str; 6] = ["rdi", "rsi", "rdx", "rcx", "r8", "r9"];
const argregs8: [&'static str; 6] = ["dil", "sil", "dl", "cl", "r8b", "r9b"];
const argregs32: [&'static str; 6] = ["edi", "esi", "edx", "ecx", "r8d", "r9d"];

fn init_escaped() {
    ESCAPED.with(|e| {
        let mut escaped = e.borrow_mut();

        if escaped.len() > 0 {
            return;
        }

        escaped.insert(char::from(8), 'b');  // \b
        escaped.insert(char::from(12), 'f'); // \f
        escaped.insert(char::from(10), 'n'); // \n
        escaped.insert(char::from(13), 'r'); // \r
        escaped.insert(char::from(9), 't');  // \t
        escaped.insert('\\', '\\');
        escaped.insert('\'', '\'');
        escaped.insert('\"', '"');
    })
}

fn escaped(c: char) -> Option<char> {
    ESCAPED.with(|e| {
        let escaped = e.borrow();
        match escaped.get(&c) {
            Some(esc) => Some(*esc),
            None => None,
        }
    })
}

fn backslash_escape(s: & String) -> String {
    init_escaped();

    let mut buf = String::new();
    let mut chars = s.chars();
    while let Some(c) = chars.next() {
        if let Some(esc) = escaped(c) {
            buf.push('\\');
            buf.push(esc);
        } else if c.is_ascii_graphic() || c == ' ' {
            buf.push(c);
        } else {
            buf.push_str(&format!("\\{:03o}", u32::from(c)));
        }
    }

    //buf.push(char::from(0));
    return buf;
}

fn emit_cmp(insn: &str, ir: &IR) {
    let lhs = ir.lhs as usize;
    let rhs = ir.rhs as usize;

    emit!("cmp {}, {}", regs[lhs], regs[rhs]);
    emit!("{} {}", insn, regs8[lhs]);
    emit!("movzb {}, {}", regs[lhs], regs8[lhs]);
}

fn reg(r: usize, size: i32) -> &'static str {
    match size {
        1 => regs8[r],
        4 => regs32[r],
        8 => regs[r],
        _ => panic!(),
    }
}

fn argreg(r: usize, size: i32) -> &'static str {
    match size {
        1 => argregs8[r],
        4 => argregs32[r],
        8 => argregs[r],
        _ => panic!(),
    }
}

fn emit_code(fun: &Function) {
    let ret = format!(".Lend{}", bump_nlabel());

    p!(".text");
    p!(".global {}", fun.name);
    p!("{}:", fun.name);
    emit!("push rbp");
    emit!("mov rbp, rsp");
    emit!("sub rsp, {}", roundup(fun.stacksize, 16));
    emit!("push r12");
    emit!("push r13");
    emit!("push r14");
    emit!("push r15");

    for i in 0..fun.ir.len() {
        let ir = &fun.ir[i as usize];
        let lhs = ir.lhs;
        let rhs = ir.rhs;

        match ir.op {
            IRType::IMM => {
                emit!("mov {}, {}", regs[lhs as usize], rhs);
            }
            IRType::BPREL => {
                emit!("lea {}, [rbp{}]", regs[lhs as usize], rhs);
            }
            IRType::MOV => {
                emit!("mov {}, {}", regs[lhs as usize], regs[rhs as usize]);
            }
            IRType::RETURN => {
                emit!("mov rax, {}", regs[lhs as usize]);
                emit!("jmp {}", ret);
            }
            IRType::CALL => {
                for i in 0..ir.nargs {
                    emit!("mov {}, {}", argregs[i], regs[ir.args[i] as usize]);
                }

                emit!("push r10");
                emit!("push r11");
                emit!("mov rax, 0");
                emit!("call {}", ir.name);
                emit!("pop r11");
                emit!("pop r10");

                emit!("mov {}, rax", regs[lhs as usize]);
            }
            IRType::LABEL => {
                p!(".L{}:", lhs);
            }
            IRType::LABEL_ADDR => {
                emit!("lea {}, {}", regs[lhs as usize], ir.name);
            }
            IRType::EQ => {
                emit_cmp("sete", ir)
            }
            IRType::NE => {
                emit_cmp("setne", ir)
            }
            IRType::LT => {
                emit_cmp("setl", ir)
            }
            IRType::LE => {
                emit_cmp("setle", ir)
            }
            IRType::AND => {
                emit!("and {}, {}", regs[lhs as usize], regs[rhs as usize]);
            }
            IRType::OR => {
                emit!("or {}, {}", regs[lhs as usize], regs[rhs as usize]);
            }
            IRType::XOR => {
                emit!("xor {}, {}", regs[lhs as usize], regs[rhs as usize]);
            }
            IRType::SHL => {
                emit!("mov cl, {}", regs8[rhs as usize]);
                emit!("shl {}, cl", regs[lhs as usize]);
            }
            IRType::SHR => {
                emit!("mov cl, {}", regs8[rhs as usize]);
                emit!("shr {}, cl", regs[lhs as usize]);
            }
            IRType::JMP => {
                emit!("jmp .L{}", lhs);
            }
            IRType::IF => {
                emit!("cmp {}, 0", regs[lhs as usize]);
                emit!("jne .L{}", rhs);
            }
            IRType::UNLESS => {
                emit!("cmp {}, 0", regs[lhs as usize]);
                emit!("je .L{}", rhs);
            }
            IRType::LOAD => {
                emit!("mov {}, [{}]", reg(lhs as usize, ir.size), regs[rhs as usize]);
                if ir.size == 1 {
                    emit!("movzb {}, {}", regs[lhs as usize], regs8[lhs as usize]);
                }
            }
            IRType::STORE => {
                emit!("mov [{}], {}", regs[lhs as usize], reg(rhs as usize, ir.size));
            }
            IRType::STORE_ARG => {
                emit!("mov [rbp{}], {}", lhs, argreg(rhs as usize, ir.size));
            }
            IRType::ADD => {
                emit!("add {}, {}", regs[lhs as usize], regs[rhs as usize]);
            }
            IRType::SUB => {
                emit!("sub {}, {}", regs[lhs as usize], regs[rhs as usize]);
            }
            IRType::MUL => loop {
                emit!("mov rax, {}", regs[rhs as usize]);
                emit!("imul {}", regs[lhs as usize]);
                emit!("mov {}, rax", regs[lhs as usize]);
                break;
            }
            IRType::DIV => {
                emit!("mov rax, {}", regs[lhs as usize]);
                emit!("cqo");
                emit!("idiv {}", regs[rhs as usize]);
                emit!("mov {}, rax", regs[lhs as usize]);
            }
            IRType::MOD => {
                emit!("mov rax, {}", regs[lhs as usize]);
                emit!("cqo");
                emit!("idiv {}", regs[rhs as usize]);
                emit!("mov {}, rdx", regs[lhs as usize]);
            }
            IRType::NOP => {}
            ref i => {
                panic!("unknown operator {:?}", i);
            }
        }
    }
    p!("{}:", ret);
    emit!("pop r15");
    emit!("pop r14");
    emit!("pop r13");
    emit!("pop r12");
    emit!("mov rsp, rbp");
    emit!("pop rbp");
    emit!("ret");
}

fn emit_data(var: & Var) {
    if var.data.is_some() {
        p!(".data");
        p!("{}:", var.name);
        emit!(".ascii \"{}\"", backslash_escape(&var.data.clone().unwrap()));
        return;
    }

    p!(".bss");
    p!("{}:", var.name);
    emit!(".zero {}", var.ty.len);
}

pub fn gen_x86(prog: &mut Program) {
    p!(".intel_syntax noprefix");

    for v in prog.gvars.iter() {
        emit_data(&v.borrow());
   }

    for f in prog.funcs.iter() {
        emit_code(f);
    }
}
<commit_msg>Fix a global variable bug.<commit_after>
// This pass generates x86-64 assembly from IR.

#![allow(non_upper_case_globals)]

use crate::util::*;
use crate::*;
use std::cell::RefCell;
use std::collections::HashMap;

macro_rules! p {
    ($fmt:expr) => {
        println!($fmt);
    };
    ($fmt:expr,$($x:tt)*) => {
        println!($fmt, $( $x )*);
    };
}

macro_rules! emit {
    ($fmt:expr) => {
        print!("\t");
        println!($fmt);
    };
    ($fmt:expr,$($x:tt)*) => {
        print!("\t");
        println!($fmt, $( $x )*);
    };
}

thread_local! {
    static ESCAPED: RefCell<HashMap<char,char>> = RefCell::new(HashMap::new());
}

pub const regs: [&'static str; 7] = ["r10", "r11", "rbx", "r12", "r13", "r14", "r15"];
pub const regs8: [&'static str; 7] = ["r10b", "r11b", "bl", "r12b", "r13b", "r14b", "r15b"];
pub const regs32: [&'static str; 7] = ["r10d", "r11d", "ebx", "r12d", "r13d", "r14d", "r15d"];

pub fn num_regs() -> usize {
    return regs.len();
}

const argregs: [&'static str; 6] = ["rdi", "rsi", "rdx", "rcx", "r8", "r9"];
const argregs8: [&'static str; 6] = ["dil", "sil", "dl", "cl", "r8b", "r9b"];
const argregs32: [&'static str; 6] = ["edi", "esi", "edx", "ecx", "r8d", "r9d"];

fn init_escaped() {
    ESCAPED.with(|e| {
        let mut escaped = e.borrow_mut();

        if escaped.len() > 0 {
            return;
        }

        escaped.insert(char::from(8), 'b');  // \b
        escaped.insert(char::from(12), 'f'); // \f
        escaped.insert(char::from(10), 'n'); // \n
        escaped.insert(char::from(13), 'r'); // \r
        escaped.insert(char::from(9), 't');  // \t
        escaped.insert('\\', '\\');
        escaped.insert('\'', '\'');
        escaped.insert('\"', '"');
    })
}

fn escaped(c: char) -> Option<char> {
    ESCAPED.with(|e| {
        let escaped = e.borrow();
        match escaped.get(&c) {
            Some(esc) => Some(*esc),
            None => None,
        }
    })
}

fn backslash_escape(s: & String) -> String {
    init_escaped();

    let mut buf = String::new();
    let mut chars = s.chars();
    while let Some(c) = chars.next() {
        if let Some(esc) = escaped(c) {
            buf.push('\\');
            buf.push(esc);
        } else if c.is_ascii_graphic() || c == ' ' {
            buf.push(c);
        } else {
            buf.push_str(&format!("\\{:03o}", u32::from(c)));
        }
    }

    //buf.push(char::from(0));
    return buf;
}

fn emit_cmp(insn: &str, ir: &IR) {
    let lhs = ir.lhs as usize;
    let rhs = ir.rhs as usize;

    emit!("cmp {}, {}", regs[lhs], regs[rhs]);
    emit!("{} {}", insn, regs8[lhs]);
    emit!("movzb {}, {}", regs[lhs], regs8[lhs]);
}

fn reg(r: usize, size: i32) -> &'static str {
    match size {
        1 => regs8[r],
        4 => regs32[r],
        8 => regs[r],
        _ => panic!(),
    }
}

fn argreg(r: usize, size: i32) -> &'static str {
    match size {
        1 => argregs8[r],
        4 => argregs32[r],
        8 => argregs[r],
        _ => panic!(),
    }
}

fn emit_code(fun: &Function) {
    let ret = format!(".Lend{}", bump_nlabel());

    p!(".text");
    p!(".global {}", fun.name);
    p!("{}:", fun.name);
    emit!("push rbp");
    emit!("mov rbp, rsp");
    emit!("sub rsp, {}", roundup(fun.stacksize, 16));
    emit!("push r12");
    emit!("push r13");
    emit!("push r14");
    emit!("push r15");

    for i in 0..fun.ir.len() {
        let ir = &fun.ir[i as usize];
        let lhs = ir.lhs;
        let rhs = ir.rhs;

        match ir.op {
            IRType::IMM => {
                emit!("mov {}, {}", regs[lhs as usize], rhs);
            }
            IRType::BPREL => {
                emit!("lea {}, [rbp{}]", regs[lhs as usize], rhs);
            }
            IRType::MOV => {
                emit!("mov {}, {}", regs[lhs as usize], regs[rhs as usize]);
            }
            IRType::RETURN => {
                emit!("mov rax, {}", regs[lhs as usize]);
                emit!("jmp {}", ret);
            }
            IRType::CALL => {
                for i in 0..ir.nargs {
                    emit!("mov {}, {}", argregs[i], regs[ir.args[i] as usize]);
                }

                emit!("push r10");
                emit!("push r11");
                emit!("mov rax, 0");
                emit!("call {}", ir.name);
                emit!("pop r11");
                emit!("pop r10");

                emit!("mov {}, rax", regs[lhs as usize]);
            }
            IRType::LABEL => {
                p!(".L{}:", lhs);
            }
            IRType::LABEL_ADDR => {
                emit!("lea {}, {}", regs[lhs as usize], ir.name);
            }
            IRType::EQ => {
                emit_cmp("sete", ir)
            }
            IRType::NE => {
                emit_cmp("setne", ir)
            }
            IRType::LT => {
                emit_cmp("setl", ir)
            }
            IRType::LE => {
                emit_cmp("setle", ir)
            }
            IRType::AND => {
                emit!("and {}, {}", regs[lhs as usize], regs[rhs as usize]);
            }
            IRType::OR => {
                emit!("or {}, {}", regs[lhs as usize], regs[rhs as usize]);
            }
            IRType::XOR => {
                emit!("xor {}, {}", regs[lhs as usize], regs[rhs as usize]);
            }
            IRType::SHL => {
                emit!("mov cl, {}", regs8[rhs as usize]);
                emit!("shl {}, cl", regs[lhs as usize]);
            }
            IRType::SHR => {
                emit!("mov cl, {}", regs8[rhs as usize]);
                emit!("shr {}, cl", regs[lhs as usize]);
            }
            IRType::JMP => {
                emit!("jmp .L{}", lhs);
            }
            IRType::IF => {
                emit!("cmp {}, 0", regs[lhs as usize]);
                emit!("jne .L{}", rhs);
            }
            IRType::UNLESS => {
                emit!("cmp {}, 0", regs[lhs as usize]);
                emit!("je .L{}", rhs);
            }
            IRType::LOAD => {
                emit!("mov {}, [{}]", reg(lhs as usize, ir.size), regs[rhs as usize]);
                if ir.size == 1 {
                    emit!("movzb {}, {}", regs[lhs as usize], regs8[lhs as usize]);
                }
            }
            IRType::STORE => {
                emit!("mov [{}], {}", regs[lhs as usize], reg(rhs as usize, ir.size));
            }
            IRType::STORE_ARG => {
                emit!("mov [rbp{}], {}", lhs, argreg(rhs as usize, ir.size));
            }
            IRType::ADD => {
                emit!("add {}, {}", regs[lhs as usize], regs[rhs as usize]);
            }
            IRType::SUB => {
                emit!("sub {}, {}", regs[lhs as usize], regs[rhs as usize]);
            }
            IRType::MUL => loop {
                emit!("mov rax, {}", regs[rhs as usize]);
                emit!("imul {}", regs[lhs as usize]);
                emit!("mov {}, rax", regs[lhs as usize]);
                break;
            }
            IRType::DIV => {
                emit!("mov rax, {}", regs[lhs as usize]);
                emit!("cqo");
                emit!("idiv {}", regs[rhs as usize]);
                emit!("mov {}, rax", regs[lhs as usize]);
            }
            IRType::MOD => {
                emit!("mov rax, {}", regs[lhs as usize]);
                emit!("cqo");
                emit!("idiv {}", regs[rhs as usize]);
                emit!("mov {}, rdx", regs[lhs as usize]);
            }
            IRType::NOP => {}
            ref i => {
                panic!("unknown operator {:?}", i);
            }
        }
    }
    p!("{}:", ret);
    emit!("pop r15");
    emit!("pop r14");
    emit!("pop r13");
    emit!("pop r12");
    emit!("mov rsp, rbp");
    emit!("pop rbp");
    emit!("ret");
}

fn emit_data(var: & Var) {
    if var.data.is_some() {
        p!(".data");
        p!("{}:", var.name);
        emit!(".ascii \"{}\"", backslash_escape(&var.data.clone().unwrap()));
        return;
    }

    p!(".bss");
    p!("{}:", var.name);
    emit!(".zero {}", var.ty.size);
}

pub fn gen_x86(prog: &mut Program) {
    p!(".intel_syntax noprefix");

    for v in prog.gvars.iter() {
        emit_data(&v.borrow());
   }

    for f in prog.funcs.iter() {
        emit_code(f);
    }
}
<|endoftext|>


<commit_before>pub mod song;

#[cfg(feature = "portaudio")]
pub mod sound {
    use portaudio;

    const CHANNELS: i32 = 2;
    const FRAMES: u32 = 64;
    const SAMPLE_HZ: f64 = 44_100.0;

    pub struct Sound {
        pa: portaudio::PortAudio,
    }

    impl Sound {
        pub fn new() -> Sound {
            Sound {
                pa: portaudio::PortAudio::new().unwrap(),
            }
        }

        pub fn init(&mut self) -> Result<(), portaudio::Error> {
            let settings = try!(self.pa.default_output_stream_settings::<f32>(CHANNELS, SAMPLE_HZ, FRAMES));
            let mut stream = try!(self.pa.open_non_blocking_stream(settings, callback));
            try!(stream.start());

            let callback_fn = move |pa::OutputStreamCallbackArgs { buffer, frames, .. }| {
                if let Ok(command) = receiver.try_recv() {
                    generator.process_command(command);
                }

                generator.get_samples(frames, &mut generator_buffer);
                let mut idx = 0;
                for item in generator_buffer.iter().take(frames) {
                    for _ in 0..(channel_count as usize) {
                        buffer[idx] = *item;// as SampleOutput;
                        idx += 1;
                    }
                }

                portaudio::Continue
            };

            Ok(())
        }

        pub fn load(&mut self, _filename: String) -> i32 {
            0
        }
        pub fn play(&mut self, _id: u32) {}

        pub fn stop(&mut self, _id: u32) {}
    }

}

#[cfg(feature = "sdl_audio")]
pub mod sound {
    use std::sync::mpsc;
    use px8::packet;

    use std::collections::HashMap;
    use sdl2;
    use sdl2::mixer;

    /// Minimum value for playback volume parameter.
    pub const MIN_VOLUME: f64 = 0.0;

    /// Maximum value for playback volume parameter.
    pub const MAX_VOLUME: f64 = 1.0;

    pub struct SoundInternal {
        music_tracks: HashMap<String, mixer::Music>,
        sound_tracks: HashMap<String, mixer::Chunk>,
        pub csend: mpsc::Sender<Vec<u8>>,
        crecv: mpsc::Receiver<Vec<u8>>,
    }

    impl SoundInternal {
        pub fn new() -> SoundInternal {
            let (csend, crecv) = mpsc::channel();

            SoundInternal {
                music_tracks: HashMap::new(),
                sound_tracks: HashMap::new(),
                csend: csend,
                crecv: crecv,
            }
        }

        pub fn init(&mut self) {
            let _ = mixer::init(mixer::INIT_MP3 | mixer::INIT_FLAC | mixer::INIT_MOD |
                mixer::INIT_FLUIDSYNTH | mixer::INIT_MODPLUG |
                mixer::INIT_OGG).unwrap();
            mixer::open_audio(mixer::DEFAULT_FREQUENCY,
                              mixer::DEFAULT_FORMAT,
                              mixer::DEFAULT_CHANNELS,
                              1024).unwrap();
            mixer::allocate_channels(16);
            info!("query spec => {:?}", sdl2::mixer::query_spec());
        }

        pub fn update(&mut self) {
            for sound_packet in self.crecv.try_iter() {
                info!("[SOUND] PACKET {:?}", sound_packet);
                match packet::read_packet(sound_packet).unwrap() {
                    packet::Packet::LoadMusic(res) => {
                        let filename = res.filename.clone();
                        let track = mixer::Music::from_file(filename.as_ref()).unwrap();
                        info!("[SOUND][SoundInternal] MUSIC Track {:?}", filename);
                        info!("music type => {:?}", track.get_type());
                        self.music_tracks.insert(filename, track);
                    },
                    packet::Packet::PlayMusic(res) => {
                        let filename = res.filename.clone();
                        self.music_tracks.get(&filename).expect("music: Attempted to play value that is not bound to asset").play(-1);
                    }
                    packet::Packet::StopMusic(res) => {
                        sdl2::mixer::Music::halt();
                    }
                    packet::Packet::PauseMusic(res) => {
                        sdl2::mixer::Music::pause();
                    }
                    packet::Packet::RewindMusic(res) => {
                        sdl2::mixer::Music::rewind();
                    }
                    packet::Packet::ResumeMusic(res) => {
                        sdl2::mixer::Music::resume();
                    }
                    packet::Packet::LoadSound(res) => {
                        let filename = res.filename.clone();
                        let track = mixer::Chunk::from_file(filename.as_ref()).unwrap();
                        info!("[SOUND][SoundInternal] SOUND Track {:?}", filename);
                        self.sound_tracks.insert(filename, track);
                    },
                    packet::Packet::PlaySound(res) => {
                        let filename = res.filename.clone();
                        sdl2::mixer::Channel::all().play(&self.sound_tracks.get(&filename).unwrap(), 0);
                    }
                }
            }
        }

        pub fn set_volume(&mut self, volume: f64) {
            info!("[SOUND][SoundInternal] music volume => {:?}", sdl2::mixer::Music::get_volume());
            // Map 0.0 - 1.0 to 0 - 128 (sdl2::mixer::MAX_VOLUME).
            mixer::Music::set_volume((volume.max(MIN_VOLUME).min(MAX_VOLUME) *
                mixer::MAX_VOLUME as f64) as i32);
            info!("[SOUND][SoundInternal] music volume => {:?}", sdl2::mixer::Music::get_volume());
        }

    }

    #[derive(Copy, Clone)]
    pub enum Repeat {
        /// Repeats forever.
        Forever,
        /// Repeats amount of times.
        Times(u16),
    }

    impl Repeat {
        fn to_sdl2_repeats(&self) -> i32 {
            match *self {
                Repeat::Forever => -1,
                Repeat::Times(val) => val as i32,
            }
        }
    }

    pub struct Sound {
        csend: mpsc::Sender<Vec<u8>>,
    }

    impl Sound {
        pub fn new(csend: mpsc::Sender<Vec<u8>>) -> Sound {
            Sound {
                csend: csend,
            }
        }

        // Music
        pub fn load(&mut self, filename: String) -> i32 {
            info!("[SOUND] Load music {:?}", filename);
            let p = packet::LoadMusic {
                filename: filename,
            };
            self.csend.send(packet::write_packet(p).unwrap());
            0
        }

        pub fn play(&mut self, filename: String) {
            info!("[SOUND] Play music {:?}", filename);
            let p = packet::PlayMusic {
                filename: filename,
            };
            self.csend.send(packet::write_packet(p).unwrap());
        }

        pub fn stop(&mut self) {
            info!("[SOUND] Stop music");
            let p = packet::StopMusic {
                filename: "".to_string(),
            };
            self.csend.send(packet::write_packet(p).unwrap());
        }

        pub fn pause(&mut self) {
            info!("[SOUND] Pause music");
            let p = packet::PauseMusic {
                filename: "".to_string(),
            };
            self.csend.send(packet::write_packet(p).unwrap());
        }

        pub fn resume(&mut self) {
            info!("[SOUND] Resume music");
            let p = packet::ResumeMusic {
                filename: "".to_string(),
            };
            self.csend.send(packet::write_packet(p).unwrap());
        }

        pub fn rewind(&mut self) {
            info!("[SOUND] Rewind music");
            let p = packet::RewindMusic {
                filename: "".to_string(),
            };
            self.csend.send(packet::write_packet(p).unwrap());
        }

        // Sound
        pub fn load_sound(&mut self, filename: String) -> i32 {
            info!("[SOUND] Load sound {:?}", filename);
            let p = packet::LoadSound {
                filename: filename,
            };
            self.csend.send(packet::write_packet(p).unwrap());
            0
        }

        pub fn play_sound(&mut self, filename: String) -> i32 {
            info!("[SOUND] Play sound {:?}", filename);
            let p = packet::PlaySound {
                filename: filename,
            };
            self.csend.send(packet::write_packet(p).unwrap());
            0
        }
    }
}

#[cfg(all(not(feature = "sdl_audio"), not(feature = "portaudio")))]
pub mod sound {
    use std::sync::mpsc;

    pub struct SoundInternal {
        pub csend: mpsc::Sender<Vec<u8>>,
    }

    impl SoundInternal {
        pub fn new() -> SoundInternal {
            let (csend, _) = mpsc::channel();

            SoundInternal {
                csend: csend,
            }
        }

        pub fn init(&mut self) {}
        pub fn update(&mut self) {}
    }

    pub struct Sound {
    }

    impl Sound {
        pub fn new(_csend: mpsc::Sender<Vec<u8>>) -> Sound {
            Sound {}
        }

        pub fn load(&mut self, _filename: String) -> i32 {
            0
        }
        pub fn play(&mut self, _filename: String) {}

        pub fn stop(&mut self, _filename: String) {}
    }
}
<commit_msg>continue sound support #5<commit_after>pub mod song;

#[cfg(feature = "portaudio")]
pub mod sound {
    use portaudio;

    const CHANNELS: i32 = 2;
    const FRAMES: u32 = 64;
    const SAMPLE_HZ: f64 = 44_100.0;

    pub struct Sound {
        pa: portaudio::PortAudio,
    }

    impl Sound {
        pub fn new() -> Sound {
            Sound {
                pa: portaudio::PortAudio::new().unwrap(),
            }
        }

        pub fn init(&mut self) -> Result<(), portaudio::Error> {
            let settings = try!(self.pa.default_output_stream_settings::<f32>(CHANNELS, SAMPLE_HZ, FRAMES));
            let mut stream = try!(self.pa.open_non_blocking_stream(settings, callback));
            try!(stream.start());

            let callback_fn = move |pa::OutputStreamCallbackArgs { buffer, frames, .. }| {
                if let Ok(command) = receiver.try_recv() {
                    generator.process_command(command);
                }

                generator.get_samples(frames, &mut generator_buffer);
                let mut idx = 0;
                for item in generator_buffer.iter().take(frames) {
                    for _ in 0..(channel_count as usize) {
                        buffer[idx] = *item;// as SampleOutput;
                        idx += 1;
                    }
                }

                portaudio::Continue
            };

            Ok(())
        }

        pub fn load(&mut self, _filename: String) -> i32 {
            0
        }
        pub fn play(&mut self, _id: u32) {}

        pub fn stop(&mut self, _id: u32) {}
    }

}

#[cfg(feature = "sdl_audio")]
pub mod sound {
    use std::sync::mpsc;
    use px8::packet;

    use std::collections::HashMap;
    use sdl2;
    use sdl2::mixer;

    /// Minimum value for playback volume parameter.
    pub const MIN_VOLUME: f64 = 0.0;

    /// Maximum value for playback volume parameter.
    pub const MAX_VOLUME: f64 = 1.0;

    pub struct SoundInternal {
        music_tracks: HashMap<String, mixer::Music>,
        sound_tracks: HashMap<String, mixer::Chunk>,
        pub csend: mpsc::Sender<Vec<u8>>,
        crecv: mpsc::Receiver<Vec<u8>>,
    }

    impl SoundInternal {
        pub fn new() -> SoundInternal {
            let (csend, crecv) = mpsc::channel();

            SoundInternal {
                music_tracks: HashMap::new(),
                sound_tracks: HashMap::new(),
                csend: csend,
                crecv: crecv,
            }
        }

        pub fn init(&mut self) {
            let _ = mixer::init(mixer::INIT_MP3 | mixer::INIT_FLAC | mixer::INIT_MOD |
                mixer::INIT_FLUIDSYNTH | mixer::INIT_MODPLUG |
                mixer::INIT_OGG).unwrap();
            mixer::open_audio(mixer::DEFAULT_FREQUENCY,
                              mixer::DEFAULT_FORMAT,
                              mixer::DEFAULT_CHANNELS,
                              1024).unwrap();
            mixer::allocate_channels(16);
            info!("query spec => {:?}", sdl2::mixer::query_spec());
        }

        pub fn update(&mut self) {
            for sound_packet in self.crecv.try_iter() {
                info!("[SOUND] PACKET {:?}", sound_packet);
                match packet::read_packet(sound_packet).unwrap() {
                    packet::Packet::LoadMusic(res) => {
                        let filename = res.filename.clone();
                        let track = mixer::Music::from_file(filename.as_ref()).unwrap();
                        info!("[SOUND][SoundInternal] MUSIC Track {:?}", filename);
                        info!("music type => {:?}", track.get_type());
                        self.music_tracks.insert(filename, track);
                    },
                    packet::Packet::PlayMusic(res) => {
                        let filename = res.filename.clone();
                        self.music_tracks.get(&filename).expect("music: Attempted to play value that is not bound to asset").play(-1);
                    }
                    packet::Packet::StopMusic(res) => {
                        sdl2::mixer::Music::halt();
                    }
                    packet::Packet::PauseMusic(res) => {
                        sdl2::mixer::Music::pause();
                    }
                    packet::Packet::RewindMusic(res) => {
                        sdl2::mixer::Music::rewind();
                    }
                    packet::Packet::ResumeMusic(res) => {
                        sdl2::mixer::Music::resume();
                    }
                    packet::Packet::LoadSound(res) => {
                        let filename = res.filename.clone();
                        let track = mixer::Chunk::from_file(filename.as_ref()).unwrap();
                        info!("[SOUND][SoundInternal] SOUND Track {:?}", filename);
                        self.sound_tracks.insert(filename, track);
                    },
                    packet::Packet::PlaySound(res) => {
                        let filename = res.filename.clone();
                        sdl2::mixer::Channel::all().play(&self.sound_tracks.get(&filename).unwrap(), 0);
                    }
                }
            }
        }

        pub fn set_volume(&mut self, volume: f64) {
            info!("[SOUND][SoundInternal] music volume => {:?}", sdl2::mixer::Music::get_volume());
            // Map 0.0 - 1.0 to 0 - 128 (sdl2::mixer::MAX_VOLUME).
            mixer::Music::set_volume((volume.max(MIN_VOLUME).min(MAX_VOLUME) *
                mixer::MAX_VOLUME as f64) as i32);
            info!("[SOUND][SoundInternal] music volume => {:?}", sdl2::mixer::Music::get_volume());
        }

    }

    #[derive(Copy, Clone)]
    pub enum Repeat {
        /// Repeats forever.
        Forever,
        /// Repeats amount of times.
        Times(u16),
    }

    impl Repeat {
        fn to_sdl2_repeats(&self) -> i32 {
            match *self {
                Repeat::Forever => -1,
                Repeat::Times(val) => val as i32,
            }
        }
    }

    pub struct Sound {
        csend: mpsc::Sender<Vec<u8>>,
    }

    impl Sound {
        pub fn new(csend: mpsc::Sender<Vec<u8>>) -> Sound {
            Sound {
                csend: csend,
            }
        }

        // Music
        pub fn load(&mut self, filename: String) -> i32 {
            info!("[SOUND] Load music {:?}", filename);
            let p = packet::LoadMusic {
                filename: filename,
            };
            self.csend.send(packet::write_packet(p).unwrap());
            0
        }

        pub fn play(&mut self, filename: String) {
            info!("[SOUND] Play music {:?}", filename);
            let p = packet::PlayMusic {
                filename: filename,
            };
            self.csend.send(packet::write_packet(p).unwrap());
        }

        pub fn stop(&mut self) {
            info!("[SOUND] Stop music");
            let p = packet::StopMusic {
                filename: "".to_string(),
            };
            self.csend.send(packet::write_packet(p).unwrap());
        }

        pub fn pause(&mut self) {
            info!("[SOUND] Pause music");
            let p = packet::PauseMusic {
                filename: "".to_string(),
            };
            self.csend.send(packet::write_packet(p).unwrap());
        }

        pub fn resume(&mut self) {
            info!("[SOUND] Resume music");
            let p = packet::ResumeMusic {
                filename: "".to_string(),
            };
            self.csend.send(packet::write_packet(p).unwrap());
        }

        pub fn rewind(&mut self) {
            info!("[SOUND] Rewind music");
            let p = packet::RewindMusic {
                filename: "".to_string(),
            };
            self.csend.send(packet::write_packet(p).unwrap());
        }

        // Sound
        pub fn load_sound(&mut self, filename: String) -> i32 {
            info!("[SOUND] Load sound {:?}", filename);
            let p = packet::LoadSound {
                filename: filename,
            };
            self.csend.send(packet::write_packet(p).unwrap());
            0
        }

        pub fn play_sound(&mut self, filename: String) -> i32 {
            info!("[SOUND] Play sound {:?}", filename);
            let p = packet::PlaySound {
                filename: filename,
            };
            self.csend.send(packet::write_packet(p).unwrap());
            0
        }
    }
}

#[cfg(all(not(feature = "sdl_audio"), not(feature = "portaudio")))]
pub mod sound {
    use std::sync::mpsc;

    pub struct SoundInternal {
        pub csend: mpsc::Sender<Vec<u8>>,
    }

    impl SoundInternal {
        pub fn new() -> SoundInternal {
            let (csend, _) = mpsc::channel();

            SoundInternal {
                csend: csend,
            }
        }

        pub fn init(&mut self) {}
        pub fn update(&mut self) {}
    }

    pub struct Sound {
    }

    impl Sound {
        pub fn new(_csend: mpsc::Sender<Vec<u8>>) -> Sound {
            Sound {}
        }

        // Music
        pub fn load(&mut self, _filename: String) -> i32 {
            0
        }
        pub fn play(&mut self, _filename: String) {}

        pub fn stop(&mut self) {}

        pub fn pause(&mut self) {}

        pub fn resume(&mut self) {}

        pub fn rewind(&mut self) {}

        // Sound
        pub fn load_sound(&mut self, _filename: String) -> i32 {
            0
        }

        pub fn play_sound(&mut self, _filename: String) -> i32 {
            0
        }
    }
}
<|endoftext|>