<commit_before>use crate::traps::{TrapManifest, TrapSite};

use std::slice::from_raw_parts;

// The layout of this struct is very tightly coupled to lucetc's `write_function_manifest`!
//
// Specifically, `write_function_manifest` sets up relocations on `code_addr` and `traps_addr`.
// It does not explicitly serialize a correctly formed `FunctionSpec`, because addresses
// for these fields do not exist until the object is loaded in the future.
//
// So `write_function_manifest` has implicit knowledge of the layout of this structure
// (including padding bytes between `code_len` and `traps_addr`)
#[repr(C)]
#[derive(Clone, Debug)]
pub struct FunctionSpec {
    code_addr: u64,
    code_len: u32,
    traps_addr: u64,
    traps_len: u64
}

impl FunctionSpec {
    pub fn new(code_addr: u64, code_len: u32, traps_addr: u64, traps_len: u64) -> Self {
        FunctionSpec { code_addr, code_len, traps_addr, traps_len }
    }
    pub fn code_len(&self) -> u32 {
        self.code_len
    }
    pub fn traps_len(&self) -> u64 {
        self.traps_len
    }
    pub fn contains(&self, addr: u64) -> bool {
        // TODO This *may* be an off by one - replicating the check in
        // looking up trap manifest addresses. Need to verify if the
        // length produced by Cranelift is of an inclusive or exclusive range
        addr >= self.code_addr && (addr - self.code_addr) <= (self.code_len as u64)
    }
    pub fn relative_addr(&self, addr: u64) -> Option<u32> {
        if let Some(offset) = addr.checked_sub(self.code_addr) {
            if offset < (self.code_len as u64) {
                // self.code_len is u32, so if the above check succeeded
                // offset must implicitly be <= u32::MAX - the following
                // conversion will not truncate bits
                return Some(offset as u32);
            }
        }

        None
    }
    pub fn traps(&self) -> Option<TrapManifest> {
        let traps_ptr = self.traps_addr as *const TrapSite;
        if !traps_ptr.is_null() {
            let traps_slice =
                unsafe {
                    from_raw_parts(traps_ptr, self.traps_len as usize)
                };
            Some(TrapManifest::new(traps_slice))
        } else {
            None
        }
    }
}
<commit_msg>correct off by one in interpretation of function size<commit_after>use crate::traps::{TrapManifest, TrapSite};

use std::slice::from_raw_parts;

// The layout of this struct is very tightly coupled to lucetc's `write_function_manifest`!
//
// Specifically, `write_function_manifest` sets up relocations on `code_addr` and `traps_addr`.
// It does not explicitly serialize a correctly formed `FunctionSpec`, because addresses
// for these fields do not exist until the object is loaded in the future.
//
// So `write_function_manifest` has implicit knowledge of the layout of this structure
// (including padding bytes between `code_len` and `traps_addr`)
#[repr(C)]
#[derive(Clone, Debug)]
pub struct FunctionSpec {
    code_addr: u64,
    code_len: u32,
    traps_addr: u64,
    traps_len: u64
}

impl FunctionSpec {
    pub fn new(code_addr: u64, code_len: u32, traps_addr: u64, traps_len: u64) -> Self {
        FunctionSpec { code_addr, code_len, traps_addr, traps_len }
    }
    pub fn code_len(&self) -> u32 {
        self.code_len
    }
    pub fn traps_len(&self) -> u64 {
        self.traps_len
    }
    pub fn contains(&self, addr: u64) -> bool {
        addr >= self.code_addr && (addr - self.code_addr) < (self.code_len as u64)
    }
    pub fn relative_addr(&self, addr: u64) -> Option<u32> {
        if let Some(offset) = addr.checked_sub(self.code_addr) {
            if offset < (self.code_len as u64) {
                // self.code_len is u32, so if the above check succeeded
                // offset must implicitly be <= u32::MAX - the following
                // conversion will not truncate bits
                return Some(offset as u32);
            }
        }

        None
    }
    pub fn traps(&self) -> Option<TrapManifest> {
        let traps_ptr = self.traps_addr as *const TrapSite;
        if !traps_ptr.is_null() {
            let traps_slice =
                unsafe {
                    from_raw_parts(traps_ptr, self.traps_len as usize)
                };
            Some(TrapManifest::new(traps_slice))
        } else {
            None
        }
    }
}
<|endoftext|>


<commit_before>extern mod syntax;
extern mod rustc;
extern mod extra;

use rustc::{front, metadata, driver, middle};
use rustc::middle::{ty,typeck};
use rustc::metadata::cstore;

use std::num::*;
use std::{num,str,io,os,local_data};
use std::hashmap::HashMap;

use syntax::{parse,ast,ast_map,codemap,diagnostic};
use syntax::parse::token;
use syntax::visit::{Visitor, fn_kind};
use find_ast_node::{FNodeInfoMap,safe_node_id_to_type,get_node_info_str,build_node_info_map,AstNode,find_node_tree_loc_at_byte_pos,NodeTreeLoc,astnode_expr,FNodeInfo,ToJsonStr,ToJsonStrFc,AstNodeAccessors,KindToStr,build_node_def_node_table,get_node_source};
use jumptodefmap::*;

use syntax::abi::AbiSet;

use rfindctx::{RFindCtx,ctxtkey};
pub use codemaput::{ZTextFilePos,ZTextFilePosLen,get_span_str,ToZTextFilePos,ZIndexFilePos,ToZIndexFilePos};
use rsfind::{ShowDefMode,SDM_LineCol,SDM_Line,SDM_Source,SDM_GeditCmd,MyOption};
use crosscratemap::{CrossCrateMap,CrossCrateMapItem};

pub mod find_ast_node;
pub mod text_formatting;
pub mod ioutil;
pub mod htmlwriter;
pub mod rust2html;
pub mod codemaput;
pub mod rfindctx;
pub mod rsfind;
pub mod crosscratemap;
pub mod rfserver;
pub mod util;
pub mod rf_ast_ut;
pub mod jumptodefmap;

pub macro_rules! if_some {
	($b:ident in $a:expr then $c:expr)=>(
		match $a {
			Some($b)=>$c,
			None=>{}
		}
	);
}
pub macro_rules! tlogi{
	($($a:expr),*)=>(println((file!()+":"+line!().to_str()+": " $(+$a.to_str())*) ))
}
pub macro_rules! logi{
	($($a:expr),*)=>(println(""$(+$a.to_str())*) )
}
//macro_rules! dump{ ($a:expr)=>(logi!(fmt!("%s=%?",stringify!($a),$a).indent(2,160));)}
macro_rules! dump{ ($($a:expr),*)=>
	(	{	let mut txt=~"";
			$( { txt=txt.append(
				 fmt!("%s=%?",stringify!($a),$a)+",")
				}
			);*;
			logi!(txt);
		}
	)
}

pub macro_rules! if_some {
	($b:ident in $a:expr then $c:expr)=>(
		match $a {
			Some($b)=>$c,
			None=>{}
		}
	);
	($b:ident in $a:expr then $c:expr _else $d:expr)=>(
		match $a {
			Some($b)=>$c,
			None=>{$d}
		}
	);
}

fn main() {

    use extra::getopts::*;
    use std::hashmap::HashMap;

	//test_default_arg(1,(2,3));
	//test_default_arg(1);

    let args = os::args();

    let opts = ~[
        optmulti("L"),optflag("d"),optflag("r"),optflag("j"),optflag("h"),optflag("i"),optflag("g"),optflag("w"),optflag("f"),optopt("x")
    ];

	let matches = getopts(args.tail(), opts).unwrap();
    let libs1 = matches.opt_strs("L").map(|s| Path(*s));
	let libs=if libs1.len()>0 {libs1} else {
		match (os::getenv(&"RUST_LIBS")) {
			Some(x)=>~[Path(x)],
			None=>~[]
		}
	};

	if matches.opt_present("h") {
		println("rustfind: args/useage:-");
		println(" filename.rs [-L<lib path>] : create linked html pages for sources in crate");
		println(" -r filename.rs [-L<library path>]  : dump .rfx 'crosscratemap'  containing ast nodes and jump definitions");
		println(" -x where to look for html of external crates -  :eg rustfind filename mysource.rs -x ~/rust/src\n");
		println(" cratename.rs anotherfile.rs:line:col:");
		println("    - load cratename.rs; look for definition at anotherfile.rs:line:col");
		println("    - where anotherfile.rs is assumed to be a module of the crate");
		println(" -f filename.rs:line:col : return definition reference of symbol at given position");
		println(" -i filename.rs [-L<lib path>] : interactive mode");
		println(" -g format output as gedit filepos +line filename");
		println(" debug opts:-\n");
		println(" -j filename.rs [-L<library path>]  : dump JSON map of the ast nodes & defintions");
		println(" -d filename.rs [-L<lib path>] : debug for this tool");
		println(" set RUST_LIBS for a default library search path");
	};
	if matches.free.len()>0 {
		let mut done=false;
		let filename=util::get_filename_only(matches.free[0]);
		let dc = @get_ast_and_resolve(&Path(filename), libs);
		local_data::set(ctxtkey, dc);

		if (matches.opt_present("d")) {
			debug_test(dc);
			done=true;
		} else if (matches.opt_present("j")){
			dump_json(dc);
		}
		let mut i=0;
		let lib_html_path=if matches.opt_present("x"){ matches.opt_str("x")} else {~""};
		if (matches.opt_present("f")) {
			while i<matches.free.len() {
				let mode=if matches.opt_present("g"){SDM_GeditCmd} else {SDM_Source};
				print(lookup_def_at_text_file_pos_str(dc,matches.free[i],mode).unwrap_or(~"no def found\n"));
				i+=1;
				done=true;
			}
		}
		if matches.opt_present("i") {
			rfserver::run_server(dc);
			done=true;
		}
		if matches.opt_present("r") {
			println("Writing .rfx ast nodes/cross-crate-map:-");
			write_source_as_html_and_rfx(dc,lib_html_path, rust2html::DefaultOptions,false);
			println("Writing .rfx .. done");
			done=true;
		}

		// Dump as html..
		if matches.opt_present("w") || !(done) {
			println("Creating HTML pages from source & .rfx:-");
			write_source_as_html_and_rfx(dc,lib_html_path, rust2html::DefaultOptions,true);
			println("Creating HTML pages from source.. done");
		}
	}
}

/// tags: crate,ast,parse resolve
/// Parses, resolves the given crate
fn get_ast_and_resolve(
	cpath: &std::path::PosixPath,
	libs: ~[std::path::PosixPath])
	-> RFindCtx {

    let parsesess = parse::new_parse_sess(None);
    let sessopts = @driver::session::options {
        binary: @"rustdoc",
        maybe_sysroot: Some(@std::os::self_exe_path().unwrap().pop()),
        addl_lib_search_paths: @mut libs,
        ..  (*rustc::driver::session::basic_options()).clone()
    };
	let quiet=true;
	fn no_emit(cmsp: Option<(@codemap::CodeMap, codemap::Span)>, msg: &str, lvl: syntax::diagnostic::level) {
	}

    let diagnostic_handler = syntax::diagnostic::mk_handler(None);
    let span_diagnostic_handler =
        syntax::diagnostic::mk_span_handler(diagnostic_handler, parsesess.cm);

    let mut sess = driver::driver::build_session_(sessopts, parsesess.cm,
                                                  if quiet{no_emit}else{syntax::diagnostic::emit},
                                                  span_diagnostic_handler);
	let input=driver::driver::file_input(cpath.clone());
	let cfg= driver::driver::build_configuration(sess); //was, @"", &input);

	let crate1=driver::driver::phase_1_parse_input(sess,cfg.clone(),&input);
	let crate2=driver::driver::phase_2_configure_and_expand(sess,cfg,crate1);

	let ca=driver::driver::phase_3_run_analysis_passes(sess,crate2);
    RFindCtx { crate: crate2, tycx: ca.ty_cx, sess: sess, ca:ca }
}

