<commit_before>use std::io::println;
use rf_common::*;
use syntax::ast;
use rustc::middle::{ty,typeck};
use syntax::codemap::{BytePos, Pos};
use rsfind::ShowDefMode;

use find_ast_node::{FNodeInfoMap, FNodeInfo, AstNode, NodeTreeLoc, find_node_tree_loc_at_byte_pos,
	build_node_def_node_table, build_node_info_map, get_node_source, astnode_expr,
	get_def_id, byte_pos_from_text_file_pos_str, ToJsonStr, ToJsonStrFc, AstNodeAccessors};
use rfindctx::{RFindCtx,get_source_loc};
use codemaput::ZTextFilePos;
use rf_ast_ut::{auto_deref_ty, find_named_struct_field};
use util::flatten_to_str; //todo - why is qualifying manually not working?!
//use super::rf_use_ast;

//todo - simple declartions of types shouldn't mean bringing in associated code modules ?
// a user that needs the type JumpToDefMap needn't necaserily need all its functions...

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

pub type JumpToDefMap = HashMap<ast::NodeId,ast::DefId> ;

pub fn lookup_def_node_of_node(dc:&RFindCtx,node:&AstNode, nodeinfomap:&FNodeInfoMap, _: &HashMap<ast::NodeId,ast::DefId>)->Option<ast::DefId> {

	match *node {
		astnode_expr(e)=>match e.node {
			// handle methods-calls
			ast::ExprMethodCall(..)=>{
				// Currently unused
// 				let rec_ty_node= astnode_expr(*receiver).ty_node_id();
// 				let rec_ty_node1= dc.tycx.node_types.find(&(*id as uint));

                let method_map = dc.ca.maps.method_map.borrow();
                let method_map = method_map.get();
				match method_map.find(&e.id) {
					None=> {},//logi!("no method map entry for",e.id),
					Some(mme)=>{
						//logi!("Method Map entry for",e.id);
						match mme.origin {
							typeck::method_static(def_id)=>
								return Some(def_id),
							typeck::method_object(_)=>
// 								return Some(mp.trait_id),
								return None,
							typeck::method_param(mp)=>{
                                let trait_method_def_ids = dc.tycx.trait_method_def_ids.borrow();
                                let trait_method_def_ids = trait_method_def_ids.get();
								match trait_method_def_ids.find(&mp.trait_id) {
									None=>{},
									Some(method_def_ids)=>{
										return Some(method_def_ids[mp.method_num])
									}
								}
							}
						}
					}
				}
			},
			// handle struct-fields? "object.field"
			ast::ExprField(ref object_expr, ref ident, _)=>{
				// we want the type of the object..
                let node_types = dc.tycx.node_types.borrow();
                let node_types = node_types.get();
				let obj_ty=node_types.find(&(object_expr.id as uint));
				let tydef=/*rf_ast_ut::*/auto_deref_ty(ty::get(*obj_ty.unwrap()));
				match tydef.sty {
					ty::ty_struct(def,_)=> {
						let node_to_show=/*rf_ast_ut::*/find_named_struct_field(&dc.tycx, def.node, ident).unwrap_or(def);
						return Some(node_to_show);//mk_result(dc,m,node_spans,node_to_show,"(struct_field)");
					},
					_=>return None
				}
			}
			_=>{}
		},
		_=>{}

	}

	// handle everything else
	match node.ty_node_id() {
		Some(id) =>{
			let (def_id, _)= def_info_from_node_id(dc,nodeinfomap,id);
			return if def_id != ast::DefId{krate:0,node:id} {Some(def_id)} else {None}
/*			match opt_info {
				Some(info)=> {
					return Some(def_id);
				},
				_=>{ println("can't find def for"+node.get_id().to_str()+".ty_node_id="+id.to_str()); //return None;
					//let (def_id,opt_info)= def_info_from_node_id(dc,nodeinfomap,node.get_id().unwrap());
					//match opt_info {
					//	Some(info)=> {return Some(def_id);}
					//	None=>{}
					//}
				}
			}
*/
		},
		None=> {}
	};
	return None;
}

pub fn build_jump_to_def_map(dc:&RFindCtx, nim: &FNodeInfoMap,nd:&HashMap<ast::NodeId,ast::DefId>)->~JumpToDefMap{
// todo: NodeId->AStNode  .. lookup_def_ inner functionality extracted
	let mut jdm=~HashMap::new();
	for (k,node_info) in nim.iter() {
		match lookup_def_node_of_node(dc,&node_info.node, nim,nd) {
			None=>{},
			Some(def_node_id)=>{
//				if *k != def_node_id.node && def_node_id.crate==0 || (def_node_id.crate!=0)
				{
					jdm.insert(*k,def_node_id);
				}
			}
		}
	}
	jdm
}

pub fn def_info_from_node_id<'a,'b>(dc:&'a RFindCtx, node_info:&'b FNodeInfoMap, id:ast::NodeId)->(ast::DefId,Option<&'b FNodeInfo>) {
	let crate_num=0;
    let def_map = dc.tycx.def_map.borrow();
    let def_map = def_map.get();
	match def_map.find(&id) { // finds a def..
		Some(a)=>{
			match get_def_id(crate_num,*a){
				Some(b)=>
					(b,node_info.find(&b.node)),
//				match b.crate {
//					0=>(b.node,node_info.find(&b.node)),
//					_ => (id as int, None)
//				},
				None=>(ast::DefId{krate:0,node:id},None)
			}
		},
		None=>(ast::DefId{krate:0,node:id},None)
	}
}

pub fn dump_json(dc:&RFindCtx) {
	// TODO: full/partial options - we currently wwrite out all the nodes we find.
	// need option to only write out nodes that map to definitons.
	println("{");
	println("\tcode_map:[");
//	for dc.sess.codemap.files.iter().advance |f| {
    let files = dc.sess.codemap.files.borrow();
    let files = files.get();
	for f in files.iter() {
        let lines = f.lines.borrow();
        let lines = lines.get();
		print!("\t\t\\{ name:\"{}\"", f.name);
        print!("\tglobal_start_pos:{},", f.start_pos.to_uint().to_str());
        print!("\tlength:{},", (f.src.len()).to_str());
		print!("\tnum_lines:{},", lines.len().to_str());
		print!("\tlines:[\n{},", flatten_to_str(*lines, |&x|{(x-f.start_pos).to_uint()} ,","));
	    print!("\n\t\t]\n\t\\},\n");
	}
	println("\t]");
	println("\tnode_spans:");
	let nim=build_node_info_map(dc.crate_);
	let node_def_node = build_node_def_node_table(dc);
	let jdm=build_jump_to_def_map(dc, &nim,node_def_node);
	println(nim.to_json_str(dc));
	println(",");
	println("\tnode_defs [\n");
	println(jdm.to_json_str());
	println("\t],\n");
	println("\tdef_ids:");
	println(node_def_node.to_json_str());
	println("}");
}

pub fn lookup_def_at_text_file_pos(dc:&RFindCtx, tfp:&ZTextFilePos, show_mode:ShowDefMode)->Option<~str> {
	match tfp.to_byte_pos(dc.tycx) {
		None=>None,
		Some(bp)=>lookup_def_at_byte_pos(dc,bp,show_mode)
	}
}

pub fn lookup_def_at_text_file_pos_str(dc:&RFindCtx,file_pos_str:&str, show_mode:ShowDefMode)->Option<~str> {
	match byte_pos_from_text_file_pos_str(dc,file_pos_str) {
		None=>None,
		Some(bp)=>lookup_def_at_byte_pos(dc,bp,show_mode),
	}
}

pub fn node_id_from_text_file_pos_str(dc:&RFindCtx, file_pos_str:&str)->Option<ast::NodeId> {
	match node_from_text_file_pos_str(dc, file_pos_str) {
		None=>None,
		Some(an)=>an.get_id()
	}
}
pub fn node_from_text_file_pos_str(dc:&RFindCtx, file_pos_str:&str)->Option<AstNode> {
	match byte_pos_from_text_file_pos_str(dc,file_pos_str) {
		Some(bp)=>{let ndt=find_node_tree_loc_at_byte_pos(dc.crate_,bp); Some(*ndt.last().get_ref().clone())},
		None=>None
	}
}

pub fn lookup_def_at_byte_pos(dc:&RFindCtx, bp:BytePos, m:ShowDefMode)->Option<~str> {
	let ndt=find_node_tree_loc_at_byte_pos(dc.crate_,bp);
	lookup_def_of_node_tree_loc(dc,&ndt,m)
}

pub fn lookup_def_of_node_tree_loc(dc:&RFindCtx,node_tree_loc:&NodeTreeLoc,m:ShowDefMode)->Option<~str> {
	lookup_def_of_node(dc,*node_tree_loc.last().get_ref(),m)
}

pub fn lookup_def_of_node(dc: &RFindCtx, node: &AstNode, m: ShowDefMode)->Option<~str> {
	println("def of node:"+node.get_id().unwrap_or(0).to_str());
	let node_spans=build_node_info_map(dc.crate_);
	let node_def_node = build_node_def_node_table(dc);
	lookup_def_of_node_sub(dc,node,m,&node_spans,node_def_node)
}

pub fn lookup_def_of_node_sub(dc:&RFindCtx,node:&AstNode,m:ShowDefMode,nim:&FNodeInfoMap, node_def_node:&HashMap<ast::NodeId,ast::DefId>)->Option<~str> {
	// TODO - cache outside?

	fn mk_result(dc:&RFindCtx,  m:ShowDefMode, nim:&FNodeInfoMap, def_node_id:ast::DefId, _: &str)->Option<~str> {
		if def_node_id.krate != 0 {
			Some(~"{cross-crate-def not implemented, "+def_node_id.to_str()+"}")
		}
		else {
			match nim.find(&def_node_id.node) {
				None=>None,
				Some(def_info)=>{
					let loc=get_source_loc(dc,def_info.span.lo);
					let def_pos_str=
						loc.file.name + ":"+loc.line.to_str()+": "+
							match m { SDM_LineCol=>loc.col.to_uint().to_str()+": ", _ =>~"" }+"\n";
					return	match m{
						SDM_Source=>Some(def_pos_str+get_node_source(dc.tycx,nim, def_node_id)+"\n"),
						SDM_GeditCmd=>Some("+"+loc.line.to_str()+" "+loc.file.name+" "),
						_ => Some(def_pos_str)
					};

				}
			}
		}
	}
	match lookup_def_node_of_node(dc, node, nim, node_def_node) {
		None=>None,
		Some(def_node_id)=>mk_result(dc,m, nim,def_node_id, "")
	}
}

