<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 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_dtor;
pub mod thread_local_key;
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_INVALID_PARAMETER => return ErrorKind::InvalidInput,
        c::ERROR_SEM_TIMEOUT
        | c::WAIT_TIMEOUT
        | c::ERROR_DRIVER_CANCEL_TIMEOUT
        | c::ERROR_OPERATION_ABORTED
        | c::ERROR_SERVICE_REQUEST_TIMEOUT
        | c::ERROR_COUNTER_TIMEOUT
        | c::ERROR_TIMEOUT
        | c::ERROR_RESOURCE_CALL_TIMED_OUT
        | c::ERROR_CTX_MODEM_RESPONSE_TIMEOUT
        | c::ERROR_CTX_CLIENT_QUERY_TIMEOUT
        | c::FRS_ERR_SYSVOL_POPULATE_TIMEOUT
        | c::ERROR_DS_TIMELIMIT_EXCEEDED
        | c::DNS_ERROR_RECORD_TIMED_OUT
        | c::ERROR_IPSEC_IKE_TIMED_OUT
        | c::ERROR_RUNLEVEL_SWITCH_TIMEOUT
        | c::ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT => 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 start = &haystack[..];

    // For performance reasons unfold the loop eight times.
    while start.len() >= 8 {
        macro_rules! if_return {
            ($($n:literal,)+) => {
                $(
                    if start[$n] == needle {
                        return Some((&start[$n] as *const u16 as usize - ptr as usize) / 2);
                    }
                )+
            }
        }

        if_return!(0, 1, 2, 3, 4, 5, 6, 7,);

        start = &start[8..];
    }

    for c in start {
        if *c == needle {
            return Some((c as *const u16 as usize - ptr as usize) / 2);
        }
    }
    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 as u64 { c::INFINITE } else { ms as c::DWORD })
        .unwrap_or(c::INFINITE)
}

/// Use `__fastfail` to abort the process
///
/// This is the same implementation as in libpanic_abort's `__rust_start_panic`. See
/// that function for more information on `__fastfail`
#[allow(unreachable_code)]
pub fn abort_internal() -> ! {
    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
    unsafe {
        llvm_asm!("int $$0x29" :: "{ecx}"(7) ::: volatile); // 7 is FAST_FAIL_FATAL_APP_EXIT
        crate::intrinsics::unreachable();
    }
    crate::intrinsics::abort();
}
<commit_msg>Reverse formatting<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 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_dtor;
pub mod thread_local_key;
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_INVALID_PARAMETER => return ErrorKind::InvalidInput,
        c::ERROR_SEM_TIMEOUT
        | c::WAIT_TIMEOUT
        | c::ERROR_DRIVER_CANCEL_TIMEOUT
        | c::ERROR_OPERATION_ABORTED
        | c::ERROR_SERVICE_REQUEST_TIMEOUT
        | c::ERROR_COUNTER_TIMEOUT
        | c::ERROR_TIMEOUT
        | c::ERROR_RESOURCE_CALL_TIMED_OUT
        | c::ERROR_CTX_MODEM_RESPONSE_TIMEOUT
        | c::ERROR_CTX_CLIENT_QUERY_TIMEOUT
        | c::FRS_ERR_SYSVOL_POPULATE_TIMEOUT
        | c::ERROR_DS_TIMELIMIT_EXCEEDED
        | c::DNS_ERROR_RECORD_TIMED_OUT
        | c::ERROR_IPSEC_IKE_TIMED_OUT
        | c::ERROR_RUNLEVEL_SWITCH_TIMEOUT
        | c::ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT => 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 start = &haystack[..];

    // For performance reasons unfold the loop eight times.
    while start.len() >= 8 {
        macro_rules! if_return {
            ($($n:literal,)+) => {
                $(
                    if start[$n] == needle {
                        return Some((&start[$n] as *const u16 as usize - ptr as usize) / 2);
                    }
                )+
            }
        }

        if_return!(0, 1, 2, 3, 4, 5, 6, 7,);

        start = &start[8..];
    }

    for c in start {
        if *c == needle {
            return Some((c as *const u16 as usize - ptr as usize) / 2);
        }
    }
    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 as u64 { c::INFINITE } else { ms as c::DWORD })
        .unwrap_or(c::INFINITE)
}

/// Use `__fastfail` to abort the process
///
/// This is the same implementation as in libpanic_abort's `__rust_start_panic`. See
/// that function for more information on `__fastfail`
#[allow(unreachable_code)]
pub fn abort_internal() -> ! {
    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
    unsafe {
        llvm_asm!("int $$0x29" :: "{ecx}"(7) ::: volatile); // 7 is FAST_FAIL_FATAL_APP_EXIT
        crate::intrinsics::unreachable();
    }
    crate::intrinsics::abort();
}
<|endoftext|>


<commit_before>use stats::LogProb;

pub mod evidence {
    /// Scale of evidence as defined by
    /// [Kass and Raftery 1995](http://www.andrew.cmu.edu/user/kk3n/simplicity/KassRaftery1995.pdf).
    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
    pub enum KassRaftery {
        None,
        Barely,
        Positive,
        Strong,
        VeryStrong,
    }
}

custom_derive! {
    /// A newtype for Bayes factors.
    #[derive(
        NewtypeFrom,
        NewtypeDeref,
        PartialEq,
        PartialOrd,
        Copy,
        Clone,
        Debug,
    )]
    pub struct BayesFactor(pub f64);
}

impl BayesFactor {
    /// Calculate Bayes factor from given probabilities.
    pub fn new(a: LogProb, b: LogProb) -> Self {
        BayesFactor((a - b).exp())
    }

    /// Calculate strength of evidence as defined by
    /// [Kass and Raftery 1995](http://www.andrew.cmu.edu/user/kk3n/simplicity/KassRaftery1995.pdf).
    pub fn evidence_kass_raftery(&self) -> evidence::KassRaftery {
        let k = **self;
        if k >= 1.0 && k <= 3.0 {
            evidence::KassRaftery::Barely
        } else if k <= 20.0 {
            evidence::KassRaftery::Positive
        } else if k <= 150.0 {
            evidence::KassRaftery::Strong
        } else {
            evidence::KassRaftery::VeryStrong
        }
    }
}

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

    #[test]
    fn test_bayes_factor() {
        let bf = BayesFactor::new(LogProb(0.5_f64.ln()), LogProb(0.1_f64.ln()));
        assert_relative_eq!(*bf, 5.0, epsilon = 1e-9);
        assert_eq!(bf.evidence_kass_raftery(), evidence::KassRaftery::Positive);
    }
}
<commit_msg>Serde support for KassRaftery.<commit_after>use stats::LogProb;

pub mod evidence {
    /// Scale of evidence as defined by
    /// [Kass and Raftery 1995](http://www.andrew.cmu.edu/user/kk3n/simplicity/KassRaftery1995.pdf).
    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
    pub enum KassRaftery {
        None,
        Barely,
        Positive,
        Strong,
        VeryStrong,
    }
}

custom_derive! {
    /// A newtype for Bayes factors.
    #[derive(
        NewtypeFrom,
        NewtypeDeref,
        PartialEq,
        PartialOrd,
        Copy,
        Clone,
        Debug,
    )]
    pub struct BayesFactor(pub f64);
}

impl BayesFactor {
    /// Calculate Bayes factor from given probabilities.
    pub fn new(a: LogProb, b: LogProb) -> Self {
        BayesFactor((a - b).exp())
    }

    /// Calculate strength of evidence as defined by
    /// [Kass and Raftery 1995](http://www.andrew.cmu.edu/user/kk3n/simplicity/KassRaftery1995.pdf).
    pub fn evidence_kass_raftery(&self) -> evidence::KassRaftery {
        let k = **self;
        if k >= 1.0 && k <= 3.0 {
            evidence::KassRaftery::Barely
        } else if k <= 20.0 {
            evidence::KassRaftery::Positive
        } else if k <= 150.0 {
            evidence::KassRaftery::Strong
        } else {
            evidence::KassRaftery::VeryStrong
        }
    }
}

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

    #[test]
    fn test_bayes_factor() {
        let bf = BayesFactor::new(LogProb(0.5_f64.ln()), LogProb(0.1_f64.ln()));
        assert_relative_eq!(*bf, 5.0, epsilon = 1e-9);
        assert_eq!(bf.evidence_kass_raftery(), evidence::KassRaftery::Positive);
    }
}
<|endoftext|>


<commit_before>extern crate glutin;
extern crate libc;
use std::ptr;

mod gl {
    pub use self::Gles2 as Gl;
    include!(concat!(env!("OUT_DIR"), "/test_gl_bindings.rs"));
}
use gl::types::*;

#[cfg(any(target_os = "macos", target_os = "windows"))]
#[test]
fn test_headless() {
    let width: i32 = 256;
    let height: i32 = 256;
    let window = glutin::HeadlessRendererBuilder::new(width as u32, height as u32).build().unwrap();

    unsafe { window.make_current().expect("Couldn't make window current") };

    let gl = gl::Gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);

    unsafe {
        let mut framebuffer = 0;
        let mut texture = 0;
        gl.GenFramebuffers(1, &mut framebuffer);
        gl.BindFramebuffer(gl::FRAMEBUFFER, framebuffer);
        gl.GenTextures(1, &mut texture);
        gl.BindTexture(gl::TEXTURE_2D, texture);
        gl.TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as i32);
        gl.TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as i32);
        gl.TexImage2D(gl::TEXTURE_2D, 0, gl::RGBA as i32, width, height,
                     0, gl::RGBA, gl::UNSIGNED_BYTE, ptr::null());
        gl.FramebufferTexture2D(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, texture, 0);
        let status = gl.CheckFramebufferStatus(gl::FRAMEBUFFER);
        if status != gl::FRAMEBUFFER_COMPLETE {
          panic!("Error while creating the framebuffer");
        }

        gl.ClearColor(0.0, 1.0, 0.0, 1.0);
        gl.Clear(gl::COLOR_BUFFER_BIT);
        gl.Enable(gl::SCISSOR_TEST);
        gl.Scissor(1, 0, 1, 1);
        gl.ClearColor(1.0, 0.0, 0.0, 1.0);
        gl.Clear(gl::COLOR_BUFFER_BIT);

        let mut values: Vec<u8> = vec![0;(width*height*4) as usize];
        gl.ReadPixels(0, 0, width, height, gl::RGBA, gl::UNSIGNED_BYTE, values.as_mut_ptr() as *mut GLvoid);

        assert_eq!(values[0], 0);
        assert_eq!(values[1], 255);
        assert_eq!(values[2], 0);
        assert_eq!(values[3], 255);

        assert_eq!(values[4], 255);
        assert_eq!(values[5], 0);
        assert_eq!(values[6], 0);
        assert_eq!(values[7], 255);
    }
}
<commit_msg>Disabled headless test on windows<commit_after>extern crate glutin;
extern crate libc;
use std::ptr;

