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

//! Windows console handling

// FIXME (#13400): this is only a tiny fraction of the Windows console api

extern crate libc;

use std::io::IoResult;

use Attr;
use color;
use {Terminal,UnwrappableTerminal};

/// A Terminal implementation which uses the Win32 Console API.
pub struct WinConsole<T> {
    buf: T,
    def_foreground: color::Color,
    def_background: color::Color,
    foreground: color::Color,
    background: color::Color,
}

#[allow(non_snake_case)]
#[repr(C)]
struct CONSOLE_SCREEN_BUFFER_INFO {
    dwSize: [libc::c_short; 2],
    dwCursorPosition: [libc::c_short; 2],
    wAttributes: libc::WORD,
    srWindow: [libc::c_short; 4],
    dwMaximumWindowSize: [libc::c_short; 2],
}

#[allow(non_snake_case)]
#[link(name = "kernel32")]
extern "system" {
    fn SetConsoleTextAttribute(handle: libc::HANDLE, attr: libc::WORD) -> libc::BOOL;
    fn GetStdHandle(which: libc::DWORD) -> libc::HANDLE;
    fn GetConsoleScreenBufferInfo(handle: libc::HANDLE,
                                  info: *mut CONSOLE_SCREEN_BUFFER_INFO) -> libc::BOOL;
}

fn color_to_bits(color: color::Color) -> u16 {
    // magic numbers from mingw-w64's wincon.h

    let bits = match color % 8 {
        color::BLACK   => 0,
        color::BLUE    => 0x1,
        color::GREEN   => 0x2,
        color::RED     => 0x4,
        color::YELLOW  => 0x2 | 0x4,
        color::MAGENTA => 0x1 | 0x4,
        color::CYAN    => 0x1 | 0x2,
        color::WHITE   => 0x1 | 0x2 | 0x4,
        _ => unreachable!()
    };

    if color >= 8 {
        bits | 0x8
    } else {
        bits
    }
}

fn bits_to_color(bits: u16) -> color::Color {
    let color = match bits & 0x7 {
        0 => color::BLACK,
        0x1 => color::BLUE,
        0x2 => color::GREEN,
        0x4 => color::RED,
        0x6 => color::YELLOW,
        0x5 => color::MAGENTA,
        0x3 => color::CYAN,
        0x7 => color::WHITE,
        _ => unreachable!()
    };

    color | (bits & 0x8) // copy the hi-intensity bit
}

impl<T: Writer+Send> WinConsole<T> {
    fn apply(&mut self) {
        let _unused = self.buf.flush();
        let mut accum: libc::WORD = 0;
        accum |= color_to_bits(self.foreground);
        accum |= color_to_bits(self.background) << 4;

        unsafe {
            // Magic -11 means stdout, from
            // http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231%28v=vs.85%29.aspx
            //
            // You may be wondering, "but what about stderr?", and the answer
            // to that is that setting terminal attributes on the stdout
            // handle also sets them for stderr, since they go to the same
            // terminal! Admittedly, this is fragile, since stderr could be
            // redirected to a different console. This is good enough for
            // rustc though. See #13400.
            let out = GetStdHandle(-11);
            SetConsoleTextAttribute(out, accum);
        }
    }

    /// Returns `None` whenever the terminal cannot be created for some
    /// reason.
    pub fn new(out: T) -> Option<Winconsole<T>> {
        let fg;
        let bg;
        unsafe {
            let mut buffer_info = ::std::mem::uninitialized();
            if GetConsoleScreenBufferInfo(GetStdHandle(-11), &mut buffer_info) != 0 {
                fg = bits_to_color(buffer_info.wAttributes);
                bg = bits_to_color(buffer_info.wAttributes >> 4);
            } else {
                fg = color::WHITE;
                bg = color::BLACK;
            }
        }
        Some(WinConsole {
            buf: out,
            def_foreground: fg,
            def_background: bg,
            foreground: fg,
            background: bg,
        })
    }
}

impl<T: Writer> Writer for WinConsole<T> {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        self.buf.write(buf)
    }

    fn flush(&mut self) -> IoResult<()> {
        self.buf.flush()
    }
}

impl<T: Writer+Send> Terminal<T> for WinConsole<T> {
    fn fg(&mut self, color: color::Color) -> IoResult<bool> {
        self.foreground = color;
        self.apply();

        Ok(true)
    }

    fn bg(&mut self, color: color::Color) -> IoResult<bool> {
        self.background = color;
        self.apply();

        Ok(true)
    }

    fn attr(&mut self, attr: Attr) -> IoResult<bool> {
        match attr {
            Attr::ForegroundColor(f) => {
                self.foreground = f;
                self.apply();
                Ok(true)
            },
            Attr::BackgroundColor(b) => {
                self.background = b;
                self.apply();
                Ok(true)
            },
            _ => Ok(false)
        }
    }

    fn supports_attr(&self, attr: Attr) -> bool {
        // it claims support for underscore and reverse video, but I can't get
        // it to do anything -cmr
        match attr {
            Attr::ForegroundColor(_) | Attr::BackgroundColor(_) => true,
            _ => false
        }
    }

    fn reset(&mut self) -> IoResult<bool> {
        self.foreground = self.def_foreground;
        self.background = self.def_background;
        self.apply();

        Ok(true)
    }

    fn get_ref<'a>(&'a self) -> &'a T { &self.buf }

    fn get_mut<'a>(&'a mut self) -> &'a mut T { &mut self.buf }
}

impl<T: Writer+Send> UnwrappableTerminal<T> for WinConsole<T> {
    fn unwrap(self) -> T { self.buf }
}
<commit_msg>Fix a typo that broke the windows build<commit_after>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Windows console handling

// FIXME (#13400): this is only a tiny fraction of the Windows console api

extern crate libc;

use std::io::IoResult;

use Attr;
use color;
use {Terminal,UnwrappableTerminal};

/// A Terminal implementation which uses the Win32 Console API.
pub struct WinConsole<T> {
    buf: T,
    def_foreground: color::Color,
    def_background: color::Color,
    foreground: color::Color,
    background: color::Color,
}

#[allow(non_snake_case)]
#[repr(C)]
struct CONSOLE_SCREEN_BUFFER_INFO {
    dwSize: [libc::c_short; 2],
    dwCursorPosition: [libc::c_short; 2],
    wAttributes: libc::WORD,
    srWindow: [libc::c_short; 4],
    dwMaximumWindowSize: [libc::c_short; 2],
}

#[allow(non_snake_case)]
#[link(name = "kernel32")]
extern "system" {
    fn SetConsoleTextAttribute(handle: libc::HANDLE, attr: libc::WORD) -> libc::BOOL;
    fn GetStdHandle(which: libc::DWORD) -> libc::HANDLE;
    fn GetConsoleScreenBufferInfo(handle: libc::HANDLE,
                                  info: *mut CONSOLE_SCREEN_BUFFER_INFO) -> libc::BOOL;
}

fn color_to_bits(color: color::Color) -> u16 {
    // magic numbers from mingw-w64's wincon.h

    let bits = match color % 8 {
        color::BLACK   => 0,
        color::BLUE    => 0x1,
        color::GREEN   => 0x2,
        color::RED     => 0x4,
        color::YELLOW  => 0x2 | 0x4,
        color::MAGENTA => 0x1 | 0x4,
        color::CYAN    => 0x1 | 0x2,
        color::WHITE   => 0x1 | 0x2 | 0x4,
        _ => unreachable!()
    };

    if color >= 8 {
        bits | 0x8
    } else {
        bits
    }
}

fn bits_to_color(bits: u16) -> color::Color {
    let color = match bits & 0x7 {
        0 => color::BLACK,
        0x1 => color::BLUE,
        0x2 => color::GREEN,
        0x4 => color::RED,
        0x6 => color::YELLOW,
        0x5 => color::MAGENTA,
        0x3 => color::CYAN,
        0x7 => color::WHITE,
        _ => unreachable!()
    };

    color | (bits & 0x8) // copy the hi-intensity bit
}

impl<T: Writer+Send> WinConsole<T> {
    fn apply(&mut self) {
        let _unused = self.buf.flush();
        let mut accum: libc::WORD = 0;
        accum |= color_to_bits(self.foreground);
        accum |= color_to_bits(self.background) << 4;

        unsafe {
            // Magic -11 means stdout, from
            // http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231%28v=vs.85%29.aspx
            //
            // You may be wondering, "but what about stderr?", and the answer
            // to that is that setting terminal attributes on the stdout
            // handle also sets them for stderr, since they go to the same
            // terminal! Admittedly, this is fragile, since stderr could be
            // redirected to a different console. This is good enough for
            // rustc though. See #13400.
            let out = GetStdHandle(-11);
            SetConsoleTextAttribute(out, accum);
        }
    }

    /// Returns `None` whenever the terminal cannot be created for some
    /// reason.
    pub fn new(out: T) -> Option<WinConsole<T>> {
        let fg;
        let bg;
        unsafe {
            let mut buffer_info = ::std::mem::uninitialized();
            if GetConsoleScreenBufferInfo(GetStdHandle(-11), &mut buffer_info) != 0 {
                fg = bits_to_color(buffer_info.wAttributes);
                bg = bits_to_color(buffer_info.wAttributes >> 4);
            } else {
                fg = color::WHITE;
                bg = color::BLACK;
            }
        }
        Some(WinConsole {
            buf: out,
            def_foreground: fg,
            def_background: bg,
            foreground: fg,
            background: bg,
        })
    }
}

impl<T: Writer> Writer for WinConsole<T> {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        self.buf.write(buf)
    }

    fn flush(&mut self) -> IoResult<()> {
        self.buf.flush()
    }
}

impl<T: Writer+Send> Terminal<T> for WinConsole<T> {
    fn fg(&mut self, color: color::Color) -> IoResult<bool> {
        self.foreground = color;
        self.apply();

        Ok(true)
    }

    fn bg(&mut self, color: color::Color) -> IoResult<bool> {
        self.background = color;
        self.apply();

        Ok(true)
    }

    fn attr(&mut self, attr: Attr) -> IoResult<bool> {
        match attr {
            Attr::ForegroundColor(f) => {
                self.foreground = f;
                self.apply();
                Ok(true)
            },
            Attr::BackgroundColor(b) => {
                self.background = b;
                self.apply();
                Ok(true)
            },
            _ => Ok(false)
        }
    }

    fn supports_attr(&self, attr: Attr) -> bool {
        // it claims support for underscore and reverse video, but I can't get
        // it to do anything -cmr
        match attr {
            Attr::ForegroundColor(_) | Attr::BackgroundColor(_) => true,
            _ => false
        }
    }

    fn reset(&mut self) -> IoResult<bool> {
        self.foreground = self.def_foreground;
        self.background = self.def_background;
        self.apply();

        Ok(true)
    }

    fn get_ref<'a>(&'a self) -> &'a T { &self.buf }

    fn get_mut<'a>(&'a mut self) -> &'a mut T { &mut self.buf }
}

impl<T: Writer+Send> UnwrappableTerminal<T> for WinConsole<T> {
    fn unwrap(self) -> T { self.buf }
}
<|endoftext|>


<commit_before>#![allow(non_upper_case_globals)]

