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

use crate::io::ErrorKind;

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

#[macro_use]
pub mod weak;

pub mod alloc;
pub mod android;
pub mod args;
#[path = "../unix/cmath.rs"]
pub mod cmath;
pub mod condvar;
pub mod env;
pub mod fd;
pub mod fs;
pub mod futex;
pub mod io;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub mod kernel_copy;
#[cfg(target_os = "l4re")]
mod l4re;
pub mod memchr;
pub mod mutex;
#[cfg(not(target_os = "l4re"))]
pub mod net;
#[cfg(target_os = "l4re")]
pub use self::l4re::net;
pub mod os;
pub mod path;
pub mod pipe;
pub mod process;
pub mod rand;
pub mod rwlock;
pub mod stack_overflow;
pub mod stdio;
pub mod thread;
pub mod thread_local_dtor;
pub mod thread_local_key;
pub mod time;

pub use crate::sys_common::os_str_bytes as os_str;

// SAFETY: must be called only once during runtime initialization.
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
pub unsafe fn init(argc: isize, argv: *const *const u8) {
    // The standard streams might be closed on application startup. To prevent
    // std::io::{stdin, stdout,stderr} objects from using other unrelated file
    // resources opened later, we reopen standards streams when they are closed.
    sanitize_standard_fds();

    // By default, some platforms will send a *signal* when an EPIPE error
    // would otherwise be delivered. This runtime doesn't install a SIGPIPE
    // handler, causing it to kill the program, which isn't exactly what we
    // want!
    //
    // Hence, we set SIGPIPE to ignore when the program starts up in order
    // to prevent this problem.
    reset_sigpipe();

    stack_overflow::init();
    args::init(argc, argv);

    unsafe fn sanitize_standard_fds() {
        #[cfg(not(miri))]
        // The standard fds are always available in Miri.
        cfg_if::cfg_if! {
            if #[cfg(not(any(
                target_os = "emscripten",
                target_os = "fuchsia",
                target_os = "vxworks",
                // The poll on Darwin doesn't set POLLNVAL for closed fds.
                target_os = "macos",
                target_os = "ios",
                target_os = "redox",
            )))] {
                use crate::sys::os::errno;
                let pfds: &mut [_] = &mut [
                    libc::pollfd { fd: 0, events: 0, revents: 0 },
                    libc::pollfd { fd: 1, events: 0, revents: 0 },
                    libc::pollfd { fd: 2, events: 0, revents: 0 },
                ];
                while libc::poll(pfds.as_mut_ptr(), 3, 0) == -1 {
                    if errno() == libc::EINTR {
                        continue;
                    }
                    libc::abort();
                }
                for pfd in pfds {
                    if pfd.revents & libc::POLLNVAL == 0 {
                        continue;
                    }
                    if libc::open("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
                        // If the stream is closed but we failed to reopen it, abort the
                        // process. Otherwise we wouldn't preserve the safety of
                        // operations on the corresponding Rust object Stdin, Stdout, or
                        // Stderr.
                        libc::abort();
                    }
                }
            } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "redox"))] {
                use crate::sys::os::errno;
                for fd in 0..3 {
                    if libc::fcntl(fd, libc::F_GETFD) == -1 && errno() == libc::EBADF {
                        if libc::open("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
                            libc::abort();
                        }
                    }
                }
            }
        }
    }

    unsafe fn reset_sigpipe() {
        #[cfg(not(any(target_os = "emscripten", target_os = "fuchsia")))]
        assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR);
    }
}

// SAFETY: must be called only once during runtime cleanup.
// NOTE: this is not guaranteed to run, for example when the program aborts.
pub unsafe fn cleanup() {
    args::cleanup();
    stack_overflow::cleanup();
}

#[cfg(target_os = "android")]
pub use crate::sys::android::signal;
#[cfg(not(target_os = "android"))]
pub use libc::signal;

pub fn decode_error_kind(errno: i32) -> ErrorKind {
    match errno as libc::c_int {
        libc::ECONNREFUSED => ErrorKind::ConnectionRefused,
        libc::ECONNRESET => ErrorKind::ConnectionReset,
        libc::EPERM | libc::EACCES => ErrorKind::PermissionDenied,
        libc::EPIPE => ErrorKind::BrokenPipe,
        libc::ENOTCONN => ErrorKind::NotConnected,
        libc::ECONNABORTED => ErrorKind::ConnectionAborted,
        libc::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable,
        libc::EADDRINUSE => ErrorKind::AddrInUse,
        libc::ENOENT => ErrorKind::NotFound,
        libc::EINTR => ErrorKind::Interrupted,
        libc::EINVAL => ErrorKind::InvalidInput,
        libc::ETIMEDOUT => ErrorKind::TimedOut,
        libc::EEXIST => ErrorKind::AlreadyExists,
        libc::ENOSYS => ErrorKind::Unsupported,
        libc::ENOMEM => ErrorKind::OutOfMemory,

        // These two constants can have the same value on some systems,
        // but different values on others, so we can't use a match
        // clause
        x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => ErrorKind::WouldBlock,

        _ => ErrorKind::Uncategorized,
    }
}

#[doc(hidden)]
pub trait IsMinusOne {
    fn is_minus_one(&self) -> bool;
}

macro_rules! impl_is_minus_one {
    ($($t:ident)*) => ($(impl IsMinusOne for $t {
        fn is_minus_one(&self) -> bool {
            *self == -1
        }
    })*)
}

impl_is_minus_one! { i8 i16 i32 i64 isize }

pub fn cvt<T: IsMinusOne>(t: T) -> crate::io::Result<T> {
    if t.is_minus_one() { Err(crate::io::Error::last_os_error()) } else { Ok(t) }
}

pub fn cvt_r<T, F>(mut f: F) -> crate::io::Result<T>
where
    T: IsMinusOne,
    F: FnMut() -> T,
{
    loop {
        match cvt(f()) {
            Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
            other => return other,
        }
    }
}

pub fn cvt_nz(error: libc::c_int) -> crate::io::Result<()> {
    if error == 0 { Ok(()) } else { Err(crate::io::Error::from_raw_os_error(error)) }
}

// On Unix-like platforms, libc::abort will unregister signal handlers
// including the SIGABRT handler, preventing the abort from being blocked, and
// fclose streams, with the side effect of flushing them so libc buffered
// output will be printed.  Additionally the shell will generally print a more
// understandable error message like "Abort trap" rather than "Illegal
// instruction" that intrinsics::abort would cause, as intrinsics::abort is
// implemented as an illegal instruction.
pub fn abort_internal() -> ! {
    unsafe { libc::abort() }
}

cfg_if::cfg_if! {
    if #[cfg(target_os = "android")] {
        #[link(name = "dl")]
        #[link(name = "log")]
        #[link(name = "gcc")]
        extern "C" {}
    } else if #[cfg(target_os = "freebsd")] {
        #[link(name = "execinfo")]
        #[link(name = "pthread")]
        extern "C" {}
    } else if #[cfg(target_os = "netbsd")] {
        #[link(name = "pthread")]
        #[link(name = "rt")]
        extern "C" {}
    } else if #[cfg(any(target_os = "dragonfly", target_os = "openbsd"))] {
        #[link(name = "pthread")]
        extern "C" {}
    } else if #[cfg(target_os = "solaris")] {
        #[link(name = "socket")]
        #[link(name = "posix4")]
        #[link(name = "pthread")]
        #[link(name = "resolv")]
        extern "C" {}
    } else if #[cfg(target_os = "illumos")] {
        #[link(name = "socket")]
        #[link(name = "posix4")]
        #[link(name = "pthread")]
        #[link(name = "resolv")]
        #[link(name = "nsl")]
        // Use libumem for the (malloc-compatible) allocator
        #[link(name = "umem")]
        extern "C" {}
    } else if #[cfg(target_os = "macos")] {
        #[link(name = "System")]
        // res_init and friends require -lresolv on macOS/iOS.
        // See #41582 and http://blog.achernya.com/2013/03/os-x-has-silly-libsystem.html
        #[link(name = "resolv")]
        extern "C" {}
    } else if #[cfg(target_os = "ios")] {
        #[link(name = "System")]
        #[link(name = "objc")]
        #[link(name = "Security", kind = "framework")]
        #[link(name = "Foundation", kind = "framework")]
        #[link(name = "resolv")]
        extern "C" {}
    } else if #[cfg(target_os = "fuchsia")] {
        #[link(name = "zircon")]
        #[link(name = "fdio")]
        extern "C" {}
    }
}
<commit_msg>ErrorKind: Reformat the mapping table (unix)<commit_after>#![allow(missing_docs, nonstandard_style)]

use crate::io::ErrorKind;

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

#[macro_use]
pub mod weak;

pub mod alloc;
pub mod android;
pub mod args;
#[path = "../unix/cmath.rs"]
pub mod cmath;
pub mod condvar;
pub mod env;
pub mod fd;
pub mod fs;
pub mod futex;
pub mod io;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub mod kernel_copy;
#[cfg(target_os = "l4re")]
mod l4re;
pub mod memchr;
pub mod mutex;
#[cfg(not(target_os = "l4re"))]
pub mod net;
#[cfg(target_os = "l4re")]
pub use self::l4re::net;
pub mod os;
pub mod path;
pub mod pipe;
pub mod process;
pub mod rand;
pub mod rwlock;
pub mod stack_overflow;
pub mod stdio;
pub mod thread;
pub mod thread_local_dtor;
pub mod thread_local_key;
pub mod time;

pub use crate::sys_common::os_str_bytes as os_str;

// SAFETY: must be called only once during runtime initialization.
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
pub unsafe fn init(argc: isize, argv: *const *const u8) {
    // The standard streams might be closed on application startup. To prevent
    // std::io::{stdin, stdout,stderr} objects from using other unrelated file
    // resources opened later, we reopen standards streams when they are closed.
    sanitize_standard_fds();

    // By default, some platforms will send a *signal* when an EPIPE error
    // would otherwise be delivered. This runtime doesn't install a SIGPIPE
    // handler, causing it to kill the program, which isn't exactly what we
    // want!
    //
    // Hence, we set SIGPIPE to ignore when the program starts up in order
    // to prevent this problem.
    reset_sigpipe();

    stack_overflow::init();
    args::init(argc, argv);

    unsafe fn sanitize_standard_fds() {
        #[cfg(not(miri))]
        // The standard fds are always available in Miri.
        cfg_if::cfg_if! {
            if #[cfg(not(any(
                target_os = "emscripten",
                target_os = "fuchsia",
                target_os = "vxworks",
                // The poll on Darwin doesn't set POLLNVAL for closed fds.
                target_os = "macos",
                target_os = "ios",
                target_os = "redox",
            )))] {
                use crate::sys::os::errno;
                let pfds: &mut [_] = &mut [
                    libc::pollfd { fd: 0, events: 0, revents: 0 },
                    libc::pollfd { fd: 1, events: 0, revents: 0 },
                    libc::pollfd { fd: 2, events: 0, revents: 0 },
                ];
                while libc::poll(pfds.as_mut_ptr(), 3, 0) == -1 {
                    if errno() == libc::EINTR {
                        continue;
                    }
                    libc::abort();
                }
                for pfd in pfds {
                    if pfd.revents & libc::POLLNVAL == 0 {
                        continue;
                    }
                    if libc::open("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
                        // If the stream is closed but we failed to reopen it, abort the
                        // process. Otherwise we wouldn't preserve the safety of
                        // operations on the corresponding Rust object Stdin, Stdout, or
                        // Stderr.
                        libc::abort();
                    }
                }
            } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "redox"))] {
                use crate::sys::os::errno;
                for fd in 0..3 {
                    if libc::fcntl(fd, libc::F_GETFD) == -1 && errno() == libc::EBADF {
                        if libc::open("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 {
                            libc::abort();
                        }
                    }
                }
            }
        }
    }

    unsafe fn reset_sigpipe() {
        #[cfg(not(any(target_os = "emscripten", target_os = "fuchsia")))]
        assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR);
    }
}