mod gl {
    pub use self::Gles2 as Gl;
    include!(concat!(env!("OUT_DIR"), "/test_gl_bindings.rs"));
}
use gl::types::*;

#[cfg(target_os = "macos")]
#[test]
fn test_headless() {
    let width: i32 = 256;
    let height: i32 = 256;
    let window = glutin::HeadlessRendererBuilder::new(width as u32, height as u32).build().unwrap();

    unsafe { window.make_current().expect("Couldn't make window current") };

    let gl = gl::Gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);

    unsafe {
        let mut framebuffer = 0;
        let mut texture = 0;
        gl.GenFramebuffers(1, &mut framebuffer);
        gl.BindFramebuffer(gl::FRAMEBUFFER, framebuffer);
        gl.GenTextures(1, &mut texture);
        gl.BindTexture(gl::TEXTURE_2D, texture);
        gl.TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as i32);
        gl.TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as i32);
        gl.TexImage2D(gl::TEXTURE_2D, 0, gl::RGBA as i32, width, height,
                     0, gl::RGBA, gl::UNSIGNED_BYTE, ptr::null());
        gl.FramebufferTexture2D(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, texture, 0);
        let status = gl.CheckFramebufferStatus(gl::FRAMEBUFFER);
        if status != gl::FRAMEBUFFER_COMPLETE {
          panic!("Error while creating the framebuffer");
        }

        gl.ClearColor(0.0, 1.0, 0.0, 1.0);
        gl.Clear(gl::COLOR_BUFFER_BIT);
        gl.Enable(gl::SCISSOR_TEST);
        gl.Scissor(1, 0, 1, 1);
        gl.ClearColor(1.0, 0.0, 0.0, 1.0);
        gl.Clear(gl::COLOR_BUFFER_BIT);

        let mut values: Vec<u8> = vec![0;(width*height*4) as usize];
        gl.ReadPixels(0, 0, width, height, gl::RGBA, gl::UNSIGNED_BYTE, values.as_mut_ptr() as *mut GLvoid);

        assert_eq!(values[0], 0);
        assert_eq!(values[1], 255);
        assert_eq!(values[2], 0);
        assert_eq!(values[3], 255);

        assert_eq!(values[4], 255);
        assert_eq!(values[5], 0);
        assert_eq!(values[6], 0);
        assert_eq!(values[7], 255);
    }
}
<|endoftext|>


<commit_before>/*
  Implements the basic IBBA maximization algorithm with a priority queue.
*/

use std::collections::BinaryHeap;

extern crate gelpia_utils;
use gelpia_utils::{Quple, INF, NINF, Flt};

extern crate gr;
use gr::{GI, width_box, split_box, midpoint_box, eps_tol};

extern crate function;
use function::FuncObj;

// BEGIN: MOVE THESE INTO OPTIONS PARSING FRAMEWORK
use std::env;

extern crate getopts;
use getopts::Options;
// END: MOVE THESE INTO OPTIONS PARSING FRAMEWORK

fn ibba(x_0: &Vec<GI>, e_x: Flt, e_f: Flt, f: FuncObj) -> (Flt, Vec<GI>) {
    let mut f_best_high = NINF;
    let mut f_best_low  = NINF;
    let mut best_x = x_0.clone();
    let mut q = BinaryHeap::new();
    let mut i: u32 = 0;

    let (fc, dfc) = f.call(&x_0);
    q.push(Quple{p: INF, pf: i, data: x_0.clone(), fdata: fc, dfdata: dfc});
    while q.len() != 0 {
        let v = q.pop();
        let (ref x, fx) =
            match v {
                Some(y) => (y.data, y.fdata),
                None => panic!("wtf")
            };

//        let xw = width_box(x);
        //let fx = f.call(x);
//        let fw = fx.width();

        if fx.upper() < f_best_low ||
            width_box(x, e_x) ||
            eps_tol(fx, e_f) //|| (!contains_zero && !on_boundary)
        {
                if f_best_high < fx.upper() {
                    f_best_high = fx.upper();
                    best_x = x.clone();
                }
                continue;
            }
        else {
            let (x_s, is_split) = split_box(&x);
            for sx in x_s {
                let est = f.call(&midpoint_box(&sx)).0;
                if f_best_low < est.lower()  {
                    f_best_low = est.lower();
                }
                i += 1;
                if is_split {
                    let (fc, dfc) = f.call(&x_0);
                    q.push(Quple{p: est.upper(),
                                 pf: i,
                                 data: sx.clone(),
                                 fdata: fc,
                                 dfdata: dfc});
                }
            }
        }
    }
//    println!("{:?}", i);
    (f_best_high, best_x)
}

// BEGIN: MOVE THESE INTO OPTIONS PARSING FRAMEWORK
fn proc_consts(consts: &String) -> Vec<GI> {
    let mut result = vec![];
    for inst in consts.split('|') {
        if inst == "" {
            continue;
        }
        result.push(GI::new_c(inst).unwrap());
    }
    result
}

// END: MOVE THESE INTO OPTIONS PARSING FRAMEWORK

fn main() {
    // BEGIN: MOVE THESE INTO OPTIONS PARSING FRAMEWORK
    let args: Vec<String> = env::args().collect();

    let mut opts = Options::new();
    opts.reqopt("c", "constants", "", "");
    opts.reqopt("f", "function", "", "");
    opts.reqopt("i", "input", "", "");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => {m},
        Err(f) => {panic!(f.to_string())}
    };
    let const_string = matches.opt_str("c").unwrap();
    let input_string = matches.opt_str("i").unwrap();
    let func_string = matches.opt_str("f").unwrap();

    let args = proc_consts(&input_string.to_string());
    let fo = FuncObj::new(&proc_consts(&const_string.to_string()),
                              &func_string.to_string(), false, "".to_string());

    // END: MOVE THESE INTO OPTIONS PARSING FRAMEWORK

    let (max, interval) = ibba(&args, 1e-4, 1e-4, fo.clone());
    println!("Max: {:?}", max);
    for i in 0..interval.len()  {
        println!("X{}: {}", i, interval[i].to_string());
    }

}
<commit_msg>Update serial.rs<commit_after>// Cooperative optimization solver
use std::collections::BinaryHeap;
use std::io::Write;
extern crate rand;

#[macro_use(max)]
extern crate gelpia_utils;
extern crate gr;

use gelpia_utils::{Quple, INF, NINF, Flt, Parameters, eps_tol, check_diff};

use gr::{GI, width_box, split_box, midpoint_box};

use std::sync::{Barrier, RwLock, Arc, RwLockWriteGuard};

use std::sync::atomic::{AtomicBool, Ordering};

use std::thread;

use std::time::Duration;

extern crate function;
use function::FuncObj;

extern crate args;
use args::{process_args};

extern crate time;

/// Returns the guaranteed upperbound for the algorithm
/// from the queue.
fn get_upper_bound(q: &RwLockWriteGuard<BinaryHeap<Quple>>,
                   f_best_high: f64) -> f64{
    let mut max = f_best_high;
    for qi in q.iter() {
        max = max!{max, qi.fdata.upper()};
    }
    max
}

fn log_max(q: &RwLockWriteGuard<BinaryHeap<Quple>>,
           f_best_low: f64,
           f_best_high: f64) {
    let max = get_upper_bound(q, f_best_high);
    let _ = writeln!(&mut std::io::stderr(),
                     "lb: {}, possible ub: {}, guaranteed ub: {}",
                     f_best_low,
                     f_best_high,
                     max);
}

#[allow(dead_code)]
fn print_q(q: &RwLockWriteGuard<BinaryHeap<Quple>>) {
    let mut lq: BinaryHeap<Quple> = (*q).clone();
    while lq.len() != 0 {
        let qi = lq.pop().unwrap();
        let (gen, v, _) = (qi.pf, qi.p, qi.fdata);
        print!("[{}, {}, {}], ", v, gen, qi.fdata.to_string());
    }
    println!("\n");
}

/// Returns a tuple (function_estimate, eval_interval)
/// # Arguments
/// * `f` - The function to evaluate with
/// * `input` - The input domain
fn est_func(f: &FuncObj, input: &Vec<GI>) -> (Flt, GI, Option<Vec<GI>>) {
    let mid = midpoint_box(input);
    let (est_m, _) = f.call(&mid);
    let (fsx, dfsx) = f.call(&input);
    let (fsx_u, _) = f.call(&input.iter()
                            .map(|&si| GI::new_p(si.upper()))
                            .collect::<Vec<_>>());
    let (fsx_l, _) = f.call(&input.iter()
                            .map(|&si| GI::new_p(si.lower()))
                            .collect::<Vec<_>>());
    let est_max = est_m.lower().max(fsx_u.lower()).max(fsx_l.lower());
    (est_max, fsx, dfsx)
}

