<commit_before>#![allow(missing_docs, nonstandard_style)]

use crate::ffi::{OsStr, OsString};
use crate::io::ErrorKind;
use crate::os::windows::ffi::{OsStrExt, OsStringExt};
use crate::path::PathBuf;
use crate::ptr;
use crate::time::Duration;

pub use self::rand::hashmap_random_keys;
pub use libc::strlen;

#[macro_use]
pub mod compat;

pub mod alloc;
pub mod args;
pub mod c;
pub mod cmath;
pub mod condvar;
pub mod env;
pub mod ext;
pub mod fast_thread_local;
pub mod fs;
pub mod handle;
pub mod io;
pub mod memchr;
pub mod mutex;
pub mod net;
pub mod os;
pub mod os_str;
pub mod path;
pub mod pipe;
pub mod process;
pub mod rand;
pub mod rwlock;
pub mod thread;
pub mod thread_local;
pub mod time;
cfg_if::cfg_if! {
    if #[cfg(not(target_vendor = "uwp"))] {
        pub mod stdio;
        pub mod stack_overflow;
    } else {
        pub mod stdio_uwp;
        pub mod stack_overflow_uwp;
        pub use self::stdio_uwp as stdio;
        pub use self::stack_overflow_uwp as stack_overflow;
    }
}

#[cfg(not(test))]
pub fn init() {}

pub fn decode_error_kind(errno: i32) -> ErrorKind {
    match errno as c::DWORD {
        c::ERROR_ACCESS_DENIED => return ErrorKind::PermissionDenied,
        c::ERROR_ALREADY_EXISTS => return ErrorKind::AlreadyExists,
        c::ERROR_FILE_EXISTS => return ErrorKind::AlreadyExists,
        c::ERROR_BROKEN_PIPE => return ErrorKind::BrokenPipe,
        c::ERROR_FILE_NOT_FOUND => return ErrorKind::NotFound,
        c::ERROR_PATH_NOT_FOUND => return ErrorKind::NotFound,
        c::ERROR_NO_DATA => return ErrorKind::BrokenPipe,
        c::ERROR_OPERATION_ABORTED => return ErrorKind::TimedOut,
        _ => {}
    }

    match errno {
        c::WSAEACCES => ErrorKind::PermissionDenied,
        c::WSAEADDRINUSE => ErrorKind::AddrInUse,
        c::WSAEADDRNOTAVAIL => ErrorKind::AddrNotAvailable,
        c::WSAECONNABORTED => ErrorKind::ConnectionAborted,
        c::WSAECONNREFUSED => ErrorKind::ConnectionRefused,
        c::WSAECONNRESET => ErrorKind::ConnectionReset,
        c::WSAEINVAL => ErrorKind::InvalidInput,
        c::WSAENOTCONN => ErrorKind::NotConnected,
        c::WSAEWOULDBLOCK => ErrorKind::WouldBlock,
        c::WSAETIMEDOUT => ErrorKind::TimedOut,

        _ => ErrorKind::Other,
    }
}

pub fn to_u16s<S: AsRef<OsStr>>(s: S) -> crate::io::Result<Vec<u16>> {
    fn inner(s: &OsStr) -> crate::io::Result<Vec<u16>> {
        let mut maybe_result: Vec<u16> = s.encode_wide().collect();
        if maybe_result.iter().any(|&u| u == 0) {
            return Err(crate::io::Error::new(
                ErrorKind::InvalidInput,
                "strings passed to WinAPI cannot contain NULs",
            ));
        }
        maybe_result.push(0);
        Ok(maybe_result)
    }
    inner(s.as_ref())
}

// Many Windows APIs follow a pattern of where we hand a buffer and then they
// will report back to us how large the buffer should be or how many bytes
// currently reside in the buffer. This function is an abstraction over these
// functions by making them easier to call.
//
// The first callback, `f1`, is yielded a (pointer, len) pair which can be
// passed to a syscall. The `ptr` is valid for `len` items (u16 in this case).
// The closure is expected to return what the syscall returns which will be
// interpreted by this function to determine if the syscall needs to be invoked
// again (with more buffer space).
//
// Once the syscall has completed (errors bail out early) the second closure is
// yielded the data which has been read from the syscall. The return value
// from this closure is then the return value of the function.
fn fill_utf16_buf<F1, F2, T>(mut f1: F1, f2: F2) -> crate::io::Result<T>
where
    F1: FnMut(*mut u16, c::DWORD) -> c::DWORD,
    F2: FnOnce(&[u16]) -> T,
{
    // Start off with a stack buf but then spill over to the heap if we end up
    // needing more space.
    let mut stack_buf = [0u16; 512];
    let mut heap_buf = Vec::new();
    unsafe {
        let mut n = stack_buf.len();
        loop {
            let buf = if n <= stack_buf.len() {
                &mut stack_buf[..]
            } else {
                let extra = n - heap_buf.len();
                heap_buf.reserve(extra);
                heap_buf.set_len(n);
                &mut heap_buf[..]
            };

            // This function is typically called on windows API functions which
            // will return the correct length of the string, but these functions
            // also return the `0` on error. In some cases, however, the
            // returned "correct length" may actually be 0!
            //
            // To handle this case we call `SetLastError` to reset it to 0 and
            // then check it again if we get the "0 error value". If the "last
            // error" is still 0 then we interpret it as a 0 length buffer and
            // not an actual error.
            c::SetLastError(0);
            let k = match f1(buf.as_mut_ptr(), n as c::DWORD) {
                0 if c::GetLastError() == 0 => 0,
                0 => return Err(crate::io::Error::last_os_error()),
                n => n,
            } as usize;
            if k == n && c::GetLastError() == c::ERROR_INSUFFICIENT_BUFFER {
                n *= 2;
            } else if k >= n {
                n = k;
            } else {
                return Ok(f2(&buf[..k]));
            }
        }
    }
}

fn os2path(s: &[u16]) -> PathBuf {
    PathBuf::from(OsString::from_wide(s))
}

#[allow(dead_code)] // Only used in backtrace::gnu::get_executable_filename()
fn wide_char_to_multi_byte(
    code_page: u32,
    flags: u32,
    s: &[u16],
    no_default_char: bool,
) -> crate::io::Result<Vec<i8>> {
    unsafe {
        let mut size = c::WideCharToMultiByte(
            code_page,
            flags,
            s.as_ptr(),
            s.len() as i32,
            ptr::null_mut(),
            0,
            ptr::null(),
            ptr::null_mut(),
        );
        if size == 0 {
            return Err(crate::io::Error::last_os_error());
        }

        let mut buf = Vec::with_capacity(size as usize);
        buf.set_len(size as usize);

        let mut used_default_char = c::FALSE;
        size = c::WideCharToMultiByte(
            code_page,
            flags,
            s.as_ptr(),
            s.len() as i32,
            buf.as_mut_ptr(),
            buf.len() as i32,
            ptr::null(),
            if no_default_char { &mut used_default_char } else { ptr::null_mut() },
        );
        if size == 0 {
            return Err(crate::io::Error::last_os_error());
        }
        if no_default_char && used_default_char == c::TRUE {
            return Err(crate::io::Error::new(
                crate::io::ErrorKind::InvalidData,
                "string cannot be converted to requested code page",
            ));
        }

        buf.set_len(size as usize);

        Ok(buf)
    }
}

pub fn truncate_utf16_at_nul(v: &[u16]) -> &[u16] {
    match v.iter().position(|c| *c == 0) {
        // don't include the 0
        Some(i) => &v[..i],
        None => v,
    }
}

pub trait IsZero {
    fn is_zero(&self) -> bool;
}

macro_rules! impl_is_zero {
    ($($t:ident)*) => ($(impl IsZero for $t {
        fn is_zero(&self) -> bool {
            *self == 0
        }
    })*)
}

impl_is_zero! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }

pub fn cvt<I: IsZero>(i: I) -> crate::io::Result<I> {
    if i.is_zero() { Err(crate::io::Error::last_os_error()) } else { Ok(i) }
}

pub fn dur2timeout(dur: Duration) -> c::DWORD {
    // Note that a duration is a (u64, u32) (seconds, nanoseconds) pair, and the
    // timeouts in windows APIs are typically u32 milliseconds. To translate, we
    // have two pieces to take care of:
    //
    // * Nanosecond precision is rounded up
    // * Greater than u32::MAX milliseconds (50 days) is rounded up to INFINITE
    //   (never time out).
    dur.as_secs()
        .checked_mul(1000)
        .and_then(|ms| ms.checked_add((dur.subsec_nanos() as u64) / 1_000_000))
        .and_then(|ms| ms.checked_add(if dur.subsec_nanos() % 1_000_000 > 0 { 1 } else { 0 }))
        .map(|ms| if ms > <c::DWORD>::max_value() as u64 { c::INFINITE } else { ms as c::DWORD })
        .unwrap_or(c::INFINITE)
}

// On Windows, use the processor-specific __fastfail mechanism.  In Windows 8
// and later, this will terminate the process immediately without running any
// in-process exception handlers.  In earlier versions of Windows, this
// sequence of instructions will be treated as an access violation,
// terminating the process but without necessarily bypassing all exception
// handlers.
//
// https://docs.microsoft.com/en-us/cpp/intrinsics/fastfail
#[allow(unreachable_code)]
pub unsafe fn abort_internal() -> ! {
    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
    {
        llvm_asm!("int $$0x29" :: "{ecx}"(7) ::: volatile); // 7 is FAST_FAIL_FATAL_APP_EXIT
        crate::intrinsics::unreachable();
    }
    crate::intrinsics::abort();
}
<commit_msg>Rollup merge of #67705 - lzutao:wmemchr, r=wesleywiser<commit_after>#![allow(missing_docs, nonstandard_style)]

use crate::ffi::{OsStr, OsString};
use crate::io::ErrorKind;
use crate::os::windows::ffi::{OsStrExt, OsStringExt};
use crate::path::PathBuf;
use crate::ptr;
use crate::time::Duration;

pub use self::rand::hashmap_random_keys;
pub use libc::strlen;

#[macro_use]
pub mod compat;

pub mod alloc;
pub mod args;
pub mod c;
pub mod cmath;
pub mod condvar;
pub mod env;
pub mod ext;
pub mod fast_thread_local;
pub mod fs;
pub mod handle;
pub mod io;
pub mod memchr;
pub mod mutex;
pub mod net;
pub mod os;
pub mod os_str;
pub mod path;
pub mod pipe;
pub mod process;
pub mod rand;
pub mod rwlock;
pub mod thread;
pub mod thread_local;
pub mod time;
cfg_if::cfg_if! {
    if #[cfg(not(target_vendor = "uwp"))] {
        pub mod stdio;
        pub mod stack_overflow;
    } else {
        pub mod stdio_uwp;
        pub mod stack_overflow_uwp;
        pub use self::stdio_uwp as stdio;
        pub use self::stack_overflow_uwp as stack_overflow;
    }
}

#[cfg(not(test))]
pub fn init() {}