pub fn make_jdm(dc:&RFindCtx)->( FNodeInfoMap, ~HashMap<ast::NodeId,ast::DefId>,~JumpToDefMap)
{
    let nim=build_node_info_map(dc.crate_);
    let ndm=build_node_def_node_table(dc);
    let jdm=build_jump_to_def_map(dc, &nim,ndm);
    (nim,ndm,jdm)
}
<commit_msg>Update to rust master<commit_after>use std::io::println;
use rf_common::*;
use syntax::ast;
use rustc::middle::{ty,typeck};
use syntax::codemap::{BytePos, Pos};
use rsfind::ShowDefMode;

use find_ast_node::{FNodeInfoMap, FNodeInfo, AstNode, NodeTreeLoc, find_node_tree_loc_at_byte_pos,
	build_node_def_node_table, build_node_info_map, get_node_source, astnode_expr,
	get_def_id, byte_pos_from_text_file_pos_str, ToJsonStr, ToJsonStrFc, AstNodeAccessors};
use rfindctx::{RFindCtx,get_source_loc};
use codemaput::ZTextFilePos;
use rf_ast_ut::{auto_deref_ty, find_named_struct_field};
use util::flatten_to_str; //todo - why is qualifying manually not working?!
//use super::rf_use_ast;

//todo - simple declartions of types shouldn't mean bringing in associated code modules ?
// a user that needs the type JumpToDefMap needn't necaserily need all its functions...

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

pub type JumpToDefMap = HashMap<ast::NodeId,ast::DefId> ;

pub fn lookup_def_node_of_node(dc:&RFindCtx,node:&AstNode, nodeinfomap:&FNodeInfoMap, _: &HashMap<ast::NodeId,ast::DefId>)->Option<ast::DefId> {

	match *node {
		astnode_expr(e)=>match e.node {
			// handle methods-calls
			ast::ExprMethodCall(..)=>{
				// Currently unused
// 				let rec_ty_node= astnode_expr(*receiver).ty_node_id();
// 				let rec_ty_node1= dc.tycx.node_types.find(&(*id as uint));

                let method_map = dc.ca.maps.method_map.borrow();
                let method_map = method_map.get();
				match method_map.find(&e.id) {
					None=> {},//logi!("no method map entry for",e.id),
					Some(origin)=>{
						//logi!("Method Map entry for",e.id);
						match *origin {
							typeck::method_static(def_id)=>
								return Some(def_id),
							typeck::method_object(_)=>
// 								return Some(mp.trait_id),
								return None,
							typeck::method_param(mp)=>{
                                let trait_method_def_ids = dc.tycx.trait_method_def_ids.borrow();
                                let trait_method_def_ids = trait_method_def_ids.get();
								match trait_method_def_ids.find(&mp.trait_id) {
									None=>{},
									Some(method_def_ids)=>{
										return Some(method_def_ids[mp.method_num])
									}
								}
							}
						}
					}
				}
			},
			// handle struct-fields? "object.field"
			ast::ExprField(ref object_expr, ref ident, _)=>{
				// we want the type of the object..
                let node_types = dc.tycx.node_types.borrow();
                let node_types = node_types.get();
				let obj_ty=node_types.find(&(object_expr.id as uint));
				let tydef=/*rf_ast_ut::*/auto_deref_ty(ty::get(*obj_ty.unwrap()));
				match tydef.sty {
					ty::ty_struct(def,_)=> {
						let node_to_show=/*rf_ast_ut::*/find_named_struct_field(&dc.tycx, def.node, ident).unwrap_or(def);
						return Some(node_to_show);//mk_result(dc,m,node_spans,node_to_show,"(struct_field)");
					},
					_=>return None
				}
			}
			_=>{}
		},
		_=>{}

	}

	// handle everything else
	match node.ty_node_id() {
		Some(id) =>{
			let (def_id, _)= def_info_from_node_id(dc,nodeinfomap,id);
			return if def_id != ast::DefId{krate:0,node:id} {Some(def_id)} else {None}
/*			match opt_info {
				Some(info)=> {
					return Some(def_id);
				},
				_=>{ println("can't find def for"+node.get_id().to_str()+".ty_node_id="+id.to_str()); //return None;
					//let (def_id,opt_info)= def_info_from_node_id(dc,nodeinfomap,node.get_id().unwrap());
					//match opt_info {
					//	Some(info)=> {return Some(def_id);}
					//	None=>{}
					//}
				}
			}
*/
		},
		None=> {}
	};
	return None;
}

pub fn build_jump_to_def_map(dc:&RFindCtx, nim: &FNodeInfoMap,nd:&HashMap<ast::NodeId,ast::DefId>)->~JumpToDefMap{
// todo: NodeId->AStNode  .. lookup_def_ inner functionality extracted
	let mut jdm=~HashMap::new();
	for (k,node_info) in nim.iter() {
		match lookup_def_node_of_node(dc,&node_info.node, nim,nd) {
			None=>{},
			Some(def_node_id)=>{
//				if *k != def_node_id.node && def_node_id.crate==0 || (def_node_id.crate!=0)
				{
					jdm.insert(*k,def_node_id);
				}
			}
		}
	}
	jdm
}

pub fn def_info_from_node_id<'a,'b>(dc:&'a RFindCtx, node_info:&'b FNodeInfoMap, id:ast::NodeId)->(ast::DefId,Option<&'b FNodeInfo>) {
	let crate_num=0;
    let def_map = dc.tycx.def_map.borrow();
    let def_map = def_map.get();
	match def_map.find(&id) { // finds a def..
		Some(a)=>{
			match get_def_id(crate_num,*a){
				Some(b)=>
					(b,node_info.find(&b.node)),
//				match b.crate {
//					0=>(b.node,node_info.find(&b.node)),
//					_ => (id as int, None)
//				},
				None=>(ast::DefId{krate:0,node:id},None)
			}
		},
		None=>(ast::DefId{krate:0,node:id},None)
	}
}

pub fn dump_json(dc:&RFindCtx) {
	// TODO: full/partial options - we currently wwrite out all the nodes we find.
	// need option to only write out nodes that map to definitons.
	println("{");
	println("\tcode_map:[");
//	for dc.sess.codemap.files.iter().advance |f| {
    let files = dc.sess.codemap.files.borrow();
    let files = files.get();
	for f in files.iter() {
        let lines = f.lines.borrow();
        let lines = lines.get();
		print!("\t\t\\{ name:\"{}\"", f.name);
        print!("\tglobal_start_pos:{},", f.start_pos.to_uint().to_str());
        print!("\tlength:{},", (f.src.len()).to_str());
		print!("\tnum_lines:{},", lines.len().to_str());
		print!("\tlines:[\n{},", flatten_to_str(*lines, |&x|{(x-f.start_pos).to_uint()} ,","));
	    print!("\n\t\t]\n\t\\},\n");
	}
	println("\t]");
	println("\tnode_spans:");
	let nim=build_node_info_map(dc.crate_);
	let node_def_node = build_node_def_node_table(dc);
	let jdm=build_jump_to_def_map(dc, &nim,node_def_node);
	println(nim.to_json_str(dc));
	println(",");
	println("\tnode_defs [\n");
	println(jdm.to_json_str());
	println("\t],\n");
	println("\tdef_ids:");
	println(node_def_node.to_json_str());
	println("}");
}

pub fn lookup_def_at_text_file_pos(dc:&RFindCtx, tfp:&ZTextFilePos, show_mode:ShowDefMode)->Option<~str> {
	match tfp.to_byte_pos(dc.tycx) {
		None=>None,
		Some(bp)=>lookup_def_at_byte_pos(dc,bp,show_mode)
	}
}

pub fn lookup_def_at_text_file_pos_str(dc:&RFindCtx,file_pos_str:&str, show_mode:ShowDefMode)->Option<~str> {
	match byte_pos_from_text_file_pos_str(dc,file_pos_str) {
		None=>None,
		Some(bp)=>lookup_def_at_byte_pos(dc,bp,show_mode),
	}
}

pub fn node_id_from_text_file_pos_str(dc:&RFindCtx, file_pos_str:&str)->Option<ast::NodeId> {
	match node_from_text_file_pos_str(dc, file_pos_str) {
		None=>None,
		Some(an)=>an.get_id()
	}
}
pub fn node_from_text_file_pos_str(dc:&RFindCtx, file_pos_str:&str)->Option<AstNode> {
	match byte_pos_from_text_file_pos_str(dc,file_pos_str) {
		Some(bp)=>{let ndt=find_node_tree_loc_at_byte_pos(dc.crate_,bp); Some(*ndt.last().get_ref().clone())},
		None=>None
	}
}

pub fn lookup_def_at_byte_pos(dc:&RFindCtx, bp:BytePos, m:ShowDefMode)->Option<~str> {
	let ndt=find_node_tree_loc_at_byte_pos(dc.crate_,bp);
	lookup_def_of_node_tree_loc(dc,&ndt,m)
}

pub fn lookup_def_of_node_tree_loc(dc:&RFindCtx,node_tree_loc:&NodeTreeLoc,m:ShowDefMode)->Option<~str> {
	lookup_def_of_node(dc,*node_tree_loc.last().get_ref(),m)
}

pub fn lookup_def_of_node(dc: &RFindCtx, node: &AstNode, m: ShowDefMode)->Option<~str> {
	println("def of node:"+node.get_id().unwrap_or(0).to_str());
	let node_spans=build_node_info_map(dc.crate_);
	let node_def_node = build_node_def_node_table(dc);
	lookup_def_of_node_sub(dc,node,m,&node_spans,node_def_node)
}

pub fn lookup_def_of_node_sub(dc:&RFindCtx,node:&AstNode,m:ShowDefMode,nim:&FNodeInfoMap, node_def_node:&HashMap<ast::NodeId,ast::DefId>)->Option<~str> {
	// TODO - cache outside?

	fn mk_result(dc:&RFindCtx,  m:ShowDefMode, nim:&FNodeInfoMap, def_node_id:ast::DefId, _: &str)->Option<~str> {
		if def_node_id.krate != 0 {
			Some(~"{cross-crate-def not implemented, "+def_node_id.to_str()+"}")
		}
		else {
			match nim.find(&def_node_id.node) {
				None=>None,
				Some(def_info)=>{
					let loc=get_source_loc(dc,def_info.span.lo);
					let def_pos_str=
						loc.file.name + ":"+loc.line.to_str()+": "+
							match m { SDM_LineCol=>loc.col.to_uint().to_str()+": ", _ =>~"" }+"\n";
					return	match m{
						SDM_Source=>Some(def_pos_str+get_node_source(dc.tycx,nim, def_node_id)+"\n"),
						SDM_GeditCmd=>Some("+"+loc.line.to_str()+" "+loc.file.name+" "),
						_ => Some(def_pos_str)
					};

				}
			}
		}
	}
	match lookup_def_node_of_node(dc, node, nim, node_def_node) {
		None=>None,
		Some(def_node_id)=>mk_result(dc,m, nim,def_node_id, "")
	}
}