// Returns the upper bound, the domain where this bound occurs and a status
// flag indicating whether the answer is complete for the problem.
fn ibba(x_0: Vec<GI>, e_x: Flt, e_f: Flt, e_f_r: Flt,
        f_bestag: Arc<RwLock<Flt>>,
        f_best_shared: Arc<RwLock<Flt>>,
        x_bestbb: Arc<RwLock<Vec<GI>>>,
        b1: Arc<Barrier>, b2: Arc<Barrier>,
        q: Arc<RwLock<BinaryHeap<Quple>>>,
        sync: Arc<AtomicBool>, stop: Arc<AtomicBool>,
        f: FuncObj,
        logging: bool, max_iters: u32)
        -> (Flt, Flt, Vec<GI>) {
    let mut best_x = x_0.clone();

    let mut iters: u32 = 0;
    let (est_max, first_val, _) = est_func(&f, &x_0);

    q.write().unwrap().push(Quple{p: est_max, pf: 0, data: x_0.clone(),
                                  fdata: first_val, dfdata: None});
    let mut f_best_low = est_max;
    let mut f_best_high = est_max;

    while q.read().unwrap().len() != 0 && !stop.load(Ordering::Acquire) {
        if max_iters != 0 && iters >= max_iters {
            break;
        }

        // Take q as writable during an iteration
        let mut q = q.write().unwrap();

        let fbl_orig = f_best_low;
        f_best_low = max!(f_best_low, *f_bestag.read().unwrap());

        if iters % 2048 == 0 {
            let guaranteed_bound = get_upper_bound(&q, f_best_high);
            if (guaranteed_bound - f_best_high).abs() < e_f {
                f_best_high = guaranteed_bound;
                break;
            }
        }

        if logging && fbl_orig != f_best_low {
            log_max(&q, f_best_low, f_best_high);
        }

        let (ref x, iter_est, fx, ref dfx, gen) =
            match q.pop() {
                Some(y) => (y.data, y.p, y.fdata, y.dfdata, y.pf),
                None    => unreachable!()
            };

        if check_diff(dfx.clone(), x, &x_0) {
            continue;
        }
        if fx.upper() < f_best_low ||
            width_box(x, e_x) ||
            eps_tol(fx, iter_est, e_f, e_f_r) {
                {
                    if f_best_high < fx.upper() {
                        f_best_high = fx.upper();
                        best_x = x.clone();
                        if logging {
                            log_max(&q, f_best_low, f_best_high);
                        }
                    }
                    continue;
                }
            }
        else {
            let (x_s, is_split) = split_box(&x);
            for sx in x_s {
                let (est_max, fsx, dfsx) = est_func(&f, &sx);
                if f_best_low < est_max  {
                    f_best_low = est_max;
                    *x_bestbb.write().unwrap() = sx.clone();
                }
                iters += 1;
                if is_split {
                    q.push(Quple{p: est_max,
                                 pf: gen+1,
                                 data: sx,
                                 fdata: fsx,
                                 dfdata:dfsx});
                }
            }
        }
    }
    stop.store(true, Ordering::Release);
    (f_best_low, f_best_high, best_x)
}

fn main() {
    let args = process_args();

    let ref x_0 = args.domain;
    let ref fo = args.function;
    let x_err = args.x_error;
    let y_err = args.y_error;
    let y_rel = args.y_error_rel;
    let seed = args.seed;

    // Early out if there are no input variables...
    if x_0.len() == 0 {
        let result = fo.call(&x_0).0;
        println!("[[{},{}], {{}}]", result.lower(), result.upper());
        return
    }

    let q_inner: BinaryHeap<Quple> = BinaryHeap::new();
    let q = Arc::new(RwLock::new(q_inner));

    let b1 = Arc::new(Barrier::new(3));
    let b2 = Arc::new(Barrier::new(3));

    let sync = Arc::new(AtomicBool::new(false));
    let stop = Arc::new(AtomicBool::new(false));

    let f_bestag: Arc<RwLock<Flt>> = Arc::new(RwLock::new(NINF));
    let f_best_shared: Arc<RwLock<Flt>> = Arc::new(RwLock::new(NINF));

    let x_e = x_0.clone();
    let x_i = x_0.clone();

    let x_bestbb = Arc::new(RwLock::new(x_0.clone()));

    let ibba_thread =
    {
        let q = q.clone();
        let b1 = b1.clone();
        let b2 = b2.clone();
        let f_bestag = f_bestag.clone();
        let f_best_shared = f_best_shared.clone();
        let x_bestbb = x_bestbb.clone();
        let sync = sync.clone();
        let stop = stop.clone();
        let fo_c = fo.clone();
        let logging = args.logging;
        let iters= args.iters;
        thread::Builder::new().name("IBBA".to_string()).spawn(move || {
            ibba(x_i, x_err, y_err, y_rel,
                 f_bestag, f_best_shared,
                 x_bestbb,
                 b1, b2, q, sync, stop, fo_c, logging, iters)
        })};

    let result = ibba_thread.unwrap().join();

    if result.is_ok() {
        let (min, mut max, mut interval) = result.unwrap();
        // Go through all remaining intervals from IBBA to find the true
        // max
        let ref lq = q.read().unwrap();
        for i in lq.iter() {
            let ref top = *i;
            let (ub, dom) = (top.fdata.upper(), &top.data);
            if ub > max {
                max = ub;
                interval = dom.clone();
            }
        }
        println!("[[{},{}], {{", min, max);
        for i in 0..args.names.len() {
            println!("'{}' : {},", args.names[i], interval[i].to_string());
        }
        println!("}}]");

    }
    else {println!("error")}
}
<|endoftext|>


<commit_before>use super::{Result, Error};

use std::sync::mpsc;

use websocket::ws::sender::Sender as SenderTrait;
use websocket::client::{Client, Sender, Receiver};
use websocket::stream::WebSocketStream;
use websocket::message::{Message as WsMessage, Type as MessageType};

use serde_json;
use serde_json::builder::ObjectBuilder;

use super::model::*;

/// The websocket protocol version expected.
const VERSION: u64 = 3;

/// Websocket connection to the Discord servers.
pub struct Connection {
	keepalive_channel: mpsc::Sender<Status>,
	receiver: Receiver<WebSocketStream>,
	ready_event: Option<Event>,
	/// Known state composed from received events
	pub state: State,
}

impl Connection {
	pub fn new(url: &str, token: &str) -> Result<Connection> {
		// establish the websocket connection
		let url = match ::websocket::client::request::Url::parse(url) {
			Ok(url) => url,
			Err(_) => return Err(Error::Other("Invalid URL in Connection::new()"))
		};
		let response = try!(try!(Client::connect(url)).send());
		try!(response.validate());
		let (mut sender, mut receiver) = response.begin().split();

		// send the handshake
		let map = ObjectBuilder::new()
			.insert("op", 2)
			.insert_object("d", |object| object
				.insert("token", token)
				.insert_object("properties", |object| object
					.insert("$os", ::std::env::consts::OS)
					.insert("$browser", "Howl library for Rust")
					.insert("$device", "howl")
					.insert("$referring_domain", "")
					.insert("$referrer", "")
				)
				.insert("v", 3)
			)
			.unwrap();
		try!(sender.send_message(&WsMessage::text(try!(serde_json::to_string(&map)))));

		// read the Ready event
		let ready = try!(recv_message(&mut receiver));
		let state = try!(State::new(ready.clone()));
		let heartbeat_interval = state.heartbeat_interval;

		// spawn the keepalive thread
		let (tx, rx) = mpsc::channel();
		::std::thread::spawn(move || keepalive(heartbeat_interval, sender, rx));

		// return the connection
		Ok(Connection {
			keepalive_channel: tx,
			receiver: receiver,
			ready_event: Some(ready),
			state: state,
		})
	}

	pub fn set_game_id(&mut self, game_id: Option<u64>) {
		let _ = self.keepalive_channel.send(Status::SetGameId(game_id));
	}

	pub fn recv_event(&mut self) -> Result<Event> {
		// clear the ready event
		if let Some(ready) = self.ready_event.take() {
			Ok(ready)
		} else {
			match recv_message(&mut self.receiver) {
				Err(err) => Err(err),
				Ok(event) => {
					self.state.update(&event);
					Ok(event)
				}
			}
		}
	}

	pub fn shutdown(&mut self) -> Result<()> {
		let _ = self.keepalive_channel.send(Status::Shutdown);
		try!(self.receiver.get_mut().get_mut().shutdown(::std::net::Shutdown::Both));
		Ok(())
	}
}

fn recv_message(receiver: &mut Receiver<WebSocketStream>) -> Result<Event> {
	use websocket::ws::receiver::Receiver;
	let message: WsMessage = try!(receiver.recv_message());
	if message.opcode == MessageType::Close {
		Ok(Event::Closed(message.cd_status_code.unwrap_or(0xffff)))
	} else if message.opcode != MessageType::Text {
		println!("Unexpected message: {:?}", message);
		Ok(Event::Closed(0xfffe))
	} else {
		let json: serde_json::Value = try!(serde_json::from_reader(&message.payload[..]));
		let original = format!("{:?}", json);
		match Event::decode(json) {
			Ok(event) => Ok(event),
			Err(err) => {
				// If there was a decode failure, print the original json for debugging
				println!("<<< {} >>>", original);
				Err(err)
			}
		}
	}
}

enum Status {
	Shutdown,
	SetGameId(Option<u64>),
}

fn keepalive(interval: u64, mut sender: Sender<WebSocketStream>, channel: mpsc::Receiver<Status>) {
	let mut countdown = interval;
	let mut game_id = None;
	'outer: loop {
		// TODO: this is not a precise timer, but it's good enough for now
		::std::thread::sleep_ms(100);
		countdown = countdown.saturating_sub(100);

		loop {
			match channel.try_recv() {
				Ok(Status::Shutdown) => break 'outer,
				Ok(Status::SetGameId(id)) => { game_id = id; countdown = 0; },
				Err(mpsc::TryRecvError::Empty) => break,
				Err(mpsc::TryRecvError::Disconnected) => break 'outer,
			}
		}

		if countdown == 0 {
			countdown = interval;
			let map = ObjectBuilder::new()
				.insert("op", 3)
				.insert_object("d", |object| object
					.insert("idle_since", serde_json::Value::Null)
					.insert("game_id", game_id)
				)
				.unwrap();
			let json = match serde_json::to_string(&map) {
				Ok(json) => json,
				Err(e) => return println!("error jsoning ping: {:?}", e)
			};
			match sender.send_message(&WsMessage::text(json)) {
				Ok(()) => {},
				Err(e) => return println!("error sending ping: {:?}", e)
			}
		}
	}
	let _ = sender.get_mut().shutdown(::std::net::Shutdown::Both);
}

/// State tracking for events received over Discord.
pub struct State {
	user: CurrentUser,
	session_id: String,
	heartbeat_interval: u64,
	private_channels: Vec<PrivateChannel>,
	servers: Vec<LiveServer>,
}

