<commit_before>use winapi;
use user32;
use kernel32;
use gdi32;

use winapi::{UINT, WPARAM, LPARAM};
use winapi::windef::HWND;
use winapi::winuser::WNDCLASSEXW;

use std::ptr;
use std::mem;
use std::ffi::OsStr;
use std::os::windows::ffi::OsStrExt;
use std::path::PathBuf;
use std::cell::RefCell;
use std::sync::mpsc;
use std::sync::mpsc::{Sender, Receiver};
use std::thread;

use num::FromPrimitive;

use config::WindowConfig;
use event::{Event, VKeyCode};

pub struct Window {
    internal: InternalWindow,
    event_receiver: Receiver<Event>
}

impl Window {
    pub fn new<'a>(name: &'a str, config: &WindowConfig) -> Window {
        // Channel for the handle to the window
        let (tx, rx) = mpsc::channel();
        let name = name.into();
        let config = config.clone();

        thread::spawn(move || {
            unsafe {
                // Event channel
                let (sx, rx) = mpsc::channel();
                event_sender.with(|sender| {
                    *sender.borrow_mut() = Some(sx);
                });

                let internal_window = InternalWindow::new(name, config);
                tx.send((internal_window, rx)).unwrap();

                let mut msg = mem::uninitialized();

                while user32::GetMessageW(&mut msg, ptr::null_mut(), 0, 0) > 0 {
                    user32::TranslateMessage(&msg);
                    user32::DispatchMessageW(&msg);
                }
            }
        });

        let (internal_window, reciever) = rx.recv().unwrap();

        Window {
            internal: internal_window,
            event_receiver: reciever
        }
    }

    #[inline]
    pub fn show(&self) {
        self.internal.show();
    }

    #[inline]
    pub fn hide(&self) {
        self.internal.hide();
    }

    pub fn print_event(&self) {
        println!("{:?}", self.event_receiver.try_recv());
    }

    /// Destroy the window, consuming it in the process
    #[inline]
    pub fn kill(self) {
        self.internal.kill();
    }
}

#[derive(Clone)]
struct InternalWindow( HWND );

unsafe impl Send for InternalWindow {}
unsafe impl Sync for InternalWindow {}

impl InternalWindow {
    fn new<'a>(name: String, config: WindowConfig) -> InternalWindow {
        unsafe {
            let class_name = register_window_class();

            let window_name = osstr(&name);

            let style = {
                let mut style_temp = 0;

                if config.resizable == true {
                    style_temp |= winapi::WS_SIZEBOX;

                    if config.maximizable == true {
                        style_temp |= winapi::WS_MAXIMIZEBOX;
                    }
                }

                if config.minimizable == true {
                    style_temp |= winapi::WS_MINIMIZEBOX;
                }

                if config.title_icon == true {
                    style_temp |= winapi::WS_SYSMENU;
                }

                style_temp
            };

            let window_handle = user32::CreateWindowExW(
                winapi::WS_EX_CLIENTEDGE,
                class_name.as_ptr(),
                window_name.as_ptr() as winapi::LPCWSTR,
                style,
                winapi::CW_USEDEFAULT,
                winapi::CW_USEDEFAULT,
                config.size_x,
                config.size_y,
                ptr::null_mut(),
                ptr::null_mut(),
                kernel32::GetModuleHandleW(ptr::null()),
                ptr::null_mut()
            );

            if window_handle == ptr::null_mut() {
                panic!(format!("Error: {}", ::std::io::Error::last_os_error()));
            }

            if let Some(p) = config.icon {
                let path = wide_path(p).as_ptr();

                let icon = user32::LoadImageW(ptr::null_mut(), path, winapi::IMAGE_ICON, 32, 32, winapi::LR_LOADFROMFILE);
                if icon != ptr::null_mut() {
                    user32::SendMessageW(window_handle, winapi::WM_SETICON, winapi::ICON_BIG as u64, icon as winapi::LPARAM);
                }
                else {
                    panic!("Could not load 32x32 icon (TODO: Make this not panic)");
                }

                let icon = user32::LoadImageW(ptr::null_mut(), path, winapi::IMAGE_ICON, 16, 16, winapi::LR_LOADFROMFILE);
                if icon != ptr::null_mut() {
                    user32::SendMessageW(window_handle, winapi::WM_SETICON, winapi::ICON_SMALL as u64, icon as winapi::LPARAM);
                }
                else {
                    panic!("Could not load 16x16 icon (TODO: Make this not panic)");
                }
            }

            InternalWindow( window_handle )
        }
    }

    #[inline]
    fn show(&self) {
        unsafe {
            user32::ShowWindow(self.0, winapi::SW_SHOW);
        }
    }

    #[inline]
    fn hide(&self) {
        unsafe {
            user32::ShowWindow(self.0, winapi::SW_HIDE);
        }
    }

    #[inline]
    fn kill(self) {
        unsafe {
            user32::DestroyWindow(self.0);
        }
    }
}

unsafe fn register_window_class() -> Vec<u16> {
    let class_name = osstr("Window Class");

    let window_class = WNDCLASSEXW {
        cbSize: mem::size_of::<WNDCLASSEXW>() as winapi::UINT,
        style: winapi::CS_OWNDC | winapi::CS_VREDRAW | winapi::CS_HREDRAW,
        lpfnWndProc: Some(callback),
        cbClsExtra: 0,
        cbWndExtra: 0,
        hInstance: kernel32::GetModuleHandleW(ptr::null()),
        hIcon: ptr::null_mut(),
        hCursor: ptr::null_mut(),
        hbrBackground: ptr::null_mut(),
        lpszMenuName: ptr::null(),
        lpszClassName: class_name.as_ptr(),
        hIconSm: ptr::null_mut()
    };
    user32::RegisterClassExW(&window_class);

    class_name
}

#[allow(non_upper_case_globals)]
thread_local!(static event_sender: RefCell<Option<Sender<Event>>> = RefCell::new(None));

fn send_event(event: Event) {
    event_sender.with(|sender| {
        let value = sender.borrow();
        let sender = match *value {
            Some(ref s) => s,
            None => return
        };

        sender.send(event).ok();
    });
}

unsafe extern "system" fn callback(hwnd: HWND, msg: UINT,
                                   wparam: WPARAM, lparam: LPARAM)
                                   -> winapi::LRESULT {

    match msg {
        winapi::WM_KEYDOWN  => {
            use event::Event::KeyDown;
            use event::PressState;

            let press_state = {
                match lparam & 0x40000000 {
                    0 => PressState::Pressed,
                    _ => PressState::Held
                }
            };

            match VKeyCode::from_u64(wparam) {
                Some(k) => send_event(KeyDown(press_state, k)),
                None    => ()
            }

            0
        }

        winapi::WM_PAINT    => {
            let mut pstruct = mem::uninitialized();
            let hdc = user32::BeginPaint(hwnd, &mut pstruct);

            user32::FillRect(hdc, &pstruct.rcPaint, gdi32::CreateSolidBrush(0x000000));

            user32::EndPaint(hwnd, &pstruct);
            0
        }

        _ => user32::DefWindowProcW(hwnd, msg, wparam, lparam)
    }

}

fn osstr<'a>(s: &'a str) -> Vec<u16> {
    OsStr::new(s).encode_wide().chain(Some(0).into_iter()).collect::<Vec<_>>()
}

fn wide_path(path: PathBuf) -> Vec<u16> {
    path.as_os_str().encode_wide().chain(Some(0).into_iter()).collect::<Vec<_>>()
}<commit_msg>Fixed issue where killed window would remain open<commit_after>use winapi;
use user32;
use kernel32;
use gdi32;

use winapi::{UINT, WPARAM, LPARAM};
use winapi::windef::HWND;
use winapi::winuser::WNDCLASSEXW;

use std::ptr;
use std::mem;
use std::ffi::OsStr;
use std::os::windows::ffi::OsStrExt;
use std::path::PathBuf;
use std::cell::RefCell;
use std::sync::mpsc;
use std::sync::mpsc::{Sender, Receiver};
use std::thread;

use num::FromPrimitive;

use config::WindowConfig;
use event::{Event, VKeyCode};

pub struct Window {
    internal: InternalWindow,
    event_receiver: Receiver<Event>
}

impl Window {
    pub fn new<'a>(name: &'a str, config: &WindowConfig) -> Window {
        // Channel for the handle to the window
        let (tx, rx) = mpsc::channel();
        let name = name.into();
        let config = config.clone();

        thread::spawn(move || {
            unsafe {
                // Event channel
                let (sx, rx) = mpsc::channel();
                event_sender.with(|sender| {
                    *sender.borrow_mut() = Some(sx);
                });

                let internal_window = InternalWindow::new(name, config);
                tx.send((internal_window, rx)).unwrap();

                let mut msg = mem::uninitialized();

                while user32::GetMessageW(&mut msg, ptr::null_mut(), 0, 0) > 0 {
                    user32::TranslateMessage(&msg);
                    user32::DispatchMessageW(&msg);
                }
            }
        });

        let (internal_window, reciever) = rx.recv().unwrap();

        Window {
            internal: internal_window,
            event_receiver: reciever
        }
    }

    #[inline]
    pub fn show(&self) {
        self.internal.show();
    }

    #[inline]
    pub fn hide(&self) {
        self.internal.hide();
    }

    pub fn print_event(&self) {
        println!("{:?}", self.event_receiver.try_recv());
    }

    /// Destroy the window, consuming it in the process
    #[inline]
    pub fn kill(self) {
        self.hide();
        self.internal.kill();
    }
}

#[derive(Clone)]
struct InternalWindow( HWND );

unsafe impl Send for InternalWindow {}
unsafe impl Sync for InternalWindow {}

impl InternalWindow {
    fn new<'a>(name: String, config: WindowConfig) -> InternalWindow {
        unsafe {
            let class_name = register_window_class();

            let window_name = osstr(&name);

            let style = {
                let mut style_temp = 0;

                if config.resizable == true {
                    style_temp |= winapi::WS_SIZEBOX;

                    if config.maximizable == true {
                        style_temp |= winapi::WS_MAXIMIZEBOX;
                    }
                }

                if config.minimizable == true {
                    style_temp |= winapi::WS_MINIMIZEBOX;
                }

                if config.title_icon == true {
                    style_temp |= winapi::WS_SYSMENU;
                }

                style_temp
            };

            let window_handle = user32::CreateWindowExW(
                winapi::WS_EX_CLIENTEDGE,
                class_name.as_ptr(),
                window_name.as_ptr() as winapi::LPCWSTR,
                style,
                winapi::CW_USEDEFAULT,
                winapi::CW_USEDEFAULT,
                config.size_x,
                config.size_y,
                ptr::null_mut(),
                ptr::null_mut(),
                kernel32::GetModuleHandleW(ptr::null()),
                ptr::null_mut()
            );

            if window_handle == ptr::null_mut() {
                panic!(format!("Error: {}", ::std::io::Error::last_os_error()));
            }

            if let Some(p) = config.icon {
                let path = wide_path(p).as_ptr();

                let icon = user32::LoadImageW(ptr::null_mut(), path, winapi::IMAGE_ICON, 32, 32, winapi::LR_LOADFROMFILE);
                if icon != ptr::null_mut() {
                    user32::SendMessageW(window_handle, winapi::WM_SETICON, winapi::ICON_BIG as u64, icon as winapi::LPARAM);
                }
                else {
                    panic!("Could not load 32x32 icon (TODO: Make this not panic)");
                }

                let icon = user32::LoadImageW(ptr::null_mut(), path, winapi::IMAGE_ICON, 16, 16, winapi::LR_LOADFROMFILE);
                if icon != ptr::null_mut() {
                    user32::SendMessageW(window_handle, winapi::WM_SETICON, winapi::ICON_SMALL as u64, icon as winapi::LPARAM);
                }
                else {
                    panic!("Could not load 16x16 icon (TODO: Make this not panic)");
                }
            }

            InternalWindow( window_handle )
        }
    }

    #[inline]
    fn show(&self) {
        unsafe {
            user32::ShowWindow(self.0, winapi::SW_SHOW);
        }
    }

    #[inline]
    fn hide(&self) {
        unsafe {
            user32::ShowWindow(self.0, winapi::SW_HIDE);
        }
    }

    #[inline]
    fn kill(self) {
        unsafe {
            user32::DestroyWindow(self.0);
        }
    }
}