pub fn make_jdm(dc:&RFindCtx)->( FNodeInfoMap, ~HashMap<ast::NodeId,ast::DefId>,~JumpToDefMap)
{
    let nim=build_node_info_map(dc.crate_);
    let ndm=build_node_def_node_table(dc);
    let jdm=build_jump_to_def_map(dc, &nim,ndm);
    (nim,ndm,jdm)
}
<|endoftext|>


<commit_before>//! ICH - Incremental Compilation Hash

pub use self::hcx::{
    hash_stable_trait_impls, NodeIdHashingMode, StableHashingContext, StableHashingContextProvider,
};
use rustc_span::symbol::{sym, Symbol};
pub use rustc_span::CachingSourceMapView;

mod hcx;

mod impls_hir;
mod impls_syntax;
mod impls_ty;

pub const IGNORED_ATTRIBUTES: &[Symbol] = &[
    sym::cfg,
    sym::rustc_if_this_changed,
    sym::rustc_then_this_would_need,
    sym::rustc_dirty,
    sym::rustc_clean,
    sym::rustc_partition_reused,
    sym::rustc_partition_codegened,
    sym::rustc_expected_cgu_reuse,
];
<commit_msg>nix CachingSourceMapView reexport<commit_after>//! ICH - Incremental Compilation Hash

pub use self::hcx::{
    hash_stable_trait_impls, NodeIdHashingMode, StableHashingContext, StableHashingContextProvider,
};
use rustc_span::symbol::{sym, Symbol};

mod hcx;

mod impls_hir;
mod impls_syntax;
mod impls_ty;

pub const IGNORED_ATTRIBUTES: &[Symbol] = &[
    sym::cfg,
    sym::rustc_if_this_changed,
    sym::rustc_then_this_would_need,
    sym::rustc_dirty,
    sym::rustc_clean,
    sym::rustc_partition_reused,
    sym::rustc_partition_codegened,
    sym::rustc_expected_cgu_reuse,
];
<|endoftext|>


<commit_before>#[macro_use]
extern crate itertools;

use itertools::Itertools;
use std::collections::HashSet;

#[derive(Debug, PartialEq, Clone, Copy, Hash, Eq)]
enum ItemType {
    Generator,
    Microchip,
}

#[derive(Debug, Clone, PartialEq, Hash, Eq)]
struct Item {
    what: ItemType,
    compatible: &'static str,
    floor: u32,
}

impl Item {
    fn new(what: ItemType, compatible: &'static str, floor: u32) -> Item {
        Item {
            what: what,
            compatible: compatible,
            floor: floor,
        }
    }
}

fn valid_floor(items: &[&Item]) -> bool {
    let generators = items.iter()
        .filter(|&item| item.what == ItemType::Generator)
        .map(|item| item.compatible)
        .collect::<HashSet<_>>();
    if generators.is_empty() {
        return true;
    }

    let chips = items.iter()
        .filter(|&item| item.what == ItemType::Microchip)
        .map(|item| item.compatible)
        .collect::<HashSet<_>>();
    if chips.is_empty() {
        return true;
    }

    chips.is_subset(&generators)
}

fn valid_layout(items: &Vec<Item>) -> bool {
    [0, 1, 2, 3]
        .iter()
        .all(|&i| valid_floor(&items.iter().filter(|&item| item.floor == i).collect::<Vec<_>>()))
}

fn done(items: &Vec<Item>) -> bool {
    items.iter().all(|i| i.floor == 3)
}

fn steps(current_floor: u32, layout: &Vec<Item>) -> Vec<(Vec<Item>, u32)> {
    let mut possible_layouts = Vec::new();

    // items on current floor
    let items = layout.iter()
        .enumerate()
        .filter(|&(_, ref item)| item.floor == current_floor)
        .collect::<Vec<_>>();

    // possible single item moves
    for &(i, _) in &items {
        // down
        if current_floor != 0 {
            let new = layout.iter()
                .enumerate()
                .map(|(j, ref item)| if i == j {
                    Item::new(item.what, item.compatible, item.floor - 1)
                } else {
                    Item::new(item.what, item.compatible, item.floor)
                })
                .collect::<Vec<Item>>();
            if valid_layout(&new) {
                possible_layouts.push((new, current_floor - 1));
            }
        }

        // up
        if current_floor != 3 {
            let new = layout.iter()
                .enumerate()
                .map(|(j, ref item)| if i == j {
                    Item::new(item.what, item.compatible, item.floor + 1)
                } else {
                    Item::new(item.what, item.compatible, item.floor)
                })
                .collect::<Vec<Item>>();
            if valid_layout(&new) {
                possible_layouts.push((new, current_floor + 1));
            }
        }
    }

    // possible double moves
    for (i1, i2) in items.iter().tuple_combinations() {
        let &(i1, _) = i1;
        let &(i2, _) = i2;
        if current_floor != 3 {
            let new = layout.iter()
                .enumerate()
                .map(|(j, ref item)| if j == i1 || j == i2 {
                    Item::new(item.what, item.compatible, item.floor + 1)
                } else {
                    Item::new(item.what, item.compatible, item.floor)
                })
                .collect::<Vec<Item>>();
            if valid_layout(&new) {
                possible_layouts.push((new, current_floor + 1));
            }
        }

        if current_floor != 0 {
            let new = layout.iter()
                .enumerate()
                .map(|(j, ref item)| if j == i1 || j == i2 {
                    Item::new(item.what, item.compatible, item.floor - 1)
                } else {
                    Item::new(item.what, item.compatible, item.floor)
                })
                .collect::<Vec<Item>>();
            if valid_layout(&new) {
                possible_layouts.push((new, current_floor - 1));
            }
        }
    }

    possible_layouts
}

fn solve(start_layout: Vec<Item>) {
    let mut layouts = steps(0, &start_layout);
    let mut cache: HashSet<(Vec<Item>, u32)> = HashSet::new();
    cache.insert((start_layout, 0));
    let mut stepcount = 1;
    loop {
        stepcount += 1;
        let mut next = Vec::new();
        for (layout, floor) in layouts {
            let new_steps = steps(floor, &layout);
            for new_layout in new_steps {
                if done(&new_layout.0) {
                    println!("result: {}", stepcount);
                    return;
                }
                if !cache.contains(&new_layout) {
                    cache.insert(new_layout.clone());
                    next.push(new_layout);
                }
            }
        }
        layouts = next;
    }
}

fn main() {
    use ItemType::*;

    let part1_layout = vec![Item::new(Generator, "polonium", 0),
                            Item::new(Generator, "thulium", 0),
                            Item::new(Microchip, "thulium", 0),
                            Item::new(Generator, "promethium", 0),
                            Item::new(Generator, "ruthenium", 0),
                            Item::new(Microchip, "ruthenium", 0),
                            Item::new(Generator, "cobalt", 0),
                            Item::new(Microchip, "cobalt", 0),
                            Item::new(Microchip, "polonium", 1),
                            Item::new(Microchip, "promethium", 1)];

    let part2_layout = vec![Item::new(Generator, "polonium", 0),
                            Item::new(Generator, "thulium", 0),
                            Item::new(Microchip, "thulium", 0),
                            Item::new(Generator, "promethium", 0),
                            Item::new(Generator, "ruthenium", 0),
                            Item::new(Microchip, "ruthenium", 0),
                            Item::new(Generator, "cobalt", 0),
                            Item::new(Microchip, "cobalt", 0),
                            Item::new(Microchip, "elerium", 0),
                            Item::new(Generator, "elerium", 0),
                            Item::new(Microchip, "dilithium", 0),
                            Item::new(Generator, "dilithium", 0),
                            Item::new(Microchip, "polonium", 1),
                            Item::new(Microchip, "promethium", 1)];
    //solve(part1_layout);
    solve(part2_layout);
}
<commit_msg>make this horrible code a little bit faster<commit_after>#[macro_use]
extern crate itertools;

use itertools::Itertools;
use std::collections::HashSet;

#[derive(Debug, PartialEq, Clone, Copy, Hash, Eq)]
enum ItemType {
    Generator,
    Microchip,
}

#[derive(Debug, Clone, PartialEq, Hash, Eq)]
struct Item {
    what: ItemType,
    compatible: &'static str,
    floor: u32,
}

impl Item {
    fn new(what: ItemType, compatible: &'static str, floor: u32) -> Item {
        Item {
            what: what,
            compatible: compatible,
            floor: floor,
        }
    }
}

fn valid_floor(items: &[&Item]) -> bool {
    let generators = items.iter()
        .filter(|&item| item.what == ItemType::Generator)
        .map(|item| item.compatible)
        .collect::<HashSet<_>>();
    if generators.is_empty() {
        return true;
    }

    let chips = items.iter()
        .filter(|&item| item.what == ItemType::Microchip)
        .map(|item| item.compatible)
        .collect::<HashSet<_>>();
    if chips.is_empty() {
        return true;
    }

    chips.is_subset(&generators)
}

fn valid_layout(items: &Vec<Item>) -> bool {
    [0, 1, 2, 3]
        .iter()
        .all(|&i| valid_floor(&items.iter().filter(|&item| item.floor == i).collect::<Vec<_>>()))
}

fn steps(current_floor: u32, layout: &Vec<Item>) -> Vec<(Vec<Item>, u32)> {
    let mut possible_layouts = Vec::new();

    // items on current floor
    let items = layout.iter()
        .enumerate()
        .filter(|&(_, ref item)| item.floor == current_floor)
        .collect::<Vec<_>>();

    let mut try_single = true;

    // possible double up moves
    if current_floor != 3 {
        for (i1, i2) in items.iter().tuple_combinations() {
            let &(i1, _) = i1;
            let &(i2, _) = i2;
            let new = layout.iter()
                .enumerate()
                .map(|(j, ref item)| if j == i1 || j == i2 {
                    Item::new(item.what, item.compatible, item.floor + 1)
                } else {
                    Item::new(item.what, item.compatible, item.floor)
                })
                .collect::<Vec<Item>>();
            if valid_layout(&new) {
                try_single = false;
                possible_layouts.push((new, current_floor + 1));
            }
        }
    }

    let items_on_0 = layout.iter().filter(|&item| item.floor == 0).count() != 0;
    let items_on_1 = layout.iter().filter(|&item| item.floor == 1).count() != 0;
    let try_down = current_floor != 0 || current_floor == 1 && items_on_0 || current_floor == 2 && (items_on_0 || items_on_1);

    for &(i, _) in &items {
        // down
        if try_down {
            let new = layout.iter()
                .enumerate()
                .map(|(j, ref item)| if i == j {
                    Item::new(item.what, item.compatible, item.floor - 1)
                } else {
                    Item::new(item.what, item.compatible, item.floor)
                })
                .collect::<Vec<Item>>();
            if valid_layout(&new) {
                possible_layouts.push((new, current_floor - 1));
            }
        }

        // only move one thing up if could not move double items
        if current_floor != 3 && try_single {
            let new = layout.iter()
                .enumerate()
                .map(|(j, ref item)| if i == j {
                    Item::new(item.what, item.compatible, item.floor + 1)
                } else {
                    Item::new(item.what, item.compatible, item.floor)
                })
                .collect::<Vec<Item>>();
            if valid_layout(&new) {
                possible_layouts.push((new, current_floor + 1));
            }
        }
    }

    possible_layouts
}