// SAFETY: must be called only once during runtime cleanup.
// NOTE: this is not guaranteed to run, for example when the program aborts.
pub unsafe fn cleanup() {
    args::cleanup();
    stack_overflow::cleanup();
}

#[cfg(target_os = "android")]
pub use crate::sys::android::signal;
#[cfg(not(target_os = "android"))]
pub use libc::signal;

pub fn decode_error_kind(errno: i32) -> ErrorKind {
    use ErrorKind::*;
    match errno as libc::c_int {
        libc::EADDRINUSE => AddrInUse,
        libc::EADDRNOTAVAIL => AddrNotAvailable,
        libc::ECONNABORTED => ConnectionAborted,
        libc::ECONNREFUSED => ConnectionRefused,
        libc::ECONNRESET => ConnectionReset,
        libc::EEXIST => AlreadyExists,
        libc::EINTR => Interrupted,
        libc::EINVAL => InvalidInput,
        libc::ENOENT => NotFound,
        libc::ENOMEM => OutOfMemory,
        libc::ENOSYS => Unsupported,
        libc::ENOTCONN => NotConnected,
        libc::EPIPE => BrokenPipe,
        libc::ETIMEDOUT => TimedOut,

        libc::EACCES | libc::EPERM  => PermissionDenied,

        // These two constants can have the same value on some systems,
        // but different values on others, so we can't use a match
        // clause
        x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => WouldBlock,

        _ => Uncategorized,
    }
}

#[doc(hidden)]
pub trait IsMinusOne {
    fn is_minus_one(&self) -> bool;
}

macro_rules! impl_is_minus_one {
    ($($t:ident)*) => ($(impl IsMinusOne for $t {
        fn is_minus_one(&self) -> bool {
            *self == -1
        }
    })*)
}

impl_is_minus_one! { i8 i16 i32 i64 isize }

pub fn cvt<T: IsMinusOne>(t: T) -> crate::io::Result<T> {
    if t.is_minus_one() { Err(crate::io::Error::last_os_error()) } else { Ok(t) }
}

pub fn cvt_r<T, F>(mut f: F) -> crate::io::Result<T>
where
    T: IsMinusOne,
    F: FnMut() -> T,
{
    loop {
        match cvt(f()) {
            Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
            other => return other,
        }
    }
}

pub fn cvt_nz(error: libc::c_int) -> crate::io::Result<()> {
    if error == 0 { Ok(()) } else { Err(crate::io::Error::from_raw_os_error(error)) }
}

// On Unix-like platforms, libc::abort will unregister signal handlers
// including the SIGABRT handler, preventing the abort from being blocked, and
// fclose streams, with the side effect of flushing them so libc buffered
// output will be printed.  Additionally the shell will generally print a more
// understandable error message like "Abort trap" rather than "Illegal
// instruction" that intrinsics::abort would cause, as intrinsics::abort is
// implemented as an illegal instruction.
pub fn abort_internal() -> ! {
    unsafe { libc::abort() }
}

cfg_if::cfg_if! {
    if #[cfg(target_os = "android")] {
        #[link(name = "dl")]
        #[link(name = "log")]
        #[link(name = "gcc")]
        extern "C" {}
    } else if #[cfg(target_os = "freebsd")] {
        #[link(name = "execinfo")]
        #[link(name = "pthread")]
        extern "C" {}
    } else if #[cfg(target_os = "netbsd")] {
        #[link(name = "pthread")]
        #[link(name = "rt")]
        extern "C" {}
    } else if #[cfg(any(target_os = "dragonfly", target_os = "openbsd"))] {
        #[link(name = "pthread")]
        extern "C" {}
    } else if #[cfg(target_os = "solaris")] {
        #[link(name = "socket")]
        #[link(name = "posix4")]
        #[link(name = "pthread")]
        #[link(name = "resolv")]
        extern "C" {}
    } else if #[cfg(target_os = "illumos")] {
        #[link(name = "socket")]
        #[link(name = "posix4")]
        #[link(name = "pthread")]
        #[link(name = "resolv")]
        #[link(name = "nsl")]
        // Use libumem for the (malloc-compatible) allocator
        #[link(name = "umem")]
        extern "C" {}
    } else if #[cfg(target_os = "macos")] {
        #[link(name = "System")]
        // res_init and friends require -lresolv on macOS/iOS.
        // See #41582 and http://blog.achernya.com/2013/03/os-x-has-silly-libsystem.html
        #[link(name = "resolv")]
        extern "C" {}
    } else if #[cfg(target_os = "ios")] {
        #[link(name = "System")]
        #[link(name = "objc")]
        #[link(name = "Security", kind = "framework")]
        #[link(name = "Foundation", kind = "framework")]
        #[link(name = "resolv")]
        extern "C" {}
    } else if #[cfg(target_os = "fuchsia")] {
        #[link(name = "zircon")]
        #[link(name = "fdio")]
        extern "C" {}
    }
}
<|endoftext|>


<commit_before>use {Action, InputTranslator, MouseTranslationData};
use input::Button;
use piston_window::Size;
use std::convert::Into;
use std::default::Default;

/// Convenience object for constructing an InputMap
pub struct InputTranslatorBuilder<A: Action> {
    input_remappings: Vec<(Button, A)>,
    mouse_data: MouseTranslationData
}

impl<A: Action> InputTranslatorBuilder<A> {
    pub fn new() -> Self { Default::default() }

    pub fn x_scroll_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.x_axis_scroll_inverted = invert;
        self
    }

    pub fn get_x_scroll_inverted(&self) -> &bool {
        &self.mouse_data.x_axis_scroll_inverted
    }

    pub fn y_scroll_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.y_axis_scroll_inverted = invert;
        self
    }

    pub fn get_y_scroll_inverted(&self) -> &bool {
        &self.mouse_data.y_axis_scroll_inverted
    }

    pub fn x_motion_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.x_axis_motion_inverted = invert;
        self
    }
    pub fn get_x_motion_inverted(&self) -> &bool {
        &self.mouse_data.x_axis_motion_inverted
    }
    pub fn y_motion_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.y_axis_motion_inverted = invert;
        self
    }
    pub fn get_y_motion_inverted(&self) -> &bool {
        &self.mouse_data.y_axis_motion_inverted
    }

    pub fn viewport_size(mut self, sz: Size) -> Self {
        self.mouse_data.viewport_size = sz;
        self
    }

    pub fn get_viewport_size(&self) -> &Size {
        &self.mouse_data.viewport_size
    }

    pub fn with_action_mapping(mut self, but: Button, act: A) -> Self {
        self.input_remappings.push((but, act));
        self
    }

    pub fn build(self) -> InputTranslator<A> {self.into()}
}

impl<A: Action> Default for InputTranslatorBuilder<A> {
    fn default() -> Self {
        InputTranslatorBuilder {
            input_remappings: vec![],
            mouse_data: MouseTranslationData::new((800, 600).into())
        }
    }
}

impl<A: Action> Into<InputTranslator<A>> for InputTranslatorBuilder<A> {
    fn into(self) -> InputTranslator<A> {
        let mut input_map = InputTranslator::new(self.mouse_data.viewport_size);

        input_map.mouse_translator.data.x_axis_motion_inverted = self.mouse_data.x_axis_motion_inverted;
        input_map.mouse_translator.data.y_axis_motion_inverted = self.mouse_data.y_axis_motion_inverted;
        input_map.mouse_translator.data.x_axis_scroll_inverted = self.mouse_data.x_axis_scroll_inverted;
        input_map.mouse_translator.data.y_axis_scroll_inverted = self.mouse_data.y_axis_scroll_inverted;

        //TODO: set key remappings
        input_map.keymap.btn_map.reserve(self.input_remappings.len());

        input_map
    }
}

<commit_msg>Add newlines between functions<commit_after>use {Action, InputTranslator, MouseTranslationData};
use input::Button;
use piston_window::Size;
use std::convert::Into;
use std::default::Default;

/// Convenience object for constructing an InputMap
pub struct InputTranslatorBuilder<A: Action> {
    input_remappings: Vec<(Button, A)>,
    mouse_data: MouseTranslationData
}

impl<A: Action> InputTranslatorBuilder<A> {
    pub fn new() -> Self { Default::default() }

    pub fn x_scroll_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.x_axis_scroll_inverted = invert;
        self
    }

    pub fn get_x_scroll_inverted(&self) -> &bool {
        &self.mouse_data.x_axis_scroll_inverted
    }

    pub fn y_scroll_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.y_axis_scroll_inverted = invert;
        self
    }

    pub fn get_y_scroll_inverted(&self) -> &bool {
        &self.mouse_data.y_axis_scroll_inverted
    }

    pub fn x_motion_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.x_axis_motion_inverted = invert;
        self
    }

    pub fn get_x_motion_inverted(&self) -> &bool {
        &self.mouse_data.x_axis_motion_inverted
    }

    pub fn y_motion_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.y_axis_motion_inverted = invert;
        self
    }

    pub fn get_y_motion_inverted(&self) -> &bool {
        &self.mouse_data.y_axis_motion_inverted
    }

    pub fn viewport_size(mut self, sz: Size) -> Self {
        self.mouse_data.viewport_size = sz;
        self
    }

    pub fn get_viewport_size(&self) -> &Size {
        &self.mouse_data.viewport_size
    }

    pub fn with_action_mapping(mut self, but: Button, act: A) -> Self {
        self.input_remappings.push((but, act));
        self
    }

    pub fn build(self) -> InputTranslator<A> {self.into()}
}

impl<A: Action> Default for InputTranslatorBuilder<A> {
    fn default() -> Self {
        InputTranslatorBuilder {
            input_remappings: vec![],
            mouse_data: MouseTranslationData::new((800, 600).into())
        }
    }
}

impl<A: Action> Into<InputTranslator<A>> for InputTranslatorBuilder<A> {
    fn into(self) -> InputTranslator<A> {
        let mut input_map = InputTranslator::new(self.mouse_data.viewport_size);

        input_map.mouse_translator.data.x_axis_motion_inverted = self.mouse_data.x_axis_motion_inverted;
        input_map.mouse_translator.data.y_axis_motion_inverted = self.mouse_data.y_axis_motion_inverted;
        input_map.mouse_translator.data.x_axis_scroll_inverted = self.mouse_data.x_axis_scroll_inverted;
        input_map.mouse_translator.data.y_axis_scroll_inverted = self.mouse_data.y_axis_scroll_inverted;

        //TODO: set key remappings
        input_map.keymap.btn_map.reserve(self.input_remappings.len());

        input_map
    }
}