unsafe fn register_window_class() -> Vec<u16> {
    let class_name = osstr("Window Class");

    let window_class = WNDCLASSEXW {
        cbSize: mem::size_of::<WNDCLASSEXW>() as winapi::UINT,
        style: winapi::CS_OWNDC | winapi::CS_VREDRAW | winapi::CS_HREDRAW,
        lpfnWndProc: Some(callback),
        cbClsExtra: 0,
        cbWndExtra: 0,
        hInstance: kernel32::GetModuleHandleW(ptr::null()),
        hIcon: ptr::null_mut(),
        hCursor: ptr::null_mut(),
        hbrBackground: ptr::null_mut(),
        lpszMenuName: ptr::null(),
        lpszClassName: class_name.as_ptr(),
        hIconSm: ptr::null_mut()
    };
    user32::RegisterClassExW(&window_class);

    class_name
}

#[allow(non_upper_case_globals)]
thread_local!(static event_sender: RefCell<Option<Sender<Event>>> = RefCell::new(None));

fn send_event(event: Event) {
    event_sender.with(|sender| {
        let value = sender.borrow();
        let sender = match *value {
            Some(ref s) => s,
            None => return
        };

        sender.send(event).ok();
    });
}

unsafe extern "system" fn callback(hwnd: HWND, msg: UINT,
                                   wparam: WPARAM, lparam: LPARAM)
                                   -> winapi::LRESULT {

    match msg {
        winapi::WM_KEYDOWN  => {
            use event::Event::KeyDown;
            use event::PressState;

            let press_state = {
                match lparam & 0x40000000 {
                    0 => PressState::Pressed,
                    _ => PressState::Held
                }
            };

            match VKeyCode::from_u64(wparam) {
                Some(k) => send_event(KeyDown(press_state, k)),
                None    => ()
            }

            0
        }

        winapi::WM_PAINT    => {
            let mut pstruct = mem::uninitialized();
            let hdc = user32::BeginPaint(hwnd, &mut pstruct);

            user32::FillRect(hdc, &pstruct.rcPaint, gdi32::CreateSolidBrush(0x000000));

            user32::EndPaint(hwnd, &pstruct);
            0
        }

        _ => user32::DefWindowProcW(hwnd, msg, wparam, lparam)
    }

}

fn osstr<'a>(s: &'a str) -> Vec<u16> {
    OsStr::new(s).encode_wide().chain(Some(0).into_iter()).collect::<Vec<_>>()
}

fn wide_path(path: PathBuf) -> Vec<u16> {
    path.as_os_str().encode_wide().chain(Some(0).into_iter()).collect::<Vec<_>>()
}<|endoftext|>


<commit_before>#![allow(unstable)]
extern crate octobuild;

use octobuild::common::{BuildTask};
use octobuild::wincmd;
use octobuild::xg;
use octobuild::graph::{Graph, NodeIndex, Node, EdgeIndex, Edge};

use std::os;

use std::io::{Command, File, BufferedReader};
use std::io::process::ProcessExit;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{channel, Sender, Receiver};
use std::thread::Thread;

#[derive(Show)]
struct TaskMessage {
index: NodeIndex,
task: BuildTask
}

#[derive(Show)]
struct ResultMessage {
index: NodeIndex,
result: Result<BuildResult, String>
}

#[derive(Show)]
struct BuildResult {
exit_code: ProcessExit,
}

fn main() {
	println!("XGConsole:");
	for arg in parse_command_line(os::args()).iter() {
		println!("  {}", arg);
	}

	let (tx_result, rx_result): (Sender<ResultMessage>, Receiver<ResultMessage>) = channel();
	let (tx_task, rx_task): (Sender<TaskMessage>, Receiver<TaskMessage>) = channel();

	let mutex_rx_task = Arc::new(Mutex::new(rx_task));
	for cpu_id in range(0, std::os::num_cpus()) {
		let local_rx_task = mutex_rx_task.clone();
		let local_tx_result = tx_result .clone();
			Thread::spawn(move || {
			loop {
				let message: TaskMessage;
				match local_rx_task.lock().unwrap().recv() {
						Ok(v) => {message = v;
					}
						Err(_) => {
						break;
					}
					}
				println!("{}: {:?}", cpu_id, message);
				local_tx_result.send(execute_task(message));
			}
		});
	}
	free(tx_result);

	let args = os::args();
	let mut path;
	if args.len() <= 1 {
				path = Path::new(&args[0]).dir_path();
				path.push("../tests/graph-parser.xml");
	} else {
			path =Path::new(&args[1]);
	}
	println!("Example path: {}", path.display());
	match File::open(&path) {
			Ok(file) => {
			match xg::parser::parse(BufferedReader::new(file)) {
					Ok(graph) => {
					match validate_graph(graph) {
							Ok(graph) => {
								execute_graph(&graph, tx_task, mutex_rx_task, rx_result);
						}
							Err(msg) =>{panic! (msg);}
						}
				}
					Err(msg) =>{panic! (msg);}
				}
		}
			Err(msg) =>{panic! (msg);}
		}

	println!("done");
}

fn validate_graph(graph: Graph<BuildTask, ()>) -> Result<Graph<BuildTask, ()>, String> {
	let mut completed:Vec<bool> = vec![];
	let mut queue:Vec<NodeIndex> = vec![];
		graph. each_node(|index: NodeIndex, _:&Node<BuildTask>|->bool {
			completed.push(false);
			queue.push(index);
			true
	});
	let mut count:usize = 0;
	let mut i:usize = 0;
	while i < queue.len() {
		let index = queue[i];
		if (!completed[index.node_id()]) && (is_ready(&graph, &completed, &index)) {
			completed[index.node_id()] = true;
				graph.each_incoming_edge(index, |_:EdgeIndex, edge:&Edge<()>| -> bool {
					queue.push(edge.source());
					true
			});
			count += 1;
			if count ==completed.len() {
				return Ok(graph);
			}
		}
		i = i + 1;
	}
	return Err("Found cycles in build dependencies.".to_string());
}

fn execute_task(message: TaskMessage) -> ResultMessage {
	println!("{}", message.task.title);

	let args = wincmd::expand_args(&message.task.args, &|name:&str|->Option<String>{os::getenv(name)});
	match Command::new(message.task.exec)
	.args(args.as_slice())
	.cwd(&Path::new(&message.task.working_dir))
	.output(){
			Ok(output) => {
			println!("stdout: {}", String::from_utf8_lossy(output.output.as_slice()));
			println!("stderr: {}", String::from_utf8_lossy(output.error.as_slice()));
			ResultMessage {
			index: message.index,
			result: Ok(BuildResult {
			exit_code: output.status
			})
			}}
			Err(e) => {
			ResultMessage {
			index: message.index,
			result: Err(format!("Failed to start process: {}", e))}
		}
		}
}

fn execute_graph(graph: &Graph<BuildTask, ()>, tx_task: Sender<TaskMessage>, rx_task: Arc<Mutex<Receiver<TaskMessage>>>, rx_result: Receiver<ResultMessage>) {
	let mut completed:Vec<bool> = vec![];
		graph. each_node(|index: NodeIndex, node:&Node<BuildTask>|->bool {
		let mut has_edges = false;
			graph.each_outgoing_edge(index, |_:EdgeIndex, _:&Edge<()>| -> bool {
			has_edges = true;
			false
		});
		if !has_edges {
				tx_task.send(TaskMessage{
			index: index,
			task: node.data.clone(),
			})  ;
		}
			completed.push(false);
		true
	});
	let mut count:usize = 0;
	for message in rx_result.iter() {
		assert!(!completed[message.index.node_id()]);
		count += 1;
		println!("R {}/{}: {:?}", count, completed.len(), message);
		match message.result {
				Ok (result) => {
				if !result.exit_code.success() {
					break;
				}
				completed[message.index.node_id()] = true;
					graph.each_incoming_edge(message.index, |_:EdgeIndex, edge:&Edge<()>| -> bool {
					let source = edge.source();
					if !completed[source.node_id()] {
						if is_ready(graph, &completed, &source) {
								tx_task.send(TaskMessage{
							index: source,
							task: graph.node(source).data.clone(),
							})  ;
						}
					}
					true
				});
			}
				Err (e) => {
				println!("{}", e);
				break;
			}
			}
		if count == completed.len() {
			break;
		}
	}
	// No more tasks.
		free(tx_task);
	// Cleanup task list.
	match rx_task.lock() {
			queue => {
			for _ in queue.iter() {
			}
		}
		}
	// Wait for in progress task completion.
	for _ in rx_result.iter() {
	}
}

fn free<T>(_:T) {
}

fn is_ready(graph: &Graph<BuildTask, ()>, completed: &Vec<bool>, source: &NodeIndex) -> bool {
	let mut ready = true;
		graph.each_outgoing_edge(*source, |_:EdgeIndex, deps:&Edge<()>| -> bool {
		if !completed[deps.target().node_id()]{
			ready = false;
			false
		} else {
			true
		}
	});
	ready
}

fn parse_command_line(args: Vec<String>) -> Vec<String> {
	let mut result: Vec<String> = Vec::new();
	for arg in args.slice(1, args.len()).iter() {
			result.push(arg.clone());
	}
	result
}
<commit_msg>Small refactoring.<commit_after>#![allow(unstable)]
extern crate octobuild;

use octobuild::common::{BuildTask};
use octobuild::wincmd;
use octobuild::xg;
use octobuild::graph::{Graph, NodeIndex, Node, EdgeIndex, Edge};

use std::os;

use std::io::{Command, File, BufferedReader};
use std::io::process::ProcessExit;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{channel, Sender, Receiver};
use std::thread::Thread;

#[derive(Show)]
struct TaskMessage {
index: NodeIndex,
task: BuildTask
}

#[derive(Show)]
struct ResultMessage {
index: NodeIndex,
result: Result<BuildResult, String>
}

#[derive(Show)]
struct BuildResult {
exit_code: ProcessExit,
}

fn main() {
	println!("XGConsole:");
	for arg in parse_command_line(os::args()).iter() {
		println!("  {}", arg);
	}

	let (tx_result, rx_result): (Sender<ResultMessage>, Receiver<ResultMessage>) = channel();
	let (tx_task, rx_task): (Sender<TaskMessage>, Receiver<TaskMessage>) = channel();

	let mutex_rx_task = create_threads(rx_task, tx_result, std::os::num_cpus(), |worker_id:usize| {
		move |task:TaskMessage| -> ResultMessage {
			println!("{}: {:?}", worker_id, task);
			execute_task(task)
		}
	});

	let args = os::args();
	let mut path;
	if args.len() <= 1 {
				path = Path::new(&args[0]).dir_path();
				path.push("../tests/graph-parser.xml");
	} else {
			path =Path::new(&args[1]);
	}
	println!("Example path: {}", path.display());
	match File::open(&path) {
			Ok(file) => {
			match xg::parser::parse(BufferedReader::new(file)) {
					Ok(graph) => {
					match validate_graph(graph) {
							Ok(graph) => {
								execute_graph(&graph, tx_task, mutex_rx_task, rx_result);
						}
							Err(msg) =>{panic! (msg);}
						}
				}
					Err(msg) =>{panic! (msg);}
				}
		}
			Err(msg) =>{panic! (msg);}
		}

	println!("done");
}