pub use self::x86_shared::*;

use core::prelude::*;
use core::mem::size_of;

mod x86_shared;

bitflags! {
	flags EFlags: u32 {
		const CarryFlag = 1 << 0,
		const ParityFlag = 1 << 2,
		const AdjustFlag = 1 << 4,
		const ZeroFlag = 1 << 6,
		const SignFlag = 1 << 7,
		const TrapFlag = 1 << 8,
		const InterruptFlag = 1 << 9,
		const DirectionFlag = 1 << 10,
		const OverflowFlag = 1 << 11,
		const Iopl1 = 1 << 12,
		const Iopl2 = 1 << 13,
		const NestedTaskFlag = 1 << 14,
		const ResumeFlag = 1 << 16,
		const Virtual8086Flag = 1 << 17,
		const AlignmentFlag = 1 << 18,
		const VirtualInterruptFlag = 1 << 19,
		const VirtualInterruptPending = 1 << 20,
		const CpuIdFlag = 1 << 21
	}
}

bitflags! {
	flags Cr0Flags: u32 {
		const ProtectedMode = 1 << 0,
		const MonitorCoprocessor = 1 << 1,
		const EmulateCoprocessor = 1 << 2,
		const TaskSwitched = 1 << 3,
		const ExtensionType = 1 << 4,
		const NumericError = 1 << 5,
		const WriteProtect = 1 << 16,
		const AlignmentMask = 1 << 18,
		const NotWriteThrough = 1 << 29,
		const CacheDisable = 1 << 30,
		const EnablePaging = 1 << 31
	}
}

bitflags! {
	flags Cr4Flags: u32 {
		const EnableVme = 1 << 0,
		const VirtualInterrupts = 1 << 1,
		const TimeStampDisable = 1 << 2,
		const DebuggingExtensions = 1 << 3,
		const EnablePse = 1 << 4,
		const EnablePae = 1 << 5,
		const EnableMachineCheck = 1 << 6,
		const EnableGlobalPages = 1 << 7,
		const EnablePpmc = 1 << 8,
		const EnableSse = 1 << 9,
		const UnmaskedSse = 1 << 10,
		const EnableVmx = 1 << 13,
		const EnableSmx = 1 << 14,
		const EnablePcid = 1 << 17,
		const EnableOsXSave = 1 << 18,
		const EnableSmep = 1 << 20,
		const EnableSmap = 1 << 21
	}
}

bitflags! {
	flags GdtAccess: u8 {
		const Accessed = 1 << 0,
		const Writable = 1 << 1,
		const Direction = 1 << 2,
		const Executable = 1 << 3,
		const NotTss = 1 << 4,
	}
}

#[derive(Copy, Clone)]
#[repr(C, packed)]
pub struct GdtEntry {
	limit: u16,
	base1: u16,
	base2: u8,
	access: u8,
	flags: u8,
	base3: u8,
}

#[derive(Copy, Clone)]
#[repr(C, packed)]
pub struct IdtEntry {
	offset1: u16,
	selector: u16,
	reserved: u8,
	flags: u8,
	offset2: u16
}

impl GdtEntry {
	pub fn null() -> GdtEntry {
		GdtEntry {
			base1: 0,
			base2: 0,
			base3: 0,
			access: 0,
			limit: 0,
			flags: 0
		}
	}

	pub fn new(base: *const (), limit: usize, access: GdtAccess, dpl: PrivilegeLevel) -> GdtEntry {
		let (limit, flags) = if limit < 0x100000 {
			((limit & 0xFFFF) as u16, ((limit & 0xF0000) >> 16) as u8 | 0x40u8)
		} else {
			if ((limit - 0xFFF) & 0xFFF) > 0 {
				panic!("bad segment limit for GDT entry");
			}
			(((limit & 0xFFFF000) >> 12) as u16, ((limit & 0xF0000000) >> 28) as u8 | 0xC0u8)
		};
		GdtEntry {
			base1: base as u16,
			base2: ((base as usize & 0xFF0000) >> 16) as u8,
			base3: ((base as usize & 0xFF000000) >> 24) as u8,
			access: access.bits() | ((dpl as u8) << 5) | 0x80,
			limit: limit,
			flags: flags
		}
	}
}

pub const NULL_IDT_ENTRY: IdtEntry = IdtEntry { offset1: 0, selector: 0, reserved: 0, flags: 0, offset2: 0 };

impl IdtEntry {
	pub fn new(f: unsafe extern "C" fn(), dpl: PrivilegeLevel, block: bool) -> IdtEntry {
		IdtEntry {
			offset1: f as u16,
			offset2: ((f as usize & 0xFFFF0000) >> 16) as u16,
			selector: 8,
			reserved: 0,
			flags: if block { 0x8E } else { 0x8F } | ((dpl as u8) << 5)
		}
	}
}

#[derive(Copy, Clone)]
#[repr(C, packed)]
pub struct Tss {
	pub link: u16,
	reserved0: u16,
	pub esp0: u32,
	pub ss0: u16,
	reserved1: u16,
	pub esp1: u32,
	pub ss1: u16,
	reserved2: u16,
	pub esp2: u32,
	pub ss2: u16,
	reserved3: u16,

	pub cr3: u32,
	pub eip: u32,
	pub eflags: u32,

	pub eax: u32,
	pub ecx: u32,
	pub edx: u32,
	pub ebx: u32,
	pub esp: u32,
	pub ebp: u32,
	pub esi: u32,
	pub edi: u32,

	pub es: u16,
	reserved4: u16,
	pub cs: u16,
	reserved5: u16,
	pub ss: u16,
	reserved6: u16,
	pub ds: u16,
	reserved7: u16,
	pub fs: u16,
	reserved8: u16,
	pub gs: u16,
	reserved9: u16,
	pub ldtr: u16,
	reserved10: u32,
	pub iobp_offset: u16
}

impl Tss {
	pub fn new() -> Tss {
		Tss {
			link: 0,
			reserved0: 0,
			esp0: 0,
			ss0: 0,
			reserved1: 0,
			esp1: 0,
			ss1: 0,
			reserved2: 0,
			esp2: 0,
			ss2: 0,
			reserved3: 0,
			cr3: 0,
			eip: 0,
			eflags: 0,
			eax: 0,
			ecx: 0,
			edx: 0,
			ebx: 0,
			esp: 0,
			ebp: 0,
			esi: 0,
			edi: 0,
			es: 0,
			reserved4: 0,
			cs: 0,
			reserved5: 0,
			ss: 0,
			reserved6: 0,
			ds: 0,
			reserved7: 0,
			fs: 0,
			reserved8: 0,
			gs: 0,
			reserved9: 0,
			ldtr: 0,
			reserved10: 0,
			iobp_offset: size_of::<Tss>() as u16
		}
	}
}

#[inline(always)]
pub fn get_cr0() -> Cr0Flags {
	unsafe {
		let mut r: u32;
		asm!("mov $0, cr0" : "=r"(r) ::: "intel");
		Cr0Flags::from_bits_truncate(r)
	}
}

#[inline(always)]
pub fn get_cr2() -> u32 {
	unsafe {
		let mut r: u32;
		asm!("mov $0, cr2" : "=r"(r) ::: "intel");
		r
	}
}

#[inline(always)]
pub fn get_cr3() -> u32 {
	unsafe {
		let mut r: u32;
		asm!("mov $0, cr3" : "=r"(r) ::: "intel");
		r
	}
}

#[inline(always)]
pub fn get_cr4() -> Cr4Flags {
	unsafe {
		let mut r: u32;
		asm!("mov $0, cr4" : "=r"(r) ::: "intel");
		Cr4Flags::from_bits_truncate(r)
	}
}

#[inline(always)]
pub fn get_flags() -> EFlags {
	unsafe {
		let mut r: u32;
		asm!("pushfd; pop $0" : "=r"(r) ::: "intel");
		EFlags::from_bits_truncate(r)
	}
}

#[inline(always)]
pub unsafe fn set_cr0(flags: Cr0Flags) {
	asm!("mov cr0, $0" :: "r"(flags.bits()) :: "volatile", "intel");
}

#[inline(always)]
pub unsafe fn set_cr3(val: u32) {
	asm!("mov cr3, $0" :: "r"(val) :: "volatile", "intel");
}

#[inline(always)]
pub unsafe fn set_cr4(flags: Cr4Flags) {
	asm!("mov cr4, $0" :: "r"(flags.bits()) :: "volatile", "intel");
}

#[inline(always)]
pub unsafe fn set_gdt(gdt: &[GdtEntry]) {
	#[repr(C, packed)]
	struct GDTR {
		limit: u16,
		ptr: *const GdtEntry,
	}
	asm!("lgdt $0" :: "*m"(&GDTR { ptr: gdt.as_ptr(), limit: (gdt.len()*8 - 1) as u16 }) :: "volatile", "intel");
}

#[inline(always)]
pub unsafe fn set_idt(idt: &[IdtEntry]) {
	#[repr(C, packed)]
	struct IDTR {
		limit: u16,
		ptr: *const IdtEntry,
	}
	asm!("lidt $0" :: "*m"(&IDTR { ptr: idt.as_ptr(), limit: idt.len() as u16 * 8 }) :: "volatile", "intel");
}

#[inline(always)]
pub unsafe fn set_flags(val: EFlags) {
	asm!("push $0; popfd" :: "r"(val.bits()) : "flags" : "volatile", "intel");
}

#[inline(always)]
pub unsafe fn stack_jmp(stack: *mut (), ip: *const ()) -> ! {
	asm!("mov esp, $0; jmp $1" :: "rg"(stack), "r"(ip) :: "volatile", "intel");
	loop { }
}
<commit_msg>I swear to god if LLVM keeps pulling this...<commit_after>#![allow(non_upper_case_globals)]

pub use self::x86_shared::*;

use core::prelude::*;
use core::mem::size_of;

mod x86_shared;

bitflags! {
	flags EFlags: u32 {
		const CarryFlag = 1 << 0,
		const ParityFlag = 1 << 2,
		const AdjustFlag = 1 << 4,
		const ZeroFlag = 1 << 6,
		const SignFlag = 1 << 7,
		const TrapFlag = 1 << 8,
		const InterruptFlag = 1 << 9,
		const DirectionFlag = 1 << 10,
		const OverflowFlag = 1 << 11,
		const Iopl1 = 1 << 12,
		const Iopl2 = 1 << 13,
		const NestedTaskFlag = 1 << 14,
		const ResumeFlag = 1 << 16,
		const Virtual8086Flag = 1 << 17,
		const AlignmentFlag = 1 << 18,
		const VirtualInterruptFlag = 1 << 19,
		const VirtualInterruptPending = 1 << 20,
		const CpuIdFlag = 1 << 21
	}
}

bitflags! {
	flags Cr0Flags: u32 {
		const ProtectedMode = 1 << 0,
		const MonitorCoprocessor = 1 << 1,
		const EmulateCoprocessor = 1 << 2,
		const TaskSwitched = 1 << 3,
		const ExtensionType = 1 << 4,
		const NumericError = 1 << 5,
		const WriteProtect = 1 << 16,
		const AlignmentMask = 1 << 18,
		const NotWriteThrough = 1 << 29,
		const CacheDisable = 1 << 30,
		const EnablePaging = 1 << 31
	}
}