fn solve(start_layout: Vec<Item>) {
    //let mut layouts = steps(0, &start_layout);
    let mut layouts = vec![(start_layout.clone(), 0)];
    let mut cache: HashSet<(Vec<Item>, u32)> = HashSet::new();
    cache.insert((start_layout, 0));
    let mut stepcount = 0;
    let done = |items: &Vec<Item>| items.iter().all(|i| i.floor == 3);
    loop {
        stepcount += 1;
        let mut next = Vec::new();
        for (layout, floor) in layouts {
            let new_steps = steps(floor, &layout);
            for new_layout in new_steps {
                if done(&new_layout.0) {
                    println!("result: {}", stepcount);
                    return;
                }
                if !cache.contains(&new_layout) {
                    cache.insert(new_layout.clone());
                    next.push(new_layout);
                }
            }
        }
        layouts = next;
    }
}

fn main() {
    use ItemType::*;

    let part1_layout = vec![Item::new(Generator, "polonium", 0),
                            Item::new(Generator, "thulium", 0),
                            Item::new(Microchip, "thulium", 0),
                            Item::new(Generator, "promethium", 0),
                            Item::new(Generator, "ruthenium", 0),
                            Item::new(Microchip, "ruthenium", 0),
                            Item::new(Generator, "cobalt", 0),
                            Item::new(Microchip, "cobalt", 0),
                            Item::new(Microchip, "polonium", 1),
                            Item::new(Microchip, "promethium", 1)];

    let part2_layout = vec![Item::new(Generator, "polonium", 0),
                            Item::new(Generator, "thulium", 0),
                            Item::new(Microchip, "thulium", 0),
                            Item::new(Generator, "promethium", 0),
                            Item::new(Generator, "ruthenium", 0),
                            Item::new(Microchip, "ruthenium", 0),
                            Item::new(Generator, "cobalt", 0),
                            Item::new(Microchip, "cobalt", 0),
                            Item::new(Microchip, "elerium", 0),
                            Item::new(Generator, "elerium", 0),
                            Item::new(Microchip, "dilithium", 0),
                            Item::new(Generator, "dilithium", 0),
                            Item::new(Microchip, "polonium", 1),
                            Item::new(Microchip, "promethium", 1)];
    solve(part1_layout);
    solve(part2_layout);
}
<|endoftext|>


<commit_before>use sovrin::api::ErrorCode;
use sovrin::api::wallet::{
    sovrin_create_wallet,
    sovrin_open_wallet,
    sovrin_wallet_set_seq_no_for_value,
    sovrin_delete_wallet,
    sovrin_close_wallet
};

use utils::callback::CallbackUtils;
use utils::timeout::TimeoutUtils;

use std::ffi::CString;
use std::ptr::null;
use std::sync::mpsc::channel;

pub struct WalletUtils {}

impl WalletUtils {
    pub fn create_wallet(pool_name: &str, wallet_name: &str, xtype: Option<&str>, config: Option<&str>) -> Result<(), ErrorCode> {
        let (sender, receiver) = channel();

        let cb = Box::new(move |err| {
            sender.send(err).unwrap();
        });

        let (command_handle, cb) = CallbackUtils::closure_to_create_wallet_cb(cb);

        let pool_name = CString::new(pool_name).unwrap();
        let wallet_name = CString::new(wallet_name).unwrap();
        let xtype_str = xtype.map(|s| CString::new(s).unwrap()).unwrap_or(CString::new("").unwrap());
        let config_str = config.map(|s| CString::new(s).unwrap()).unwrap_or(CString::new("").unwrap());

        let err =
            sovrin_create_wallet(command_handle,
                                 pool_name.as_ptr(),
                                 wallet_name.as_ptr(),
                                 if xtype.is_some() { xtype_str.as_ptr() } else { null() },
                                 if config.is_some() { config_str.as_ptr() } else { null() },
                                 null(),
                                 cb);

        if err != ErrorCode::Success {
            return Err(err);
        }

        let err = receiver.recv_timeout(TimeoutUtils::short_timeout()).unwrap();

        if err != ErrorCode::Success {
            return Err(err);
        }

        Ok(())
    }

    pub fn open_wallet(wallet_name: &str, config: Option<&str>) -> Result<i32, ErrorCode> {
        let (sender, receiver) = channel();

        let cb = Box::new(move |err, handle| {
            sender.send((err, handle)).unwrap();
        });

        let (command_handle, cb) = CallbackUtils::closure_to_open_wallet_cb(cb);

        let wallet_name = CString::new(wallet_name).unwrap();
        let config_str = config.map(|s| CString::new(s).unwrap()).unwrap_or(CString::new("").unwrap());

        let err =
            sovrin_open_wallet(command_handle,
                               wallet_name.as_ptr(),
                               if config.is_some() { config_str.as_ptr() } else { null() },
                               null(),
                               cb);

        if err != ErrorCode::Success {
            return Err(err);
        }

        let (err, wallet_handle) = receiver.recv_timeout(TimeoutUtils::short_timeout()).unwrap();

        if err != ErrorCode::Success {
            return Err(err);
        }

        Ok(wallet_handle)
    }

    pub fn create_and_open_wallet(pool_name: &str, wallet_name: &str, xtype: &str) -> Result<i32, ErrorCode> {
        let (sender, receiver) = channel();
        let (open_sender, open_receiver) = channel();

        let cb = Box::new(move |err| {
            sender.send(err).unwrap();
        });
        let open_cb = Box::new(move |err, handle| {
            open_sender.send((err, handle)).unwrap();
        });

        let (command_handle, cb) = CallbackUtils::closure_to_create_wallet_cb(cb);
        let (open_command_handle, open_cb) = CallbackUtils::closure_to_open_wallet_cb(open_cb);

        let pool_name = CString::new(pool_name).unwrap();
        let wallet_name = CString::new(wallet_name).unwrap();
        let xtype = CString::new(xtype).unwrap();

        let err =
            sovrin_create_wallet(command_handle,
                                 pool_name.as_ptr(),
                                 wallet_name.as_ptr(),
                                 xtype.as_ptr(),
                                 null(),
                                 null(),
                                 cb);

        if err != ErrorCode::Success {
            return Err(err);
        }

        let err = receiver.recv_timeout(TimeoutUtils::short_timeout()).unwrap();

        if err != ErrorCode::Success {
            return Err(err);
        }

        let err =
            sovrin_open_wallet(open_command_handle,
                               wallet_name.as_ptr(),
                               null(),
                               null(),
                               open_cb);

        if err != ErrorCode::Success {
            return Err(err);
        }

        let (err, wallet_handle) = open_receiver.recv_timeout(TimeoutUtils::short_timeout()).unwrap();

        if err != ErrorCode::Success {
            return Err(err);
        }

        Ok(wallet_handle)
    }

    pub fn wallet_set_seq_no_for_value(wallet_handle: i32, claim_def_uuid: &str, claim_def_seq_no: i32) -> Result<(), ErrorCode> {
        let (sender, receiver) = channel();

        let cb = Box::new(move |err| {
            sender.send(err).unwrap();
        });

        let (command_handle, cb) = CallbackUtils::closure_to_wallet_set_seq_no_for_value_cb(cb);

        let claim_def_uuid = CString::new(claim_def_uuid).unwrap();

        let err =
            sovrin_wallet_set_seq_no_for_value(command_handle,
                                               wallet_handle,
                                               claim_def_uuid.as_ptr(),
                                               claim_def_seq_no,
                                               cb);

        if err != ErrorCode::Success {
            return Err(err);
        }

        let err = receiver.recv_timeout(TimeoutUtils::short_timeout()).unwrap();

        if err != ErrorCode::Success {
            return Err(err);
        }

        Ok(())
    }

    pub fn delete_wallet(wallet_name: &str) -> Result<(), ErrorCode> {
        let (sender, receiver) = channel();

        let cb = Box::new(move |err| {
            sender.send(err).unwrap();
        });

        let (command_handle, cb) = CallbackUtils::closure_to_delete_wallet_cb(cb);

        let wallet_name = CString::new(wallet_name).unwrap();

        let err =
            sovrin_delete_wallet(command_handle,
                                 wallet_name.as_ptr(),
                                 null(),
                                 cb);

        if err != ErrorCode::Success {
            return Err(err);
        }

        let err = receiver.recv_timeout(TimeoutUtils::short_timeout()).unwrap();

        if err != ErrorCode::Success {
            return Err(err);
        }

        Ok(())
    }

    pub fn close_wallet(wallet_handle: i32) -> Result<(), ErrorCode> {
        let (sender, receiver) = channel();

        let cb = Box::new(move |err| {
            sender.send(err).unwrap();
        });

        let (command_handle, cb) = CallbackUtils::closure_to_delete_wallet_cb(cb);

        let err =
            sovrin_close_wallet(command_handle,
                                wallet_handle,
                                cb);

        if err != ErrorCode::Success {
            return Err(err);
        }

        let err = receiver.recv_timeout(TimeoutUtils::short_timeout()).unwrap();

        if err != ErrorCode::Success {
            return Err(err);
        }

        Ok(())
    }
}<commit_msg>changes for wallet_set_seq_no_for_value<commit_after>use sovrin::api::ErrorCode;
use sovrin::api::wallet::{
    sovrin_create_wallet,
    sovrin_open_wallet,
    sovrin_wallet_set_seq_no_for_value,
    sovrin_delete_wallet,
    sovrin_close_wallet
};

use utils::callback::CallbackUtils;
use utils::timeout::TimeoutUtils;

use std::ffi::CString;
use std::ptr::null;
use std::sync::mpsc::channel;

pub struct WalletUtils {}

impl WalletUtils {
    pub fn create_wallet(pool_name: &str, wallet_name: &str, xtype: Option<&str>, config: Option<&str>) -> Result<(), ErrorCode> {
        let (sender, receiver) = channel();

        let cb = Box::new(move |err| {
            sender.send(err).unwrap();
        });

        let (command_handle, cb) = CallbackUtils::closure_to_create_wallet_cb(cb);

        let pool_name = CString::new(pool_name).unwrap();
        let wallet_name = CString::new(wallet_name).unwrap();
        let xtype_str = xtype.map(|s| CString::new(s).unwrap()).unwrap_or(CString::new("").unwrap());
        let config_str = config.map(|s| CString::new(s).unwrap()).unwrap_or(CString::new("").unwrap());

        let err =
            sovrin_create_wallet(command_handle,
                                 pool_name.as_ptr(),
                                 wallet_name.as_ptr(),
                                 if xtype.is_some() { xtype_str.as_ptr() } else { null() },
                                 if config.is_some() { config_str.as_ptr() } else { null() },
                                 null(),
                                 cb);

        if err != ErrorCode::Success {
            return Err(err);
        }

        let err = receiver.recv_timeout(TimeoutUtils::short_timeout()).unwrap();

        if err != ErrorCode::Success {
            return Err(err);
        }

        Ok(())
    }