fn create_threads<R: Send, T: Send, Worker:Fn(T) -> R + Send, Factory:Fn(usize) -> Worker>(rx_task: Receiver<T>, tx_result: Sender<R>, num_cpus: usize, factory: Factory) ->  Arc<Mutex<Receiver<T>>> {
	let mutex_rx_task = Arc::new(Mutex::new(rx_task));
	for cpu_id in range(0, num_cpus) {
    		let local_rx_task = mutex_rx_task.clone();
    		let local_tx_result = tx_result.clone();
				let worker = factory(cpu_id);
    			Thread::spawn(move || {
    			loop {
    				let task: T;
    				match local_rx_task.lock().unwrap().recv() {
    						Ok(v) => {task = v;
    					}
    						Err(_) => {
    						break;
    					}
    					}
    				match local_tx_result.send(worker(task)) {
						Ok(_) => {}
						Err(_) => {break;}
					}
				}
    		});
    	}
	mutex_rx_task
}

fn validate_graph(graph: Graph<BuildTask, ()>) -> Result<Graph<BuildTask, ()>, String> {
	let mut completed:Vec<bool> = vec![];
	let mut queue:Vec<NodeIndex> = vec![];
		graph. each_node(|index: NodeIndex, _:&Node<BuildTask>|->bool {
			completed.push(false);
			queue.push(index);
			true
	});
	let mut count:usize = 0;
	let mut i:usize = 0;
	while i < queue.len() {
		let index = queue[i];
		if (!completed[index.node_id()]) && (is_ready(&graph, &completed, &index)) {
			completed[index.node_id()] = true;
				graph.each_incoming_edge(index, |_:EdgeIndex, edge:&Edge<()>| -> bool {
					queue.push(edge.source());
					true
			});
			count += 1;
			if count ==completed.len() {
				return Ok(graph);
			}
		}
		i = i + 1;
	}
	return Err("Found cycles in build dependencies.".to_string());
}

fn execute_task(message: TaskMessage) -> ResultMessage {
	println!("{}", message.task.title);

	let args = wincmd::expand_args(&message.task.args, &|name:&str|->Option<String>{os::getenv(name)});
	match Command::new(message.task.exec)
	.args(args.as_slice())
	.cwd(&Path::new(&message.task.working_dir))
	.output(){
			Ok(output) => {
			println!("stdout: {}", String::from_utf8_lossy(output.output.as_slice()));
			println!("stderr: {}", String::from_utf8_lossy(output.error.as_slice()));
			ResultMessage {
			index: message.index,
			result: Ok(BuildResult {
			exit_code: output.status
			})
			}}
			Err(e) => {
			ResultMessage {
			index: message.index,
			result: Err(format!("Failed to start process: {}", e))}
		}
		}
}

fn execute_graph(graph: &Graph<BuildTask, ()>, tx_task: Sender<TaskMessage>, rx_task: Arc<Mutex<Receiver<TaskMessage>>>, rx_result: Receiver<ResultMessage>) {
	let mut completed:Vec<bool> = vec![];
		graph. each_node(|index: NodeIndex, node:&Node<BuildTask>|->bool {
		let mut has_edges = false;
			graph.each_outgoing_edge(index, |_:EdgeIndex, _:&Edge<()>| -> bool {
			has_edges = true;
			false
		});
		if !has_edges {
				tx_task.send(TaskMessage{
			index: index,
			task: node.data.clone(),
			})  ;
		}
			completed.push(false);
		true
	});
	let mut count:usize = 0;
	for message in rx_result.iter() {
		assert!(!completed[message.index.node_id()]);
		count += 1;
		println!("R {}/{}: {:?}", count, completed.len(), message);
		match message.result {
				Ok (result) => {
				if !result.exit_code.success() {
					break;
				}
				completed[message.index.node_id()] = true;
					graph.each_incoming_edge(message.index, |_:EdgeIndex, edge:&Edge<()>| -> bool {
					let source = edge.source();
					if !completed[source.node_id()] {
						if is_ready(graph, &completed, &source) {
								tx_task.send(TaskMessage{
							index: source,
							task: graph.node(source).data.clone(),
							})  ;
						}
					}
					true
				});
			}
				Err (e) => {
				println!("{}", e);
				break;
			}
			}
		if count == completed.len() {
			break;
		}
	}
	// No more tasks.
		free(tx_task);
	// Cleanup task list.
	match rx_task.lock() {
			queue => {
			for _ in queue.iter() {
			}
		}
		}
	// Wait for in progress task completion.
	for _ in rx_result.iter() {
	}
}

fn free<T>(_:T) {
}

fn is_ready(graph: &Graph<BuildTask, ()>, completed: &Vec<bool>, source: &NodeIndex) -> bool {
	let mut ready = true;
		graph.each_outgoing_edge(*source, |_:EdgeIndex, deps:&Edge<()>| -> bool {
		if !completed[deps.target().node_id()]{
			ready = false;
			false
		} else {
			true
		}
	});
	ready
}

fn parse_command_line(args: Vec<String>) -> Vec<String> {
	let mut result: Vec<String> = Vec::new();
	for arg in args.slice(1, args.len()).iter() {
			result.push(arg.clone());
	}
	result
}
<|endoftext|>


<commit_before>use std::io::{File, Open, ReadWrite};
use std::io::IoResult;
use super::GapBuffer;
use super::gap_buffer;
use super::Position;
use super::Range;

pub struct Buffer {
    data: GapBuffer,
    file: Option<File>,
    cursor: Position,
    selection: Option<Range>,
}

pub fn from_file(path: &Path) -> IoResult<Buffer> {
    // Try to open and read the file, returning any errors encountered.
    let mut file = match File::open_mode(path, Open, ReadWrite) {
        Ok(f) => f,
        Err(error) => return Err(error),
    };
    let mut data = match file.read_to_string() {
        Ok(d) => d,
        Err(error) => return Err(error),
    };

    let data = gap_buffer::new(data);

    // Create a new buffer using the loaded data, file, and other defaults.
    Ok(Buffer{ data: data, file: Some(file), cursor: Position{ line: 0, offset: 0 }, selection: None })
}

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

    #[test]
    fn from_file_loads_file_into_buffer() {
        match from_file(&Path::new("tests/sample/file")) {
            Ok(buffer) => assert_eq!(buffer.data.to_string(), "it works!\n"),
            Err(error) => panic!(error),
        }
    }
}
<commit_msg>Remove cursor and selection fields; these should be handled by the UI.<commit_after>use std::io::{File, Open, ReadWrite};
use std::io::IoResult;
use super::GapBuffer;
use super::gap_buffer;
use super::Position;
use super::Range;

pub struct Buffer {
    data: GapBuffer,
    file: Option<File>,
}

pub fn from_file(path: &Path) -> IoResult<Buffer> {
    // Try to open and read the file, returning any errors encountered.
    let mut file = match File::open_mode(path, Open, ReadWrite) {
        Ok(f) => f,
        Err(error) => return Err(error),
    };
    let mut data = match file.read_to_string() {
        Ok(d) => d,
        Err(error) => return Err(error),
    };

    let data = gap_buffer::new(data);

    // Create a new buffer using the loaded data, file, and other defaults.
    Ok(Buffer{ data: data, file: Some(file) })
}

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

    #[test]
    fn from_file_loads_file_into_buffer() {
        match from_file(&Path::new("tests/sample/file")) {
            Ok(buffer) => assert_eq!(buffer.data.to_string(), "it works!\n"),
            Err(error) => panic!(error),
        }
    }
}
<|endoftext|>


<commit_before>use std::{
    cell::RefCell,
    sync::atomic::{AtomicU64, Ordering},
    time::{Duration, Instant},
};

use crossbeam::{
    channel::{self, Receiver, Sender, TryRecvError},
    sync::Parker,
};
use gba::Gba;

type GbaThreadCallback = Box<dyn 'static + Send + FnMut(&mut Gba, &mut GbaThreadState)>;
type GbaThreadCallbackOnce = Box<dyn 'static + Send + FnOnce(&mut Gba, &mut GbaThreadState)>;

fn gba_thread_fn(rx: Receiver<GbaMessage>) {
    let mut ctx = Context::default();
    ctx.state.target_fps = 60.0;

    log::trace!("waiting for GBA start");
    ctx.state.paused = true;
    wait_for_gba_unpause(&mut ctx, &rx);

    let spin_sleeper = spin_sleep::SpinSleeper::default();

    log::trace!("starting GBA thread loop");
    while !ctx.state.stopped {
        let frame_start_time = Instant::now();

        ctx.gba.frame();
        ctx.state.frame_duration = frame_start_time.elapsed();
        ctx.state.frame_count += 1;

        ctx.on_frame
            .iter_mut()
            .for_each(|(_, cb)| (cb)(&mut ctx.gba, &mut ctx.state));
        empty_gba_message_queue(&mut ctx, &rx);

        if ctx.state.paused {
            wait_for_gba_unpause(&mut ctx, &rx);
        } else {
            let frame_duration = frame_start_time.elapsed();
            ctx.state.frame_processing_duration = frame_duration;
            let target_frame_duration = Duration::from_secs_f64(1.0 / ctx.state.target_fps);
            if frame_duration < target_frame_duration {
                spin_sleeper.sleep(target_frame_duration - frame_duration);
            }
        }
    }
    log::trace!("exited GBA thread loop");
}

fn empty_gba_message_queue(ctx: &mut Context, rx: &Receiver<GbaMessage>) {
    loop {
        match rx.try_recv() {
            Ok(msg) => process_gba_message(ctx, msg),
            Err(TryRecvError::Disconnected) => {
                log::trace!("no more GBA handles, shutting down");
                ctx.state.stop();
                break;
            }
            Err(TryRecvError::Empty) => break,
        }
    }
}

fn wait_for_gba_unpause(ctx: &mut Context, rx: &Receiver<GbaMessage>) {
    while ctx.state.paused && !ctx.state.stopped {
        match rx.recv() {
            Ok(msg) => process_gba_message(ctx, msg),
            Err(_) => {
                log::trace!("no more GBA handles, shutting down");
                ctx.state.stop();
                break;
            }
        }
    }
}

fn process_gba_message(ctx: &mut Context, msg: GbaMessage) {
    match msg {
        GbaMessage::Shutdown => {
            log::trace!("GBA thread shutdown requested");
            ctx.state.stopped = true;
        }
        GbaMessage::CallbackAfterFrame(cb) => (cb)(&mut ctx.gba, &mut ctx.state),
        GbaMessage::CallbackOnFrame(id, cb) => ctx.on_frame.push((id, cb)),
        GbaMessage::RemoveOnFrameCallback(rm_id) => ctx.on_frame.retain(|&(id, _)| id != rm_id),
    }
}

#[derive(Default)]
struct Context {
    gba: Gba,
    state: GbaThreadState,
    on_frame: Vec<(CallbackId, GbaThreadCallback)>,
}

#[derive(Default)]
pub struct GbaThreadState {
    pub paused: bool,
    stopped: bool,
    pub target_fps: f64,

    frame_count: u64,

    frame_duration: Duration,

    /// Duration including drawing the frame and running all of the callbacks.
    frame_processing_duration: Duration,
}

impl GbaThreadState {
    pub fn stop(&mut self) {
        self.stopped = true;
    }

    pub fn stopping(&self) -> bool {
        self.stopped
    }

    /// Returns the amount of time required to render the current frame.
    pub fn frame_duration(&self) -> Duration {
        self.frame_duration
    }

    pub fn frame_count(&self) -> u64 {
        self.frame_count
    }

    /// Returns the amount of time required to render the previous frame
    /// and run all of the callbacks.
    pub fn frame_processing_duration(&self) -> Duration {
        self.frame_processing_duration
    }
}

/// A handle to a GBA instance running in its own thread.
pub struct GbaHandle {
    tx: Sender<GbaMessage>,
    parker: RefCell<Option<Parker>>,
}

impl GbaHandle {
    pub fn new() -> GbaHandle {
        let (tx, rx) = channel::unbounded();
        std::thread::spawn(move || gba_thread_fn(rx));
        let parker = RefCell::new(None);
        GbaHandle { tx, parker }
    }

    pub fn shutdown(&self) {
        let _ = self.tx.send(GbaMessage::Shutdown);
    }

