<commit_before>use fnv::FnvHashMap;
use {UndoCmd, UndoStack};

pub struct UndoGroup<'a, T: UndoCmd> {
    group: FnvHashMap<usize, UndoStack<'a, T>>,
    active: Option<usize>,
}

impl<'a, T: UndoCmd> UndoGroup<'a, T> {
    pub fn new() -> Self {
        UndoGroup {
            group: FnvHashMap::default(),
            active: None,
        }
    }

    pub fn with_capacity(capacity: usize) -> Self {
        UndoGroup {
            group: FnvHashMap::with_capacity_and_hasher(capacity, Default::default()),
            active: None,
        }
    }

    pub fn add_undo_stack(&mut self, stack: UndoStack<'a, T>) -> usize {
        let id = match self.group.keys().max() {
            Some(max) => max + 1,
            None => 0,
        };
        self.group.insert(id, stack);
        id
    }

    pub fn remove_undo_stack(&mut self, id: usize) -> Option<UndoStack<'a, T>> {
        self.group.remove(&id)
    }

    pub fn set_active_undo_stack(&mut self, id: usize) -> Result<(), ()> {
        if self.group.contains_key(&id) {
            self.active = Some(id);
            Ok(())
        } else {
            Err(())
        }
    }

    pub fn is_clean(&self) -> Option<bool> {
        self.get_active_stack().map(|t| t.is_clean())
    }

    pub fn is_dirty(&self) -> Option<bool> {
        self.is_clean().map(|t| !t)
    }

    pub fn push(&mut self, cmd: T) {
        if let Some(stack) = self.get_mut_active_stack() {
            stack.push(cmd);
        }
    }

    pub fn redo(&mut self) {
        if let Some(stack) = self.get_mut_active_stack() {
            stack.redo();
        }
    }

    pub fn undo(&mut self) {
        if let Some(stack) = self.get_mut_active_stack() {
            stack.undo();
        }
    }

    fn get_active_stack(&self) -> Option<&UndoStack<'a, T>> {
        self.active.and_then(move |active| self.group.get(&active))
    }

    fn get_mut_active_stack(&mut self) -> Option<&mut UndoStack<'a, T>> {
        self.active.and_then(move |active| self.group.get_mut(&active))
    }
}
<commit_msg>Change active to be a reference instead of a key<commit_after>use fnv::FnvHashMap;
use {UndoCmd, UndoStack};

pub struct UndoGroup<'a, T: UndoCmd + 'a> {
    group: FnvHashMap<usize, UndoStack<'a, T>>,
    active: Option<&'a mut UndoStack<'a, T>>,
}

impl<'a, T: UndoCmd> UndoGroup<'a, T> {
    pub fn new() -> Self {
        UndoGroup {
            group: FnvHashMap::default(),
            active: None,
        }
    }

    pub fn with_capacity(capacity: usize) -> Self {
        UndoGroup {
            group: FnvHashMap::with_capacity_and_hasher(capacity, Default::default()),
            active: None,
        }
    }

    pub fn add_undo_stack(&mut self, stack: UndoStack<'a, T>) -> usize {
        let id = match self.group.keys().max() {
            Some(max) => max + 1,
            None => 0,
        };
        self.group.insert(id, stack);
        id
    }

    pub fn remove_undo_stack(&mut self, id: usize) -> Option<UndoStack<'a, T>> {
        self.group.remove(&id)
    }

    pub fn set_active_undo_stack(&'a mut self, id: usize) {
        self.active = self.group.get_mut(&id);
    }

    pub fn is_clean(&self) -> Option<bool> {
        self.active.as_ref().map(|t| t.is_clean())
    }

    pub fn is_dirty(&self) -> Option<bool> {
        self.is_clean().map(|t| !t)
    }

    pub fn push(&mut self, cmd: T) {
        if let Some(ref mut stack) = self.active {
            stack.push(cmd);
        }
    }

    pub fn redo(&mut self) {
        if let Some(ref mut stack) = self.active {
            stack.redo();
        }
    }

    pub fn undo(&mut self) {
        if let Some(ref mut stack) = self.active {
            stack.undo();
        }
    }
}
<|endoftext|>


<commit_before>use std::default::Default;

#[deriving(Clone,Show)]
pub struct Hints {
    pub resizable: bool,
    pub visible: bool,
    pub decorated: bool,
    pub red_bits: u8,
    pub green_bits: u8,
    pub blue_bits: u8,
    pub alpha_bits: u8,
    pub depth_bits: u8,
    pub stencil_bits: u8,
    pub accum_red_bits: u8,
    pub accum_green_bits: u8,
    pub accum_blue_bits: u8,
    pub accum_alpha_bits: u8,
    pub aux_buffers: u8,
    pub samples: u8,
    pub refresh_rate: u8,
    pub stereo: bool,
    pub srgb_capable: bool,
    pub client_api: ClientAPI,
    pub context_version: (u8, u8),
    //pub robustness: ,
    pub opengl_forward_compat: bool,
    pub opengl_debug_context: bool,
    pub opengl_profile: Profile,
}

#[deriving(Clone, Show)]
pub enum ClientAPI {
    OpenGL,
    OpenGLES,
}

#[deriving(Clone, Show)]
pub enum Profile {
    AnyProfile,
    CompatProfile,
    CoreProfile,
}

impl Default for Hints {
    fn default() -> Hints {
        Hints {
            resizable: true,
            visible: true,
            decorated: true,
            red_bits: 8,
            green_bits: 8,
            blue_bits: 8,
            alpha_bits: 8,
            depth_bits: 24,
            stencil_bits: 8,
            accum_red_bits: 0,
            accum_green_bits: 0,
            accum_blue_bits: 0,
            accum_alpha_bits: 0,
            aux_buffers: 0,
            samples: 0,
            refresh_rate: 0,
            stereo: false,
            srgb_capable: false,
            client_api: OpenGL,
            context_version: (1, 0),
            //robustness: ,
            opengl_forward_compat: false,
            opengl_debug_context: false,
            opengl_profile: AnyProfile,
        }
    }
}
<commit_msg>Mark hints as deprecated<commit_after>use std::default::Default;

#[deriving(Clone,Show)]
#[deprecated = "Will be removed soon (it's not supported anyway)"]
pub struct Hints {
    pub resizable: bool,
    pub visible: bool,
    pub decorated: bool,
    pub red_bits: u8,
    pub green_bits: u8,
    pub blue_bits: u8,
    pub alpha_bits: u8,
    pub depth_bits: u8,
    pub stencil_bits: u8,
    pub accum_red_bits: u8,
    pub accum_green_bits: u8,
    pub accum_blue_bits: u8,
    pub accum_alpha_bits: u8,
    pub aux_buffers: u8,
    pub samples: u8,
    pub refresh_rate: u8,
    pub stereo: bool,
    pub srgb_capable: bool,
    pub client_api: ClientAPI,
    pub context_version: (u8, u8),
    //pub robustness: ,
    pub opengl_forward_compat: bool,
    pub opengl_debug_context: bool,
    pub opengl_profile: Profile,
}

#[deriving(Clone, Show)]
pub enum ClientAPI {
    OpenGL,
    OpenGLES,
}

#[deriving(Clone, Show)]
pub enum Profile {
    AnyProfile,
    CompatProfile,
    CoreProfile,
}

impl Default for Hints {
    fn default() -> Hints {
        Hints {
            resizable: true,
            visible: true,
            decorated: true,
            red_bits: 8,
            green_bits: 8,
            blue_bits: 8,
            alpha_bits: 8,
            depth_bits: 24,
            stencil_bits: 8,
            accum_red_bits: 0,
            accum_green_bits: 0,
            accum_blue_bits: 0,
            accum_alpha_bits: 0,
            aux_buffers: 0,
            samples: 0,
            refresh_rate: 0,
            stereo: false,
            srgb_capable: false,
            client_api: OpenGL,
            context_version: (1, 0),
            //robustness: ,
            opengl_forward_compat: false,
            opengl_debug_context: false,
            opengl_profile: AnyProfile,
        }
    }
}
<|endoftext|>


<commit_before>use std::path::Path;
use rustc_serialize::json::{self, Json};

use git2::build::RepoBuilder;
use git2::{Delta, DiffFormat, DiffDelta, DiffHunk, DiffLine, ObjectType, Tree, Repository,
    ErrorClass, Error as GitError};
use std::str;

static INDEX_GIT_URL: &'static str = "https://github.com/rust-lang/crates.io-index";

pub struct Index {
    repo: Repository,
}

#[derive(Ord, PartialOrd, Eq, PartialEq, Debug)]
pub enum ChangeType {
    Added,
    Yanked
}

#[derive(Ord, PartialOrd, Eq, PartialEq, Debug)]
pub struct Crate {
    pub name: String,
    pub state: ChangeType,
    pub version: String,
}

#[derive(PartialOrd, PartialEq, Debug)]
enum CrateDecodeError {
    InvalidTopology {
        json: Json
    },
    MissingFieldError {
        object: json::Object,
        field: &'static str,
    },
    StringExpected {
        json: Json
    },
    BoolExpected {
        json: Json
    },
}

use self::CrateDecodeError::*;

impl Crate {
    fn from_json(value: Json) -> Result<Crate, CrateDecodeError> {
        fn extract<'a>(o: &'a json::Object,
                       field: &'static str)
                       -> Result<&'a Json, CrateDecodeError> {
            o.get(field).ok_or_else(|| {
                MissingFieldError {
                    object: o.clone(),
                    field: field,
                }
            })
        }

        fn into_string(value: &Json) -> Result<String, CrateDecodeError> {
            value.as_string()
                 .ok_or_else(|| StringExpected { json: value.clone() })
                 .map(Into::into)
        }

        fn into_bool(value: &Json) -> Result<bool, CrateDecodeError> {
            value.as_boolean()
                 .ok_or_else(|| BoolExpected { json: value.clone() })
                 .map(Into::into)
        }