    pub fn open_wallet(wallet_name: &str, config: Option<&str>) -> Result<i32, ErrorCode> {
        let (sender, receiver) = channel();

        let cb = Box::new(move |err, handle| {
            sender.send((err, handle)).unwrap();
        });

        let (command_handle, cb) = CallbackUtils::closure_to_open_wallet_cb(cb);

        let wallet_name = CString::new(wallet_name).unwrap();
        let config_str = config.map(|s| CString::new(s).unwrap()).unwrap_or(CString::new("").unwrap());

        let err =
            sovrin_open_wallet(command_handle,
                               wallet_name.as_ptr(),
                               if config.is_some() { config_str.as_ptr() } else { null() },
                               null(),
                               cb);

        if err != ErrorCode::Success {
            return Err(err);
        }

        let (err, wallet_handle) = receiver.recv_timeout(TimeoutUtils::short_timeout()).unwrap();

        if err != ErrorCode::Success {
            return Err(err);
        }

        Ok(wallet_handle)
    }

    pub fn create_and_open_wallet(pool_name: &str, wallet_name: &str, xtype: &str) -> Result<i32, ErrorCode> {
        let (sender, receiver) = channel();
        let (open_sender, open_receiver) = channel();

        let cb = Box::new(move |err| {
            sender.send(err).unwrap();
        });
        let open_cb = Box::new(move |err, handle| {
            open_sender.send((err, handle)).unwrap();
        });

        let (command_handle, cb) = CallbackUtils::closure_to_create_wallet_cb(cb);
        let (open_command_handle, open_cb) = CallbackUtils::closure_to_open_wallet_cb(open_cb);

        let pool_name = CString::new(pool_name).unwrap();
        let wallet_name = CString::new(wallet_name).unwrap();
        let xtype = CString::new(xtype).unwrap();

        let err =
            sovrin_create_wallet(command_handle,
                                 pool_name.as_ptr(),
                                 wallet_name.as_ptr(),
                                 xtype.as_ptr(),
                                 null(),
                                 null(),
                                 cb);

        if err != ErrorCode::Success {
            return Err(err);
        }

        let err = receiver.recv_timeout(TimeoutUtils::short_timeout()).unwrap();

        if err != ErrorCode::Success {
            return Err(err);
        }

        let err =
            sovrin_open_wallet(open_command_handle,
                               wallet_name.as_ptr(),
                               null(),
                               null(),
                               open_cb);

        if err != ErrorCode::Success {
            return Err(err);
        }

        let (err, wallet_handle) = open_receiver.recv_timeout(TimeoutUtils::short_timeout()).unwrap();

        if err != ErrorCode::Success {
            return Err(err);
        }

        Ok(wallet_handle)
    }

    pub fn wallet_set_seq_no_for_value(wallet_handle: i32, value: &str, seq_no: i32) -> Result<(), ErrorCode> {
        let (sender, receiver) = channel();

        let cb = Box::new(move |err| {
            sender.send(err).unwrap();
        });

        let (command_handle, cb) = CallbackUtils::closure_to_wallet_set_seq_no_for_value_cb(cb);

        let value = CString::new(value).unwrap();

        let err =
            sovrin_wallet_set_seq_no_for_value(command_handle,
                                               wallet_handle,
                                               value.as_ptr(),
                                               seq_no,
                                               cb);

        if err != ErrorCode::Success {
            return Err(err);
        }

        let err = receiver.recv_timeout(TimeoutUtils::short_timeout()).unwrap();

        if err != ErrorCode::Success {
            return Err(err);
        }

        Ok(())
    }

    pub fn delete_wallet(wallet_name: &str) -> Result<(), ErrorCode> {
        let (sender, receiver) = channel();

        let cb = Box::new(move |err| {
            sender.send(err).unwrap();
        });

        let (command_handle, cb) = CallbackUtils::closure_to_delete_wallet_cb(cb);

        let wallet_name = CString::new(wallet_name).unwrap();

        let err =
            sovrin_delete_wallet(command_handle,
                                 wallet_name.as_ptr(),
                                 null(),
                                 cb);

        if err != ErrorCode::Success {
            return Err(err);
        }

        let err = receiver.recv_timeout(TimeoutUtils::short_timeout()).unwrap();

        if err != ErrorCode::Success {
            return Err(err);
        }

        Ok(())
    }

    pub fn close_wallet(wallet_handle: i32) -> Result<(), ErrorCode> {
        let (sender, receiver) = channel();

        let cb = Box::new(move |err| {
            sender.send(err).unwrap();
        });

        let (command_handle, cb) = CallbackUtils::closure_to_delete_wallet_cb(cb);

        let err =
            sovrin_close_wallet(command_handle,
                                wallet_handle,
                                cb);

        if err != ErrorCode::Success {
            return Err(err);
        }

        let err = receiver.recv_timeout(TimeoutUtils::short_timeout()).unwrap();

        if err != ErrorCode::Success {
            return Err(err);
        }

        Ok(())
    }
}<|endoftext|>


<commit_before>//! The forwarder module shall act as wrapper for the ffi mangled lib.rs
//! calls, which shall be very thin and spare there, but extensive here
//! to prepare clean calls to adbfflutter.
use crate::{
    common::paths::SearchPath,
    ctrl::{ForwardNetMsg, UiUpdateMsg},
    data::{collection::Collection, ipc::IPC},
    net::subs::peer_representation,
    shared,
};
use async_std::task;
use crossbeam::{sync::WaitGroup, unbounded};
use std::{
    sync::{mpsc::channel, Arc, Mutex},
    thread,
};

/// just return the number of audio files found for now
pub fn ffi_file_count_good(input_path: Vec<String>) -> u32 {
    // prepare data
    let cleaned_paths = SearchPath::new(&input_path);
    let search_path = Arc::new(Mutex::new(cleaned_paths));

    let (tx, _rx) = channel::<UiUpdateMsg>();
    let synced_to_ui_messages = Arc::new(Mutex::new(tx.clone()));
    let has_ui = false;

    // set up data and run search
    let collection_protected = Arc::new(Mutex::new(Collection::new()));
    let output_data_return_handle = shared::collection_search(
        collection_protected,
        search_path,
        synced_to_ui_messages,
        has_ui,
    );

    // scope and block trickery for lifetime and mutability
    output_data_return_handle.nr_found_songs
}

/// return the peer hash for testing yet
pub async fn ffi_new_peer() -> u64 {
    // mock input parameters
    let dummy_wait_net_thread = WaitGroup::new();
    let (ui_sender, reactor) = channel::<UiUpdateMsg>();
    let (_, dummy_ipc_receive) = unbounded::<IPC>();

    // todo: make it a lazy static as RUNTIME, to also hold the same IP, otherwise it will
    //       always change its IP!
    let single_shot_net_thread = thread::Builder::new()
        .name("app_net".into())
        .spawn(move || {
            task::block_on(async move {
                let _ =
                    shared::net_search(dummy_wait_net_thread, Some(ui_sender), dummy_ipc_receive)
                        .await;
            });
        })
        .unwrap();

    // very interesting, the compiler is awesome!!
    let out;

    // loop over fixme: (very cheap version here, that could be done more elegantly) with poll
    loop {
        if let Ok(reaction) = reactor.try_recv() {
            match reaction {
                UiUpdateMsg::CollectionUpdate(_, _) => {}
                UiUpdateMsg::NetUpdate(net_message) => {
                    match net_message {
                        ForwardNetMsg::Add(peer) => {
                            // yet only id is interesting
                            out = peer_representation::peer_to_hash(&peer.id);
                            break;
                        }
                        ForwardNetMsg::Delete(_peer_id) => {}
                        ForwardNetMsg::Stats(_) => {}
                    }
                }
                UiUpdateMsg::PeerSearchFinished(_peer_id, _data) => {}
                UiUpdateMsg::StopUI => {}
            }
        }
    }
    // kill this big thread / fixme: very inefficent yet
    drop(single_shot_net_thread);
    out
}
<commit_msg>[net] not yet working async event loop in static ref<commit_after>//! The forwarder module shall act as wrapper for the ffi mangled lib.rs
//! calls, which shall be very thin and spare there, but extensive here
//! to prepare clean calls to adbfflutter.
use crate::{
    common::paths::SearchPath,
    ctrl::{ForwardNetMsg, UiUpdateMsg},
    data::{collection::Collection, ipc::IPC},
    net::subs::peer_representation,
    shared,
};
use async_std::task;
use futures::{future::FutureExt, select};

use crossbeam::{sync::WaitGroup, unbounded, Receiver as CReceiver};
use std::{
    sync::{mpsc::channel, Arc, Mutex},
    thread,
};

lazy_static! {
    /// a static runtime for all network activity
    static ref NET_RUNTIME: CReceiver<UiUpdateMsg> = create_net_runtime();
}

/// just return the number of audio files found for now
pub fn ffi_file_count_good(input_path: Vec<String>) -> u32 {
    // prepare data
    let cleaned_paths = SearchPath::new(&input_path);
    let search_path = Arc::new(Mutex::new(cleaned_paths));

    let (tx, _rx) = channel::<UiUpdateMsg>();
    let synced_to_ui_messages = Arc::new(Mutex::new(tx.clone()));
    let has_ui = false;

    // set up data and run search
    let collection_protected = Arc::new(Mutex::new(Collection::new()));
    let output_data_return_handle = shared::collection_search(
        collection_protected,
        search_path,
        synced_to_ui_messages,
        has_ui,
    );

    // scope and block trickery for lifetime and mutability
    output_data_return_handle.nr_found_songs
}

/// return the peer hash for testing yet
pub async fn ffi_new_peer() -> u64 {
    // get network runtime
    let net_receiver = &NET_RUNTIME.clone();

    // very interesting, the compiler is awesome!!
    let out;
    loop {
        if let Ok(reaction) = net_receiver.try_recv() {
            match reaction {
                UiUpdateMsg::CollectionUpdate(_, _) => {}
                UiUpdateMsg::NetUpdate(net_message) => {
                    match net_message {
                        ForwardNetMsg::Add(peer) => {
                            // yet only id is interesting
                            out = peer_representation::peer_to_hash(&peer.id);
                            break;
                        }
                        ForwardNetMsg::Delete(_peer_id) => {}
                        ForwardNetMsg::Stats(_) => {}
                    }
                }
                UiUpdateMsg::PeerSearchFinished(_peer_id, _data) => {}
                UiUpdateMsg::StopUI => {}
            }
        }
    }
    out
}