fn debug_test(dc:&RFindCtx) {

	// TODO: parse commandline source locations,convert to codemap locations
	//dump!(ctxt.tycx);
	logi!("==== Get tables of node-spans,def_maps,JumpToDefTable..===")
    let (node_info_map,node_def_node,jdm)=jumptodefmap::make_jdm(dc);
	println(node_info_map.to_json_str(dc));

	logi!("==== Node Definition mappings...===")
	println(node_def_node.to_json_str());

	logi!("==== JumpToDef Table ===");
	println(jdm.to_json_str());

	logi!("==== dump def table.===");
	rf_ast_ut::dump_ctxt_def_map(dc.tycx);

	logi!("==== Test node search by location...===");

	// Step a test 'cursor' src_pos through the given source file..
	let mut test_cursor=15 as uint;

	while test_cursor<500 {
		let loc = rfindctx::get_source_loc(dc,codemap::BytePos(test_cursor));

		logi!(~"\n=====Find AST node at: ",loc.file.name,":",loc.line,":",loc.col,":"," =========");

		let nodetloc = find_node_tree_loc_at_byte_pos(dc.crate,codemap::BytePos(test_cursor));
		let node_info =  get_node_info_str(dc,&nodetloc);
		dump!(node_info);
		println("node ast loc:"+(do nodetloc.map |x| { x.get_id().to_str() }).to_str());

		if_some!(id in nodetloc.last().ty_node_id() then {
			logi!("source=",get_node_source(dc.tycx, node_info_map,ast::DefId{crate:0,node:id}));
			if_some!(t in safe_node_id_to_type(dc.tycx, id) then {
				println(fmt!("typeinfo: %?",
					{let ntt= rustc::middle::ty::get(t); ntt}));
				dump!(id,dc.tycx.def_map.find(&id));
				});
			let (def_id,opt_info)= def_info_from_node_id(dc,node_info_map,id);
			if_some!(info in opt_info then{
				logi!("src node=",id," def node=",def_id,
					" span=",fmt!("%?",info.span));
				logi!("def source=", get_node_source(dc.tycx, node_info_map, def_id));
			})
		})

		test_cursor+=20;
	}

	// test byte pos from file...
	logi!("====test file:pos source lookup====");
	dump!(ZTextFilePosLen::new("test_input.rs",3-1,0,10).get_str(dc.tycx));
	dump!(ZTextFilePosLen::new("test_input.rs",9-1,0,10).get_str(dc.tycx));
	dump!(ZTextFilePosLen::new("test_input2.rs",4-1,0,10).get_str(dc.tycx));
	dump!(ZTextFilePosLen::new("test_input2.rs",11-1,0,10).get_str(dc.tycx));
	let ospan=ZTextFilePosLen::new("test_input2.rs", 10-1,0,32).to_byte_pos(dc.tycx);
	if_some!(x in ospan then {
		let (lo,hi)=x;
		logi!(get_span_str(dc.tycx, &codemap::Span{lo:lo,hi:hi,expn_info:None} ));
	});
	dump!(codemaput::zget_file_line_str(dc.tycx,"test_input2.rs",5-1));
	dump!(codemaput::zget_file_line_str(dc.tycx,"test_input.rs",9-1));

	logi!("\n====test full file:pos lookup====");
	dump!(lookup_def_at_text_file_pos(dc, &ZTextFilePos::new("test_input.rs",8-1,21),SDM_Source));println("");
	dump!(lookup_def_at_text_file_pos(dc, &ZTextFilePos::new("test_input2.rs",3-1,12),SDM_Source));println("");
	dump!(lookup_def_at_text_file_pos(dc, &ZTextFilePos::new("test_input.rs",10-1,8),SDM_Source));println("");
	dump!(lookup_def_at_text_file_pos(dc, &ZTextFilePos::new("test_input.rs",13-1,16),SDM_Source));println("");
	dump!(lookup_def_at_text_file_pos(dc, &ZTextFilePos::new("test_input.rs",11-1,10),SDM_Source));println("");

}

pub fn write_source_as_html_and_rfx(dc:&RFindCtx,lib_html_path:&str,opts:uint, write_html:bool) {

	let mut xcm:~CrossCrateMap=~HashMap::new();
	cstore::iter_crate_data(dc.tycx.cstore, |i,md| {
//		dump!(i, md.name,md.data.len(),md.cnum);
		println("loading cross crate data "+i.to_str()+" "+md.name);
		let xcm_sub=crosscratemap::read_cross_crate_map(dc, i, md.name+&".rfx",lib_html_path);
		for (k,v) in xcm_sub.iter() {xcm.insert(*k,(*v).clone());}
	});

    let (info_map,def_map,jump_map)=make_jdm(dc);
	crosscratemap::write_cross_crate_map(dc,lib_html_path,
        info_map,def_map,jump_map);
	if write_html {
		rust2html::write_source_as_html_sub(dc,info_map,jump_map,xcm,lib_html_path,opts);
	}
}

<commit_msg>fixed some more errors<commit_after>extern mod syntax;
extern mod rustc;
extern mod extra;

use rustc::{front, metadata, driver, middle};
use rustc::middle::{ty,typeck};
use rustc::metadata::cstore;

use std::num::*;
use std::{num,str,io,os,local_data};
use std::hashmap::HashMap;

use syntax::{parse,ast,ast_map,codemap,diagnostic};
use syntax::parse::token;
use syntax::visit::{Visitor, fn_kind};
use find_ast_node::{FNodeInfoMap,safe_node_id_to_type,get_node_info_str,build_node_info_map,AstNode,find_node_tree_loc_at_byte_pos,NodeTreeLoc,astnode_expr,FNodeInfo,ToJsonStr,ToJsonStrFc,AstNodeAccessors,KindToStr,build_node_def_node_table,get_node_source};
use jumptodefmap::*;

use syntax::abi::AbiSet;

use rfindctx::{RFindCtx,ctxtkey};
pub use codemaput::{ZTextFilePos,ZTextFilePosLen,get_span_str,ToZTextFilePos,ZIndexFilePos,ToZIndexFilePos};
use rsfind::{ShowDefMode,SDM_LineCol,SDM_Line,SDM_Source,SDM_GeditCmd,MyOption};
use crosscratemap::{CrossCrateMap,CrossCrateMapItem};

pub mod find_ast_node;
pub mod text_formatting;
pub mod ioutil;
pub mod htmlwriter;
pub mod rust2html;
pub mod codemaput;
pub mod rfindctx;
pub mod rsfind;
pub mod crosscratemap;
pub mod rfserver;
pub mod util;
pub mod rf_ast_ut;
pub mod jumptodefmap;

pub macro_rules! if_some {
	($b:ident in $a:expr then $c:expr)=>(
		match $a {
			Some($b)=>$c,
			None=>{}
		}
	);
}
pub macro_rules! tlogi{
	($($a:expr),*)=>(println((file!()+":"+line!().to_str()+": " $(+$a.to_str())*) ))
}
pub macro_rules! logi{
	($($a:expr),*)=>(println(""$(+$a.to_str())*) )
}
//macro_rules! dump{ ($a:expr)=>(logi!(fmt!("%s=%?",stringify!($a),$a).indent(2,160));)}
macro_rules! dump{ ($($a:expr),*)=>
	(	{	let mut txt=~"";
			$( { txt=txt.append(
				 fmt!("%s=%?",stringify!($a),$a)+",")
				}
			);*;
			logi!(txt);
		}
	)
}

pub macro_rules! if_some {
	($b:ident in $a:expr then $c:expr)=>(
		match $a {
			Some($b)=>$c,
			None=>{}
		}
	);
	($b:ident in $a:expr then $c:expr _else $d:expr)=>(
		match $a {
			Some($b)=>$c,
			None=>{$d}
		}
	);
}

fn main() {

    use extra::getopts::*;
    use std::hashmap::HashMap;

	//test_default_arg(1,(2,3));
	//test_default_arg(1);

    let args = os::args();

    let opts = ~[
        optmulti("L"),optflag("d"),optflag("r"),optflag("j"),optflag("h"),optflag("i"),optflag("g"),optflag("w"),optflag("f"),optopt("x")
    ];

	let matches = getopts(args.tail(), opts).unwrap();
    let libs1 = matches.opt_strs("L").map(|s| Path(*s));
	let libs=if libs1.len()>0 {libs1} else {
		match (os::getenv(&"RUST_LIBS")) {
			Some(x)=>~[Path(x)],
			None=>~[]
		}
	};

	if matches.opt_present("h") {
		println("rustfind: args/useage:-");
		println(" filename.rs [-L<lib path>] : create linked html pages for sources in crate");
		println(" -r filename.rs [-L<library path>]  : dump .rfx 'crosscratemap'  containing ast nodes and jump definitions");
		println(" -x where to look for html of external crates -  :eg rustfind filename mysource.rs -x ~/rust/src\n");
		println(" cratename.rs anotherfile.rs:line:col:");
		println("    - load cratename.rs; look for definition at anotherfile.rs:line:col");
		println("    - where anotherfile.rs is assumed to be a module of the crate");
		println(" -f filename.rs:line:col : return definition reference of symbol at given position");
		println(" -i filename.rs [-L<lib path>] : interactive mode");
		println(" -g format output as gedit filepos +line filename");
		println(" debug opts:-\n");
		println(" -j filename.rs [-L<library path>]  : dump JSON map of the ast nodes & defintions");
		println(" -d filename.rs [-L<lib path>] : debug for this tool");
		println(" set RUST_LIBS for a default library search path");
	};
	if matches.free.len()>0 {
		let mut done=false;
		let filename=util::get_filename_only(matches.free[0]);
		let dc = @get_ast_and_resolve(&Path(filename), libs);
		local_data::set(ctxtkey, dc);

		if (matches.opt_present("d")) {
			debug_test(dc);
			done=true;
		} else if (matches.opt_present("j")){
			dump_json(dc);
		}
		let mut i=0;
		let lib_html_path=if matches.opt_present("x"){ matches.opt_str("x").unwrap()} else {~""};
		if (matches.opt_present("f")) {
			while i<matches.free.len() {
				let mode=if matches.opt_present("g"){SDM_GeditCmd} else {SDM_Source};
				print(lookup_def_at_text_file_pos_str(dc,matches.free[i],mode).unwrap_or(~"no def found\n"));
				i+=1;
				done=true;
			}
		}
		if matches.opt_present("i") {
			rfserver::run_server(dc);
			done=true;
		}
		if matches.opt_present("r") {
			println("Writing .rfx ast nodes/cross-crate-map:-");
			write_source_as_html_and_rfx(dc,lib_html_path, rust2html::DefaultOptions,false);
			println("Writing .rfx .. done");
			done=true;
		}

		// Dump as html..
		if matches.opt_present("w") || !(done) {
			println("Creating HTML pages from source & .rfx:-");
			write_source_as_html_and_rfx(dc,lib_html_path, rust2html::DefaultOptions,true);
			println("Creating HTML pages from source.. done");
		}
	}
}

/// tags: crate,ast,parse resolve
/// Parses, resolves the given crate
fn get_ast_and_resolve(
	cpath: &std::path::PosixPath,
	libs: ~[std::path::PosixPath])
	-> RFindCtx {

    let parsesess = parse::new_parse_sess(None);
    let sessopts = @driver::session::options {
        binary: @"rustdoc",
        maybe_sysroot: Some(@std::os::self_exe_path().unwrap().pop()),
        addl_lib_search_paths: @mut libs,
        ..  (*rustc::driver::session::basic_options()).clone()
    };
	let quiet=true;
	fn no_emit(cmsp: Option<(@codemap::CodeMap, codemap::Span)>, msg: &str, lvl: syntax::diagnostic::level) {
	}

    let diagnostic_handler = syntax::diagnostic::mk_handler(None);
    let span_diagnostic_handler =
        syntax::diagnostic::mk_span_handler(diagnostic_handler, parsesess.cm);

    let mut sess = driver::driver::build_session_(sessopts, parsesess.cm,
                                                  if quiet{no_emit}else{no_emit},
                                                  span_diagnostic_handler);
	let input=driver::driver::file_input(cpath.clone());
	let cfg= driver::driver::build_configuration(sess); //was, @"", &input);

	let crate1=driver::driver::phase_1_parse_input(sess,cfg.clone(),&input);
	let crate2=driver::driver::phase_2_configure_and_expand(sess,cfg,crate1);

	let ca=driver::driver::phase_3_run_analysis_passes(sess,crate2);
    RFindCtx { crate: crate2, tycx: ca.ty_cx, sess: sess, ca:ca }
}