        value.as_object().ok_or_else(|| InvalidTopology { json: value.clone() }).and_then(|o| {
            extract(o, "name")
                .and_then(into_string)
                .and_then(|name| {
                    extract(o, "vers")
                        .and_then(into_string)
                        .and_then(|version| {
                            extract(o, "yanked").and_then(into_bool).map(|yanked| {
                                Crate {
                                    name: name,
                                    state: if yanked {
                                        ChangeType::Yanked
                                    } else {
                                        ChangeType::Added
                                    },
                                    version: version,
                                }
                            })
                        })
                })
        })
    }
}

impl Index {
    pub fn at_path<P>(path: P) -> Result<Index, GitError>
        where P: AsRef<Path>
    {
        let repo =
        Repository::open(path.as_ref()).or_else(|err| if err.class() == ErrorClass::Repository {
            RepoBuilder::new().bare(true).clone(INDEX_GIT_URL, path.as_ref())
        } else {
            Err(err)
        })?;

        Ok(Index { repo: repo })
    }

    pub fn changes<S1, S2>(&self, from: S1, to: S2) -> Result<Vec<Crate>, GitError>
        where S1: AsRef<str>,
              S2: AsRef<str>
    {
        fn into_tree<S: AsRef<str>>(repo: &Repository, rev: S) -> Result<Tree, GitError> {
            repo.revparse_single(rev.as_ref()).and_then(|obj| {
                repo.find_tree(match obj.kind() {
                    Some(ObjectType::Commit) => obj.as_commit().expect("valid commit").tree_id(),
                    _ => /* let it fail later */ obj.id()
                })
            })
        }

        let (from, to) = (into_tree(&self.repo, from)?, into_tree(&self.repo, to)?);
        let diff = self.repo.diff_tree_to_tree(Some(&from), Some(&to), None)?;
        let mut res = Vec::new();
        diff.print(DiffFormat::Patch,
                   |delta: DiffDelta, hunk: Option<DiffHunk>, diffline: DiffLine| -> bool {
                       if !match delta.status() {
                           Delta::Added | Delta::Modified => true,
                           _ => false,
                       } {
                           return true;
                       }

                       let hunk: DiffHunk = match hunk {
                           Some(h) => h,
                           None => return true,
                       };
                       let content = match str::from_utf8(diffline.content()) {
                           Ok(c) => c,
                           Err(_) => return true,
                       };
                       println!("hunk.new_lines() = {:?}", hunk.new_lines());
                       println!("diffline.new_lineno() = {:?}", diffline.new_lineno());
                       println!("diffline.old_lineno() = {:?}", diffline.old_lineno());
                       println!("diffline.origin() = {:?}", diffline.origin());
                       println!("delta.status() = {:?}", delta.status());
                       println!("diffline.content() = {}", str::from_utf8(diffline.content()).unwrap());
                       println!("diffline.num_lines() = {:?}", diffline.num_lines());
                       if diffline.origin() != '+' {
                           return true
                       }

                       if let Some(c) = Json::from_str(content)
                           .ok()
                           .and_then(|json| Crate::from_json(json).ok()) {
                           res.push(c)
                       }
                       return true;
                   })?;

        Ok(res)
    }
}
<commit_msg>fix(index): remove debug prints<commit_after>use std::path::Path;
use rustc_serialize::json::{self, Json};

use git2::build::RepoBuilder;
use git2::{Delta, DiffFormat, DiffDelta, DiffHunk, DiffLine, ObjectType, Tree, Repository,
    ErrorClass, Error as GitError};
use std::str;

static INDEX_GIT_URL: &'static str = "https://github.com/rust-lang/crates.io-index";

pub struct Index {
    repo: Repository,
}

#[derive(Ord, PartialOrd, Eq, PartialEq, Debug)]
pub enum ChangeType {
    Added,
    Yanked
}

#[derive(Ord, PartialOrd, Eq, PartialEq, Debug)]
pub struct Crate {
    pub name: String,
    pub state: ChangeType,
    pub version: String,
}

#[derive(PartialOrd, PartialEq, Debug)]
enum CrateDecodeError {
    InvalidTopology {
        json: Json
    },
    MissingFieldError {
        object: json::Object,
        field: &'static str,
    },
    StringExpected {
        json: Json
    },
    BoolExpected {
        json: Json
    },
}

use self::CrateDecodeError::*;

impl Crate {
    fn from_json(value: Json) -> Result<Crate, CrateDecodeError> {
        fn extract<'a>(o: &'a json::Object,
                       field: &'static str)
                       -> Result<&'a Json, CrateDecodeError> {
            o.get(field).ok_or_else(|| {
                MissingFieldError {
                    object: o.clone(),
                    field: field,
                }
            })
        }

        fn into_string(value: &Json) -> Result<String, CrateDecodeError> {
            value.as_string()
                 .ok_or_else(|| StringExpected { json: value.clone() })
                 .map(Into::into)
        }

        fn into_bool(value: &Json) -> Result<bool, CrateDecodeError> {
            value.as_boolean()
                 .ok_or_else(|| BoolExpected { json: value.clone() })
                 .map(Into::into)
        }

        value.as_object().ok_or_else(|| InvalidTopology { json: value.clone() }).and_then(|o| {
            extract(o, "name")
                .and_then(into_string)
                .and_then(|name| {
                    extract(o, "vers")
                        .and_then(into_string)
                        .and_then(|version| {
                            extract(o, "yanked").and_then(into_bool).map(|yanked| {
                                Crate {
                                    name: name,
                                    state: if yanked {
                                        ChangeType::Yanked
                                    } else {
                                        ChangeType::Added
                                    },
                                    version: version,
                                }
                            })
                        })
                })
        })
    }
}

impl Index {
    pub fn at_path<P>(path: P) -> Result<Index, GitError>
        where P: AsRef<Path>
    {
        let repo =
        Repository::open(path.as_ref()).or_else(|err| if err.class() == ErrorClass::Repository {
            RepoBuilder::new().bare(true).clone(INDEX_GIT_URL, path.as_ref())
        } else {
            Err(err)
        })?;

        Ok(Index { repo: repo })
    }

    pub fn changes<S1, S2>(&self, from: S1, to: S2) -> Result<Vec<Crate>, GitError>
        where S1: AsRef<str>,
              S2: AsRef<str>
    {
        fn into_tree<S: AsRef<str>>(repo: &Repository, rev: S) -> Result<Tree, GitError> {
            repo.revparse_single(rev.as_ref()).and_then(|obj| {
                repo.find_tree(match obj.kind() {
                    Some(ObjectType::Commit) => obj.as_commit().expect("valid commit").tree_id(),
                    _ => /* let it fail later */ obj.id()
                })
            })
        }

        let (from, to) = (into_tree(&self.repo, from)?, into_tree(&self.repo, to)?);
        let diff = self.repo.diff_tree_to_tree(Some(&from), Some(&to), None)?;
        let mut res = Vec::new();
        diff.print(DiffFormat::Patch,
                   |delta: DiffDelta, hunk: Option<DiffHunk>, diffline: DiffLine| -> bool {
                       if !match delta.status() {
                           Delta::Added | Delta::Modified => true,
                           _ => false,
                       } {
                           return true;
                       }

                       let hunk: DiffHunk = match hunk {
                           Some(h) => h,
                           None => return true,
                       };
                       let content = match str::from_utf8(diffline.content()) {
                           Ok(c) => c,
                           Err(_) => return true,
                       };
                       if diffline.origin() != '+' {
                           return true
                       }

                       if let Some(c) = Json::from_str(content)
                           .ok()
                           .and_then(|json| Crate::from_json(json).ok()) {
                           res.push(c)
                       }
                       return true;
                   })?;

        Ok(res)
    }
}
<|endoftext|>


<commit_before>use libc::{c_char, c_ulong, c_int, c_uint, O_RDONLY, read, strerror};
use std::ffi::{c_str_to_bytes, CString};
use std::{mem, os, str};

pub static MAX_JOYSTICK_VALUE:i16 = 32767;
pub static MIN_JOYSTICK_VALUE:i16 = -32767;