impl State {
	fn new(ready: Event) -> Result<State> {
		match ready {
			Event::Ready { version, user, session_id, heartbeat_interval, private_channels, servers, read_state: _ } => {
				if version != VERSION {
					println!("[Warning] Got version {} instead of {}", version, VERSION);
					return Err(Error::Other("Wrong version specified"))
				}
				Ok(State {
					user: user,
					session_id: session_id,
					heartbeat_interval: heartbeat_interval,
					private_channels: private_channels,
					servers: servers,
				})
			},
			_ => Err(Error::Other("First event for State must be Ready")),
		}
	}

	fn update(&mut self, event: &Event) {
		match *event {
			Event::UserUpdate(ref user) => self.user = user.clone(),
			Event::VoiceStateUpdate(ref server, ref state) => {
				self.servers.iter_mut().find(|s| s.id == *server).map(|srv| {
					match srv.voice_states.iter_mut().find(|u| u.user_id == state.user_id) {
						Some(srv_state) => { srv_state.clone_from(state); return }
						None => {}
					}
					srv.voice_states.push(state.clone());
				});
			}
			Event::PresenceUpdate { ref server_id, ref presence, roles: _ } => {
				// TODO: double-check this
				self.servers.iter_mut().find(|s| s.id == *server_id).map(|srv| {
					match srv.presences.iter_mut().find(|u| u.user_id == presence.user_id) {
						Some(srv_presence) => { srv_presence.clone_from(presence); return }
						None => {}
					}
					srv.presences.push(presence.clone());
				});
			}
			Event::ServerCreate(ref server) => self.servers.push(server.clone()),
			Event::ServerUpdate(ref server) => {
				self.servers.iter_mut().find(|s| s.id == server.id).map(|srv| {
					srv.name.clone_from(&server.name);
					srv.joined_at.clone_from(&server.joined_at);
					srv.afk_timeout = server.afk_timeout;
					srv.afk_channel_id.clone_from(&server.afk_channel_id);
					srv.icon.clone_from(&server.icon);
					srv.roles.clone_from(&server.roles);
					srv.region.clone_from(&server.region);
					// embed_enabled and embed_channel_id skipped
					srv.owner_id.clone_from(&server.owner_id);
				});
			}
			Event::ServerDelete(ref server) => self.servers.retain(|s| s.id != server.id),
			Event::ServerMemberAdd { ref server_id, ref joined_at, ref roles, ref user } => {
				self.servers.iter_mut().find(|s| s.id == *server_id).map(|srv| {
					srv.members.push(Member {
						user: user.clone(),
						roles: roles.clone(),
						joined_at: joined_at.clone(),
						mute: false,
						deaf: false,
					})
				});
			}
			Event::ServerMemberUpdate { ref server_id, ref roles, ref user } => {
				self.servers.iter_mut().find(|s| s.id == *server_id).map(|srv| {
					srv.members.iter_mut().find(|m| m.user.id == user.id).map(|member| {
						member.user.clone_from(user);
						member.roles.clone_from(roles);
					})
				});
			}
			Event::ServerMemberRemove(ref server_id, ref user) => {
				self.servers.iter_mut().find(|s| s.id == *server_id).map(|srv| {
					srv.members.retain(|m| m.user.id != user.id);
				});
			}
			Event::ServerRoleCreate(ref server_id, ref role) => {
				self.servers.iter_mut().find(|s| s.id == *server_id).map(|srv| {
					srv.roles.push(role.clone());
				});
			}
			Event::ServerRoleUpdate(ref server_id, ref role) => {
				self.servers.iter_mut().find(|s| s.id == *server_id).map(|srv| {
					srv.roles.iter_mut().find(|r| r.id == role.id).map(|srv_role| {
						srv_role.clone_from(role);
					});
				});
			}
			Event::ServerRoleDelete(ref server_id, ref role_id) => {
				self.servers.iter_mut().find(|s| s.id == *server_id).map(|srv| {
					srv.roles.retain(|r| r.id != *role_id);
				});
			}
			Event::ChannelCreate(ref channel) => match *channel {
				Channel::Private(ref channel) => {
					self.private_channels.push(channel.clone());
				}
				Channel::Public(ref channel) => {
					self.servers.iter_mut().find(|s| s.id == channel.server_id).map(|srv| {
						srv.channels.push(channel.clone());
					});
				}
			},
			Event::ChannelUpdate(ref channel) => match *channel {
				Channel::Private(ref channel) => {
					self.private_channels.iter_mut().find(|c| c.id == channel.id).map(|chan| {
						chan.clone_from(channel);
					});
				}
				Channel::Public(ref channel) => {
					self.servers.iter_mut().find(|s| s.id == channel.server_id).map(|srv| {
						srv.channels.iter_mut().find(|c| c.id == channel.id).map(|chan| {
							chan.clone_from(channel);
						})
					});
				}
			},
			Event::ChannelDelete(ref channel) => match *channel {
				Channel::Private(ref channel) => {
					self.private_channels.retain(|c| c.id != channel.id);
				}
				Channel::Public(ref channel) => {
					self.servers.iter_mut().find(|s| s.id == channel.server_id).map(|srv| {
						srv.channels.retain(|c| c.id != channel.id);
					});
				}
			},
			_ => {}
		}
	}

	#[inline]
	pub fn user(&self) -> &CurrentUser { &self.user }

	#[inline]
	pub fn session_id(&self) -> &str { &self.session_id }

	#[inline]
	pub fn private_channels(&self) -> &[PrivateChannel] { &self.private_channels }

	#[inline]
	pub fn servers(&self) -> &[LiveServer] { &self.servers }

	pub fn find_channel(&self, id: &ChannelId) -> Option<ChannelRef> {
		for server in &self.servers {
			for channel in &server.channels {
				if channel.id == *id {
					return Some(ChannelRef::Public(server, channel))
				}
			}
		}
		for channel in &self.private_channels {
			if channel.id == *id {
				return Some(ChannelRef::Private(channel))
			}
		}
		None
	}
}

/// A reference to a private or public channel
pub enum ChannelRef<'a> {
	/// A private channel
	Private(&'a PrivateChannel),
	/// A public channel and its server
	Public(&'a LiveServer, &'a PublicChannel),
}
<commit_msg>Adjust user-agent information<commit_after>use super::{Result, Error};

use std::sync::mpsc;

use websocket::ws::sender::Sender as SenderTrait;
use websocket::client::{Client, Sender, Receiver};
use websocket::stream::WebSocketStream;
use websocket::message::{Message as WsMessage, Type as MessageType};

use serde_json;
use serde_json::builder::ObjectBuilder;

use super::model::*;

/// The websocket protocol version expected.
const VERSION: u64 = 3;

/// Websocket connection to the Discord servers.
pub struct Connection {
	keepalive_channel: mpsc::Sender<Status>,
	receiver: Receiver<WebSocketStream>,
	ready_event: Option<Event>,
	/// Known state composed from received events
	pub state: State,
}

impl Connection {
	pub fn new(url: &str, token: &str) -> Result<Connection> {
		// establish the websocket connection
		let url = match ::websocket::client::request::Url::parse(url) {
			Ok(url) => url,
			Err(_) => return Err(Error::Other("Invalid URL in Connection::new()"))
		};
		let response = try!(try!(Client::connect(url)).send());
		try!(response.validate());
		let (mut sender, mut receiver) = response.begin().split();

		// send the handshake
		let map = ObjectBuilder::new()
			.insert("op", 2)
			.insert_object("d", |object| object
				.insert("token", token)
				.insert_object("properties", |object| object
					.insert("$os", ::std::env::consts::OS)
					.insert("$browser", "Discord library for Rust")
					.insert("$device", "discord-rs")
					.insert("$referring_domain", "")
					.insert("$referrer", "")
				)
				.insert("v", 3)
			)
			.unwrap();
		try!(sender.send_message(&WsMessage::text(try!(serde_json::to_string(&map)))));

		// read the Ready event
		let ready = try!(recv_message(&mut receiver));
		let state = try!(State::new(ready.clone()));
		let heartbeat_interval = state.heartbeat_interval;

		// spawn the keepalive thread
		let (tx, rx) = mpsc::channel();
		::std::thread::spawn(move || keepalive(heartbeat_interval, sender, rx));

		// return the connection
		Ok(Connection {
			keepalive_channel: tx,
			receiver: receiver,
			ready_event: Some(ready),
			state: state,
		})
	}

	pub fn set_game_id(&mut self, game_id: Option<u64>) {
		let _ = self.keepalive_channel.send(Status::SetGameId(game_id));
	}

	pub fn recv_event(&mut self) -> Result<Event> {
		// clear the ready event
		if let Some(ready) = self.ready_event.take() {
			Ok(ready)
		} else {
			match recv_message(&mut self.receiver) {
				Err(err) => Err(err),
				Ok(event) => {
					self.state.update(&event);
					Ok(event)
				}
			}
		}
	}

	pub fn shutdown(&mut self) -> Result<()> {
		let _ = self.keepalive_channel.send(Status::Shutdown);
		try!(self.receiver.get_mut().get_mut().shutdown(::std::net::Shutdown::Both));
		Ok(())
	}
}

fn recv_message(receiver: &mut Receiver<WebSocketStream>) -> Result<Event> {
	use websocket::ws::receiver::Receiver;
	let message: WsMessage = try!(receiver.recv_message());
	if message.opcode == MessageType::Close {
		Ok(Event::Closed(message.cd_status_code.unwrap_or(0xffff)))
	} else if message.opcode != MessageType::Text {
		println!("Unexpected message: {:?}", message);
		Ok(Event::Closed(0xfffe))
	} else {
		let json: serde_json::Value = try!(serde_json::from_reader(&message.payload[..]));
		let original = format!("{:?}", json);
		match Event::decode(json) {
			Ok(event) => Ok(event),
			Err(err) => {
				// If there was a decode failure, print the original json for debugging
				println!("<<< {} >>>", original);
				Err(err)
			}
		}
	}
}

enum Status {
	Shutdown,
	SetGameId(Option<u64>),
}