<|endoftext|>


<commit_before>use std::fs::File;
use std::io::{Read, Seek, SeekFrom};
use std::path::Path;
use std::str;

use std::fmt;

use byteorder::{BigEndian, ReadBytesExt};

pub struct Crt {
    pub header: Header,
    chips: Vec<Chip>,
}

impl Crt {
    pub fn load_from_file(filename: &str) -> Result<Crt, String> {
        let mut file = File::open(filename).map_err(|e| e.to_string())?;
        let mut signature = [0u8; 16];
        file.read(&mut signature).map_err(|e| e.to_string())?;
        if &signature != b"C64 CARTRIDGE   " {
            return Err("Invalid signature".to_string())
        }
        let header_len = file.read_u32::<BigEndian>().map_err(|e| e.to_string())?;
        let mut version = [0u8;2];
        file.read(&mut version).map_err(|e| e.to_string())?;
        let hw_type = file.read_u16::<BigEndian>().map_err(|e| e.to_string())?;
        let exrom = file.read_u8().map_err(|e| e.to_string())?;
        let game = file.read_u8().map_err(|e| e.to_string())?;
        file.seek(SeekFrom::Start(0x20)).map_err(|e| e.to_string())?;
        let mut name = [0u8; 32];
        file.read(&mut name).map_err(|e| e.to_string())?;
        let mut chips: Vec<Chip> = Vec::new();

        Ok(Crt {
            header: Header {
                signature: signature,
                header_len: header_len,
                version: version,
                hw_type: hw_type,
                exrom: exrom,
                game: game,
                name: name,
            },
            chips: chips,
        })
    }
}

pub struct Header {
    signature: [u8; 16],
    header_len: u32,
    version: [u8; 2],
    hw_type: u16,
    exrom: u8,
    game: u8,
    // 001A-001F RFU
    name: [u8; 32],
}

impl fmt::Debug for Header {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
"Header {{
    signature: {},
    header_len: {} bytes,
    version: {:x}.{:x}
    hw_type: {},
    exrom: {},
    game: {},
    name: {},
}}",
            str::from_utf8(&self.signature).unwrap(),
            self.header_len,
            self.version[0],
            self.version[1],
            self.hw_type,
            self.exrom,
            self.game,
            str::from_utf8(&self.name).unwrap()
        )
    }
}

struct Chip {
    signature: [u8; 4],
    length: u32, // header and data combined
    chip_type: ChipType,
    bank_number: u16,
    load_addr: u16,
    data_size: u16,
    data: Vec<u8>,
}

enum ChipType {
    ROM,
    RAM,
    Flash,
}
<commit_msg>better display of cartridge versions<commit_after>use std::fs::File;
use std::io::{Read, Seek, SeekFrom};
use std::path::Path;
use std::str;

use std::fmt;

use byteorder::{BigEndian, ReadBytesExt};

pub struct Crt {
    pub header: Header,
    chips: Vec<Chip>,
}

impl Crt {
    pub fn load_from_file(filename: &str) -> Result<Crt, String> {
        let mut file = File::open(filename).map_err(|e| e.to_string())?;
        let mut signature = [0u8; 16];
        file.read(&mut signature).map_err(|e| e.to_string())?;
        if &signature != b"C64 CARTRIDGE   " {
            return Err("Invalid signature".to_string())
        }
        let header_len = file.read_u32::<BigEndian>().map_err(|e| e.to_string())?;
        let mut version = [0u8;2];
        file.read(&mut version).map_err(|e| e.to_string())?;
        let hw_type = file.read_u16::<BigEndian>().map_err(|e| e.to_string())?;
        let exrom = file.read_u8().map_err(|e| e.to_string())?;
        let game = file.read_u8().map_err(|e| e.to_string())?;
        file.seek(SeekFrom::Start(0x20)).map_err(|e| e.to_string())?;
        let mut name = [0u8; 32];
        file.read(&mut name).map_err(|e| e.to_string())?;
        let mut chips: Vec<Chip> = Vec::new();

        Ok(Crt {
            header: Header {
                signature: signature,
                header_len: header_len,
                version: version,
                hw_type: hw_type,
                exrom: exrom,
                game: game,
                name: name,
            },
            chips: chips,
        })
    }
}

pub struct Header {
    signature: [u8; 16],
    header_len: u32,
    version: [u8; 2],
    hw_type: u16,
    exrom: u8,
    game: u8,
    // 001A-001F RFU
    name: [u8; 32],
}

impl fmt::Debug for Header {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
"Header {{
    signature: {},
    header_len: {} bytes,
    version: {:x}.{:02x}
    hw_type: {},
    exrom: {},
    game: {},
    name: {},
}}",
            str::from_utf8(&self.signature).unwrap(),
            self.header_len,
            self.version[0],
            self.version[1],
            self.hw_type,
            self.exrom,
            self.game,
            str::from_utf8(&self.name).unwrap()
        )
    }
}

struct Chip {
    signature: [u8; 4],
    length: u32, // header and data combined
    chip_type: ChipType,
    bank_number: u16,
    load_addr: u16,
    data_size: u16,
    data: Vec<u8>,
}

enum ChipType {
    ROM,
    RAM,
    Flash,
}
<|endoftext|>


<commit_before>extern crate sdl2;
extern crate minifb;
use minifb::*;
use utils;
pub mod cpu;
pub mod opcodes;
mod clock;
mod memory;
mod io;
mod cia;
mod vic;

pub const SCREEN_WIDTH:  usize = 384; // extend 20 pixels left and right for the borders
pub const SCREEN_HEIGHT: usize = 272; // extend 36 pixels top and down for the borders

// PAL clock frequency in Hz
const CLOCK_FREQ: f64 = 985248.0;

pub struct C64
{
    pub window: minifb::Window,
    memory: memory::MemShared,
    io:    io::IO,
    clock: clock::Clock,
    cpu: cpu::CPUShared,
    cia1: cia::CIAShared,
    cia2: cia::CIAShared,
    vic: vic::VICShared,

    boot_complete: bool,
    pub file_to_load: String,
    cycle_count: u32,
}

impl C64
{
    pub fn new() -> C64
    {
        let memory = memory::Memory::new_shared();
        let vic    = vic::VIC::new_shared();
        let cia1   = cia::CIA::new_shared(true);
        let cia2   = cia::CIA::new_shared(false);
        let cpu    = cpu::CPU::new_shared();

        let c64 = C64
        {
            window: Window::new("Rust64", SCREEN_WIDTH, SCREEN_HEIGHT, Scale::X1, Vsync::No).unwrap(),
            memory: memory.clone(), // shared system memory (RAM, ROM, IO registers)
            io:    io::IO::new(),
            clock: clock::Clock::new(CLOCK_FREQ),
            cpu: cpu.clone(),
            cia1: cia1.clone(),
            cia2: cia2.clone(),
            vic: vic.clone(),
            boot_complete: false,
            file_to_load: String::new(),
            cycle_count: 0,
        };

        // cyclic dependencies are not possible in Rust (yet?), so we have
        // to resort to setting references manually
        c64.cia1.borrow_mut().set_references(memory.clone(), cpu.clone(), vic.clone());
        c64.cia2.borrow_mut().set_references(memory.clone(), cpu.clone(), vic.clone());
        c64.vic.borrow_mut().set_references(memory.clone(), cpu.clone());
        c64.cpu.borrow_mut().set_references(memory.clone(), vic.clone(), cia1.clone(), cia2.clone());

        drop(memory);
        drop(cia1);
        drop(cia2);
        drop(vic);
        drop(cpu);

        c64
    }

    pub fn reset(&mut self)
    {
        self.memory.borrow_mut().reset();
        self.cpu.borrow_mut().reset();
        self.cia1.borrow_mut().reset();
        self.cia2.borrow_mut().reset();
    }

    pub fn load_prg(&mut self, filename: &str)
    {
        let prg_data = utils::open_file(filename, 0);
        let start_address: u16 = ((prg_data[1] as u16) << 8) | (prg_data[0] as u16);
        let end_addr = start_address + (prg_data.len() as u16) - 2;
        println!("Loading {} to start location at ${:04x} (SYS {})", filename, start_address, start_address);

        for i in 2..(prg_data.len())
        {
            self.memory.borrow_mut().write_byte(start_address + (i as u16) - 2, prg_data[i]);
        }

        //self.memory.borrow_mut().write_word_le(0x02b, start_address);
        //self.memory.borrow_mut().write_word_le(0x02d, end_addr);
        //self.memory.borrow_mut().write_word_le(0x02f, end_addr);
        //self.memory.borrow_mut().write_word_le(0x031, end_addr);
    }

    pub fn run(&mut self)
    {
        if !self.boot_complete
        {
            // $A480 is the BASIC warm start sequence - safe to assume we can load a cmdline program now
            self.boot_complete = self.cpu.borrow_mut().PC == 0xa480;

            if self.boot_complete
            {
                if self.file_to_load.len() > 0
                {
                    let prg_file = &self.file_to_load.to_owned()[..];
                    self.load_prg(prg_file);
                }
            }
        }

        if self.clock.tick() {
            let mut should_trigger_vblank = false;

            self.vic.borrow_mut().update(self.cycle_count, &mut should_trigger_vblank);

            // TODO: update sid *HERE* when it's done
            self.cia1.borrow_mut().process_irq();
            self.cia2.borrow_mut().process_irq();
            self.cia1.borrow_mut().update();
            self.cia2.borrow_mut().update();

            self.cpu.borrow_mut().update();

            if should_trigger_vblank
            {
                self.window.update(&self.vic.borrow_mut().window_buffer);
                self.io.update(&self.window, &mut self.cia1);
                self.cia1.borrow_mut().count_tod();
                self.cia2.borrow_mut().count_tod();

                if self.io.check_restore_key(&self.window)
                {
                    self.cpu.borrow_mut().trigger_nmi();
                }
            }

            self.cycle_count += 1;
        }
    }
}
<commit_msg>formatting change<commit_after>extern crate sdl2;
extern crate minifb;
use minifb::*;
use utils;
pub mod cpu;
pub mod opcodes;
mod clock;
mod memory;
mod io;
mod cia;
mod vic;

pub const SCREEN_WIDTH:  usize = 384; // extend 20 pixels left and right for the borders
pub const SCREEN_HEIGHT: usize = 272; // extend 36 pixels top and down for the borders

// PAL clock frequency in Hz
const CLOCK_FREQ: f64 = 985248.0;

pub struct C64
{
    pub window: minifb::Window,
    memory: memory::MemShared,
    io:    io::IO,
    clock: clock::Clock,
    cpu: cpu::CPUShared,
    cia1: cia::CIAShared,
    cia2: cia::CIAShared,
    vic: vic::VICShared,

    boot_complete: bool,
    pub file_to_load: String,
    cycle_count: u32,
}