static JSIOCGAXES: c_uint = 2147576337;
static JSIOCGBUTTONS: c_uint = 2147576338;
static JSIOCGID: c_uint = 2151705107;
static JSIOCGID_LEN: usize = 64;
extern {
	fn open(path: *const c_char, oflag: c_int) -> c_int;
	fn close(fd: c_int) -> c_int;
	fn ioctl(fd: c_uint, op: c_uint, result: *mut c_char);
}
fn os_error() -> &'static str {
	unsafe {
		let num = os::errno() as c_int;
		let bytes = c_str_to_bytes(mem::transmute(&strerror(num)));
		str::from_utf8(bytes).unwrap()
	}
}
pub struct Joystick {
	id: u8,
	fd: c_int,
	plugged: bool
}
impl Joystick {
	pub fn new(id: u8) -> Result<Joystick, &'static str> {
		let path = format!("/dev/input/js{}", id);
		unsafe {
			let c_path = CString::from_slice(path.as_bytes());
			let fd =  open(c_path.as_ptr(), O_RDONLY | 0x800);
			if fd == -1 {
				Err(os_error())
			} else {
				Ok(Joystick {
					id: id,
					fd: fd,
					plugged: true
				})
			}
		}
	}
	/// Poll this joystick for events
	pub fn poll(&mut self) -> Option<::Event> {
		use ::IntoEvent;
		unsafe {
			let mut event:LinuxEvent = mem::uninitialized();
			loop {
				let event_size = mem::size_of::<LinuxEvent>() as c_ulong;
				if read(self.fd, mem::transmute(&mut event), event_size) == -1 {
					match os::errno() {
						19 => self.plugged = false,
						11 => (),
						code =>
							panic!("Error while polling joystick {} - {} - {}", self.id, code, os_error())
					}
					return None
				} else if event._type & 0x80 == 0 {
					return Some(event.into_event())
				}
			}
		}
	}
	/// Check if this joystick is still plugged in
	pub fn is_plugged(&self) -> bool {
		self.plugged
	}
	/// Get the number of axes supported by this joystick
	pub fn get_num_axes(&self) -> u8 {
		unsafe {
			let mut num_axes: c_char = mem::uninitialized();
			ioctl(self.fd as u32, JSIOCGAXES, &mut num_axes as *mut i8);
			num_axes as u8
		}
	}
	/// Get the number of buttons supported by this joystick
	pub fn get_num_buttons(&self) -> u8 {
		unsafe {
			let mut num_buttons: c_char = mem::uninitialized();
			ioctl(self.fd as u32, JSIOCGBUTTONS, &mut num_buttons as *mut i8);
			num_buttons as u8
		}
	}
	/// Get the pretty identifier of this joystick
	pub fn get_pretty_id(&self) -> String {
		unsafe {
			let text = String::with_capacity(JSIOCGID_LEN);
			ioctl(self.fd as u32, JSIOCGID, text.as_ptr() as *mut i8);
			let new_text = String::from_raw_parts(text.as_ptr() as *mut u8, JSIOCGID_LEN, JSIOCGID_LEN);
			mem::forget(text);
			new_text
		}
	}
	/// Get the numerical identifier of this joystick
	pub fn get_id(&self) -> u8 {
		self.id
	}
}
impl Drop for Joystick {
	fn drop(&mut self) {
		unsafe {
			if close(self.fd) == -1 {
				panic!("Failed to close joystick {} due to {}", self.id, os_error())
			}
		}
	}
}
#[repr(C)]
pub struct LinuxEvent {
	/// timestamp in milleseconds
	time: u32,
	/// value
	value: i16,
	/// event type
	_type: u8,
	/// axis / button number
	number: u8
}
impl ::IntoEvent for LinuxEvent {
	fn into_event(self) -> ::Event {
		match (self._type, self.value) {
			(1, 0) => ::Event::ButtonReleased(self.number),
			(1, 1) => ::Event::ButtonPressed(self.number),
			(2, _) => ::Event::JoystickMoved(self.number, self.value),
			_ => panic!("Bad type and value {} {}", self._type, self.value)
		}
	}
}
<commit_msg>Explain error more<commit_after>use libc::{c_char, c_ulong, c_int, c_uint, O_RDONLY, read, strerror};
use std::ffi::{c_str_to_bytes, CString};
use std::{mem, os, str};

pub static MAX_JOYSTICK_VALUE:i16 = 32767;
pub static MIN_JOYSTICK_VALUE:i16 = -32767;

static JSIOCGAXES: c_uint = 2147576337;
static JSIOCGBUTTONS: c_uint = 2147576338;
static JSIOCGID: c_uint = 2151705107;
static JSIOCGID_LEN: usize = 64;
extern {
	fn open(path: *const c_char, oflag: c_int) -> c_int;
	fn close(fd: c_int) -> c_int;
	fn ioctl(fd: c_uint, op: c_uint, result: *mut c_char);
}
fn os_error() -> &'static str {
	unsafe {
		let num = os::errno() as c_int;
		let bytes = c_str_to_bytes(mem::transmute(&strerror(num)));
		str::from_utf8(bytes).unwrap()
	}
}
pub struct Joystick {
	id: u8,
	fd: c_int,
	plugged: bool
}
impl Joystick {
	pub fn new(id: u8) -> Result<Joystick, &'static str> {
		let path = format!("/dev/input/js{}", id);
		unsafe {
			let c_path = CString::from_slice(path.as_bytes());
			let fd =  open(c_path.as_ptr(), O_RDONLY | 0x800);
			if fd == -1 {
				Err(os_error())
			} else {
				Ok(Joystick {
					id: id,
					fd: fd,
					plugged: true
				})
			}
		}
	}
	/// Poll this joystick for events
	pub fn poll(&mut self) -> Option<::Event> {
		use ::IntoEvent;
		unsafe {
			let mut event:LinuxEvent = mem::uninitialized();
			loop {
				let event_size = mem::size_of::<LinuxEvent>() as c_ulong;
				if read(self.fd, mem::transmute(&mut event), event_size) == -1 {
					match os::errno() {
						19 => self.plugged = false,
						11 => (),
						code =>
							panic!("Error while polling joystick {} - {} - {}", self.id, code, os_error())
					}
					return None
				} else if event._type & 0x80 == 0 {
					return Some(event.into_event())
				}
			}
		}
	}
	/// Check if this joystick is still plugged in
	pub fn is_plugged(&self) -> bool {
		self.plugged
	}
	/// Get the number of axes supported by this joystick
	pub fn get_num_axes(&self) -> u8 {
		unsafe {
			let mut num_axes: c_char = mem::uninitialized();
			ioctl(self.fd as u32, JSIOCGAXES, &mut num_axes as *mut i8);
			num_axes as u8
		}
	}
	/// Get the number of buttons supported by this joystick
	pub fn get_num_buttons(&self) -> u8 {
		unsafe {
			let mut num_buttons: c_char = mem::uninitialized();
			ioctl(self.fd as u32, JSIOCGBUTTONS, &mut num_buttons as *mut i8);
			num_buttons as u8
		}
	}
	/// Get the pretty identifier of this joystick
	pub fn get_pretty_id(&self) -> String {
		unsafe {
			let text = String::with_capacity(JSIOCGID_LEN);
			ioctl(self.fd as u32, JSIOCGID, text.as_ptr() as *mut i8);
			let new_text = String::from_raw_parts(text.as_ptr() as *mut u8, JSIOCGID_LEN, JSIOCGID_LEN);
			mem::forget(text);
			new_text
		}
	}
	/// Get the numerical identifier of this joystick
	pub fn get_id(&self) -> u8 {
		self.id
	}
}
impl Drop for Joystick {
	fn drop(&mut self) {
		unsafe {
			if close(self.fd) == -1 {
				panic!("Failed to close joystick {} due to {}", self.id, os_error())
			}
		}
	}
}
#[repr(C)]
pub struct LinuxEvent {
	/// timestamp in milleseconds
	time: u32,
	/// value
	value: i16,
	/// event type
	_type: u8,
	/// axis / button number
	number: u8
}
impl ::IntoEvent for LinuxEvent {
	fn into_event(self) -> ::Event {
		match (self._type, self.value) {
			(1, 0) => ::Event::ButtonReleased(self.number),
			(1, 1) => ::Event::ButtonPressed(self.number),
			(2, _) => ::Event::JoystickMoved(self.number, self.value),
			_ => panic!("Bad type and value {} {} for joystick", self._type, self.value)
		}
	}
}
<|endoftext|>


<commit_before>use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Mutex, Condvar};
use std::thread;

pub trait Latch {
    fn probe(&self) -> bool;
    fn set(&self);
    fn wait(&self);
}

/// A Latch starts as false and eventually becomes true. You can block
/// until it becomes true.
pub struct SpinLatch {
    b: AtomicBool
}

impl SpinLatch {
    #[inline]
    pub fn new() -> SpinLatch {
        SpinLatch {
            b: AtomicBool::new(false)
        }
    }
}

impl Latch for SpinLatch {
    /// Test if latch is set.
    fn probe(&self) -> bool {
        self.b.load(Ordering::Acquire)
    }

    /// Set the latch to true, releasing all threads who are waiting.
    fn set(&self) {
        self.b.store(true, Ordering::Release);
    }

    /// Spin until latch is set. Use with caution.
    fn wait(&self) {
        while !self.probe() {
            thread::yield_now();
        }
    }
}

/// A Latch starts as false and eventually becomes true. You can block
/// until it becomes true.
pub struct LockLatch {
    b: AtomicBool,
    m: Mutex<()>,
    v: Condvar,
}

impl LockLatch {
    #[inline]
    pub fn new() -> LockLatch {
        LockLatch {
            b: AtomicBool::new(false),
            m: Mutex::new(()),
            v: Condvar::new(),
        }
    }
}

impl Latch for LockLatch {
    /// Test if latch is set.
    fn probe(&self) -> bool {
        self.b.load(Ordering::Acquire)
    }

    /// Set the latch to true, releasing all threads who are waiting.
    fn set(&self) {
        self.b.store(true, Ordering::Release);
        self.v.notify_all();
    }

    /// Spin until latch is set. Use with caution.
    fn wait(&self) {
        let mut guard = self.m.lock().unwrap();
        while !self.probe() {
            guard = self.v.wait(guard).unwrap();
        }
    }
}
<commit_msg>remove the `probe` method from the `Latch` interface<commit_after>use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Mutex, Condvar};
use std::thread;

pub trait Latch {
    fn set(&self);
    fn wait(&self);
}

/// A Latch starts as false and eventually becomes true. You can block
/// until it becomes true.
pub struct SpinLatch {
    b: AtomicBool
}

impl SpinLatch {
    #[inline]
    pub fn new() -> SpinLatch {
        SpinLatch {
            b: AtomicBool::new(false)
        }
    }

    /// Test if latch is set.
    pub fn probe(&self) -> bool {
        self.b.load(Ordering::Acquire)
    }
}

impl Latch for SpinLatch {
    /// Set the latch to true, releasing all threads who are waiting.
    fn set(&self) {
        self.b.store(true, Ordering::Release);
    }

    /// Spin until latch is set. Use with caution.
    fn wait(&self) {
        while !self.probe() {
            thread::yield_now();
        }
    }
}

/// A Latch starts as false and eventually becomes true. You can block
/// until it becomes true.
pub struct LockLatch {
    b: AtomicBool,
    m: Mutex<()>,
    v: Condvar,
}