fn debug_test(dc:&RFindCtx) {

	// TODO: parse commandline source locations,convert to codemap locations
	//dump!(ctxt.tycx);
	logi!("==== Get tables of node-spans,def_maps,JumpToDefTable..===")
    let (node_info_map,node_def_node,jdm)=jumptodefmap::make_jdm(dc);
	println(node_info_map.to_json_str(dc));

	logi!("==== Node Definition mappings...===")
	println(node_def_node.to_json_str());

	logi!("==== JumpToDef Table ===");
	println(jdm.to_json_str());

	logi!("==== dump def table.===");
	rf_ast_ut::dump_ctxt_def_map(dc.tycx);

	logi!("==== Test node search by location...===");

	// Step a test 'cursor' src_pos through the given source file..
	let mut test_cursor=15 as uint;

	while test_cursor<500 {
		let loc = rfindctx::get_source_loc(dc,codemap::BytePos(test_cursor));

		logi!(~"\n=====Find AST node at: ",loc.file.name,":",loc.line,":",loc.col,":"," =========");

		let nodetloc = find_node_tree_loc_at_byte_pos(dc.crate,codemap::BytePos(test_cursor));
		let node_info =  get_node_info_str(dc,&nodetloc);
		dump!(node_info);
		println("node ast loc:"+(do nodetloc.map |x| { x.get_id().to_str() }).to_str());

		if_some!(id in nodetloc.last().ty_node_id() then {
			logi!("source=",get_node_source(dc.tycx, node_info_map,ast::DefId{crate:0,node:id}));
			if_some!(t in safe_node_id_to_type(dc.tycx, id) then {
				println(fmt!("typeinfo: %?",
					{let ntt= rustc::middle::ty::get(t); ntt}));
				dump!(id,dc.tycx.def_map.find(&id));
				});
			let (def_id,opt_info)= def_info_from_node_id(dc,node_info_map,id);
			if_some!(info in opt_info then{
				logi!("src node=",id," def node=",def_id,
					" span=",fmt!("%?",info.span));
				logi!("def source=", get_node_source(dc.tycx, node_info_map, def_id));
			})
		})

		test_cursor+=20;
	}

	// test byte pos from file...
	logi!("====test file:pos source lookup====");
	dump!(ZTextFilePosLen::new("test_input.rs",3-1,0,10).get_str(dc.tycx));
	dump!(ZTextFilePosLen::new("test_input.rs",9-1,0,10).get_str(dc.tycx));
	dump!(ZTextFilePosLen::new("test_input2.rs",4-1,0,10).get_str(dc.tycx));
	dump!(ZTextFilePosLen::new("test_input2.rs",11-1,0,10).get_str(dc.tycx));
	let ospan=ZTextFilePosLen::new("test_input2.rs", 10-1,0,32).to_byte_pos(dc.tycx);
	if_some!(x in ospan then {
		let (lo,hi)=x;
		logi!(get_span_str(dc.tycx, &codemap::Span{lo:lo,hi:hi,expn_info:None} ));
	});
	dump!(codemaput::zget_file_line_str(dc.tycx,"test_input2.rs",5-1));
	dump!(codemaput::zget_file_line_str(dc.tycx,"test_input.rs",9-1));

	logi!("\n====test full file:pos lookup====");
	dump!(lookup_def_at_text_file_pos(dc, &ZTextFilePos::new("test_input.rs",8-1,21),SDM_Source));println("");
	dump!(lookup_def_at_text_file_pos(dc, &ZTextFilePos::new("test_input2.rs",3-1,12),SDM_Source));println("");
	dump!(lookup_def_at_text_file_pos(dc, &ZTextFilePos::new("test_input.rs",10-1,8),SDM_Source));println("");
	dump!(lookup_def_at_text_file_pos(dc, &ZTextFilePos::new("test_input.rs",13-1,16),SDM_Source));println("");
	dump!(lookup_def_at_text_file_pos(dc, &ZTextFilePos::new("test_input.rs",11-1,10),SDM_Source));println("");

}

pub fn write_source_as_html_and_rfx(dc:&RFindCtx,lib_html_path:&str,opts:uint, write_html:bool) {

	let mut xcm:~CrossCrateMap=~HashMap::new();
	cstore::iter_crate_data(dc.tycx.cstore, |i,md| {
//		dump!(i, md.name,md.data.len(),md.cnum);
		println("loading cross crate data "+i.to_str()+" "+md.name);
		let xcm_sub=crosscratemap::read_cross_crate_map(dc, i, md.name+&".rfx",lib_html_path);
		for (k,v) in xcm_sub.iter() {xcm.insert(*k,(*v).clone());}
	});

    let (info_map,def_map,jump_map)=make_jdm(dc);
	crosscratemap::write_cross_crate_map(dc,lib_html_path,
        info_map,def_map,jump_map);
	if write_html {
		rust2html::write_source_as_html_sub(dc,info_map,jump_map,xcm,lib_html_path,opts);
	}
}

<|endoftext|>


<commit_before>#[macro_export]
macro_rules! as_item { ($i:item) => {$i} }

// Required because if-let can't be used with irrefutable patterns, so it needs
// to be special
// cased.
#[macro_export]
macro_rules! request_fns {
    ($fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty) => (
        pub fn $fn_name(&self, $($arg: $in_),*) -> $crate::Result<$out> {
            let reply = try!((self.0).rpc(&request_variant!($fn_name $($arg),*)));
            let __Reply::$fn_name(reply) = reply;
            Ok(reply)
        }
    );
    ($( $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty)*) => ( $(
        pub fn $fn_name(&self, $($arg: $in_),*) -> $crate::Result<$out> {
            let reply = try!((self.0).rpc(&request_variant!($fn_name $($arg),*)));
            if let __Reply::$fn_name(reply) = reply {
                Ok(reply)
            } else {
                Err($crate::Error::InternalError)
            }
        }
    )*);
}

// Required because enum variants with no fields can't be suffixed by parens
#[macro_export]
macro_rules! define_request {
    ($(@($($finished:tt)*))* --) => (as_item!(
            #[allow(non_camel_case_types)]
            #[derive(Debug, Serialize, Deserialize)]
            enum __Request { $($($finished)*),* }
    ););
    ($(@$finished:tt)* -- $name:ident() $($req:tt)*) =>
        (define_request!($(@$finished)* @($name) -- $($req)*););
    ($(@$finished:tt)* -- $name:ident $args: tt $($req:tt)*) =>
        (define_request!($(@$finished)* @($name $args) -- $($req)*););
    ($($started:tt)*) => (define_request!(-- $($started)*););
}

// Required because enum variants with no fields can't be suffixed by parens
#[macro_export]
macro_rules! request_variant {
    ($x:ident) => (__Request::$x);
    ($x:ident $($y:ident),+) => (__Request::$x($($y),+));
}