impl C64
{
    pub fn new() -> C64
    {
        let memory = memory::Memory::new_shared();
        let vic    = vic::VIC::new_shared();
        let cia1   = cia::CIA::new_shared(true);
        let cia2   = cia::CIA::new_shared(false);
        let cpu    = cpu::CPU::new_shared();

        let c64 = C64
        {
            window: Window::new("Rust64", SCREEN_WIDTH, SCREEN_HEIGHT, Scale::X1, Vsync::No).unwrap(),
            memory: memory.clone(), // shared system memory (RAM, ROM, IO registers)
            io:    io::IO::new(),
            clock: clock::Clock::new(CLOCK_FREQ),
            cpu: cpu.clone(),
            cia1: cia1.clone(),
            cia2: cia2.clone(),
            vic: vic.clone(),
            boot_complete: false,
            file_to_load: String::new(),
            cycle_count: 0,
        };

        // cyclic dependencies are not possible in Rust (yet?), so we have
        // to resort to setting references manually
        c64.cia1.borrow_mut().set_references(memory.clone(), cpu.clone(), vic.clone());
        c64.cia2.borrow_mut().set_references(memory.clone(), cpu.clone(), vic.clone());
        c64.vic.borrow_mut().set_references(memory.clone(), cpu.clone());
        c64.cpu.borrow_mut().set_references(memory.clone(), vic.clone(), cia1.clone(), cia2.clone());

        drop(memory);
        drop(cia1);
        drop(cia2);
        drop(vic);
        drop(cpu);

        c64
    }

    pub fn reset(&mut self)
    {
        self.memory.borrow_mut().reset();
        self.cpu.borrow_mut().reset();
        self.cia1.borrow_mut().reset();
        self.cia2.borrow_mut().reset();
    }

    pub fn load_prg(&mut self, filename: &str)
    {
        let prg_data = utils::open_file(filename, 0);
        let start_address: u16 = ((prg_data[1] as u16) << 8) | (prg_data[0] as u16);
        let end_addr = start_address + (prg_data.len() as u16) - 2;
        println!("Loading {} to start location at ${:04x} (start_address)", filename, start_address, start_address);

        for i in 2..(prg_data.len())
        {
            self.memory.borrow_mut().write_byte(start_address + (i as u16) - 2, prg_data[i]);
        }

        //self.memory.borrow_mut().write_word_le(0x02b, start_address);
        //self.memory.borrow_mut().write_word_le(0x02d, end_addr);
        //self.memory.borrow_mut().write_word_le(0x02f, end_addr);
        //self.memory.borrow_mut().write_word_le(0x031, end_addr);
    }

    pub fn run(&mut self)
    {
        if !self.boot_complete
        {
            // $A480 is the BASIC warm start sequence - safe to assume we can load a cmdline program now
            self.boot_complete = self.cpu.borrow_mut().PC == 0xA480;

            if self.boot_complete
            {
                if self.file_to_load.len() > 0
                {
                    let prg_file = &self.file_to_load.to_owned()[..];
                    self.load_prg(prg_file);
                }
            }
        }

        if self.clock.tick() {
            let mut should_trigger_vblank = false;

            self.vic.borrow_mut().update(self.cycle_count, &mut should_trigger_vblank);

            // TODO: update sid *HERE* when it's done
            self.cia1.borrow_mut().process_irq();
            self.cia2.borrow_mut().process_irq();
            self.cia1.borrow_mut().update();
            self.cia2.borrow_mut().update();

            self.cpu.borrow_mut().update();

            if should_trigger_vblank
            {
                self.window.update(&self.vic.borrow_mut().window_buffer);
                self.io.update(&self.window, &mut self.cia1);
                self.cia1.borrow_mut().count_tod();
                self.cia2.borrow_mut().count_tod();

                if self.io.check_restore_key(&self.window)
                {
                    self.cpu.borrow_mut().trigger_nmi();
                }
            }

            self.cycle_count += 1;
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Mozilla Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::errors::*;
use clap::{ArgGroup, Parser};
use std::env;
use std::ffi::OsString;
use std::path::PathBuf;
use which::which_in;

const ENV_VAR_SCCACHE_START_SERVER: &str = "SCCACHE_START_SERVER";

#[derive(clap::ArgEnum, Debug, Clone)]
pub enum StatsFormat {
    Text,
    Json,
}

impl Default for StatsFormat {
    fn default() -> Self {
        Self::Text
    }
}

/// A specific command to run.
pub enum Command {
    /// Show cache statistics and exit.
    ShowStats(StatsFormat),
    /// Run background server.
    InternalStartServer,
    /// Start background server as a subprocess.
    StartServer,
    /// Stop background server.
    StopServer,
    /// Zero cache statistics and exit.
    ZeroStats,
    /// Show the status of the distributed client.
    DistStatus,
    /// Perform a login to authenticate for distributed compilation.
    DistAuth,
    /// Package a toolchain for distributed compilation (executable, out)
    PackageToolchain(PathBuf, PathBuf),
    /// Run a compiler command.
    Compile {
        /// The binary to execute.
        exe: OsString,
        /// The commandline arguments to pass to `exe`.
        cmdline: Vec<OsString>,
        /// The directory in which to execute the command.
        cwd: PathBuf,
        /// The environment variables to use for execution.
        env_vars: Vec<(OsString, OsString)>,
    },
}

#[derive(Parser)]
#[clap(version)]
#[clap(trailing_var_arg = true)]
#[clap(after_help = concat!(
    "Enabled features:\n",
    "    S3:        ", cfg!(feature = "s3"), "\n",
    "    Redis:     ", cfg!(feature = "redis"), "\n",
    "    Memcached: ", cfg!(feature = "memcached"), "\n",
    "    GCS:       ", cfg!(feature = "gcs"), "\n",
    "    Azure:     ", cfg!(feature = "azure"), "\n")
)]
#[clap(group(
    ArgGroup::new("one_and_only_one")
        .args(&[
            "dist-auth",
            "dist-status",
            "show-stats",
            "start-server",
            "stop-server",
            "zero-stats",
            "package-toolchain",
            "cmd",
        ])
        .required(true)
))]
struct Opts {
    /// authenticate for distributed compilation
    #[clap(long)]
    dist_auth: bool,
    /// show status of the distributed client
    #[clap(long)]
    dist_status: bool,
    /// show cache statistics
    #[clap(short, long)]
    show_stats: bool,
    /// start background server
    #[clap(long, env = ENV_VAR_SCCACHE_START_SERVER, hide_env = true)]
    start_server: bool,
    /// stop background server
    #[clap(long)]
    stop_server: bool,
    /// zero statistic counters
    #[clap(short, long)]
    zero_stats: bool,

    /// package toolchain for distributed compilation
    #[clap(long, number_of_values = 2, value_names = &["EXECUTABLE", "OUT"])]
    package_toolchain: Vec<PathBuf>,
    /// set output format of statistics
    #[clap(long, arg_enum, value_name = "FORMAT", default_value_t = StatsFormat::default())]
    stats_format: StatsFormat,

    cmd: Vec<OsString>,
}

/// Parse the commandline into a `Command` to execute.
pub fn parse() -> Command {
    match try_parse() {
        Ok(cmd) => cmd,
        Err(e) => {
            println!("sccache: {e}");
            for e in e.chain().skip(1) {
                println!("sccache: caused by: {e}");
            }
            std::process::exit(1);
        }
    }
}

fn try_parse() -> Result<Command> {
    trace!("parse");
    let cwd =
        env::current_dir().context("sccache: Couldn't determine current working directory")?;
    let internal_start_server = env::var(ENV_VAR_SCCACHE_START_SERVER).as_deref() == Ok("1");

    let mut args: Vec<_> = env::args_os().collect();
    if !internal_start_server {
        // Internal start server is passed in the env, but we only care about it being `1`, unset it
        // otherwise so that the `ArgGroup` is enforced correctly
        env::remove_var(ENV_VAR_SCCACHE_START_SERVER);

        if let Ok(exe) = env::current_exe() {
            match exe
                .file_stem()
                .and_then(|s| s.to_str())
                .map(|s| s.to_lowercase())
            {
                // If the executable has its standard name, do nothing.
                Some(ref e) if e == env!("CARGO_PKG_NAME") => {}
                // Otherwise, if it was copied/hardlinked under a different $name, act
                // as if it were invoked with `sccache $name`, but avoid $name resolving
                // to ourselves again if it's in the PATH.
                _ => {
                    if let (Some(path), Some(exe_filename)) = (env::var_os("PATH"), exe.file_name())
                    {
                        match which_in(exe_filename, Some(&path), &cwd) {
                            Ok(ref full_path)
                                if full_path.canonicalize()? == exe.canonicalize()? =>
                            {
                                if let Some(dir) = full_path.parent() {
                                    let path = env::join_paths(
                                        env::split_paths(&path).filter(|p| p != dir),
                                    )
                                    .ok();
                                    if let Ok(full_path) = which_in(exe_filename, path, &cwd) {
                                        args[0] = full_path.into();
                                    }
                                }
                            }
                            Ok(full_path) => args[0] = full_path.into(),
                            Err(_) => {}
                        }
                        args.insert(0, env!("CARGO_PKG_NAME").into());
                    }
                }
            }
        }
    }

    let Opts {
        dist_auth,
        dist_status,
        show_stats,
        mut start_server,
        stop_server,
        zero_stats,
        package_toolchain,
        stats_format,
        cmd,
    } = Opts::parse_from(args);

    // `start_server` is used to smuggle `SCCACHE_START_SERVER` into the group since env var only
    // args aren't supported in `clap`
    if internal_start_server {
        start_server = false;
    }

    if internal_start_server {
        Ok(Command::InternalStartServer)
    } else if show_stats {
        Ok(Command::ShowStats(stats_format))
    } else if start_server {
        Ok(Command::StartServer)
    } else if stop_server {
        Ok(Command::StopServer)
    } else if zero_stats {
        Ok(Command::ZeroStats)
    } else if dist_auth {
        Ok(Command::DistAuth)
    } else if dist_status {
        Ok(Command::DistStatus)
    } else if let [executable, out] = package_toolchain.as_slice() {
        Ok(Command::PackageToolchain(executable.into(), out.into()))
    } else if let [exe, cmdline @ ..] = cmd.as_slice() {
        let mut env_vars: Vec<_> = env::vars_os().collect();

        // If we're running under rr, avoid the `LD_PRELOAD` bits, as it will
        // almost surely do the wrong thing, as the compiler gets executed
        // in a different process tree.
        //
        // FIXME: Maybe we should strip out `LD_PRELOAD` always?
        if env::var_os("RUNNING_UNDER_RR").is_some() {
            env_vars.retain(|(k, _v)| k != "LD_PRELOAD" && k != "RUNNING_UNDER_RR");
        }

        Ok(Command::Compile {
            exe: exe.to_owned(),
            cmdline: cmdline.to_owned(),
            cwd,
            env_vars,
        })
    } else {
        unreachable!("`ArgGroup` should enforce a single command to be run");
    }
}
<commit_msg>Fix issue where `SCCACHE_START_SERVER=1` and `--start-server` could be used<commit_after>// Copyright 2016 Mozilla Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::errors::*;
use clap::ValueSource;
use clap::{error::ErrorKind, ArgGroup, IntoApp, Parser};
use std::env;
use std::ffi::OsString;
use std::path::PathBuf;
use which::which_in;

const ENV_VAR_SCCACHE_START_SERVER: &str = "SCCACHE_START_SERVER";

#[derive(clap::ArgEnum, Debug, Clone)]
pub enum StatsFormat {
    Text,
    Json,
}

impl Default for StatsFormat {
    fn default() -> Self {
        Self::Text
    }
}