    pub fn on_frame<F>(&self, cb: F) -> CallbackId
    where
        F: 'static + Send + FnMut(&mut Gba, &mut GbaThreadState),
    {
        let id = CallbackId::next_id();
        if self
            .tx
            .send(GbaMessage::CallbackOnFrame(id, Box::new(cb)))
            .is_err()
        {
            log::warn!("called `on_frame` on disconnected GBA handle");
            CallbackId(0)
        } else {
            id
        }
    }

    pub fn remove_on_frame(&self, id: CallbackId) {
        if self.tx.send(GbaMessage::RemoveOnFrameCallback(id)).is_err() {
            log::warn!("called `remove_on_frame` on disconnected GBA handle");
        }
    }

    pub fn after_frame<F>(&self, cb: F)
    where
        F: 'static + Send + FnOnce(&mut Gba, &mut GbaThreadState),
    {
        if self
            .tx
            .send(GbaMessage::CallbackAfterFrame(Box::new(cb)))
            .is_err()
        {
            log::warn!("called `after_frame` on disconnected GBA handle")
        }
    }

    pub fn after_frame_wait<F>(&self, cb: F)
    where
        F: 'static + Send + FnOnce(&mut Gba, &mut GbaThreadState),
    {
        let mut parker = self.parker.borrow_mut();
        if parker.is_none() {
            *parker = Some(Parker::new());
        }
        let parker = parker.as_mut().unwrap();
        let unparker = parker.unparker().clone();

        let msg = GbaMessage::CallbackAfterFrame(Box::new(move |gba, state| {
            (cb)(gba, state);
            unparker.unpark();
        }));

        if self.tx.send(msg).is_err() {
            log::warn!("called `after_frame_wait` on disconnected GBA handle")
        } else {
            parker.park();
        }
    }

    pub fn set_paused(&self, paused: bool) {
        self.after_frame(move |_, state| state.paused = paused);
    }
}

impl Clone for GbaHandle {
    fn clone(&self) -> Self {
        GbaHandle {
            tx: self.tx.clone(),
            parker: RefCell::new(None),
        }
    }
}

impl Default for GbaHandle {
    fn default() -> Self {
        Self::new()
    }
}

enum GbaMessage {
    CallbackAfterFrame(GbaThreadCallbackOnce),
    CallbackOnFrame(CallbackId, GbaThreadCallback),
    RemoveOnFrameCallback(CallbackId),
    Shutdown,
}

#[derive(Copy, Clone, PartialEq, Eq)]
pub struct CallbackId(u64);

impl CallbackId {
    fn next_id() -> Self {
        static NEXT_CALLBACK_ID: AtomicU64 = AtomicU64::new(1);
        let id = NEXT_CALLBACK_ID.fetch_add(1, Ordering::Relaxed);
        CallbackId(id)
    }
}
<commit_msg>Add a method for removing a callback from within itself.<commit_after>use std::{
    cell::RefCell,
    sync::atomic::{AtomicU64, Ordering},
    time::{Duration, Instant},
};

use crossbeam::{
    channel::{self, Receiver, Sender, TryRecvError},
    sync::Parker,
};
use gba::Gba;

type GbaThreadCallback = Box<dyn 'static + Send + FnMut(&mut Gba, &mut GbaThreadState)>;
type GbaThreadCallbackOnce = Box<dyn 'static + Send + FnOnce(&mut Gba, &mut GbaThreadState)>;

fn gba_thread_fn(rx: Receiver<GbaMessage>) {
    let mut ctx = Context::default();
    ctx.state.target_fps = 60.0;

    log::trace!("waiting for GBA start");
    ctx.state.paused = true;
    wait_for_gba_unpause(&mut ctx, &rx);

    let spin_sleeper = spin_sleep::SpinSleeper::default();

    log::trace!("starting GBA thread loop");
    while !ctx.state.stopped {
        let frame_start_time = Instant::now();

        ctx.gba.frame();
        ctx.state.frame_duration = frame_start_time.elapsed();
        ctx.state.frame_count += 1;

        // FIXME replace this with retain_mut when that is stabilized in 1.61
        //
        // ctx.on_frame.retain_mut(|(_, cb)| {
        //     ctx.state.remove_callback = false;
        //     (cb)(&mut ctx.gba, &mut ctx.state);
        //     !std::mem::take(&mut ctx.state.remove_callback)
        // });
        let mut idx = 0;
        while idx < ctx.on_frame.len() {
            let (_, ref mut cb) = ctx.on_frame[idx];
            ctx.state.remove_callback = false;
            (cb)(&mut ctx.gba, &mut ctx.state);
            if std::mem::take(&mut ctx.state.remove_callback) {
                let _ = ctx.on_frame.remove(idx);
            } else {
                idx += 1;
            }
        }

        empty_gba_message_queue(&mut ctx, &rx);

        if ctx.state.paused {
            wait_for_gba_unpause(&mut ctx, &rx);
        } else {
            let frame_duration = frame_start_time.elapsed();
            ctx.state.frame_processing_duration = frame_duration;
            let target_frame_duration = Duration::from_secs_f64(1.0 / ctx.state.target_fps);
            if frame_duration < target_frame_duration {
                spin_sleeper.sleep(target_frame_duration - frame_duration);
            }
        }
    }
    log::trace!("exited GBA thread loop");
}

fn empty_gba_message_queue(ctx: &mut Context, rx: &Receiver<GbaMessage>) {
    loop {
        match rx.try_recv() {
            Ok(msg) => process_gba_message(ctx, msg),
            Err(TryRecvError::Disconnected) => {
                log::trace!("no more GBA handles, shutting down");
                ctx.state.stop();
                break;
            }
            Err(TryRecvError::Empty) => break,
        }
    }
}

fn wait_for_gba_unpause(ctx: &mut Context, rx: &Receiver<GbaMessage>) {
    while ctx.state.paused && !ctx.state.stopped {
        match rx.recv() {
            Ok(msg) => process_gba_message(ctx, msg),
            Err(_) => {
                log::trace!("no more GBA handles, shutting down");
                ctx.state.stop();
                break;
            }
        }
    }
}

fn process_gba_message(ctx: &mut Context, msg: GbaMessage) {
    match msg {
        GbaMessage::Shutdown => {
            log::trace!("GBA thread shutdown requested");
            ctx.state.stopped = true;
        }
        GbaMessage::CallbackAfterFrame(cb) => (cb)(&mut ctx.gba, &mut ctx.state),
        GbaMessage::CallbackOnFrame(id, cb) => ctx.on_frame.push((id, cb)),
        GbaMessage::RemoveOnFrameCallback(rm_id) => ctx.on_frame.retain(|&(id, _)| id != rm_id),
    }
}

#[derive(Default)]
struct Context {
    gba: Gba,
    state: GbaThreadState,
    on_frame: Vec<(CallbackId, GbaThreadCallback)>,
}

#[derive(Default)]
pub struct GbaThreadState {
    pub paused: bool,
    stopped: bool,
    pub target_fps: f64,

    frame_count: u64,

    frame_duration: Duration,

    /// Duration including drawing the frame and running all of the callbacks.
    frame_processing_duration: Duration,

    /// When set to true, the currently executing callback will be marked for deletion.
    remove_callback: bool,
}

impl GbaThreadState {
    pub fn stop(&mut self) {
        self.stopped = true;
    }

    pub fn stopping(&self) -> bool {
        self.stopped
    }

    /// Returns the amount of time required to render the current frame.
    pub fn frame_duration(&self) -> Duration {
        self.frame_duration
    }

    pub fn frame_count(&self) -> u64 {
        self.frame_count
    }

    /// Returns the amount of time required to render the previous frame
    /// and run all of the callbacks.
    pub fn frame_processing_duration(&self) -> Duration {
        self.frame_processing_duration
    }

    // Remove the current callback.
    pub fn remove_callback(&mut self) {
        self.remove_callback = true;
    }
}

/// A handle to a GBA instance running in its own thread.
pub struct GbaHandle {
    tx: Sender<GbaMessage>,
    parker: RefCell<Option<Parker>>,
}

impl GbaHandle {
    pub fn new() -> GbaHandle {
        let (tx, rx) = channel::unbounded();
        std::thread::spawn(move || gba_thread_fn(rx));
        let parker = RefCell::new(None);
        GbaHandle { tx, parker }
    }

    pub fn shutdown(&self) {
        let _ = self.tx.send(GbaMessage::Shutdown);
    }

    pub fn on_frame<F>(&self, cb: F) -> CallbackId
    where
        F: 'static + Send + FnMut(&mut Gba, &mut GbaThreadState),
    {
        let id = CallbackId::next_id();
        if self
            .tx
            .send(GbaMessage::CallbackOnFrame(id, Box::new(cb)))
            .is_err()
        {
            log::warn!("called `on_frame` on disconnected GBA handle");
            CallbackId(0)
        } else {
            id
        }
    }

    pub fn remove_on_frame(&self, id: CallbackId) {
        if self.tx.send(GbaMessage::RemoveOnFrameCallback(id)).is_err() {
            log::warn!("called `remove_on_frame` on disconnected GBA handle");
        }
    }

    pub fn after_frame<F>(&self, cb: F)
    where
        F: 'static + Send + FnOnce(&mut Gba, &mut GbaThreadState),
    {
        if self
            .tx
            .send(GbaMessage::CallbackAfterFrame(Box::new(cb)))
            .is_err()
        {
            log::warn!("called `after_frame` on disconnected GBA handle")
        }
    }

    pub fn after_frame_wait<F>(&self, cb: F)
    where
        F: 'static + Send + FnOnce(&mut Gba, &mut GbaThreadState),
    {
        let mut parker = self.parker.borrow_mut();
        if parker.is_none() {
            *parker = Some(Parker::new());
        }
        let parker = parker.as_mut().unwrap();
        let unparker = parker.unparker().clone();

        let msg = GbaMessage::CallbackAfterFrame(Box::new(move |gba, state| {
            (cb)(gba, state);
            unparker.unpark();
        }));

        if self.tx.send(msg).is_err() {
            log::warn!("called `after_frame_wait` on disconnected GBA handle")
        } else {
            parker.park();
        }
    }

    pub fn set_paused(&self, paused: bool) {
        self.after_frame(move |_, state| state.paused = paused);
    }
}

impl Clone for GbaHandle {
    fn clone(&self) -> Self {
        GbaHandle {
            tx: self.tx.clone(),
            parker: RefCell::new(None),
        }
    }
}

impl Default for GbaHandle {
    fn default() -> Self {
        Self::new()
    }
}

enum GbaMessage {
    CallbackAfterFrame(GbaThreadCallbackOnce),
    CallbackOnFrame(CallbackId, GbaThreadCallback),
    RemoveOnFrameCallback(CallbackId),
    Shutdown,
}

#[derive(Copy, Clone, PartialEq, Eq)]
pub struct CallbackId(u64);

impl CallbackId {
    fn next_id() -> Self {
        static NEXT_CALLBACK_ID: AtomicU64 = AtomicU64::new(1);
        let id = NEXT_CALLBACK_ID.fetch_add(1, Ordering::Relaxed);
        CallbackId(id)
    }
}
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

use core_types::{
    Bool,
    Int,
    MapPos,
    Size2,
};
use core::{
    Unit,
};
use game_state::GameState;
use dir::Dir;

struct Tile {
    cost: Int,
    parent: Option<Dir>,
}

struct Map {
    size: Size2<Int>,
    tiles: ~[Tile],
}