/// open a net thread and return receiver to receive from thread
fn create_net_runtime() -> CReceiver<UiUpdateMsg> {
    // mock input parameters
    // outgoing crossbeam receiver
    let (forwarder_ui, receiver_ui) = unbounded::<UiUpdateMsg>();
    println!("creating...");
    // net thread with forwarding message from normal receiver to crossbeam receiver
    thread::Builder::new()
        .name("app_net".into())
        .spawn(move || {
            println!("thread spawned...");
            let dummy_wait_net_thread = WaitGroup::new();
            let (ui_sender, reactor) = channel::<UiUpdateMsg>();
            let (_, dummy_ipc_receive) = unbounded::<IPC>();

            task::block_on(async move {
                println!("async spawned...");
                let net_fut =
                    shared::net_search(dummy_wait_net_thread, Some(ui_sender), dummy_ipc_receive)
                        .fuse();
                let mut net = Box::pin(net_fut);
                println!("net_creating...");

                loop {
                    println!("trying...");
                    let mut receiver = Box::pin(
                        async {
                            println!("rec1...");
                            let out = reactor.try_recv();
                            println!("rec2...");
                            out
                        }
                        .fuse(),
                    );
                    println!("pinned receiver...");
                    select! {
                        _ = receiver => {
                            println!("receiver...");
                            match receiver.await {
                                Ok(received_msg) => {
                                    println!("receiver ok...");
                                    if forwarder_ui.send(received_msg).is_err() {
                                        panic!("wasn't captured");
                                    }
                                },
                                Err(_) => {}, // is all fine, received was bad, maybe end?
                            }
                        },
                        _ = net => unreachable!(), // should run forever
                    }
                }
                // finish the whole lazy stuff
                //drop(single_shot_net_thread);
            })
        })
        .unwrap();
    receiver_ui
}

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

    #[test]
    fn external_test_net_runtime() {
        //
        task::block_on(async move {
            ffi_new_peer().await;
        });
        assert!(false);
    }
}
<|endoftext|>


<commit_before>/*
gl/src/gl_wrapper/mod.rs, 2017-07-19

Copyright (c) 2017 Juuso Tuononen

This file is licensed under

Apache License, Version 2.0

or

MIT License
*/

pub mod gl_raw {

    //! Raw OpenGL bindings form `gl_generator` crate

    #[cfg(feature = "gles")]
    pub use gl_es_generated::*;

    #[cfg(not(feature = "gles"))]
    pub use gl_generated::*;
}

pub mod shader;
pub mod uniform;
pub mod buffer;
pub mod texture;

use gl_raw::types::*;

use std::ffi::CStr;

/// OpenGL error types
#[derive(Debug)]
pub enum GLError {
    InvalidEnum,
    InvalidValue,
    InvalidOperation,
    InvalidFramebufferOperation,
    OutOfMemory,
    UnknownError(GLenum),
}

impl GLError {
    /// Get next error from OpenGL. Returns `Err(GLError)` if there is an error.
    pub fn get_error() -> Result<(),GLError> {
        let error;

        unsafe {
            error = gl_raw::GetError();
        }

        if error == gl_raw::NO_ERROR {
            return Ok(());
        }

        let error = match error {
            gl_raw::INVALID_ENUM => GLError::InvalidEnum,
            gl_raw::INVALID_VALUE => GLError::InvalidValue,
            gl_raw::INVALID_OPERATION => GLError::InvalidOperation,
            gl_raw::OUT_OF_MEMORY => GLError::OutOfMemory,
            gl_raw::INVALID_FRAMEBUFFER_OPERATION => GLError::InvalidFramebufferOperation,
            unknown_error => GLError::UnknownError(unknown_error),
        };

        Err(error)
    }
}

/// Return OpenGL version string.
pub fn get_version_string<'a>() -> &'a CStr {
    unsafe {
        let ptr_to_str = gl_raw::GetString(gl_raw::VERSION) as *const i8;
        CStr::from_ptr(ptr_to_str)
    }
}<commit_msg>cast OpenGL's GetString function's return type to c_char pointer<commit_after>/*
gl/src/gl_wrapper/mod.rs, 2017-08-05

Copyright (c) 2017 Juuso Tuononen

This file is licensed under

Apache License, Version 2.0

or

MIT License
*/

pub mod gl_raw {

    //! Raw OpenGL bindings form `gl_generator` crate

    #[cfg(feature = "gles")]
    pub use gl_es_generated::*;

    #[cfg(not(feature = "gles"))]
    pub use gl_generated::*;
}

pub mod shader;
pub mod uniform;
pub mod buffer;
pub mod texture;

use gl_raw::types::*;

use std::os::raw::c_char;
use std::ffi::CStr;

/// OpenGL error types
#[derive(Debug)]
pub enum GLError {
    InvalidEnum,
    InvalidValue,
    InvalidOperation,
    InvalidFramebufferOperation,
    OutOfMemory,
    UnknownError(GLenum),
}

impl GLError {
    /// Get next error from OpenGL. Returns `Err(GLError)` if there is an error.
    pub fn get_error() -> Result<(),GLError> {
        let error;

        unsafe {
            error = gl_raw::GetError();
        }

        if error == gl_raw::NO_ERROR {
            return Ok(());
        }

        let error = match error {
            gl_raw::INVALID_ENUM => GLError::InvalidEnum,
            gl_raw::INVALID_VALUE => GLError::InvalidValue,
            gl_raw::INVALID_OPERATION => GLError::InvalidOperation,
            gl_raw::OUT_OF_MEMORY => GLError::OutOfMemory,
            gl_raw::INVALID_FRAMEBUFFER_OPERATION => GLError::InvalidFramebufferOperation,
            unknown_error => GLError::UnknownError(unknown_error),
        };

        Err(error)
    }
}

/// Return OpenGL version string.
pub fn get_version_string<'a>() -> &'a CStr {
    unsafe {
        let ptr_to_str = gl_raw::GetString(gl_raw::VERSION) as *const c_char;
        CStr::from_ptr(ptr_to_str)
    }
}<|endoftext|>


<commit_before>use proc_macro2::{Delimiter, Group, TokenStream, TokenTree};
use quote::{format_ident, quote, ToTokens};
use std::iter::once;
use syn::parse::{Nothing, ParseStream};
use syn::{
    braced, bracketed, parenthesized, token, Attribute, Ident, Index, LitInt, LitStr, Result, Token,
};

pub struct Attrs {
    pub display: Option<Display>,
    pub source: bool,
}

pub struct Display {
    pub fmt: LitStr,
    pub args: TokenStream,
    pub was_shorthand: bool,
}

pub fn get(input: &[Attribute]) -> Result<Attrs> {
    let mut attrs = Attrs {
        display: None,
        source: false,
    };

    for attr in input {
        if attr.path.is_ident("error") {
            let display = parse_display(attr)?;
            attrs.display = Some(display);
        } else if attr.path.is_ident("source") {
            parse_source(attr)?;
            attrs.source = true;
        }
    }

    Ok(attrs)
}

fn parse_display(attr: &Attribute) -> Result<Display> {
    attr.parse_args_with(|input: ParseStream| {
        let mut display = Display {
            fmt: input.parse()?,
            args: parse_token_expr(input, false)?,
            was_shorthand: false,
        };
        display.expand_shorthand();
        Ok(display)
    })
}

fn parse_token_expr(input: ParseStream, mut last_is_comma: bool) -> Result<TokenStream> {
    let mut tokens = TokenStream::new();
    while !input.is_empty() {
        if last_is_comma && input.peek(Token![.]) {
            if input.peek2(Ident) {
                input.parse::<Token![.]>()?;
                last_is_comma = false;
                continue;
            }
            if input.peek2(LitInt) {
                input.parse::<Token![.]>()?;
                let int: Index = input.parse()?;
                let ident = format_ident!("_{}", int.index, span = int.span);
                tokens.extend(once(TokenTree::Ident(ident)));
                last_is_comma = false;
                continue;
            }
        }
        last_is_comma = input.peek(Token![,]);
        let token: TokenTree = if input.peek(token::Paren) {
            let content;
            let delimiter = parenthesized!(content in input);
            let nested = parse_token_expr(&content, true)?;
            let mut group = Group::new(Delimiter::Parenthesis, nested);
            group.set_span(delimiter.span);
            TokenTree::Group(group)
        } else if input.peek(token::Brace) {
            let content;
            let delimiter = braced!(content in input);
            let nested = parse_token_expr(&content, true)?;
            let mut group = Group::new(Delimiter::Brace, nested);
            group.set_span(delimiter.span);
            TokenTree::Group(group)
        } else if input.peek(token::Bracket) {
            let content;
            let delimiter = bracketed!(content in input);
            let nested = parse_token_expr(&content, true)?;
            let mut group = Group::new(Delimiter::Bracket, nested);
            group.set_span(delimiter.span);
            TokenTree::Group(group)
        } else {
            input.parse()?
        };
        tokens.extend(once(token));
    }
    Ok(tokens)
}

fn parse_source(attr: &Attribute) -> Result<()> {
    syn::parse2::<Nothing>(attr.tokens.clone())?;
    Ok(())
}