/// A specific command to run.
pub enum Command {
    /// Show cache statistics and exit.
    ShowStats(StatsFormat),
    /// Run background server.
    InternalStartServer,
    /// Start background server as a subprocess.
    StartServer,
    /// Stop background server.
    StopServer,
    /// Zero cache statistics and exit.
    ZeroStats,
    /// Show the status of the distributed client.
    DistStatus,
    /// Perform a login to authenticate for distributed compilation.
    DistAuth,
    /// Package a toolchain for distributed compilation (executable, out)
    PackageToolchain(PathBuf, PathBuf),
    /// Run a compiler command.
    Compile {
        /// The binary to execute.
        exe: OsString,
        /// The commandline arguments to pass to `exe`.
        cmdline: Vec<OsString>,
        /// The directory in which to execute the command.
        cwd: PathBuf,
        /// The environment variables to use for execution.
        env_vars: Vec<(OsString, OsString)>,
    },
}

#[derive(Parser)]
#[clap(version)]
#[clap(trailing_var_arg = true)]
#[clap(after_help = concat!(
    "Enabled features:\n",
    "    S3:        ", cfg!(feature = "s3"), "\n",
    "    Redis:     ", cfg!(feature = "redis"), "\n",
    "    Memcached: ", cfg!(feature = "memcached"), "\n",
    "    GCS:       ", cfg!(feature = "gcs"), "\n",
    "    Azure:     ", cfg!(feature = "azure"), "\n")
)]
#[clap(group(
    ArgGroup::new("one_and_only_one")
        .args(&[
            "dist-auth",
            "dist-status",
            "show-stats",
            "start-server",
            "stop-server",
            "zero-stats",
            "package-toolchain",
            "cmd",
        ])
        .required(true)
))]
struct Opts {
    /// authenticate for distributed compilation
    #[clap(long)]
    dist_auth: bool,
    /// show status of the distributed client
    #[clap(long)]
    dist_status: bool,
    /// show cache statistics
    #[clap(short, long)]
    show_stats: bool,
    /// start background server
    #[clap(long, hide_env = true, env = ENV_VAR_SCCACHE_START_SERVER)]
    start_server: bool,
    /// stop background server
    #[clap(long)]
    stop_server: bool,
    /// zero statistic counters
    #[clap(short, long)]
    zero_stats: bool,

    /// package toolchain for distributed compilation
    #[clap(long, number_of_values = 2, value_names = &["EXECUTABLE", "OUT"])]
    package_toolchain: Vec<PathBuf>,
    /// set output format of statistics
    #[clap(long, arg_enum, value_name = "FORMAT", default_value_t = StatsFormat::default())]
    stats_format: StatsFormat,

    cmd: Vec<OsString>,
}

/// Parse the commandline into a `Command` to execute.
pub fn parse() -> Command {
    match try_parse() {
        Ok(cmd) => cmd,
        Err(e) => match e.downcast::<clap::error::Error>() {
            // If the error is from clap then let them handle formatting and exiting
            Ok(clap_err) => clap_err.exit(),
            Err(some_other_err) => {
                println!("sccache: {some_other_err}");
                for source in some_other_err.chain().skip(1) {
                    println!("sccache: caused by: {source}");
                }
                std::process::exit(1);
            }
        },
    }
}

fn try_parse() -> Result<Command> {
    trace!("parse");
    let cwd =
        env::current_dir().context("sccache: Couldn't determine current working directory")?;

    // We only if the value is `1` so unset it otherwise
    let internal_start_server = match env::var(ENV_VAR_SCCACHE_START_SERVER).as_deref() {
        Ok("1") => true,
        _ => {
            env::remove_var(ENV_VAR_SCCACHE_START_SERVER);
            false
        }
    };

    let mut args: Vec<_> = env::args_os().collect();
    if !internal_start_server {
        if let Ok(exe) = env::current_exe() {
            match exe
                .file_stem()
                .and_then(|s| s.to_str())
                .map(|s| s.to_lowercase())
            {
                // If the executable has its standard name, do nothing.
                Some(ref e) if e == env!("CARGO_PKG_NAME") => {}
                // Otherwise, if it was copied/hardlinked under a different $name, act
                // as if it were invoked with `sccache $name`, but avoid $name resolving
                // to ourselves again if it's in the PATH.
                _ => {
                    if let (Some(path), Some(exe_filename)) = (env::var_os("PATH"), exe.file_name())
                    {
                        match which_in(exe_filename, Some(&path), &cwd) {
                            Ok(ref full_path)
                                if full_path.canonicalize()? == exe.canonicalize()? =>
                            {
                                if let Some(dir) = full_path.parent() {
                                    let path = env::join_paths(
                                        env::split_paths(&path).filter(|p| p != dir),
                                    )
                                    .ok();
                                    if let Ok(full_path) = which_in(exe_filename, path, &cwd) {
                                        args[0] = full_path.into();
                                    }
                                }
                            }
                            Ok(full_path) => args[0] = full_path.into(),
                            Err(_) => {}
                        }
                        args.insert(0, env!("CARGO_PKG_NAME").into());
                    }
                }
            }
        }
    }

    let opts_result = Opts::try_parse_from(&args);

    // A command can either be from `ENV_VAR_SCCACHE_START_SERVER` being set or from command-line
    // args. Validate things so that error messages are nice and the returned opts are correct
    let opts = match (internal_start_server, opts_result) {
        (true, Err(e)) => {
            // Return a more obvious error message when there is a conflict from
            // `ENV_VAR_SCCACHE_START_SERVER` being used with another command
            if e.kind() == ErrorKind::ArgumentConflict {
                bail!("`{ENV_VAR_SCCACHE_START_SERVER}=1` can't be used with other commands");
            } else {
                return Err(e.into());
            }
        }
        (false, Err(e)) => {
            return Err(e.into());
        }
        (true, Ok(mut opts)) => {
            // `start_server` is used to smuggle `ENV_VAR_SCCACHE_START_SERVER` into the arg group,
            // but they should still conflict, so check the source of `start_server` to see if they
            // were both set or not
            let opts_matches = Opts::command().try_get_matches_from(&args)?;
            if let Some(ValueSource::EnvVariable) = opts_matches.value_source("start-server") {
                opts.start_server = false;
                opts
            } else {
                bail!("`{ENV_VAR_SCCACHE_START_SERVER}=1` can't be used with other commands");
            }
        }
        (false, Ok(opts)) => opts,
    };

    let Opts {
        dist_auth,
        dist_status,
        show_stats,
        start_server,
        stop_server,
        zero_stats,
        package_toolchain,
        stats_format,
        cmd,
    } = opts;

    Ok(if internal_start_server {
        Command::InternalStartServer
    } else if show_stats {
        Command::ShowStats(stats_format)
    } else if start_server {
        Command::StartServer
    } else if stop_server {
        Command::StopServer
    } else if zero_stats {
        Command::ZeroStats
    } else if dist_auth {
        Command::DistAuth
    } else if dist_status {
        Command::DistStatus
    } else if let [executable, out] = package_toolchain.as_slice() {
        Command::PackageToolchain(executable.into(), out.into())
    } else if let [exe, cmdline @ ..] = cmd.as_slice() {
        let mut env_vars: Vec<_> = env::vars_os().collect();

        // If we're running under rr, avoid the `LD_PRELOAD` bits, as it will
        // almost surely do the wrong thing, as the compiler gets executed
        // in a different process tree.
        //
        // FIXME: Maybe we should strip out `LD_PRELOAD` always?
        if env::var_os("RUNNING_UNDER_RR").is_some() {
            env_vars.retain(|(k, _v)| k != "LD_PRELOAD" && k != "RUNNING_UNDER_RR");
        }

        Command::Compile {
            exe: exe.to_owned(),
            cmdline: cmdline.to_owned(),
            cwd,
            env_vars,
        }
    } else {
        unreachable!("`ArgGroup` should enforce a single command to be run");
    })
}
<|endoftext|>


<commit_before>extern crate semver;

use std::collections::HashMap;
use std::io::net::ip::IpAddr;

#[deriving(PartialEq, Show, Clone)]
pub enum Scheme {
    Http,
    Https
}

#[deriving(PartialEq, Show, Clone)]
pub enum Host<'a> {
    HostName(&'a str),
    HostIp(IpAddr)
}

#[deriving(PartialEq, Show, Clone)]
pub enum Method<'a> {
    Get,
    Post,
    Put,
    Patch,
    Delete,
    Other(&'a str)
}

pub trait Request {
    /// The version of HTTP being used
    fn http_version(&self) -> semver::Version;

    /// The version of the conduit spec being used
    fn conduit_version(&self) -> semver::Version;

    /// The request method, such as GET, POST, PUT, DELETE or PATCH
    fn method<'a>(&'a self) -> Method<'a>;

    /// The scheme part of the request URL
    fn scheme(&self) -> Scheme;

    /// The host part of the requested URL
    fn host<'a>(&'a self) -> Host<'a>;

    /// The initial part of the request URL's path that corresponds
    /// to a virtual root. This allows an application to have a
    /// virtual location that consumes part of the path.
    fn virtual_root<'a>(&'a self) -> Option<&'a str>;

    /// The remainder of the path.
    fn path<'a>(&'a self) -> &'a str;

    /// The portion of the request URL that follows the "?"
    fn query_string<'a>(&'a self) -> Option<&'a str>;

    /// The remote IP address of the client or the last proxy that
    /// sent the request.
    fn remote_ip(&self) -> IpAddr;

    /// The byte-size of the body, if any
    fn content_length(&self) -> Option<uint>;

    /// The request's headers, as conduit::Headers.
    fn headers<'a>(&'a self) -> &'a Headers;

    /// A Reader for the body of the request
    fn body<'a>(&'a mut self) -> &'a mut Reader;
}

pub type HeaderEntries<'a> = Box<Iterator<(&'a str, Vec<&'a str>)>>;

pub trait Headers {
    /// Find the value of a given header. Multi-line headers are represented
    /// as an array.
    fn find<'a>(&'a self, key: &str) -> Option<Vec<&'a str>>;

    /// Returns true if a particular header exists
    fn has(&self, key: &str) -> bool;

    /// Iterate over all of the available headers.
    fn iter<'a>(&'a self) -> HeaderEntries<'a>;
}

pub struct Response {
    /// The status code as a tuple of the return code and status string
    pub status: (uint, &'static str),

    /// A Map of the headers
    pub headers: HashMap<String, String>,

    /// A Writer for body of the response
    pub body: Box<Reader + Send>
}

pub type Handler<E> = fn(&mut Request) -> Result<Response, E>;
<commit_msg>More general handler<commit_after>extern crate semver;

use std::collections::HashMap;
use std::io::net::ip::IpAddr;

#[deriving(PartialEq, Show, Clone)]
pub enum Scheme {
    Http,
    Https
}

#[deriving(PartialEq, Show, Clone)]
pub enum Host<'a> {
    HostName(&'a str),
    HostIp(IpAddr)
}

#[deriving(PartialEq, Show, Clone)]
pub enum Method<'a> {
    Get,
    Post,
    Put,
    Patch,
    Delete,
    Other(&'a str)
}

pub trait Request {
    /// The version of HTTP being used
    fn http_version(&self) -> semver::Version;

    /// The version of the conduit spec being used
    fn conduit_version(&self) -> semver::Version;