// The main macro that creates RPC services.
#[macro_export]
macro_rules! rpc {
    (
        mod $server:ident {

            service {
                $(
                    $(#[$attr:meta])*
                    rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty;
                )*
            }
        }
    ) => {
        rpc! {
            mod $server {

                items { }

                service {
                    $(
                        $(#[$attr])*
                        rpc $fn_name($($arg: $in_),*) -> $out;
                    )*
                }
            }
        }
    };

    (
        // Names the service
        mod $server:ident {

            // Include any desired or required items. Conflicts can arise with the following names:
            // 1. Service
            // 2. Client
            // 3. serve
            // 4. __Reply
            // 5. __Request
            items { $($i:item)* }

            // List any rpc methods: rpc foo(arg1: Arg1, ..., argN: ArgN) -> Out
            service {
                $(
                    $(#[$attr:meta])*
                    rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty;
                )*
            }
        }
    ) => {
        #[doc="A module containing an rpc service and client stub."]
        pub mod $server {

            $($i)*

            #[doc="The provided RPC service."]
            pub trait Service: Send + Sync {
                $(
                    $(#[$attr])*
                    fn $fn_name(&self, $($arg:$in_),*) -> $out;
                )*
            }

            define_request!($($fn_name($($in_),*))*);

            #[allow(non_camel_case_types)]
            #[derive(Debug, Serialize, Deserialize)]
            enum __Reply {
                $(
                    $fn_name($out),
                )*
            }

            #[doc="The client stub that makes RPC calls to the server."]
            pub struct Client($crate::protocol::Client<__Request, __Reply>);

            impl Client {
                #[doc="Create a new client that connects to the given address."]
                pub fn new<A>(addr: A, timeout: ::std::option::Option<::std::time::Duration>)
                    -> $crate::Result<Self>
                    where A: ::std::net::ToSocketAddrs,
                {
                    let inner = try!($crate::protocol::Client::new(addr, timeout));
                    Ok(Client(inner))
                }

                request_fns!($($fn_name($($arg: $in_),*) -> $out)*);
            }

            struct __Server<S: 'static + Service>(S);

            impl<S> $crate::protocol::Serve for __Server<S>
                where S: 'static + Service
            {
                type Request = __Request;
                type Reply = __Reply;
                fn serve(&self, request: __Request) -> __Reply {
                    match request {
                        $(
                            request_variant!($fn_name $($arg),*) =>
                                __Reply::$fn_name((self.0).$fn_name($($arg),*)),
                         )*
                    }
                }
            }

            #[doc="Start a running service."]
            pub fn serve<A, S>(addr: A,
                               service: S,
                               read_timeout: ::std::option::Option<::std::time::Duration>)
                -> $crate::Result<$crate::protocol::ServeHandle>
                where A: ::std::net::ToSocketAddrs,
                      S: 'static + Service
            {
                let server = ::std::sync::Arc::new(__Server(service));
                Ok(try!($crate::protocol::serve_async(addr, server, read_timeout)))
            }
        }
    }
}

#[cfg(test)]
#[allow(dead_code)]
mod test {
    use std::time::Duration;

    fn test_timeout() -> Option<Duration> {
        Some(Duration::from_secs(5))
    }

    rpc! {
        mod my_server {
            items {
                #[derive(PartialEq, Debug, Serialize, Deserialize)]
                pub struct Foo {
                    pub message: String
                }
            }

            service {
                rpc hello(foo: Foo) -> Foo;
                rpc add(x: i32, y: i32) -> i32;
            }
        }
    }

    use self::my_server::*;

    impl Service for () {
        fn hello(&self, s: Foo) -> Foo {
            Foo { message: format!("Hello, {}", &s.message) }
        }

        fn add(&self, x: i32, y: i32) -> i32 {
            x + y
        }
    }

    #[test]
    fn simple_test() {
        println!("Starting");
        let addr = "127.0.0.1:9000";
        let shutdown = my_server::serve(addr, (), test_timeout()).unwrap();
        let client = Client::new(addr, None).unwrap();
        assert_eq!(3, client.add(1, 2).unwrap());
        let foo = Foo { message: "Adam".into() };
        let want = Foo { message: format!("Hello, {}", &foo.message) };
        assert_eq!(want, client.hello(Foo { message: "Adam".into() }).unwrap());
        drop(client);
        shutdown.shutdown();
    }

    // Tests a service definition with a fn that takes no args
    rpc! {
        mod foo {
            service {
                rpc hello() -> String;
            }
        }
    }

    // Tests a service definition with an import
    rpc! {
        mod bar {
            items {
                use std::collections::HashMap;
            }

            service {
                #[doc="Hello bob"]
                rpc baz(s: String) -> HashMap<String, String>;
            }
        }
    }
}
<commit_msg>Hide helper macros from tarpc documentation<commit_after>#[doc(hidden)]
#[macro_export]
macro_rules! as_item { ($i:item) => {$i} }

// Required because if-let can't be used with irrefutable patterns, so it needs
// to be special
// cased.
#[doc(hidden)]
#[macro_export]
macro_rules! request_fns {
    ($fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty) => (
        pub fn $fn_name(&self, $($arg: $in_),*) -> $crate::Result<$out> {
            let reply = try!((self.0).rpc(&request_variant!($fn_name $($arg),*)));
            let __Reply::$fn_name(reply) = reply;
            Ok(reply)
        }
    );
    ($( $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty)*) => ( $(
        pub fn $fn_name(&self, $($arg: $in_),*) -> $crate::Result<$out> {
            let reply = try!((self.0).rpc(&request_variant!($fn_name $($arg),*)));
            if let __Reply::$fn_name(reply) = reply {
                Ok(reply)
            } else {
                Err($crate::Error::InternalError)
            }
        }
    )*);
}

// Required because enum variants with no fields can't be suffixed by parens
#[doc(hidden)]
#[macro_export]
macro_rules! define_request {
    ($(@($($finished:tt)*))* --) => (as_item!(
            #[allow(non_camel_case_types)]
            #[derive(Debug, Serialize, Deserialize)]
            enum __Request { $($($finished)*),* }
    ););
    ($(@$finished:tt)* -- $name:ident() $($req:tt)*) =>
        (define_request!($(@$finished)* @($name) -- $($req)*););
    ($(@$finished:tt)* -- $name:ident $args: tt $($req:tt)*) =>
        (define_request!($(@$finished)* @($name $args) -- $($req)*););
    ($($started:tt)*) => (define_request!(-- $($started)*););
}

// Required because enum variants with no fields can't be suffixed by parens
#[doc(hidden)]
#[macro_export]
macro_rules! request_variant {
    ($x:ident) => (__Request::$x);
    ($x:ident $($y:ident),+) => (__Request::$x($($y),+));
}

// The main macro that creates RPC services.
#[macro_export]
macro_rules! rpc {
    (
        mod $server:ident {

            service {
                $(
                    $(#[$attr:meta])*
                    rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty;
                )*
            }
        }
    ) => {
        rpc! {
            mod $server {

                items { }

                service {
                    $(
                        $(#[$attr])*
                        rpc $fn_name($($arg: $in_),*) -> $out;
                    )*
                }
            }
        }
    };

    (
        // Names the service
        mod $server:ident {

            // Include any desired or required items. Conflicts can arise with the following names:
            // 1. Service
            // 2. Client
            // 3. serve
            // 4. __Reply
            // 5. __Request
            items { $($i:item)* }

            // List any rpc methods: rpc foo(arg1: Arg1, ..., argN: ArgN) -> Out
            service {
                $(
                    $(#[$attr:meta])*
                    rpc $fn_name:ident( $( $arg:ident : $in_:ty ),* ) -> $out:ty;
                )*
            }
        }
    ) => {
        #[doc="A module containing an rpc service and client stub."]
        pub mod $server {

            $($i)*

            #[doc="The provided RPC service."]
            pub trait Service: Send + Sync {
                $(
                    $(#[$attr])*
                    fn $fn_name(&self, $($arg:$in_),*) -> $out;
                )*
            }

            define_request!($($fn_name($($in_),*))*);

            #[allow(non_camel_case_types)]
            #[derive(Debug, Serialize, Deserialize)]
            enum __Reply {
                $(
                    $fn_name($out),
                )*
            }

            #[doc="The client stub that makes RPC calls to the server."]
            pub struct Client($crate::protocol::Client<__Request, __Reply>);

            impl Client {
                #[doc="Create a new client that connects to the given address."]
                pub fn new<A>(addr: A, timeout: ::std::option::Option<::std::time::Duration>)
                    -> $crate::Result<Self>
                    where A: ::std::net::ToSocketAddrs,
                {
                    let inner = try!($crate::protocol::Client::new(addr, timeout));
                    Ok(Client(inner))
                }

                request_fns!($($fn_name($($arg: $in_),*) -> $out)*);
            }

            struct __Server<S: 'static + Service>(S);

            impl<S> $crate::protocol::Serve for __Server<S>
                where S: 'static + Service
            {
                type Request = __Request;
                type Reply = __Reply;
                fn serve(&self, request: __Request) -> __Reply {
                    match request {
                        $(
                            request_variant!($fn_name $($arg),*) =>
                                __Reply::$fn_name((self.0).$fn_name($($arg),*)),
                         )*
                    }
                }
            }

            #[doc="Start a running service."]
            pub fn serve<A, S>(addr: A,
                               service: S,
                               read_timeout: ::std::option::Option<::std::time::Duration>)
                -> $crate::Result<$crate::protocol::ServeHandle>
                where A: ::std::net::ToSocketAddrs,
                      S: 'static + Service
            {
                let server = ::std::sync::Arc::new(__Server(service));
                Ok(try!($crate::protocol::serve_async(addr, server, read_timeout)))
            }
        }
    }
}

#[cfg(test)]
#[allow(dead_code)]
mod test {
    use std::time::Duration;

    fn test_timeout() -> Option<Duration> {
        Some(Duration::from_secs(5))
    }

    rpc! {
        mod my_server {
            items {
                #[derive(PartialEq, Debug, Serialize, Deserialize)]
                pub struct Foo {
                    pub message: String
                }
            }

            service {
                rpc hello(foo: Foo) -> Foo;
                rpc add(x: i32, y: i32) -> i32;
            }
        }
    }

    use self::my_server::*;

    impl Service for () {
        fn hello(&self, s: Foo) -> Foo {
            Foo { message: format!("Hello, {}", &s.message) }
        }

        fn add(&self, x: i32, y: i32) -> i32 {
            x + y
        }
    }

    #[test]
    fn simple_test() {
        println!("Starting");
        let addr = "127.0.0.1:9000";
        let shutdown = my_server::serve(addr, (), test_timeout()).unwrap();
        let client = Client::new(addr, None).unwrap();
        assert_eq!(3, client.add(1, 2).unwrap());
        let foo = Foo { message: "Adam".into() };
        let want = Foo { message: format!("Hello, {}", &foo.message) };
        assert_eq!(want, client.hello(Foo { message: "Adam".into() }).unwrap());
        drop(client);
        shutdown.shutdown();
    }

    // Tests a service definition with a fn that takes no args
    rpc! {
        mod foo {
            service {
                rpc hello() -> String;
            }
        }
    }

    // Tests a service definition with an import
    rpc! {
        mod bar {
            items {
                use std::collections::HashMap;
            }

            service {
                #[doc="Hello bob"]
                rpc baz(s: String) -> HashMap<String, String>;
            }
        }
    }
}
<|endoftext|>


<commit_before>pub struct DBusInterface; // TODO: Implement.
<commit_msg>interface: add basic interface<commit_after>extern crate dbus;
use self::dbus::{Connection, Error, Message, MessageItem};

pub trait DBusInterface {
    fn call_method(&mut self, method: &str, conn: &Connection, m: &Message) -> Option<Message>;

    fn set_property(&mut self, prop: &str, value: MessageItem) -> Result<(), Error>;
    fn get_property(&self, prop: &str) -> Result<(), Error>;
}
<|endoftext|>


<commit_before>//! `StructureNuker` data description.
use crate::data::RoomName;

with_structure_fields_and_update_struct! {
    /// An nuker structure - a structure which can be loaded with energy and ghodium, and then
    /// fired to launch a large impact missile into another nearby room.
    #[derive(Clone, Debug, PartialEq)]
    #[serde(rename_all = "camelCase")]
    pub struct StructureNuker {
        /// The user ID of the owner of this structure.
        pub user: String,
        /// Whether or not this structure is non-functional due to a degraded controller.
        #[serde(default, rename = "off")]
        pub disabled: bool,
        /// The current amount of energy held in this structure.
        pub energy: i32,
        /// The maximum amount of energy that can be held in this structure.
        pub energy_capacity: i32,
        /// The current amount of ghodium held in this structure.
        #[serde(rename = "G")]
        pub ghodium: i32,
        /// The maximum amount of ghodium that can be held in this structure.
        #[serde(rename = "GCapacity")]
        pub ghodium_capacity: i32,
        /// The game time at which this nuker will next be able to launch a missile.
        pub cooldown_time: u32,
        /// Whether or not an attack on this structure will send an email to the owner automatically.
        pub notify_when_attacked: bool,
    }

    /// The update structure for a `StructureNuker`.
    #[derive(Clone, Debug)]
    #[serde(rename_all = "camelCase")]
    pub struct StructureNukerUpdate {
        - user: String,
        #[serde(rename = "off")]
        - disabled: bool,
        - energy: i32,
        - energy_capacity: i32,
        #[serde(rename = "G")]
        - ghodium: i32,
        #[serde(rename = "GCapacity")]
        - ghodium_capacity: i32,
        - cooldown_time: u32,
        - notify_when_attacked: bool,
    }
}

#[cfg(test)]
mod test {
    use serde::Deserialize;

    use crate::data::RoomName;

    use super::StructureNuker;

    #[test]
    fn parse_nuker() {
        let json = json!({
            "G": 5000,
            "GCapacity": 5000,
            "_id": "582582913105cae9690e9cb6",
            "cooldownTime": 19516631,
            "energy": 300000,
            "energyCapacity": 300000,
            "hits": 1000,
            "hitsMax": 1000,
            "notifyWhenAttacked": true,
            "room": "E9N23",
            "type": "nuker",
            "user": "561e4d4645f3f7244a7622e8",
            "x": 19,
            "y": 13
        });

        let obj = StructureNuker::deserialize(json).unwrap();

        assert_eq!(
            obj,
            StructureNuker {
                room: RoomName::new("E9N23").unwrap(),
                x: 19,
                y: 13,
                id: "582582913105cae9690e9cb6".to_owned(),
                hits: 1000,
                hits_max: 1000,
                energy: 300000,
                energy_capacity: 300000,
                ghodium: 5000,
                ghodium_capacity: 5000,
                cooldown_time: 19516631,
                notify_when_attacked: true,
                disabled: false,
                user: "561e4d4645f3f7244a7622e8".to_owned(),
            }
        );
    }
}
<commit_msg>Updated StructureNuker<commit_after>//! `StructureNuker` data description.
use crate::data::RoomName;
use super::super::resources::Store;

with_structure_fields_and_update_struct! {
    /// An nuker structure - a structure which can be loaded with energy and ghodium, and then
    /// fired to launch a large impact missile into another nearby room.
    #[derive(Clone, Debug, PartialEq)]
    #[serde(rename_all = "camelCase")]
    pub struct StructureNuker {
        /// The user ID of the owner of this structure.
        pub user: String,
        /// Whether or not this structure is non-functional due to a degraded controller.
        #[serde(default, rename = "off")]
        pub disabled: bool,
        /// The current amount of energy and ghodium held in this structure.
        pub store: Store,
        /// The maximum amount of energy and ghodium that can be held in this structure.
        #[serde(rename = "storeCapacityResource")]
        pub capacity_resource: Store,
        /// The game time at which this nuker will next be able to launch a missile.
        pub cooldown_time: u32,
        /// Whether or not an attack on this structure will send an email to the owner automatically.
        pub notify_when_attacked: bool,
    }

    /// The update structure for a `StructureNuker`.
    #[derive(Clone, Debug)]
    #[serde(rename_all = "camelCase")]
    pub struct StructureNukerUpdate {
        - user: String,
        #[serde(rename = "off")]
        - disabled: bool,
        - store: Store,
        #[serde(rename = "storeCapacityResource")]
        - capacity_resource: Store,
        - cooldown_time: u32,
        - notify_when_attacked: bool,
    }
}

#[cfg(test)]
mod test {
    use serde::Deserialize;

    use crate::data::RoomName;

    use super::StructureNuker;

    #[test]
    fn parse_nuker() {
        let json = json!({
          "_id": "5df45e27d1ba60a873688d18",
          "type": "nuker",
          "x": 25,
          "y": 19,
          "room": "E17S38",
          "notifyWhenAttacked": false,
          "user": "589f5265d25357e8253e3ee8",
          "store": {
            "energy": 300000,
            "G": 5000
          },
          "storeCapacityResource": {
            "energy": 300000,
            "G": 5000
          },
          "hits": 1000,
          "hitsMax": 1000,
          "cooldownTime": 30260100
        });

        let obj = StructureNuker::deserialize(json).unwrap();

        assert_eq!(
            obj,
            StructureNuker {
                room: RoomName::new("E17S38").unwrap(),
                x: 25,
                y: 19,
                id: "5df45e27d1ba60a873688d18".to_owned(),
                hits: 1000,
                hits_max: 1000,
                store: store! {
                    Energy: 300000,
                    Ghodium: 5000
                },
                capacity_resource: store! {
                    Energy: 300000,
                    Ghodium: 5000
                },
                cooldown_time: 30260100,
                notify_when_attacked: false,
                disabled: false,
                user: "589f5265d25357e8253e3ee8".to_owned(),
            }
        );
    }
}
<|endoftext|>


<commit_before>//! Describes the high-level CUDA cuDNN instance.
//!
//! If you are using the high-level interface for cuDNN, you will start
//! by initilizing a new `Cudnn` instance. This initilizes the cuDNN resources,
//! stores the handle and manages future calls.

use super::{API, Error, TensorDescriptor, FilterDescriptor, ConvolutionDescriptor};
use super::utils::{ConvolutionConfig, ScalParams};
use ffi::*;

#[derive(Debug, Clone)]
/// Provides a the high-level interface to CUDA's cuDNN.
pub struct Cudnn {
    id: isize,
}

impl Drop for Cudnn {
    #[allow(unused_must_use)]
    fn drop(&mut self) {
        API::destroy(self.id_c());
    }
}

impl Cudnn {
    /// Initializes a new CUDA cuDNN context.
    ///
    /// Make sure your current CUDA device is cuDNN enabled.
    pub fn new() -> Result<Cudnn, Error> {
        Ok(Cudnn::from_c(try!(API::init())))
    }

    /// Initializes a new CUDA cuDNN Context from its C type.
    pub fn from_c(id: cudnnHandle_t) -> Cudnn {
        Cudnn { id: id as isize }
    }

    /// Returns the id as isize.
    pub fn id(&self) -> isize {
        self.id
    }

    /// Returns the CUDA cuDNN Context as its C type.
    pub fn id_c(&self) -> cudnnHandle_t {
        self.id as cudnnHandle_t
    }

    /// Returns the version of the CUDA cuDNN library.
    pub fn version() -> usize {
        API::get_version()
    }

    /// Initializes the parameters and configurations for running CUDA cuDNN operations.
    ///
    /// This includes finding the right convolution algorithm, workspace size and allocating
    /// that workspace.
    pub fn init_convolution(
        &self,
        mem_alloc: fn(usize) -> *mut ::libc::c_void,
        src_desc: cudnnTensorDescriptor_t,
        filter_desc: cudnnFilterDescriptor_t,
        conv_desc: cudnnConvolutionDescriptor_t,
        dest_desc: cudnnTensorDescriptor_t,
    ) -> Result<ConvolutionConfig, Error> {
        let algos_fwd = try!(API::find_convolution_forward_algorithm(self.id_c(), filter_desc, src_desc, conv_desc, dest_desc));
        let workspace_size_fwd = try!(API::get_convolution_forward_workspace_size(self.id_c(), algos_fwd[0].algo, filter_desc, src_desc, conv_desc, dest_desc));

        let algos_bwd = try!(API::find_convolution_backward_data_algorithm(self.id_c(), filter_desc, src_desc, conv_desc, dest_desc));
        let workspace_size_bwd = try!(API::get_convolution_backward_data_workspace_size(self.id_c(), algos_bwd[0].algo, filter_desc, src_desc, conv_desc, dest_desc));

        Ok(ConvolutionConfig::new(
            algos_fwd[0].algo, mem_alloc(workspace_size_fwd), workspace_size_fwd,
            algos_bwd[0].algo, mem_alloc(workspace_size_bwd), workspace_size_bwd,
        ))
    }

    /// Computes the forward Sigmoid Activation function.
    ///
    /// Writes the result of the computation to `dest_data`.
    pub fn sigmoid_forward<T>(
        &self,
        src_desc: &TensorDescriptor,
        src_data: *const ::libc::c_void,
        dest_desc: &TensorDescriptor,
        dest_data: *mut ::libc::c_void,
        scale: ScalParams<T>,
    ) -> Result<(), Error> {
        API::activation_forward(
            self.id_c(),
            cudnnActivationMode_t::CUDNN_ACTIVATION_SIGMOID,
            scale.a, src_desc.id_c(), src_data,
            scale.b, dest_desc.id_c(), dest_data
        )
    }

    /// Computes the backward Sigmoid Activation function.
    ///
    /// Writes the result of the computation to `dest_diff_data`.
    pub fn sigmoid_backward<T>(
        &self,
        src_desc: &TensorDescriptor,
        src_data: *const ::libc::c_void,
        src_diff_desc: &TensorDescriptor,
        src_diff_data: *const ::libc::c_void,
        dest_desc: TensorDescriptor,
        dest_data: *const ::libc::c_void,
        dest_diff_desc: TensorDescriptor,
        dest_diff_data: *mut ::libc::c_void,
        scale: ScalParams<T>,
    ) -> Result<(), Error> {
        API::activation_backward(
            self.id_c(),
            cudnnActivationMode_t::CUDNN_ACTIVATION_SIGMOID,
            scale.a, src_desc.id_c(), src_data, src_diff_desc.id_c(), src_diff_data,
            scale.b, dest_desc.id_c(), dest_data, dest_diff_desc.id_c(), dest_diff_data
        )
    }

    /// Computes the forward Rectified Linear Activation function.
    ///
    /// Writes the result of the computation to `dest_data`.
    pub fn relu_forward<T>(
        &self,
        src_desc: TensorDescriptor,
        src_data: *const ::libc::c_void,
        dest_desc: TensorDescriptor,
        dest_data: *mut ::libc::c_void,
        scale: ScalParams<T>,
    ) -> Result<(), Error> {
        API::activation_forward(
            self.id_c(),
            cudnnActivationMode_t::CUDNN_ACTIVATION_RELU,
            scale.a, src_desc.id_c(), src_data,
            scale.b, dest_desc.id_c(), dest_data
        )
    }

    /// Computes the backward Rectified Linear Activation function.
    ///
    /// Writes the result of the computation to `dest_diff_data`.
    pub fn relu_backward<T>(
        &self,
        src_desc: &TensorDescriptor,
        src_data: *const ::libc::c_void,
        src_diff_desc: &TensorDescriptor,
        src_diff_data: *const ::libc::c_void,
        dest_desc: TensorDescriptor,
        dest_data: *const ::libc::c_void,
        dest_diff_desc: TensorDescriptor,
        dest_diff_data: *mut ::libc::c_void,
        scale: ScalParams<T>,
    ) -> Result<(), Error> {
        API::activation_backward(
            self.id_c(),
            cudnnActivationMode_t::CUDNN_ACTIVATION_RELU,
            scale.a, src_desc.id_c(), src_data, src_diff_desc.id_c(), src_diff_data,
            scale.b, dest_desc.id_c(), dest_data, dest_diff_desc.id_c(), dest_diff_data
        )
    }

    /// Computes the forward Hyperbolic Tangent Activation function.
    ///
    /// Writes the result of the computation to `dest_data`.
    pub fn tanh_forward<T>(
        &self,
        src_desc: TensorDescriptor,
        src_data: *const ::libc::c_void,
        dest_desc: TensorDescriptor,
        dest_data: *mut ::libc::c_void,
        scale: ScalParams<T>,
    ) -> Result<(), Error> {
        API::activation_forward(
            self.id_c(),
            cudnnActivationMode_t::CUDNN_ACTIVATION_TANH,
            scale.a, src_desc.id_c(), src_data,
            scale.b, dest_desc.id_c(), dest_data
        )
    }

    /// Computes the backward Hyperbolic Tangent Activation function.
    ///
    /// Writes the result of the computation to `dest_diff_data`.
    pub fn tanh_backward<T>(
        &self,
        src_desc: &TensorDescriptor,
        src_data: *const ::libc::c_void,
        src_diff_desc: &TensorDescriptor,
        src_diff_data: *const ::libc::c_void,
        dest_desc: TensorDescriptor,
        dest_data: *const ::libc::c_void,
        dest_diff_desc: TensorDescriptor,
        dest_diff_data: *mut ::libc::c_void,
        scale: ScalParams<T>,
    ) -> Result<(), Error> {
        API::activation_backward(
            self.id_c(),
            cudnnActivationMode_t::CUDNN_ACTIVATION_TANH,
            scale.a, src_desc.id_c(), src_data, src_diff_desc.id_c(), src_diff_data,
            scale.b, dest_desc.id_c(), dest_data, dest_diff_desc.id_c(), dest_diff_data
        )
    }

    /// Computes the forward Convolution function.
    ///
    /// Writes the result of the computation to `dest_data`.
    pub fn convolution_forward<T>(
        &self,
        conv_config: &ConvolutionConfig,
        conv_desc: &ConvolutionDescriptor,
        src_desc: &TensorDescriptor,
        src_data: *const ::libc::c_void,
        filter_desc: &FilterDescriptor,
        filter_data: *const ::libc::c_void,
        dest_desc: TensorDescriptor,
        dest_data: *mut ::libc::c_void,
        scale: ScalParams<T>,
    ) -> Result<(), Error> {
        API::convolution_forward(
            self.id_c(),
            *conv_config.forward_algo(), conv_desc.id_c(), *conv_config.forward_workspace(), *conv_config.forward_workspace_size(),
            scale.a, src_desc.id_c(), src_data, filter_desc.id_c(), filter_data,
            scale.b, dest_desc.id_c(), dest_data
        )
    }

    /// Computes the backward Convolution function w.r.t the data.
    ///
    /// Writes the result of the computation to `dest_data`.
    pub fn convolution_backward<T>(
        &self,
        conv_config: &ConvolutionConfig,
        conv_desc: &ConvolutionDescriptor,
        src_diff_desc: &TensorDescriptor,
        src_diff_data: *const ::libc::c_void,
        filter_desc: &FilterDescriptor,
        filter_data: *const ::libc::c_void,
        dest_grad_desc: TensorDescriptor,
        dest_grad_data: *mut ::libc::c_void,
        scale: ScalParams<T>,
    ) -> Result<(), Error> {
        API::convolution_backward_data(
            self.id_c(),
            *conv_config.backward_algo(), conv_desc.id_c(), *conv_config.backward_workspace(), *conv_config.backward_workspace_size(),
            scale.a, src_diff_desc.id_c(), src_diff_data, filter_desc.id_c(), filter_data,
            scale.b, dest_grad_desc.id_c(), dest_grad_data
        )
    }
}
<commit_msg>perf/lib: make cudnn take pointers<commit_after>//! Describes the high-level CUDA cuDNN instance.
//!
//! If you are using the high-level interface for cuDNN, you will start
//! by initilizing a new `Cudnn` instance. This initilizes the cuDNN resources,
//! stores the handle and manages future calls.

use super::{API, Error, TensorDescriptor, FilterDescriptor, ConvolutionDescriptor};
use super::utils::{ConvolutionConfig, ScalParams};
use ffi::*;

#[derive(Debug, Clone)]
/// Provides a the high-level interface to CUDA's cuDNN.
pub struct Cudnn {
    id: isize,
}

impl Drop for Cudnn {
    #[allow(unused_must_use)]
    fn drop(&mut self) {
        API::destroy(self.id_c());
    }
}

impl Cudnn {
    /// Initializes a new CUDA cuDNN context.
    ///
    /// Make sure your current CUDA device is cuDNN enabled.
    pub fn new() -> Result<Cudnn, Error> {
        Ok(Cudnn::from_c(try!(API::init())))
    }

    /// Initializes a new CUDA cuDNN Context from its C type.
    pub fn from_c(id: cudnnHandle_t) -> Cudnn {
        Cudnn { id: id as isize }
    }

    /// Returns the id as isize.
    pub fn id(&self) -> isize {
        self.id
    }

    /// Returns the CUDA cuDNN Context as its C type.
    pub fn id_c(&self) -> cudnnHandle_t {
        self.id as cudnnHandle_t
    }

    /// Returns the version of the CUDA cuDNN library.
    pub fn version() -> usize {
        API::get_version()
    }

    /// Initializes the parameters and configurations for running CUDA cuDNN operations.
    ///
    /// This includes finding the right convolution algorithm, workspace size and allocating
    /// that workspace.
    pub fn init_convolution(
        &self,
        mem_alloc: fn(usize) -> *mut ::libc::c_void,
        src_desc: cudnnTensorDescriptor_t,
        filter_desc: cudnnFilterDescriptor_t,
        conv_desc: cudnnConvolutionDescriptor_t,
        dest_desc: cudnnTensorDescriptor_t,
    ) -> Result<ConvolutionConfig, Error> {
        let algos_fwd = try!(API::find_convolution_forward_algorithm(self.id_c(), filter_desc, src_desc, conv_desc, dest_desc));
        let workspace_size_fwd = try!(API::get_convolution_forward_workspace_size(self.id_c(), algos_fwd[0].algo, filter_desc, src_desc, conv_desc, dest_desc));

        let algos_bwd = try!(API::find_convolution_backward_data_algorithm(self.id_c(), filter_desc, src_desc, conv_desc, dest_desc));
        let workspace_size_bwd = try!(API::get_convolution_backward_data_workspace_size(self.id_c(), algos_bwd[0].algo, filter_desc, src_desc, conv_desc, dest_desc));

        Ok(ConvolutionConfig::new(
            algos_fwd[0].algo, mem_alloc(workspace_size_fwd), workspace_size_fwd,
            algos_bwd[0].algo, mem_alloc(workspace_size_bwd), workspace_size_bwd,
        ))
    }

    /// Computes the forward Sigmoid Activation function.
    ///
    /// Writes the result of the computation to `dest_data`.
    pub fn sigmoid_forward<T>(
        &self,
        src_desc: &TensorDescriptor,
        src_data: *const ::libc::c_void,
        dest_desc: &TensorDescriptor,
        dest_data: *mut ::libc::c_void,
        scale: ScalParams<T>,
    ) -> Result<(), Error> {
        API::activation_forward(
            self.id_c(),
            cudnnActivationMode_t::CUDNN_ACTIVATION_SIGMOID,
            scale.a, src_desc.id_c(), src_data,
            scale.b, dest_desc.id_c(), dest_data
        )
    }

    /// Computes the backward Sigmoid Activation function.
    ///
    /// Writes the result of the computation to `dest_diff_data`.
    pub fn sigmoid_backward<T>(
        &self,
        src_desc: &TensorDescriptor,
        src_data: *const ::libc::c_void,
        src_diff_desc: &TensorDescriptor,
        src_diff_data: *const ::libc::c_void,
        dest_desc: &TensorDescriptor,
        dest_data: *const ::libc::c_void,
        dest_diff_desc: &TensorDescriptor,
        dest_diff_data: *mut ::libc::c_void,
        scale: ScalParams<T>,
    ) -> Result<(), Error> {
        API::activation_backward(
            self.id_c(),
            cudnnActivationMode_t::CUDNN_ACTIVATION_SIGMOID,
            scale.a, src_desc.id_c(), src_data, src_diff_desc.id_c(), src_diff_data,
            scale.b, dest_desc.id_c(), dest_data, dest_diff_desc.id_c(), dest_diff_data
        )
    }

    /// Computes the forward Rectified Linear Activation function.
    ///
    /// Writes the result of the computation to `dest_data`.
    pub fn relu_forward<T>(
        &self,
        src_desc: &TensorDescriptor,
        src_data: *const ::libc::c_void,
        dest_desc: &TensorDescriptor,
        dest_data: *mut ::libc::c_void,
        scale: ScalParams<T>,
    ) -> Result<(), Error> {
        API::activation_forward(
            self.id_c(),
            cudnnActivationMode_t::CUDNN_ACTIVATION_RELU,
            scale.a, src_desc.id_c(), src_data,
            scale.b, dest_desc.id_c(), dest_data
        )
    }

    /// Computes the backward Rectified Linear Activation function.
    ///
    /// Writes the result of the computation to `dest_diff_data`.
    pub fn relu_backward<T>(
        &self,
        src_desc: &TensorDescriptor,
        src_data: *const ::libc::c_void,
        src_diff_desc: &TensorDescriptor,
        src_diff_data: *const ::libc::c_void,
        dest_desc: &TensorDescriptor,
        dest_data: *const ::libc::c_void,
        dest_diff_desc: &TensorDescriptor,
        dest_diff_data: *mut ::libc::c_void,
        scale: ScalParams<T>,
    ) -> Result<(), Error> {
        API::activation_backward(
            self.id_c(),
            cudnnActivationMode_t::CUDNN_ACTIVATION_RELU,
            scale.a, src_desc.id_c(), src_data, src_diff_desc.id_c(), src_diff_data,
            scale.b, dest_desc.id_c(), dest_data, dest_diff_desc.id_c(), dest_diff_data
        )
    }

    /// Computes the forward Hyperbolic Tangent Activation function.
    ///
    /// Writes the result of the computation to `dest_data`.
    pub fn tanh_forward<T>(
        &self,
        src_desc: &TensorDescriptor,
        src_data: *const ::libc::c_void,
        dest_desc: &TensorDescriptor,
        dest_data: *mut ::libc::c_void,
        scale: ScalParams<T>,
    ) -> Result<(), Error> {
        API::activation_forward(
            self.id_c(),
            cudnnActivationMode_t::CUDNN_ACTIVATION_TANH,
            scale.a, src_desc.id_c(), src_data,
            scale.b, dest_desc.id_c(), dest_data
        )
    }

    /// Computes the backward Hyperbolic Tangent Activation function.
    ///
    /// Writes the result of the computation to `dest_diff_data`.
    pub fn tanh_backward<T>(
        &self,
        src_desc: &TensorDescriptor,
        src_data: *const ::libc::c_void,
        src_diff_desc: &TensorDescriptor,
        src_diff_data: *const ::libc::c_void,
        dest_desc: &TensorDescriptor,
        dest_data: *const ::libc::c_void,
        dest_diff_desc: &TensorDescriptor,
        dest_diff_data: *mut ::libc::c_void,
        scale: ScalParams<T>,
    ) -> Result<(), Error> {
        API::activation_backward(
            self.id_c(),
            cudnnActivationMode_t::CUDNN_ACTIVATION_TANH,
            scale.a, src_desc.id_c(), src_data, src_diff_desc.id_c(), src_diff_data,
            scale.b, dest_desc.id_c(), dest_data, dest_diff_desc.id_c(), dest_diff_data
        )
    }

    /// Computes the forward Convolution function.
    ///
    /// Writes the result of the computation to `dest_data`.
    pub fn convolution_forward<T>(
        &self,
        conv_config: &ConvolutionConfig,
        conv_desc: &ConvolutionDescriptor,
        src_desc: &TensorDescriptor,
        src_data: *const ::libc::c_void,
        filter_desc: &FilterDescriptor,
        filter_data: *const ::libc::c_void,
        dest_desc: &TensorDescriptor,
        dest_data: *mut ::libc::c_void,
        scale: ScalParams<T>,
    ) -> Result<(), Error> {
        API::convolution_forward(
            self.id_c(),
            *conv_config.forward_algo(), conv_desc.id_c(), *conv_config.forward_workspace(), *conv_config.forward_workspace_size(),
            scale.a, src_desc.id_c(), src_data, filter_desc.id_c(), filter_data,
            scale.b, dest_desc.id_c(), dest_data
        )
    }

    /// Computes the backward Convolution function w.r.t the data.
    ///
    /// Writes the result of the computation to `dest_data`.
    pub fn convolution_backward<T>(
        &self,
        conv_config: &ConvolutionConfig,
        conv_desc: &ConvolutionDescriptor,
        src_diff_desc: &TensorDescriptor,
        src_diff_data: *const ::libc::c_void,
        filter_desc: &FilterDescriptor,
        filter_data: *const ::libc::c_void,
        dest_grad_desc: &TensorDescriptor,
        dest_grad_data: *mut ::libc::c_void,
        scale: ScalParams<T>,
    ) -> Result<(), Error> {
        API::convolution_backward_data(
            self.id_c(),
            *conv_config.backward_algo(), conv_desc.id_c(), *conv_config.backward_workspace(), *conv_config.backward_workspace_size(),
            scale.a, src_diff_desc.id_c(), src_diff_data, filter_desc.id_c(), filter_data,
            scale.b, dest_grad_desc.id_c(), dest_grad_data
        )
    }
}
<|endoftext|>


<commit_before>use dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize};
use event::Event;
use event_loop::{ControlFlow, EventLoopWindowTarget as RootELW, EventLoopClosed};
use icon::Icon;
use monitor::{MonitorHandle as RootMH};
use window::{CreationError, MouseCursor, WindowAttributes};

use std::collections::vec_deque::IntoIter as VecDequeIter;
use std::marker::PhantomData;

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DeviceId;

impl DeviceId {
    pub unsafe fn dummy() -> Self {
        DeviceId
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct MonitorHandle;

impl MonitorHandle {
    pub fn get_hidpi_factor(&self) -> f64 {
        unimplemented!();
    }

    pub fn get_position(&self) -> PhysicalPosition {
        unimplemented!();
    }

    pub fn get_dimensions(&self) -> PhysicalSize {
        unimplemented!();
    }

    pub fn get_name(&self) -> Option<String> {
        unimplemented!();
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct WindowId;

impl WindowId {
    pub unsafe fn dummy() -> WindowId {
        WindowId
    }
}

pub struct Window;

impl Window {
    // TODO: type of window_target
    pub fn new<T>(target: &EventLoopWindowTarget<T>, window: WindowAttributes, platform: PlatformSpecificWindowBuilderAttributes) -> Result<Self, CreationError> {
        unimplemented!();
    }

    pub fn set_title(&self, title: &str) {
        unimplemented!();
    }

    pub fn show(&self) {
        unimplemented!();
    }

    pub fn hide(&self) {
        unimplemented!();
    }

    pub fn request_redraw(&self) {
        unimplemented!();
    }

    pub fn get_position(&self) -> Option<LogicalPosition> {
        unimplemented!();
    }

    pub fn get_inner_position(&self) -> Option<LogicalPosition> {
        unimplemented!();
    }

    pub fn set_position(&self, position: LogicalPosition) {
        unimplemented!();
    }

    #[inline]
    pub fn get_inner_size(&self) -> Option<LogicalSize> {
        unimplemented!();
    }

    #[inline]
    pub fn get_outer_size(&self) -> Option<LogicalSize> {
        unimplemented!();
    }

    #[inline]
    pub fn set_inner_size(&self, size: LogicalSize) {
        unimplemented!();
    }

    #[inline]
    pub fn set_min_dimensions(&self, dimensions: Option<LogicalSize>) {
        unimplemented!();
    }

    #[inline]
    pub fn set_max_dimensions(&self, dimensions: Option<LogicalSize>) {
        unimplemented!();
    }

    #[inline]
    pub fn set_resizable(&self, resizable: bool) {
        unimplemented!();
    }

    #[inline]
    pub fn get_hidpi_factor(&self) -> f64 {
        unimplemented!();
    }

    #[inline]
    pub fn set_cursor(&self, cursor: MouseCursor) {
        unimplemented!();
    }

    #[inline]
    pub fn set_cursor_position(&self, position: LogicalPosition) -> Result<(), String> {
        unimplemented!();
    }

    #[inline]
    pub fn grab_cursor(&self, grab: bool) -> Result<(), String> {
        unimplemented!();
    }

    #[inline]
    pub fn hide_cursor(&self, hide: bool) {
        unimplemented!();
    }

    #[inline]
    pub fn set_maximized(&self, maximized: bool) {
        unimplemented!();
    }

    #[inline]
    pub fn set_fullscreen(&self, monitor: Option<RootMH>) {
        unimplemented!();
    }

    #[inline]
    pub fn set_decorations(&self, decorations: bool) {
        unimplemented!();
    }

    #[inline]
    pub fn set_always_on_top(&self, always_on_top: bool) {
        unimplemented!();
    }

    #[inline]
    pub fn set_window_icon(&self, window_icon: Option<Icon>) {
        unimplemented!();
    }

    #[inline]
    pub fn set_ime_spot(&self, position: LogicalPosition) {
        unimplemented!();
    }

    #[inline]
    pub fn get_current_monitor(&self) -> RootMH {
        unimplemented!();
    }

    #[inline]
    pub fn get_available_monitors(&self) -> VecDequeIter<MonitorHandle> {
        unimplemented!();
    }

    #[inline]
    pub fn get_primary_monitor(&self) -> MonitorHandle {
        unimplemented!();
    }

    #[inline]
    pub fn id(&self) -> WindowId {
        unimplemented!();
    }
}

pub struct EventLoop<T> {
    _phantom: PhantomData<T>
}

impl<T> EventLoop<T> {
    pub fn new() -> Self {
        unimplemented!();
    }

    pub fn get_available_monitors(&self) -> VecDequeIter<MonitorHandle> {
        unimplemented!();
    }

    pub fn get_primary_monitor(&self) -> MonitorHandle {
        unimplemented!();
    }

    pub fn run<F>(mut self, event_handler: F) -> !
        where F: 'static + FnMut(Event<T>, &RootELW<T>, &mut ControlFlow)
    {
        unimplemented!();
    }

    pub fn create_proxy(&self) -> EventLoopProxy<T> {
        unimplemented!();
    }

    pub fn window_target(&self) -> &RootELW<T> {
        unimplemented!();
        /*&EventLoopWindowTarget {
            p: self.event_loop.window_target(),
            _marker: std::marker::PhantomData
        }*/
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct EventLoopProxy<T> {
    _phantom: PhantomData<T>
}

impl<T> EventLoopProxy<T> {
    pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed> {
        unimplemented!();
    }
}

pub struct EventLoopWindowTarget<T> {
    _phantom: PhantomData<T>
}

#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PlatformSpecificWindowBuilderAttributes;

<commit_msg>Implemented a few easy methods<commit_after>use dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize};
use event::Event;
use event_loop::{ControlFlow, EventLoopWindowTarget as RootELW, EventLoopClosed};
use icon::Icon;
use monitor::{MonitorHandle as RootMH};
use window::{CreationError, MouseCursor, WindowAttributes};
use stdweb::{
    document,
    web::html_element::CanvasElement
};
use std::cell::Cell;
use std::collections::VecDeque;
use std::collections::vec_deque::IntoIter as VecDequeIter;
use std::marker::PhantomData;
use std::rc::Rc;

// TODO: dpi
// TODO: pointer locking (stdweb PR required)
// TODO: should there be a maximization / fullscreen API?

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DeviceId;

impl DeviceId {
    pub unsafe fn dummy() -> Self {
        DeviceId
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct MonitorHandle;

impl MonitorHandle {
    pub fn get_hidpi_factor(&self) -> f64 {
        unimplemented!();
    }

    pub fn get_position(&self) -> PhysicalPosition {
        unimplemented!();
    }

    pub fn get_dimensions(&self) -> PhysicalSize {
        unimplemented!();
    }

    pub fn get_name(&self) -> Option<String> {
        unimplemented!();
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct WindowId;

impl WindowId {
    pub unsafe fn dummy() -> WindowId {
        WindowId
    }
}

pub struct Window {
    canvas: CanvasElement,
    monitors: VecDeque<MonitorHandle>
}

impl Window {
    // TODO: type of window_target
    pub fn new<T>(target: &EventLoopWindowTarget<T>, window: WindowAttributes, platform: PlatformSpecificWindowBuilderAttributes) -> Result<Self, CreationError> {
        unimplemented!();
    }

    pub fn set_title(&self, title: &str) {
        document().set_title(title);
    }

    pub fn show(&self) {
        // Intentionally a no-op
    }

    pub fn hide(&self) {
        // Intentionally a no-op
    }

    pub fn request_redraw(&self) {
        // TODO: what does this mean
        unimplemented!();
    }

    pub fn get_position(&self) -> Option<LogicalPosition> {
        let bounds = canvas.get_bouding_client_rect();
        Some(LogicalPosition {
            x: bounds.get_x(),
            y: bounds.get_y(),
        })
    }

    pub fn get_inner_position(&self) -> Option<LogicalPosition> {
        self.get_inner_position()
    }

    pub fn set_position(&self, position: LogicalPosition) {
        // TODO: use CSS?
        unimplemented!();
    }

    #[inline]
    pub fn get_inner_size(&self) -> Option<LogicalSize> {
        Some(LogicalSize {
            x: self.canvas.width() as f64
            y: self.canvas.height() as f64
        })
    }

    #[inline]
    pub fn get_outer_size(&self) -> Option<LogicalSize> {
        Some(LogicalSize {
            x: self.canvas.width() as f64
            y: self.canvas.height() as f64
        })
    }

    #[inline]
    pub fn set_inner_size(&self, size: LogicalSize) {
        self.canvas.set_width(size.x as u32);
        self.canvas.set_height(size.y as u32);
    }

    #[inline]
    pub fn set_min_dimensions(&self, _dimensions: Option<LogicalSize>) {
        // Intentionally a no-op: users can't resize canvas elements
    }

    #[inline]
    pub fn set_max_dimensions(&self, _dimensions: Option<LogicalSize>) {
        // Intentionally a no-op: users can't resize canvas elements
    }

    #[inline]
    pub fn set_resizable(&self, _resizable: bool) {
        // Intentionally a no-op: users can't resize canvas elements
    }

    #[inline]
    pub fn get_hidpi_factor(&self) -> f64 {
        unimplemented!();
    }

    #[inline]
    pub fn set_cursor(&self, cursor: MouseCursor) {
        let text = match cursor {
            MouseCursor::Default => "auto",
            MouseCursor::Crosshair => "crosshair",
            MouseCursor::Hand => "pointer",
            MouseCursor::Arrow => "default",
            MouseCursor::Move => "move",
            MouseCursor::Text => "text",
            MouseCursor::Wait => "wait",
            MouseCursor::Help => "help",
            MouseCursor::Progress => "progress",

            MouseCursor::NotAllowed => "not-allowed",
            MouseCursor::ContextMenu => "context-menu",
            MouseCursor::Cell => "cell",
            MouseCursor::VerticalText => "vertical-text",
            MouseCursor::Alias => "alias",
            MouseCursor::Copy => "copy",
            MouseCursor::NoDrop => "no-drop",
            MouseCursor::Grab => "grab",
            MouseCursor::Grabbing => "grabbing",
            MouseCursor::AllScroll => "all-scroll",
            MouseCursor::ZoomIn => "zoom-in",
            MouseCursor::ZoomOut => "zoom-out",

            MouseCursor::EResize => "e-resize",
            MouseCursor::NResize => "n-resize",
            MouseCursor::NeResize => "ne-resize",
            MouseCursor::NwResize => "nw-resize",
            MouseCursor::SResize => "s-resize",
            MouseCursor::SeResize => "se-resize",
            MouseCursor::SwResize => "sw-resize",
            MouseCursor::WResize => "w-resize",
            MouseCursor::EwResize => "ew-resize",
            MouseCursor::NsResize => "ns-resize",
            MouseCursor::NeswResize => "nesw-resize",
            MouseCursor::NwseResize => "nwse-resize",
            MouseCursor::ColResize => "col-resize",
            MouseCursor::RowResize => "row-resize",
        };
        self.canvas.set_attribute("cursor", text);
            .expect("Setting the cursor on the canvas");
    }

    #[inline]
    pub fn set_cursor_position(&self, position: LogicalPosition) -> Result<(), String> {
        // TODO: pointer capture
        unimplemented!();
    }

    #[inline]
    pub fn grab_cursor(&self, grab: bool) -> Result<(), String> {
        // TODO: pointer capture
        unimplemented!();
    }

    #[inline]
    pub fn hide_cursor(&self, hide: bool) {
        self.canvas.set_attribute("cursor", "none")
            .expect("Setting the cursor on the canvas");
    }

    #[inline]
    pub fn set_maximized(&self, maximized: bool) {
        // TODO: should there be a maximization / fullscreen API?
        unimplemented!();
    }

    #[inline]
    pub fn set_fullscreen(&self, monitor: Option<RootMH>) {
        // TODO: should there be a maximization / fullscreen API?
        unimplemented!();
    }

    #[inline]
    pub fn set_decorations(&self, _decorations: bool) {
        // Intentionally a no-op, no canvas decorations
    }

    #[inline]
    pub fn set_always_on_top(&self, _always_on_top: bool) {
        // Intentionally a no-op, no window ordering
    }

    #[inline]
    pub fn set_window_icon(&self, window_icon: Option<Icon>) {
        // TODO: should this set the favicon?
        unimplemented!();
    }

    #[inline]
    pub fn set_ime_spot(&self, position: LogicalPosition) {
        unimplemented!();
    }

    #[inline]
    pub fn get_current_monitor(&self) -> RootMH {
        RootMH {
            inner: MonitorHandle
        }
    }

    #[inline]
    pub fn get_available_monitors(&self) -> VecDequeIter<MonitorHandle> {
        self.monitors.iter()
    }

    #[inline]
    pub fn get_primary_monitor(&self) -> MonitorHandle {
        MonitorHandle
    }

    #[inline]
    pub fn id(&self) -> WindowId {
        WindowId::dummy()
    }
}

fn new_rootelw<T>() -> RootELW<T> {
    RootELW {
        p: EventLoopWindowTarget,
        _marker: PhantomData
    }
}

pub struct EventLoop<T> {
    window_target: RootELW<T>,
    monitors: VecDeque<MonitorHandle>,
    data: Rc<Cell<EventLoopData>>,
}

struct EventLoopData {
    events: VecDeque<T>,
    control: ControlFlow,
}

impl<T> EventLoop<T> {
    pub fn new() -> Self {
        unimplemented!();
    }

    pub fn get_available_monitors(&self) -> VecDequeIter<MonitorHandle> {
        self.monitors.iter()
    }

    pub fn get_primary_monitor(&self) -> MonitorHandle {
        MonitorHandle
    }

    pub fn run<F>(mut self, event_handler: F) -> !
        where F: 'static + FnMut(Event<T>, &RootELW<T>, &mut ControlFlow)
    {
        // TODO: Create event handlers for the JS events
        // TODO: how to handle request redraw?
        unimplemented!();
    }

    pub fn create_proxy(&self) -> EventLoopProxy<T> {
        EventLoopProxy {
            events: self.window_target.p.events.clone()
        }
    }

    pub fn window_target(&self) -> &RootELW<T> {
        &self.window_target
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct EventLoopProxy<T> {
    data: EventLoopData
}

impl<T> EventLoopProxy<T> {
    pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed> {
        self.data.borrow_mut().events.push_back(Event::UserEvent(event));
        Ok(())
    }
}

pub struct EventLoopWindowTarget<T> {
    _phantom: PhantomData<T>
}

#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PlatformSpecificWindowBuilderAttributes;

<|endoftext|>


<commit_before>use std::{iter, ptr, vec};

use serde::de::{
    self,
    value::{Error, SeqDeserializer},
    Deserializer, IntoDeserializer,
};

#[derive(Debug)]
pub enum ValOrVec<T> {
    Val(T),
    Vec(Vec<T>),
}

impl<T> ValOrVec<T> {
    pub fn push(&mut self, new_val: T) {
        match self {
            // To transform a Self::Val into a Self::Vec, we take the existing
            // value out via ptr::read and add it to a vector, together with the
            // new value. Since setting self to `ValOrVec::Vec` normally would
            // cause T's Drop implementation to run if it has one (which would
            // free resources that will now be owned by the first vec element),
            // we instead use ptr::write to set self to Self::Vec.
            ValOrVec::Val(val) => {
                let mut vec = Vec::with_capacity(2);
                // Safety: since the vec is pre-allocated, push can't panic, so
                //   there is no opportunity for outside code to observe an
                //   invalid state of self.
                unsafe {
                    let existing_val = ptr::read(val);
                    vec.push(existing_val);
                    vec.push(new_val);
                    ptr::write(self, ValOrVec::Vec(vec))
                }
            }
            ValOrVec::Vec(vec) => vec.push(new_val),
        }
    }
}

impl<T> IntoIterator for ValOrVec<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;

    fn into_iter(self) -> Self::IntoIter {
        IntoIter::new(self)
    }
}

pub enum IntoIter<T> {
    Val(iter::Once<T>),
    Vec(vec::IntoIter<T>),
}

impl<T> IntoIter<T> {
    fn new(vv: ValOrVec<T>) -> Self {
        match vv {
            ValOrVec::Val(val) => IntoIter::Val(iter::once(val)),
            ValOrVec::Vec(vec) => IntoIter::Vec(vec.into_iter()),
        }
    }
}

impl<T> Iterator for IntoIter<T> {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        match self {
            IntoIter::Val(iter) => iter.next(),
            IntoIter::Vec(iter) => iter.next(),
        }
    }
}

impl<'de, T> IntoDeserializer<'de> for ValOrVec<T>
where
    T: IntoDeserializer<'de> + Deserializer<'de, Error = Error>,
{
    type Deserializer = Self;

    fn into_deserializer(self) -> Self::Deserializer {
        self
    }
}

macro_rules! forward_to_part {
    ($($method:ident,)*) => {
        $(
            fn $method<V>(self, visitor: V) -> Result<V::Value, Self::Error>
                where V: de::Visitor<'de>
            {
                match self {
                    ValOrVec::Val(val) => val.$method(visitor),
                    ValOrVec::Vec(_) => Err(de::Error::custom("TODO: Error message")),
                }
            }
        )*
    }
}

impl<'de, T> Deserializer<'de> for ValOrVec<T>
where
    T: IntoDeserializer<'de> + Deserializer<'de, Error = Error>,
{
    type Error = Error;

    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        match self {
            ValOrVec::Val(val) => val.deserialize_any(visitor),
            ValOrVec::Vec(_) => self.deserialize_seq(visitor),
        }
    }

    fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        visitor.visit_seq(SeqDeserializer::new(self.into_iter()))
    }

    fn deserialize_enum<V>(
        self,
        name: &'static str,
        variants: &'static [&'static str],
        visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        match self {
            ValOrVec::Val(val) => val.deserialize_enum(name, variants, visitor),
            ValOrVec::Vec(_) => Err(de::Error::custom("TODO: Error message")),
        }
    }

    fn deserialize_tuple<V>(
        self,
        len: usize,
        visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        match self {
            ValOrVec::Val(val) => val.deserialize_tuple(len, visitor),
            ValOrVec::Vec(_) => Err(de::Error::custom("TODO: Error message")),
        }
    }

    fn deserialize_struct<V>(
        self,
        name: &'static str,
        fields: &'static [&'static str],
        visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        match self {
            ValOrVec::Val(val) => val.deserialize_struct(name, fields, visitor),
            ValOrVec::Vec(_) => Err(de::Error::custom("TODO: Error message")),
        }
    }

    fn deserialize_unit_struct<V>(
        self,
        name: &'static str,
        visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        match self {
            ValOrVec::Val(val) => val.deserialize_unit_struct(name, visitor),
            ValOrVec::Vec(_) => Err(de::Error::custom("TODO: Error message")),
        }
    }

    fn deserialize_tuple_struct<V>(
        self,
        name: &'static str,
        len: usize,
        visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        match self {
            ValOrVec::Val(val) => {
                val.deserialize_tuple_struct(name, len, visitor)
            }
            ValOrVec::Vec(_) => Err(de::Error::custom("TODO: Error message")),
        }
    }

    fn deserialize_newtype_struct<V>(
        self,
        name: &'static str,
        visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        match self {
            ValOrVec::Val(val) => val.deserialize_newtype_struct(name, visitor),
            ValOrVec::Vec(_) => Err(de::Error::custom("TODO: Error message")),
        }
    }

    forward_to_part! {
        deserialize_bool,
        deserialize_char,
        deserialize_str,
        deserialize_string,
        deserialize_bytes,
        deserialize_byte_buf,
        deserialize_unit,
        deserialize_u8,
        deserialize_u16,
        deserialize_u32,
        deserialize_u64,
        deserialize_i8,
        deserialize_i16,
        deserialize_i32,
        deserialize_i64,
        deserialize_f32,
        deserialize_f64,
        deserialize_option,
        deserialize_identifier,
        deserialize_ignored_any,
        deserialize_map,
    }
}

#[cfg(test)]
mod tests {
    use std::borrow::Cow;

    use matches::assert_matches;

    use super::ValOrVec;

    #[test]
    fn cow_borrowed() {
        let mut x = ValOrVec::Val(Cow::Borrowed("a"));
        x.push(Cow::Borrowed("b"));
        x.push(Cow::Borrowed("c"));
        assert_matches!(x, ValOrVec::Vec(v) if v == vec!["a", "b", "c"]);
    }

    #[test]
    fn cow_owned() {
        let mut x = ValOrVec::Val(Cow::from("a".to_owned()));
        x.push(Cow::from("b".to_owned()));
        x.push(Cow::from("c".to_owned()));
        assert_matches!(
            x,
            ValOrVec::Vec(v) if v == vec!["a".to_owned(), "b".to_owned(), "c".to_owned()]
        );
    }
}
<commit_msg>Update deserialization error messages<commit_after>use std::{iter, ptr, vec};

use serde::de::{
    self,
    value::{Error, SeqDeserializer},
    Deserializer, IntoDeserializer,
};

#[derive(Debug)]
pub enum ValOrVec<T> {
    Val(T),
    Vec(Vec<T>),
}

impl<T> ValOrVec<T> {
    pub fn push(&mut self, new_val: T) {
        match self {
            // To transform a Self::Val into a Self::Vec, we take the existing
            // value out via ptr::read and add it to a vector, together with the
            // new value. Since setting self to `ValOrVec::Vec` normally would
            // cause T's Drop implementation to run if it has one (which would
            // free resources that will now be owned by the first vec element),
            // we instead use ptr::write to set self to Self::Vec.
            ValOrVec::Val(val) => {
                let mut vec = Vec::with_capacity(2);
                // Safety: since the vec is pre-allocated, push can't panic, so
                //   there is no opportunity for outside code to observe an
                //   invalid state of self.
                unsafe {
                    let existing_val = ptr::read(val);
                    vec.push(existing_val);
                    vec.push(new_val);
                    ptr::write(self, ValOrVec::Vec(vec))
                }
            }
            ValOrVec::Vec(vec) => vec.push(new_val),
        }
    }
}

impl<T> IntoIterator for ValOrVec<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;

    fn into_iter(self) -> Self::IntoIter {
        IntoIter::new(self)
    }
}

pub enum IntoIter<T> {
    Val(iter::Once<T>),
    Vec(vec::IntoIter<T>),
}

impl<T> IntoIter<T> {
    fn new(vv: ValOrVec<T>) -> Self {
        match vv {
            ValOrVec::Val(val) => IntoIter::Val(iter::once(val)),
            ValOrVec::Vec(vec) => IntoIter::Vec(vec.into_iter()),
        }
    }
}

impl<T> Iterator for IntoIter<T> {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        match self {
            IntoIter::Val(iter) => iter.next(),
            IntoIter::Vec(iter) => iter.next(),
        }
    }
}

impl<'de, T> IntoDeserializer<'de> for ValOrVec<T>
where
    T: IntoDeserializer<'de> + Deserializer<'de, Error = Error>,
{
    type Deserializer = Self;

    fn into_deserializer(self) -> Self::Deserializer {
        self
    }
}

macro_rules! forward_to_part {
    ($($method:ident,)*) => {
        $(
            fn $method<V>(self, visitor: V) -> Result<V::Value, Self::Error>
                where V: de::Visitor<'de>
            {
                match self {
                    ValOrVec::Val(val) => val.$method(visitor),
                    ValOrVec::Vec(_) => Err(de::Error::custom("unsupported value")),
                }
            }
        )*
    }
}

impl<'de, T> Deserializer<'de> for ValOrVec<T>
where
    T: IntoDeserializer<'de> + Deserializer<'de, Error = Error>,
{
    type Error = Error;

    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        match self {
            ValOrVec::Val(val) => val.deserialize_any(visitor),
            ValOrVec::Vec(_) => self.deserialize_seq(visitor),
        }
    }

    fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        visitor.visit_seq(SeqDeserializer::new(self.into_iter()))
    }

    fn deserialize_enum<V>(
        self,
        name: &'static str,
        variants: &'static [&'static str],
        visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        match self {
            ValOrVec::Val(val) => val.deserialize_enum(name, variants, visitor),
            ValOrVec::Vec(_) => Err(de::Error::custom("unsupported value")),
        }
    }

    fn deserialize_tuple<V>(
        self,
        len: usize,
        visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        match self {
            ValOrVec::Val(val) => val.deserialize_tuple(len, visitor),
            ValOrVec::Vec(_) => Err(de::Error::custom("unsupported value")),
        }
    }

    fn deserialize_struct<V>(
        self,
        name: &'static str,
        fields: &'static [&'static str],
        visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        match self {
            ValOrVec::Val(val) => val.deserialize_struct(name, fields, visitor),
            ValOrVec::Vec(_) => Err(de::Error::custom("unsupported value")),
        }
    }

    fn deserialize_unit_struct<V>(
        self,
        name: &'static str,
        visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        match self {
            ValOrVec::Val(val) => val.deserialize_unit_struct(name, visitor),
            ValOrVec::Vec(_) => Err(de::Error::custom("unsupported value")),
        }
    }

    fn deserialize_tuple_struct<V>(
        self,
        name: &'static str,
        len: usize,
        visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        match self {
            ValOrVec::Val(val) => {
                val.deserialize_tuple_struct(name, len, visitor)
            }
            ValOrVec::Vec(_) => Err(de::Error::custom("unsupported value")),
        }
    }

    fn deserialize_newtype_struct<V>(
        self,
        name: &'static str,
        visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        match self {
            ValOrVec::Val(val) => val.deserialize_newtype_struct(name, visitor),
            ValOrVec::Vec(_) => Err(de::Error::custom("unsupported value")),
        }
    }

    forward_to_part! {
        deserialize_bool,
        deserialize_char,
        deserialize_str,
        deserialize_string,
        deserialize_bytes,
        deserialize_byte_buf,
        deserialize_unit,
        deserialize_u8,
        deserialize_u16,
        deserialize_u32,
        deserialize_u64,
        deserialize_i8,
        deserialize_i16,
        deserialize_i32,
        deserialize_i64,
        deserialize_f32,
        deserialize_f64,
        deserialize_option,
        deserialize_identifier,
        deserialize_ignored_any,
        deserialize_map,
    }
}

#[cfg(test)]
mod tests {
    use std::borrow::Cow;

    use matches::assert_matches;

    use super::ValOrVec;

    #[test]
    fn cow_borrowed() {
        let mut x = ValOrVec::Val(Cow::Borrowed("a"));
        x.push(Cow::Borrowed("b"));
        x.push(Cow::Borrowed("c"));
        assert_matches!(x, ValOrVec::Vec(v) if v == vec!["a", "b", "c"]);
    }

    #[test]
    fn cow_owned() {
        let mut x = ValOrVec::Val(Cow::from("a".to_owned()));
        x.push(Cow::from("b".to_owned()));
        x.push(Cow::from("c".to_owned()));
        assert_matches!(
            x,
            ValOrVec::Vec(v) if v == vec!["a".to_owned(), "b".to_owned(), "c".to_owned()]
        );
    }
}
<|endoftext|>