impl LockLatch {
    #[inline]
    pub fn new() -> LockLatch {
        LockLatch {
            b: AtomicBool::new(false),
            m: Mutex::new(()),
            v: Condvar::new(),
        }
    }
}

impl Latch for LockLatch {
    /// Set the latch to true, releasing all threads who are waiting.
    fn set(&self) {
        self.b.store(true, Ordering::Release);
        self.v.notify_all();
    }

    /// Spin until latch is set. Use with caution.
    fn wait(&self) {
        let mut guard = self.m.lock().unwrap();
        while !self.probe() {
            guard = self.v.wait(guard).unwrap();
        }
    }
}
<|endoftext|>


<commit_before>use std::io::{Read, Chars, CharsError};
use std::borrow::Cow;
use std::fmt;
use std::char;

use num::Num;

use error::{ParserError, ParserErrorKind, StreamError};

/// Token types
#[derive(PartialEq)]
pub enum Token {
    /// `(`
    OpenParen,
    /// `)`
    CloseParen,
    /// `[`
    OpenBracket,
    /// `]`
    CloseBracket,
    /// `#(`
    OpenVectorParen,
    /// `#vu8(`
    OpenBytesParen,
    /// `.`
    Dot,
    /// `'`
    Quote,
    /// `\``
    QuasiQuote,
    /// `,`
    Comma,
    /// `,@`
    UnquoteSplicing,
    Identifier(Cow<'static, str>),
    /// `#t`
    True,
    /// `#f`
    False,
    /// `#\<String>`
    Character(String),
    String(String),
    Numeric(String),
    /// End of character stream
    EOF
}

impl fmt::Debug for Token {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Token::OpenParen => write!(f, "OpenParen"),
            Token::OpenVectorParen => write!(f, "OpenVectorParen"),
            Token::OpenBytesParen => write!(f, "OpenBytesParen"),
            Token::CloseParen => write!(f, "CloseParen"),
            Token::OpenBracket => write!(f, "OpenBracket"),
            Token::CloseBracket => write!(f, "CloseBracket"),
            Token::Dot => write!(f, "Dot"),
            Token::Quote => write!(f, "Quote"),
            Token::QuasiQuote => write!(f, "QuasiQuote"),
            Token::Comma => write!(f, "Comma"),
            Token::UnquoteSplicing => write!(f, "UnquoteSplicing"),
            Token::Identifier(ref name) => write!(f, "Identifier({})", name),
            Token::True => write!(f, "#t"),
            Token::False => write!(f, "#f"),
            Token::Character(ref name) => write!(f, "#\\{}", name),
            Token::Numeric(ref rep) => rep.fmt(f),
            Token::String(ref rep) => write!(f, "{:?}", rep),
            Token::EOF => write!(f, "EOF"),
        }
    }
}

/// TokenWrapper provides positional information to each token
pub struct TokenWrapper {
    pub line: usize,
    pub column: usize,
    pub token: Token
}

fn wrap(line: usize, column: usize, t: Token) -> TokenWrapper {
    TokenWrapper {
        line: line,
        column: column,
        token: t
    }
}

fn is_whitespace(c: char) -> bool {
    match c {
        '\t' | '\n' | '\x0b' | '\x0c' | '\r' | ' ' => true,
        _ => false
    }
}

fn is_initial(c: char) -> bool {
    match c {
        'a'...'z' | 'A'...'Z' | '!' | '$' | '%' | '&' | '*' | '/' | ':' | '<' | '=' | '>' | '?' | '^' | '_' | '~' => true,
        _ => false
    }
}

fn is_subsequent(c: char) -> bool {
    if is_initial(c) {
        true
    } else {
        match c {
            '0'...'9' | '+' | '-' | '.' | '@' => true,
            _ => false
        }
    }
}

fn is_delim(c: char) -> bool {
    match c {
        '(' | ')' | '[' | ']' | '"' | ';' | '#' => true,
        _ => c.is_whitespace()
    }
}

/// Lexer transforms character stream into a token stream
pub struct Lexer<R> {
    line: usize,
    column: usize,
    stream: Chars<R>,
    lookahead_buf: Option<char>,
}

macro_rules! try_consume {
    ($this:ident) => (
        match $this.consume() {
            Some(Ok(c)) => c,
            Some(Err(e)) => return Err($this.make_error(ParserErrorKind::UnderlyingError(StreamError(e)))),
            None => return Err($this.make_error(ParserErrorKind::UnexpectedEOF))
        }
    )
}

impl <R: Read + Sized> Lexer<R> {
    /// Creates new Lexer from io::Buffer
    pub fn new(stream: R) -> Lexer<R> {
        Lexer {
            line: 1,
            column: 1,
            stream: stream.chars(),
            lookahead_buf: None,
        }
    }

    pub fn lex_token(&mut self) -> Result<TokenWrapper, ParserError> {
        try!(self.consume_whitespace());

        let line = self.line;
        let col = self.column;

        let token = try!(self.lex());

        try!(self.consume_whitespace());

        Ok(wrap(line, col, token))
    }

    /// return next token
    fn lex(&mut self) -> Result<Token, ParserError> {
        let c = match try!(self.consume_eof()) {
            Some(c) => c,
            None => return Ok(Token::EOF)
        };

        let end_of_token = try!(self.is_end_of_token());

        if is_initial(c) {
            let mut init = String::new();
            init.push(c);
            self.lex_ident(init).map(|s| Token::Identifier(Cow::Owned(s)))
        } else if c == '+' {
            if end_of_token {
                Ok(Token::Identifier(Cow::Borrowed("+")))
            } else {
                self.lex_numeric("+".to_string()).map(Token::Numeric)
            }
        } else if c == '-' {
            if end_of_token {
                Ok(Token::Identifier(Cow::Borrowed("-")))
            } else {
                match try!(self.lookahead()) {
                    Some('>') => self.lex_ident("-".to_string()).map(|s| Token::Identifier(Cow::Owned(s))),
                    Some(_) => self.lex_numeric("-".to_string()).map(Token::Numeric),
                    None => Ok(Token::Identifier(Cow::Borrowed("-")))
                }
            }
        } else if c == ',' {
            match try!(self.lookahead()) {
                Some('@') => {
                    self.consume().expect("lookahead buffer error");
                    Ok(Token::UnquoteSplicing)
                },
                _ => Ok(Token::Comma)
            }
        } else if c == '(' {
            Ok(Token::OpenParen)
        } else if c == ')' {
            Ok(Token::CloseParen)
        } else if c == '[' {
            Ok(Token::OpenBracket)
        } else if c == ']' {
            Ok(Token::CloseBracket)
        } else if c == '.' {
            if end_of_token {
                Ok(Token::Dot)
            } else {
                let rest_prefix = try!(self.read_while(|c| !is_delim(c)));
                if rest_prefix == ".." {
                    Ok(Token::Identifier(Cow::Borrowed("...")))
                } else {
                    Err(self.make_error(ParserErrorKind::InvalidToken(format!("{}{}", c, rest_prefix))))
                }
            }
        } else if c == '\'' {
            Ok(Token::Quote)
        } else if c == '`' {
            Ok(Token::QuasiQuote)
        } else if c == '#' {
            let c0 = try!(self.consume());
            match c0 {
                't' | 'T' => Ok(Token::True),
                'f' | 'F' => Ok(Token::False),
                'b' | 'B' | 'o' | 'O' | 'd' | 'D' | 'x' | 'X' | 'i' | 'I' | 'e' | 'E' => {
                    let s = format!("{}{}", c, c0);
                    self.lex_numeric(s).map(Token::Numeric)
                },
                'v' | 'u' => {
                    let rest_prefix = try!(self.read_while(|c| !is_delim(c)));
                    let delim = try!(self.consume());
                    let prefix = format!("{}{}{}", c0, rest_prefix, delim);
                    match prefix.as_ref() {
                        "vu8(" | "u8(" =>
                            Ok(Token::OpenBytesParen),
                        _ =>
                            Err(self.make_error(ParserErrorKind::InvalidToken(prefix)))
                    }
                },
                '\\' => self.lex_char().map(Token::Character),
                '(' => Ok(Token::OpenVectorParen),
                _ => Err(self.make_error(ParserErrorKind::InvalidToken(format!("#{}", c))))
            }
        } else if c == '"' {
            self.lex_string().map(Token::String)
        } else if c.is_numeric() {
            let s = format!("{}", c);
            self.lex_numeric(s).map(Token::Numeric)
        } else {
            Err(self.make_error(ParserErrorKind::InvalidCharacter(c)))
        }
    }

    fn is_end_of_token(&mut self) -> Result<bool, ParserError> {
        match try!(self.lookahead()) {
            Some(c) => Ok(is_whitespace(c) || is_delim(c)),
            None => Ok(true)
        }
    }

    fn lex_ident(&mut self, initial: String) -> Result<String, ParserError> {
        let mut s = initial;
        let sub = try!(self.read_while(is_subsequent));
        s.push_str(sub.as_ref());
        return Ok(s);
    }

    fn lex_char(&mut self) -> Result<String, ParserError> {
        let c = try!(self.consume());
        let mut s = String::new();
        s.push(c);
        let sub = try!(self.read_while(|c| c.is_alphanumeric()));
        s.push_str(sub.as_ref());
        return Ok(s);
    }