    /// The request method, such as GET, POST, PUT, DELETE or PATCH
    fn method<'a>(&'a self) -> Method<'a>;

    /// The scheme part of the request URL
    fn scheme(&self) -> Scheme;

    /// The host part of the requested URL
    fn host<'a>(&'a self) -> Host<'a>;

    /// The initial part of the request URL's path that corresponds
    /// to a virtual root. This allows an application to have a
    /// virtual location that consumes part of the path.
    fn virtual_root<'a>(&'a self) -> Option<&'a str>;

    /// The remainder of the path.
    fn path<'a>(&'a self) -> &'a str;

    /// The portion of the request URL that follows the "?"
    fn query_string<'a>(&'a self) -> Option<&'a str>;

    /// The remote IP address of the client or the last proxy that
    /// sent the request.
    fn remote_ip(&self) -> IpAddr;

    /// The byte-size of the body, if any
    fn content_length(&self) -> Option<uint>;

    /// The request's headers, as conduit::Headers.
    fn headers<'a>(&'a self) -> &'a Headers;

    /// A Reader for the body of the request
    fn body<'a>(&'a mut self) -> &'a mut Reader;
}

pub type HeaderEntries<'a> = Box<Iterator<(&'a str, Vec<&'a str>)>>;

pub trait Headers {
    /// Find the value of a given header. Multi-line headers are represented
    /// as an array.
    fn find<'a>(&'a self, key: &str) -> Option<Vec<&'a str>>;

    /// Returns true if a particular header exists
    fn has(&self, key: &str) -> bool;

    /// Iterate over all of the available headers.
    fn iter<'a>(&'a self) -> HeaderEntries<'a>;
}

pub struct Response {
    /// The status code as a tuple of the return code and status string
    pub status: (uint, &'static str),

    /// A Map of the headers
    pub headers: HashMap<String, String>,

    /// A Writer for body of the response
    pub body: Box<Reader + Send>
}

trait Handler<E> {
    fn call(&self, request: &mut Request) -> Result<Response, E>;
}

impl<E> Handler<E> for fn(&mut Request) -> Result<Response, E> {
    fn call(&self, request: &mut Request) -> Result<Response, E> {
        (*self)(request)
    }
}
<|endoftext|>


<commit_before>use super::super::bus;
use super::cp0::cp0::CP0;

const NUM_GPREG: usize = 32;
const NUM_FPREG: usize = 32;

const PIF_ROM_START: u64 = 0xffff_ffff_bfc0_0000;

#[derive(Debug)]
pub struct Cpu {
    reg_gprs: [u64; NUM_GPREG],
    reg_fprs: [f64; NUM_FPREG],

    reg_pc: u64,

    reg_hi: u64,
    reg_lo: u64,

    reg_llbit: bool,

    reg_fcr0: u32,
    reg_fcr31: u32,

    cp0: CP0,

    bus: bus::Bus,
}

impl Cpu {
    pub fn new(bus: bus::Bus) -> Cpu {
        Cpu {
            reg_gprs: [0; NUM_GPREG],
            reg_fprs: [0.0; NUM_FPREG],

            reg_pc: 0,

            reg_hi: 0,
            reg_lo: 0,

            reg_llbit: false,

            reg_fcr0: 0,
            reg_fcr31: 0,

            cp0: CP0::default(),

            bus: bus,
        }
    }

    pub fn power_on_reset(&mut self) {
        self.cp0.power_on_reset();

        self.reg_pc = PIF_ROM_START;
    }

    pub fn run(&mut self) {
        loop {
            self.run_instruction();
        }
    }

    pub fn run_instruction(&mut self) {
        let instruction = self.read_word(self.reg_pc);

        let opcode = (instruction >> 26) & 0b111111;
        match opcode {
            0b001111 => {
                // LUI
                let imval = instruction & 0xffff;
                let rt = (instruction >> 16) & 0b11111;
                // assume 32 bit mode
                self.write_gpr(rt as usize, (imval << 16) as u64);
            }
            0b010000 => {
                // MTC0
                let rd = (instruction >> 11) & 0b11111;
                let rt = (instruction >> 16) & 0b11111;
                let data = self.read_gpr(rt as usize);
                self.cp0.write_reg(rd, data);
            }
            _ => {
                panic!("Unrecognised instruction {:#x}", instruction);
            }
        }

        self.reg_pc += 4;
    }

    fn read_word(&self, addr: u64) -> u32 {
        let paddr = vaddr_to_paddr(addr);
        self.bus.read_word(paddr as u32)
    }

    fn write_gpr(&mut self, index: usize, value: u64) {
        if index != 0 {
            self.reg_gprs[index] = value;
        }
    }

    fn read_gpr(&self, index: usize) -> u64 {
        match index {
            0 => 0,
            _ => self.reg_gprs[index],
        }
    }
}

fn vaddr_to_paddr(vaddr: u64) -> u64 {
    let addr_bit_values = (vaddr >> 29) & 0b111;
    if addr_bit_values == 0b101 {
        // kseg1
        vaddr - 0xffff_ffff_a000_0000
    } else {
        panic!("Unrecognised virtual address {:#x}", vaddr);
    }
}
<commit_msg>Implemented ORI<commit_after>use super::super::bus;
use super::cp0::cp0::CP0;

const NUM_GPREG: usize = 32;
const NUM_FPREG: usize = 32;

const PIF_ROM_START: u64 = 0xffff_ffff_bfc0_0000;

#[derive(Debug)]
pub struct Cpu {
    reg_gprs: [u64; NUM_GPREG],
    reg_fprs: [f64; NUM_FPREG],

    reg_pc: u64,

    reg_hi: u64,
    reg_lo: u64,

    reg_llbit: bool,

    reg_fcr0: u32,
    reg_fcr31: u32,

    cp0: CP0,

    bus: bus::Bus,
}

impl Cpu {
    pub fn new(bus: bus::Bus) -> Cpu {
        Cpu {
            reg_gprs: [0; NUM_GPREG],
            reg_fprs: [0.0; NUM_FPREG],

            reg_pc: 0,

            reg_hi: 0,
            reg_lo: 0,

            reg_llbit: false,

            reg_fcr0: 0,
            reg_fcr31: 0,

            cp0: CP0::default(),

            bus: bus,
        }
    }

    pub fn power_on_reset(&mut self) {
        self.cp0.power_on_reset();

        self.reg_pc = PIF_ROM_START;
    }

    pub fn run(&mut self) {
        loop {
            self.run_instruction();
        }
    }

    pub fn run_instruction(&mut self) {
        let instruction = self.read_word(self.reg_pc);

        let opcode = (instruction >> 26) & 0b111111;
        let rs = (instruction >> 21) & 0b11111;
        let rt = (instruction >> 16) & 0b11111;
        let imval = instruction & 0xffff;

        match opcode {
            0b010000 => {
                // MTC0
                let rd = (instruction >> 11) & 0b11111;
                let data = self.read_gpr(rt as usize);
                self.cp0.write_reg(rd, data);
            }
            0b001101 => {
                // ORI
                let res = self.read_gpr(rs as usize) | (imval as u64);
                self.write_gpr(rt as usize, res);
            }
            0b001111 => {
                // LUI
                let rt = (instruction >> 16) & 0b11111;
                // assume 32 bit mode
                self.write_gpr(rt as usize, (imval << 16) as u64);
            }
            _ => {
                panic!("Unrecognised instruction {:#x}", instruction);
            }
        }

        self.reg_pc += 4;
    }

    fn read_word(&self, addr: u64) -> u32 {
        let paddr = vaddr_to_paddr(addr);
        self.bus.read_word(paddr as u32)
    }

    fn write_gpr(&mut self, index: usize, value: u64) {
        if index != 0 {
            self.reg_gprs[index] = value;
        }
    }

    fn read_gpr(&self, index: usize) -> u64 {
        match index {
            0 => 0,
            _ => self.reg_gprs[index],
        }
    }
}

fn vaddr_to_paddr(vaddr: u64) -> u64 {
    let addr_bit_values = (vaddr >> 29) & 0b111;
    if addr_bit_values == 0b101 {
        // kseg1
        vaddr - 0xffff_ffff_a000_0000
    } else {
        panic!("Unrecognised virtual address {:#x}", vaddr);
    }
}
<|endoftext|>


<commit_before>extern crate mysql;
use mysql::prelude::*;
use std;
use model::*;
use user::*;
impl Model for mysql::PooledConn {
    fn get_threads_list(&mut self,offset:usize, count:usize)->Vec<Thread>{
        let sql =format!("SELECT * FROM v_thread_list LIMIT {}, {}", offset, count);
        let params:&[&ToValue] = &[];
        return self.prep_exec(sql,params).unwrap().map(|row|{
            let mut row = row.unwrap();
            Thread::new(
                row.take("uid").expect("uid"),
                row.take("subject").expect("uid"),
                row.take("recent_update").expect("recent_update"),
                row.take("created_datetime").expect("created_datetime"),
                User::new()
                .uid(row.take("opener_uid").expect("opener_uid"))
                .nickname(row.take("opener_nickname").expect("opener_nickname"))
                .email(row.take("opener_email").expect("opener_email"))
            )
        }).collect();
    }