bitflags! {
	flags Cr4Flags: u32 {
		const EnableVme = 1 << 0,
		const VirtualInterrupts = 1 << 1,
		const TimeStampDisable = 1 << 2,
		const DebuggingExtensions = 1 << 3,
		const EnablePse = 1 << 4,
		const EnablePae = 1 << 5,
		const EnableMachineCheck = 1 << 6,
		const EnableGlobalPages = 1 << 7,
		const EnablePpmc = 1 << 8,
		const EnableSse = 1 << 9,
		const UnmaskedSse = 1 << 10,
		const EnableVmx = 1 << 13,
		const EnableSmx = 1 << 14,
		const EnablePcid = 1 << 17,
		const EnableOsXSave = 1 << 18,
		const EnableSmep = 1 << 20,
		const EnableSmap = 1 << 21
	}
}

bitflags! {
	flags GdtAccess: u8 {
		const Accessed = 1 << 0,
		const Writable = 1 << 1,
		const Direction = 1 << 2,
		const Executable = 1 << 3,
		const NotTss = 1 << 4,
	}
}

#[derive(Copy, Clone, Debug)]
#[repr(C, packed)]
pub struct GdtEntry {
	limit: u16,
	base1: u16,
	base2: u8,
	access: u8,
	flags: u8,
	base3: u8,
}

#[derive(Copy, Clone)]
#[repr(C, packed)]
pub struct IdtEntry {
	offset1: u16,
	selector: u16,
	reserved: u8,
	flags: u8,
	offset2: u16
}

impl GdtEntry {
	pub fn null() -> GdtEntry {
		GdtEntry {
			base1: 0,
			base2: 0,
			base3: 0,
			access: 0,
			limit: 0,
			flags: 0
		}
	}

	pub fn new(base: *const (), limit: usize, access: GdtAccess, dpl: PrivilegeLevel) -> GdtEntry {
		let (limit, flags) = if limit < 0x100000 {
			((limit & 0xFFFF) as u16, ((limit & 0xF0000) >> 16) as u8 | 0x40u8)
		} else {
			if ((limit - 0xFFF) & 0xFFF) > 0 {
				panic!("bad segment limit for GDT entry");
			}
			(((limit & 0xFFFF000) >> 12) as u16, ((limit & 0xF0000000) >> 28) as u8 | 0xC0u8)
		};
		GdtEntry {
			base1: base as u16,
			base2: ((base as usize & 0xFF0000) >> 16) as u8,
			base3: ((base as usize & 0xFF000000) >> 24) as u8,
			access: access.bits() | ((dpl as u8) << 5) | 0x80,
			limit: limit,
			flags: flags
		}
	}
}

pub const NULL_IDT_ENTRY: IdtEntry = IdtEntry { offset1: 0, selector: 0, reserved: 0, flags: 0, offset2: 0 };

impl IdtEntry {
	pub fn new(f: unsafe extern "C" fn(), dpl: PrivilegeLevel, block: bool) -> IdtEntry {
		IdtEntry {
			offset1: f as u16,
			offset2: ((f as usize & 0xFFFF0000) >> 16) as u16,
			selector: 8,
			reserved: 0,
			flags: if block { 0x8E } else { 0x8F } | ((dpl as u8) << 5)
		}
	}
}

#[derive(Copy, Clone, Debug)]
#[repr(C, packed)]
pub struct Tss {
	pub link: u16,
	reserved0: u16,
	pub esp0: u32,
	pub ss0: u16,
	reserved1: u16,
	pub esp1: u32,
	pub ss1: u16,
	reserved2: u16,
	pub esp2: u32,
	pub ss2: u16,
	reserved3: u16,

	pub cr3: u32,
	pub eip: u32,
	pub eflags: u32,

	pub eax: u32,
	pub ecx: u32,
	pub edx: u32,
	pub ebx: u32,
	pub esp: u32,
	pub ebp: u32,
	pub esi: u32,
	pub edi: u32,

	pub es: u16,
	reserved4: u16,
	pub cs: u16,
	reserved5: u16,
	pub ss: u16,
	reserved6: u16,
	pub ds: u16,
	reserved7: u16,
	pub fs: u16,
	reserved8: u16,
	pub gs: u16,
	reserved9: u16,
	pub ldtr: u16,
	reserved10: u32,
	pub iobp_offset: u16
}

impl Tss {
	pub fn new() -> Tss {
		Tss {
			link: 0,
			reserved0: 0,
			esp0: 0,
			ss0: 0,
			reserved1: 0,
			esp1: 0,
			ss1: 0,
			reserved2: 0,
			esp2: 0,
			ss2: 0,
			reserved3: 0,
			cr3: 0,
			eip: 0,
			eflags: 0,
			eax: 0,
			ecx: 0,
			edx: 0,
			ebx: 0,
			esp: 0,
			ebp: 0,
			esi: 0,
			edi: 0,
			es: 0,
			reserved4: 0,
			cs: 0,
			reserved5: 0,
			ss: 0,
			reserved6: 0,
			ds: 0,
			reserved7: 0,
			fs: 0,
			reserved8: 0,
			gs: 0,
			reserved9: 0,
			ldtr: 0,
			reserved10: 0,
			iobp_offset: size_of::<Tss>() as u16
		}
	}
}

#[inline(always)]
pub fn get_cr0() -> Cr0Flags {
	unsafe {
		let mut r: u32;
		asm!("mov $0, cr0" : "=r"(r) ::: "intel");
		Cr0Flags::from_bits_truncate(r)
	}
}

#[inline(always)]
pub fn get_cr2() -> u32 {
	unsafe {
		let mut r: u32;
		asm!("mov $0, cr2" : "=r"(r) ::: "intel");
		r
	}
}

#[inline(always)]
pub fn get_cr3() -> u32 {
	unsafe {
		let mut r: u32;
		asm!("mov $0, cr3" : "=r"(r) ::: "intel");
		r
	}
}

#[inline(always)]
pub fn get_cr4() -> Cr4Flags {
	unsafe {
		let mut r: u32;
		asm!("mov $0, cr4" : "=r"(r) ::: "intel");
		Cr4Flags::from_bits_truncate(r)
	}
}

#[inline(always)]
pub fn get_flags() -> EFlags {
	unsafe {
		let mut r: u32;
		asm!("pushfd; pop $0" : "=r"(r) ::: "intel");
		EFlags::from_bits_truncate(r)
	}
}

#[inline(always)]
pub unsafe fn set_cr0(flags: Cr0Flags) {
	asm!("mov cr0, $0" :: "r"(flags.bits()) :: "volatile", "intel");
}

#[inline(always)]
pub unsafe fn set_cr3(val: u32) {
	asm!("mov cr3, $0" :: "r"(val) :: "volatile", "intel");
}

#[inline(always)]
pub unsafe fn set_cr4(flags: Cr4Flags) {
	asm!("mov cr4, $0" :: "r"(flags.bits()) :: "volatile", "intel");
}

#[inline(always)]
pub unsafe fn set_gdt(gdt: &[GdtEntry]) {
	#[repr(C, packed)]
	struct GDTR {
		limit: u16,
		ptr: *const GdtEntry,
	}
	asm!("lgdtl $0" :: "*m"(&GDTR { ptr: gdt.as_ptr(), limit: (gdt.len()*size_of::<GdtEntry>() - 1) as u16 }) :: "volatile");
}

#[inline(always)]
pub unsafe fn set_idt(idt: &[IdtEntry]) {
	#[repr(C, packed)]
	struct IDTR {
		limit: u16,
		ptr: *const IdtEntry,
	}
	asm!("lidtl $0" :: "*m"(&IDTR { ptr: idt.as_ptr(), limit: idt.len() as u16 * 8 }) :: "volatile");
}

#[inline(always)]
pub unsafe fn set_flags(val: EFlags) {
	asm!("push $0; popfd" :: "r"(val.bits()) : "flags" : "volatile", "intel");
}

#[inline(always)]
pub unsafe fn stack_jmp(stack: *mut (), ip: *const ()) -> ! {
	asm!("mov esp, $0; jmp $1" :: "rg"(stack), "r"(ip) :: "volatile", "intel");
	loop { }
}
<|endoftext|>


<commit_before>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use enums::SurfaceType;
use ffi;
#[cfg(feature = "use_glib")]
use glib::translate::*;
use std::fmt;

use enums::Status;
use surface::Surface;

#[derive(Debug)]
pub struct XCBDrawable(pub u32);

impl XCBDrawable {
    fn to_raw_none(&self) -> u32 {
        self.0
    }
}

impl fmt::Display for XCBDrawable {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "XCBDrawable")
    }
}

#[derive(Debug)]
pub struct XCBPixmap(pub u32);

impl XCBPixmap {
    fn to_raw_none(&self) -> u32 {
        self.0
    }
}

impl fmt::Display for XCBPixmap {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "XCBPixmap")
    }
}

#[derive(Debug)]
pub struct XCBConnection(pub *mut ffi::xcb_connection_t);

impl XCBConnection {
    pub fn to_raw_none(&self) -> *mut ffi::xcb_connection_t {
        self.0
    }

    pub unsafe fn from_raw_none(ptr: *mut ffi::xcb_connection_t) -> XCBConnection {
        assert!(!ptr.is_null());
        XCBConnection(ptr)
    }

    pub unsafe fn from_raw_borrow(ptr: *mut ffi::xcb_connection_t) -> XCBConnection {
        assert!(!ptr.is_null());
        XCBConnection(ptr)
    }