    fn lex_string(&mut self) -> Result<String, ParserError> {
        let mut s = String::new();
        loop {
            match try!(self.consume()) {
                '"' => return Ok(s),
                '\\' => match try!(self.consume()) {
                    'a' => s.push('\x07'),
                    'b' => s.push('\x08'),
                    't' => s.push('\t'),
                    'n' => s.push('\n'),
                    'v' => s.push('\x0b'),
                    'f' => s.push('\x0c'),
                    'r' => s.push('\r'),
                    '"' => s.push('"'),
                    '\\' => s.push('\\'),
                    'x' => {
                        let hex_str = try!(self.read_while(|c| c != ';'));
                        if try!(self.consume()) != ';' {
                            panic!("read_while error");
                        }
                        if hex_str.len() == 0 {
                            return Err(self.make_error(ParserErrorKind::InvalidStringEscape(hex_str)))
                        }
                        let code = match Num::from_str_radix(hex_str.as_ref(), 16) {
                            Ok(n) => n,
                            Err(_) => return Err(self.make_error(ParserErrorKind::InvalidStringEscape(hex_str)))
                        };
                        match char::from_u32(code) {
                            Some(c) => s.push(c),
                            None => return Err(self.make_error(ParserErrorKind::InvalidUnicodeRange(code)))
                        }
                    },
                    c =>
                        if c.is_whitespace() {
                            try!(self.read_while(|c| c != '\n' && c.is_whitespace()));
                            if c != '\n' {
                                if let '\n' = try!(self.consume()) {
                                    try!(self.read_while(|c| c != '\n' && c.is_whitespace()));
                                } else {
                                    return Err(self.make_error(ParserErrorKind::InvalidStringLiteral))
                                }
                            }
                        } else {
                            return Err(self.make_error(ParserErrorKind::InvalidStringEscape(format!("{}", c))))
                        }
                },
                c => s.push(c),
            }
        }
    }

    fn lex_numeric(&mut self, init: String) -> Result<String, ParserError> {
        let mut s = init;
        let sub = try!(self.read_while(|c| !is_delim(c)));
        s.push_str(sub.as_ref());
        return Ok(s);
    }

    fn make_error(&self, kind: ParserErrorKind) -> ParserError {
        ParserError {
            line: self.line,
            column: self.column,
            kind: kind
        }
    }

    fn lookahead(&mut self) -> Result<Option<char>, CharsError> {
        match self.lookahead_buf {
            Some(c) => Ok(Some(c)),
            None => {
                match self.stream.next() {
                    Some(Ok(ch)) => {
                        self.lookahead_buf = Some(ch);
                        Ok(Some(ch))
                    },
                    Some(Err(e)) => {
                        Err(e)
                    },
                    None => {
                        Ok(None)
                    }
                }
            }
        }
    }

    fn advance(&mut self, c: char) {
        if c == '\n' {
            self.line += 1;
            self.column = 1;
        } else {
            self.column += 1;
        }
    }

    fn read_while<F>(&mut self, f: F) -> Result<String, ParserError> where
        F: Fn(char) -> bool
    {
        let mut s = match self.lookahead_buf {
            None => String::new(),
            Some(c) => if f(c) {
                self.lookahead_buf = None;
                self.advance(c);
                let mut s = String::new();
                s.push(c);
                s
            } else {
                return Ok(String::new());
            }
        };

        loop {
            match self.stream.next() {
                Some(Ok(c)) => if f(c) {
                    self.advance(c);
                    s.push(c);
                } else {
                    self.lookahead_buf = Some(c);
                    return Ok(s);
                },
                Some(Err(e)) =>
                    return Err(self.make_error(ParserErrorKind::UnderlyingError(StreamError(e)))),
                None => return Ok(s)
            }
        }
    }

    fn consume_eof(&mut self) -> Result<Option<char>, CharsError> {
        let c = match self.lookahead_buf {
            Some(c) => {
                self.lookahead_buf = None;
                Some(Ok(c))
            },
            None => self.stream.next()
        };

        match c {
            Some(Ok(ch)) => {
                self.advance(ch);
                Ok(Some(ch))
            },
            Some(Err(e)) => Err(e),
            None => Ok(None)
        }
    }

    fn consume(&mut self) -> Result<char, ParserError> {
        match try!(self.consume_eof()) {
            Some(c) => Ok(c),
            None => return Err(self.make_error(ParserErrorKind::UnexpectedEOF))
        }
    }

    fn consume_whitespace(&mut self) -> Result<bool, ParserError> {
        let mut consumed = false;
        loop {
            let whitespace = try!(self.read_while(is_whitespace));
            consumed = consumed || whitespace.len() > 0;
            if let Some(';') = try!(self.lookahead()) {
                consumed = true;
                try!(self.read_while(|c| c != '\n'));
                if self.lookahead_buf.is_some() {
                    self.lookahead_buf = None;
                }
            } else {
                return Ok(consumed);
            }
        }
    }
}
<commit_msg>More generic whitespace handling<commit_after>use std::io::{Read, Chars, CharsError};
use std::borrow::Cow;
use std::fmt;
use std::char;

use num::Num;

use error::{ParserError, ParserErrorKind, StreamError};

/// Token types
#[derive(PartialEq)]
pub enum Token {
    /// `(`
    OpenParen,
    /// `)`
    CloseParen,
    /// `[`
    OpenBracket,
    /// `]`
    CloseBracket,
    /// `#(`
    OpenVectorParen,
    /// `#vu8(`
    OpenBytesParen,
    /// `.`
    Dot,
    /// `'`
    Quote,
    /// `\``
    QuasiQuote,
    /// `,`
    Comma,
    /// `,@`
    UnquoteSplicing,
    Identifier(Cow<'static, str>),
    /// `#t`
    True,
    /// `#f`
    False,
    /// `#\<String>`
    Character(String),
    String(String),
    Numeric(String),
    /// End of character stream
    EOF
}

impl fmt::Debug for Token {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Token::OpenParen => write!(f, "OpenParen"),
            Token::OpenVectorParen => write!(f, "OpenVectorParen"),
            Token::OpenBytesParen => write!(f, "OpenBytesParen"),
            Token::CloseParen => write!(f, "CloseParen"),
            Token::OpenBracket => write!(f, "OpenBracket"),
            Token::CloseBracket => write!(f, "CloseBracket"),
            Token::Dot => write!(f, "Dot"),
            Token::Quote => write!(f, "Quote"),
            Token::QuasiQuote => write!(f, "QuasiQuote"),
            Token::Comma => write!(f, "Comma"),
            Token::UnquoteSplicing => write!(f, "UnquoteSplicing"),
            Token::Identifier(ref name) => write!(f, "Identifier({})", name),
            Token::True => write!(f, "#t"),
            Token::False => write!(f, "#f"),
            Token::Character(ref name) => write!(f, "#\\{}", name),
            Token::Numeric(ref rep) => rep.fmt(f),
            Token::String(ref rep) => write!(f, "{:?}", rep),
            Token::EOF => write!(f, "EOF"),
        }
    }
}

/// TokenWrapper provides positional information to each token
pub struct TokenWrapper {
    pub line: usize,
    pub column: usize,
    pub token: Token
}

fn wrap(line: usize, column: usize, t: Token) -> TokenWrapper {
    TokenWrapper {
        line: line,
        column: column,
        token: t
    }
}

fn is_whitespace(c: char) -> bool {
    match c {
        '\t' | '\n' | '\x0b' | '\x0c' | '\r' | ' ' | '\u{0085}' => true,
        _ => c.is_whitespace()
    }
}

fn is_initial(c: char) -> bool {
    match c {
        'a'...'z' | 'A'...'Z' | '!' | '$' | '%' | '&' | '*' | '/' | ':' | '<' | '=' | '>' | '?' | '^' | '_' | '~' => true,
        _ => false
    }
}

fn is_subsequent(c: char) -> bool {
    if is_initial(c) {
        true
    } else {
        match c {
            '0'...'9' | '+' | '-' | '.' | '@' => true,
            _ => false
        }
    }
}

fn is_delim(c: char) -> bool {
    match c {
        '(' | ')' | '[' | ']' | '"' | ';' | '#' => true,
        _ => c.is_whitespace()
    }
}

/// Lexer transforms character stream into a token stream
pub struct Lexer<R> {
    line: usize,
    column: usize,
    stream: Chars<R>,
    lookahead_buf: Option<char>,
}

macro_rules! try_consume {
    ($this:ident) => (
        match $this.consume() {
            Some(Ok(c)) => c,
            Some(Err(e)) => return Err($this.make_error(ParserErrorKind::UnderlyingError(StreamError(e)))),
            None => return Err($this.make_error(ParserErrorKind::UnexpectedEOF))
        }
    )
}

impl <R: Read + Sized> Lexer<R> {
    /// Creates new Lexer from io::Buffer
    pub fn new(stream: R) -> Lexer<R> {
        Lexer {
            line: 1,
            column: 1,
            stream: stream.chars(),
            lookahead_buf: None,
        }
    }

    pub fn lex_token(&mut self) -> Result<TokenWrapper, ParserError> {
        try!(self.consume_whitespace());

        let line = self.line;
        let col = self.column;

        let token = try!(self.lex());

        try!(self.consume_whitespace());

        Ok(wrap(line, col, token))
    }