pub fn decode_error_kind(errno: i32) -> ErrorKind {
    match errno as c::DWORD {
        c::ERROR_ACCESS_DENIED => return ErrorKind::PermissionDenied,
        c::ERROR_ALREADY_EXISTS => return ErrorKind::AlreadyExists,
        c::ERROR_FILE_EXISTS => return ErrorKind::AlreadyExists,
        c::ERROR_BROKEN_PIPE => return ErrorKind::BrokenPipe,
        c::ERROR_FILE_NOT_FOUND => return ErrorKind::NotFound,
        c::ERROR_PATH_NOT_FOUND => return ErrorKind::NotFound,
        c::ERROR_NO_DATA => return ErrorKind::BrokenPipe,
        c::ERROR_OPERATION_ABORTED => return ErrorKind::TimedOut,
        _ => {}
    }

    match errno {
        c::WSAEACCES => ErrorKind::PermissionDenied,
        c::WSAEADDRINUSE => ErrorKind::AddrInUse,
        c::WSAEADDRNOTAVAIL => ErrorKind::AddrNotAvailable,
        c::WSAECONNABORTED => ErrorKind::ConnectionAborted,
        c::WSAECONNREFUSED => ErrorKind::ConnectionRefused,
        c::WSAECONNRESET => ErrorKind::ConnectionReset,
        c::WSAEINVAL => ErrorKind::InvalidInput,
        c::WSAENOTCONN => ErrorKind::NotConnected,
        c::WSAEWOULDBLOCK => ErrorKind::WouldBlock,
        c::WSAETIMEDOUT => ErrorKind::TimedOut,

        _ => ErrorKind::Other,
    }
}

pub fn unrolled_find_u16s(needle: u16, haystack: &[u16]) -> Option<usize> {
    let ptr = haystack.as_ptr();
    let mut len = haystack.len();
    let mut start = &haystack[..];

    // For performance reasons unfold the loop eight times.
    while len >= 8 {
        if start[0] == needle {
            return Some((start.as_ptr() as usize - ptr as usize) / 2);
        }
        if start[1] == needle {
            return Some((start[1..].as_ptr() as usize - ptr as usize) / 2);
        }
        if start[2] == needle {
            return Some((start[2..].as_ptr() as usize - ptr as usize) / 2);
        }
        if start[3] == needle {
            return Some((start[3..].as_ptr() as usize - ptr as usize) / 2);
        }
        if start[4] == needle {
            return Some((start[4..].as_ptr() as usize - ptr as usize) / 2);
        }
        if start[5] == needle {
            return Some((start[5..].as_ptr() as usize - ptr as usize) / 2);
        }
        if start[6] == needle {
            return Some((start[6..].as_ptr() as usize - ptr as usize) / 2);
        }
        if start[7] == needle {
            return Some((start[7..].as_ptr() as usize - ptr as usize) / 2);
        }

        start = &start[8..];
        len -= 8;
    }

    for (i, c) in start.iter().enumerate() {
        if *c == needle {
            return Some((start.as_ptr() as usize - ptr as usize) / 2 + i);
        }
    }
    None
}

pub fn to_u16s<S: AsRef<OsStr>>(s: S) -> crate::io::Result<Vec<u16>> {
    fn inner(s: &OsStr) -> crate::io::Result<Vec<u16>> {
        let mut maybe_result: Vec<u16> = s.encode_wide().collect();
        if unrolled_find_u16s(0, &maybe_result).is_some() {
            return Err(crate::io::Error::new(
                ErrorKind::InvalidInput,
                "strings passed to WinAPI cannot contain NULs",
            ));
        }
        maybe_result.push(0);
        Ok(maybe_result)
    }
    inner(s.as_ref())
}

// Many Windows APIs follow a pattern of where we hand a buffer and then they
// will report back to us how large the buffer should be or how many bytes
// currently reside in the buffer. This function is an abstraction over these
// functions by making them easier to call.
//
// The first callback, `f1`, is yielded a (pointer, len) pair which can be
// passed to a syscall. The `ptr` is valid for `len` items (u16 in this case).
// The closure is expected to return what the syscall returns which will be
// interpreted by this function to determine if the syscall needs to be invoked
// again (with more buffer space).
//
// Once the syscall has completed (errors bail out early) the second closure is
// yielded the data which has been read from the syscall. The return value
// from this closure is then the return value of the function.
fn fill_utf16_buf<F1, F2, T>(mut f1: F1, f2: F2) -> crate::io::Result<T>
where
    F1: FnMut(*mut u16, c::DWORD) -> c::DWORD,
    F2: FnOnce(&[u16]) -> T,
{
    // Start off with a stack buf but then spill over to the heap if we end up
    // needing more space.
    let mut stack_buf = [0u16; 512];
    let mut heap_buf = Vec::new();
    unsafe {
        let mut n = stack_buf.len();
        loop {
            let buf = if n <= stack_buf.len() {
                &mut stack_buf[..]
            } else {
                let extra = n - heap_buf.len();
                heap_buf.reserve(extra);
                heap_buf.set_len(n);
                &mut heap_buf[..]
            };

            // This function is typically called on windows API functions which
            // will return the correct length of the string, but these functions
            // also return the `0` on error. In some cases, however, the
            // returned "correct length" may actually be 0!
            //
            // To handle this case we call `SetLastError` to reset it to 0 and
            // then check it again if we get the "0 error value". If the "last
            // error" is still 0 then we interpret it as a 0 length buffer and
            // not an actual error.
            c::SetLastError(0);
            let k = match f1(buf.as_mut_ptr(), n as c::DWORD) {
                0 if c::GetLastError() == 0 => 0,
                0 => return Err(crate::io::Error::last_os_error()),
                n => n,
            } as usize;
            if k == n && c::GetLastError() == c::ERROR_INSUFFICIENT_BUFFER {
                n *= 2;
            } else if k >= n {
                n = k;
            } else {
                return Ok(f2(&buf[..k]));
            }
        }
    }
}

fn os2path(s: &[u16]) -> PathBuf {
    PathBuf::from(OsString::from_wide(s))
}

#[allow(dead_code)] // Only used in backtrace::gnu::get_executable_filename()
fn wide_char_to_multi_byte(
    code_page: u32,
    flags: u32,
    s: &[u16],
    no_default_char: bool,
) -> crate::io::Result<Vec<i8>> {
    unsafe {
        let mut size = c::WideCharToMultiByte(
            code_page,
            flags,
            s.as_ptr(),
            s.len() as i32,
            ptr::null_mut(),
            0,
            ptr::null(),
            ptr::null_mut(),
        );
        if size == 0 {
            return Err(crate::io::Error::last_os_error());
        }

        let mut buf = Vec::with_capacity(size as usize);
        buf.set_len(size as usize);

        let mut used_default_char = c::FALSE;
        size = c::WideCharToMultiByte(
            code_page,
            flags,
            s.as_ptr(),
            s.len() as i32,
            buf.as_mut_ptr(),
            buf.len() as i32,
            ptr::null(),
            if no_default_char { &mut used_default_char } else { ptr::null_mut() },
        );
        if size == 0 {
            return Err(crate::io::Error::last_os_error());
        }
        if no_default_char && used_default_char == c::TRUE {
            return Err(crate::io::Error::new(
                crate::io::ErrorKind::InvalidData,
                "string cannot be converted to requested code page",
            ));
        }

        buf.set_len(size as usize);

        Ok(buf)
    }
}

pub fn truncate_utf16_at_nul(v: &[u16]) -> &[u16] {
    match unrolled_find_u16s(0, v) {
        // don't include the 0
        Some(i) => &v[..i],
        None => v,
    }
}

pub trait IsZero {
    fn is_zero(&self) -> bool;
}

macro_rules! impl_is_zero {
    ($($t:ident)*) => ($(impl IsZero for $t {
        fn is_zero(&self) -> bool {
            *self == 0
        }
    })*)
}

impl_is_zero! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }

pub fn cvt<I: IsZero>(i: I) -> crate::io::Result<I> {
    if i.is_zero() { Err(crate::io::Error::last_os_error()) } else { Ok(i) }
}

pub fn dur2timeout(dur: Duration) -> c::DWORD {
    // Note that a duration is a (u64, u32) (seconds, nanoseconds) pair, and the
    // timeouts in windows APIs are typically u32 milliseconds. To translate, we
    // have two pieces to take care of:
    //
    // * Nanosecond precision is rounded up
    // * Greater than u32::MAX milliseconds (50 days) is rounded up to INFINITE
    //   (never time out).
    dur.as_secs()
        .checked_mul(1000)
        .and_then(|ms| ms.checked_add((dur.subsec_nanos() as u64) / 1_000_000))
        .and_then(|ms| ms.checked_add(if dur.subsec_nanos() % 1_000_000 > 0 { 1 } else { 0 }))
        .map(|ms| if ms > <c::DWORD>::max_value() as u64 { c::INFINITE } else { ms as c::DWORD })
        .unwrap_or(c::INFINITE)
}

// On Windows, use the processor-specific __fastfail mechanism.  In Windows 8
// and later, this will terminate the process immediately without running any
// in-process exception handlers.  In earlier versions of Windows, this
// sequence of instructions will be treated as an access violation,
// terminating the process but without necessarily bypassing all exception
// handlers.
//
// https://docs.microsoft.com/en-us/cpp/intrinsics/fastfail
#[allow(unreachable_code)]
pub unsafe fn abort_internal() -> ! {
    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
    {
        llvm_asm!("int $$0x29" :: "{ecx}"(7) ::: volatile); // 7 is FAST_FAIL_FATAL_APP_EXIT
        crate::intrinsics::unreachable();
    }
    crate::intrinsics::abort();
}
<|endoftext|>