    fn get_thread(&mut self, thread_uid:i32)->Option<Thread>{
        let sql =format!("SELECT * FROM v_thread_list WHERE uid = ? LIMIT 1");
        let params:&[&ToValue] = &[&thread_uid];
        let mut thread = match self.first_exec(sql, params).unwrap(){
            Some(v)=>v,
            None=>return None
        };

        let res = Thread::new(
            thread.take("uid").expect("uid"),
            thread.take("subject").expect("uid"),
            thread.take("recent_update").expect("recent_update"),
            thread.take("created_datetime").expect("created_datetime"),
            User::new()
                .uid(thread.take("opener_uid").expect("opener_uid"))
                .nickname(thread.take("opener_nickname").expect("opener_nickname"))
                .email(thread.take("opener_email").expect("opener_email"))
        );
        return Some(res);
    }
    fn get_comments(&mut self, thread_uid:i32)->Option<Vec<Comment>>{
        let sql ="SELECT * FROM v_comments WHERE thread_uid = ?";
        let params:&[&ToValue] = &[&thread_uid];
        let comments:Vec< _ >  = self.prep_exec(sql,params).unwrap().map(|row|{
            let mut row = row.unwrap();
            Comment::new(
                row.take("uid").expect("uid"),
                User::new()
                .nickname(row.take("user_nickname").expect("user_nickname"))
                    .uid(row.take("user_uid").expect("user_uid"))
                    .email(row.take("user_email").expect("user_email")),
                row.take("write_datetime").expect("write_datetime"),
                row.take("comment").expect("comment")
            )
        }).collect();
        if comments.len() == 0{
            return None;
        }
        return Some(comments);
    }
    fn add_new_comment(&mut self, thread_uid:i32, user:User, content:String)->Result<(), ModelError>{
        let mut stmt = self.prepare(r"INSERT INTO tb_comments
                                       (thread_uid, writer_uid, write_datetime, comment)
                                   VALUES
                                       (:thread_uid, :writer_uid, NOW(), :comment)").unwrap();
        if let Err(e) = stmt.execute(params!{
            "thread_uid" => thread_uid,
            "writer_uid" => user.get_uid(),
            "comment" => content,
        }){
            return Err(ModelError::CollapseInsertData(String::from("E-Mail")));
        }
        Ok(())
    }
    fn add_thread(&mut self, subject:&String, user:User,first_comment:&String)->Result<Thread, ()>{
        use mysql::IsolationLevel;
        let uid:i32;
        {
            let mut transaction = self.start_transaction(false, Some(IsolationLevel::Serializable), Some(false)).unwrap();

            /*
            `uid` INT(11) NOT NULL AUTO_INCREMENT,
        `opener_uid` INT(11) NOT NULL DEFAULT '0',
        `opener_nickname` VARCHAR(32) NOT NULL,
        `subject` VARCHAR(64) NOT NULL COLLATE 'utf8mb4_unicode_ci',
        `created_datetime` DATETIME NOT NULL,
            */
            let params:&[&ToValue] = &[&user.get_uid(), &user.get_nickname(), subject];
            transaction.prep_exec("INSERT INTO tb_threads (opener_uid, opener_nickname, subject, created_datetime) VALUES (?,?,?,now())",params);
            let row = transaction.first("SELECT LAST_INSERT_ID() FROM tb_threads").unwrap();
            let row = row.unwrap();
            uid = row.get(0).unwrap();
            transaction.prep_exec(r"INSERT INTO tb_comments
                                       (thread_uid, writer_uid, write_datetime, comment)
                                   VALUES
                                       (:thread_uid, :writer_uid, NOW(), :comment)",params!{
                "thread_uid" => uid,
                "writer_uid" => user.get_uid(),
                "comment" => first_comment,
            }).unwrap();
            transaction.commit();

        }
        return match self.get_thread(uid){
            Some(v)=>Ok(v),
            None=>Err(())
        };
    }
    // add code here
}

impl Tag{
    pub fn list(model:&mut mysql::PooledConn, q:&str)->Vec<Tag>{
        let sql = "SELECT * FROM v_tag_threads_count_list where tag_name LIKE ?";
        let params:&[&ToValue] = &[&format!("%{}%", q)];

        let mut threads:Vec<Thread> = Vec::new();
        //let thread_uids:Vec<i32> =
        model.prep_exec(sql,params).unwrap().map(|row|{
            let row = row.unwrap();
            return Tag::new(row.get(0).unwrap()).with_thread_count(row.get(1).unwrap());
        }).collect()
    }
    pub fn get(model:&mut mysql::PooledConn, name:&str)->Tag{
        let sql = "SELECT thread_uid FROM v_tags where tag_name=?";
        let params:&[&ToValue] = &[&name];

        let mut threads:Vec<Thread> = Vec::new();
        let thread_uids:Vec<i32> =
        model.prep_exec(sql,params).unwrap().map(|row|{
            let row = row.unwrap();
            //eprintln!("{:?}",row);
            return row.get(0).unwrap();
        }).collect();
        //.into_iter()
        for uid in thread_uids{
            threads.push(match model.get_thread(uid){
                Some(v)=>v,
                None=>continue
            });
        }
        return Tag::new(name.to_string()).with_threads(threads);
    }
    pub fn put(&mut self,model:&mut mysql::PooledConn, thread:&Thread){
        let sql = "INSERT INTO tb_tags VALUES (?, ?)";
        let param:&[&ToValue] = &[self.get_name(), &thread.get_uid()];
        model.prep_exec(sql, param).unwrap();
    }
    pub fn delete(&mut self,model:&mut mysql::PooledConn, thread:&Thread){
        let sql = "DELETE FROM tb_tags WHERE thread_uid = ?";
        let param:&[&ToValue] = &[&thread.get_uid()];
        model.prep_exec(sql, param).unwrap();
    }
}
impl Thread{
    pub fn list(model:&mut mysql::PooledConn ,mut q: Option<String>, offset:usize, count:usize)->Vec<Thread>{
        //let sql =format!("SELECT * FROM v_thread_list WHERE subject like ?");
        let mut sql = String::from("SELECT * FROM v_thread_list ");
        use std::fmt::{Error, Write};
        return if let Some(ref mut q) = q{
            let t = format!("%{}%", q);
            let params:&[&ToValue]= &[&t];
            sql.push_str("WHERE subject LIKE ? ");

            write!(&mut sql, "LIMIT {}, {}", offset, count);
            model.prep_exec(sql,params).unwrap().map(|row|{
            let mut row = row.unwrap();
            Thread::new(
                row.take("uid").expect("uid"),
                row.take("subject").expect("uid"),
                row.take("recent_update").expect("recent_update"),
                row.take("created_datetime").expect("created_datetime"),
                User::new()
                .uid(row.take("opener_uid").expect("opener_uid"))
                .nickname(row.take("opener_nickname").expect("opener_nickname"))
                .email(row.take("opener_email").expect("opener_email"))
            )
            }).collect()
        }
        else{
            let params:&[&ToValue] = &[];
            write!(&mut sql, "LIMIT {}, {}", offset, count);
            model.prep_exec(sql,params).unwrap().map(|row|{
            let mut row = row.unwrap();
            Thread::new(
                row.take("uid").expect("uid"),
                row.take("subject").expect("uid"),
                row.take("recent_update").expect("recent_update"),
                row.take("created_datetime").expect("created_datetime"),
                User::new()
                .uid(row.take("opener_uid").expect("opener_uid"))
                .nickname(row.take("opener_nickname").expect("opener_nickname"))
                .email(row.take("opener_email").expect("opener_email"))
            )
            }).collect()
        };
    }
}<commit_msg>last_insert_id수정<commit_after>extern crate mysql;
use mysql::prelude::*;
use std;
use model::*;
use user::*;
impl Model for mysql::PooledConn {
    fn get_threads_list(&mut self,offset:usize, count:usize)->Vec<Thread>{
        let sql =format!("SELECT * FROM v_thread_list LIMIT {}, {}", offset, count);
        let params:&[&ToValue] = &[];
        return self.prep_exec(sql,params).unwrap().map(|row|{
            let mut row = row.unwrap();
            Thread::new(
                row.take("uid").expect("uid"),
                row.take("subject").expect("uid"),
                row.take("recent_update").expect("recent_update"),
                row.take("created_datetime").expect("created_datetime"),
                User::new()
                .uid(row.take("opener_uid").expect("opener_uid"))
                .nickname(row.take("opener_nickname").expect("opener_nickname"))
                .email(row.take("opener_email").expect("opener_email"))
            )
        }).collect();
    }

    fn get_thread(&mut self, thread_uid:i32)->Option<Thread>{
        let sql =format!("SELECT * FROM v_thread_list WHERE uid = ? LIMIT 1");
        let params:&[&ToValue] = &[&thread_uid];
        let mut thread = match self.first_exec(sql, params).unwrap(){
            Some(v)=>v,
            None=>return None
        };

        let res = Thread::new(
            thread.take("uid").expect("uid"),
            thread.take("subject").expect("uid"),
            thread.take("recent_update").expect("recent_update"),
            thread.take("created_datetime").expect("created_datetime"),
            User::new()
                .uid(thread.take("opener_uid").expect("opener_uid"))
                .nickname(thread.take("opener_nickname").expect("opener_nickname"))
                .email(thread.take("opener_email").expect("opener_email"))
        );
        return Some(res);
    }
    fn get_comments(&mut self, thread_uid:i32)->Option<Vec<Comment>>{
        let sql ="SELECT * FROM v_comments WHERE thread_uid = ?";
        let params:&[&ToValue] = &[&thread_uid];
        let comments:Vec< _ >  = self.prep_exec(sql,params).unwrap().map(|row|{
            let mut row = row.unwrap();
            Comment::new(
                row.take("uid").expect("uid"),
                User::new()
                .nickname(row.take("user_nickname").expect("user_nickname"))
                    .uid(row.take("user_uid").expect("user_uid"))
                    .email(row.take("user_email").expect("user_email")),
                row.take("write_datetime").expect("write_datetime"),
                row.take("comment").expect("comment")
            )
        }).collect();
        if comments.len() == 0{
            return None;
        }
        return Some(comments);
    }
    fn add_new_comment(&mut self, thread_uid:i32, user:User, content:String)->Result<(), ModelError>{
        let mut stmt = self.prepare(r"INSERT INTO tb_comments
                                       (thread_uid, writer_uid, write_datetime, comment)
                                   VALUES
                                       (:thread_uid, :writer_uid, NOW(), :comment)").unwrap();
        if let Err(e) = stmt.execute(params!{
            "thread_uid" => thread_uid,
            "writer_uid" => user.get_uid(),
            "comment" => content,
        }){
            return Err(ModelError::CollapseInsertData(String::from("E-Mail")));
        }
        Ok(())
    }
    fn add_thread(&mut self, subject:&String, user:User,first_comment:&String)->Result<Thread, ()>{
        use mysql::IsolationLevel;
        let uid:i32;
        {
            let mut transaction = self.start_transaction(false, Some(IsolationLevel::Serializable), Some(false)).unwrap();
            let params:&[&ToValue] = &[&user.get_uid(), &user.get_nickname(), subject];
            {
                let result = transaction.prep_exec("INSERT INTO tb_threads (opener_uid, opener_nickname, subject, created_datetime) VALUES (?,?,?,now())",params).unwrap();
                uid = result.last_insert_id() as i32;
            }
            transaction.prep_exec(r"INSERT INTO tb_comments
                                       (thread_uid, writer_uid, write_datetime, comment)
                                   VALUES
                                       (:thread_uid, :writer_uid, NOW(), :comment)",params!{
                "thread_uid" => uid,
                "writer_uid" => user.get_uid(),
                "comment" => first_comment,
            }).unwrap();
            transaction.commit();

        }
        return match self.get_thread(uid){
            Some(v)=>Ok(v),
            None=>Err(())
        };
    }
    // add code here
}

impl Tag{
    pub fn list(model:&mut mysql::PooledConn, q:&str)->Vec<Tag>{
        let sql = "SELECT * FROM v_tag_threads_count_list where tag_name LIKE ?";
        let params:&[&ToValue] = &[&format!("%{}%", q)];

        let mut threads:Vec<Thread> = Vec::new();
        //let thread_uids:Vec<i32> =
        model.prep_exec(sql,params).unwrap().map(|row|{
            let row = row.unwrap();
            return Tag::new(row.get(0).unwrap()).with_thread_count(row.get(1).unwrap());
        }).collect()
    }
    pub fn get(model:&mut mysql::PooledConn, name:&str)->Tag{
        let sql = "SELECT thread_uid FROM v_tags where tag_name=?";
        let params:&[&ToValue] = &[&name];

        let mut threads:Vec<Thread> = Vec::new();
        let thread_uids:Vec<i32> =
        model.prep_exec(sql,params).unwrap().map(|row|{
            let row = row.unwrap();
            //eprintln!("{:?}",row);
            return row.get(0).unwrap();
        }).collect();
        //.into_iter()
        for uid in thread_uids{
            threads.push(match model.get_thread(uid){
                Some(v)=>v,
                None=>continue
            });
        }
        return Tag::new(name.to_string()).with_threads(threads);
    }
    pub fn put(&mut self,model:&mut mysql::PooledConn, thread:&Thread){
        let sql = "INSERT INTO tb_tags VALUES (?, ?)";
        let param:&[&ToValue] = &[self.get_name(), &thread.get_uid()];
        model.prep_exec(sql, param).unwrap();
    }
    pub fn delete(&mut self,model:&mut mysql::PooledConn, thread:&Thread){
        let sql = "DELETE FROM tb_tags WHERE thread_uid = ?";
        let param:&[&ToValue] = &[&thread.get_uid()];
        model.prep_exec(sql, param).unwrap();
    }
}
impl Thread{
    pub fn list(model:&mut mysql::PooledConn ,mut q: Option<String>, offset:usize, count:usize)->Vec<Thread>{
        //let sql =format!("SELECT * FROM v_thread_list WHERE subject like ?");
        let mut sql = String::from("SELECT * FROM v_thread_list ");
        use std::fmt::{Error, Write};
        return if let Some(ref mut q) = q{
            let t = format!("%{}%", q);
            let params:&[&ToValue]= &[&t];
            sql.push_str("WHERE subject LIKE ? ");

            write!(&mut sql, "LIMIT {}, {}", offset, count);
            model.prep_exec(sql,params).unwrap().map(|row|{
            let mut row = row.unwrap();
            Thread::new(
                row.take("uid").expect("uid"),
                row.take("subject").expect("uid"),
                row.take("recent_update").expect("recent_update"),
                row.take("created_datetime").expect("created_datetime"),
                User::new()
                .uid(row.take("opener_uid").expect("opener_uid"))
                .nickname(row.take("opener_nickname").expect("opener_nickname"))
                .email(row.take("opener_email").expect("opener_email"))
            )
            }).collect()
        }
        else{
            let params:&[&ToValue] = &[];
            write!(&mut sql, "LIMIT {}, {}", offset, count);
            model.prep_exec(sql,params).unwrap().map(|row|{
            let mut row = row.unwrap();
            Thread::new(
                row.take("uid").expect("uid"),
                row.take("subject").expect("uid"),
                row.take("recent_update").expect("recent_update"),
                row.take("created_datetime").expect("created_datetime"),
                User::new()
                .uid(row.take("opener_uid").expect("opener_uid"))
                .nickname(row.take("opener_nickname").expect("opener_nickname"))
                .email(row.take("opener_email").expect("opener_email"))
            )
            }).collect()
        };
    }
}<|endoftext|>


<commit_before>use std::io::{Read, Seek, SeekFrom};
use byteorder::{BigEndian, ByteOrder};
use {HEADER_LEN, FarbfeldError, FarbfeldResult};

/// A farbfeld decoder
#[derive(Debug)]
pub struct FarbfeldDecoder<R> {
    r: R,