    /// return next token
    fn lex(&mut self) -> Result<Token, ParserError> {
        let c = match try!(self.consume_eof()) {
            Some(c) => c,
            None => return Ok(Token::EOF)
        };

        let end_of_token = try!(self.is_end_of_token());

        if is_initial(c) {
            let mut init = String::new();
            init.push(c);
            self.lex_ident(init).map(|s| Token::Identifier(Cow::Owned(s)))
        } else if c == '+' {
            if end_of_token {
                Ok(Token::Identifier(Cow::Borrowed("+")))
            } else {
                self.lex_numeric("+".to_string()).map(Token::Numeric)
            }
        } else if c == '-' {
            if end_of_token {
                Ok(Token::Identifier(Cow::Borrowed("-")))
            } else {
                match try!(self.lookahead()) {
                    Some('>') => self.lex_ident("-".to_string()).map(|s| Token::Identifier(Cow::Owned(s))),
                    Some(_) => self.lex_numeric("-".to_string()).map(Token::Numeric),
                    None => Ok(Token::Identifier(Cow::Borrowed("-")))
                }
            }
        } else if c == ',' {
            match try!(self.lookahead()) {
                Some('@') => {
                    self.consume().expect("lookahead buffer error");
                    Ok(Token::UnquoteSplicing)
                },
                _ => Ok(Token::Comma)
            }
        } else if c == '(' {
            Ok(Token::OpenParen)
        } else if c == ')' {
            Ok(Token::CloseParen)
        } else if c == '[' {
            Ok(Token::OpenBracket)
        } else if c == ']' {
            Ok(Token::CloseBracket)
        } else if c == '.' {
            if end_of_token {
                Ok(Token::Dot)
            } else {
                let rest_prefix = try!(self.read_while(|c| !is_delim(c)));
                if rest_prefix == ".." {
                    Ok(Token::Identifier(Cow::Borrowed("...")))
                } else {
                    Err(self.make_error(ParserErrorKind::InvalidToken(format!("{}{}", c, rest_prefix))))
                }
            }
        } else if c == '\'' {
            Ok(Token::Quote)
        } else if c == '`' {
            Ok(Token::QuasiQuote)
        } else if c == '#' {
            let c0 = try!(self.consume());
            match c0 {
                't' | 'T' => Ok(Token::True),
                'f' | 'F' => Ok(Token::False),
                'b' | 'B' | 'o' | 'O' | 'd' | 'D' | 'x' | 'X' | 'i' | 'I' | 'e' | 'E' => {
                    let s = format!("{}{}", c, c0);
                    self.lex_numeric(s).map(Token::Numeric)
                },
                'v' | 'u' => {
                    let rest_prefix = try!(self.read_while(|c| !is_delim(c)));
                    let delim = try!(self.consume());
                    let prefix = format!("{}{}{}", c0, rest_prefix, delim);
                    match prefix.as_ref() {
                        "vu8(" | "u8(" =>
                            Ok(Token::OpenBytesParen),
                        _ =>
                            Err(self.make_error(ParserErrorKind::InvalidToken(prefix)))
                    }
                },
                '\\' => self.lex_char().map(Token::Character),
                '(' => Ok(Token::OpenVectorParen),
                _ => Err(self.make_error(ParserErrorKind::InvalidToken(format!("#{}", c))))
            }
        } else if c == '"' {
            self.lex_string().map(Token::String)
        } else if c.is_numeric() {
            let s = format!("{}", c);
            self.lex_numeric(s).map(Token::Numeric)
        } else {
            Err(self.make_error(ParserErrorKind::InvalidCharacter(c)))
        }
    }

    fn is_end_of_token(&mut self) -> Result<bool, ParserError> {
        match try!(self.lookahead()) {
            Some(c) => Ok(is_whitespace(c) || is_delim(c)),
            None => Ok(true)
        }
    }

    fn lex_ident(&mut self, initial: String) -> Result<String, ParserError> {
        let mut s = initial;
        let sub = try!(self.read_while(is_subsequent));
        s.push_str(sub.as_ref());
        return Ok(s);
    }

    fn lex_char(&mut self) -> Result<String, ParserError> {
        let c = try!(self.consume());
        let mut s = String::new();
        s.push(c);
        let sub = try!(self.read_while(|c| c.is_alphanumeric()));
        s.push_str(sub.as_ref());
        return Ok(s);
    }

    fn lex_string(&mut self) -> Result<String, ParserError> {
        let mut s = String::new();
        loop {
            match try!(self.consume()) {
                '"' => return Ok(s),
                '\\' => match try!(self.consume()) {
                    'a' => s.push('\x07'),
                    'b' => s.push('\x08'),
                    't' => s.push('\t'),
                    'n' => s.push('\n'),
                    'v' => s.push('\x0b'),
                    'f' => s.push('\x0c'),
                    'r' => s.push('\r'),
                    '"' => s.push('"'),
                    '\\' => s.push('\\'),
                    'x' => {
                        let hex_str = try!(self.read_while(|c| c != ';'));
                        if try!(self.consume()) != ';' {
                            panic!("read_while error");
                        }
                        if hex_str.len() == 0 {
                            return Err(self.make_error(ParserErrorKind::InvalidStringEscape(hex_str)))
                        }
                        let code = match Num::from_str_radix(hex_str.as_ref(), 16) {
                            Ok(n) => n,
                            Err(_) => return Err(self.make_error(ParserErrorKind::InvalidStringEscape(hex_str)))
                        };
                        match char::from_u32(code) {
                            Some(c) => s.push(c),
                            None => return Err(self.make_error(ParserErrorKind::InvalidUnicodeRange(code)))
                        }
                    },
                    c =>
                        if c.is_whitespace() {
                            try!(self.read_while(|c| c != '\n' && c.is_whitespace()));
                            if c != '\n' {
                                if let '\n' = try!(self.consume()) {
                                    try!(self.read_while(|c| c != '\n' && c.is_whitespace()));
                                } else {
                                    return Err(self.make_error(ParserErrorKind::InvalidStringLiteral))
                                }
                            }
                        } else {
                            return Err(self.make_error(ParserErrorKind::InvalidStringEscape(format!("{}", c))))
                        }
                },
                c => s.push(c),
            }
        }
    }

    fn lex_numeric(&mut self, init: String) -> Result<String, ParserError> {
        let mut s = init;
        let sub = try!(self.read_while(|c| !is_delim(c)));
        s.push_str(sub.as_ref());
        return Ok(s);
    }

    fn make_error(&self, kind: ParserErrorKind) -> ParserError {
        ParserError {
            line: self.line,
            column: self.column,
            kind: kind
        }
    }

    fn lookahead(&mut self) -> Result<Option<char>, CharsError> {
        match self.lookahead_buf {
            Some(c) => Ok(Some(c)),
            None => {
                match self.stream.next() {
                    Some(Ok(ch)) => {
                        self.lookahead_buf = Some(ch);
                        Ok(Some(ch))
                    },
                    Some(Err(e)) => {
                        Err(e)
                    },
                    None => {
                        Ok(None)
                    }
                }
            }
        }
    }

    fn advance(&mut self, c: char) {
        if c == '\n' {
            self.line += 1;
            self.column = 1;
        } else {
            self.column += 1;
        }
    }

    fn read_while<F>(&mut self, f: F) -> Result<String, ParserError> where
        F: Fn(char) -> bool
    {
        let mut s = match self.lookahead_buf {
            None => String::new(),
            Some(c) => if f(c) {
                self.lookahead_buf = None;
                self.advance(c);
                let mut s = String::new();
                s.push(c);
                s
            } else {
                return Ok(String::new());
            }
        };

        loop {
            match self.stream.next() {
                Some(Ok(c)) => if f(c) {
                    self.advance(c);
                    s.push(c);
                } else {
                    self.lookahead_buf = Some(c);
                    return Ok(s);
                },
                Some(Err(e)) =>
                    return Err(self.make_error(ParserErrorKind::UnderlyingError(StreamError(e)))),
                None => return Ok(s)
            }
        }
    }

    fn consume_eof(&mut self) -> Result<Option<char>, CharsError> {
        let c = match self.lookahead_buf {
            Some(c) => {
                self.lookahead_buf = None;
                Some(Ok(c))
            },
            None => self.stream.next()
        };

        match c {
            Some(Ok(ch)) => {
                self.advance(ch);
                Ok(Some(ch))
            },
            Some(Err(e)) => Err(e),
            None => Ok(None)
        }
    }

    fn consume(&mut self) -> Result<char, ParserError> {
        match try!(self.consume_eof()) {
            Some(c) => Ok(c),
            None => return Err(self.make_error(ParserErrorKind::UnexpectedEOF))
        }
    }

    fn consume_whitespace(&mut self) -> Result<bool, ParserError> {
        let mut consumed = false;
        loop {
            let whitespace = try!(self.read_while(is_whitespace));
            consumed = consumed || whitespace.len() > 0;
            if let Some(';') = try!(self.lookahead()) {
                consumed = true;
                try!(self.read_while(|c| c != '\n'));
                if self.lookahead_buf.is_some() {
                    self.lookahead_buf = None;
                }
            } else {
                return Ok(consumed);
            }
        }
    }
}
<|endoftext|>


<commit_before>use std;

#[derive(Debug,Clone,PartialEq)]
pub enum Token {
  // Structure
  EOF,
  Enter,
  Exit,
  Space,
  Comment(String),

  // Literals
  Null,
  Bool(bool),
  Float(f64),
  Int(i64),
  StrLit(String),
  Name(String),

  // Keywords
  Break,
  Continue,
  Else,
  For,
  Func,
  If,
  Return,
  While,

  // Symbols
  Arr, // ->
  Ass, // =
  Col, // :
  Com, // ,
  Dot, // .
  Meta,// ::
  Semi,// ;

  // Braces
  Cul, // {
  Cur, // }
  Pal, // (
  Par, // )
  Sql, // [
  Sqr, // ]

  // Operators
  Add, // +
  And, // &
  Car, // ^
  Div, // /
  Dol, // $
  Mul, // *
  Neg, // ~
  Not, // !
  Or,  // |
  Pct, // %
  Sub, // -

  // Comparisons
  Eql, // ==
  Ge,  // >=
  Gt,  // >
  Le,  // <=
  Lt,  // <
  Ne,  // !=
}

use self::Token::*;

fn lex_number(it: &mut std::iter::Peekable<std::str::Chars>) -> Token {
  let mut digits = String::new();
  while let Some(&c) = it.peek() {
    match c {
      '0'...'9' | '.' => {
        it.next();
        digits.push(c);
      }
      _ => {break}
    }
  }

  match digits.contains(".") {
    true => Float(digits.parse::<f64>().unwrap()),
    false => Int(digits.parse::<i64>().unwrap())
  }
}

fn lex_pair(next: char, solo: Token, pair: Token, it: &mut std::iter::Peekable<std::str::Chars>) -> Token {
  it.next();
  match it.peek() {
    Some(&c) => {
      if c == next {
        it.next();
        pair
      }
      else {
        solo
      }
    }

    // is this right? if it.peek() fails, return the solo token?
    None => solo
  }
}