fn keepalive(interval: u64, mut sender: Sender<WebSocketStream>, channel: mpsc::Receiver<Status>) {
	let mut countdown = interval;
	let mut game_id = None;
	'outer: loop {
		// TODO: this is not a precise timer, but it's good enough for now
		::std::thread::sleep_ms(100);
		countdown = countdown.saturating_sub(100);

		loop {
			match channel.try_recv() {
				Ok(Status::Shutdown) => break 'outer,
				Ok(Status::SetGameId(id)) => { game_id = id; countdown = 0; },
				Err(mpsc::TryRecvError::Empty) => break,
				Err(mpsc::TryRecvError::Disconnected) => break 'outer,
			}
		}

		if countdown == 0 {
			countdown = interval;
			let map = ObjectBuilder::new()
				.insert("op", 3)
				.insert_object("d", |object| object
					.insert("idle_since", serde_json::Value::Null)
					.insert("game_id", game_id)
				)
				.unwrap();
			let json = match serde_json::to_string(&map) {
				Ok(json) => json,
				Err(e) => return println!("error jsoning ping: {:?}", e)
			};
			match sender.send_message(&WsMessage::text(json)) {
				Ok(()) => {},
				Err(e) => return println!("error sending ping: {:?}", e)
			}
		}
	}
	let _ = sender.get_mut().shutdown(::std::net::Shutdown::Both);
}

/// State tracking for events received over Discord.
pub struct State {
	user: CurrentUser,
	session_id: String,
	heartbeat_interval: u64,
	private_channels: Vec<PrivateChannel>,
	servers: Vec<LiveServer>,
}

impl State {
	fn new(ready: Event) -> Result<State> {
		match ready {
			Event::Ready { version, user, session_id, heartbeat_interval, private_channels, servers, read_state: _ } => {
				if version != VERSION {
					println!("[Warning] Got version {} instead of {}", version, VERSION);
					return Err(Error::Other("Wrong version specified"))
				}
				Ok(State {
					user: user,
					session_id: session_id,
					heartbeat_interval: heartbeat_interval,
					private_channels: private_channels,
					servers: servers,
				})
			},
			_ => Err(Error::Other("First event for State must be Ready")),
		}
	}

	fn update(&mut self, event: &Event) {
		match *event {
			Event::UserUpdate(ref user) => self.user = user.clone(),
			Event::VoiceStateUpdate(ref server, ref state) => {
				self.servers.iter_mut().find(|s| s.id == *server).map(|srv| {
					match srv.voice_states.iter_mut().find(|u| u.user_id == state.user_id) {
						Some(srv_state) => { srv_state.clone_from(state); return }
						None => {}
					}
					srv.voice_states.push(state.clone());
				});
			}
			Event::PresenceUpdate { ref server_id, ref presence, roles: _ } => {
				// TODO: double-check this
				self.servers.iter_mut().find(|s| s.id == *server_id).map(|srv| {
					match srv.presences.iter_mut().find(|u| u.user_id == presence.user_id) {
						Some(srv_presence) => { srv_presence.clone_from(presence); return }
						None => {}
					}
					srv.presences.push(presence.clone());
				});
			}
			Event::ServerCreate(ref server) => self.servers.push(server.clone()),
			Event::ServerUpdate(ref server) => {
				self.servers.iter_mut().find(|s| s.id == server.id).map(|srv| {
					srv.name.clone_from(&server.name);
					srv.joined_at.clone_from(&server.joined_at);
					srv.afk_timeout = server.afk_timeout;
					srv.afk_channel_id.clone_from(&server.afk_channel_id);
					srv.icon.clone_from(&server.icon);
					srv.roles.clone_from(&server.roles);
					srv.region.clone_from(&server.region);
					// embed_enabled and embed_channel_id skipped
					srv.owner_id.clone_from(&server.owner_id);
				});
			}
			Event::ServerDelete(ref server) => self.servers.retain(|s| s.id != server.id),
			Event::ServerMemberAdd { ref server_id, ref joined_at, ref roles, ref user } => {
				self.servers.iter_mut().find(|s| s.id == *server_id).map(|srv| {
					srv.members.push(Member {
						user: user.clone(),
						roles: roles.clone(),
						joined_at: joined_at.clone(),
						mute: false,
						deaf: false,
					})
				});
			}
			Event::ServerMemberUpdate { ref server_id, ref roles, ref user } => {
				self.servers.iter_mut().find(|s| s.id == *server_id).map(|srv| {
					srv.members.iter_mut().find(|m| m.user.id == user.id).map(|member| {
						member.user.clone_from(user);
						member.roles.clone_from(roles);
					})
				});
			}
			Event::ServerMemberRemove(ref server_id, ref user) => {
				self.servers.iter_mut().find(|s| s.id == *server_id).map(|srv| {
					srv.members.retain(|m| m.user.id != user.id);
				});
			}
			Event::ServerRoleCreate(ref server_id, ref role) => {
				self.servers.iter_mut().find(|s| s.id == *server_id).map(|srv| {
					srv.roles.push(role.clone());
				});
			}
			Event::ServerRoleUpdate(ref server_id, ref role) => {
				self.servers.iter_mut().find(|s| s.id == *server_id).map(|srv| {
					srv.roles.iter_mut().find(|r| r.id == role.id).map(|srv_role| {
						srv_role.clone_from(role);
					});
				});
			}
			Event::ServerRoleDelete(ref server_id, ref role_id) => {
				self.servers.iter_mut().find(|s| s.id == *server_id).map(|srv| {
					srv.roles.retain(|r| r.id != *role_id);
				});
			}
			Event::ChannelCreate(ref channel) => match *channel {
				Channel::Private(ref channel) => {
					self.private_channels.push(channel.clone());
				}
				Channel::Public(ref channel) => {
					self.servers.iter_mut().find(|s| s.id == channel.server_id).map(|srv| {
						srv.channels.push(channel.clone());
					});
				}
			},
			Event::ChannelUpdate(ref channel) => match *channel {
				Channel::Private(ref channel) => {
					self.private_channels.iter_mut().find(|c| c.id == channel.id).map(|chan| {
						chan.clone_from(channel);
					});
				}
				Channel::Public(ref channel) => {
					self.servers.iter_mut().find(|s| s.id == channel.server_id).map(|srv| {
						srv.channels.iter_mut().find(|c| c.id == channel.id).map(|chan| {
							chan.clone_from(channel);
						})
					});
				}
			},
			Event::ChannelDelete(ref channel) => match *channel {
				Channel::Private(ref channel) => {
					self.private_channels.retain(|c| c.id != channel.id);
				}
				Channel::Public(ref channel) => {
					self.servers.iter_mut().find(|s| s.id == channel.server_id).map(|srv| {
						srv.channels.retain(|c| c.id != channel.id);
					});
				}
			},
			_ => {}
		}
	}

	#[inline]
	pub fn user(&self) -> &CurrentUser { &self.user }

	#[inline]
	pub fn session_id(&self) -> &str { &self.session_id }

	#[inline]
	pub fn private_channels(&self) -> &[PrivateChannel] { &self.private_channels }

	#[inline]
	pub fn servers(&self) -> &[LiveServer] { &self.servers }

	pub fn find_channel(&self, id: &ChannelId) -> Option<ChannelRef> {
		for server in &self.servers {
			for channel in &server.channels {
				if channel.id == *id {
					return Some(ChannelRef::Public(server, channel))
				}
			}
		}
		for channel in &self.private_channels {
			if channel.id == *id {
				return Some(ChannelRef::Private(channel))
			}
		}
		None
	}
}

/// A reference to a private or public channel
pub enum ChannelRef<'a> {
	/// A private channel
	Private(&'a PrivateChannel),
	/// A public channel and its server
	Public(&'a LiveServer, &'a PublicChannel),
}
<|endoftext|>