impl ToTokens for Display {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let fmt = &self.fmt;
        let args = &self.args;
        if self.was_shorthand && fmt.value() == "{}" {
            let arg = args.clone().into_iter().nth(1).unwrap();
            tokens.extend(quote! {
                std::fmt::Display::fmt(#arg, formatter)
            });
        } else if self.was_shorthand && fmt.value() == "{:?}" {
            let arg = args.clone().into_iter().nth(1).unwrap();
            tokens.extend(quote! {
                std::fmt::Debug::fmt(#arg, formatter)
            });
        } else {
            tokens.extend(quote! {
                write!(formatter, #fmt #args)
            });
        }
    }
}
<commit_msg>Detect duplicate attributes on the same syntax tree node<commit_after>use proc_macro2::{Delimiter, Group, TokenStream, TokenTree};
use quote::{format_ident, quote, ToTokens};
use std::iter::once;
use syn::parse::{Nothing, ParseStream};
use syn::{
    braced, bracketed, parenthesized, token, Attribute, Error, Ident, Index, LitInt, LitStr,
    Result, Token,
};

pub struct Attrs {
    pub display: Option<Display>,
    pub source: bool,
}

pub struct Display {
    pub fmt: LitStr,
    pub args: TokenStream,
    pub was_shorthand: bool,
}

pub fn get(input: &[Attribute]) -> Result<Attrs> {
    let mut attrs = Attrs {
        display: None,
        source: false,
    };

    for attr in input {
        if attr.path.is_ident("error") {
            let display = parse_display(attr)?;
            if attrs.display.is_some() {
                return Err(Error::new_spanned(
                    attr,
                    "only one #[error(...)] attribute is allowed",
                ));
            }
            attrs.display = Some(display);
        } else if attr.path.is_ident("source") {
            parse_source(attr)?;
            if attrs.source {
                return Err(Error::new_spanned(attr, "duplicate #[source] attribute"));
            }
            attrs.source = true;
        }
    }

    Ok(attrs)
}

fn parse_display(attr: &Attribute) -> Result<Display> {
    attr.parse_args_with(|input: ParseStream| {
        let mut display = Display {
            fmt: input.parse()?,
            args: parse_token_expr(input, false)?,
            was_shorthand: false,
        };
        display.expand_shorthand();
        Ok(display)
    })
}

fn parse_token_expr(input: ParseStream, mut last_is_comma: bool) -> Result<TokenStream> {
    let mut tokens = TokenStream::new();
    while !input.is_empty() {
        if last_is_comma && input.peek(Token![.]) {
            if input.peek2(Ident) {
                input.parse::<Token![.]>()?;
                last_is_comma = false;
                continue;
            }
            if input.peek2(LitInt) {
                input.parse::<Token![.]>()?;
                let int: Index = input.parse()?;
                let ident = format_ident!("_{}", int.index, span = int.span);
                tokens.extend(once(TokenTree::Ident(ident)));
                last_is_comma = false;
                continue;
            }
        }
        last_is_comma = input.peek(Token![,]);
        let token: TokenTree = if input.peek(token::Paren) {
            let content;
            let delimiter = parenthesized!(content in input);
            let nested = parse_token_expr(&content, true)?;
            let mut group = Group::new(Delimiter::Parenthesis, nested);
            group.set_span(delimiter.span);
            TokenTree::Group(group)
        } else if input.peek(token::Brace) {
            let content;
            let delimiter = braced!(content in input);
            let nested = parse_token_expr(&content, true)?;
            let mut group = Group::new(Delimiter::Brace, nested);
            group.set_span(delimiter.span);
            TokenTree::Group(group)
        } else if input.peek(token::Bracket) {
            let content;
            let delimiter = bracketed!(content in input);
            let nested = parse_token_expr(&content, true)?;
            let mut group = Group::new(Delimiter::Bracket, nested);
            group.set_span(delimiter.span);
            TokenTree::Group(group)
        } else {
            input.parse()?
        };
        tokens.extend(once(token));
    }
    Ok(tokens)
}

fn parse_source(attr: &Attribute) -> Result<()> {
    syn::parse2::<Nothing>(attr.tokens.clone())?;
    Ok(())
}

impl ToTokens for Display {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let fmt = &self.fmt;
        let args = &self.args;
        if self.was_shorthand && fmt.value() == "{}" {
            let arg = args.clone().into_iter().nth(1).unwrap();
            tokens.extend(quote! {
                std::fmt::Display::fmt(#arg, formatter)
            });
        } else if self.was_shorthand && fmt.value() == "{:?}" {
            let arg = args.clone().into_iter().nth(1).unwrap();
            tokens.extend(quote! {
                std::fmt::Debug::fmt(#arg, formatter)
            });
        } else {
            tokens.extend(quote! {
                write!(formatter, #fmt #args)
            });
        }
    }
}
<|endoftext|>


<commit_before>//! Densely numbered entity references as mapping keys.
use crate::boxed_slice::BoxedSlice;
use crate::iter::{Iter, IterMut};
use crate::keys::Keys;
use crate::EntityRef;
use std::iter::FromIterator;
use std::marker::PhantomData;
use std::ops::{Index, IndexMut};
use std::slice;
use std::vec::Vec;

/// A primary mapping `K -> V` allocating dense entity references.
///
/// The `PrimaryMap` data structure uses the dense index space to implement a map with a vector.
///
/// A primary map contains the main definition of an entity, and it can be used to allocate new
/// entity references with the `push` method.
///
/// There should only be a single `PrimaryMap` instance for a given `EntityRef` type, otherwise
/// conflicting references will be created. Using unknown keys for indexing will cause a panic.
///
/// Note that `PrimaryMap` doesn't implement `Deref` or `DerefMut`, which would allow
/// `&PrimaryMap<K, V>` to convert to `&[V]`. One of the main advantages of `PrimaryMap` is
/// that it only allows indexing with the distinct `EntityRef` key type, so converting to a
/// plain slice would make it easier to use incorrectly. To make a slice of a `PrimaryMap`, use
/// `into_boxed_slice`.
#[derive(Debug, Clone)]
pub struct PrimaryMap<K, V>
where
    K: EntityRef,
{
    elems: Vec<V>,
    unused: PhantomData<K>,
}

impl<K, V> PrimaryMap<K, V>
where
    K: EntityRef,
{
    /// Create a new empty map.
    pub fn new() -> Self {
        Self {
            elems: Vec::new(),
            unused: PhantomData,
        }
    }

    /// Create a new empty map with the given capacity.
    pub fn with_capacity(capacity: usize) -> Self {
        Self {
            elems: Vec::with_capacity(capacity),
            unused: PhantomData,
        }
    }

    /// Check if `k` is a valid key in the map.
    pub fn is_valid(&self, k: K) -> bool {
        k.index() < self.elems.len()
    }

    /// Get the element at `k` if it exists.
    pub fn get(&self, k: K) -> Option<&V> {
        self.elems.get(k.index())
    }

    /// Get the element at `k` if it exists, mutable version.
    pub fn get_mut(&mut self, k: K) -> Option<&mut V> {
        self.elems.get_mut(k.index())
    }

    /// Is this map completely empty?
    pub fn is_empty(&self) -> bool {
        self.elems.is_empty()
    }

    /// Get the total number of entity references created.
    pub fn len(&self) -> usize {
        self.elems.len()
    }

    /// Iterate over all the keys in this map.
    pub fn keys(&self) -> Keys<K> {
        Keys::with_len(self.elems.len())
    }

    /// Iterate over all the values in this map.
    pub fn values(&self) -> slice::Iter<V> {
        self.elems.iter()
    }

    /// Iterate over all the values in this map, mutable edition.
    pub fn values_mut(&mut self) -> slice::IterMut<V> {
        self.elems.iter_mut()
    }

    /// Iterate over all the keys and values in this map.
    pub fn iter(&self) -> Iter<K, V> {
        Iter::new(self.elems.iter())
    }

    /// Iterate over all the keys and values in this map, mutable edition.
    pub fn iter_mut(&mut self) -> IterMut<K, V> {
        IterMut::new(self.elems.iter_mut())
    }

    /// Remove all entries from this map.
    pub fn clear(&mut self) {
        self.elems.clear()
    }

    /// Get the key that will be assigned to the next pushed value.
    pub fn next_key(&self) -> K {
        K::new(self.elems.len())
    }

    /// Append `v` to the mapping, assigning a new key which is returned.
    pub fn push(&mut self, v: V) -> K {
        let k = self.next_key();
        self.elems.push(v);
        k
    }

    /// Returns the last element that was inserted in the map.
    pub fn last(&self) -> Option<&V> {
        self.elems.last()
    }

    /// Reserves capacity for at least `additional` more elements to be inserted.
    pub fn reserve(&mut self, additional: usize) {
        self.elems.reserve(additional)
    }

    /// Reserves the minimum capacity for exactly `additional` more elements to be inserted.
    pub fn reserve_exact(&mut self, additional: usize) {
        self.elems.reserve_exact(additional)
    }

    /// Consumes this `PrimaryMap` and produces a `BoxedSlice`.
    pub fn into_boxed_slice(self) -> BoxedSlice<K, V> {
        unsafe { BoxedSlice::<K, V>::from_raw(Box::<[V]>::into_raw(self.elems.into_boxed_slice())) }
    }
}

/// Immutable indexing into an `PrimaryMap`.
/// The indexed value must be in the map.
impl<K, V> Index<K> for PrimaryMap<K, V>
where
    K: EntityRef,
{
    type Output = V;

    fn index(&self, k: K) -> &V {
        &self.elems[k.index()]
    }
}

/// Mutable indexing into an `PrimaryMap`.
impl<K, V> IndexMut<K> for PrimaryMap<K, V>
where
    K: EntityRef,
{
    fn index_mut(&mut self, k: K) -> &mut V {
        &mut self.elems[k.index()]
    }
}

impl<'a, K, V> IntoIterator for &'a PrimaryMap<K, V>
where
    K: EntityRef,
{
    type Item = (K, &'a V);
    type IntoIter = Iter<'a, K, V>;

    fn into_iter(self) -> Self::IntoIter {
        Iter::new(self.elems.iter())
    }
}

impl<'a, K, V> IntoIterator for &'a mut PrimaryMap<K, V>
where
    K: EntityRef,
{
    type Item = (K, &'a mut V);
    type IntoIter = IterMut<'a, K, V>;

    fn into_iter(self) -> Self::IntoIter {
        IterMut::new(self.elems.iter_mut())
    }
}

impl<K, V> FromIterator<V> for PrimaryMap<K, V>
where
    K: EntityRef,
{
    fn from_iter<T>(iter: T) -> Self
    where
        T: IntoIterator<Item = V>,
    {
        Self {
            elems: Vec::from_iter(iter),
            unused: PhantomData,
        }
    }
}

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

    // `EntityRef` impl for testing.
    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
    struct E(u32);

    impl EntityRef for E {
        fn new(i: usize) -> Self {
            E(i as u32)
        }
        fn index(self) -> usize {
            self.0 as usize
        }
    }

    #[test]
    fn basic() {
        let r0 = E(0);
        let r1 = E(1);
        let m = PrimaryMap::<E, isize>::new();

        let v: Vec<E> = m.keys().collect();
        assert_eq!(v, []);

        assert!(!m.is_valid(r0));
        assert!(!m.is_valid(r1));
    }

    #[test]
    fn push() {
        let mut m = PrimaryMap::new();
        let k0: E = m.push(12);
        let k1 = m.push(33);

        assert_eq!(m[k0], 12);
        assert_eq!(m[k1], 33);

        let v: Vec<E> = m.keys().collect();
        assert_eq!(v, [k0, k1]);
    }

    #[test]
    fn iter() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 0;
        for (key, value) in &m {
            assert_eq!(key.index(), i);
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
            i += 1;
        }
        i = 0;
        for (key_mut, value_mut) in m.iter_mut() {
            assert_eq!(key_mut.index(), i);
            match i {
                0 => assert_eq!(*value_mut, 12),
                1 => assert_eq!(*value_mut, 33),
                _ => panic!(),
            }
            i += 1;
        }
    }

    #[test]
    fn iter_rev() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 2;
        for (key, value) in m.iter().rev() {
            i -= 1;
            assert_eq!(key.index(), i);
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
        }

        i = 2;
        for (key, value) in m.iter_mut().rev() {
            i -= 1;
            assert_eq!(key.index(), i);
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
        }
    }
    #[test]
    fn keys() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 0;
        for key in m.keys() {
            assert_eq!(key.index(), i);
            i += 1;
        }
    }

    #[test]
    fn keys_rev() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 2;
        for key in m.keys().rev() {
            i -= 1;
            assert_eq!(key.index(), i);
        }
    }

    #[test]
    fn values() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 0;
        for value in m.values() {
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
            i += 1;
        }
        i = 0;
        for value_mut in m.values_mut() {
            match i {
                0 => assert_eq!(*value_mut, 12),
                1 => assert_eq!(*value_mut, 33),
                _ => panic!(),
            }
            i += 1;
        }
    }