pub fn lex(input: &str) -> Vec<Token> {
  let mut tokens: Vec<Token> = Vec::new();
  let mut it = input.chars().peekable();

  while let Some(&c) = it.peek() {
    let x = match c {
      '0'...'9' => lex_number(&mut it),
      '-' => lex_pair('>', Sub, Arr, &mut it),
      '<' => lex_pair('=', Lt, Le, &mut it),
      '>' => lex_pair('=', Gt, Ge, &mut it),
      '=' => lex_pair('=', Ass, Eql, &mut it),
      '!' => lex_pair('=', Not, Ne, &mut it),
      ':' => lex_pair(':', Col, Meta, &mut it),
      '+' => {it.next(); Add}
      '/' => {it.next(); Div}
      '*' => {it.next(); Mul}
      '(' => {it.next(); Pal}
      ')' => {it.next(); Par}
      '[' => {it.next(); Sql}
      ']' => {it.next(); Sqr}
      '{' => {it.next(); Cul}
      '}' => {it.next(); Cur}
      _ => {it.next(); Space}
    };

    match x {
     Space => (),
     Comment(_) => (),
      _ => tokens.push(x),
    }

  }

  tokens
}
<commit_msg>lexer: Clean up lex_pair() a bit<commit_after>use std;

#[derive(Debug,Clone,PartialEq)]
pub enum Token {
  // Structure
  EOF,
  Enter,
  Exit,
  Space,
  Comment(String),

  // Literals
  Null,
  Bool(bool),
  Float(f64),
  Int(i64),
  StrLit(String),
  Name(String),

  // Keywords
  Break,
  Continue,
  Else,
  For,
  Func,
  If,
  Return,
  While,

  // Symbols
  Arr, // ->
  Ass, // =
  Col, // :
  Com, // ,
  Dot, // .
  Meta,// ::
  Semi,// ;

  // Braces
  Cul, // {
  Cur, // }
  Pal, // (
  Par, // )
  Sql, // [
  Sqr, // ]

  // Operators
  Add, // +
  And, // &
  Car, // ^
  Div, // /
  Dol, // $
  Mul, // *
  Neg, // ~
  Not, // !
  Or,  // |
  Pct, // %
  Sub, // -

  // Comparisons
  Eql, // ==
  Ge,  // >=
  Gt,  // >
  Le,  // <=
  Lt,  // <
  Ne,  // !=
}

use self::Token::*;

fn lex_number(it: &mut std::iter::Peekable<std::str::Chars>) -> Token {
  let mut digits = String::new();
  while let Some(&c) = it.peek() {
    match c {
      '0'...'9' | '.' => {
        it.next();
        digits.push(c);
      }
      _ => {break}
    }
  }

  match digits.contains(".") {
    true => Float(digits.parse::<f64>().unwrap()),
    false => Int(digits.parse::<i64>().unwrap())
  }
}

fn lex_pair(next: char, solo: Token, pair: Token, it: &mut std::iter::Peekable<std::str::Chars>) -> Token {
  it.next();

  if let Some(&c) = it.peek() {
    if c == next {
      it.next();
      return pair;
    }
  }

  // is this right? if peek() returns a None, we just return `solo`?
  // seems right. None should be the EOF, meaning `solo` is the last token
  solo
}

pub fn lex(input: &str) -> Vec<Token> {
  let mut tokens: Vec<Token> = Vec::new();
  let mut it = input.chars().peekable();

  while let Some(&c) = it.peek() {
    let x = match c {
      '0'...'9' => lex_number(&mut it),
      '-' => lex_pair('>', Sub, Arr, &mut it),
      '<' => lex_pair('=', Lt, Le, &mut it),
      '>' => lex_pair('=', Gt, Ge, &mut it),
      '=' => lex_pair('=', Ass, Eql, &mut it),
      '!' => lex_pair('=', Not, Ne, &mut it),
      ':' => lex_pair(':', Col, Meta, &mut it),
      '+' => {it.next(); Add}
      '/' => {it.next(); Div}
      '*' => {it.next(); Mul}
      '(' => {it.next(); Pal}
      ')' => {it.next(); Par}
      '[' => {it.next(); Sql}
      ']' => {it.next(); Sqr}
      '{' => {it.next(); Cul}
      '}' => {it.next(); Cur}
      _ => {it.next(); Space}
    };

    match x {
     Space => (),
     Comment(_) => (),
      _ => tokens.push(x),
    }

  }

  tokens
}
<|endoftext|>


<commit_before>pub struct Model {
    pub board: Board,
    pub turn: Turn,
    pub white_pieces: u32,
    pub white_hexes: u32,
    pub black_pieces: u32,
    pub black_hexes: u32,
    pub selected_piece: Option<FieldCoord>,
}

impl Model {
    pub fn init() -> Model {
        unimplemented!();
    }
}

pub enum Turn {
    White,
    Black,
}

pub struct Board {
    // The hex board uses an axial coordinate system with (0, 0) at the center. The x-axis slopes
    // up to the right, and the y-axis goes up and down. The board is stored as a dense 2D array,
    // as a ragged array won't work (since each row would have to be a different type).
    board: [[Option<Hex>; 5]; 5],
}

// Fields are numbered clockwise from the top. Even indicies are black, odd indicies are white.
type Hex = [Field; 6];

// There's no need to store the color of the piece on this field, since only white pieces can be on
// white fields, and vice versa.
pub enum Field {
    Piece,
    Empty,
}

impl Board {
    pub fn get_field(&self, coord: &FieldCoord) -> &Field {
        match *self.get_hex(&coord.to_hex()) {
            Some(ref hex) => &hex[coord.f as usize],
            None => panic!("Tried to get field on removed hex: {:?}", coord),
        }
    }
    /// Return fields that share an edge with the given field. These fields are always the opposite
    /// color of the given field. If all of a piece's edge neighbors are occupied, that piece might
    /// be capturable.
    pub fn get_field_edge_neighbors(&self, coord: &FieldCoord) -> Vec<FieldCoord> {
        unimplemented!();
    }
    /// Return fields that share a vertex with the given field and have the same color as the given
    /// field. Pieces can move to fields that are vertex neighbors of the field they are on.
    pub fn get_field_vertex_neighbors(&self, coord: &FieldCoord) -> Vec<FieldCoord> {
        unimplemented!();
    }
    pub fn move_piece(&mut self, from: &FieldCoord, to: &FieldCoord) {
        unimplemented!();
    }
    pub fn remove_piece(&mut self, coord: &FieldCoord) {
        unimplemented!();
    }

    fn get_hex(&self, coord: &HexCoord) -> &Option<Hex> {
        let x = coord.x + 2;
        let y = coord.y + 2;
        &self.board[x as usize][y as usize]
    }
    pub fn get_hex_neighbors(&self, coord: &HexCoord) -> Vec<HexCoord> {
        coord
            .get_neighbors()
            .iter()
            .filter(|&&c| match c {
                Some(_) => true,
                None => false,
            })
            .map(|c| c.unwrap())
            .filter(|c| match *self.get_hex(c) {
                Some(_) => true,
                None => false,
            })
            .collect()
    }
    /// Return fields that share an edge with the given hex and are outside of the given hex. If a
    /// hex is removed from the board, pieces occupying that hex's field neighbors might be
    /// capturable.
    pub fn get_hex_field_neighbors(&self, coord: &HexCoord) -> Vec<FieldCoord> {
        unimplemented!();
    }
    pub fn is_hex_removable(&self, coord: &HexCoord) -> bool {
        unimplemented!();
    }
    pub fn remove_hex(&mut self, coord: &HexCoord) {
        unimplemented!();
    }
}

#[derive(Debug)]
pub struct FieldCoord {
    x: i32,
    y: i32,
    f: u32,
}

#[derive(Clone, Copy)]
pub struct HexCoord {
    x: i32,
    y: i32,
}

impl FieldCoord {
    pub fn new(x: i32, y: i32, f: u32) -> FieldCoord {
        assert!((x + y).abs() <= 2 && x.abs() <= 2 && y.abs() <= 2 && f < 6);
        FieldCoord { x, y, f }
    }
    pub fn to_hex(&self) -> HexCoord {
        HexCoord::new(self.x, self.y)
    }
}

impl HexCoord {
    pub fn new(x: i32, y: i32) -> HexCoord {
        assert!((x + y).abs() <= 2 && x.abs() <= 2 && y.abs() <= 2);
        HexCoord { x, y }
    }
    pub fn to_field(&self, f: u32) -> FieldCoord {
        FieldCoord::new(self.x, self.y, f)
    }
    // We return an array of Options instead of a Vec so that get_hex_field_neighbors and
    // is_hex_removable know which neighbors are on which side of the hex. They need to know this
    // for different reasons:
    //   * get_hex_field_neighbors: the index of each neighboring field depends on which hex
    //                              neighbor that field neighbor is on
    //   * is_hex_removable: a hex is removable if it is attached to the board by 3 or less
    //                       *adjacent* sides
    fn get_neighbors(&self) -> [Option<HexCoord>; 6] {
        let mut neighbors = [None; 6];

        if self.y < 2 && (self.x + self.y) != 2 {
            neighbors[0] = Some(HexCoord::new(self.x, self.y + 1));
        }
        if (self.x + self.y) != 2 && self.x < 2 {
            neighbors[1] = Some(HexCoord::new(self.x + 1, self.y));
        }
        if self.x < 2 && self.y > -2 {
            neighbors[2] = Some(HexCoord::new(self.x + 1, self.y - 1));
        }
        if self.y > -2 && (self.x + self.y) > -2 {
            neighbors[3] = Some(HexCoord::new(self.x, self.y - 1));
        }
        if (self.x + self.y) > -2 && self.x > -2 {
            neighbors[4] = Some(HexCoord::new(self.x - 1, self.y));
        }
        if self.x > -2 && self.y < 2 {
            neighbors[5] = Some(HexCoord::new(self.x - 1, self.y + 1));
        }

        neighbors
    }
}
<commit_msg>Change get_neighbors to return a tuple<commit_after>pub struct Model {
    pub board: Board,
    pub turn: Turn,
    pub white_pieces: u32,
    pub white_hexes: u32,
    pub black_pieces: u32,
    pub black_hexes: u32,
    pub selected_piece: Option<FieldCoord>,
}