impl<'a> Map {
    fn tile_mut(&'a mut self, pos: MapPos) -> &'a mut Tile {
        &mut self.tiles[pos.x + (pos.y * self.size.w)]
    }

    fn tile(&'a self, pos: MapPos) -> &'a Tile {
        &self.tiles[pos.x + (pos.y * self.size.w)]
    }

    fn is_inboard(&self, pos: MapPos) -> Bool {
        let x = pos.x;
        let y = pos.y;
        x >= 0 && y >= 0 && x < self.size.w && y < self.size.h
    }
}

pub struct Pathfinder {
    priv queue: ~[MapPos],
    priv map: Map,
}

fn create_tiles(tiles_count: Int) -> ~[Tile] {
    let mut tiles = ~[];
    for _ in range(0, tiles_count) {
        tiles.push(Tile {
            cost: 0,
            parent: None,
        });
    }
    tiles
}

impl Pathfinder {
    pub fn new(map_size: Size2<Int>) -> Pathfinder {
        let tiles_count = map_size.w * map_size.h;
        Pathfinder {
            queue: ~[],
            map: Map {
                size: map_size,
                tiles: create_tiles(tiles_count),
            },
        }
    }

    fn process_neighbour_pos(
        &mut self,
        state: &GameState,
        _: &Unit, // TODO: use unit`s type and action points later
        original_pos: MapPos,
        neighbour_pos: MapPos
    ) {
        let old_cost = self.map.tile(original_pos).cost;
        let tile = self.map.tile_mut(neighbour_pos);
        if state.unit_at_opt(neighbour_pos).is_some() {
            return;
        }
        let new_cost: Int = old_cost + 1;
        if tile.cost > new_cost {
            self.queue.push(neighbour_pos);
            // update neighbour tile info
            tile.cost = new_cost;
            let dir = Dir::get_dir_from_to(neighbour_pos, original_pos);
            tile.parent = Some(dir);
        }
    }

    fn clean_map(&mut self) {
        for tile in self.map.tiles.mut_iter() {
            tile.cost = 30000; // TODO: magic number
            tile.parent = None;
        }
    }

    fn try_to_push_neighbours(
        &mut self,
        state: &GameState,
        unit: &Unit,
        pos: MapPos
    ) {
        assert!(self.map.is_inboard(pos));
        for i in range(0 as Int, 6) {
            let neighbour_pos = Dir::get_neighbour_pos(pos, Dir::from_int(i));
            if self.map.is_inboard(neighbour_pos) {
                self.process_neighbour_pos(
                    state, unit, pos, neighbour_pos);
            }
        }
    }

    fn push_start_pos_to_queue(&mut self, start_pos: MapPos) {
        self.queue.push(start_pos);
        let start_tile = self.map.tile_mut(start_pos);
        start_tile.cost = 0;
        start_tile.parent = None;
    }

    pub fn fill_map(&mut self, state: &GameState, unit: &Unit) {
        assert!(self.queue.len() == 0);
        self.clean_map();
        self.push_start_pos_to_queue(unit.pos);
        while self.queue.len() != 0 {
            let pos = self.queue.shift().unwrap();
            self.try_to_push_neighbours(state, unit, pos);
        }
    }

    pub fn get_path(&self, destination: MapPos) -> ~[MapPos] {
        let mut path = ~[];
        let mut pos = destination;
        assert!(self.map.is_inboard(pos));
        path.push(destination);
        while self.map.tile(pos).cost != 0 {
            let parent_dir = self.map.tile(pos).parent.unwrap();
            pos = Dir::get_neighbour_pos(pos, parent_dir);
            assert!(self.map.is_inboard(pos));
            path.push(pos);
        }
        path.reverse();
        path
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>Pathfinder: max_cost() -> Int<commit_after>// See LICENSE file for copyright and license details.

use core_types::{
    Bool,
    Int,
    MapPos,
    Size2,
};
use core::{
    Unit,
};
use game_state::GameState;
use dir::Dir;

struct Tile {
    cost: Int,
    parent: Option<Dir>,
}

struct Map {
    size: Size2<Int>,
    tiles: ~[Tile],
}

fn max_cost() -> Int {
    30000
}

impl<'a> Map {
    fn tile_mut(&'a mut self, pos: MapPos) -> &'a mut Tile {
        &mut self.tiles[pos.x + (pos.y * self.size.w)]
    }

    fn tile(&'a self, pos: MapPos) -> &'a Tile {
        &self.tiles[pos.x + (pos.y * self.size.w)]
    }

    fn is_inboard(&self, pos: MapPos) -> Bool {
        let x = pos.x;
        let y = pos.y;
        x >= 0 && y >= 0 && x < self.size.w && y < self.size.h
    }
}

pub struct Pathfinder {
    priv queue: ~[MapPos],
    priv map: Map,
}

fn create_tiles(tiles_count: Int) -> ~[Tile] {
    let mut tiles = ~[];
    for _ in range(0, tiles_count) {
        tiles.push(Tile {
            cost: 0,
            parent: None,
        });
    }
    tiles
}

impl Pathfinder {
    pub fn new(map_size: Size2<Int>) -> Pathfinder {
        let tiles_count = map_size.w * map_size.h;
        Pathfinder {
            queue: ~[],
            map: Map {
                size: map_size,
                tiles: create_tiles(tiles_count),
            },
        }
    }

    fn process_neighbour_pos(
        &mut self,
        state: &GameState,
        _: &Unit, // TODO: use unit`s type and action points later
        original_pos: MapPos,
        neighbour_pos: MapPos
    ) {
        let old_cost = self.map.tile(original_pos).cost;
        let tile = self.map.tile_mut(neighbour_pos);
        if state.unit_at_opt(neighbour_pos).is_some() {
            return;
        }
        let new_cost: Int = old_cost + 1;
        if tile.cost > new_cost {
            self.queue.push(neighbour_pos);
            // update neighbour tile info
            tile.cost = new_cost;
            let dir = Dir::get_dir_from_to(neighbour_pos, original_pos);
            tile.parent = Some(dir);
        }
    }

    fn clean_map(&mut self) {
        for tile in self.map.tiles.mut_iter() {
            tile.cost = max_cost();
            tile.parent = None;
        }
    }

    fn try_to_push_neighbours(
        &mut self,
        state: &GameState,
        unit: &Unit,
        pos: MapPos
    ) {
        assert!(self.map.is_inboard(pos));
        for i in range(0 as Int, 6) {
            let neighbour_pos = Dir::get_neighbour_pos(pos, Dir::from_int(i));
            if self.map.is_inboard(neighbour_pos) {
                self.process_neighbour_pos(
                    state, unit, pos, neighbour_pos);
            }
        }
    }

    fn push_start_pos_to_queue(&mut self, start_pos: MapPos) {
        self.queue.push(start_pos);
        let start_tile = self.map.tile_mut(start_pos);
        start_tile.cost = 0;
        start_tile.parent = None;
    }

    pub fn fill_map(&mut self, state: &GameState, unit: &Unit) {
        assert!(self.queue.len() == 0);
        self.clean_map();
        self.push_start_pos_to_queue(unit.pos);
        while self.queue.len() != 0 {
            let pos = self.queue.shift().unwrap();
            self.try_to_push_neighbours(state, unit, pos);
        }
    }

    pub fn get_path(&self, destination: MapPos) -> ~[MapPos] {
        let mut path = ~[];
        let mut pos = destination;
        assert!(self.map.is_inboard(pos));
        path.push(destination);
        while self.map.tile(pos).cost != 0 {
            let parent_dir = self.map.tile(pos).parent.unwrap();
            pos = Dir::get_neighbour_pos(pos, parent_dir);
            assert!(self.map.is_inboard(pos));
            path.push(pos);
        }
        path.reverse();
        path
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>


<commit_before>use crate::internal::prelude::*;
use serde::de::{
    self,
    Deserialize,
    Deserializer,
    MapAccess,
    Visitor
};
use serde::ser::Serializer;
use super::super::prelude::*;
use std::{
    collections::HashMap,
    mem::transmute,
    fmt
};

/// Determines to what entity an action was used on.
#[derive(Debug)]
#[repr(u8)]
pub enum Target {
    Guild = 10,
    Channel = 20,
    User = 30,
    Role = 40,
    Invite = 50,
    Webhook = 60,
    Emoji = 70,
    #[doc(hidden)]
    __Nonexhaustive,
}

/// Determines the action that was done on a target.
#[derive(Debug)]
pub enum Action {
    GuildUpdate,
    Channel(ActionChannel),
    ChannelOverwrite(ActionChannelOverwrite),
    Member(ActionMember),
    Role(ActionRole),
    Invite(ActionInvite),
    Webhook(ActionWebhook),
    Emoji(ActionEmoji),
    MessageDelete,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl Action {
    pub fn num(&self) -> u8 {
        use self::Action::*;

        match *self {
            GuildUpdate => 1,
            Action::Channel(ref x) => x.num(),
            Action::ChannelOverwrite(ref x) => x.num(),
            Action::Member(ref x) => x.num(),
            Action::Role(ref x) => x.num(),
            Action::Invite(ref x) => x.num(),
            Action::Webhook(ref x) => x.num(),
            Action::Emoji(ref x) => x.num(),
            Action::MessageDelete => 72,
            Action::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug)]
#[repr(u8)]
pub enum ActionChannel {
    Create = 10,
    Update = 11,
    Delete = 12,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ActionChannel {
    pub fn num(&self) -> u8 {
        match *self {
            ActionChannel::Create => 10,
            ActionChannel::Update => 11,
            ActionChannel::Delete => 12,
            ActionChannel::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug)]
#[repr(u8)]
pub enum ActionChannelOverwrite {
    Create = 13,
    Update = 14,
    Delete = 15,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ActionChannelOverwrite {
    pub fn num(&self) -> u8 {
        match *self {
            ActionChannelOverwrite::Create => 13,
            ActionChannelOverwrite::Update => 14,
            ActionChannelOverwrite::Delete => 15,
            ActionChannelOverwrite::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug)]
#[repr(u8)]
pub enum ActionMember {
    Kick = 20,
    Prune = 21,
    BanAdd = 22,
    BanRemove = 23,
    Update = 24,
    RoleUpdate = 25,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ActionMember {
    pub fn num(&self) -> u8 {
        match *self {
            ActionMember::Kick => 20,
            ActionMember::Prune => 21,
            ActionMember::BanAdd => 22,
            ActionMember::BanRemove => 23,
            ActionMember::Update => 24,
            ActionMember::RoleUpdate => 25,
            ActionMember::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug)]
#[repr(u8)]
pub enum ActionRole {
    Create = 30,
    Update = 31,
    Delete = 32,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ActionRole {
    pub fn num(&self) -> u8 {
        match *self {
            ActionRole::Create => 30,
            ActionRole::Update => 31,
            ActionRole::Delete => 32,
            ActionRole::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug)]
#[repr(u8)]
pub enum ActionInvite {
    Create = 40,
    Update = 41,
    Delete = 42,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ActionInvite {
    pub fn num(&self) -> u8 {
        match *self {
            ActionInvite::Create => 40,
            ActionInvite::Update => 41,
            ActionInvite::Delete => 42,
            ActionInvite::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug)]
#[repr(u8)]
pub enum ActionWebhook {
    Create = 50,
    Update = 51,
    Delete = 52,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ActionWebhook {
    pub fn num(&self) -> u8 {
        match *self {
            ActionWebhook::Create => 50,
            ActionWebhook::Update => 51,
            ActionWebhook::Delete => 52,
            ActionWebhook::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug)]
#[repr(u8)]
pub enum ActionEmoji {
    Create = 60,
    Delete = 61,
    Update = 62,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ActionEmoji {
    pub fn num(&self) -> u8 {
        match *self {
            ActionEmoji::Create => 60,
            ActionEmoji::Update => 61,
            ActionEmoji::Delete => 62,
            ActionEmoji::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Change {
    #[serde(rename = "key")] pub name: String,
    // TODO: Change these to an actual type.
    #[serde(rename = "old_value")] pub old: String,
    #[serde(rename = "new_value")] pub new: String,
}

#[derive(Debug)]
pub struct AuditLogs {
    pub entries: HashMap<AuditLogEntryId, AuditLogEntry>,
    pub webhooks: Vec<Webhook>,
    pub users: Vec<User>,
    pub(crate) _nonexhaustive: (),
}

#[derive(Debug, Deserialize, Serialize)]
pub struct AuditLogEntry {
    /// Determines to what entity an [`action`] was used on.
    ///
    /// [`action`]: #structfield.action
    #[serde(with = "u64_handler")]
    pub target_id: u64,
    /// Determines what action was done on a [`target`]
    ///
    /// [`target`]: #structfield.target
    #[serde(
        with = "action_handler",
        rename = "action_type"
    )]
    pub action: Action,
    /// What was the reasoning by doing an action on a target? If there was one.
    pub reason: Option<String>,
    /// The user that did this action on a target.
    pub user_id: UserId,
    /// What changes were made.
    pub changes: Option<Vec<Change>>,
    /// The id of this entry.
    pub id: AuditLogEntryId,
    /// Some optional data assosiated with this entry.
    pub options: Option<Options>,
    #[serde(skip)]
    pub(crate) _nonexhaustive: (),
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Options {
    /// Number of days after which inactive members were kicked.
    #[serde(default, with = "option_u64_handler")]
    pub delete_member_days: Option<u64>,
    /// Number of members removed by the prune
    #[serde(default, with = "option_u64_handler")]
    pub members_removed: Option<u64>,
    /// Channel in which the messages were deleted
    #[serde(default)]
    pub channel_id: Option<ChannelId>,
    /// Number of deleted messages.
    #[serde(default, with = "option_u64_handler")]
    pub count: Option<u64>,
    /// Id of the overwritten entity
    #[serde(default, with = "option_u64_handler")]
    pub id: Option<u64>,
    /// Type of overwritten entity ("member" or "role").
    #[serde(default, rename = "type")]
    pub kind: Option<String>,
    /// Name of the role if type is "role"
    #[serde(default)]
    pub role_name: Option<String>,
    #[serde(skip)]
    pub(crate) _nonexhaustive: (),
}

mod u64_handler {
    use super::*;

    pub fn deserialize<'de, D: Deserializer<'de>>(des: D) -> StdResult<u64, D::Error> {
        struct U64Visitor;

        impl<'de> Visitor<'de> for U64Visitor {
            type Value = u64;

            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
                formatter.write_str("an integer or a string with a valid number inside")
            }

            // NOTE: Serde internally delegates number types below `u64` to it.
            fn visit_u64<E: de::Error>(self, val: u64) -> StdResult<u64, E> {
                Ok(val)
            }

            fn visit_str<E: de::Error>(self, string: &str) -> StdResult<u64, E> {
                string.parse().map_err(de::Error::custom)
            }
        }

        des.deserialize_any(U64Visitor)
    }

    // Due to `Serialize`.
    #[allow(clippy::trivially_copy_pass_by_ref)]
    pub fn serialize<S: Serializer>(num: &u64, s: S) -> StdResult<S::Ok, S::Error> {
        s.serialize_u64(*num)
    }
}

mod option_u64_handler {
    use super::*;

    pub fn deserialize<'de, D: Deserializer<'de>>(des: D) -> StdResult<Option<u64>, D::Error> {
        struct OptionU64Visitor;

        impl<'de> Visitor<'de> for OptionU64Visitor {
            type Value = Option<u64>;

            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
                formatter.write_str("an optional integer or a string with a valid number inside")
            }

            fn visit_some<D: Deserializer<'de>>(self, deserializer: D) -> StdResult<Self::Value, D::Error> {
                deserializer.deserialize_any(OptionU64Visitor)
            }

            fn visit_none<E: de::Error>(self) -> StdResult<Self::Value, E> {
                Ok(None)
            }

            fn visit_u64<E: de::Error>(self, val: u64) -> StdResult<Option<u64>, E> {
                Ok(Some(val))
            }

            fn visit_str<E: de::Error>(self, string: &str) -> StdResult<Option<u64>, E> {
                string.parse().map(Some).map_err(de::Error::custom)
            }
        }

        des.deserialize_option(OptionU64Visitor)
    }

    pub fn serialize<S: Serializer>(num: &Option<u64>, s: S) -> StdResult<S::Ok, S::Error> {
        use serde::Serialize;

        Option::serialize(num, s)
    }
}

mod action_handler {
    use super::*;

    pub fn deserialize<'de, D: Deserializer<'de>>(de: D) -> StdResult<Action, D::Error> {
        struct ActionVisitor;

        impl<'de> Visitor<'de> for ActionVisitor {
            type Value = Action;

            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
                formatter.write_str("an integer between 1 to 72")
            }

            // NOTE: Serde internally delegates number types below `u64` to it.
            fn visit_u64<E: de::Error>(self, value: u64) -> StdResult<Action, E> {
                let value = value as u8;

                Ok(match value {
                    1 => Action::GuildUpdate,
                    10..=12 => Action::Channel(unsafe { transmute(value) }),
                    13..=15 => Action::ChannelOverwrite(unsafe { transmute(value) }),
                    20..=25 => Action::Member(unsafe { transmute(value) }),
                    30..=32 => Action::Role(unsafe { transmute(value) }),
                    40..=42 => Action::Invite(unsafe { transmute(value) }),
                    50..=52 => Action::Webhook(unsafe { transmute(value) }),
                    60..=62 => Action::Emoji(unsafe { transmute(value) }),
                    72 => Action::MessageDelete,
                    _ => return Err(E::custom(format!("Unexpected action number: {}", value))),
                })
            }
        }

        de.deserialize_any(ActionVisitor)
    }

    pub fn serialize<S: Serializer>(
        action: &Action,
        serializer: S,
    ) -> StdResult<S::Ok, S::Error> {
        serializer.serialize_u8(action.num())
    }
}
impl<'de> Deserialize<'de> for AuditLogs {
    fn deserialize<D: Deserializer<'de>>(de: D) -> StdResult<Self, D::Error> {
        #[derive(Deserialize)]
        #[serde(field_identifier)]
        enum Field {
            #[serde(rename = "audit_log_entries")] Entries,
            #[serde(rename = "webhooks")] Webhooks,
            #[serde(rename = "users")] Users,
        }

        struct EntriesVisitor;

        impl<'de> Visitor<'de> for EntriesVisitor {
            type Value = AuditLogs;

            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
                formatter.write_str("audit log entries")
            }

            fn visit_map<V: MapAccess<'de>>(self, mut map: V) -> StdResult<AuditLogs, V::Error> {
                let mut audit_log_entries = None;
                let mut users = None;
                let mut webhooks = None;

                while let Some(field) = map.next_key()? {
                    match field {
                        Field::Entries => {
                            if audit_log_entries.is_some() {
                                return Err(de::Error::duplicate_field("entries"));
                            }

                            audit_log_entries = Some(map.next_value::<Vec<AuditLogEntry>>()?);
                        },
                        Field::Webhooks => {
                            if webhooks.is_some() {
                                return Err(de::Error::duplicate_field("webhooks"));
                            }

                            webhooks = Some(map.next_value::<Vec<Webhook>>()?);
                        },
                        Field::Users => {
                            if users.is_some() {
                                return Err(de::Error::duplicate_field("users"));
                            }

                            users = Some(map.next_value::<Vec<User>>()?);
                        },
                    }
                }

                Ok(AuditLogs {
                    entries: audit_log_entries
                        .unwrap()
                        .into_iter()
                        .map(|entry| (entry.id, entry))
                        .collect(),
                    webhooks: webhooks.unwrap(),
                    users: users.unwrap(),
                    _nonexhaustive: (),
                })
            }
        }

        const FIELD: &[&str] = &["audit_log_entries"];
        de.deserialize_struct("AuditLogs", FIELD, EntriesVisitor)
    }
}
<commit_msg>Patch auditlog deserialize to allow unknown fields (#741)<commit_after>use crate::internal::prelude::*;
use serde::de::{
    self,
    Deserialize,
    Deserializer,
    MapAccess,
    Visitor
};
use serde::ser::Serializer;
use super::super::prelude::*;
use std::{
    collections::HashMap,
    mem::transmute,
    fmt,
    error::Error,
};

/// Determines to what entity an action was used on.
#[derive(Debug)]
#[repr(u8)]
pub enum Target {
    Guild = 10,
    Channel = 20,
    User = 30,
    Role = 40,
    Invite = 50,
    Webhook = 60,
    Emoji = 70,
    #[doc(hidden)]
    __Nonexhaustive,
}

/// Determines the action that was done on a target.
#[derive(Debug)]
pub enum Action {
    GuildUpdate,
    Channel(ActionChannel),
    ChannelOverwrite(ActionChannelOverwrite),
    Member(ActionMember),
    Role(ActionRole),
    Invite(ActionInvite),
    Webhook(ActionWebhook),
    Emoji(ActionEmoji),
    MessageDelete,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl Action {
    pub fn num(&self) -> u8 {
        use self::Action::*;

        match *self {
            GuildUpdate => 1,
            Action::Channel(ref x) => x.num(),
            Action::ChannelOverwrite(ref x) => x.num(),
            Action::Member(ref x) => x.num(),
            Action::Role(ref x) => x.num(),
            Action::Invite(ref x) => x.num(),
            Action::Webhook(ref x) => x.num(),
            Action::Emoji(ref x) => x.num(),
            Action::MessageDelete => 72,
            Action::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug)]
#[repr(u8)]
pub enum ActionChannel {
    Create = 10,
    Update = 11,
    Delete = 12,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ActionChannel {
    pub fn num(&self) -> u8 {
        match *self {
            ActionChannel::Create => 10,
            ActionChannel::Update => 11,
            ActionChannel::Delete => 12,
            ActionChannel::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug)]
#[repr(u8)]
pub enum ActionChannelOverwrite {
    Create = 13,
    Update = 14,
    Delete = 15,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ActionChannelOverwrite {
    pub fn num(&self) -> u8 {
        match *self {
            ActionChannelOverwrite::Create => 13,
            ActionChannelOverwrite::Update => 14,
            ActionChannelOverwrite::Delete => 15,
            ActionChannelOverwrite::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug)]
#[repr(u8)]
pub enum ActionMember {
    Kick = 20,
    Prune = 21,
    BanAdd = 22,
    BanRemove = 23,
    Update = 24,
    RoleUpdate = 25,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ActionMember {
    pub fn num(&self) -> u8 {
        match *self {
            ActionMember::Kick => 20,
            ActionMember::Prune => 21,
            ActionMember::BanAdd => 22,
            ActionMember::BanRemove => 23,
            ActionMember::Update => 24,
            ActionMember::RoleUpdate => 25,
            ActionMember::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug)]
#[repr(u8)]
pub enum ActionRole {
    Create = 30,
    Update = 31,
    Delete = 32,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ActionRole {
    pub fn num(&self) -> u8 {
        match *self {
            ActionRole::Create => 30,
            ActionRole::Update => 31,
            ActionRole::Delete => 32,
            ActionRole::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug)]
#[repr(u8)]
pub enum ActionInvite {
    Create = 40,
    Update = 41,
    Delete = 42,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ActionInvite {
    pub fn num(&self) -> u8 {
        match *self {
            ActionInvite::Create => 40,
            ActionInvite::Update => 41,
            ActionInvite::Delete => 42,
            ActionInvite::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug)]
#[repr(u8)]
pub enum ActionWebhook {
    Create = 50,
    Update = 51,
    Delete = 52,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ActionWebhook {
    pub fn num(&self) -> u8 {
        match *self {
            ActionWebhook::Create => 50,
            ActionWebhook::Update => 51,
            ActionWebhook::Delete => 52,
            ActionWebhook::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug)]
#[repr(u8)]
pub enum ActionEmoji {
    Create = 60,
    Delete = 61,
    Update = 62,
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ActionEmoji {
    pub fn num(&self) -> u8 {
        match *self {
            ActionEmoji::Create => 60,
            ActionEmoji::Update => 61,
            ActionEmoji::Delete => 62,
            ActionEmoji::__Nonexhaustive => unreachable!(),
        }
    }
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Change {
    #[serde(rename = "key")] pub name: String,
    // TODO: Change these to an actual type.
    #[serde(rename = "old_value")] pub old: String,
    #[serde(rename = "new_value")] pub new: String,
}

#[derive(Debug)]
pub struct AuditLogs {
    pub entries: HashMap<AuditLogEntryId, AuditLogEntry>,
    pub webhooks: Vec<Webhook>,
    pub users: Vec<User>,
    pub(crate) _nonexhaustive: (),
}

#[derive(Debug, Deserialize, Serialize)]
pub struct AuditLogEntry {
    /// Determines to what entity an [`action`] was used on.
    ///
    /// [`action`]: #structfield.action
    #[serde(with = "u64_handler")]
    pub target_id: u64,
    /// Determines what action was done on a [`target`]
    ///
    /// [`target`]: #structfield.target
    #[serde(
        with = "action_handler",
        rename = "action_type"
    )]
    pub action: Action,
    /// What was the reasoning by doing an action on a target? If there was one.
    pub reason: Option<String>,
    /// The user that did this action on a target.
    pub user_id: UserId,
    /// What changes were made.
    pub changes: Option<Vec<Change>>,
    /// The id of this entry.
    pub id: AuditLogEntryId,
    /// Some optional data assosiated with this entry.
    pub options: Option<Options>,
    #[serde(skip)]
    pub(crate) _nonexhaustive: (),
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Options {
    /// Number of days after which inactive members were kicked.
    #[serde(default, with = "option_u64_handler")]
    pub delete_member_days: Option<u64>,
    /// Number of members removed by the prune
    #[serde(default, with = "option_u64_handler")]
    pub members_removed: Option<u64>,
    /// Channel in which the messages were deleted
    #[serde(default)]
    pub channel_id: Option<ChannelId>,
    /// Number of deleted messages.
    #[serde(default, with = "option_u64_handler")]
    pub count: Option<u64>,
    /// Id of the overwritten entity
    #[serde(default, with = "option_u64_handler")]
    pub id: Option<u64>,
    /// Type of overwritten entity ("member" or "role").
    #[serde(default, rename = "type")]
    pub kind: Option<String>,
    /// Name of the role if type is "role"
    #[serde(default)]
    pub role_name: Option<String>,
    #[serde(skip)]
    pub(crate) _nonexhaustive: (),
}

mod u64_handler {
    use super::*;

    pub fn deserialize<'de, D: Deserializer<'de>>(des: D) -> StdResult<u64, D::Error> {
        struct U64Visitor;

        impl<'de> Visitor<'de> for U64Visitor {
            type Value = u64;

            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
                formatter.write_str("an integer or a string with a valid number inside")
            }

            // NOTE: Serde internally delegates number types below `u64` to it.
            fn visit_u64<E: de::Error>(self, val: u64) -> StdResult<u64, E> {
                Ok(val)
            }

            fn visit_str<E: de::Error>(self, string: &str) -> StdResult<u64, E> {
                string.parse().map_err(de::Error::custom)
            }
        }

        des.deserialize_any(U64Visitor)
    }

    // Due to `Serialize`.
    #[allow(clippy::trivially_copy_pass_by_ref)]
    pub fn serialize<S: Serializer>(num: &u64, s: S) -> StdResult<S::Ok, S::Error> {
        s.serialize_u64(*num)
    }
}

mod option_u64_handler {
    use super::*;

    pub fn deserialize<'de, D: Deserializer<'de>>(des: D) -> StdResult<Option<u64>, D::Error> {
        struct OptionU64Visitor;

        impl<'de> Visitor<'de> for OptionU64Visitor {
            type Value = Option<u64>;

            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
                formatter.write_str("an optional integer or a string with a valid number inside")
            }

            fn visit_some<D: Deserializer<'de>>(self, deserializer: D) -> StdResult<Self::Value, D::Error> {
                deserializer.deserialize_any(OptionU64Visitor)
            }

            fn visit_none<E: de::Error>(self) -> StdResult<Self::Value, E> {
                Ok(None)
            }

            fn visit_u64<E: de::Error>(self, val: u64) -> StdResult<Option<u64>, E> {
                Ok(Some(val))
            }

            fn visit_str<E: de::Error>(self, string: &str) -> StdResult<Option<u64>, E> {
                string.parse().map(Some).map_err(de::Error::custom)
            }
        }

        des.deserialize_option(OptionU64Visitor)
    }

    pub fn serialize<S: Serializer>(num: &Option<u64>, s: S) -> StdResult<S::Ok, S::Error> {
        use serde::Serialize;

        Option::serialize(num, s)
    }
}

mod action_handler {
    use super::*;

    pub fn deserialize<'de, D: Deserializer<'de>>(de: D) -> StdResult<Action, D::Error> {
        struct ActionVisitor;

        impl<'de> Visitor<'de> for ActionVisitor {
            type Value = Action;

            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
                formatter.write_str("an integer between 1 to 72")
            }

            // NOTE: Serde internally delegates number types below `u64` to it.
            fn visit_u64<E: de::Error>(self, value: u64) -> StdResult<Action, E> {
                let value = value as u8;

                Ok(match value {
                    1 => Action::GuildUpdate,
                    10..=12 => Action::Channel(unsafe { transmute(value) }),
                    13..=15 => Action::ChannelOverwrite(unsafe { transmute(value) }),
                    20..=25 => Action::Member(unsafe { transmute(value) }),
                    30..=32 => Action::Role(unsafe { transmute(value) }),
                    40..=42 => Action::Invite(unsafe { transmute(value) }),
                    50..=52 => Action::Webhook(unsafe { transmute(value) }),
                    60..=62 => Action::Emoji(unsafe { transmute(value) }),
                    72 => Action::MessageDelete,
                    _ => return Err(E::custom(format!("Unexpected action number: {}", value))),
                })
            }
        }

        de.deserialize_any(ActionVisitor)
    }

    pub fn serialize<S: Serializer>(
        action: &Action,
        serializer: S,
    ) -> StdResult<S::Ok, S::Error> {
        serializer.serialize_u8(action.num())
    }
}
impl<'de> Deserialize<'de> for AuditLogs {
    fn deserialize<D: Deserializer<'de>>(de: D) -> StdResult<Self, D::Error> {
        #[derive(Deserialize)]
        #[serde(field_identifier)]
        enum Field {
            #[serde(rename = "audit_log_entries")] Entries,
            #[serde(rename = "webhooks")] Webhooks,
            #[serde(rename = "users")] Users,
            // TODO(field added by Discord, undocumented) #[serde(rename = "integrations")] Integrations,
        }

        struct EntriesVisitor;

        impl<'de> Visitor<'de> for EntriesVisitor {
            type Value = AuditLogs;

            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
                formatter.write_str("audit log entries")
            }

            fn visit_map<V: MapAccess<'de>>(self, mut map: V) -> StdResult<AuditLogs, V::Error> {
                let mut audit_log_entries = None;
                let mut users = None;
                let mut webhooks = None;

                loop {
                    match map.next_key() {
                        Ok(Some(Field::Entries)) => {
                            if audit_log_entries.is_some() {
                                return Err(de::Error::duplicate_field("entries"));
                            }

                            audit_log_entries = Some(map.next_value::<Vec<AuditLogEntry>>()?);
                        }
                        Ok(Some(Field::Webhooks)) => {
                            if webhooks.is_some() {
                                return Err(de::Error::duplicate_field("webhooks"));
                            }

                            webhooks = Some(map.next_value::<Vec<Webhook>>()?);
                        }
                        Ok(Some(Field::Users)) => {
                            if users.is_some() {
                                return Err(de::Error::duplicate_field("users"));
                            }

                            users = Some(map.next_value::<Vec<User>>()?);
                        }
                        Ok(None) => break, // No more keys
                        Err(e) => if e.description().contains("unknown field") {
                            // e is of type <V as MapAccess>::Error, which is a macro-defined trait, ultimately
                            // implemented by serde::de::value::Error. Seeing as every error is a simple string and not
                            // using a proper Error num, the best we can do here is to check if the string contains
                            // this error. This was added because Discord randomly started sending new fields.
                            // But no JSON deserializer should ever error over this.
                            map.next_value::<serde_json::Value>()?; // Actually read the value to avoid syntax errors
                        } else {
                            return Err(e)
                        }
                    }
                }

                Ok(AuditLogs {
                    entries: audit_log_entries
                        .unwrap()
                        .into_iter()
                        .map(|entry| (entry.id, entry))
                        .collect(),
                    webhooks: webhooks.unwrap(),
                    users: users.unwrap(),
                    _nonexhaustive: (),
                })
            }
        }

        const FIELD: &[&str] = &["audit_log_entries"];
        de.deserialize_struct("AuditLogs", FIELD, EntriesVisitor)
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Michael 'ExpHP' Lamparski
//
// Licensed under the terms of the MIT License, available at:
//  http://opensource.org/licenses/MIT
// and also included in the file COPYING at the root of this distribution.
// This file may not be copied, modified, or distributed except according
// to those terms.

extern crate num;

use std::collections::hash_map::{HashMap,Hasher};
use std::default::Default;
use std::ops::{Add,Sub,Mul,Div,Rem};
use std::cmp::{min,max};
use std::num::{ToPrimitive,FromPrimitive}; // and regret it
use std::hash::Hash;

use num::{Zero,One,Integer};

/// TODO
#[derive(Show,Clone)]
pub struct Factorization<K>
 where K: Eq + Clone + Hash<Hasher> + ToPrimitive + FromPrimitive + num::Integer,
{
	// powers are currently usize for consistency with the pow() functions
	//  in both std::num and the num crate.
	powers: HashMap<K, usize>,
}

// NOTE: ToPrimitive and FromPrimitive are unstable, and are currently included
//  in case I feel compelled to make a FactorTree using BigInt
impl<K> Factorization<K>
 where K: Eq + Clone + Hash<Hasher> + ToPrimitive + FromPrimitive + num::Integer,
{

	pub fn set(self: &mut Self, key: K, pwr: usize) {
		match pwr {
			0 => self.powers.remove(&key),
			_ => self.powers.insert(key, pwr),
		};
	}

	pub fn get(self: &Self, key: &K) -> usize {
		match self.powers.get(key) {
			None      => 0,
			Some(pwr) => *pwr,
		}
	}

	// TODO: Make private
	pub fn from_factor(factor: K) -> Self
	{
		let mut map = HashMap::new();
		map.insert(factor, 1us);

		Factorization { powers: map }
	}

	// TODO: Make doctests less tedious-looking by using something like
	//        factorize(20), once such a function exists.

	/// The integer represented by this Factorization.
	///
	/// # Example:
	///
	/// ```
	/// use factor::Factorization;
	/// use std::default::Default;
	///
	/// let mut f: Factorization<u64> = Default::default();
	/// f = f * Factorization::from_factor(2);
	/// f = f * Factorization::from_factor(2);
	/// f = f * Factorization::from_factor(5);
	/// assert_eq!(f.product(), 20);
	/// ```
	pub fn product(self: &Self) -> K
	{
		let mut result: K = One::one();
		for (k,v) in self.powers.iter() {
			result = result * num::pow(k.clone(), v.clone());
		};
		result
	}

	/// The total number of positive integers which evenly divide
	///  the number represented by the Factorization (including 1
	///  and the number itself).
	///
	/// # Example:
	///
	/// ```
	/// use factor::Factorization;
	/// use std::default::Default;
	///
	/// let mut f: Factorization<u64> = Default::default();
	/// f = f * Factorization::from_factor(2);
	/// f = f * Factorization::from_factor(2);
	/// f = f * Factorization::from_factor(5);
	/// assert_eq!(f.count_divisors(), 6);
	/// ```
	pub fn count_divisors(self: &Self) -> K
	{
		let mut result: K = One::one();
		for (_,v) in self.powers.iter() {
			result = result * FromPrimitive::from_uint(v.clone() + 1).unwrap();
		};
		result
	}

	/// The sum of all positive integers which evenly divide
	///  the number represented by the Factorization (including 1
	///  and the number itself).
	///
	/// # Example:
	///
	/// ```
	/// use factor::Factorization;
	/// use std::default::Default;
	///
	/// let mut f: Factorization<u64> = Default::default();
	/// f = f * Factorization::from_factor(2);
	/// f = f * Factorization::from_factor(2);
	/// f = f * Factorization::from_factor(5);
	/// assert_eq!(f.sum_divisors(), 42);
	/// ```
	pub fn sum_divisors(self: &Self) -> K
	{
		// A geometric series for each factor
		let mut result: K = One::one();
		for (k,v) in self.powers.iter() {
			result = result * (num::pow(k.clone(), v.clone() + 1) - One::one());
			result = result / (k.clone() - One::one());
		};
		result
	}

	/// Euler totient function $\varphi(x)$, the total number of
	///  positive integers less than `x` that are coprime to `x`.
	///
	/// # Example:
	///
	/// ```
	/// use factor::Factorization;
	/// use std::default::Default;
	///
	/// let mut f: Factorization<u64> = Default::default();
	/// f = f * Factorization::from_factor(2);
	/// f = f * Factorization::from_factor(2);
	/// f = f * Factorization::from_factor(5);
	/// assert_eq!(f.totient(), 8);
	/// ```
	pub fn totient(self: &Self) -> K
	{
		let mut result: K = One::one();
		for (k,v) in self.powers.iter() {
			result = result * num::pow(k.clone(), v.clone() - 1);
			result = result * (k.clone() - One::one());
		};
		return result;
	}

	// TODO: pending unboxed abstract types
	// fn iter_divisors(self: &Self) -> Iterator<K>

	// TODO: Docs
	// Returns None if any factors have odd powers
	///
	/// # Example:
	///
	/// ```
	/// use factor::Factorization;
	/// use std::default::Default;
	///
	/// let mut f: Factorization<u64> = Default::default();
	/// f = f * Factorization::from_factor(2);
	/// f = f * Factorization::from_factor(2);
	/// f = f * Factorization::from_factor(5);
	/// assert!(f.sqrt().is_none());  // 20: not square!
	///
	/// f = f * Factorization::from_factor(5);
	/// assert!(f.sqrt().is_some());  // 100: 10*10
	/// assert_eq!(f.sqrt().unwrap().product(), 10);
	/// ```
	pub fn sqrt(self: &Self) -> Option<Self>
	{
		let mut result = self.clone();
		for (_,v) in result.powers.iter_mut() {

			if *v % 2 == 1 {
				return None; // Odd power!  Abort!  Abort!
			};

			*v = *v / 2;
		};
		Some(result)
	}

	// TODO: Docs & test
	pub fn pow(self: &Self, pwr: usize) -> Self
	{
		let mut result = self.clone();
		for (_,v) in result.powers.iter_mut() {
			*v = *v * pwr;
		};
		result
	}

	// TODO: Docs & test
	pub fn gcd(self: &Self, other: &Self) -> Self
	{
		// Iterate through shorter list
		if other.powers.len() < self.powers.len() {
			return self.gcd(other);
		};

		let mut result: Self = Default::default();
		for (k,v) in other.powers.clone().into_iter() {
			result.set(k.clone(), min(self.get(&k), v));
		};
		result
	}

	// TODO: Docs & test
	pub fn lcm(self: &Self, other: &Self) -> Self
	{
		let mut result = self.clone();
		for (k,v) in other.powers.clone().into_iter() {
			result.set(k.clone(), max(self.get(&k), v));
		};
		result
	}

}

impl<K> Default
for Factorization<K>
 where K: Eq + Clone + Hash<Hasher> + ToPrimitive + FromPrimitive + num::Integer,
{
	/// Creates a Factorization representing 1.
	fn default() -> Self
	{ Factorization { powers: HashMap::new() } }
}

impl<K> Mul<Self> for Factorization<K>
 where K: Eq + Clone + Hash<Hasher> + ToPrimitive + FromPrimitive + num::Integer,
{
	type Output = Self;
	fn mul(self: Self, other: Self) -> Self
	{
		let mut result = self;
		for (k,v) in other.powers.into_iter() {
			let current = result.get(&k); // owned proxy
			result.set(k.clone(), current + v);
		}
		result
	}
}
<commit_msg>Drizzle with TODO sauce<commit_after>// Copyright 2015 Michael 'ExpHP' Lamparski
//
// Licensed under the terms of the MIT License, available at:
//  http://opensource.org/licenses/MIT
// and also included in the file COPYING at the root of this distribution.
// This file may not be copied, modified, or distributed except according
// to those terms.

extern crate num;

use std::collections::hash_map::{HashMap,Hasher};
use std::default::Default;
use std::ops::{Add,Sub,Mul,Div,Rem};
use std::cmp::{min,max};
use std::num::{ToPrimitive,FromPrimitive}; // and regret it
use std::hash::Hash;

use num::{Zero,One,Integer};

/// TODO
#[derive(Show,Clone)]
pub struct Factorization<K>
 where K: Eq + Clone + Hash<Hasher> + ToPrimitive + FromPrimitive + num::Integer,
{
	// powers are currently usize for consistency with the pow() functions
	//  in both std::num and the num crate.
	powers: HashMap<K, usize>,
}

// TODO: some of Factorization's methods need to be special cased for Zero

// TODO: While Factorization is intended to only store prime numbers (and zero)
//        as factors, it will currently accept anything.
//
//       Some alternatives under consideration:
//         * a Prime data type (possibly one form of a "known primality" enum
//             type) for keys
//         * allow non-prime keys.  The issue with this is that many of the
//           math methods (gcd, totient, etc.) are only worth implementing
//           for the all-prime case, and the user would have to be trusted to
//           use them responsibly.

// NOTE: ToPrimitive and FromPrimitive are unstable, and are currently included
//  in case I feel compelled to make a FactorTree using BigInt
impl<K> Factorization<K>
 where K: Eq + Clone + Hash<Hasher> + ToPrimitive + FromPrimitive + num::Integer,
{

	pub fn set(self: &mut Self, key: K, pwr: usize) {
		match pwr {
			0 => self.powers.remove(&key),
			_ => self.powers.insert(key, pwr),
		};
	}

	pub fn get(self: &Self, key: &K) -> usize {
		match self.powers.get(key) {
			None      => 0,
			Some(pwr) => *pwr,
		}
	}

	pub fn from_factor(factor: K) -> Self
	{
		let mut map = HashMap::new();
		map.insert(factor, 1us);

		Factorization { powers: map }
	}

	// TODO: Make doctests less tedious-looking by using something like
	//        factorize(20), once such a function exists.

	/// The integer represented by this Factorization.
	///
	/// # Example:
	///
	/// ```
	/// use factor::Factorization;
	/// use std::default::Default;
	///
	/// let mut f: Factorization<u64> = Default::default();
	/// f = f * Factorization::from_factor(2);
	/// f = f * Factorization::from_factor(2);
	/// f = f * Factorization::from_factor(5);
	/// assert_eq!(f.product(), 20);
	/// ```
	pub fn product(self: &Self) -> K
	{
		let mut result: K = One::one();
		for (k,v) in self.powers.iter() {
			result = result * num::pow(k.clone(), v.clone());
		};
		result
	}

	/// The total number of positive integers which evenly divide
	///  the number represented by the Factorization (including 1
	///  and the number itself).
	///
	/// # Example:
	///
	/// ```
	/// use factor::Factorization;
	/// use std::default::Default;
	///
	/// let mut f: Factorization<u64> = Default::default();
	/// f = f * Factorization::from_factor(2);
	/// f = f * Factorization::from_factor(2);
	/// f = f * Factorization::from_factor(5);
	/// assert_eq!(f.count_divisors(), 6);
	/// ```
	pub fn count_divisors(self: &Self) -> K
	{
		let mut result: K = One::one();
		for (_,v) in self.powers.iter() {
			result = result * FromPrimitive::from_uint(v.clone() + 1).unwrap();
		};
		result
	}

	/// The sum of all positive integers which evenly divide
	///  the number represented by the Factorization (including 1
	///  and the number itself).
	///
	/// # Example:
	///
	/// ```
	/// use factor::Factorization;
	/// use std::default::Default;
	///
	/// let mut f: Factorization<u64> = Default::default();
	/// f = f * Factorization::from_factor(2);
	/// f = f * Factorization::from_factor(2);
	/// f = f * Factorization::from_factor(5);
	/// assert_eq!(f.sum_divisors(), 42);
	/// ```
	pub fn sum_divisors(self: &Self) -> K
	{
		// A geometric series for each factor
		let mut result: K = One::one();
		for (k,v) in self.powers.iter() {
			result = result * (num::pow(k.clone(), v.clone() + 1) - One::one());
			result = result / (k.clone() - One::one());
		};
		result
	}

	/// Euler totient function $\varphi(x)$, the total number of
	///  positive integers less than `x` that are coprime to `x`.
	///
	/// # Example:
	///
	/// ```
	/// use factor::Factorization;
	/// use std::default::Default;
	///
	/// let mut f: Factorization<u64> = Default::default();
	/// f = f * Factorization::from_factor(2);
	/// f = f * Factorization::from_factor(2);
	/// f = f * Factorization::from_factor(5);
	/// assert_eq!(f.totient(), 8);
	/// ```
	pub fn totient(self: &Self) -> K
	{
		let mut result: K = One::one();
		for (k,v) in self.powers.iter() {
			result = result * num::pow(k.clone(), v.clone() - 1);
			result = result * (k.clone() - One::one());
		};
		return result;
	}

	// TODO: pending unboxed abstract types
	// fn iter_divisors(self: &Self) -> Iterator<K>

	// TODO: Docs
	// Returns None if any factors have odd powers
	///
	/// # Example:
	///
	/// ```
	/// use factor::Factorization;
	/// use std::default::Default;
	///
	/// let mut f: Factorization<u64> = Default::default();
	/// f = f * Factorization::from_factor(2);
	/// f = f * Factorization::from_factor(2);
	/// f = f * Factorization::from_factor(5);
	/// assert!(f.sqrt().is_none());  // 20: not square!
	///
	/// f = f * Factorization::from_factor(5);
	/// assert!(f.sqrt().is_some());  // 100: 10*10
	/// assert_eq!(f.sqrt().unwrap().product(), 10);
	/// ```
	pub fn sqrt(self: &Self) -> Option<Self>
	{
		let mut result = self.clone();
		for (_,v) in result.powers.iter_mut() {

			if *v % 2 == 1 {
				return None; // Odd power!  Abort!  Abort!
			};

			*v = *v / 2;
		};
		Some(result)
	}

	// TODO: Docs & test
	pub fn pow(self: &Self, pwr: usize) -> Self
	{
		let mut result = self.clone();
		for (_,v) in result.powers.iter_mut() {
			*v = *v * pwr;
		};
		result
	}

	// TODO: Docs & test
	pub fn gcd(self: &Self, other: &Self) -> Self
	{
		// Iterate through shorter list
		if other.powers.len() < self.powers.len() {
			return self.gcd(other);
		};

		let mut result: Self = Default::default();
		for (k,v) in other.powers.clone().into_iter() {
			result.set(k.clone(), min(self.get(&k), v));
		};
		result
	}

	// TODO: Docs & test
	pub fn lcm(self: &Self, other: &Self) -> Self
	{
		let mut result = self.clone();
		for (k,v) in other.powers.clone().into_iter() {
			result.set(k.clone(), max(self.get(&k), v));
		};
		result
	}

	// TODO: Reasonable (?) methods to implement
	// pub fn is_multiple_of(self: &Self, other: &Self) -> bool
}

impl<K> Default
for Factorization<K>
 where K: Eq + Clone + Hash<Hasher> + ToPrimitive + FromPrimitive + num::Integer,
{
	/// Creates a Factorization representing 1.
	fn default() -> Self
	{ Factorization { powers: HashMap::new() } }
}

impl<K> Mul<Self> for Factorization<K>
 where K: Eq + Clone + Hash<Hasher> + ToPrimitive + FromPrimitive + num::Integer,
{
	type Output = Self;
	fn mul(self: Self, other: Self) -> Self
	{
		let mut result = self;
		for (k,v) in other.powers.into_iter() {
			let current = result.get(&k); // owned proxy
			result.set(k.clone(), current + v);
		}
		result
	}
}
<|endoftext|>