<commit_before>pub fn dirt() -> String {
  struct Wave {
    freq: f32,
    amp: f32,
  }

  let mut waves = Vec::new();
  for i in 0..10 {
    waves.push(
      Wave { freq:  ((1 << i) as f32) / 4.0, amp: 1.0 / (1 << i) as f32 }
    );
  }

  let mut contents = String::new();
  for wave in waves.iter() {
    contents.push_str(format!(r#"
    {{
      float freq = {};
      float amp = {};

      float dnoise = abs(cnoise(freq * world_position));
      noise += dnoise * amp;
      total_amp += amp;
    }}
    "#, wave.freq, wave.amp).as_str());
  }

  format!(r#"
  float total_amp = 0.0;
  float noise = 0.0;
  {}
  noise /= total_amp;
  return mix(vec3(0.4, 0.3, 0.1), vec3(0.7, 0.6, 0.4), noise);
  "#, contents)
}
<commit_msg>tweak dirt shader<commit_after>pub fn dirt() -> String {
  struct Wave {
    freq: f32,
    amp: f32,
  }

  let mut waves = Vec::new();
  for i in 0..10 {
    waves.push(
      Wave { freq: (1 << i) as f32, amp: 1.0 / (1 << i) as f32 }
    );
  }

  let mut contents = String::new();
  for wave in waves.iter() {
    contents.push_str(format!(r#"
    {{
      float freq = {};
      float amp = {};

      float dnoise = abs(cnoise(freq * world_position));
      noise += dnoise * amp;
      total_amp += amp;
    }}
    "#, wave.freq, wave.amp).as_str());
  }

  format!(r#"
  float total_amp = 0.0;
  float noise = 0.0;
  {}
  noise /= total_amp;
  return mix(vec3(0.4, 0.3, 0.1), vec3(0.7, 0.6, 0.4), noise);
  "#, contents)
}
<|endoftext|>


<commit_before>extern crate tokio;
extern crate tokio_io;
extern crate futures;
extern crate bytes;
extern crate prost;
#[macro_use]
extern crate prost_derive;
extern crate uuid;

use tokio::executor::current_thread;
use tokio::net::TcpListener;
use tokio_io::io;
use futures::{Future, Stream};
use prost::Message;
use uuid::Uuid;

use lsfn_api::{Welcome, ShipDescription, ControlDescription, SensorDescription};
use lsfn_api::control_description::ControlType;
use lsfn_api::sensor_description::SensorType;

pub mod lsfn_api {
    include!(concat!(env!("OUT_DIR"), "/lsfn.protocol.rs"));
}

fn main() {
    let addr = "127.0.0.1:6142".parse().unwrap();
    let listener = TcpListener::bind(&addr).unwrap();

    let ship = Welcome { ship: Some(ShipDescription {
        id: Uuid::new_v4().to_string(),
        name: "HMS Edge of Reason".to_string(),
        controls: vec![ ControlDescription {
            id: Uuid::new_v4().to_string(),
            name: "Thruster".to_string(),
            control_type: i32::from(ControlType::Trigger),
            throttle_range: None,
        } ],
        sensors: vec![ SensorDescription {
            id: Uuid::new_v4().to_string(),
            name: "Galacic Position System".to_string(),
            sensor_type: i32::from(SensorType::GalacticCoordinates),
            radar_range: None,
            iff_detector_range: None,
        }],
    }) };

    let server = listener.incoming().for_each(move |socket| {
        println!("accepted socket; addr={:?}", socket.peer_addr().unwrap());

        let mut ship_message = vec![];
        ship.encode(&mut ship_message)?;
        let connection = io::write_all(socket, ship_message)
            .then(|res| {
                println!("wrote message; success={:?}", res.is_ok());
                Ok(())
            });

        // Spawn a new task that processes the socket:
        current_thread::spawn(connection);

        Ok(())
    })
        .map_err(|err| {
            // All tasks must have an `Error` type of `()`. This forces error
            // handling and helps avoid silencing failures.
            //
            // In our example, we are only going to log the error to STDOUT.
            println!("accept error = {:?}", err);
        });

    current_thread::run(|_| {
        // Now, the server task is spawned.
        current_thread::spawn(server);

        println!("server running on localhost:6142");
    });
}
<commit_msg>Correct minor spelling mistake<commit_after>extern crate tokio;
extern crate tokio_io;
extern crate futures;
extern crate bytes;
extern crate prost;
#[macro_use]
extern crate prost_derive;
extern crate uuid;

use tokio::executor::current_thread;
use tokio::net::TcpListener;
use tokio_io::io;
use futures::{Future, Stream};
use prost::Message;
use uuid::Uuid;

use lsfn_api::{Welcome, ShipDescription, ControlDescription, SensorDescription};
use lsfn_api::control_description::ControlType;
use lsfn_api::sensor_description::SensorType;

pub mod lsfn_api {
    include!(concat!(env!("OUT_DIR"), "/lsfn.protocol.rs"));
}

fn main() {
    let addr = "127.0.0.1:6142".parse().unwrap();
    let listener = TcpListener::bind(&addr).unwrap();

    let ship = Welcome { ship: Some(ShipDescription {
        id: Uuid::new_v4().to_string(),
        name: "HMS Edge of Reason".to_string(),
        controls: vec![ ControlDescription {
            id: Uuid::new_v4().to_string(),
            name: "Thruster".to_string(),
            control_type: i32::from(ControlType::Trigger),
            throttle_range: None,
        } ],
        sensors: vec![ SensorDescription {
            id: Uuid::new_v4().to_string(),
            name: "Galactic Position System".to_string(),
            sensor_type: i32::from(SensorType::GalacticCoordinates),
            radar_range: None,
            iff_detector_range: None,
        }],
    }) };

    let server = listener.incoming().for_each(move |socket| {
        println!("accepted socket; addr={:?}", socket.peer_addr().unwrap());

        let mut ship_message = vec![];
        ship.encode(&mut ship_message)?;
        let connection = io::write_all(socket, ship_message)
            .then(|res| {
                println!("wrote message; success={:?}", res.is_ok());
                Ok(())
            });

        // Spawn a new task that processes the socket:
        current_thread::spawn(connection);

        Ok(())
    })
        .map_err(|err| {
            // All tasks must have an `Error` type of `()`. This forces error
            // handling and helps avoid silencing failures.
            //
            // In our example, we are only going to log the error to STDOUT.
            println!("accept error = {:?}", err);
        });

    current_thread::run(|_| {
        // Now, the server task is spawned.
        current_thread::spawn(server);

        println!("server running on localhost:6142");
    });
}
<|endoftext|>


<commit_before>extern crate termion;

use termion::event::{Key, Event, MouseEvent};
use termion::input::{TermRead, MouseTerminal};
use termion::raw::IntoRawMode;
use std::io::{Write, stdout, stdin};

fn main() {
    let stdin = stdin();
    let mut stdout = MouseTerminal::from(stdout().into_raw_mode().unwrap());

    writeln!(stdout,
             "{}{}q to exit. Type stuff, use alt, click around...",
             termion::clear::All,
             termion::cursor::Goto(1, 1))
        .unwrap();

    let mut x = 5;
    let mut y = 5;

    for c in stdin.events() {
        let evt = c.unwrap();
        match evt {
            Event::Key(Key::Char('q')) => break,
            Event::Mouse(me) => {
                match me {
                    MouseEvent::Press(_, a, b) |
                    MouseEvent::Release(a, b) |
                    MouseEvent::Hold(a, b) => {
                        x = a;
                        y = b;
                    }
                }
            }
            _ => {}
        }
        write!(stdout,
               "{}{}  {:?}{}",
               termion::clear::All,
               termion::cursor::Goto(x, y),
               evt,
               termion::cursor::Goto(x, y))
            .unwrap();
        stdout.flush().unwrap();
    }

    write!(stdout, "{}", termion::cursor::Show).unwrap();
}
<commit_msg>Update the mouse example.<commit_after>extern crate termion;

use termion::event::*;
use termion::cursor;
use termion::input::{TermRead, MouseTerminal};
use termion::raw::IntoRawMode;
use std::io::{self, Write};

fn main() {
    let stdin = io::stdin();
    let mut stdout = MouseTerminal::from(io::stdout().into_raw_mode().unwrap());

    writeln!(stdout,
             "{}{}q to exit. Type stuff, use alt, click around...",
             termion::clear::All,
             termion::cursor::Goto(1, 1))
        .unwrap();

    for c in stdin.events() {
        let evt = c.unwrap();
        match evt {
            Event::Key(Key::Char('q')) => break,
            Event::Mouse(me) => {
                match me {
                    MouseEvent::Press(_, a, b) |
                    MouseEvent::Release(a, b) |
                    MouseEvent::Hold(a, b) => {
                        write!(stdout, "{}", cursor::Goto(a, b)).unwrap();
                    }
                }
            }
            _ => {}
        }

        stdout.flush().unwrap();
    }
}
<|endoftext|>


<commit_before>use orbtk::prelude::*;

widget!(MainView);

impl Template for MainView {
    fn template(self, _: Entity, ctx: &mut BuildContext) -> Self {
        self.name("MainView").child(
            Stack::create()
                .child(
                    Button::create()
                        .text("left")
                        .horizontal_alignment("start")
                        .build(ctx),
                )
                .child(
                    Button::create()
                        .margin((0.0, 8.0, 0.0, 0.0))
                        .text("center")
                        .horizontal_alignment("center")
                        .build(ctx),
                )
                .child(
                    Button::create()
                        .margin((0.0, 8.0, 0.0, 0.0))
                        .text("stretch")
                        .horizontal_alignment("stretch")
                        .build(ctx),
                )
                .child(
                    Button::create()
                        .margin((0.0, 8.0, 0.0, 0.0))
                        .text("right")
                        .horizontal_alignment("end")
                        .build(ctx),
                )
                .build(ctx),
        )
    }
}

fn main() {
    // use this only if you want to run it as web application.
    orbtk::initialize();

    Application::new()
        .window(|ctx| {
            Window::create()
                .title("OrbTk - stack example")
                .position((100.0, 100.0))
                .size(420.0, 730.0)
                .child(MainView::create().margin(4.0).build(ctx))
                .build(ctx)
        })
        .run();
}
<commit_msg>Finish stack example.<commit_after>use orbtk::prelude::*;

widget!(MainView);

impl Template for MainView {
    fn template(self, _: Entity, ctx: &mut BuildContext) -> Self {
        self.name("MainView").child(
            Stack::create()
                .child(
                    TextBlock::create()
                        .margin((0.0, 0.0, 0.0, 8.0))
                        .text("Stack vertical")
                        .selector("h1")
                        .build(ctx),
                )
                .child(
                    Stack::create()
                        .spacing(4.0)
                        .child(
                            Button::create()
                                .text("left")
                                .horizontal_alignment("start")
                                .build(ctx),
                        )
                        .child(
                            Button::create()
                                .text("center")
                                .horizontal_alignment("center")
                                .build(ctx),
                        )
                        .child(
                            Button::create()
                                .text("stretch")
                                .horizontal_alignment("stretch")
                                .build(ctx),
                        )
                        .child(
                            Button::create()
                                .text("right")
                                .horizontal_alignment("end")
                                .build(ctx),
                        )
                        .build(ctx),
                )
                .child(
                    TextBlock::create()
                        .margin((0.0, 0.0, 0.0, 8.0))
                        .text("Stack horizontal")
                        .selector("h1")
                        .build(ctx),
                )
                .child(
                    Stack::create()
                        .orientation("horitzontal")
                        .spacing(4.0)
                        .child(
                            Button::create()
                                .text("top")
                                .vertical_alignment("start")
                                .build(ctx),
                        )
                        .build(ctx),
                )
                .build(ctx),
        )
    }
}

fn main() {
    // use this only if you want to run it as web application.
    orbtk::initialize();

    Application::new()
        .window(|ctx| {
            Window::create()
                .title("OrbTk - stack example")
                .position((100.0, 100.0))
                .size(420.0, 730.0)
                .child(MainView::create().margin(4.0).build(ctx))
                .build(ctx)
        })
        .run();
}
<|endoftext|>


<commit_before>#![warn(bad_style,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results)]

extern crate twitter_api as twitter;
extern crate rustc_serialize as rustc_serialize;
extern crate oauth_client as oauth;

use std::io;
use std::io::prelude::*;
use std::env;
use std::fs::{File, OpenOptions};
use std::path::Path;
use std::path::PathBuf;
use rustc_serialize::Decodable;
use rustc_serialize::json::{self, Json};
use oauth::Token;

const TWITTER_CONF_FILENAME: &'static str = ".twitter.conf";

fn get_home_dir() -> PathBuf{
    match env::home_dir() {
        Some(p) => p,
        None => {
            panic!("Impossible to get your home dir!");
        }
    }
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct Config {
    pub consumer_key: String,
    pub consumer_secret: String,
    pub access_key: String,
    pub access_secret: String
}

impl Config {
    pub fn read() -> Option<Config> {
        let path = Path::new(PATH);
        let mut file = match File::open(&path) {
            Ok(f) => f,
            Err(_) => return None
        };
        let conf = Json::from_reader(&mut file).unwrap();
        Decodable::decode(&mut json::Decoder::new(conf)).ok()
    }

    pub fn write(&self) {
        let path = Path::new(PATH);
        let mut file = match OpenOptions::new().write(true).open(&path) {
            Ok(f) => f,
            Err(e) => panic!("{}", e)
        };
        let _ = write!(&mut file, "{}\n", &json::encode(self).unwrap());
    }
}

fn console_input(prompt: &str) -> String {
    print!("{}\n\t", prompt);
    let mut line = String::new();
    let _ = io::stdin().read_line(&mut line).unwrap();
    line.trim().to_string()
}

fn main() {
    let conf = match Config::read() {
        Some(c) => c,
        None => {
            let consumer_key    = console_input("input your consumer key:");
            let consumer_secret = console_input("input your consumer secret:");
            let consumer = Token::new(consumer_key, consumer_secret);

            let request = twitter::get_request_token(&consumer);
            println!("open the following url:");
            println!("\t{}", twitter::get_authorize_url(&request));
            let pin = console_input("input pin:");
            let access = twitter::get_access_token(&consumer, &request, &pin);

            let c = Config {
                consumer_key: consumer.key.to_string(),
                consumer_secret: consumer.secret.to_string(),
                access_key: access.key.to_string(),
                access_secret: access.secret.to_string()
            };
            c.write();
            c
        }
    };

    let consumer = Token::new(conf.consumer_key, conf.consumer_secret);
    let access = Token::new(conf.access_key, conf.access_secret);

    let status = console_input("What's happening?");
    twitter::tweet(&consumer, &access, &status);
}

<commit_msg>examples/tweet.rs : read() takes now the path of the twitter file conf as parameter<commit_after>#![warn(bad_style,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results)]

extern crate twitter_api as twitter;
extern crate rustc_serialize as rustc_serialize;
extern crate oauth_client as oauth;

use std::io;
use std::io::prelude::*;
use std::env;
use std::fs::{File, OpenOptions};
use std::path::Path;
use std::path::PathBuf;
use rustc_serialize::Decodable;
use rustc_serialize::json::{self, Json};
use oauth::Token;

const TWITTER_CONF_FILENAME: &'static str = ".twitter.conf";

fn get_home_dir() -> PathBuf{
    match env::home_dir() {
        Some(p) => p,
        None => {
            panic!("Impossible to get your home dir!");
        }
    }
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct Config {
    pub consumer_key: String,
    pub consumer_secret: String,
    pub access_key: String,
    pub access_secret: String
}

impl Config {
    pub fn read(path_file : &Path) -> Option<Config> {
        let mut file = match File::open(path_file) {
            Ok(f) => f,
            Err(_) => return None
        };
        let conf = Json::from_reader(&mut file).unwrap();
        Decodable::decode(&mut json::Decoder::new(conf)).ok()
    }

    pub fn write(&self) {
        let path = Path::new(PATH);
        let mut file = match OpenOptions::new().write(true).open(&path) {
            Ok(f) => f,
            Err(e) => panic!("{}", e)
        };
        let _ = write!(&mut file, "{}\n", &json::encode(self).unwrap());
    }
}

fn console_input(prompt: &str) -> String {
    print!("{}\n\t", prompt);
    let mut line = String::new();
    let _ = io::stdin().read_line(&mut line).unwrap();
    line.trim().to_string()
}

fn main() {
    let conf = match Config::read() {
        Some(c) => c,
        None => {
            let consumer_key    = console_input("input your consumer key:");
            let consumer_secret = console_input("input your consumer secret:");
            let consumer = Token::new(consumer_key, consumer_secret);

            let request = twitter::get_request_token(&consumer);
            println!("open the following url:");
            println!("\t{}", twitter::get_authorize_url(&request));
            let pin = console_input("input pin:");
            let access = twitter::get_access_token(&consumer, &request, &pin);

            let c = Config {
                consumer_key: consumer.key.to_string(),
                consumer_secret: consumer.secret.to_string(),
                access_key: access.key.to_string(),
                access_secret: access.secret.to_string()
            };
            c.write();
            c
        }
    };

    let consumer = Token::new(conf.consumer_key, conf.consumer_secret);
    let access = Token::new(conf.access_key, conf.access_secret);

    let status = console_input("What's happening?");
    twitter::tweet(&consumer, &access, &status);
}

<|endoftext|>


<commit_before>// Copyright 2015-2016, 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>

//! `IMPL` The `glib_wrapper!` macro and miscellaneous wrapper traits.

/// Defines a wrapper type and implements the appropriate traits.
///
/// The basic syntax is
///
/// ```ignore
/// glib_wrapper! {
///     /// Documentation
///     pub struct $name($kind<$foreign>);
///
///     match fn {
///         $fn_name => /* a closure-like expression */,
///         ...
///     }
/// }
/// ```
///
/// This creates a wrapper named `$name` around the foreign type `$foreign`
/// of `$kind` (one of `Boxed`, `Shared`, `Object`) using expressions from the `match fn`
/// block to implement type-specific low-level operations (the expression
/// will be evaluated in `unsafe` context).
///
/// ### Boxed
///
/// Boxed records with single ownership.
///
/// ```ignore
/// glib_wrapper! {
///     /// Text buffer iterator
///     pub struct TextIter(Boxed<ffi::GtkTextIter>);
///
///     match fn {
///         copy => |ptr| ffi::gtk_text_iter_copy(ptr),
///         free => |ptr| ffi::gtk_text_iter_free(ptr),
///     }
/// }
/// ```
///
/// `copy`: `|*const $foreign| -> *mut $foreign` creates a copy of the value.
///
/// `free`: `|*mut $foreign|` frees the value.
///
/// ### Shared
///
/// Records with reference counted shared ownership.
///
/// ```ignore
/// glib_wrapper! {
///     /// Object holding timing information for a single frame.
///     pub struct FrameTimings(Shared<ffi::GdkFrameTimings>);
///
///     match fn {
///         ref => |ptr| ffi::gdk_frame_timings_ref(ptr),
///         unref => |ptr| ffi::gdk_frame_timings_unref(ptr),
///     }
/// }
/// ```
///
/// `ref`: `|*mut $foreign|` increases the refcount.
///
/// `unref`: `|*mut $foreign|` decreases the refcount.
///
/// ### Object
///
/// Objects -- classes and interfaces.
///
/// ```ignore
/// glib_wrapper! {
///     /// Object representing an input device.
///     pub struct Device(Object<ffi::GdkDevice>);
///
///     match fn {
///         get_type => || ffi::gdk_device_get_type(),
///     }
/// }
/// ```
///
/// ```ignore
/// glib_wrapper! {
///     /// A container with just one child.
///     pub struct Bin(Object<ffi::GtkBin>): Container, Widget, Buildable;
///
///     match fn {
///         get_type => || ffi::gtk_bin_get_type(),
///     }
/// }
/// ```
///
/// Implementing types from other crates requires specifying their FFI
/// counterparts as well:
///
/// ```ignore
/// glib_wrapper! {
///     pub struct Application(Object<ffi::GtkApplication>): [
///         gio::Application => gio_ffi::GApplication,
///         gio::ActionGroup => gio_ffi::GActionGroup,
///         gio::ActionMap => gio_ffi::GActionMap,
///     ];
///
///     match fn {
///         get_type => || ffi::gtk_application_get_type(),
///     }
/// }
/// ```
///
/// `get_type: || -> GType` returns the type identifier of the class or interface.
#[macro_export]
macro_rules! glib_wrapper {
    (
        $(#[$attr:meta])*
        pub struct $name:ident(Boxed<$ffi_name:path>);

        match fn {
            copy => |$copy_arg:ident| $copy_expr:expr,
            free => |$free_arg:ident| $free_expr:expr,
        }
    ) => {
        glib_boxed_wrapper!([$($attr)*] $name, $ffi_name, @copy $copy_arg $copy_expr,
            @free $free_arg $free_expr);
    };

    // Same as Shared, to be removed
    (
        $(#[$attr:meta])*
        pub struct $name:ident(Refcounted<$ffi_name:path>);

        match fn {
            ref => |$ref_arg:ident| $ref_expr:expr,
            unref => |$unref_arg:ident| $unref_expr:expr,
        }
    ) => {
        glib_shared_wrapper!([$($attr)*] $name, $ffi_name, @ref $ref_arg $ref_expr,
            @unref $unref_arg $unref_expr);
    };

    (
        $(#[$attr:meta])*
        pub struct $name:ident(Shared<$ffi_name:path>);

        match fn {
            ref => |$ref_arg:ident| $ref_expr:expr,
            unref => |$unref_arg:ident| $unref_expr:expr,
        }
    ) => {
        glib_shared_wrapper!([$($attr)*] $name, $ffi_name, @ref $ref_arg $ref_expr,
            @unref $unref_arg $unref_expr);
    };

    (
        $(#[$attr:meta])*
        pub struct $name:ident(Object<$ffi_name:path>);

        match fn {
            get_type => || $get_type_expr:expr,
        }
    ) => {
        glib_object_wrapper!([$($attr)*] $name, $ffi_name, @get_type $get_type_expr, []);
    };

    (
        $(#[$attr:meta])*
        pub struct $name:ident(Object<$ffi_name:path>): [$($implements:tt)+];

        match fn {
            get_type => || $get_type_expr:expr,
        }
    ) => {
        glib_object_wrapper!([$($attr)*] $name, $ffi_name, @get_type $get_type_expr,
            @implements $($implements)+);
    };

    (
        $(#[$attr:meta])*
        pub struct $name:ident(Object<$ffi_name:path>): $($implements:path),+;

        match fn {
            get_type => || $get_type_expr:expr,
        }
    ) => {
        glib_object_wrapper!([$($attr)*] $name, $ffi_name, @get_type $get_type_expr,
            [$($implements),+]);
    };
}

/// A wrapper struct.
pub trait Wrapper {
    /// Foreign type represented by the struct.
    type GlibType: 'static;
}

pub trait UnsafeFrom<T> {
    unsafe fn from(t: T) -> Self;
}
<commit_msg>Remove deprecated macro syntax<commit_after>// Copyright 2015-2016, 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>

//! `IMPL` The `glib_wrapper!` macro and miscellaneous wrapper traits.

/// Defines a wrapper type and implements the appropriate traits.
///
/// The basic syntax is
///
/// ```ignore
/// glib_wrapper! {
///     /// Documentation
///     pub struct $name($kind<$foreign>);
///
///     match fn {
///         $fn_name => /* a closure-like expression */,
///         ...
///     }
/// }
/// ```
///
/// This creates a wrapper named `$name` around the foreign type `$foreign`
/// of `$kind` (one of `Boxed`, `Shared`, `Object`) using expressions from the `match fn`
/// block to implement type-specific low-level operations (the expression
/// will be evaluated in `unsafe` context).
///
/// ### Boxed
///
/// Boxed records with single ownership.
///
/// ```ignore
/// glib_wrapper! {
///     /// Text buffer iterator
///     pub struct TextIter(Boxed<ffi::GtkTextIter>);
///
///     match fn {
///         copy => |ptr| ffi::gtk_text_iter_copy(ptr),
///         free => |ptr| ffi::gtk_text_iter_free(ptr),
///     }
/// }
/// ```
///
/// `copy`: `|*const $foreign| -> *mut $foreign` creates a copy of the value.
///
/// `free`: `|*mut $foreign|` frees the value.
///
/// ### Shared
///
/// Records with reference counted shared ownership.
///
/// ```ignore
/// glib_wrapper! {
///     /// Object holding timing information for a single frame.
///     pub struct FrameTimings(Shared<ffi::GdkFrameTimings>);
///
///     match fn {
///         ref => |ptr| ffi::gdk_frame_timings_ref(ptr),
///         unref => |ptr| ffi::gdk_frame_timings_unref(ptr),
///     }
/// }
/// ```
///
/// `ref`: `|*mut $foreign|` increases the refcount.
///
/// `unref`: `|*mut $foreign|` decreases the refcount.
///
/// ### Object
///
/// Objects -- classes and interfaces.
///
/// ```ignore
/// glib_wrapper! {
///     /// Object representing an input device.
///     pub struct Device(Object<ffi::GdkDevice>);
///
///     match fn {
///         get_type => || ffi::gdk_device_get_type(),
///     }
/// }
/// ```
///
/// ```ignore
/// glib_wrapper! {
///     /// A container with just one child.
///     pub struct Bin(Object<ffi::GtkBin>): Container, Widget, Buildable;
///
///     match fn {
///         get_type => || ffi::gtk_bin_get_type(),
///     }
/// }
/// ```
///
/// Implementing types from other crates requires specifying their FFI
/// counterparts as well:
///
/// ```ignore
/// glib_wrapper! {
///     pub struct Application(Object<ffi::GtkApplication>): [
///         gio::Application => gio_ffi::GApplication,
///         gio::ActionGroup => gio_ffi::GActionGroup,
///         gio::ActionMap => gio_ffi::GActionMap,
///     ];
///
///     match fn {
///         get_type => || ffi::gtk_application_get_type(),
///     }
/// }
/// ```
///
/// `get_type: || -> GType` returns the type identifier of the class or interface.
#[macro_export]
macro_rules! glib_wrapper {
    (
        $(#[$attr:meta])*
        pub struct $name:ident(Boxed<$ffi_name:path>);

        match fn {
            copy => |$copy_arg:ident| $copy_expr:expr,
            free => |$free_arg:ident| $free_expr:expr,
        }
    ) => {
        glib_boxed_wrapper!([$($attr)*] $name, $ffi_name, @copy $copy_arg $copy_expr,
            @free $free_arg $free_expr);
    };

    (
        $(#[$attr:meta])*
        pub struct $name:ident(Shared<$ffi_name:path>);

        match fn {
            ref => |$ref_arg:ident| $ref_expr:expr,
            unref => |$unref_arg:ident| $unref_expr:expr,
        }
    ) => {
        glib_shared_wrapper!([$($attr)*] $name, $ffi_name, @ref $ref_arg $ref_expr,
            @unref $unref_arg $unref_expr);
    };

    (
        $(#[$attr:meta])*
        pub struct $name:ident(Object<$ffi_name:path>);

        match fn {
            get_type => || $get_type_expr:expr,
        }
    ) => {
        glib_object_wrapper!([$($attr)*] $name, $ffi_name, @get_type $get_type_expr, []);
    };

    (
        $(#[$attr:meta])*
        pub struct $name:ident(Object<$ffi_name:path>): [$($implements:tt)+];

        match fn {
            get_type => || $get_type_expr:expr,
        }
    ) => {
        glib_object_wrapper!([$($attr)*] $name, $ffi_name, @get_type $get_type_expr,
            @implements $($implements)+);
    };

    (
        $(#[$attr:meta])*
        pub struct $name:ident(Object<$ffi_name:path>): $($implements:path),+;

        match fn {
            get_type => || $get_type_expr:expr,
        }
    ) => {
        glib_object_wrapper!([$($attr)*] $name, $ffi_name, @get_type $get_type_expr,
            [$($implements),+]);
    };
}

/// A wrapper struct.
pub trait Wrapper {
    /// Foreign type represented by the struct.
    type GlibType: 'static;
}

pub trait UnsafeFrom<T> {
    unsafe fn from(t: T) -> Self;
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate nom;
extern crate macho;

use std::env;
use std::fs;
use std::io::Read;

fn main() {
    let args: Vec<_> = env::args().collect();
    if args.len() != 2 {
        println!("Usage: {} <file>", args[0]);
        return;
    }

    let mut fh = fs::File::open(&args[1]).unwrap();
    let mut buf: Vec<u8> = Vec::new();
    let _ = fh.read_to_end(&mut buf);

    match macho::MachHeader::parse(&buf[..]) {
        Some(header) => {
            println!("{:?}", header);
        },
        None => {
            panic!("Error parsing header")
        }

    }
}
<commit_msg>Pretty print from reader<commit_after>#[macro_use]
extern crate nom;
extern crate macho;

use std::env;
use std::fs;
use std::io::Read;

fn main() {
    let args: Vec<_> = env::args().collect();
    if args.len() != 2 {
        println!("Usage: {} <file>", args[0]);
        return;
    }

    let mut fh = fs::File::open(&args[1]).unwrap();
    let mut buf: Vec<u8> = Vec::new();
    let _ = fh.read_to_end(&mut buf);

    match macho::MachHeader::parse(&buf[..]) {
        Some(header) => {
            println!("{:#?}", header);
        },
        None => {
            panic!("Error parsing header")
        }

    }
}
<|endoftext|>


<commit_before>//! The public FFI functions for initializing, adding sinks to, and applying a logger.

use std::convert::TryFrom;
use std::ffi::{CStr, CString};
use std::ptr;
use std::str::from_utf8;

use fern::Dispatch;
use libc::{c_char, c_int};
use log::{error, LevelFilter as LogLevelFilter};

use pact_matching::logging::fetch_buffer_contents;

use crate::error::set_error_msg;
use crate::log::level_filter::LevelFilter;
use crate::log::logger::{add_sink, apply_logger, set_logger};
use crate::log::sink::Sink;
use crate::log::status::Status;
use crate::util::string::to_c;

/// Convenience function to direct all logging to stdout.
#[no_mangle]
pub extern "C" fn pactffi_log_to_stdout(level_filter: LevelFilter) -> c_int {
    pactffi_logger_init();

    let spec = match CString::new("stdout") {
        Ok(spec) => spec,
        Err(e) => {
            set_error_msg(e.to_string());
            return Status::CantConstructSink as c_int;
        }
    };

    let status = pactffi_logger_attach_sink(spec.as_ptr(), level_filter);
    if status != 0 {
        return status;
    }

    let status = pactffi_logger_apply();
    if status != 0 {
        return status;
    }

    Status::Success as c_int
}

/// Convenience function to direct all logging to stderr.
#[no_mangle]
pub extern "C" fn pactffi_log_to_stderr(level_filter: LevelFilter) -> c_int {
    pactffi_logger_init();

    let spec = match CString::new("stderr") {
        Ok(spec) => spec,
        Err(e) => {
            set_error_msg(e.to_string());
            return Status::CantConstructSink as c_int;
        }
    };

    let status = pactffi_logger_attach_sink(spec.as_ptr(), level_filter);
    if status != 0 {
        return status;
    }

    let status = pactffi_logger_apply();
    if status != 0 {
        return status;
    }

    Status::Success as c_int
}

/// Convenience function to direct all logging to a file.
///
/// # Safety
/// This function will fail if the file_name pointer is invalid or does not point to a NULL
/// terminated string.
#[no_mangle]
pub unsafe extern "C" fn pactffi_log_to_file(
    file_name: *const c_char,
    level_filter: LevelFilter,
) -> c_int {
    pactffi_logger_init();

    let spec = {
        if file_name.is_null() {
            return Status::CantConstructSink as c_int;
        }

        let file_name =
            match CStr::from_ptr(file_name).to_str() {
                Ok(file_name) => file_name,
                Err(e) => {
                    set_error_msg(e.to_string());
                    return Status::CantConstructSink as c_int;
                }
            };

        let spec = format!("file {}", file_name);

        match CString::new(spec) {
            Ok(spec) => spec,
            Err(e) => {
                set_error_msg(e.to_string());
                return Status::CantConstructSink as c_int;
            }
        }
    };

    let status = pactffi_logger_attach_sink(spec.as_ptr(), level_filter);
    if status != 0 {
        return status;
    }

    let status = pactffi_logger_apply();
    if status != 0 {
        return status;
    }

    Status::Success as c_int
}

/// Convenience function to direct all logging to a thread local memory buffer.
#[no_mangle]
pub extern "C" fn pactffi_log_to_buffer(level_filter: LevelFilter) -> c_int {
  pactffi_logger_init();

  let spec = match CString::new("buffer") {
    Ok(spec) => spec,
    Err(e) => {
      set_error_msg(e.to_string());
      return Status::CantConstructSink as c_int;
    }
  };

  let status = pactffi_logger_attach_sink(spec.as_ptr(), level_filter);
  if status != 0 {
    return status;
  }

  let status = pactffi_logger_apply();
  if status != 0 {
    return status;
  }

  Status::Success as c_int
}

// C API uses something like the pledge API to select write locations, including:
//
// * stdout (`pactffi_logger_attach_sink("stdout", LevelFilter_Info)`)
// * stderr (`pactffi_logger_attach_sink("stderr", LevelFilter_Debug)`)
// * file w/ file path (`pactffi_logger_attach_sink("file /some/file/path", LevelFilter_Trace)`)
//
// The general flow is:
//
// 1. Call `pactffi_logger_init` to create a `Dispatch` struct.
// 2. Call `pactffi_logger_attach_sink` to add an additional sink, using bitflags to set the metadata.
// 3. Call `pactffi_logger_apply` to finalize the logger and enable logging to the configured sinks.
//
// Once `pactffi_logger_apply` has been called, any additional calls to `logger_attach_sink` will fail
// with an error indicating the logger has been applied already.
//
// ```
// pactffi_logger_init();
//
// int result = pactffi_logger_attach_sink("stderr", FilterLevel_Debug);
// /* handle the error */
//
// int result = pactffi_logger_attach_sink("file /some/file/path", FilterLevel_Info);
// /* handle the error */
//
// int result = pactffi_logger_apply();
// /* handle the error */
// ```

/// Initialize the thread-local logger with no sinks.
///
/// This initialized logger does nothing until `pactffi_logger_apply` has been called.
///
/// # Usage
///
/// ```c
/// pactffi_logger_init();
/// ```
///
/// # Safety
///
/// This function is always safe to call.
#[no_mangle]
pub extern "C" fn pactffi_logger_init() {
  set_logger(Dispatch::new());
}

/// Attach an additional sink to the thread-local logger.
///
/// This logger does nothing until `pactffi_logger_apply` has been called.
///
/// Three types of sinks can be specified:
///
/// - stdout (`pactffi_logger_attach_sink("stdout", LevelFilter_Info)`)
/// - stderr (`pactffi_logger_attach_sink("stderr", LevelFilter_Debug)`)
/// - file w/ file path (`pactffi_logger_attach_sink("file /some/file/path", LevelFilter_Trace)`)
/// - buffer (`pactffi_logger_attach_sink("buffer", LevelFilter_Debug)`)
///
/// # Usage
///
/// ```c
/// int result = pactffi_logger_attach_sink("file /some/file/path", LogLevel_Filter);
/// ```
///
/// # Error Handling
///
/// The return error codes are as follows:
///
/// - `-1`: Can't set logger (applying the logger failed, perhaps because one is applied already).
/// - `-2`: No logger has been initialized (call `pactffi_logger_init` before any other log function).
/// - `-3`: The sink specifier was not UTF-8 encoded.
/// - `-4`: The sink type specified is not a known type (known types: "stdout", "stderr", or "file /some/path").
/// - `-5`: No file path was specified in a file-type sink specification.
/// - `-6`: Opening a sink to the specified file path failed (check permissions).
///
/// # Safety
///
/// This function checks the validity of the passed-in sink specifier, and errors
/// out if the specifier isn't valid UTF-8.
#[allow(clippy::missing_safety_doc)]
#[allow(clippy::not_unsafe_ptr_arg_deref)]
#[no_mangle]
pub extern "C" fn pactffi_logger_attach_sink(
    sink_specifier: *const c_char,
    level_filter: LevelFilter,
) -> c_int {
    // Get the specifier from the raw C string.
    let sink_specifier = unsafe { CStr::from_ptr(sink_specifier) };
    let sink_specifier = match sink_specifier.to_str() {
        Ok(sink_specifier) => sink_specifier,
        // TODO: Permit non-UTF8 strings, as some filesystems may have non-UTF8
        //       paths to which the user wants to direct the logging output.
        Err(_) => return Status::SpecifierNotUtf8 as c_int,
    };

    // Attempt to construct a sink from the specifier.
    let sink = match Sink::try_from(sink_specifier) {
        Ok(sink) => sink,
        Err(err) => return Status::from(err) as c_int,
    };

    // Convert from our `#[repr(C)]` LevelFilter to the one from the `log` crate.
    let level_filter: LogLevelFilter = level_filter.into();

    // Construct a dispatcher from the sink and level filter.
    let dispatch = Into::<Dispatch>::into(sink)
        .level(level_filter)
        .format(|out, message, record| {
            out.finish(format_args!(
                "[{}][{}] {}",
                record.level(),
                record.target(),
                message
            ))
        });

    // Take the existing logger, if there is one, add a new sink to it, and put it back.
    let status = match add_sink(dispatch) {
        Ok(_) => Status::Success,
        Err(err) => Status::from(err),
    };

    status as c_int
}

/// Apply the thread-local logger to the program.
///
/// Any attempts to modify the logger after the call to `logger_apply` will fail.
#[no_mangle]
pub extern "C" fn pactffi_logger_apply() -> c_int {
    let status = match apply_logger() {
        Ok(_) => Status::Success,
        Err(err) => Status::from(err),
    };

    status as c_int
}

/// Fetch the in-memory logger buffer contents. This will only have any contents if the `buffer`
/// sink has been configured to log to. The contents will be allocated on the heap and will need
/// to be freed with `string_delete`.
///
/// Fetches the logs associated with the provided identifier, or uses the "global" one if the
/// identifier is not specified (i.e. NULL).
///
/// Returns a NULL pointer if the buffer can't be fetched. This can occur is there is not
/// sufficient memory to make a copy of the contents or the buffer contains non-UTF-8 characters.
///
/// # Safety
///
/// This function will fail if the log_id pointer is invalid or does not point to a NULL
/// terminated string.
#[no_mangle]
pub unsafe extern "C" fn pactffi_fetch_log_buffer(log_id: *const c_char,) -> *const c_char {
  let id = if log_id.is_null() {
    "global"
  } else {
    CStr::from_ptr(log_id).to_str().unwrap_or("global")
  };
  match from_utf8(&fetch_buffer_contents(&id.to_string())) {
    Ok(contents) => match to_c(contents) {
      Ok(c_str) => c_str,
      Err(err) => {
        error!("Failed to copy in-memory log buffer - {}", err);
        ptr::null()
      }
    }
    Err(err) => {
      error!("Failed to convert in-memory log buffer to UTF-8 = {}", err);
      ptr::null()
    }
  }
}
<commit_msg>chore: mark pactffi_logger_attach_sink as unsafe #148<commit_after>//! The public FFI functions for initializing, adding sinks to, and applying a logger.

use std::convert::TryFrom;
use std::ffi::{CStr, CString};
use std::ptr;
use std::str::from_utf8;

use fern::Dispatch;
use libc::{c_char, c_int};
use log::{error, LevelFilter as LogLevelFilter};

use pact_matching::logging::fetch_buffer_contents;

use crate::error::set_error_msg;
use crate::log::level_filter::LevelFilter;
use crate::log::logger::{add_sink, apply_logger, set_logger};
use crate::log::sink::Sink;
use crate::log::status::Status;
use crate::util::string::to_c;

/// Convenience function to direct all logging to stdout.
#[no_mangle]
pub extern "C" fn pactffi_log_to_stdout(level_filter: LevelFilter) -> c_int {
    pactffi_logger_init();

    let spec = match CString::new("stdout") {
        Ok(spec) => spec,
        Err(e) => {
            set_error_msg(e.to_string());
            return Status::CantConstructSink as c_int;
        }
    };

    let status = unsafe { pactffi_logger_attach_sink(spec.as_ptr(), level_filter) };
    if status != 0 {
        return status;
    }

    let status = pactffi_logger_apply();
    if status != 0 {
        return status;
    }

    Status::Success as c_int
}

/// Convenience function to direct all logging to stderr.
#[no_mangle]
pub extern "C" fn pactffi_log_to_stderr(level_filter: LevelFilter) -> c_int {
    pactffi_logger_init();

    let spec = match CString::new("stderr") {
        Ok(spec) => spec,
        Err(e) => {
            set_error_msg(e.to_string());
            return Status::CantConstructSink as c_int;
        }
    };

    let status = unsafe { pactffi_logger_attach_sink(spec.as_ptr(), level_filter) };
    if status != 0 {
        return status;
    }

    let status = pactffi_logger_apply();
    if status != 0 {
        return status;
    }

    Status::Success as c_int
}

/// Convenience function to direct all logging to a file.
///
/// # Safety
/// This function will fail if the file_name pointer is invalid or does not point to a NULL
/// terminated string.
#[no_mangle]
pub unsafe extern "C" fn pactffi_log_to_file(
    file_name: *const c_char,
    level_filter: LevelFilter,
) -> c_int {
    pactffi_logger_init();

    let spec = {
        if file_name.is_null() {
            return Status::CantConstructSink as c_int;
        }

        let file_name =
            match CStr::from_ptr(file_name).to_str() {
                Ok(file_name) => file_name,
                Err(e) => {
                    set_error_msg(e.to_string());
                    return Status::CantConstructSink as c_int;
                }
            };

        let spec = format!("file {}", file_name);

        match CString::new(spec) {
            Ok(spec) => spec,
            Err(e) => {
                set_error_msg(e.to_string());
                return Status::CantConstructSink as c_int;
            }
        }
    };

    let status = pactffi_logger_attach_sink(spec.as_ptr(), level_filter);
    if status != 0 {
        return status;
    }

    let status = pactffi_logger_apply();
    if status != 0 {
        return status;
    }

    Status::Success as c_int
}

/// Convenience function to direct all logging to a thread local memory buffer.
#[no_mangle]
pub extern "C" fn pactffi_log_to_buffer(level_filter: LevelFilter) -> c_int {
  pactffi_logger_init();

  let spec = match CString::new("buffer") {
    Ok(spec) => spec,
    Err(e) => {
      set_error_msg(e.to_string());
      return Status::CantConstructSink as c_int;
    }
  };

  let status = unsafe { pactffi_logger_attach_sink(spec.as_ptr(), level_filter) };
  if status != 0 {
    return status;
  }

  let status = pactffi_logger_apply();
  if status != 0 {
    return status;
  }

  Status::Success as c_int
}

// C API uses something like the pledge API to select write locations, including:
//
// * stdout (`pactffi_logger_attach_sink("stdout", LevelFilter_Info)`)
// * stderr (`pactffi_logger_attach_sink("stderr", LevelFilter_Debug)`)
// * file w/ file path (`pactffi_logger_attach_sink("file /some/file/path", LevelFilter_Trace)`)
//
// The general flow is:
//
// 1. Call `pactffi_logger_init` to create a `Dispatch` struct.
// 2. Call `pactffi_logger_attach_sink` to add an additional sink, using bitflags to set the metadata.
// 3. Call `pactffi_logger_apply` to finalize the logger and enable logging to the configured sinks.
//
// Once `pactffi_logger_apply` has been called, any additional calls to `logger_attach_sink` will fail
// with an error indicating the logger has been applied already.
//
// ```
// pactffi_logger_init();
//
// int result = pactffi_logger_attach_sink("stderr", FilterLevel_Debug);
// /* handle the error */
//
// int result = pactffi_logger_attach_sink("file /some/file/path", FilterLevel_Info);
// /* handle the error */
//
// int result = pactffi_logger_apply();
// /* handle the error */
// ```

/// Initialize the thread-local logger with no sinks.
///
/// This initialized logger does nothing until `pactffi_logger_apply` has been called.
///
/// # Usage
///
/// ```c
/// pactffi_logger_init();
/// ```
///
/// # Safety
///
/// This function is always safe to call.
#[no_mangle]
pub extern "C" fn pactffi_logger_init() {
  set_logger(Dispatch::new());
}

/// Attach an additional sink to the thread-local logger.
///
/// This logger does nothing until `pactffi_logger_apply` has been called.
///
/// Three types of sinks can be specified:
///
/// - stdout (`pactffi_logger_attach_sink("stdout", LevelFilter_Info)`)
/// - stderr (`pactffi_logger_attach_sink("stderr", LevelFilter_Debug)`)
/// - file w/ file path (`pactffi_logger_attach_sink("file /some/file/path", LevelFilter_Trace)`)
/// - buffer (`pactffi_logger_attach_sink("buffer", LevelFilter_Debug)`)
///
/// # Usage
///
/// ```c
/// int result = pactffi_logger_attach_sink("file /some/file/path", LogLevel_Filter);
/// ```
///
/// # Error Handling
///
/// The return error codes are as follows:
///
/// - `-1`: Can't set logger (applying the logger failed, perhaps because one is applied already).
/// - `-2`: No logger has been initialized (call `pactffi_logger_init` before any other log function).
/// - `-3`: The sink specifier was not UTF-8 encoded.
/// - `-4`: The sink type specified is not a known type (known types: "stdout", "stderr", or "file /some/path").
/// - `-5`: No file path was specified in a file-type sink specification.
/// - `-6`: Opening a sink to the specified file path failed (check permissions).
///
/// # Safety
///
/// This function checks the validity of the passed-in sink specifier, and errors
/// out if the specifier isn't valid UTF-8.
#[allow(clippy::missing_safety_doc)]
#[allow(clippy::not_unsafe_ptr_arg_deref)]
#[no_mangle]
pub unsafe extern "C" fn pactffi_logger_attach_sink(
    sink_specifier: *const c_char,
    level_filter: LevelFilter,
) -> c_int {
    // Get the specifier from the raw C string.
    let sink_specifier = CStr::from_ptr(sink_specifier);
    let sink_specifier = match sink_specifier.to_str() {
        Ok(sink_specifier) => sink_specifier,
        // TODO: Permit non-UTF8 strings, as some filesystems may have non-UTF8
        //       paths to which the user wants to direct the logging output.
        Err(_) => return Status::SpecifierNotUtf8 as c_int,
    };

    // Attempt to construct a sink from the specifier.
    let sink = match Sink::try_from(sink_specifier) {
        Ok(sink) => sink,
        Err(err) => return Status::from(err) as c_int,
    };

    // Convert from our `#[repr(C)]` LevelFilter to the one from the `log` crate.
    let level_filter: LogLevelFilter = level_filter.into();

    // Construct a dispatcher from the sink and level filter.
    let dispatch = Into::<Dispatch>::into(sink)
        .level(level_filter)
        .format(|out, message, record| {
            out.finish(format_args!(
                "[{}][{}] {}",
                record.level(),
                record.target(),
                message
            ))
        });

    // Take the existing logger, if there is one, add a new sink to it, and put it back.
    let status = match add_sink(dispatch) {
        Ok(_) => Status::Success,
        Err(err) => Status::from(err),
    };

    status as c_int
}

/// Apply the thread-local logger to the program.
///
/// Any attempts to modify the logger after the call to `logger_apply` will fail.
#[no_mangle]
pub extern "C" fn pactffi_logger_apply() -> c_int {
    let status = match apply_logger() {
        Ok(_) => Status::Success,
        Err(err) => Status::from(err),
    };

    status as c_int
}

/// Fetch the in-memory logger buffer contents. This will only have any contents if the `buffer`
/// sink has been configured to log to. The contents will be allocated on the heap and will need
/// to be freed with `string_delete`.
///
/// Fetches the logs associated with the provided identifier, or uses the "global" one if the
/// identifier is not specified (i.e. NULL).
///
/// Returns a NULL pointer if the buffer can't be fetched. This can occur is there is not
/// sufficient memory to make a copy of the contents or the buffer contains non-UTF-8 characters.
///
/// # Safety
///
/// This function will fail if the log_id pointer is invalid or does not point to a NULL
/// terminated string.
#[no_mangle]
pub unsafe extern "C" fn pactffi_fetch_log_buffer(log_id: *const c_char,) -> *const c_char {
  let id = if log_id.is_null() {
    "global"
  } else {
    CStr::from_ptr(log_id).to_str().unwrap_or("global")
  };
  match from_utf8(&fetch_buffer_contents(&id.to_string())) {
    Ok(contents) => match to_c(contents) {
      Ok(c_str) => c_str,
      Err(err) => {
        error!("Failed to copy in-memory log buffer - {}", err);
        ptr::null()
      }
    }
    Err(err) => {
      error!("Failed to convert in-memory log buffer to UTF-8 = {}", err);
      ptr::null()
    }
  }
}
<|endoftext|>


<commit_before>/// Problem 54
/// In the card game poker, a hand consists of five cards and are ranked, from
/// lowest to highest, in the following way:
///
/// * High Card: Highest value card.
/// * One Pair: Two cards of the same value.
/// * Two Pairs: Two different pairs.
/// * Three of a Kind: Three cards of the same value.
/// * Straight: All cards are consecutive values.
/// * Flush: All cards of the same suit.
/// * Full House: Three of a kind and a pair.
/// * Four of a Kind: Four cards of the same value.
/// * Straight Flush: All cards are consecutive values of same suit.
/// * Royal Flush: Ten, Jack, Queen, King, Ace, in same suit.
///
/// The cards are valued in the order:
/// 2, 3, 4, 5, 6, 7, 8, 9, 10, Jack, Queen, King, Ace.
///
/// If two players have the same ranked hands then the rank made up of the
/// highest value wins; for example, a pair of eights beats a pair of fives
/// (see example 1 below). But if two ranks tie, for example, both players have
/// a pair of queens, then highest cards in each hand are compared (see example
/// 4 below); if the highest cards tie then the next highest cards are compared,
/// and so on.
///
/// Consider the following five hands dealt to two players:
///
/// Hand  Player 1           Player 2             Winner
/// ----  --------           --------             ------
/// 1     5H 5C 6S 7S KD     2C 3S 8S 8D TD       Player 2
///       Pair of Fives      Pair of Eights
///
/// 2     5D 8C 9S JS AC     2C 5C 7D 8S QH       Player 1
///       Highest card Ace   Highest card Queen
///
/// 3     2D 9C AS AH AC     3D 6D 7D TD QD       Player 2
///       Three Aces         Flush with Diamonds
///
/// 4     4D 6S 9H QH QC     3D 6D 7H QD QS       Player 1
///       Pair of Queens     Pair of Queens
///       Highest card Nine  Highest card Seven
///
/// 5     2H 2D 4C 4D 4S     3C 3D 3S 9S 9D       Player 1
///       Full House         Full House
///       With Three Fours   with Three Threes
///
/// The file, poker.txt, contains one-thousand random hands dealt to two
/// players. Each line of the file contains ten cards (separated by a single
/// space): the first five are Player 1's cards and the last five are Player 2's
/// cards. You can assume that all hands are valid (no invalid characters or
/// repeated cards), each player's hand is in no specific order, and in each
/// hand there is a clear winner.
///
/// How many hands does Player 1 win?
fn main() {

}
<commit_msg>Updates to Rust Problem 54<commit_after>/// Problem 54
/// In the card game poker, a hand consists of five cards and are ranked, from
/// lowest to highest, in the following way:
///
/// * High Card: Highest value card.
/// * One Pair: Two cards of the same value.
/// * Two Pairs: Two different pairs.
/// * Three of a Kind: Three cards of the same value.
/// * Straight: All cards are consecutive values.
/// * Flush: All cards of the same suit.
/// * Full House: Three of a kind and a pair.
/// * Four of a Kind: Four cards of the same value.
/// * Straight Flush: All cards are consecutive values of same suit.
/// * Royal Flush: Ten, Jack, Queen, King, Ace, in same suit.
///
/// The cards are valued in the order:
/// 2, 3, 4, 5, 6, 7, 8, 9, 10, Jack, Queen, King, Ace.
///
/// If two players have the same ranked hands then the rank made up of the
/// highest value wins; for example, a pair of eights beats a pair of fives
/// (see example 1 below). But if two ranks tie, for example, both players have
/// a pair of queens, then highest cards in each hand are compared (see example
/// 4 below); if the highest cards tie then the next highest cards are compared,
/// and so on.
///
/// Consider the following five hands dealt to two players:
///
/// Hand  Player 1           Player 2             Winner
/// ----  --------           --------             ------
/// 1     5H 5C 6S 7S KD     2C 3S 8S 8D TD       Player 2
///       Pair of Fives      Pair of Eights
///
/// 2     5D 8C 9S JS AC     2C 5C 7D 8S QH       Player 1
///       Highest card Ace   Highest card Queen
///
/// 3     2D 9C AS AH AC     3D 6D 7D TD QD       Player 2
///       Three Aces         Flush with Diamonds
///
/// 4     4D 6S 9H QH QC     3D 6D 7H QD QS       Player 1
///       Pair of Queens     Pair of Queens
///       Highest card Nine  Highest card Seven
///
/// 5     2H 2D 4C 4D 4S     3C 3D 3S 9S 9D       Player 1
///       Full House         Full House
///       With Three Fours   with Three Threes
///
/// The file, poker.txt, contains one-thousand random hands dealt to two
/// players. Each line of the file contains ten cards (separated by a single
/// space): the first five are Player 1's cards and the last five are Player 2's
/// cards. You can assume that all hands are valid (no invalid characters or
/// repeated cards), each player's hand is in no specific order, and in each
/// hand there is a clear winner.
///
/// How many hands does Player 1 win?
fn main() {
    let data: String = "\
        5H 5C 6S 6S KD 2C 2S 8S 8D TD\n\
        5H 5C 6S 7S KD 2C 3S 8S 8D TD\n\
        5D 8C 9S JS AC 2C 5C 7D 8S QH\n\
        2D 9C AS AH AC 3D 6D 7D TD QD\n\
        4D 6S 9H QH QC 3D 6D 7H QD QS\n\
        TD JS QH KH AC 3D 6D 7D QD QD\n\
        TD JD QD KD AD 3D 4D 5D 6D 7D\n\
        4D 4S 4H 4H AC 3D 3D 3D QD QD\n\
        2H 2D 4C 4D 4S 3C 3D 3S 9S 9D\n".to_string();

    let mut wins: Vec<u32> = vec![0, 0];

    for row in data.lines() {
        let mut hands: Vec<Vec<(u8,u8)>> = Vec::new();
        hands.push(Vec::new());
        hands.push(Vec::new());
        for cardstr in row.split(' ') {
            let mut card: (u8,u8) = (0,0);
            for (i,s) in cardstr.chars().enumerate() {
                match i {
                    0 => card.0 = match s {
                        '2' => 2,
                        '3' => 3,
                        '4' => 4,
                        '5' => 5,
                        '6' => 6,
                        '7' => 7,
                        '8' => 8,
                        '9' => 9,
                        'T' => 10,
                        'J' => 11,
                        'Q' => 12,
                        'K' => 13,
                        'A' => 14,
                        _ => 0,
                    },
                    1 => card.1 = match s {
                        'D' => 1,
                        'C' => 2,
                        'H' => 3,
                        'S' => 4,
                        _ => 0,
                    },
                    _ => (),
                };
            }
            if hands[0].len() < 5 {
                hands[0].push(card)
            } else {
                hands[1].push(card)
            }
        }
        for hand in &mut hands {
            hand.sort_by_key(|k| k.0);
        }

        println!("P1: {:?} -> {:?} \nP2: {:?} -> {:?}\n",
            hands[0], score(&hands[0]), hands[1], score(&hands[1]));
    }
    println!("Answer: {}", wins[0]);
}

struct HandInfo {
    flush: bool,
    straight: bool,
    pairing: Pairing
}

impl HandInfo {
    fn new(hand: &Vec<(u8,u8)>) -> HandInfo {
        HandInfo {
            flush: is_flush(hand),
            straight: is_straight(hand),
            pairing: hand_pairing(hand)
        }
    }
}

enum Pairing {
    Nothing { rank: Vec<u8> },
    Pair { pair: u8, kickers: Vec<u8> },
    TwoPair { high_pair: u8, low_pair: u8, kicker: u8 },
    Three { high: u8, kickers: Vec<u8> },
    FullHouse { triplet: u8, pair: u8 },
    Four { quad: u8, kicker: u8 },
}

fn hand_pairing(hand: &Vec<(u8,u8)>) -> Pairing {
    let mut counts: Vec<u8> = vec![0; 15];
    for card in hand {
        counts[card.0 as usize] += 1;
    }
    println!("{:?}", counts);
    let max: u8 = *counts.iter().max().unwrap();
    let ind_max: u8 = counts.iter().position(|&x| x == max).unwrap() as u8;
    match max {
        4 => {
            Pairing::Four {
                quad: ind_max,
                kicker: counts.iter().position(|&x| x == 1).unwrap() as u8
            }
        },
        3 => {
            // Look for full house or plain three-of-a-kind
            match counts.iter().position(|&x| x == 2) {
                Some(x) => {
                    Pairing::FullHouse {
                        triplet: ind_max,
                        pair: x as u8
                    }
                },
                None => {
                    Pairing::Three {
                        high: ind_max,
                        kickers: vec![0]
                    }
                }
            }
        },
        2 => {
            // Look for two pair
            let num_two: u8 = counts.iter()
                .filter(|&x| *x == 2)
                .fold(0, |a, _| a + 1) as u8;

            match num_two {
                2 => {
                    Pairing::TwoPair { high_pair: 0, low_pair: 0, kicker: 0 }
                },
                1 => {
                    Pairing::Pair { pair: 0, kickers: vec![0] }
                },
                _ => {
                    Pairing::Nothing { rank: vec![0] }
                }
            }

        },
        1 => {
            let mut r: Vec<u8> = Vec::new();
            for card in hand.iter().rev() {
                r.push(card.0);
            }
            Pairing::Nothing { rank: r }
        },
        _ => Pairing::Nothing { rank: vec![0] }
    }
}

/// Compute a score for a hand, in the form of (rank, high card, breaker).
/// The ranks are as follows:
/// 0 High Card: Highest value card.
/// 1 One Pair: Two cards of the same value.
/// 2 Two Pairs: Two different pairs.
/// 3 Three of a Kind: Three cards of the same value.
/// 4 Straight: All cards are consecutive values.
/// 5 Flush: All cards of the same suit.
/// 6 Full House: Three of a kind and a pair.
/// 7 Four of a Kind: Four cards of the same value.
/// 8 Straight Flush: All cards are consecutive values of same suit.
///   Royal Flush: Ten, Jack, Queen, King, Ace, in same suit.
///
/// Comparing hands of the same rank breaks ties on the high card first and then
/// on the breaker. For instance, the high card of a full house is the
/// three-of-a-kind, and the breaker is the pair.
///
/// Suits count as equal rank, and are not used to break ties.
fn score(hand: &Vec<(u8,u8)>) -> Vec<u8> {
    let info = HandInfo::new(hand);
    if info.straight && info.flush {
        vec![8, hand[4].0]
    } else if info.flush {
        let mut ret: Vec<u8> = vec![5];
        for card in hand.iter().rev() {
            ret.push(card.0);
        }
        ret
    } else if info.straight {
        vec![4, hand[4].0]
    } else {
        match info.pairing {
            Pairing::Four { quad: q, kicker: k } => vec![7, q, k],
            Pairing::FullHouse { triplet: t, pair: p } => vec![6, t, p],
            Pairing::Three { high: h, kickers: k } => {
                let mut v: Vec<u8> = vec![3, h];
                v.extend_from_slice(&k);
                v
            },
            Pairing::TwoPair {
                high_pair: h, low_pair: l, kicker: k
            } => vec![2, h, l, k],
            Pairing::Pair { pair: p, kickers: k } => {
                let mut v: Vec<u8> = vec![1, p];
                v.extend_from_slice(&k);
                v
            },
            Pairing::Nothing { rank: r } => {
                let mut v: Vec<u8> = vec![0];
                // let mut k: Vec<u8> = r;
                // k.reverse();
                v.extend_from_slice(&r);
                v
            },
        }
    }
}

fn is_flush(hand: &Vec<(u8,u8)>) -> bool {
    let last: u8 = hand[0].1;
    for card in hand {
        if card.1 != last {
            return false
        }
    }
    true
}

fn is_straight(hand: &Vec<(u8,u8)>) -> bool {
    for i in 1..hand.len() {
        if hand[i].0 != hand[i-1].0+1 {
            return false
        }
    }
    true
}
<|endoftext|>


<commit_before>use std::io;
use std::io::prelude::*;
use std::fs::File;
use std::fmt;

use self::err::ConfigError;
/* includes the generated code from PEG
	- ${PROJECT_DIR}/targetbuild/ruwm-*out/
*/
// TODO
// This code need some major cleanup

use config_parser::*;

#[allow(dead_code)]
pub mod config_grammar {
	include!(concat!(env!("OUT_DIR"), "/config_grammar.rs"));
}

#[derive(Debug)]
pub struct Parser {
  variables: Variables,
  bindSym:  Vec<Config>,
  exec: Vec<Config>,
  floatingMod: Vec<Config>,
}

impl fmt::Display for Parser {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "Variables: {:?}, \
      bindSym: {:?}, \
      exec: {:?}, \
      floatingMod: {:?}",
      self.variables, self.bindSym, self.exec, self.floatingMod
    )
  }
}

  /*
   * Set up the Parser Struct
   * move ownership of the parsed file from
   * the rust-peg grammar (rust-peg) to my own structures
   */
impl Parser {

  pub fn new(config_file: &str) -> Result<Parser, ConfigError>  {
    let mut f = File::open(config_file)?;

    let mut config = String::new();
    f.read_to_string(&mut config)?;
    let config = config_grammar::content(config.as_ref())?;

    // create data structs for each configuration type
    let mut variables = Variables::new();
    let mut bindSym = Vec::new();
    let mut exec = Vec::new();
    let mut floatingMod = Vec::new();

    for x in config.iter() {
      match *x {
        Config::Set(ref v, ref s) => variables.set(v.to_owned(), s.to_owned())?,
        Config::Exec(ref a) => exec.push(Config::Exec(a.to_owned())),
        Config::BindSym(ref s, ref a) => bindSym.push(Config::BindSym(s.to_owned(),a.to_owned())),
        Config::FloatingMod(ref s) => floatingMod.push(Config::FloatingMod(s.to_owned())),
        _ => {},
      };
    }

    // let result = parse(&mut f)?;
    Ok(Parser {
      variables,
      bindSym,
      exec,
      floatingMod,
    })
  }
}

#[cfg(test)]
#[test]
fn test_grammar() {
  // TODO
  // the fact that the first line must be at the very beginning
  // is not a very big deal, since we can just strip all whitespace until
  // we reach an ascii character
  // but if there is a easy way to fix this in the grammar, then that is the
  // better option
	match config_grammar::content("# A comment
		bindsym LeftGui+1 workspace 1

bindsym $super+$rand exec 'termite --config $HOME/.config/termite/config'
   bindsym RightGui+2 workspace 2 # this is another comment

set $super Ctrl+Mod4
  # This is a comment
set $ws0 '0:emp'
bindsym RightGui+3 workspace $ws0
bindsym Hello+3 workspace 5

bindsym $super+$left focus left
bindsym $super+Ctrl focus down
bindsym $super+$up focus up
bindsym $super+$right focus right
bindsym $super+1 workspace $ws0

exec --no-startup-id 'nm-applet'

set $left h

"){
		Ok(r) => println!("Parsed as: {:?}", r),
		Err(e) => println!("Parse error: {}", e),
	};

}

#[cfg(test)]
#[test]
fn test_parser() {
  let parser = match Parser::new("/home/insi/Projects/ruwm/src/config_parser/config.test") {
    Ok(s) => s,
    Err(e) => panic!("{}", e)
  };

  println!("Parser: {}", parser.to_string());
}
<commit_msg>remove absolute directory to config file<commit_after>use std::io;
use std::io::prelude::*;
use std::fs::File;
use std::fmt;
use std::env;

use self::err::ConfigError;
/* includes the generated code from PEG
	- ${PROJECT_DIR}/targetbuild/ruwm-*out/
*/
// TODO
// This code need some major cleanup

use config_parser::*;

#[allow(dead_code)]
pub mod config_grammar {
	include!(concat!(env!("OUT_DIR"), "/config_grammar.rs"));
}

#[derive(Debug)]
pub struct Parser {
  variables: Variables,
  bindSym:  Vec<Config>,
  exec: Vec<Config>,
  floatingMod: Vec<Config>,
}

impl fmt::Display for Parser {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "Variables: {:?}, \
      bindSym: {:?}, \
      exec: {:?}, \
      floatingMod: {:?}",
      self.variables, self.bindSym, self.exec, self.floatingMod
    )
  }
}

  /*
   * Set up the Parser Struct
   * move ownership of the parsed file from
   * the rust-peg grammar (rust-peg) to my own structures
   */
impl Parser {

  pub fn new(config_file: &str) -> Result<Parser, ConfigError>  {
    let mut f = File::open(config_file)?;

    let mut config = String::new();
    f.read_to_string(&mut config)?;
    let config = config_grammar::content(config.as_ref())?;

    // create data structs for each configuration type
    let mut variables = Variables::new();
    let mut bindSym = Vec::new();
    let mut exec = Vec::new();
    let mut floatingMod = Vec::new();

    for x in config.iter() {
      match *x {
        Config::Set(ref v, ref s) => variables.set(v.to_owned(), s.to_owned())?,
        Config::Exec(ref a) => exec.push(Config::Exec(a.to_owned())),
        Config::BindSym(ref s, ref a) => bindSym.push(Config::BindSym(s.to_owned(),a.to_owned())),
        Config::FloatingMod(ref s) => floatingMod.push(Config::FloatingMod(s.to_owned())),
        _ => {},
      };
    }

    // let result = parse(&mut f)?;
    Ok(Parser {
      variables,
      bindSym,
      exec,
      floatingMod,
    })
  }
}

#[cfg(test)]
#[test]
fn test_grammar() {
  // TODO
  // the fact that the first line must be at the very beginning
  // is not a very big deal, since we can just strip all whitespace until
  // we reach an ascii character
  // but if there is a easy way to fix this in the grammar, then that is the
  // better option
	match config_grammar::content("# A comment
		bindsym LeftGui+1 workspace 1

bindsym $super+$rand exec 'termite --config $HOME/.config/termite/config'
   bindsym RightGui+2 workspace 2 # this is another comment

set $super Ctrl+Mod4
  # This is a comment
set $ws0 '0:emp'
bindsym RightGui+3 workspace $ws0
bindsym Hello+3 workspace 5

bindsym $super+$left focus left
bindsym $super+Ctrl focus down
bindsym $super+$up focus up
bindsym $super+$right focus right
bindsym $super+1 workspace $ws0

exec --no-startup-id 'nm-applet'

set $left h

"){
		Ok(r) => println!("Parsed as: {:?}", r),
		Err(e) => println!("Parse error: {}", e),
	};

}

#[cfg(test)]
#[test]
fn test_parser() {
  let parser = match Parser::new("src/config_parser/config.test") {
    Ok(s) => s,
    Err(e) => panic!("{}", e)
  };

  println!("Parser: {}", parser.to_string());
}
<|endoftext|>