impl Model {
    pub fn init() -> Model {
        unimplemented!();
    }
}

pub enum Turn {
    White,
    Black,
}

pub struct Board {
    // The hex board uses an axial coordinate system with (0, 0) at the center. The x-axis slopes
    // up to the right, and the y-axis goes up and down. The board is stored as a dense 2D array,
    // as a ragged array won't work (since each row would have to be a different type).
    board: [[Option<Hex>; 5]; 5],
}

// Fields are numbered clockwise from the top. Even indicies are black, odd indicies are white.
type Hex = [Field; 6];

// There's no need to store the color of the piece on this field, since only white pieces can be on
// white fields, and vice versa.
pub enum Field {
    Piece,
    Empty,
}

impl Board {
    pub fn get_field(&self, coord: &FieldCoord) -> &Field {
        match *self.get_hex(&coord.to_hex()) {
            Some(ref hex) => &hex[coord.f as usize],
            None => panic!("Tried to get field on removed hex: {:?}", coord),
        }
    }
    /// Return fields that share an edge with the given field. These fields are always the opposite
    /// color of the given field. If all of a piece's edge neighbors are occupied, that piece might
    /// be capturable.
    pub fn get_field_edge_neighbors(&self, coord: &FieldCoord) -> Vec<FieldCoord> {
        unimplemented!();
    }
    /// Return fields that share a vertex with the given field and have the same color as the given
    /// field. Pieces can move to fields that are vertex neighbors of the field they are on.
    pub fn get_field_vertex_neighbors(&self, coord: &FieldCoord) -> Vec<FieldCoord> {
        unimplemented!();
    }
    pub fn move_piece(&mut self, from: &FieldCoord, to: &FieldCoord) {
        unimplemented!();
    }
    pub fn remove_piece(&mut self, coord: &FieldCoord) {
        unimplemented!();
    }

    fn get_hex(&self, coord: &HexCoord) -> &Option<Hex> {
        let x = coord.x + 2;
        let y = coord.y + 2;
        &self.board[x as usize][y as usize]
    }
    pub fn get_hex_neighbors(&self, coord: &HexCoord) -> Vec<HexCoord> {
        coord
            .get_neighbors()
            .iter()
            .filter_map(|&(_, c)| match *self.get_hex(&c) {
                Some(_) => Some(c),
                None => None,
            })
            .collect()
    }
    /// Return fields that share an edge with the given hex and are outside of the given hex. If a
    /// hex is removed from the board, pieces occupying that hex's field neighbors might be
    /// capturable.
    pub fn get_hex_field_neighbors(&self, coord: &HexCoord) -> Vec<FieldCoord> {
        unimplemented!();
    }
    pub fn is_hex_removable(&self, coord: &HexCoord) -> bool {
        unimplemented!();
    }
    pub fn remove_hex(&mut self, coord: &HexCoord) {
        unimplemented!();
    }
}

#[derive(Debug)]
pub struct FieldCoord {
    x: i32,
    y: i32,
    f: u32,
}

#[derive(Clone, Copy)]
pub struct HexCoord {
    x: i32,
    y: i32,
}

impl FieldCoord {
    pub fn new(x: i32, y: i32, f: u32) -> FieldCoord {
        assert!((x + y).abs() <= 2 && x.abs() <= 2 && y.abs() <= 2 && f < 6);
        FieldCoord { x, y, f }
    }
    pub fn to_hex(&self) -> HexCoord {
        HexCoord::new(self.x, self.y)
    }
}

impl HexCoord {
    pub fn new(x: i32, y: i32) -> HexCoord {
        assert!((x + y).abs() <= 2 && x.abs() <= 2 && y.abs() <= 2);
        HexCoord { x, y }
    }
    pub fn to_field(&self, f: u32) -> FieldCoord {
        FieldCoord::new(self.x, self.y, f)
    }
    // We return a Vec of tuples so that get_hex_field_neighbors and is_hex_removable know which
    // neighbors are on which side of the hex. They need to know this for different reasons:
    //   * get_hex_field_neighbors: the index of each neighboring field depends on which hex
    //                              neighbor that field neighbor is on
    //   * is_hex_removable: a hex is removable if it is attached to the board by 3 or less
    //                       *adjacent* sides
    fn get_neighbors(&self) -> Vec<(u32, HexCoord)> {
        let mut neighbors = vec![];

        if self.y < 2 && (self.x + self.y) != 2 {
            neighbors.push((0, HexCoord::new(self.x, self.y + 1)));
        }
        if (self.x + self.y) != 2 && self.x < 2 {
            neighbors.push((1, HexCoord::new(self.x + 1, self.y)));
        }
        if self.x < 2 && self.y > -2 {
            neighbors.push((2, HexCoord::new(self.x + 1, self.y - 1)));
        }
        if self.y > -2 && (self.x + self.y) > -2 {
            neighbors.push((3, HexCoord::new(self.x, self.y - 1)));
        }
        if (self.x + self.y) > -2 && self.x > -2 {
            neighbors.push((4, HexCoord::new(self.x - 1, self.y)));
        }
        if self.x > -2 && self.y < 2 {
            neighbors.push((5, HexCoord::new(self.x - 1, self.y + 1)));
        }

        neighbors
    }
}
<|endoftext|>


<commit_before>use std::cell::UnsafeCell;
use std::sync::atomic::{AtomicUsize, Ordering};

use futex;

pub struct Mutex {
    inner: UnsafeCell<MutexInner>
}

struct MutexInner {
    lock: AtomicUsize,
    guard: i32
}

impl Mutex {
    pub fn new() -> Mutex {
        Mutex { inner: UnsafeCell::new(MutexInner::new()) }
    }

    pub fn lock(&mut self) {
        unsafe {
            let ref mut inner = *self.inner.get();
            inner.lock()
        }
    }

    pub fn unlock(&mut self) {
        unsafe {
            let ref mut inner = *self.inner.get();
            inner.unlock()
        }
    }
}

const LOCK_FREE: usize = 0xa5a5a5a5;

/// TODO: handle all let _ = ... error cases.
impl MutexInner {
    pub fn new() -> MutexInner {
        MutexInner {
            lock: AtomicUsize::new(LOCK_FREE),
            guard: 0
        }
    }

    pub fn unlock(&mut self) {
        let old_val = self.lock.load(Ordering::Relaxed);

        if old_val != /* TODO: get thread id */ 0 {
            panic!("trying to unlock a mutex we don't own");
        }

        // mark the lock as free
        self.lock.store(LOCK_FREE, Ordering::Relaxed);

        // wake up 1 thread waiting to lock
        let _ = futex::wake(&mut self.guard, 1);
    }

    pub fn lock(&mut self) {
        loop {
            // TODO: get thread id.
            let tid = 0i32;
            let swap = self.lock.compare_and_swap(LOCK_FREE, tid as usize, Ordering::Relaxed);

            // If compare_and_swap didn't return LOCK_FREE, we weren't the ones
            // to set it, so go to sleep and spin.
            if swap != LOCK_FREE {
                self.guard = tid;

                // Go to sleep, wait for someone to unlock
                let _ = futex::wait(&mut self.guard, 0);
            }
            // Otherwise we've got the mutex, time to return.
            else { break; }
        }
    }
}
<commit_msg>Have mutex take advantage of get_current_thread<commit_after>use std::cell::UnsafeCell;
use std::sync::atomic::{AtomicUsize, Ordering};

use futex;
use thread;

pub struct Mutex {
    inner: UnsafeCell<MutexInner>
}

struct MutexInner {
    lock: AtomicUsize,
    guard: i32
}

impl Mutex {
    pub fn new() -> Mutex {
        Mutex { inner: UnsafeCell::new(MutexInner::new()) }
    }

    pub fn lock(&mut self) {
        unsafe {
            let inner = &mut *self.inner.get();
            inner.lock()
        }
    }

    pub fn unlock(&mut self) {
        unsafe {
            let inner = &mut *self.inner.get();
            inner.unlock()
        }
    }
}

const LOCK_FREE: usize = 0xa5a5a5a5;

/// TODO: handle all let _ = ... error cases.
impl MutexInner {
    pub fn new() -> MutexInner {
        MutexInner {
            lock: AtomicUsize::new(LOCK_FREE),
            guard: 0
        }
    }

    pub fn unlock(&mut self) {
        let old_val = self.lock.load(Ordering::Relaxed);

        if old_val != thread::get_current_thread().tid as usize {
            panic!("trying to unlock a mutex we don't own");
        }

        // mark the lock as free
        self.lock.store(LOCK_FREE, Ordering::Relaxed);

        // wake up 1 thread waiting to lock
        let _ = futex::wake(&mut self.guard, 1);
    }

    pub fn lock(&mut self) {
        loop {
            let tid = thread::get_current_thread().tid;
            let swap = self.lock.compare_and_swap(LOCK_FREE, tid as usize, Ordering::Relaxed);

            // If compare_and_swap didn't return LOCK_FREE, we weren't the ones
            // to set it, so go to sleep and spin.
            if swap != LOCK_FREE {
                // Go to sleep, wait for someone to unlock
                let _ = futex::wait(&mut self.guard, 0);
            }
            // Otherwise we've got the mutex, time to return.
            else { break; }
        }
    }
}
<|endoftext|>