    pub unsafe fn from_raw_full(ptr: *mut ffi::xcb_connection_t) -> XCBConnection {
        assert!(!ptr.is_null());
        XCBConnection(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl<'a> ToGlibPtr<'a, *mut ffi::xcb_connection_t> for &'a XCBConnection {
    type Storage = &'a XCBConnection;

    #[inline]
    fn to_glib_none(&self) -> Stash<'a, *mut ffi::xcb_connection_t, &'a XCBConnection> {
        Stash(self.to_raw_none(), *self)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrNone<*mut ffi::xcb_connection_t> for XCBConnection {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut ffi::xcb_connection_t) -> XCBConnection {
        Self::from_raw_none(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrBorrow<*mut ffi::xcb_connection_t> for XCBConnection {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut ffi::xcb_connection_t) -> XCBConnection {
        Self::from_raw_borrow(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrFull<*mut ffi::xcb_connection_t> for XCBConnection {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut ffi::xcb_connection_t) -> XCBConnection {
        Self::from_raw_full(ptr)
    }
}

impl Clone for XCBConnection {
    fn clone(&self) -> XCBConnection {
        unsafe { Self::from_raw_none(self.to_raw_none()) }
    }
}

impl fmt::Display for XCBConnection {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "XCBConnection")
    }
}

#[derive(Debug)]
pub struct XCBRenderPictFormInfo(pub *mut ffi::xcb_render_pictforminfo_t);

impl XCBRenderPictFormInfo {
    pub fn to_raw_none(&self) -> *mut ffi::xcb_render_pictforminfo_t {
        self.0
    }

    pub unsafe fn from_raw_none(ptr: *mut ffi::xcb_render_pictforminfo_t) -> XCBRenderPictFormInfo {
        assert!(!ptr.is_null());
        XCBRenderPictFormInfo(ptr)
    }

    pub unsafe fn from_raw_borrow(
        ptr: *mut ffi::xcb_render_pictforminfo_t,
    ) -> XCBRenderPictFormInfo {
        assert!(!ptr.is_null());
        XCBRenderPictFormInfo(ptr)
    }

    pub unsafe fn from_raw_full(ptr: *mut ffi::xcb_render_pictforminfo_t) -> XCBRenderPictFormInfo {
        assert!(!ptr.is_null());
        XCBRenderPictFormInfo(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl<'a> ToGlibPtr<'a, *mut ffi::xcb_render_pictforminfo_t> for &'a XCBRenderPictFormInfo {
    type Storage = &'a XCBRenderPictFormInfo;

    #[inline]
    fn to_glib_none(
        &self,
    ) -> Stash<'a, *mut ffi::xcb_render_pictforminfo_t, &'a XCBRenderPictFormInfo> {
        Stash(self.to_raw_none(), *self)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrNone<*mut ffi::xcb_render_pictforminfo_t> for XCBRenderPictFormInfo {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut ffi::xcb_render_pictforminfo_t) -> XCBRenderPictFormInfo {
        Self::from_raw_none(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrBorrow<*mut ffi::xcb_render_pictforminfo_t> for XCBRenderPictFormInfo {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut ffi::xcb_render_pictforminfo_t) -> XCBRenderPictFormInfo {
        Self::from_raw_borrow(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrFull<*mut ffi::xcb_render_pictforminfo_t> for XCBRenderPictFormInfo {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut ffi::xcb_render_pictforminfo_t) -> XCBRenderPictFormInfo {
        Self::from_raw_full(ptr)
    }
}

impl Clone for XCBRenderPictFormInfo {
    fn clone(&self) -> XCBRenderPictFormInfo {
        unsafe { Self::from_raw_none(self.to_raw_none()) }
    }
}

impl fmt::Display for XCBRenderPictFormInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "XCBRenderPictFormInfo")
    }
}

#[derive(Debug)]
pub struct XCBScreen(pub *mut ffi::xcb_screen_t);

impl XCBScreen {
    pub fn to_raw_none(&self) -> *mut ffi::xcb_screen_t {
        self.0
    }

    pub unsafe fn from_raw_none(ptr: *mut ffi::xcb_screen_t) -> XCBScreen {
        assert!(!ptr.is_null());
        XCBScreen(ptr)
    }

    pub unsafe fn from_raw_borrow(ptr: *mut ffi::xcb_screen_t) -> XCBScreen {
        assert!(!ptr.is_null());
        XCBScreen(ptr)
    }

    pub unsafe fn from_raw_full(ptr: *mut ffi::xcb_screen_t) -> XCBScreen {
        assert!(!ptr.is_null());
        XCBScreen(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl<'a> ToGlibPtr<'a, *mut ffi::xcb_screen_t> for &'a XCBScreen {
    type Storage = &'a XCBScreen;

    #[inline]
    fn to_glib_none(&self) -> Stash<'a, *mut ffi::xcb_screen_t, &'a XCBScreen> {
        Stash(self.to_raw_none(), *self)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrNone<*mut ffi::xcb_screen_t> for XCBScreen {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut ffi::xcb_screen_t) -> XCBScreen {
        Self::from_raw_none(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrBorrow<*mut ffi::xcb_screen_t> for XCBScreen {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut ffi::xcb_screen_t) -> XCBScreen {
        Self::from_raw_borrow(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrFull<*mut ffi::xcb_screen_t> for XCBScreen {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut ffi::xcb_screen_t) -> XCBScreen {
        Self::from_raw_full(ptr)
    }
}

impl Clone for XCBScreen {
    fn clone(&self) -> XCBScreen {
        unsafe { Self::from_raw_none(self.to_raw_none()) }
    }
}

impl fmt::Display for XCBScreen {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "XCBScreen")
    }
}

pub struct XCBSurface(Surface);

impl std::ops::Deref for XCBSurface {
    type Target = Surface;

    fn deref(&self) -> &Surface {
        &self.0
    }
}

impl std::convert::TryFrom<Surface> for XCBSurface {
    type Error = Surface;

    fn try_from(surface: Surface) -> Result<Self, Surface> {
        if surface.get_type() == SurfaceType::Xcb {
            Ok(Self(surface))
        } else {
            Err(surface)
        }
    }
}

impl XCBSurface {
    pub fn create(
        connection: &XCBConnection,
        drawable: &XCBDrawable,
        visual: &XCBVisualType,
        width: i32,
        height: i32,
    ) -> Result<Self, Status> {
        unsafe {
            Ok(Self(Surface::from_raw_full(
                ffi::cairo_xcb_surface_create(
                    connection.to_raw_none(),
                    drawable.to_raw_none(),
                    visual.to_raw_none(),
                    width,
                    height,
                ),
            )?))
        }
    }

    pub fn create_for_bitmap(
        connection: &XCBConnection,
        screen: &XCBScreen,
        bitmap: &XCBPixmap,
        width: i32,
        height: i32,
    ) -> Result<Self, Status> {
        unsafe {
            Ok(Self(Surface::from_raw_full(
                ffi::cairo_xcb_surface_create_for_bitmap(
                    connection.to_raw_none(),
                    screen.to_raw_none(),
                    bitmap.to_raw_none(),
                    width,
                    height,
                ),
            )?))
        }
    }

    pub fn create_with_xrender_format(
        connection: &XCBConnection,
        screen: &XCBScreen,
        bitmap: &XCBPixmap,
        format: &XCBRenderPictFormInfo,
        width: i32,
        height: i32,
    ) -> Result<Self, Status> {
        unsafe {
            Ok(Self(Surface::from_raw_full(
                ffi::cairo_xcb_surface_create_with_xrender_format(
                    connection.to_raw_none(),
                    screen.to_raw_none(),
                    bitmap.to_raw_none(),
                    format.to_raw_none(),
                    width,
                    height,
                ),
            )?))
        }
    }

    pub fn set_size(&self, width: i32, height: i32) {
        unsafe { ffi::cairo_xcb_surface_set_size(self.to_raw_none(), width, height) }
    }

    pub fn set_drawable(&self, drawable: &XCBDrawable, width: i32, height: i32) {
        unsafe {
            ffi::cairo_xcb_surface_set_drawable(
                self.to_raw_none(),
                drawable.to_raw_none(),
                width,
                height,
            )
        }
    }
}

#[derive(Debug)]
pub struct XCBVisualType(pub *mut ffi::xcb_visualtype_t);

impl XCBVisualType {
    pub fn to_raw_none(&self) -> *mut ffi::xcb_visualtype_t {
        self.0
    }

    pub unsafe fn from_raw_none(ptr: *mut ffi::xcb_visualtype_t) -> XCBVisualType {
        assert!(!ptr.is_null());
        XCBVisualType(ptr)
    }

    pub unsafe fn from_raw_borrow(ptr: *mut ffi::xcb_visualtype_t) -> XCBVisualType {
        assert!(!ptr.is_null());
        XCBVisualType(ptr)
    }

    pub unsafe fn from_raw_full(ptr: *mut ffi::xcb_visualtype_t) -> XCBVisualType {
        assert!(!ptr.is_null());
        XCBVisualType(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl<'a> ToGlibPtr<'a, *mut ffi::xcb_visualtype_t> for &'a XCBVisualType {
    type Storage = &'a XCBVisualType;

    #[inline]
    fn to_glib_none(&self) -> Stash<'a, *mut ffi::xcb_visualtype_t, &'a XCBVisualType> {
        Stash(self.to_raw_none(), *self)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrNone<*mut ffi::xcb_visualtype_t> for XCBVisualType {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut ffi::xcb_visualtype_t) -> XCBVisualType {
        Self::from_raw_none(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrBorrow<*mut ffi::xcb_visualtype_t> for XCBVisualType {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut ffi::xcb_visualtype_t) -> XCBVisualType {
        Self::from_raw_borrow(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrFull<*mut ffi::xcb_visualtype_t> for XCBVisualType {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut ffi::xcb_visualtype_t) -> XCBVisualType {
        Self::from_raw_full(ptr)
    }
}

impl Clone for XCBVisualType {
    fn clone(&self) -> XCBVisualType {
        unsafe { Self::from_raw_none(self.to_raw_none()) }
    }
}

impl fmt::Display for XCBVisualType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "XCBVisualType")
    }
}

impl ::device::Device {
    pub fn get_connection(&self) -> XCBConnection {
        unsafe {
            XCBConnection::from_raw_full(ffi::cairo_xcb_device_get_connection(self.to_raw_none()))
        }
    }

    pub fn debug_cap_xshm_version(&self, major_version: i32, minor_version: i32) {
        unsafe {
            ffi::cairo_xcb_device_debug_cap_xshm_version(
                self.to_raw_none(),
                major_version,
                minor_version,
            )
        }
    }
}
<commit_msg>xcb: return Result from the functions that take a size<commit_after>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use enums::SurfaceType;
use ffi;
#[cfg(feature = "use_glib")]
use glib::translate::*;
use std::fmt;

use enums::Status;
use surface::Surface;

#[derive(Debug)]
pub struct XCBDrawable(pub u32);

impl XCBDrawable {
    fn to_raw_none(&self) -> u32 {
        self.0
    }
}

impl fmt::Display for XCBDrawable {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "XCBDrawable")
    }
}

#[derive(Debug)]
pub struct XCBPixmap(pub u32);

impl XCBPixmap {
    fn to_raw_none(&self) -> u32 {
        self.0
    }
}

impl fmt::Display for XCBPixmap {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "XCBPixmap")
    }
}

#[derive(Debug)]
pub struct XCBConnection(pub *mut ffi::xcb_connection_t);

impl XCBConnection {
    pub fn to_raw_none(&self) -> *mut ffi::xcb_connection_t {
        self.0
    }

    pub unsafe fn from_raw_none(ptr: *mut ffi::xcb_connection_t) -> XCBConnection {
        assert!(!ptr.is_null());
        XCBConnection(ptr)
    }

    pub unsafe fn from_raw_borrow(ptr: *mut ffi::xcb_connection_t) -> XCBConnection {
        assert!(!ptr.is_null());
        XCBConnection(ptr)
    }

    pub unsafe fn from_raw_full(ptr: *mut ffi::xcb_connection_t) -> XCBConnection {
        assert!(!ptr.is_null());
        XCBConnection(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl<'a> ToGlibPtr<'a, *mut ffi::xcb_connection_t> for &'a XCBConnection {
    type Storage = &'a XCBConnection;

    #[inline]
    fn to_glib_none(&self) -> Stash<'a, *mut ffi::xcb_connection_t, &'a XCBConnection> {
        Stash(self.to_raw_none(), *self)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrNone<*mut ffi::xcb_connection_t> for XCBConnection {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut ffi::xcb_connection_t) -> XCBConnection {
        Self::from_raw_none(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrBorrow<*mut ffi::xcb_connection_t> for XCBConnection {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut ffi::xcb_connection_t) -> XCBConnection {
        Self::from_raw_borrow(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrFull<*mut ffi::xcb_connection_t> for XCBConnection {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut ffi::xcb_connection_t) -> XCBConnection {
        Self::from_raw_full(ptr)
    }
}

impl Clone for XCBConnection {
    fn clone(&self) -> XCBConnection {
        unsafe { Self::from_raw_none(self.to_raw_none()) }
    }
}

impl fmt::Display for XCBConnection {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "XCBConnection")
    }
}

#[derive(Debug)]
pub struct XCBRenderPictFormInfo(pub *mut ffi::xcb_render_pictforminfo_t);

impl XCBRenderPictFormInfo {
    pub fn to_raw_none(&self) -> *mut ffi::xcb_render_pictforminfo_t {
        self.0
    }

    pub unsafe fn from_raw_none(ptr: *mut ffi::xcb_render_pictforminfo_t) -> XCBRenderPictFormInfo {
        assert!(!ptr.is_null());
        XCBRenderPictFormInfo(ptr)
    }

    pub unsafe fn from_raw_borrow(
        ptr: *mut ffi::xcb_render_pictforminfo_t,
    ) -> XCBRenderPictFormInfo {
        assert!(!ptr.is_null());
        XCBRenderPictFormInfo(ptr)
    }

    pub unsafe fn from_raw_full(ptr: *mut ffi::xcb_render_pictforminfo_t) -> XCBRenderPictFormInfo {
        assert!(!ptr.is_null());
        XCBRenderPictFormInfo(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl<'a> ToGlibPtr<'a, *mut ffi::xcb_render_pictforminfo_t> for &'a XCBRenderPictFormInfo {
    type Storage = &'a XCBRenderPictFormInfo;

    #[inline]
    fn to_glib_none(
        &self,
    ) -> Stash<'a, *mut ffi::xcb_render_pictforminfo_t, &'a XCBRenderPictFormInfo> {
        Stash(self.to_raw_none(), *self)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrNone<*mut ffi::xcb_render_pictforminfo_t> for XCBRenderPictFormInfo {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut ffi::xcb_render_pictforminfo_t) -> XCBRenderPictFormInfo {
        Self::from_raw_none(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrBorrow<*mut ffi::xcb_render_pictforminfo_t> for XCBRenderPictFormInfo {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut ffi::xcb_render_pictforminfo_t) -> XCBRenderPictFormInfo {
        Self::from_raw_borrow(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrFull<*mut ffi::xcb_render_pictforminfo_t> for XCBRenderPictFormInfo {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut ffi::xcb_render_pictforminfo_t) -> XCBRenderPictFormInfo {
        Self::from_raw_full(ptr)
    }
}

impl Clone for XCBRenderPictFormInfo {
    fn clone(&self) -> XCBRenderPictFormInfo {
        unsafe { Self::from_raw_none(self.to_raw_none()) }
    }
}

impl fmt::Display for XCBRenderPictFormInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "XCBRenderPictFormInfo")
    }
}

#[derive(Debug)]
pub struct XCBScreen(pub *mut ffi::xcb_screen_t);

impl XCBScreen {
    pub fn to_raw_none(&self) -> *mut ffi::xcb_screen_t {
        self.0
    }

    pub unsafe fn from_raw_none(ptr: *mut ffi::xcb_screen_t) -> XCBScreen {
        assert!(!ptr.is_null());
        XCBScreen(ptr)
    }

    pub unsafe fn from_raw_borrow(ptr: *mut ffi::xcb_screen_t) -> XCBScreen {
        assert!(!ptr.is_null());
        XCBScreen(ptr)
    }

    pub unsafe fn from_raw_full(ptr: *mut ffi::xcb_screen_t) -> XCBScreen {
        assert!(!ptr.is_null());
        XCBScreen(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl<'a> ToGlibPtr<'a, *mut ffi::xcb_screen_t> for &'a XCBScreen {
    type Storage = &'a XCBScreen;

    #[inline]
    fn to_glib_none(&self) -> Stash<'a, *mut ffi::xcb_screen_t, &'a XCBScreen> {
        Stash(self.to_raw_none(), *self)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrNone<*mut ffi::xcb_screen_t> for XCBScreen {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut ffi::xcb_screen_t) -> XCBScreen {
        Self::from_raw_none(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrBorrow<*mut ffi::xcb_screen_t> for XCBScreen {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut ffi::xcb_screen_t) -> XCBScreen {
        Self::from_raw_borrow(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrFull<*mut ffi::xcb_screen_t> for XCBScreen {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut ffi::xcb_screen_t) -> XCBScreen {
        Self::from_raw_full(ptr)
    }
}

impl Clone for XCBScreen {
    fn clone(&self) -> XCBScreen {
        unsafe { Self::from_raw_none(self.to_raw_none()) }
    }
}

impl fmt::Display for XCBScreen {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "XCBScreen")
    }
}

pub struct XCBSurface(Surface);

impl std::ops::Deref for XCBSurface {
    type Target = Surface;

    fn deref(&self) -> &Surface {
        &self.0
    }
}

impl std::convert::TryFrom<Surface> for XCBSurface {
    type Error = Surface;

    fn try_from(surface: Surface) -> Result<Self, Surface> {
        if surface.get_type() == SurfaceType::Xcb {
            Ok(Self(surface))
        } else {
            Err(surface)
        }
    }
}

impl XCBSurface {
    pub fn create(
        connection: &XCBConnection,
        drawable: &XCBDrawable,
        visual: &XCBVisualType,
        width: i32,
        height: i32,
    ) -> Result<Self, Status> {
        unsafe {
            Ok(Self(Surface::from_raw_full(
                ffi::cairo_xcb_surface_create(
                    connection.to_raw_none(),
                    drawable.to_raw_none(),
                    visual.to_raw_none(),
                    width,
                    height,
                ),
            )?))
        }
    }

    pub fn create_for_bitmap(
        connection: &XCBConnection,
        screen: &XCBScreen,
        bitmap: &XCBPixmap,
        width: i32,
        height: i32,
    ) -> Result<Self, Status> {
        unsafe {
            Ok(Self(Surface::from_raw_full(
                ffi::cairo_xcb_surface_create_for_bitmap(
                    connection.to_raw_none(),
                    screen.to_raw_none(),
                    bitmap.to_raw_none(),
                    width,
                    height,
                ),
            )?))
        }
    }

    pub fn create_with_xrender_format(
        connection: &XCBConnection,
        screen: &XCBScreen,
        bitmap: &XCBPixmap,
        format: &XCBRenderPictFormInfo,
        width: i32,
        height: i32,
    ) -> Result<Self, Status> {
        unsafe {
            Ok(Self(Surface::from_raw_full(
                ffi::cairo_xcb_surface_create_with_xrender_format(
                    connection.to_raw_none(),
                    screen.to_raw_none(),
                    bitmap.to_raw_none(),
                    format.to_raw_none(),
                    width,
                    height,
                ),
            )?))
        }
    }

    pub fn set_size(&self, width: i32, height: i32) -> Result<(), Status> {
        unsafe { ffi::cairo_xcb_surface_set_size(self.to_raw_none(), width, height) }
        match self.status() {
            Status::Success => Ok(()),
            s => Err(s),
        }
    }

    pub fn set_drawable(
        &self,
        drawable: &XCBDrawable,
        width: i32,
        height: i32,
    ) -> Result<(), Status> {
        unsafe {
            ffi::cairo_xcb_surface_set_drawable(
                self.to_raw_none(),
                drawable.to_raw_none(),
                width,
                height,
            )
        }
        match self.status() {
            Status::Success => Ok(()),
            s => Err(s),
        }
    }
}

#[derive(Debug)]
pub struct XCBVisualType(pub *mut ffi::xcb_visualtype_t);

impl XCBVisualType {
    pub fn to_raw_none(&self) -> *mut ffi::xcb_visualtype_t {
        self.0
    }

    pub unsafe fn from_raw_none(ptr: *mut ffi::xcb_visualtype_t) -> XCBVisualType {
        assert!(!ptr.is_null());
        XCBVisualType(ptr)
    }

    pub unsafe fn from_raw_borrow(ptr: *mut ffi::xcb_visualtype_t) -> XCBVisualType {
        assert!(!ptr.is_null());
        XCBVisualType(ptr)
    }

    pub unsafe fn from_raw_full(ptr: *mut ffi::xcb_visualtype_t) -> XCBVisualType {
        assert!(!ptr.is_null());
        XCBVisualType(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl<'a> ToGlibPtr<'a, *mut ffi::xcb_visualtype_t> for &'a XCBVisualType {
    type Storage = &'a XCBVisualType;

    #[inline]
    fn to_glib_none(&self) -> Stash<'a, *mut ffi::xcb_visualtype_t, &'a XCBVisualType> {
        Stash(self.to_raw_none(), *self)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrNone<*mut ffi::xcb_visualtype_t> for XCBVisualType {
    #[inline]
    unsafe fn from_glib_none(ptr: *mut ffi::xcb_visualtype_t) -> XCBVisualType {
        Self::from_raw_none(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrBorrow<*mut ffi::xcb_visualtype_t> for XCBVisualType {
    #[inline]
    unsafe fn from_glib_borrow(ptr: *mut ffi::xcb_visualtype_t) -> XCBVisualType {
        Self::from_raw_borrow(ptr)
    }
}

#[cfg(feature = "use_glib")]
impl FromGlibPtrFull<*mut ffi::xcb_visualtype_t> for XCBVisualType {
    #[inline]
    unsafe fn from_glib_full(ptr: *mut ffi::xcb_visualtype_t) -> XCBVisualType {
        Self::from_raw_full(ptr)
    }
}

impl Clone for XCBVisualType {
    fn clone(&self) -> XCBVisualType {
        unsafe { Self::from_raw_none(self.to_raw_none()) }
    }
}

impl fmt::Display for XCBVisualType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "XCBVisualType")
    }
}

impl ::device::Device {
    pub fn get_connection(&self) -> XCBConnection {
        unsafe {
            XCBConnection::from_raw_full(ffi::cairo_xcb_device_get_connection(self.to_raw_none()))
        }
    }

    pub fn debug_cap_xshm_version(&self, major_version: i32, minor_version: i32) {
        unsafe {
            ffi::cairo_xcb_device_debug_cap_xshm_version(
                self.to_raw_none(),
                major_version,
                minor_version,
            )
        }
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::fmt;
use std::error;
use std::vec::Vec;
use byteorder;
use byteorder::{BigEndian,ReadBytesExt,WriteBytesExt};

#[derive(Debug)]
pub enum Error {
	Io(byteorder::Error),
	InvalidValue,
	InvalidType
}

impl From<byteorder::Error> for Error {
	fn from(err: byteorder::Error) -> Error { Error::Io(err) }
}

impl From<Error> for byteorder::Error {
	fn from(err: Error) -> byteorder::Error {
		match err {
			Error::Io(err) => err,
			Error::InvalidValue => byteorder::Error::Io(io::Error::new(io::ErrorKind::Other, "Invalid value")),
			Error::InvalidType => byteorder::Error::Io(io::Error::new(io::ErrorKind::Other, "Invalid type")),
		}
	}
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
	        match *self {
				Error::InvalidValue => write!(f, "Invalid value."),
				Error::InvalidType => write!(f, "Invalid type."),
				Error::Io(ref err) => err.fmt(f),
			}
	}
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::InvalidValue => "Invalid value.",
            Error::InvalidType => "Invalid type.",
            Error::Io(ref err) => error::Error::description(err),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::InvalidValue => None,
            Error::InvalidType => None,
            Error::Io(ref err) => err.cause(),
        }
    }
}

pub struct XdrReader {
	reader : io::Cursor<Vec<u8>>
}

pub struct XdrWriter {
	writer : io::Cursor<Vec<u8>>
}

impl XdrWriter {
	pub fn new() -> XdrWriter {
		let v : Vec<u8>= Vec::new();
		XdrWriter{ writer: io::Cursor::new(v)}
	}

	pub fn get_buffer(self) -> Vec<u8> {
		self.writer.into_inner()
	}

	pub fn pack<T:XdrPrimitive>(&mut self, x:T) {
		XdrPrimitive::write_to_xdr(self, x)
	}

}
pub trait XdrPrimitive {
	fn read_from_xdr(x: &mut XdrReader) -> Result<Self, Error>;
	fn write_to_xdr(x: &mut XdrWriter, v: Self);
}

impl XdrPrimitive for u32 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u32, Error>{
		match x.reader.read_u32::<BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(v)
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u32::<BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for u16 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u16, Error>{
		match x.reader.read_u32::<BigEndian>() {
			Ok(v) => Ok(v as u16),
			Err(v) => Err(v)
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u32::<BigEndian>(v as u32).unwrap();
	}
}
impl XdrPrimitive for u8 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u8, Error>{
		match x.reader.read_u32::<BigEndian>() {
			Ok(v) => Ok(v as u8),
			Err(v) => Err(v)
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u32::<BigEndian>(v as u32).unwrap();
	}
}
impl XdrPrimitive for i8 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i8, Error>{
		match x.reader.read_i32::<BigEndian>() {
			Ok(v) => Ok(v as i8),
			Err(v) => Err(v)
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i32::<BigEndian>(v as i32).unwrap();
	}
}
impl XdrPrimitive for i16 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i16, Error>{
		match x.reader.read_i32::<BigEndian>() {
			Ok(v) => Ok(v as i16),
			Err(v) => Err(v)
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i32::<BigEndian>(v as i32).unwrap();
	}
}
impl XdrPrimitive for i32 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i32, Error>{
		match x.reader.read_i32::<BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(v)
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i32::<BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for i64 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i64, Error>{
		match x.reader.read_i64::<BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(v)
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i64::<BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for u64 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u64, Error>{
		match x.reader.read_u64::<BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(v)
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u64::<BigEndian>(v).unwrap();
	}

}

impl XdrPrimitive for f32 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<f32, Error>{
		match x.reader.read_f32::<BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(v)
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_f32::<BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for f64 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<f64, Error>{
		match x.reader.read_f64::<BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(v)
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_f64::<BigEndian>(v).unwrap();
	}
}
<commit_msg>Type cleanups<commit_after>use std::io;
use std::fmt;
use std::error;
use std::vec::Vec;
use byteorder;
use byteorder::{BigEndian,ReadBytesExt,WriteBytesExt};

#[derive(Debug)]
pub enum Error {
	Io(byteorder::Error),
	InvalidValue,
	InvalidType
}

impl From<byteorder::Error> for Error {
	fn from(err: byteorder::Error) -> Error { Error::Io(err) }
}

impl From<Error> for byteorder::Error {
	fn from(err: Error) -> byteorder::Error {
		match err {
			Error::Io(err) => err,
			Error::InvalidValue => byteorder::Error::Io(io::Error::new(io::ErrorKind::Other, "Invalid value")),
			Error::InvalidType => byteorder::Error::Io(io::Error::new(io::ErrorKind::Other, "Invalid type")),
		}
	}
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
	        match *self {
				Error::InvalidValue => write!(f, "Invalid value."),
				Error::InvalidType => write!(f, "Invalid type."),
				Error::Io(ref err) => err.fmt(f),
			}
	}
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::InvalidValue => "Invalid value.",
            Error::InvalidType => "Invalid type.",
            Error::Io(ref err) => error::Error::description(err),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::InvalidValue => None,
            Error::InvalidType => None,
            Error::Io(ref err) => err.cause(),
        }
    }
}

pub struct XdrReader {
	reader : io::Cursor<Vec<u8>>
}

pub struct XdrWriter {
	writer : io::Cursor<Vec<u8>>
}

impl XdrWriter {
	pub fn new() -> XdrWriter {
		let v : Vec<u8>= Vec::new();
		XdrWriter{ writer: io::Cursor::new(v)}
	}

	pub fn get_buffer(self) -> Vec<u8> {
		self.writer.into_inner()
	}

	pub fn pack<T:XdrPrimitive>(&mut self, x:T) {
		XdrPrimitive::write_to_xdr(self, x)
	}

}
pub trait XdrPrimitive {
	fn read_from_xdr(x: &mut XdrReader) -> Result<Self, Error>;
	fn write_to_xdr(x: &mut XdrWriter, v: Self);
}

impl XdrPrimitive for u32 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u32, Error>{
		match x.reader.read_u32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u32::<byteorder::BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for u16 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u16, Error>{
		match x.reader.read_u32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v as u16),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u32::<byteorder::BigEndian>(v as u32).unwrap();
	}
}
impl XdrPrimitive for u8 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u8, Error>{
		match x.reader.read_u32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v as u8),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u32::<byteorder::BigEndian>(v as u32).unwrap();
	}
}
impl XdrPrimitive for i8 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i8, Error>{
		match x.reader.read_i32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v as i8),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i32::<byteorder::BigEndian>(v as i32).unwrap();
	}
}
impl XdrPrimitive for i16 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i16, Error>{
		match x.reader.read_i32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v as i16),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i32::<byteorder::BigEndian>(v as i32).unwrap();
	}
}
impl XdrPrimitive for i32 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i32, Error>{
		match x.reader.read_i32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i32::<byteorder::BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for i64 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i64, Error>{
		match x.reader.read_i64::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i64::<byteorder::BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for u64 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u64, Error>{
		match x.reader.read_u64::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u64::<byteorder::BigEndian>(v).unwrap();
	}

}

impl XdrPrimitive for f32 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<f32, Error>{
		match x.reader.read_f32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_f32::<byteorder::BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for f64 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<f64, Error>{
		match x.reader.read_f64::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_f64::<byteorder::BigEndian>(v).unwrap();
	}
}

<|endoftext|>


<commit_before>#![crate_id = "zmq#0.1.0-pre"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![license = "MPLv2"]
#![feature(phase)]
#[phase(plugin, link)] extern crate log;

pub use ctx::Context;
pub use consts::{SocketType, REP, REQ};
pub use consts::{SocketOption, TYPE};
pub use consts::{HAUSNUMERO, ErrorCode, EINVAL, EPROTONOSUPPORT, ECONNREFUSED};
pub use msg::Msg;
pub use rep::RepSocket;
pub use req::ReqSocket;
pub use result::{ZmqResult, ZmqError};

mod ctx;
mod consts;
mod msg;
mod peer;
mod rep;
mod req;
mod result;
mod socket_base;
mod stream_engine;
mod tcp_connecter;
mod tcp_listener;
mod options;
mod v2_encoder;
mod v2_decoder;
mod v2_protocol;

#[cfg(test)]
mod test {
    #[test]
    fn test_socket_type() {
        assert_eq!(super::REQ as int, 3);
    }

    #[test]
    fn test_socket_create() {
        let c = super::Context::new();
        let s = c.socket(super::REQ);
        assert_eq!(s.getsockopt(super::TYPE), super::REQ as int);
    }

    #[test]
    fn test_socket_bind() {
        let c = super::Context::new();
        let mut s = c.socket(super::REQ);
        assert_eq!(s.bind("").unwrap_err().code, super::EINVAL);
        assert_eq!(s.bind("://127").unwrap_err().code, super::EINVAL);
        assert_eq!(s.bind("tcp://").unwrap_err().code, super::EINVAL);
        assert_eq!(s.bind("tcpp://127.0.0.1:12345").unwrap_err().code, super::EPROTONOSUPPORT);
        assert_eq!(s.bind("tcp://10.0.1.255:12345").unwrap_err().code, super::ECONNREFUSED);
        assert_eq!(s.bind("tcp://10.0.1.1:12z45").unwrap_err().code, super::EINVAL);
        assert!(s.bind("tcp://127.0.0.1:12345").is_ok());
        assert_eq!(s.bind("tcp://127.0.0.1:12345").unwrap_err().code, super::ECONNREFUSED);
    }

    #[test]
    fn test_socket_connect() {
        let c = super::Context::new();
        let mut s = c.socket(super::REQ);
        assert_eq!(s.connect("").unwrap_err().code, super::EINVAL);
        assert_eq!(s.connect("://127").unwrap_err().code, super::EINVAL);
        assert_eq!(s.connect("tcp://").unwrap_err().code, super::EINVAL);
        assert_eq!(s.connect("tcpp://127.0.0.1:12346").unwrap_err().code, super::EPROTONOSUPPORT);
        assert_eq!(s.connect("tcp://10.0.1.1:12z46").unwrap_err().code, super::EINVAL);
        assert!(s.connect("tcp://127.0.0.1:12346").is_ok());
        assert!(s.connect("tcp://127.0.0.1:12346").is_ok());
    }

    #[test]
    fn test_socket_small_message() {
        let c = super::Context::new();
        let mut req = c.socket(super::REQ);
        let mut rep = c.socket(super::REP);
        assert!(rep.bind("tcp://127.0.0.1:12347").is_ok());
        assert!(req.connect("tcp://127.0.0.1:12347").is_ok());

        let mut msg_sent = box super::Msg::new(4);
        msg_sent.data.push_all([65u8, 66u8, 67u8, 68u8]);
        assert!(req.msg_send(msg_sent).is_ok());

        let msg_recv = rep.msg_recv().unwrap();
        assert_eq!(msg_recv.data, [65u8, 66u8, 67u8, 68u8].into_owned());
    }
}
<commit_msg>Expose SocketBase trait.<commit_after>#![crate_id = "zmq#0.1.0-pre"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![license = "MPLv2"]
#![feature(phase)]
#[phase(plugin, link)] extern crate log;

pub use ctx::Context;
pub use consts::{SocketType, REP, REQ};
pub use consts::{SocketOption, TYPE};
pub use consts::{HAUSNUMERO, ErrorCode, EINVAL, EPROTONOSUPPORT, ECONNREFUSED};
pub use msg::Msg;
pub use rep::RepSocket;
pub use req::ReqSocket;
pub use result::{ZmqResult, ZmqError};
pub use socket_base::SocketBase;

mod ctx;
mod consts;
mod msg;
mod peer;
mod rep;
mod req;
mod result;
mod socket_base;
mod stream_engine;
mod tcp_connecter;
mod tcp_listener;
mod options;
mod v2_encoder;
mod v2_decoder;
mod v2_protocol;

#[cfg(test)]
mod test {
    #[test]
    fn test_socket_type() {
        assert_eq!(super::REQ as int, 3);
    }

    #[test]
    fn test_socket_create() {
        let c = super::Context::new();
        let s = c.socket(super::REQ);
        assert_eq!(s.getsockopt(super::TYPE), super::REQ as int);
    }

    #[test]
    fn test_socket_bind() {
        let c = super::Context::new();
        let mut s = c.socket(super::REQ);
        assert_eq!(s.bind("").unwrap_err().code, super::EINVAL);
        assert_eq!(s.bind("://127").unwrap_err().code, super::EINVAL);
        assert_eq!(s.bind("tcp://").unwrap_err().code, super::EINVAL);
        assert_eq!(s.bind("tcpp://127.0.0.1:12345").unwrap_err().code, super::EPROTONOSUPPORT);
        assert_eq!(s.bind("tcp://10.0.1.255:12345").unwrap_err().code, super::ECONNREFUSED);
        assert_eq!(s.bind("tcp://10.0.1.1:12z45").unwrap_err().code, super::EINVAL);
        assert!(s.bind("tcp://127.0.0.1:12345").is_ok());
        assert_eq!(s.bind("tcp://127.0.0.1:12345").unwrap_err().code, super::ECONNREFUSED);
    }

    #[test]
    fn test_socket_connect() {
        let c = super::Context::new();
        let mut s = c.socket(super::REQ);
        assert_eq!(s.connect("").unwrap_err().code, super::EINVAL);
        assert_eq!(s.connect("://127").unwrap_err().code, super::EINVAL);
        assert_eq!(s.connect("tcp://").unwrap_err().code, super::EINVAL);
        assert_eq!(s.connect("tcpp://127.0.0.1:12346").unwrap_err().code, super::EPROTONOSUPPORT);
        assert_eq!(s.connect("tcp://10.0.1.1:12z46").unwrap_err().code, super::EINVAL);
        assert!(s.connect("tcp://127.0.0.1:12346").is_ok());
        assert!(s.connect("tcp://127.0.0.1:12346").is_ok());
    }

    #[test]
    fn test_socket_small_message() {
        let c = super::Context::new();
        let mut req = c.socket(super::REQ);
        let mut rep = c.socket(super::REP);
        assert!(rep.bind("tcp://127.0.0.1:12347").is_ok());
        assert!(req.connect("tcp://127.0.0.1:12347").is_ok());

        let mut msg_sent = box super::Msg::new(4);
        msg_sent.data.push_all([65u8, 66u8, 67u8, 68u8]);
        assert!(req.msg_send(msg_sent).is_ok());

        let msg_recv = rep.msg_recv().unwrap();
        assert_eq!(msg_recv.data, [65u8, 66u8, 67u8, 68u8].into_owned());
    }
}
<|endoftext|>


<commit_before>use card_strategy::CardStrategy;

use card::Card;
use card::Suit;
use card::Rank;
use game_status::GameStatus;
use player::PlayerName;

use std::collections::BTreeMap;
use std::collections::BTreeSet;

#[derive(Debug)]
pub struct DefensiveCardStrategy;

/*
    Play 2 of clubs if in hand.
    If going to win a deal, do so with highest ranking card.
*/
impl DefensiveCardStrategy {
    fn score_card<'a>(card: &'a Card, game_status: &'a GameStatus) -> (i32, i32, i32, i32, i32, i32, i32) {
        let potential_points = Self::potential_points(card, game_status);
        let definite_points = if Self::will_win_deal(card, game_status) {
            potential_points
        } else {
            0
        };
        let later_potential_points = 0 - Self::later_potential_points(card, game_status);
        let card_penalty_to_me = Self::card_penalty_to_me(card, game_status);
        let card_penalty = 0 - Self::card_penalty(card, game_status);
        let trouble = Self::trouble_score(card, game_status);
        let card_rank = 0 - (u32::from(card.rank) as i32);
        (definite_points, potential_points, later_potential_points, card_penalty_to_me, card_penalty, trouble, card_rank)
    }

    fn card_penalty(card: &Card, game_status: &GameStatus) -> i32 {
        game_status.round_parameters.card_points.get(card)
            .map(|penalty| *penalty)
            .unwrap_or_default()
    }

    fn card_penalty_to_me(card: &Card, game_status: &GameStatus) -> i32 {
        if Self::can_win_deal(card, game_status) {
            Self::card_penalty(card, game_status)
        } else {
            0
        }
    }

    fn trouble_score(card: &Card, game_status: &GameStatus) -> i32 {
        if Self::can_win_deal(card, game_status) {
            let trouble = u32::from(card.rank) as i32;
            if Self::card_penalty_to_me(card, game_status) < 0 {
                0 - trouble
            } else {
                if Self::will_win_deal(card, game_status) {
                    u32::from(Rank::Ace) as i32
                } else {
                    trouble
                }
            }
        } else {
            0
        }
    }

    fn can_win_deal(card: &Card, game_status: &GameStatus) -> bool {
        game_status.my_in_progress_deal.as_ref().and_then(|deal|
            deal.suit.and_then(|suit|
                deal.deal_cards.iter()
                    .map(|deal_card| deal_card.card)
                    .filter(|card| card.suit == suit)
                    .max()
                    .map(|winning_card| card.suit == suit && card.rank > winning_card.rank))).unwrap_or(true)
    }

    fn will_win_deal(card: &Card, game_status: &GameStatus) -> bool {
        Self::can_win_deal(card, game_status) && (Self::plays_left(game_status).len() == 0 ||
            Self::deal_suit(game_status)
                .and_then(|suit| Self::remaining_cards(game_status).iter()
                    .filter(|card| card.suit == *suit)
                    .max()
                    .map(|winning_card| card.rank > winning_card.rank)).unwrap_or(true))
    }

    fn deal_suit(game_status: &GameStatus) -> Option<&Suit> {
        game_status.my_in_progress_deal.as_ref().and_then(|deal| deal.suit.as_ref())
    }

    fn plays_left(game_status: &GameStatus) -> BTreeSet<&PlayerName> {
        let mut players: BTreeSet<&PlayerName> = game_status.my_game_players.iter()
            .filter(|player| !player.has_turn)
            .map(|player| &player.team_name)
            .collect();

        if let &Some(ref deal) = &game_status.my_in_progress_deal {
            for deal_card in &deal.deal_cards {
                players.remove(&deal_card.player_name);
            }
        }

        players
    }

    fn remaining_cards(game_status: &GameStatus) -> BTreeSet<Card> {
        let mut cards = Card::all();

        for deal in &game_status.my_game_deals {
            for deal_card in &deal.deal_cards {
                cards.remove(&deal_card.card);
            }
        }

        if let &Some(ref deal) = &game_status.my_in_progress_deal {
            for deal_card in &deal.deal_cards {
                cards.remove(&deal_card.card);
            }
        }

        for card in &game_status.my_current_hand {
            cards.remove(&card);
        }

        cards
    }

    fn dealt_cards(game_status: &GameStatus) -> BTreeSet<Card> {
        game_status.my_in_progress_deal.as_ref()
            .map(|deal| deal.deal_cards.iter().map(|deal_card| deal_card.card).collect())
            .unwrap_or_default()
    }

    fn potential_points(card: &Card, game_status: &GameStatus) -> i32 {
        if Self::can_win_deal(card, game_status) {
            let mut cards = Self::remaining_cards(game_status);
            cards.extend(Self::dealt_cards(game_status));
            let cards = cards;

            let suit_points: i32 = cards.iter()
                .filter(|other| other.suit == card.suit)
                .filter(|other| other.rank < card.rank)
                .map(|other| Self::card_penalty(other, game_status))
                .sum();

            let other_points: i32 = cards.iter()
                .filter(|other| other.suit != card.suit)
                .map(|other| Self::card_penalty(other, game_status))
                .sum();

            suit_points + ((Self::chance_of_later_win(card, game_status) * (other_points as f32)) as i32)
        } else {
            0
        }
    }

    fn later_potential_points(card: &Card, game_status: &GameStatus) -> i32 {
        let cards = Self::remaining_cards(game_status);

        let suit_points: i32 = cards.iter()
            .filter(|other| other.suit == card.suit)
            .filter(|other| other.rank < card.rank)
            .map(|other| Self::card_penalty(other, game_status))
            .sum();

        let other_points: i32 = cards.iter()
            .filter(|other| other.suit != card.suit)
            .map(|other| Self::card_penalty(other, game_status))
            .sum();

        suit_points + ((Self::chance_of_later_win(card, game_status) * (other_points as f32)) as i32)
    }

    fn chance_of_later_win(card: &Card, game_status: &GameStatus) -> f32 {
        let cards = Self::remaining_cards(game_status);
        let suit_cards = cards.iter().filter(|other| other.suit == card.suit).collect::<Vec<_>>();
        let will_win_count = suit_cards.iter().filter(|other| other.rank < card.rank).collect::<Vec<_>>().len();
        if suit_cards.is_empty() {
            1.0
        } else {
            (will_win_count as f32) / (suit_cards.len() as f32)
        }
    }

}

impl CardStrategy for DefensiveCardStrategy {

    fn pass_cards<'a>(&mut self, game_status: &'a GameStatus) -> Vec<&'a Card> {
        game_status.my_initial_hand.iter()
            .map(|card| ((0 - Self::later_potential_points(card, game_status), card), card))
            .collect::<BTreeMap<_, &Card>>()
            .into_iter()
            .map(|kv| kv.1)
            .take(3)
            .collect()
    }

    fn play_card<'a>(&mut self, game_status: &'a GameStatus, player_name: &PlayerName) -> &'a Card {
        let current_suit = game_status.my_in_progress_deal.as_ref().and_then(|deal| deal.suit);
        let mut valid_cards = game_status.my_current_hand.iter()
            .filter(|card| Some(card.suit) == current_suit)
            .collect::<Vec<&Card>>();

        if valid_cards.is_empty() {
            valid_cards.extend(&game_status.my_current_hand);
        }

        let evaluation = valid_cards.into_iter()
            .map(|card| ((Self::score_card(card, game_status), card), card))
            .collect::<BTreeMap<_,&Card>>();

        // println!("Evaluation: {:?}", evaluation);

        evaluation.values()
            .next()
            .expect("No valid cards to play!")
    }

}

#[cfg(test)]
mod tests {
    use super::*;
    use player::PlayerName;
    use card::Card;
    use card::Rank::*;
    use card::Suit::*;
    use game_status::GameStatus;
    use game_status::dto::GameStatusDto;
    use card_strategy::CardStrategy;

    use try_from::TryFrom;
    use error::Error;

    extern crate serde;
    extern crate serde_json;

    use std::fs::File;
    use std::io::Read;

    fn open_scenario(name: &str) -> GameStatus {
        let file_name = format!("samples/scenarios/{}.json", name);
        let mut game_status_file = File::open(file_name).unwrap();
        let mut game_status_string = String::new();
        game_status_file.read_to_string(&mut game_status_string).unwrap();
        let game_status_dto: GameStatusDto = serde_json::from_str(&game_status_string).map_err(Error::from).unwrap();
        GameStatus::try_from(game_status_dto).unwrap()
    }

    fn should_play(name: &str, expected_card: Card) {
        let player_name = PlayerName::new("Derek Williams");
        let game_status = open_scenario(name);
        let card = DefensiveCardStrategy.play_card(&game_status, &player_name).clone();
        assert_eq!(expected_card, card);
    }

    #[test]
    fn normal_1() {
        should_play("normal 1", Jack.of(Diamond));
    }

    #[test]
    fn normal_2() {
        should_play("normal 2", King.of(Club));
    }

    #[test]
    fn normal_3() {
        should_play("normal 3", Six.of(Spade));
    }

    #[test]
    fn should_play_heart_1() {
        should_play("should play heart 1", Seven.of(Heart));
    }

    #[test]
    fn should_play_heart_2() {
        should_play("should play heart 2", Four.of(Heart));
    }

    #[test]
    fn should_play_high_rank_1() {
        should_play("should play high rank 1", King.of(Diamond));
    }

    #[test]
    fn should_play_high_rank_2() {
        should_play("should play high rank 2", Ace.of(Spade));
    }

    // #[test]
    // fn should_play_high_rank_3() { // Should get rid of high risk high rank
    //     should_play("should play high rank 3", Ace.of(Spade));
    // }

    #[test]
    fn should_not_crash_during_card_play() {
        should_play("crashed during card play", Ten.of(Heart));
    }

}<commit_msg>add dev note<commit_after>use card_strategy::CardStrategy;

use card::Card;
use card::Suit;
use card::Rank;
use game_status::GameStatus;
use player::PlayerName;

use std::collections::BTreeMap;
use std::collections::BTreeSet;

#[derive(Debug)]
pub struct DefensiveCardStrategy;

/*
    Play 2 of clubs if in hand.
    If going to win a deal, do so with highest ranking card.
*/
impl DefensiveCardStrategy {
    fn score_card<'a>(card: &'a Card, game_status: &'a GameStatus) -> (i32, i32, i32, i32, i32, i32, i32) {
        let potential_points = Self::potential_points(card, game_status);
        let definite_points = if Self::will_win_deal(card, game_status) {
            potential_points
        } else {
            0
        };
        let later_potential_points = 0 - Self::later_potential_points(card, game_status);
        let card_penalty_to_me = Self::card_penalty_to_me(card, game_status);
        let card_penalty = 0 - Self::card_penalty(card, game_status);
        let trouble = Self::trouble_score(card, game_status);
        let card_rank = 0 - (u32::from(card.rank) as i32);
        (definite_points, potential_points, later_potential_points, card_penalty_to_me, card_penalty, trouble, card_rank)
    }

    fn card_penalty(card: &Card, game_status: &GameStatus) -> i32 {
        game_status.round_parameters.card_points.get(card)
            .map(|penalty| *penalty)
            .unwrap_or_default()
    }

    fn card_penalty_to_me(card: &Card, game_status: &GameStatus) -> i32 {
        if Self::can_win_deal(card, game_status) {
            Self::card_penalty(card, game_status)
        } else {
            0
        }
    }

    fn trouble_score(card: &Card, game_status: &GameStatus) -> i32 {
        if Self::can_win_deal(card, game_status) {
            let trouble = u32::from(card.rank) as i32;
            if Self::card_penalty_to_me(card, game_status) < 0 {
                0 - trouble
            } else {
                if Self::will_win_deal(card, game_status) {
                    u32::from(Rank::Ace) as i32
                } else {
                    trouble
                }
            }
        } else {
            0
        }
    }

    fn can_win_deal(card: &Card, game_status: &GameStatus) -> bool {
        game_status.my_in_progress_deal.as_ref().and_then(|deal|
            deal.suit.and_then(|suit|
                deal.deal_cards.iter()
                    .map(|deal_card| deal_card.card)
                    .filter(|card| card.suit == suit)
                    .max()
                    .map(|winning_card| card.suit == suit && card.rank > winning_card.rank))).unwrap_or(true)
    }

    fn will_win_deal(card: &Card, game_status: &GameStatus) -> bool {
        Self::can_win_deal(card, game_status) && (Self::plays_left(game_status).len() == 0 ||
            Self::deal_suit(game_status)
                .and_then(|suit| Self::remaining_cards(game_status).iter()
                    .filter(|card| card.suit == *suit)
                    .max()
                    .map(|winning_card| card.rank > winning_card.rank)).unwrap_or(true))
    }

    fn deal_suit(game_status: &GameStatus) -> Option<&Suit> {
        game_status.my_in_progress_deal.as_ref().and_then(|deal| deal.suit.as_ref())
    }

    fn plays_left(game_status: &GameStatus) -> BTreeSet<&PlayerName> {
        let mut players: BTreeSet<&PlayerName> = game_status.my_game_players.iter()
            .filter(|player| !player.has_turn)
            .map(|player| &player.team_name)
            .collect();

        if let &Some(ref deal) = &game_status.my_in_progress_deal {
            for deal_card in &deal.deal_cards {
                players.remove(&deal_card.player_name);
            }
        }

        players
    }

    fn remaining_cards(game_status: &GameStatus) -> BTreeSet<Card> {
        let mut cards = Card::all();

        for deal in &game_status.my_game_deals {
            for deal_card in &deal.deal_cards {
                cards.remove(&deal_card.card);
            }
        }

        if let &Some(ref deal) = &game_status.my_in_progress_deal {
            for deal_card in &deal.deal_cards {
                cards.remove(&deal_card.card);
            }
        }

        for card in &game_status.my_current_hand {
            cards.remove(&card);
        }

        cards
    }

    fn dealt_cards(game_status: &GameStatus) -> BTreeSet<Card> {
        game_status.my_in_progress_deal.as_ref()
            .map(|deal| deal.deal_cards.iter().map(|deal_card| deal_card.card).collect())
            .unwrap_or_default()
    }

    fn potential_points(card: &Card, game_status: &GameStatus) -> i32 {
        // potential points for this deal should also have a chance modifier
        if Self::can_win_deal(card, game_status) {
            let mut cards = Self::remaining_cards(game_status);
            cards.extend(Self::dealt_cards(game_status));
            let cards = cards;

            let suit_points: i32 = cards.iter()
                .filter(|other| other.suit == card.suit)
                .filter(|other| other.rank < card.rank)
                .map(|other| Self::card_penalty(other, game_status))
                .sum();

            let other_points: i32 = cards.iter()
                .filter(|other| other.suit != card.suit)
                .map(|other| Self::card_penalty(other, game_status))
                .sum();

            suit_points + ((Self::chance_of_later_win(card, game_status) * (other_points as f32)) as i32)
        } else {
            0
        }
    }

    fn later_potential_points(card: &Card, game_status: &GameStatus) -> i32 {
        let cards = Self::remaining_cards(game_status);

        let suit_points: i32 = cards.iter()
            .filter(|other| other.suit == card.suit)
            .filter(|other| other.rank < card.rank)
            .map(|other| Self::card_penalty(other, game_status))
            .sum();

        let other_points: i32 = cards.iter()
            .filter(|other| other.suit != card.suit)
            .map(|other| Self::card_penalty(other, game_status))
            .sum();

        suit_points + ((Self::chance_of_later_win(card, game_status) * (other_points as f32)) as i32)
    }

    fn chance_of_later_win(card: &Card, game_status: &GameStatus) -> f32 {
        let cards = Self::remaining_cards(game_status);
        let suit_cards = cards.iter().filter(|other| other.suit == card.suit).collect::<Vec<_>>();
        let will_win_count = suit_cards.iter().filter(|other| other.rank < card.rank).collect::<Vec<_>>().len();
        if suit_cards.is_empty() {
            1.0
        } else {
            (will_win_count as f32) / (suit_cards.len() as f32)
        }
    }

}

impl CardStrategy for DefensiveCardStrategy {

    fn pass_cards<'a>(&mut self, game_status: &'a GameStatus) -> Vec<&'a Card> {
        game_status.my_initial_hand.iter()
            .map(|card| ((0 - Self::later_potential_points(card, game_status), card), card))
            .collect::<BTreeMap<_, &Card>>()
            .into_iter()
            .map(|kv| kv.1)
            .take(3)
            .collect()
    }

    fn play_card<'a>(&mut self, game_status: &'a GameStatus, player_name: &PlayerName) -> &'a Card {
        let current_suit = game_status.my_in_progress_deal.as_ref().and_then(|deal| deal.suit);
        let mut valid_cards = game_status.my_current_hand.iter()
            .filter(|card| Some(card.suit) == current_suit)
            .collect::<Vec<&Card>>();

        if valid_cards.is_empty() {
            valid_cards.extend(&game_status.my_current_hand);
        }

        let evaluation = valid_cards.into_iter()
            .map(|card| ((Self::score_card(card, game_status), card), card))
            .collect::<BTreeMap<_,&Card>>();

        // println!("Evaluation: {:?}", evaluation);

        evaluation.values()
            .next()
            .expect("No valid cards to play!")
    }

}

#[cfg(test)]
mod tests {
    use super::*;
    use player::PlayerName;
    use card::Card;
    use card::Rank::*;
    use card::Suit::*;
    use game_status::GameStatus;
    use game_status::dto::GameStatusDto;
    use card_strategy::CardStrategy;

    use try_from::TryFrom;
    use error::Error;

    extern crate serde;
    extern crate serde_json;

    use std::fs::File;
    use std::io::Read;

    fn open_scenario(name: &str) -> GameStatus {
        let file_name = format!("samples/scenarios/{}.json", name);
        let mut game_status_file = File::open(file_name).unwrap();
        let mut game_status_string = String::new();
        game_status_file.read_to_string(&mut game_status_string).unwrap();
        let game_status_dto: GameStatusDto = serde_json::from_str(&game_status_string).map_err(Error::from).unwrap();
        GameStatus::try_from(game_status_dto).unwrap()
    }

    fn should_play(name: &str, expected_card: Card) {
        let player_name = PlayerName::new("Derek Williams");
        let game_status = open_scenario(name);
        let card = DefensiveCardStrategy.play_card(&game_status, &player_name).clone();
        assert_eq!(expected_card, card);
    }

    #[test]
    fn normal_1() {
        should_play("normal 1", Jack.of(Diamond));
    }

    #[test]
    fn normal_2() {
        should_play("normal 2", King.of(Club));
    }

    #[test]
    fn normal_3() {
        should_play("normal 3", Six.of(Spade));
    }

    #[test]
    fn should_play_heart_1() {
        should_play("should play heart 1", Seven.of(Heart));
    }

    #[test]
    fn should_play_heart_2() {
        should_play("should play heart 2", Four.of(Heart));
    }

    #[test]
    fn should_play_high_rank_1() {
        should_play("should play high rank 1", King.of(Diamond));
    }

    #[test]
    fn should_play_high_rank_2() {
        should_play("should play high rank 2", Ace.of(Spade));
    }

    // #[test]
    // fn should_play_high_rank_3() { // Should get rid of high risk high rank
    //     should_play("should play high rank 3", Ace.of(Spade));
    // }

    #[test]
    fn should_not_crash_during_card_play() {
        should_play("crashed during card play", Ten.of(Heart));
    }

}<|endoftext|>