    width: u32,
    height: u32,
}

impl<R: Read + Seek> FarbfeldDecoder<R> {
    /// Create a new decoder from `r` and parse the header.
    /// # Failures
    /// Returns FarbfeldError::FormatError if the magic number does not match `farbfeld`
    pub fn new(r: R) -> FarbfeldResult<FarbfeldDecoder<R>> {
        let mut r = r;
        try!(r.seek(SeekFrom::Start(0)));
        let head = &mut [0; HEADER_LEN as usize];
        try!(r.read_exact(head));
        if &head[..8] != "farbfeld".as_bytes() {
                return Err(FarbfeldError::FormatError("unexpected magic number".to_string()))
        }

        Ok(FarbfeldDecoder {
            r: r,
            width: BigEndian::read_u32(&head[8..]),
            height: BigEndian::read_u32(&head[12..]),
        })
    }

    /// Returns the `(width, height)` of the image.
    pub fn dimensions(&mut self) -> (u32, u32) {
        (self.width, self.height)
    }

    /// Returns the length in bytes for a row.
    pub fn row_len(&mut self) -> usize {
        self.width as usize * 8
    }

    /// Read a single row from the image and return the bytes read.
    /// # Failures
    /// Returns a `FarbfeldError::ImageEnd` if the `row` is greater as the `height`
    pub fn read_row(&mut self, row: u32,  buf: &mut [u8]) -> FarbfeldResult<usize> {
        if row > self.height { return Err(FarbfeldError::ImageEnd) }

        let row_len = self.row_len();
        let offset = HEADER_LEN + row as u64 * row_len as u64;
        try!(self.r.seek(SeekFrom::Start(offset)));
        try!(self.r.read_exact(&mut buf[..row_len]));
        Ok(row_len)
    }

    /// Read whole image into a `Vec<u8>`.
    pub fn read_image(&mut self) -> FarbfeldResult<Vec<u8>> {
        try!(self.r.seek(SeekFrom::Start(HEADER_LEN)));
        let num_raw_bytes = self.height as usize * self.row_len();
        let mut buf = vec![0; num_raw_bytes];
        try!(self.r.read_exact(&mut buf));
        Ok(buf)
    }
}

#[cfg(test)]
mod tests {
    use std::io::{Cursor, ErrorKind, Write};
    use FarbfeldDecoder;
    use tests::IMAGE_DATA;
    use FarbfeldError;

    macro_rules! try_panic {
        ($e:expr) => {
            match $e {
                Err(e) => panic!(e),
                Ok(res) => res,
            }
        }
    }

    #[test]
    fn invalid_magic() {
        let mut img_data = Vec::new();
        try_panic!(img_data.write(b"test fail"));
        try_panic!(img_data.write(&IMAGE_DATA[8..]));
        let buf = Cursor::new(img_data);

        match FarbfeldDecoder::new(buf) {
            Err(e) => match e {
                FarbfeldError::FormatError(_) => return,
                e => panic!("{:?}", e),
            },
            Ok(_) => panic!("Got Ok expected FarbfeldError::FormatError"),
        }
    }

    #[test]
    fn truncate_header() {
        let buf = Cursor::new(&IMAGE_DATA[0..8]);

        match FarbfeldDecoder::new(buf) {
            Err(FarbfeldError::IoError(e)) => {
                if e.kind() == ErrorKind::UnexpectedEof {
                    return
                } else { panic!("{:?}", e) }
            },
            Err(e) => panic!("{:?}", e),
            Ok(_) => panic!("Got Ok expected FarbfeldError::FormatError"),
        }

    }

    #[test]
    fn truncate_data() {
        let mut img_data = Vec::with_capacity(IMAGE_DATA.len()-1);
        try_panic!(img_data.write_all(&IMAGE_DATA[..IMAGE_DATA.len()-1]));
        let buf = Cursor::new(img_data);
        let mut img = FarbfeldDecoder::new(buf).unwrap();
        match img.read_image() {
            Err(FarbfeldError::IoError(e)) => {
                if e.kind() == ErrorKind::UnexpectedEof {
                    return
                } else { panic!("{:?}", e) }
            },
            Err(e) => panic!("{:?}", e),
            Ok(_) => panic!("Got Ok expected FarbfeldError::FormatError"),
        }
    }
}
<commit_msg>use b"" syntax<commit_after>use std::io::{Read, Seek, SeekFrom};
use byteorder::{BigEndian, ByteOrder};
use {HEADER_LEN, FarbfeldError, FarbfeldResult};

/// A farbfeld decoder
#[derive(Debug)]
pub struct FarbfeldDecoder<R> {
    r: R,

    width: u32,
    height: u32,
}

impl<R: Read + Seek> FarbfeldDecoder<R> {
    /// Create a new decoder from `r` and parse the header.
    /// # Failures
    /// Returns FarbfeldError::FormatError if the magic number does not match `farbfeld`
    pub fn new(r: R) -> FarbfeldResult<FarbfeldDecoder<R>> {
        let mut r = r;
        try!(r.seek(SeekFrom::Start(0)));
        let head = &mut [0; HEADER_LEN as usize];
        try!(r.read_exact(head));
        if &head[..8] != b"farbfeld" {
                return Err(FarbfeldError::FormatError("unexpected magic number".to_string()))
        }

        Ok(FarbfeldDecoder {
            r: r,
            width: BigEndian::read_u32(&head[8..]),
            height: BigEndian::read_u32(&head[12..]),
        })
    }

    /// Returns the `(width, height)` of the image.
    pub fn dimensions(&mut self) -> (u32, u32) {
        (self.width, self.height)
    }

    /// Returns the length in bytes for a row.
    pub fn row_len(&mut self) -> usize {
        self.width as usize * 8
    }

    /// Read a single row from the image and return the bytes read.
    /// # Failures
    /// Returns a `FarbfeldError::ImageEnd` if the `row` is greater as the `height`
    pub fn read_row(&mut self, row: u32,  buf: &mut [u8]) -> FarbfeldResult<usize> {
        if row > self.height { return Err(FarbfeldError::ImageEnd) }

        let row_len = self.row_len();
        let offset = HEADER_LEN + row as u64 * row_len as u64;
        try!(self.r.seek(SeekFrom::Start(offset)));
        try!(self.r.read_exact(&mut buf[..row_len]));
        Ok(row_len)
    }

    /// Read whole image into a `Vec<u8>`.
    pub fn read_image(&mut self) -> FarbfeldResult<Vec<u8>> {
        try!(self.r.seek(SeekFrom::Start(HEADER_LEN)));
        let num_raw_bytes = self.height as usize * self.row_len();
        let mut buf = vec![0; num_raw_bytes];
        try!(self.r.read_exact(&mut buf));
        Ok(buf)
    }
}

#[cfg(test)]
mod tests {
    use std::io::{Cursor, ErrorKind, Write};
    use FarbfeldDecoder;
    use tests::IMAGE_DATA;
    use FarbfeldError;

    macro_rules! try_panic {
        ($e:expr) => {
            match $e {
                Err(e) => panic!(e),
                Ok(res) => res,
            }
        }
    }

    #[test]
    fn invalid_magic() {
        let mut img_data = Vec::new();
        try_panic!(img_data.write(b"test fail"));
        try_panic!(img_data.write(&IMAGE_DATA[8..]));
        let buf = Cursor::new(img_data);

        match FarbfeldDecoder::new(buf) {
            Err(e) => match e {
                FarbfeldError::FormatError(_) => return,
                e => panic!("{:?}", e),
            },
            Ok(_) => panic!("Got Ok expected FarbfeldError::FormatError"),
        }
    }

    #[test]
    fn truncate_header() {
        let buf = Cursor::new(&IMAGE_DATA[0..8]);

        match FarbfeldDecoder::new(buf) {
            Err(FarbfeldError::IoError(e)) => {
                if e.kind() == ErrorKind::UnexpectedEof {
                    return
                } else { panic!("{:?}", e) }
            },
            Err(e) => panic!("{:?}", e),
            Ok(_) => panic!("Got Ok expected FarbfeldError::FormatError"),
        }

    }

    #[test]
    fn truncate_data() {
        let mut img_data = Vec::with_capacity(IMAGE_DATA.len()-1);
        try_panic!(img_data.write_all(&IMAGE_DATA[..IMAGE_DATA.len()-1]));
        let buf = Cursor::new(img_data);
        let mut img = FarbfeldDecoder::new(buf).unwrap();
        match img.read_image() {
            Err(FarbfeldError::IoError(e)) => {
                if e.kind() == ErrorKind::UnexpectedEof {
                    return
                } else { panic!("{:?}", e) }
            },
            Err(e) => panic!("{:?}", e),
            Ok(_) => panic!("Got Ok expected FarbfeldError::FormatError"),
        }
    }
}
<|endoftext|>