<commit_before>pub mod window {
    use cocoa::base::id;
    use cocoa::foundation::NSUInteger;
    use cocoa::appkit::NSWindow;
    use core_graphics::geometry::{CGRect, CGPoint, CGSize};
    use objc::runtime::{BOOL, Class, YES};
    use raw::{FromRaw, FromRawError, IntoRaw};
    use std::error::Error;
    use std::fmt;
    use std::marker;
    use std::ops::{Deref, DerefMut};
    use sys::{MTLClearColor, MTLPixelFormat};
    use winit;
    use winit::os::macos::WindowExt;
    use {ClearColor, Device, PixelFormat, RenderPassDescriptor, Texture};

    pub use winit::{
        CursorState,
        Event,
        MonitorId,
        MouseCursor,
        PollEventsIterator,
        WaitEventsIterator,
        ElementState,
        MouseButton,
        MouseScrollDelta,
        Touch,
        TouchPhase,
        ScanCode,
        VirtualKeyCode
    };

    pub struct WindowBuilder {
        window: winit::WindowBuilder,
        device: Device
    }

    #[derive(Debug)]
    pub enum CreationError {
        ViewCreation(ViewError),
        Winit(winit::CreationError)
    }

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

    impl Error for CreationError {
        fn description(&self) -> &str {
            match *self {
                CreationError::ViewCreation(ref e) => e.description(),
                CreationError::Winit(ref e) => e.description()
            }
        }

        fn cause(&self) -> Option<&Error> {
            match *self {
                CreationError::ViewCreation(ref e) => Some(e),
                CreationError::Winit(ref e) => Some(e)
            }
        }
    }

    impl From<winit::CreationError> for CreationError {
        fn from(error: winit::CreationError) -> Self {
            CreationError::Winit(error)
        }
    }

    impl From<ViewError> for CreationError {
        fn from(error: ViewError) -> Self {
            CreationError::ViewCreation(error)
        }
    }

    impl WindowBuilder {
        /// Initializes a new `WindowBuilder` with default values.
        #[inline]
        pub fn new(device: Device) -> Self {
            WindowBuilder {
                window: winit::WindowBuilder::new(),
                device: device
            }
        }

        /// Requests the window to be of specific dimensions.
        ///
        /// Width and height are in pixels.
        #[inline]
        pub fn with_dimensions(self, width: u32, height: u32) -> WindowBuilder {
            WindowBuilder {window: self.window.with_dimensions(width, height), ..self}
        }

        /// Sets a minimum dimension size for the window
        ///
        /// Width and height are in pixels.
        #[inline]
        pub fn with_min_dimensions(self, width: u32, height: u32) -> WindowBuilder {
            WindowBuilder {window: self.window.with_min_dimensions(width, height), ..self}
        }

        /// Sets a maximum dimension size for the window
        ///
        /// Width and height are in pixels.
        #[inline]
        pub fn with_max_dimensions(self, width: u32, height: u32) -> WindowBuilder {
            WindowBuilder {window: self.window.with_max_dimensions(width, height), ..self}
        }

        /// Requests a specific title for the window.
        #[inline]
        pub fn with_title(self, title: String) -> WindowBuilder {
            WindowBuilder {window: self.window.with_title(title), ..self}
        }

        /// Requests fullscreen mode.
        ///
        /// If you don't specify dimensions for the window, it will match the monitor's.
        #[inline]
        pub fn with_fullscreen(self, monitor: MonitorId) -> WindowBuilder {
            WindowBuilder {window: self.window.with_fullscreen(monitor), ..self}
        }

        /// Sets whether the window will be initially hidden or visible.
        #[inline]
        pub fn with_visibility(self, visible: bool) -> WindowBuilder {
            WindowBuilder {window: self.window.with_visibility(visible), ..self}
        }

        /// Sets whether the background of the window should be transparent.
        #[inline]
        pub fn with_transparency(self, transparent: bool) -> WindowBuilder {
            WindowBuilder {window: self.window.with_transparency(transparent), ..self}
        }

        /// Sets whether the window should have a border, a title bar, etc.
        #[inline]
        pub fn with_decorations(self, decorations: bool) -> WindowBuilder {
            WindowBuilder {window: self.window.with_decorations(decorations), ..self}
        }

        /// Enables multitouch
        #[inline]
        pub fn with_multitouch(self) -> WindowBuilder {
            WindowBuilder {window: self.window.with_multitouch(), ..self}
        }

        /// Builds the window.
        ///
        /// Error should be very rare and only occur in case of permission denied, incompatible system,
        /// out of memory, etc.
        pub fn build(self) -> Result<Window, CreationError> {
            let window = try!(self.window.build());
            let view = try!(View::new(&window, self.device));

            unsafe {
                let native_window: id = window.get_nswindow() as id;
                native_window.setContentView_(view.0);
            }

            Ok(Window {
                window: window,
                view: view
            })
        }

        /// Builds the window.
        ///
        /// The context is build in a *strict* way. That means that if the backend couldn't give
        /// you what you requested, an `Err` will be returned.
        #[inline]
        pub fn build_strict(self) -> Result<Window, CreationError> {
            self.build()
        }
    }

    pub struct Window {
        window: winit::Window,
        pub view: View
    }

    impl Window {
        pub fn poll_events(&self) -> PollEventsIterator {
            self.window.poll_events()
        }

        pub fn wait_events(&self) -> WaitEventsIterator {
            self.window.wait_events()
        }

        pub fn window(&self) -> Ref<winit::Window> {
            Ref(&self.window)
        }
    }

    pub struct View(id);
    impl_from_into_raw!(View, of class "MTKView");

    impl View {
        fn new(window: &winit::Window, device: Device) -> Result<Self, ViewError> {
            let window_origin = {
                let (x, y) = try!(window.get_position().ok_or(ViewError::no_window()));
                CGPoint { x: x as f64, y: y as f64 }
            };

            let window_size = {
                let (w, h) = try!(window.get_inner_size().ok_or(ViewError::no_window()));
                CGSize { width: w as f64, height: h as f64 }
            };

            let view_frame = CGRect { origin: window_origin, size: window_size };

            let view_object: id = unsafe {
                // Dummy function to ensure that we link against MetalKit
                #[allow(dead_code)]
                #[link(name = "MetalKit", kind = "framework")]
                extern "C" {
                    fn MTKModelIOVertexDescriptorFromMetal(metalDescriptor: id) -> id;
                }

                let view_class = Class::get("MTKView").expect("Could not find MTKView class");
                let view: id = msg_send![view_class, alloc];
                msg_send![view, initWithFrame:view_frame
                                       device:device.into_raw()]
            };

            View::from_raw(view_object).map_err(From::from)
        }

        pub fn device<'a>(&self) -> Option<PhantomRef<'a, Device>> {
            let device = unsafe {
                Device::from_raw(msg_send![self.0, device])
            };
            device.ok().map(|d| PhantomRef(d, marker::PhantomData))
        }

        pub fn device_mut<'a>(&mut self) -> Option<PhantomRefMut<'a, Device>> {
            let device = unsafe {
                Device::from_raw(msg_send![self.0, device])
            };
            device.ok().map(|d| PhantomRefMut(d, marker::PhantomData))
        }

        pub fn set_device(&mut self, device: Device) {
            unsafe { msg_send![self.0, setDevice:device] }
        }

        pub fn clear_color(&self) -> ClearColor {
            let color: MTLClearColor = unsafe {
                msg_send![self.0, clearColor]
            };
            color.into()
        }

        pub fn set_clear_color<C: Into<MTLClearColor>>(&mut self, clear_color: C) {
            unsafe { msg_send![self.0, setClearColor:clear_color.into()] }
        }

        pub fn clear_depth(&self) -> f64 {
            unsafe { msg_send![self.0, clearDepth] }
        }

        pub fn set_clear_depth(&mut self, clear_depth: f64) {
            unsafe { msg_send![self.0, setClearDepth:clear_depth] }
        }

        pub fn clear_stencil(&self) -> u32 {
            unsafe { msg_send![self.0, clearStencil] }
        }

        pub fn set_clear_stencil(&mut self, clear_stencil: u32) {
            unsafe { msg_send![self.0, setClearStencil:clear_stencil] }
        }

        pub fn color_pixel_format(&self) -> PixelFormat {
            let pixel_format: MTLPixelFormat = unsafe {
                msg_send![self.0, colorPixelFormat]
            };
            pixel_format.into()
        }

        pub fn set_color_pixel_format<P: Into<MTLPixelFormat>>(&mut self, color_pixel_format: P) {
            unsafe { msg_send![self.0, setColorPixelFormat:color_pixel_format.into()] }
        }

        pub fn depth_stencil_pixel_format(&self) -> PixelFormat {
            let pixel_format: MTLPixelFormat = unsafe { msg_send![self.0, depthStencilPixelFormat] };
            pixel_format.into()
        }

        pub fn set_depth_stencil_pixel_format<P: Into<MTLPixelFormat>>(&mut self, depth_stencil_pixel_format: P) {
            unsafe { msg_send![self.0, setDepthStencilPixelFormat:depth_stencil_pixel_format.into()] }
        }

        pub fn sample_count(&self) -> usize {
            let sample_count: NSUInteger = unsafe {
                msg_send![self.0, sampleCount]
            };
            sample_count as usize
        }

        pub fn set_sample_count(&mut self, sample_count: usize) {
            let sample_count = sample_count as NSUInteger;
            unsafe { msg_send![self.0, setSampleCount:sample_count] }
        }

        pub fn current_render_pass_descriptor(&self) -> Option<PhantomRef<RenderPassDescriptor>> {
            let descriptor: id = unsafe { msg_send![self.0, currentRenderPassDescriptor] };
            FromRaw::from_raw(descriptor).ok().map(|d| PhantomRef(d, marker::PhantomData))
        }

        pub fn current_depth_stencil_texture(&self) -> Option<PhantomRef<Texture>> {
            let texture: id = unsafe { msg_send![self.0, depthStencilTexture] };
            FromRaw::from_raw(texture).ok().map(|t| PhantomRef(t, marker::PhantomData))
        }

        pub fn multisample_color_texture(&self) -> Option<PhantomRef<Texture>> {
            let texture: id = unsafe { msg_send![self.0, multisampleColorTexture] };
            FromRaw::from_raw(texture).ok().map(|t| PhantomRef(t, marker::PhantomData))
        }

        pub fn preferred_frames_per_second(&self) -> usize {
            let fps: NSUInteger = unsafe { msg_send![self.0, sampleCount] };
            fps as usize
        }

        pub fn set_preferred_frames_per_second(&self, preferred_fps: usize) {
            let preferred_fps = preferred_fps as NSUInteger;
            unsafe { msg_send![self.0, setPreferredFramesPerSecond:preferred_fps] }
        }

        pub fn is_paused(&self) -> bool {
            let is_paused: BOOL = unsafe { msg_send![self.0, isPaused] };
            is_paused == YES
        }

        pub fn draw(&self) {
            unsafe { msg_send![self.0, draw] }
        }
    }

    #[derive(Clone, Debug)]
    pub struct ViewError(ViewErrorInner);

    #[derive(Clone, Debug)]
    enum ViewErrorInner {
        NoWindow,
        CreateError(FromRawError)
    }

    impl ViewError {
        fn no_window() -> Self {
            ViewError(ViewErrorInner::NoWindow)
        }
    }

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

    impl Error for ViewError {
        fn description(&self) -> &str {
            match self.0 {
                ViewErrorInner::NoWindow => "The native window no longer exists",
                ViewErrorInner::CreateError(_) => "There was an issue creating the view",
            }
        }

        fn cause(&self) -> Option<&Error> {
            if let ViewErrorInner::CreateError(ref e) = self.0 {
                Some(e)
            } else {
                None
            }
        }
    }

    impl From<FromRawError> for ViewError {
        fn from(error: FromRawError) -> Self {
            ViewError(ViewErrorInner::CreateError(error))
        }
    }

    pub struct Ref<'a, T: 'a>(&'a T);

    impl<'a, T> Deref for Ref<'a, T> {
        type Target = T;
        fn deref(&self) -> &Self::Target {
            self.0
        }
    }

    pub struct PhantomRef<'a, T: 'a>(T, marker::PhantomData<&'a ()>);

    impl<'a, T> Deref for PhantomRef<'a, T> {
        type Target = T;
        fn deref(&self) -> &Self::Target {
            &self.0
        }
    }

    pub struct PhantomRefMut<'a, T: 'a>(T, marker::PhantomData<&'a mut ()>);

    impl<'a, T> Deref for PhantomRefMut<'a, T> {
        type Target = T;
        fn deref(&self) -> &Self::Target {
            &self.0
        }
    }

    impl<'a, T> DerefMut for PhantomRefMut<'a, T> {
        fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
            &mut self.0
        }
    }
}
<commit_msg>Remove unnecessary line breaks<commit_after>pub mod window {
    use cocoa::base::id;
    use cocoa::foundation::NSUInteger;
    use cocoa::appkit::NSWindow;
    use core_graphics::geometry::{CGRect, CGPoint, CGSize};
    use objc::runtime::{BOOL, Class, YES};
    use raw::{FromRaw, FromRawError, IntoRaw};
    use std::error::Error;
    use std::fmt;
    use std::marker;
    use std::ops::{Deref, DerefMut};
    use sys::{MTLClearColor, MTLPixelFormat};
    use winit;
    use winit::os::macos::WindowExt;
    use {ClearColor, Device, PixelFormat, RenderPassDescriptor, Texture};

    pub use winit::{
        CursorState,
        Event,
        MonitorId,
        MouseCursor,
        PollEventsIterator,
        WaitEventsIterator,
        ElementState,
        MouseButton,
        MouseScrollDelta,
        Touch,
        TouchPhase,
        ScanCode,
        VirtualKeyCode
    };

    pub struct WindowBuilder {
        window: winit::WindowBuilder,
        device: Device
    }

    #[derive(Debug)]
    pub enum CreationError {
        ViewCreation(ViewError),
        Winit(winit::CreationError)
    }

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

    impl Error for CreationError {
        fn description(&self) -> &str {
            match *self {
                CreationError::ViewCreation(ref e) => e.description(),
                CreationError::Winit(ref e) => e.description()
            }
        }

        fn cause(&self) -> Option<&Error> {
            match *self {
                CreationError::ViewCreation(ref e) => Some(e),
                CreationError::Winit(ref e) => Some(e)
            }
        }
    }

    impl From<winit::CreationError> for CreationError {
        fn from(error: winit::CreationError) -> Self {
            CreationError::Winit(error)
        }
    }

    impl From<ViewError> for CreationError {
        fn from(error: ViewError) -> Self {
            CreationError::ViewCreation(error)
        }
    }

    impl WindowBuilder {
        /// Initializes a new `WindowBuilder` with default values.
        #[inline]
        pub fn new(device: Device) -> Self {
            WindowBuilder {
                window: winit::WindowBuilder::new(),
                device: device
            }
        }

        /// Requests the window to be of specific dimensions.
        ///
        /// Width and height are in pixels.
        #[inline]
        pub fn with_dimensions(self, width: u32, height: u32) -> WindowBuilder {
            WindowBuilder {window: self.window.with_dimensions(width, height), ..self}
        }

        /// Sets a minimum dimension size for the window
        ///
        /// Width and height are in pixels.
        #[inline]
        pub fn with_min_dimensions(self, width: u32, height: u32) -> WindowBuilder {
            WindowBuilder {window: self.window.with_min_dimensions(width, height), ..self}
        }

        /// Sets a maximum dimension size for the window
        ///
        /// Width and height are in pixels.
        #[inline]
        pub fn with_max_dimensions(self, width: u32, height: u32) -> WindowBuilder {
            WindowBuilder {window: self.window.with_max_dimensions(width, height), ..self}
        }

        /// Requests a specific title for the window.
        #[inline]
        pub fn with_title(self, title: String) -> WindowBuilder {
            WindowBuilder {window: self.window.with_title(title), ..self}
        }

        /// Requests fullscreen mode.
        ///
        /// If you don't specify dimensions for the window, it will match the monitor's.
        #[inline]
        pub fn with_fullscreen(self, monitor: MonitorId) -> WindowBuilder {
            WindowBuilder {window: self.window.with_fullscreen(monitor), ..self}
        }

        /// Sets whether the window will be initially hidden or visible.
        #[inline]
        pub fn with_visibility(self, visible: bool) -> WindowBuilder {
            WindowBuilder {window: self.window.with_visibility(visible), ..self}
        }

        /// Sets whether the background of the window should be transparent.
        #[inline]
        pub fn with_transparency(self, transparent: bool) -> WindowBuilder {
            WindowBuilder {window: self.window.with_transparency(transparent), ..self}
        }

        /// Sets whether the window should have a border, a title bar, etc.
        #[inline]
        pub fn with_decorations(self, decorations: bool) -> WindowBuilder {
            WindowBuilder {window: self.window.with_decorations(decorations), ..self}
        }

        /// Enables multitouch
        #[inline]
        pub fn with_multitouch(self) -> WindowBuilder {
            WindowBuilder {window: self.window.with_multitouch(), ..self}
        }

        /// Builds the window.
        ///
        /// Error should be very rare and only occur in case of permission denied, incompatible system,
        /// out of memory, etc.
        pub fn build(self) -> Result<Window, CreationError> {
            let window = try!(self.window.build());
            let view = try!(View::new(&window, self.device));

            unsafe {
                let native_window: id = window.get_nswindow() as id;
                native_window.setContentView_(view.0);
            }

            Ok(Window {
                window: window,
                view: view
            })
        }

        /// Builds the window.
        ///
        /// The context is build in a *strict* way. That means that if the backend couldn't give
        /// you what you requested, an `Err` will be returned.
        #[inline]
        pub fn build_strict(self) -> Result<Window, CreationError> {
            self.build()
        }
    }

    pub struct Window {
        window: winit::Window,
        pub view: View
    }

    impl Window {
        pub fn poll_events(&self) -> PollEventsIterator {
            self.window.poll_events()
        }

        pub fn wait_events(&self) -> WaitEventsIterator {
            self.window.wait_events()
        }

        pub fn window(&self) -> Ref<winit::Window> {
            Ref(&self.window)
        }
    }

    pub struct View(id);
    impl_from_into_raw!(View, of class "MTKView");

    impl View {
        fn new(window: &winit::Window, device: Device) -> Result<Self, ViewError> {
            let window_origin = {
                let (x, y) = try!(window.get_position().ok_or(ViewError::no_window()));
                CGPoint { x: x as f64, y: y as f64 }
            };

            let window_size = {
                let (w, h) = try!(window.get_inner_size().ok_or(ViewError::no_window()));
                CGSize { width: w as f64, height: h as f64 }
            };

            let view_frame = CGRect { origin: window_origin, size: window_size };

            let view_object: id = unsafe {
                // Dummy function to ensure that we link against MetalKit
                #[allow(dead_code)]
                #[link(name = "MetalKit", kind = "framework")]
                extern "C" {
                    fn MTKModelIOVertexDescriptorFromMetal(metalDescriptor: id) -> id;
                }

                let view_class = Class::get("MTKView").expect("Could not find MTKView class");
                let view: id = msg_send![view_class, alloc];
                msg_send![view, initWithFrame:view_frame
                                       device:device.into_raw()]
            };

            View::from_raw(view_object).map_err(From::from)
        }

        pub fn device<'a>(&self) -> Option<PhantomRef<'a, Device>> {
            let device = unsafe {
                Device::from_raw(msg_send![self.0, device])
            };
            device.ok().map(|d| PhantomRef(d, marker::PhantomData))
        }

        pub fn device_mut<'a>(&mut self) -> Option<PhantomRefMut<'a, Device>> {
            let device = unsafe {
                Device::from_raw(msg_send![self.0, device])
            };
            device.ok().map(|d| PhantomRefMut(d, marker::PhantomData))
        }

        pub fn set_device(&mut self, device: Device) {
            unsafe { msg_send![self.0, setDevice:device] }
        }

        pub fn clear_color(&self) -> ClearColor {
            let color: MTLClearColor = unsafe { msg_send![self.0, clearColor] };
            color.into()
        }

        pub fn set_clear_color<C: Into<MTLClearColor>>(&mut self, clear_color: C) {
            unsafe { msg_send![self.0, setClearColor:clear_color.into()] }
        }

        pub fn clear_depth(&self) -> f64 {
            unsafe { msg_send![self.0, clearDepth] }
        }

        pub fn set_clear_depth(&mut self, clear_depth: f64) {
            unsafe { msg_send![self.0, setClearDepth:clear_depth] }
        }

        pub fn clear_stencil(&self) -> u32 {
            unsafe { msg_send![self.0, clearStencil] }
        }

        pub fn set_clear_stencil(&mut self, clear_stencil: u32) {
            unsafe { msg_send![self.0, setClearStencil:clear_stencil] }
        }

        pub fn color_pixel_format(&self) -> PixelFormat {
            let pixel_format: MTLPixelFormat = unsafe { msg_send![self.0, colorPixelFormat] };
            pixel_format.into()
        }

        pub fn set_color_pixel_format<P: Into<MTLPixelFormat>>(&mut self, color_pixel_format: P) {
            unsafe { msg_send![self.0, setColorPixelFormat:color_pixel_format.into()] }
        }

        pub fn depth_stencil_pixel_format(&self) -> PixelFormat {
            let pixel_format: MTLPixelFormat = unsafe { msg_send![self.0, depthStencilPixelFormat] };
            pixel_format.into()
        }

        pub fn set_depth_stencil_pixel_format<P: Into<MTLPixelFormat>>(&mut self, depth_stencil_pixel_format: P) {
            unsafe { msg_send![self.0, setDepthStencilPixelFormat:depth_stencil_pixel_format.into()] }
        }

        pub fn sample_count(&self) -> usize {
            let sample_count: NSUInteger = unsafe {
                msg_send![self.0, sampleCount]
            };
            sample_count as usize
        }

        pub fn set_sample_count(&mut self, sample_count: usize) {
            let sample_count = sample_count as NSUInteger;
            unsafe { msg_send![self.0, setSampleCount:sample_count] }
        }

        pub fn current_render_pass_descriptor(&self) -> Option<PhantomRef<RenderPassDescriptor>> {
            let descriptor: id = unsafe { msg_send![self.0, currentRenderPassDescriptor] };
            FromRaw::from_raw(descriptor).ok().map(|d| PhantomRef(d, marker::PhantomData))
        }

        pub fn current_depth_stencil_texture(&self) -> Option<PhantomRef<Texture>> {
            let texture: id = unsafe { msg_send![self.0, depthStencilTexture] };
            FromRaw::from_raw(texture).ok().map(|t| PhantomRef(t, marker::PhantomData))
        }

        pub fn multisample_color_texture(&self) -> Option<PhantomRef<Texture>> {
            let texture: id = unsafe { msg_send![self.0, multisampleColorTexture] };
            FromRaw::from_raw(texture).ok().map(|t| PhantomRef(t, marker::PhantomData))
        }

        pub fn preferred_frames_per_second(&self) -> usize {
            let fps: NSUInteger = unsafe { msg_send![self.0, sampleCount] };
            fps as usize
        }

        pub fn set_preferred_frames_per_second(&self, preferred_fps: usize) {
            let preferred_fps = preferred_fps as NSUInteger;
            unsafe { msg_send![self.0, setPreferredFramesPerSecond:preferred_fps] }
        }

        pub fn is_paused(&self) -> bool {
            let is_paused: BOOL = unsafe { msg_send![self.0, isPaused] };
            is_paused == YES
        }

        pub fn draw(&self) {
            unsafe { msg_send![self.0, draw] }
        }
    }

    #[derive(Clone, Debug)]
    pub struct ViewError(ViewErrorInner);

    #[derive(Clone, Debug)]
    enum ViewErrorInner {
        NoWindow,
        CreateError(FromRawError)
    }

    impl ViewError {
        fn no_window() -> Self {
            ViewError(ViewErrorInner::NoWindow)
        }
    }

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

    impl Error for ViewError {
        fn description(&self) -> &str {
            match self.0 {
                ViewErrorInner::NoWindow => "The native window no longer exists",
                ViewErrorInner::CreateError(_) => "There was an issue creating the view",
            }
        }

        fn cause(&self) -> Option<&Error> {
            if let ViewErrorInner::CreateError(ref e) = self.0 {
                Some(e)
            } else {
                None
            }
        }
    }

    impl From<FromRawError> for ViewError {
        fn from(error: FromRawError) -> Self {
            ViewError(ViewErrorInner::CreateError(error))
        }
    }

    pub struct Ref<'a, T: 'a>(&'a T);

    impl<'a, T> Deref for Ref<'a, T> {
        type Target = T;
        fn deref(&self) -> &Self::Target {
            self.0
        }
    }

    pub struct PhantomRef<'a, T: 'a>(T, marker::PhantomData<&'a ()>);

    impl<'a, T> Deref for PhantomRef<'a, T> {
        type Target = T;
        fn deref(&self) -> &Self::Target {
            &self.0
        }
    }

    pub struct PhantomRefMut<'a, T: 'a>(T, marker::PhantomData<&'a mut ()>);

    impl<'a, T> Deref for PhantomRefMut<'a, T> {
        type Target = T;
        fn deref(&self) -> &Self::Target {
            &self.0
        }
    }

    impl<'a, T> DerefMut for PhantomRefMut<'a, T> {
        fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
            &mut self.0
        }
    }
}
<|endoftext|>


<commit_before>use Login;
use FromJson;
use post_json;

use std::collections::HashMap;
use json::JsonValue;

/// Returns a list of courses for a given login.
///
/// # Arguments
///
/// * `login` - Login
///
/// # Example
///
/// ```
/// use htwdresden::{Login, grades}
///
/// let login = Login::new("s#####", "password");
/// let courses = grades::get_courses(&login);
/// ```
pub fn get_courses(login: &Login) -> Option<Vec<Course>> {
    let url = "https://wwwqis.htw-dresden.de/appservice/getcourses";
    let mut map = HashMap::new();
    map.insert("sNummer", login.snumber.clone()); // is cloning ok?
    map.insert("RZLogin", login.password.clone());

    let json = post_json(url, map);
    let courses = Course::mult_from_json(json);
    Some(courses)
}

#[derive(Debug)]
pub struct Course {
    pub degree_txt: String,
    pub reg_version: String,
    pub deg_nr: String,
    pub course_nr: String,
    pub course_note: String,
}

impl FromJson for Course {
    fn from_json(json: JsonValue) -> Self {
        Course {
            degree_txt: String::from(json["AbschlTxt"].as_str().unwrap()),
            reg_version: String::from(json["POVersion"].as_str().unwrap()),
            deg_nr: String::from(json["AbschlNr"].as_str().unwrap()),
            course_nr: String::from(json["StgNr"].as_str().unwrap()),
            course_note: String::from(json["StgTxt"].as_str().unwrap()),
        }
    }
}

/// Returns a list of grades for a given login and course.
///
/// # Arguments
///
/// * `login` - Login
/// * `course` - Course
///
/// # Example
///
/// ```
/// use htwdresden::{Login, Course, grades};
///
/// let login = Login::new("s#####", "password");
/// let courses = grades::get_courses(&login);
/// let all_grades = grades::get_grades(&login, &courses[0]);
/// ```
pub fn get_grades(login: &Login, course: &Course) -> Option<Vec<Grade>> {
    let url = "https://wwwqis.htw-dresden.de/appservice/getgrades";
    let mut map = HashMap::new();
    map.insert("sNummer", login.snumber.clone());
    map.insert("RZLogin", login.password.clone());
    map.insert("AbschlNr", course.deg_nr.clone());
    map.insert("StgNr", course.course_nr.clone());
    map.insert("POVersion", course.reg_version.clone());

    let json = post_json(url, map);
    let grades = Grade::mult_from_json(json);
    Some(grades)
}

#[derive(Debug)]
pub struct Grade {
    pub exam_nr: String,
    pub status: String,
    pub ects_credits: String,
    pub exam_txt: String,
    pub semester: String,
    pub try_count: String,
    pub exam_date: String,
    pub grade: String,
    pub publish_date: String,
    pub exam_form: String,
    pub comment: String,
    pub ects_grade: String,
}

impl FromJson for Grade {
    fn from_json(json: JsonValue) -> Self {
        Grade {
            exam_nr: String::from(json["PrNr"].as_str().unwrap()),
            status: String::from(json["Status"].as_str().unwrap()),
            ects_credits: String::from(json["EctsCredits"].as_str().unwrap()),
            exam_txt: String::from(json["PrTxt"].as_str().unwrap()),
            semester: String::from(json["Semester"].as_str().unwrap()),
            try_count: String::from(json["Versuch"].as_str().unwrap()),
            exam_date: String::from(json["PrDatum"].as_str().unwrap()),
            grade: String::from(json["PrNote"].as_str().unwrap()),
            publish_date: String::from(json["VoDatum"].as_str().unwrap()),
            exam_form: String::from(json["PrForm"].as_str().unwrap()),
            comment: String::from(json["Vermerk"].as_str().unwrap()),
            ects_grade: String::from(json["EctsGrade"].as_str().unwrap()),
        }
    }
}
<commit_msg>fix doc example errors<commit_after>use Login;
use FromJson;
use post_json;

use std::collections::HashMap;
use json::JsonValue;

/// Returns a list of courses for a given login.
///
/// # Arguments
///
/// * `login` - Login
///
/// # Example
///
/// ```
/// use htwdresden::{Login, grades};
///
/// let login = Login::new("s#####", "password");
/// let courses = grades::get_courses(&login);
/// ```
pub fn get_courses(login: &Login) -> Option<Vec<Course>> {
    let url = "https://wwwqis.htw-dresden.de/appservice/getcourses";
    let mut map = HashMap::new();
    map.insert("sNummer", login.snumber.clone()); // is cloning ok?
    map.insert("RZLogin", login.password.clone());

    let json = post_json(url, map);
    let courses = Course::mult_from_json(json);
    Some(courses)
}

#[derive(Debug)]
pub struct Course {
    pub degree_txt: String,
    pub reg_version: String,
    pub deg_nr: String,
    pub course_nr: String,
    pub course_note: String,
}

impl FromJson for Course {
    fn from_json(json: JsonValue) -> Self {
        Course {
            degree_txt: String::from(json["AbschlTxt"].as_str().unwrap()),
            reg_version: String::from(json["POVersion"].as_str().unwrap()),
            deg_nr: String::from(json["AbschlNr"].as_str().unwrap()),
            course_nr: String::from(json["StgNr"].as_str().unwrap()),
            course_note: String::from(json["StgTxt"].as_str().unwrap()),
        }
    }
}

/// Returns a list of grades for a given login and course.
///
/// # Arguments
///
/// * `login` - Login
/// * `course` - Course
///
/// # Example
///
/// ```
/// use htwdresden::{Login, grades};
///
/// let login = Login::new("s#####", "password");
/// let courses = grades::get_courses(&login).unwrap();
/// let all_grades = grades::get_grades(&login, &courses[0]);
/// ```
pub fn get_grades(login: &Login, course: &Course) -> Option<Vec<Grade>> {
    let url = "https://wwwqis.htw-dresden.de/appservice/getgrades";
    let mut map = HashMap::new();
    map.insert("sNummer", login.snumber.clone());
    map.insert("RZLogin", login.password.clone());
    map.insert("AbschlNr", course.deg_nr.clone());
    map.insert("StgNr", course.course_nr.clone());
    map.insert("POVersion", course.reg_version.clone());

    let json = post_json(url, map);
    let grades = Grade::mult_from_json(json);
    Some(grades)
}

#[derive(Debug)]
pub struct Grade {
    pub exam_nr: String,
    pub status: String,
    pub ects_credits: String,
    pub exam_txt: String,
    pub semester: String,
    pub try_count: String,
    pub exam_date: String,
    pub grade: String,
    pub publish_date: String,
    pub exam_form: String,
    pub comment: String,
    pub ects_grade: String,
}

impl FromJson for Grade {
    fn from_json(json: JsonValue) -> Self {
        Grade {
            exam_nr: String::from(json["PrNr"].as_str().unwrap()),
            status: String::from(json["Status"].as_str().unwrap()),
            ects_credits: String::from(json["EctsCredits"].as_str().unwrap()),
            exam_txt: String::from(json["PrTxt"].as_str().unwrap()),
            semester: String::from(json["Semester"].as_str().unwrap()),
            try_count: String::from(json["Versuch"].as_str().unwrap()),
            exam_date: String::from(json["PrDatum"].as_str().unwrap()),
            grade: String::from(json["PrNote"].as_str().unwrap()),
            publish_date: String::from(json["VoDatum"].as_str().unwrap()),
            exam_form: String::from(json["PrForm"].as_str().unwrap()),
            comment: String::from(json["Vermerk"].as_str().unwrap()),
            ects_grade: String::from(json["EctsGrade"].as_str().unwrap()),
        }
    }
}
<|endoftext|>