    #[test]
    fn values_rev() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 2;
        for value in m.values().rev() {
            i -= 1;
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
        }
        i = 2;
        for value_mut in m.values_mut().rev() {
            i -= 1;
            match i {
                0 => assert_eq!(*value_mut, 12),
                1 => assert_eq!(*value_mut, 33),
                _ => panic!(),
            }
        }
    }

    #[test]
    fn from_iter() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let n = m.values().collect::<PrimaryMap<E, _>>();
        assert!(m.len() == n.len());
        for (me, ne) in m.values().zip(n.values()) {
            assert!(*me == **ne);
        }
    }
}
<commit_msg>Add a `shrink_to_fit` function to `PrimaryMap`.<commit_after>//! Densely numbered entity references as mapping keys.
use crate::boxed_slice::BoxedSlice;
use crate::iter::{Iter, IterMut};
use crate::keys::Keys;
use crate::EntityRef;
use std::iter::FromIterator;
use std::marker::PhantomData;
use std::ops::{Index, IndexMut};
use std::slice;
use std::vec::Vec;

/// A primary mapping `K -> V` allocating dense entity references.
///
/// The `PrimaryMap` data structure uses the dense index space to implement a map with a vector.
///
/// A primary map contains the main definition of an entity, and it can be used to allocate new
/// entity references with the `push` method.
///
/// There should only be a single `PrimaryMap` instance for a given `EntityRef` type, otherwise
/// conflicting references will be created. Using unknown keys for indexing will cause a panic.
///
/// Note that `PrimaryMap` doesn't implement `Deref` or `DerefMut`, which would allow
/// `&PrimaryMap<K, V>` to convert to `&[V]`. One of the main advantages of `PrimaryMap` is
/// that it only allows indexing with the distinct `EntityRef` key type, so converting to a
/// plain slice would make it easier to use incorrectly. To make a slice of a `PrimaryMap`, use
/// `into_boxed_slice`.
#[derive(Debug, Clone)]
pub struct PrimaryMap<K, V>
where
    K: EntityRef,
{
    elems: Vec<V>,
    unused: PhantomData<K>,
}

impl<K, V> PrimaryMap<K, V>
where
    K: EntityRef,
{
    /// Create a new empty map.
    pub fn new() -> Self {
        Self {
            elems: Vec::new(),
            unused: PhantomData,
        }
    }

    /// Create a new empty map with the given capacity.
    pub fn with_capacity(capacity: usize) -> Self {
        Self {
            elems: Vec::with_capacity(capacity),
            unused: PhantomData,
        }
    }

    /// Check if `k` is a valid key in the map.
    pub fn is_valid(&self, k: K) -> bool {
        k.index() < self.elems.len()
    }

    /// Get the element at `k` if it exists.
    pub fn get(&self, k: K) -> Option<&V> {
        self.elems.get(k.index())
    }

    /// Get the element at `k` if it exists, mutable version.
    pub fn get_mut(&mut self, k: K) -> Option<&mut V> {
        self.elems.get_mut(k.index())
    }

    /// Is this map completely empty?
    pub fn is_empty(&self) -> bool {
        self.elems.is_empty()
    }

    /// Get the total number of entity references created.
    pub fn len(&self) -> usize {
        self.elems.len()
    }

    /// Iterate over all the keys in this map.
    pub fn keys(&self) -> Keys<K> {
        Keys::with_len(self.elems.len())
    }

    /// Iterate over all the values in this map.
    pub fn values(&self) -> slice::Iter<V> {
        self.elems.iter()
    }

    /// Iterate over all the values in this map, mutable edition.
    pub fn values_mut(&mut self) -> slice::IterMut<V> {
        self.elems.iter_mut()
    }

    /// Iterate over all the keys and values in this map.
    pub fn iter(&self) -> Iter<K, V> {
        Iter::new(self.elems.iter())
    }

    /// Iterate over all the keys and values in this map, mutable edition.
    pub fn iter_mut(&mut self) -> IterMut<K, V> {
        IterMut::new(self.elems.iter_mut())
    }

    /// Remove all entries from this map.
    pub fn clear(&mut self) {
        self.elems.clear()
    }

    /// Get the key that will be assigned to the next pushed value.
    pub fn next_key(&self) -> K {
        K::new(self.elems.len())
    }

    /// Append `v` to the mapping, assigning a new key which is returned.
    pub fn push(&mut self, v: V) -> K {
        let k = self.next_key();
        self.elems.push(v);
        k
    }

    /// Returns the last element that was inserted in the map.
    pub fn last(&self) -> Option<&V> {
        self.elems.last()
    }

    /// Reserves capacity for at least `additional` more elements to be inserted.
    pub fn reserve(&mut self, additional: usize) {
        self.elems.reserve(additional)
    }

    /// Reserves the minimum capacity for exactly `additional` more elements to be inserted.
    pub fn reserve_exact(&mut self, additional: usize) {
        self.elems.reserve_exact(additional)
    }

    /// Shrinks the capacity of the `PrimaryMap` as much as possible.
    pub fn shrink_to_fit(&mut self) {
        self.elems.shrink_to_fit()
    }

    /// Consumes this `PrimaryMap` and produces a `BoxedSlice`.
    pub fn into_boxed_slice(self) -> BoxedSlice<K, V> {
        unsafe { BoxedSlice::<K, V>::from_raw(Box::<[V]>::into_raw(self.elems.into_boxed_slice())) }
    }
}

/// Immutable indexing into an `PrimaryMap`.
/// The indexed value must be in the map.
impl<K, V> Index<K> for PrimaryMap<K, V>
where
    K: EntityRef,
{
    type Output = V;

    fn index(&self, k: K) -> &V {
        &self.elems[k.index()]
    }
}

/// Mutable indexing into an `PrimaryMap`.
impl<K, V> IndexMut<K> for PrimaryMap<K, V>
where
    K: EntityRef,
{
    fn index_mut(&mut self, k: K) -> &mut V {
        &mut self.elems[k.index()]
    }
}

impl<'a, K, V> IntoIterator for &'a PrimaryMap<K, V>
where
    K: EntityRef,
{
    type Item = (K, &'a V);
    type IntoIter = Iter<'a, K, V>;

    fn into_iter(self) -> Self::IntoIter {
        Iter::new(self.elems.iter())
    }
}

impl<'a, K, V> IntoIterator for &'a mut PrimaryMap<K, V>
where
    K: EntityRef,
{
    type Item = (K, &'a mut V);
    type IntoIter = IterMut<'a, K, V>;

    fn into_iter(self) -> Self::IntoIter {
        IterMut::new(self.elems.iter_mut())
    }
}

impl<K, V> FromIterator<V> for PrimaryMap<K, V>
where
    K: EntityRef,
{
    fn from_iter<T>(iter: T) -> Self
    where
        T: IntoIterator<Item = V>,
    {
        Self {
            elems: Vec::from_iter(iter),
            unused: PhantomData,
        }
    }
}

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

    // `EntityRef` impl for testing.
    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
    struct E(u32);

    impl EntityRef for E {
        fn new(i: usize) -> Self {
            E(i as u32)
        }
        fn index(self) -> usize {
            self.0 as usize
        }
    }

    #[test]
    fn basic() {
        let r0 = E(0);
        let r1 = E(1);
        let m = PrimaryMap::<E, isize>::new();

        let v: Vec<E> = m.keys().collect();
        assert_eq!(v, []);

        assert!(!m.is_valid(r0));
        assert!(!m.is_valid(r1));
    }

    #[test]
    fn push() {
        let mut m = PrimaryMap::new();
        let k0: E = m.push(12);
        let k1 = m.push(33);

        assert_eq!(m[k0], 12);
        assert_eq!(m[k1], 33);

        let v: Vec<E> = m.keys().collect();
        assert_eq!(v, [k0, k1]);
    }

    #[test]
    fn iter() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 0;
        for (key, value) in &m {
            assert_eq!(key.index(), i);
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
            i += 1;
        }
        i = 0;
        for (key_mut, value_mut) in m.iter_mut() {
            assert_eq!(key_mut.index(), i);
            match i {
                0 => assert_eq!(*value_mut, 12),
                1 => assert_eq!(*value_mut, 33),
                _ => panic!(),
            }
            i += 1;
        }
    }

    #[test]
    fn iter_rev() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 2;
        for (key, value) in m.iter().rev() {
            i -= 1;
            assert_eq!(key.index(), i);
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
        }

        i = 2;
        for (key, value) in m.iter_mut().rev() {
            i -= 1;
            assert_eq!(key.index(), i);
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
        }
    }
    #[test]
    fn keys() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 0;
        for key in m.keys() {
            assert_eq!(key.index(), i);
            i += 1;
        }
    }

    #[test]
    fn keys_rev() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 2;
        for key in m.keys().rev() {
            i -= 1;
            assert_eq!(key.index(), i);
        }
    }

    #[test]
    fn values() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 0;
        for value in m.values() {
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
            i += 1;
        }
        i = 0;
        for value_mut in m.values_mut() {
            match i {
                0 => assert_eq!(*value_mut, 12),
                1 => assert_eq!(*value_mut, 33),
                _ => panic!(),
            }
            i += 1;
        }
    }

    #[test]
    fn values_rev() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let mut i = 2;
        for value in m.values().rev() {
            i -= 1;
            match i {
                0 => assert_eq!(*value, 12),
                1 => assert_eq!(*value, 33),
                _ => panic!(),
            }
        }
        i = 2;
        for value_mut in m.values_mut().rev() {
            i -= 1;
            match i {
                0 => assert_eq!(*value_mut, 12),
                1 => assert_eq!(*value_mut, 33),
                _ => panic!(),
            }
        }
    }

    #[test]
    fn from_iter() {
        let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
        m.push(12);
        m.push(33);

        let n = m.values().collect::<PrimaryMap<E, _>>();
        assert!(m.len() == n.len());
        for (me, ne) in m.values().zip(n.values()) {
            assert!(*me == **ne);
        }
    }
}
<|endoftext|>