<commit_before>//! Bindings to various errno.h definitions.

///Error numbers defined in errno-base.h, with some exceptions which are marked accordingly
pub mod errno_base {

    ///Operation not permitted
    pub const EPERM: ::c_int = 1;

    ///No such file or directory
    pub const ENOENT: ::c_int = 2;

    ///No such process
    pub const ESRCH: ::c_int = 3;

    ///Interrupted system call. Oops
    pub const EINTR: ::c_int = 4;

    ///I/O error.
    pub const EIO: ::c_int = 5;

    ///No such device or address
    pub const ENXIO: ::c_int = 6;

    ///Argument list too long.
    ///
    ///You thought it was error too big, didn't you?
    pub const E2BIG: ::c_int = 7;

    ///Exec format error
    pub const ENOEXEC: ::c_int = 8;

    ///Bad file number
    pub const EBADF: ::c_int = 9;

    ///No child processes
    ///
    ///Alternatively, your name is Anthony Dinozzo Jr or Richard Castle
    pub const ECHILD: ::c_int = 10;

    ///Try again, I'm not really an error, just an annoyance
    pub const EAGAIN: ::c_int = 11;

    ///Out of memory
    pub const ENOMEM: ::c_int = 12;

    ///Permission denied!
    pub const EACCES: ::c_int = 13;

    ///Bad address
    pub const EFAULT: ::c_int = 14;

    ///Block device required but not found
    pub const ENOTBLK: ::c_int = 15;

    ///Device or resource is too busy to listen to you right now
    pub const EBUSY: ::c_int = 16;

    ///File already exists
    pub const EEXIST: ::c_int = 17;

    ///Cross-device link. Sorry, but quantum entanglement is not working in storage drives yet
    pub const EXDEV: ::c_int = 18;

    ///No such device.
    ///
    ///Alternatively, you have been robbed by a Jedi knight. "This is not the device you were searching for"
    pub const ENODEV: ::c_int = 19;

    ///That's... not a directory
    pub const ENOTDIR: ::c_int = 20;

    ///That's... not a file. That's a directory
    pub const EISDIR: ::c_int = 21;

    ///Your argument is invalid!
    pub const EINVAL: ::c_int = 22;

    ///File table overflowed
    pub const ENFILE: ::c_int = 23;

    ///Too many files are already open
    pub const EMFILE: ::c_int = 24;

    ///You are not a typewriter
    ///
    ///Does this expand to you are not a terminal? What a about a smart kettle? Or a WIFI-enabled microwave? Hey, somebody should go patent that
    pub const ENOTTTY: ::c_int = 25;

    ///Text file is too busy to listen to you right now
    pub const ETXTBSY: ::c_int = 26; //Ooooh, what are you writing?

    ///File is too large. What are you doing, downloading a car?
    pub const EFBIG: ::c_int = 27; //Okay, really, how?

    ///You don't have any (or at least enough) space left on the specified device. You might need a new hard drive.
    ///
    ///Might I suggest a SSD? They cost more but the performance gain is worth it
    pub const ENOSPC: ::c_int = 28; //I'm so sorry

    ///Illegal seek
    ///
    ///What the hell are you doing?
    pub const ESPIPE: ::c_int = 29;

    ///You're trying to write to a read-only file system.
    pub const EROFS: ::c_int = 30; //Haha, nice try

    ///Too many links exist
    pub const EMLINK: ::c_int = 31;

    ///Broken pipe
    pub const EPIPE: ::c_int = 32;

    ///Math argument is out of the function's domain
    ///
    ///??? I need more coffee to get this. Is it like trying to check if an int is NaN?
    pub const EDOM: ::c_int = 33;

    ///Math result could not be represented
    ///
    ///Stop trying to divide by ze--- ```EACCES```
    pub const ERANGE: ::c_int = 34;

}

pub use self::errno_base::*;

#[cfg(not(any(target_arch = "alpha", target_arch = "mips", target_arch = "parisc", target_arch = "sparc")))]
pub mod errno_common {

    ///Resource deadlock would occur
    pub const EDEADLK: ::c_int = 35;

    ///File name is too long. (Hah!)
    pub const ENAMETOOLONG: ::c_int = 36;

    ///No record locks available
    pub const ENOLCK: ::c_int = 37;

    ///Invalid system call number
    ///
    ///This is special. Arch syscall entry code returns -ENOSYS if
    ///users try to call a syscall that doesn't exist.
    pub const ENOSYS: ::c_int = 38;

    ///Directory is not empty.
    pub const ENOTEMPTY: ::c_int = 39;

    ///Too many symbolic links encountered. This is probably an infinite loop
    ///
    ///Alternatively, you broke your computer.
    pub const ELOOP: ::c_int = 40;

    ///Operation would block. You should try again?
    pub const EWOULDBLOCK: ::c_int = ::EAGAIN;

    ///No message of the desired type
    pub const ENOMSG: ::c_int = 42;

    ///Identifier was removed
    pub const EIDRM: ::c_int = 43;

    ///Channel number is out of acceptable range
    pub const ECHRNG: ::c_int = 44;

    ///Level 2 is not synchronized
    pub const EL2NSYNC: ::c_int = 45;

    ///Level 3 was halted
    pub const EL3HLT: ::c_int = 46;

    ///Level 3 was reset
    pub const EL3RST: ::c_int = 47;

    ///Link number is out of range
    ///
    ///How do you do this?
    pub const ELNRNG: ::c_int = 48;

    ///Protocol driver not attached
    pub const EUNATCH: ::c_int = 49;

    ///No CSI structure is available
    pub const ENOCSI: ::c_int = 50;

    ///Level 2 was halted
    pub const EL2HLT: ::c_int = 51;

    ///Invalid exchange
    pub const EBADE: ::c_int = 52;

    ///Invalid request descriptor
    pub const EBADR: ::c_int = 53;

    ///Exchange is full.
    ///
    ///I am so sorry
    pub const EXFULL: ::c_int = 54;

    ///No anode is available
    pub const ENOANO: ::c_int = 55;

    ///Invalid request code
    pub const EBADRQC: ::c_int = 56;

    ///Invalid slot
    pub const EBADSLT: ::c_int = 57;

    #[cfg(not(target_arch = "powerpc"))]
    ///A deadlock would occur, again
    pub const EDEADLOCK: ::c_int = EDEADLK;

    #[cfg(target_arch = "powerpc")]
    ///A deadlock would occur, again
    pub const EDEADLOCK: ::c_int = 58;

    ///Bad font file format
    pub const EBFONT: ::c_int = 59;

    ///Device is not a stream
    pub const ENOSTR: ::c_int = 60;

    ///No data is available
    pub const ENODATA: ::c_int = 61;

    ///Timer expired
    pub const ETIME: ::c_int = 62;

    ///Out of streams resources
    ///
    ///Should this be stream's? I'm not sure about the context. Is it the resources of the stream, or resources of the system's supply of streams?
    pub const ENOSR: ::c_int = 63;

    ///Requested machine was not on the network
    pub const ENONET: ::c_int = 64;

    ///Package is not installed
    pub const ENOPKG: ::c_int = 65;

    ///Object is remote when it is required to be local
    pub const EREMOTE: ::c_int = 66;

    ///Link has been severed
    pub const ENOLINK: ::c_int = 67;

    ///Error in advertising
    pub const EADV: ::c_int = 68;

    ///Srmount error
    pub const ESRMNT: ::c_int = 69;

    ///Communications error on send
    pub const ECOMM: ::c_int = 70;

    ///Protocol error
    pub const EPROTO: ::c_int = 71;

    ///A multihop was attempted
    pub const EMULTIHOP: ::c_int = 72;

    ///A RFS-specific error occurred
    pub const EDOTDOT: ::c_int = 73;

    ///Message is not a data message
    pub const EBADMASG: ::c_int = 74;

    ///Value is too large for the defined data type
    pub const EOVERFLOW: ::c_int = 75;

    ///Name is not unique on the network
    ///
    ///No, BILLY_TABLES, you can't have ten computers called '; DROP TABLE users' for "backup purposes"
    pub const ENOTUNIQ: ::c_int = 76;

    ///File descriptor is in a bad state
    ///
    ///Huh. I haven't seen this before
    pub const EBADFD: ::c_int = 77;

    ///The remote address changed.
    ///
    ///How does this happen? A change from wifi to 4g, etc?
    pub const EREMCHG: ::c_int = 78;

    ///Can not access a needed shared library
    ///
    ///Thankfully, with Cargo, this shouldn't happen :)
    pub const ELIBACC: ::c_int = 79;

    ///Attempted to access a shared library, only to find out it was corrupted
    ///
    ///WELL, FUCK.
    pub const ELIBBAD: ::c_int = 80;

    ///.lib section in a.out is corrupted
    pub const ELIBSCN: ::c_int = 81;

    ///Attempting to link in too many shared libraries
    ///
    ///Are... are you okay?
    pub const ELIBMAX: ::c_int = 82;

    ///Cannot exec a shared library directly
    pub const ELIBEXEC: ::c_int = 83;

    ///Illegal byte sequence
    ///
    ///I don't know what the hell you are doing, but you're probably doing it wrong
    pub const EILSEQ: ::c_int = 84;

    ///Interrupted system call, you should restart it
    ///
    ///Well, that's easy
    pub const ERESTART: ::c_int = 85;

    ///Streams pipe error
    pub const ESTRPIPE: ::c_int = 86;

    ///Too many users
    ///
    ///*Points finger and laughs*
    pub const EUSERS: ::c_int = 87;

    ///Socket operation attempted on an object that is not a socket
    pub const ENOTSOCK: ::c_int = 88;

    ///Destination address required
    pub const EDESTADDRREQ: ::c_int = 89;

    ///Message is too long
    pub const EMSGSIZE: ::c_int = 90;

    ///Protocol type is wrong for this socket
    pub const EPROTOTYPE: ::c_int = 91;

    ///Protocol is not available
    pub const ENOPROTOOPT: ::c_int = 92;

    ///Protocol is not supported
    pub const EPROTONOSUPPORT: ::c_int = 93;

    ///Socket type is not supported
    ///
    ///What?
    pub const ESOCKTNOSUPPORT: ::c_int = 94;

    ///Operation not supported on transport endpoint
    pub const EOPNOTSUPP: ::c_int = 95;

    ///Protocol family is not supported
    pub const EPFNOSUPPORT: ::c_int = 96;

    ///Address family is not supported by this protocol
    pub const EAFNOSUPPORT: ::c_int = 97;

    ///Address is already in use
    pub const EADDRINUSE: ::c_int = 98;

    ///Cannot assign the requested address
    pub const EADDRNOTAVAIL: ::c_int = 99;

    ///Network is down
    pub const ENETDOWN: ::c_int = 100;

    ///Network is unreachable :(
    pub const ENETUNREACH: ::c_int = 101;

    ///Network dropped connection because of a reset
    pub const ENETRESET: ::c_int = 102;

    ///Software caused the connection to abort
    pub const ECONNABORTED: ::c_int = 103;

    ///Connection was reset by a peer
    pub const ECONNRESET: ::c_int = 104;

    ///No buffer space is available
    pub const ENOBUFS: ::c_int = 105;

    ///Transport endpoint is already connected
    pub const EISCONN: ::c_int = 106;

    ///Transport endpoint is not connected
    pub const ENOTCONN: ::c_int = 107;

    ///Cannot send after the transport endpoint is shut down
    pub const ESHUTDOWN: ::c_int = 108;

    ///Too many references; Cannot splice
    pub const ETOOMANYREFS: ::c_int = 109;

    ///Connection timed out
    pub const ETIMEDOUT: ::c_int = 110;

    ///Connection was refused
    pub const ECONNREFUSED: ::c_int = 111;

    ///The host is down! D:
    pub const EHOSTDOWN: ::c_int = 112;

    ///There is no usable route to the host
    pub const EHOSTUNREACH: ::c_int = 113;

    ///Operation is already in progress. Be patient!
    pub const EALREADY: ::c_int = 114;

    ///Operation is in progress
    pub const EINPROGRESS: ::c_int = 115;

    ///The file handle is stale. Ew!
    pub const ESTALE: ::c_int = 116;

    ///The structure needs cleaning
    pub const EUCLEAN: ::c_int = 117;

    ///This is not a XENIX named type file
    pub const ENOTNAM: ::c_int = 118;

    ///No XENIX semaphores are available
    pub const ENAVAIL: ::c_int = 119;

    ///This is a named type file
    pub const EISNAM: ::c_int = 120;

    ///A remote I/O error occurred
    pub const EREMOTEIO: ::c_int = 121;

    ///You exceeded your quote
    pub const EDQUOT: ::c_int = 122;

    ///No medium was found
    pub const ENOMEDIUM: ::c_int = 123;

    ///You're using the wrong medium type
    pub const EMEDIUMTYPE: ::c_int = 124;

    ///The operation was cancelled
    pub const ECANCELED: ::c_int = 125;

    ///The required key is not available
    pub const ENOKEY: ::c_int = 126;

    ///The key you're using has expired
    pub const EKEYEXPIRED: ::c_int = 127;

    ///The key you're using has been revoked
    pub const EKEYREVOKED: ::c_int = 128;

    ///The key you're using was rejected by the service you're trying to access
    pub const EKEYREJECTED: ::c_int = 129;

    ///Your owner died.
    ///
    ///Dobby is a free computer!
    ///
    ///Just kidding. Your mutex's owner died. Dobby is still a slave
    pub const EOWNERDEAD: ::c_int = 130;

    ///The state of your mutex is not recoverable
    pub const ENOTRECOVERABLE: ::c_int = 131;

    ///Operation is not possible due to RF-kill
    pub const ERFKILL: ::c_int = 132;

    ///The memory page has a hardware error
    pub const EHWPOISON: ::c_int = 133;

}

#[cfg(not(any(target_arch = "alpha", target_arch = "mips", target_arch = "parisc", target_arch = "sparc")))]
pub use self::errno_common::*;<commit_msg>errno_base: Add compatibility for alpha<commit_after>//! Bindings to various errno.h definitions.

///Error numbers defined in errno-base.h, with some exceptions which are marked accordingly
pub mod errno_base {

    ///Operation not permitted
    pub const EPERM: ::c_int = 1;

    ///No such file or directory
    pub const ENOENT: ::c_int = 2;

    ///No such process
    pub const ESRCH: ::c_int = 3;

    ///Interrupted system call. Oops
    pub const EINTR: ::c_int = 4;

    ///I/O error.
    pub const EIO: ::c_int = 5;

    ///No such device or address
    pub const ENXIO: ::c_int = 6;

    ///Argument list too long.
    ///
    ///You thought it was error too big, didn't you?
    pub const E2BIG: ::c_int = 7;

    ///Exec format error
    pub const ENOEXEC: ::c_int = 8;

    ///Bad file number
    pub const EBADF: ::c_int = 9;

    ///No child processes
    ///
    ///Alternatively, your name is Anthony Dinozzo Jr or Richard Castle
    pub const ECHILD: ::c_int = 10;

    #[cfg(not(target_arch = "alpha"))]
    ///Try again, I'm not really an error, just an annoyance
    pub const EAGAIN: ::c_int = 11;

    #[cfg(target_arch = "alpha")]
    ///Try again, I'm not really an error, just an annoyance
    pub const EAGAIN: ::c_int = 35;

    ///Out of memory
    pub const ENOMEM: ::c_int = 12;

    ///Permission denied!
    pub const EACCES: ::c_int = 13;

    ///Bad address
    pub const EFAULT: ::c_int = 14;

    ///Block device required but not found
    pub const ENOTBLK: ::c_int = 15;

    ///Device or resource is too busy to listen to you right now
    pub const EBUSY: ::c_int = 16;

    ///File already exists
    pub const EEXIST: ::c_int = 17;

    ///Cross-device link. Sorry, but quantum entanglement is not working in storage drives yet
    pub const EXDEV: ::c_int = 18;

    ///No such device.
    ///
    ///Alternatively, you have been robbed by a Jedi knight. "This is not the device you were searching for"
    pub const ENODEV: ::c_int = 19;

    ///That's... not a directory
    pub const ENOTDIR: ::c_int = 20;

    ///That's... not a file. That's a directory
    pub const EISDIR: ::c_int = 21;

    ///Your argument is invalid!
    pub const EINVAL: ::c_int = 22;

    ///File table overflowed
    pub const ENFILE: ::c_int = 23;

    ///Too many files are already open
    pub const EMFILE: ::c_int = 24;

    ///You are not a typewriter
    ///
    ///Does this expand to you are not a terminal? What a about a smart kettle? Or a WIFI-enabled microwave? Hey, somebody should go patent that
    pub const ENOTTTY: ::c_int = 25;

    ///Text file is too busy to listen to you right now
    pub const ETXTBSY: ::c_int = 26; //Ooooh, what are you writing?

    ///File is too large. What are you doing, downloading a car?
    pub const EFBIG: ::c_int = 27; //Okay, really, how?

    ///You don't have any (or at least enough) space left on the specified device. You might need a new hard drive.
    ///
    ///Might I suggest a SSD? They cost more but the performance gain is worth it
    pub const ENOSPC: ::c_int = 28; //I'm so sorry

    ///Illegal seek
    ///
    ///What the hell are you doing?
    pub const ESPIPE: ::c_int = 29;

    ///You're trying to write to a read-only file system.
    pub const EROFS: ::c_int = 30; //Haha, nice try

    ///Too many links exist
    pub const EMLINK: ::c_int = 31;

    ///Broken pipe
    pub const EPIPE: ::c_int = 32;

    ///Math argument is out of the function's domain
    ///
    ///??? I need more coffee to get this. Is it like trying to check if an int is NaN?
    pub const EDOM: ::c_int = 33;

    ///Math result could not be represented
    ///
    ///Stop trying to divide by ze--- ```EACCES```
    pub const ERANGE: ::c_int = 34;

}

pub use self::errno_base::*;

#[cfg(not(any(target_arch = "alpha", target_arch = "mips", target_arch = "parisc", target_arch = "sparc")))]
pub mod errno_common {

    ///Resource deadlock would occur
    pub const EDEADLK: ::c_int = 35;

    ///File name is too long. (Hah!)
    pub const ENAMETOOLONG: ::c_int = 36;

    ///No record locks available
    pub const ENOLCK: ::c_int = 37;

    ///Invalid system call number
    ///
    ///This is special. Arch syscall entry code returns -ENOSYS if
    ///users try to call a syscall that doesn't exist.
    pub const ENOSYS: ::c_int = 38;

    ///Directory is not empty.
    pub const ENOTEMPTY: ::c_int = 39;

    ///Too many symbolic links encountered. This is probably an infinite loop
    ///
    ///Alternatively, you broke your computer.
    pub const ELOOP: ::c_int = 40;

    ///Operation would block. You should try again?
    pub const EWOULDBLOCK: ::c_int = ::EAGAIN;

    ///No message of the desired type
    pub const ENOMSG: ::c_int = 42;

    ///Identifier was removed
    pub const EIDRM: ::c_int = 43;

    ///Channel number is out of acceptable range
    pub const ECHRNG: ::c_int = 44;

    ///Level 2 is not synchronized
    pub const EL2NSYNC: ::c_int = 45;

    ///Level 3 was halted
    pub const EL3HLT: ::c_int = 46;

    ///Level 3 was reset
    pub const EL3RST: ::c_int = 47;

    ///Link number is out of range
    ///
    ///How do you do this?
    pub const ELNRNG: ::c_int = 48;

    ///Protocol driver not attached
    pub const EUNATCH: ::c_int = 49;

    ///No CSI structure is available
    pub const ENOCSI: ::c_int = 50;

    ///Level 2 was halted
    pub const EL2HLT: ::c_int = 51;

    ///Invalid exchange
    pub const EBADE: ::c_int = 52;

    ///Invalid request descriptor
    pub const EBADR: ::c_int = 53;

    ///Exchange is full.
    ///
    ///I am so sorry
    pub const EXFULL: ::c_int = 54;

    ///No anode is available
    pub const ENOANO: ::c_int = 55;

    ///Invalid request code
    pub const EBADRQC: ::c_int = 56;

    ///Invalid slot
    pub const EBADSLT: ::c_int = 57;

    #[cfg(not(target_arch = "powerpc"))]
    ///A deadlock would occur, again
    pub const EDEADLOCK: ::c_int = EDEADLK;

    #[cfg(target_arch = "powerpc")]
    ///A deadlock would occur, again
    pub const EDEADLOCK: ::c_int = 58;

    ///Bad font file format
    pub const EBFONT: ::c_int = 59;

    ///Device is not a stream
    pub const ENOSTR: ::c_int = 60;

    ///No data is available
    pub const ENODATA: ::c_int = 61;

    ///Timer expired
    pub const ETIME: ::c_int = 62;

    ///Out of streams resources
    ///
    ///Should this be stream's? I'm not sure about the context. Is it the resources of the stream, or resources of the system's supply of streams?
    pub const ENOSR: ::c_int = 63;

    ///Requested machine was not on the network
    pub const ENONET: ::c_int = 64;

    ///Package is not installed
    pub const ENOPKG: ::c_int = 65;

    ///Object is remote when it is required to be local
    pub const EREMOTE: ::c_int = 66;

    ///Link has been severed
    pub const ENOLINK: ::c_int = 67;

    ///Error in advertising
    pub const EADV: ::c_int = 68;

    ///Srmount error
    pub const ESRMNT: ::c_int = 69;

    ///Communications error on send
    pub const ECOMM: ::c_int = 70;

    ///Protocol error
    pub const EPROTO: ::c_int = 71;

    ///A multihop was attempted
    pub const EMULTIHOP: ::c_int = 72;

    ///A RFS-specific error occurred
    pub const EDOTDOT: ::c_int = 73;

    ///Message is not a data message
    pub const EBADMASG: ::c_int = 74;

    ///Value is too large for the defined data type
    pub const EOVERFLOW: ::c_int = 75;

    ///Name is not unique on the network
    ///
    ///No, BILLY_TABLES, you can't have ten computers called '; DROP TABLE users' for "backup purposes"
    pub const ENOTUNIQ: ::c_int = 76;

    ///File descriptor is in a bad state
    ///
    ///Huh. I haven't seen this before
    pub const EBADFD: ::c_int = 77;

    ///The remote address changed.
    ///
    ///How does this happen? A change from wifi to 4g, etc?
    pub const EREMCHG: ::c_int = 78;

    ///Can not access a needed shared library
    ///
    ///Thankfully, with Cargo, this shouldn't happen :)
    pub const ELIBACC: ::c_int = 79;

    ///Attempted to access a shared library, only to find out it was corrupted
    ///
    ///WELL, FUCK.
    pub const ELIBBAD: ::c_int = 80;

    ///.lib section in a.out is corrupted
    pub const ELIBSCN: ::c_int = 81;

    ///Attempting to link in too many shared libraries
    ///
    ///Are... are you okay?
    pub const ELIBMAX: ::c_int = 82;

    ///Cannot exec a shared library directly
    pub const ELIBEXEC: ::c_int = 83;

    ///Illegal byte sequence
    ///
    ///I don't know what the hell you are doing, but you're probably doing it wrong
    pub const EILSEQ: ::c_int = 84;

    ///Interrupted system call, you should restart it
    ///
    ///Well, that's easy
    pub const ERESTART: ::c_int = 85;

    ///Streams pipe error
    pub const ESTRPIPE: ::c_int = 86;

    ///Too many users
    ///
    ///*Points finger and laughs*
    pub const EUSERS: ::c_int = 87;

    ///Socket operation attempted on an object that is not a socket
    pub const ENOTSOCK: ::c_int = 88;

    ///Destination address required
    pub const EDESTADDRREQ: ::c_int = 89;

    ///Message is too long
    pub const EMSGSIZE: ::c_int = 90;

    ///Protocol type is wrong for this socket
    pub const EPROTOTYPE: ::c_int = 91;

    ///Protocol is not available
    pub const ENOPROTOOPT: ::c_int = 92;

    ///Protocol is not supported
    pub const EPROTONOSUPPORT: ::c_int = 93;

    ///Socket type is not supported
    ///
    ///What?
    pub const ESOCKTNOSUPPORT: ::c_int = 94;

    ///Operation not supported on transport endpoint
    pub const EOPNOTSUPP: ::c_int = 95;

    ///Protocol family is not supported
    pub const EPFNOSUPPORT: ::c_int = 96;

    ///Address family is not supported by this protocol
    pub const EAFNOSUPPORT: ::c_int = 97;

    ///Address is already in use
    pub const EADDRINUSE: ::c_int = 98;

    ///Cannot assign the requested address
    pub const EADDRNOTAVAIL: ::c_int = 99;

    ///Network is down
    pub const ENETDOWN: ::c_int = 100;

    ///Network is unreachable :(
    pub const ENETUNREACH: ::c_int = 101;

    ///Network dropped connection because of a reset
    pub const ENETRESET: ::c_int = 102;

    ///Software caused the connection to abort
    pub const ECONNABORTED: ::c_int = 103;

    ///Connection was reset by a peer
    pub const ECONNRESET: ::c_int = 104;

    ///No buffer space is available
    pub const ENOBUFS: ::c_int = 105;

    ///Transport endpoint is already connected
    pub const EISCONN: ::c_int = 106;

    ///Transport endpoint is not connected
    pub const ENOTCONN: ::c_int = 107;

    ///Cannot send after the transport endpoint is shut down
    pub const ESHUTDOWN: ::c_int = 108;

    ///Too many references; Cannot splice
    pub const ETOOMANYREFS: ::c_int = 109;

    ///Connection timed out
    pub const ETIMEDOUT: ::c_int = 110;

    ///Connection was refused
    pub const ECONNREFUSED: ::c_int = 111;

    ///The host is down! D:
    pub const EHOSTDOWN: ::c_int = 112;

    ///There is no usable route to the host
    pub const EHOSTUNREACH: ::c_int = 113;

    ///Operation is already in progress. Be patient!
    pub const EALREADY: ::c_int = 114;

    ///Operation is in progress
    pub const EINPROGRESS: ::c_int = 115;

    ///The file handle is stale. Ew!
    pub const ESTALE: ::c_int = 116;

    ///The structure needs cleaning
    pub const EUCLEAN: ::c_int = 117;

    ///This is not a XENIX named type file
    pub const ENOTNAM: ::c_int = 118;

    ///No XENIX semaphores are available
    pub const ENAVAIL: ::c_int = 119;

    ///This is a named type file
    pub const EISNAM: ::c_int = 120;

    ///A remote I/O error occurred
    pub const EREMOTEIO: ::c_int = 121;

    ///You exceeded your quote
    pub const EDQUOT: ::c_int = 122;

    ///No medium was found
    pub const ENOMEDIUM: ::c_int = 123;

    ///You're using the wrong medium type
    pub const EMEDIUMTYPE: ::c_int = 124;

    ///The operation was cancelled
    pub const ECANCELED: ::c_int = 125;

    ///The required key is not available
    pub const ENOKEY: ::c_int = 126;

    ///The key you're using has expired
    pub const EKEYEXPIRED: ::c_int = 127;

    ///The key you're using has been revoked
    pub const EKEYREVOKED: ::c_int = 128;

    ///The key you're using was rejected by the service you're trying to access
    pub const EKEYREJECTED: ::c_int = 129;

    ///Your owner died.
    ///
    ///Dobby is a free computer!
    ///
    ///Just kidding. Your mutex's owner died. Dobby is still a slave
    pub const EOWNERDEAD: ::c_int = 130;

    ///The state of your mutex is not recoverable
    pub const ENOTRECOVERABLE: ::c_int = 131;

    ///Operation is not possible due to RF-kill
    pub const ERFKILL: ::c_int = 132;

    ///The memory page has a hardware error
    pub const EHWPOISON: ::c_int = 133;

}

#[cfg(not(any(target_arch = "alpha", target_arch = "mips", target_arch = "parisc", target_arch = "sparc")))]
pub use self::errno_common::*;<|endoftext|>


<commit_before>// Copyright 2018 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use core::num::NonZeroU32;
use core::convert::From;
use core::fmt;
#[cfg(not(target_env = "sgx"))]
use std::{io, error};

pub const UNKNOWN_ERROR: Error = Error(unsafe {
    NonZeroU32::new_unchecked(0x756e6b6e) // "unkn"
});

pub const UNAVAILABLE_ERROR: Error = Error(unsafe {
    NonZeroU32::new_unchecked(0x4e416e61) // "NAna"
});

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Error(NonZeroU32);

impl Error {
    pub fn code(&self) -> NonZeroU32 {
        self.0
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            UNKNOWN_ERROR => write!(f, "Getrandom Error: unknown"),
            UNAVAILABLE_ERROR => write!(f, "Getrandom Error: unavailable"),
            code => write!(f, "Getrandom Error: {}", code.0.get()),
        }
    }
}

#[cfg(not(target_env = "sgx"))]
impl From<io::Error> for Error {
    fn from(err: io::Error) -> Self {
        err.raw_os_error()
            .and_then(|code| NonZeroU32::new(code as u32))
            .map(|code| Error(code))
            // in practice this should never happen
            .unwrap_or(UNKNOWN_ERROR)
    }
}

#[cfg(not(target_env = "sgx"))]
impl Into<io::Error> for Error {
    fn into(self) -> io::Error {
        match self {
            UNKNOWN_ERROR => io::Error::new(io::ErrorKind::Other,
                "getrandom error: unknown"),
            UNAVAILABLE_ERROR => io::Error::new(io::ErrorKind::Other,
                "getrandom error: entropy source is unavailable"),
            code => io::Error::from_raw_os_error(code.0.get() as i32),
        }
    }
}

#[cfg(not(target_env = "sgx"))]
impl error::Error for Error { }
<commit_msg>Impl From not Into<commit_after>// Copyright 2018 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use core::num::NonZeroU32;
use core::convert::From;
use core::fmt;
#[cfg(not(target_env = "sgx"))]
use std::{io, error};

pub const UNKNOWN_ERROR: Error = Error(unsafe {
    NonZeroU32::new_unchecked(0x756e6b6e) // "unkn"
});

pub const UNAVAILABLE_ERROR: Error = Error(unsafe {
    NonZeroU32::new_unchecked(0x4e416e61) // "NAna"
});

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Error(NonZeroU32);

impl Error {
    pub fn code(&self) -> NonZeroU32 {
        self.0
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            UNKNOWN_ERROR => write!(f, "Getrandom Error: unknown"),
            UNAVAILABLE_ERROR => write!(f, "Getrandom Error: unavailable"),
            code => write!(f, "Getrandom Error: {}", code.0.get()),
        }
    }
}

#[cfg(not(target_env = "sgx"))]
impl From<io::Error> for Error {
    fn from(err: io::Error) -> Self {
        err.raw_os_error()
            .and_then(|code| NonZeroU32::new(code as u32))
            .map(|code| Error(code))
            // in practice this should never happen
            .unwrap_or(UNKNOWN_ERROR)
    }
}

#[cfg(not(target_env = "sgx"))]
impl From<Error> for io::Error {
    fn from(err: Error) -> Self {
        match err {
            UNKNOWN_ERROR => io::Error::new(io::ErrorKind::Other,
                "getrandom error: unknown"),
            UNAVAILABLE_ERROR => io::Error::new(io::ErrorKind::Other,
                "getrandom error: entropy source is unavailable"),
            code => io::Error::from_raw_os_error(code.0.get() as i32),
        }
    }
}

#[cfg(not(target_env = "sgx"))]
impl error::Error for Error { }
<|endoftext|>


<commit_before>extern crate hyper;
extern crate rustc_serialize;
extern crate rusqlite;
extern crate jmap;
extern crate time;

#[macro_use]
extern crate log;

mod logger;
mod db;
mod util;
mod record;

use std::default::Default;
use std::io::Write;

use hyper::server::{Request, Response};
use hyper::method::Method::Post;
use hyper::status::StatusCode;
use hyper::uri::RequestUri::AbsolutePath;
use hyper::header;

use rustc_serialize::json::{Json,ToJson};

use jmap::parse::FromJson;
use jmap::method::{RequestBatch, ResponseBatch, ResponseMethod};
use jmap::method::RequestMethod::*;
use jmap::method::ResponseMethod::*;

use util::RequestContext;
use record::RecordHandler;
use db::Db;

macro_rules! make_crud_method_dispatcher {
    ($method: expr, $rmethods: expr, $r: expr,
     $($ty: ty { $get: ident => $rget: ident, $set: ident => $rset: ident, $getup: ident => $rgetup: ident }),*) => {
        $rmethods = match $method {
            $(
                $get(args, id)
                    => vec!($r.get_records(&args).map(|a| $rget(a, id.clone())).unwrap_or_else(|e| ResponseError(e, id.clone()))),
                $set(args, id)
                    => vec!($r.set_records(&args).map(|a| $rset(a, id.clone())).unwrap_or_else(|e| ResponseError(e, id.clone()))),
                $getup(args, id) => $r.get_record_updates(&args).map(|a| {
                    match a {
                        (a, Some(b)) => vec!($rgetup(a, id.clone()), $rget(b, id.clone())),
                        (a, _)       => vec!($rgetup(a, id.clone())),
                    }
                }).unwrap_or_else(|e| vec!(ResponseError(e, id.clone()))),
            )*
            RequestError(args, id) => vec!(ResponseError(args, id)),
        };
    }
}

fn jmap_handler(batch: RequestBatch) -> ResponseBatch {
    let mut rbatch: ResponseBatch = ResponseBatch::default();

    let r = RequestContext {
        userid: 1, // XXX get userid from auth
        db: Db::open().unwrap(),
    };

    for method in batch.0.into_iter() {
        let rmethods: Vec<ResponseMethod>;
        make_crud_method_dispatcher!(method, rmethods, r,
            Calendar {
                GetCalendars       => Calendars,
                SetCalendars       => CalendarsSet,
                GetCalendarUpdates => CalendarUpdates
            },
            CalendarEvent {
                GetCalendarEvents       => CalendarEvents,
                SetCalendarEvents       => CalendarEventsSet,
                GetCalendarEventUpdates => CalendarEventUpdates
            },
            Contact {
                GetContacts       => Contacts,
                SetContacts       => ContactsSet,
                GetContactUpdates => ContactUpdates
            },
            ContactGroup {
                GetContactGroups       => ContactGroups,
                SetContactGroups       => ContactGroupsSet,
                GetContactGroupUpdates => ContactGroupUpdates
            },
            Mailbox {
                GetMailboxes      => Mailboxes,
                SetMailboxes      => MailboxesSet,
                GetMailboxUpdates => MailboxUpdates
            }
        );

        rbatch.0.extend(rmethods.into_iter());
    }

    rbatch
}

fn finish_response(mut res: Response, code: StatusCode, body: Option<&[u8]>) {
    *res.status_mut() = code;

    match res.start()
        .and_then(|mut res|
                  match body {
                      Some(ref b) => {
                          try!(res.write_all(b));
                          Ok(res)
                      }
                      None => {
                          Ok(res)
                      }
                  })
        .and_then(|res| res.end()) {
            Err(e) => error!("response error: {}", e),
            _      => (),
        };
}

fn http_handler(mut req: Request, mut res: Response) {
    res.headers_mut().set(header::Server("salada/0.0.1".to_string()));

    let uri = req.uri.clone();

    match uri {
        AbsolutePath(ref path) => match (&req.method, &path[..]) {

            (&Post, "/jmap") => {
                match Json::from_reader(&mut req) {
                    Ok(j) => match RequestBatch::from_json(&j) {
                        Ok(b) =>
                            finish_response(res, StatusCode::Ok, Some(jmap_handler(b).to_json().to_string().as_bytes())),
                        Err(e) =>
                            finish_response(res, StatusCode::BadRequest, Some(e.to_string().into_bytes().as_ref())),
                    },
                    Err(e) =>
                        finish_response(res, StatusCode::BadRequest, Some(e.to_string().into_bytes().as_ref())),
                }
            },

            (_, "/jmap") => finish_response(res, StatusCode::MethodNotAllowed, None),
            _            => finish_response(res, StatusCode::NotFound, None),
        },
        _ => finish_response(res, StatusCode::BadRequest, None),
    };
}

fn main() {
    logger::init().unwrap();

    let server = hyper::Server::http(http_handler);
    let _listen_guard = server.listen("127.0.0.1:3000").unwrap();
    info!("Listening on http://127.0.0.1:3000/jmap");
}
<commit_msg>Server header version bump<commit_after>extern crate hyper;
extern crate rustc_serialize;
extern crate rusqlite;
extern crate jmap;
extern crate time;

#[macro_use]
extern crate log;

mod logger;
mod db;
mod util;
mod record;

use std::default::Default;
use std::io::Write;

use hyper::server::{Request, Response};
use hyper::method::Method::Post;
use hyper::status::StatusCode;
use hyper::uri::RequestUri::AbsolutePath;
use hyper::header;

use rustc_serialize::json::{Json,ToJson};

use jmap::parse::FromJson;
use jmap::method::{RequestBatch, ResponseBatch, ResponseMethod};
use jmap::method::RequestMethod::*;
use jmap::method::ResponseMethod::*;

use util::RequestContext;
use record::RecordHandler;
use db::Db;

macro_rules! make_crud_method_dispatcher {
    ($method: expr, $rmethods: expr, $r: expr,
     $($ty: ty { $get: ident => $rget: ident, $set: ident => $rset: ident, $getup: ident => $rgetup: ident }),*) => {
        $rmethods = match $method {
            $(
                $get(args, id)
                    => vec!($r.get_records(&args).map(|a| $rget(a, id.clone())).unwrap_or_else(|e| ResponseError(e, id.clone()))),
                $set(args, id)
                    => vec!($r.set_records(&args).map(|a| $rset(a, id.clone())).unwrap_or_else(|e| ResponseError(e, id.clone()))),
                $getup(args, id) => $r.get_record_updates(&args).map(|a| {
                    match a {
                        (a, Some(b)) => vec!($rgetup(a, id.clone()), $rget(b, id.clone())),
                        (a, _)       => vec!($rgetup(a, id.clone())),
                    }
                }).unwrap_or_else(|e| vec!(ResponseError(e, id.clone()))),
            )*
            RequestError(args, id) => vec!(ResponseError(args, id)),
        };
    }
}

fn jmap_handler(batch: RequestBatch) -> ResponseBatch {
    let mut rbatch: ResponseBatch = ResponseBatch::default();

    let r = RequestContext {
        userid: 1, // XXX get userid from auth
        db: Db::open().unwrap(),
    };

    for method in batch.0.into_iter() {
        let rmethods: Vec<ResponseMethod>;
        make_crud_method_dispatcher!(method, rmethods, r,
            Calendar {
                GetCalendars       => Calendars,
                SetCalendars       => CalendarsSet,
                GetCalendarUpdates => CalendarUpdates
            },
            CalendarEvent {
                GetCalendarEvents       => CalendarEvents,
                SetCalendarEvents       => CalendarEventsSet,
                GetCalendarEventUpdates => CalendarEventUpdates
            },
            Contact {
                GetContacts       => Contacts,
                SetContacts       => ContactsSet,
                GetContactUpdates => ContactUpdates
            },
            ContactGroup {
                GetContactGroups       => ContactGroups,
                SetContactGroups       => ContactGroupsSet,
                GetContactGroupUpdates => ContactGroupUpdates
            },
            Mailbox {
                GetMailboxes      => Mailboxes,
                SetMailboxes      => MailboxesSet,
                GetMailboxUpdates => MailboxUpdates
            }
        );

        rbatch.0.extend(rmethods.into_iter());
    }

    rbatch
}

fn finish_response(mut res: Response, code: StatusCode, body: Option<&[u8]>) {
    *res.status_mut() = code;

    match res.start()
        .and_then(|mut res|
                  match body {
                      Some(ref b) => {
                          try!(res.write_all(b));
                          Ok(res)
                      }
                      None => {
                          Ok(res)
                      }
                  })
        .and_then(|res| res.end()) {
            Err(e) => error!("response error: {}", e),
            _      => (),
        };
}

fn http_handler(mut req: Request, mut res: Response) {
    res.headers_mut().set(header::Server("salada/0.0.3".to_string()));

    let uri = req.uri.clone();

    match uri {
        AbsolutePath(ref path) => match (&req.method, &path[..]) {

            (&Post, "/jmap") => {
                match Json::from_reader(&mut req) {
                    Ok(j) => match RequestBatch::from_json(&j) {
                        Ok(b) =>
                            finish_response(res, StatusCode::Ok, Some(jmap_handler(b).to_json().to_string().as_bytes())),
                        Err(e) =>
                            finish_response(res, StatusCode::BadRequest, Some(e.to_string().into_bytes().as_ref())),
                    },
                    Err(e) =>
                        finish_response(res, StatusCode::BadRequest, Some(e.to_string().into_bytes().as_ref())),
                }
            },

            (_, "/jmap") => finish_response(res, StatusCode::MethodNotAllowed, None),
            _            => finish_response(res, StatusCode::NotFound, None),
        },
        _ => finish_response(res, StatusCode::BadRequest, None),
    };
}

fn main() {
    logger::init().unwrap();

    let server = hyper::Server::http(http_handler);
    let _listen_guard = server.listen("127.0.0.1:3000").unwrap();
    info!("Listening on http://127.0.0.1:3000/jmap");
}
<|endoftext|>


<commit_before>pub use self::download::download_document;
pub use self::search::search_documents;
pub use self::upload::upload_document;

mod download {
    use utils::console::*;

    use hyper::Client;
    use hyper::client::Response;
    use hyper::header::{ContentType, ContentDisposition, ContentLength, DispositionParam, Authorization, Bearer};
    use hyper::net::HttpsConnector;
    use hyper_native_tls::NativeTlsClient;
    use std::fs::File;
    use std::io;
    use std::io::{Read, Write};
    use std::str;

    error_chain! {
        errors {
            HttpDownloadCallFailed {
                description("failed to make http download call")
                display("failed to make http download call")
            }

            FailedSetFilename {
                description("failed set filename from cli parameter and content disposition header")
                display("failed set filename from cli parameter and content disposition header")
            }

            FailedContentLength {
                description("failed get content length from response header")
                display("failed get content length from response header")
            }
        }
    }

    pub fn download_document(
        access_token: &str,
        filename: Option<&str>,
        document_id: &str) -> Result<()> {
        do_download_document(access_token, filename, document_id)
            .chain_err(|| ErrorKind::HttpDownloadCallFailed)
    }

    fn do_download_document(
        access_token: &str,
        filename: Option<&str>,
        document_id: &str) -> Result<()> {
        let ssl = NativeTlsClient::new().chain_err(|| "Failed to create TLS client")?;
        let connector = HttpsConnector::new(ssl);
        let client = Client::with_connector(connector);

        let url = format!("https://api.centerdevice.de/v2/document/{}", document_id);
        let request = client.get(&url)
            .header(Authorization(Bearer { token: access_token.to_string() }))
            .header(ContentType(mime!(Star/Star)));

        let mut response = request.send().chain_err(|| "Failed to finish http request")?;

        let filename = get_filename(filename, &response)?;
        let size = get_content_length(&response)? as usize;

        verbose(format!("Retrieving {} bytes ", size));
        let w_size = write_to_file(&filename, &mut response)?;
        verboseln("done.");

        if w_size != size {
            bail!("Retrieved number of bytes ({}) does not match expected bytes ({}).", w_size, size);
        }

        Ok(())
    }

    fn get_filename(filename: Option<&str>, response: &Response) -> Result<String> {
        let filename = if let Some(_filename) = filename {
            _filename
        } else {
            let mut _filename = None;
            let content_disposition: &ContentDisposition = response.headers.get()
                .ok_or(ErrorKind::FailedSetFilename)?;
            for cp in &content_disposition.parameters {
                if let DispositionParam::Filename(_, _, ref f) = *cp {
                    _filename = Some(
                        str::from_utf8(f).chain_err(|| ErrorKind::FailedSetFilename)?);
                    break;
                }
            }
            _filename.ok_or(ErrorKind::FailedSetFilename)?
        };

        Ok(filename.to_string())
    }

    fn get_content_length(response: &Response) -> Result<u64> {
        let content_length: &ContentLength = response.headers.get()
            .ok_or(ErrorKind::FailedContentLength)?;
        let &ContentLength(size) = content_length;
        Ok(size)
    }

    fn write_to_file(filename: &str, response: &mut Response) -> Result<usize> {
        let mut out = File::create(filename).chain_err(|| "Failed to create destination file")?;

        let mut buf = [0; 128 * 1024];
        let mut written: usize = 0;
        let mut mega_bytes: usize = 0;
        loop {
            let len = match response.read(&mut buf) {
                Ok(0) => break,  // EOF.
                Ok(len) => len,
                Err(ref err) if err.kind() == io::ErrorKind::Interrupted => continue,
                Err(_) => bail!("Could not read from server response")
            };
            written += len;
            if (written / (1024 * 1024)) - mega_bytes > 0 {
                mega_bytes += 1;
                verbose(".");
            }
            out.write_all(&buf[..len]).chain_err(|| "Could not write to file")?;
        }

        Ok(written)
    }
}

mod search {
    use utils::console::*;

    use hyper::Client;
    use hyper::header::{ContentType, Authorization, Bearer, Accept, qitem};
    use hyper::net::HttpsConnector;
    use hyper_native_tls::NativeTlsClient;
    use serde_json;
    use std::io::Read;
    use std::str;

    error_chain! {
        errors {
            HttpSearchCallFailed {
                description("failed to make http search call")
                display("failed to make http search call")
            }
        }
    }

    #[derive(Serialize, Debug)]
    struct Search<'a> {
        action: &'a str,
        params: Params<'a>,
    }

    #[derive(Serialize, Debug)]
    struct Params<'a> {
        query: Query<'a>,
        filter: Filter<'a>,
    }

    #[derive(Serialize, Debug)]
    struct Query<'a> {
        #[serde(skip_serializing_if = "Option::is_none")] text: Option<&'a str>,
    }

    #[derive(Serialize, Debug)]
    struct Filter<'a> {
        #[serde(skip_serializing_if = "Option::is_none")] filenames: Option<Vec<&'a str>>,
        #[serde(skip_serializing_if = "Option::is_none")] tags: Option<Vec<&'a str>>,
    }

    impl<'a> Search<'a> {
        pub fn new(filenames: Option<Vec<&'a str>>, tags: Option<Vec<&'a str>>, fulltext: Option<&'a str>) -> Self {
            let filter = Filter { filenames: filenames, tags: tags };
            let query = Query { text: fulltext };
            let params = Params { query: query, filter: filter };

            Search { action: "search", params: params }
        }
    }

    pub fn search_documents(
        access_token: &str,
        filenames: Option<Vec<&str>>,
        tags: Option<Vec<&str>>,
        fulltext: Option<&str>) -> Result<String> {
        do_search_documents(access_token, filenames, tags, fulltext)
            .chain_err(|| ErrorKind::HttpSearchCallFailed)
    }

    fn do_search_documents(
        access_token: &str,
        filenames: Option<Vec<&str>>,
        tags: Option<Vec<&str>>,
        fulltext: Option<&str>) -> Result<String> {
        let search = Search::new(filenames, tags, fulltext);
        let search_json = serde_json::to_string(&search).chain_err(|| "JSON serialization failed")?;

        verboseln(format!("search = '{:?}'", search_json));

        let ssl = NativeTlsClient::new().chain_err(|| "Failed to create TLS client")?;
        let connector = HttpsConnector::new(ssl);
        let client = Client::with_connector(connector);

        let request = client.post("https://api.centerdevice.de/v2/documents")
            .header(Authorization(Bearer { token: access_token.to_string() }))
            .header(ContentType(mime!(Application / Json)))
            .header(Accept(vec![qitem(mime!(Application/ Json; Charset = Utf8))]))
            .body(&search_json);

        let mut response = request.send().chain_err(|| "Failed to finish http request")?;

        let mut body = Vec::new();
        response.read_to_end(&mut body).chain_err(|| "Failed to read server response")?;
        let response_body = String::from_utf8_lossy(&body).to_string();

        Ok(response_body)
    }
}

mod upload {
    use utils::console::*;

    use crypto::digest::Digest;
    use crypto::sha2::Sha256;
    use hyper::client::Request;
    use hyper::method::Method;
    use hyper::header::{Headers, ContentDisposition, DispositionParam, DispositionType, ContentType,
                        Authorization, Bearer, Accept, qitem};
    use hyper::net::HttpsConnector;
    use hyper_native_tls::NativeTlsClient;
    use mime::Mime;
    use mime_multipart::{Node, Part, FilePart, write_multipart};
    use serde_json;
    use std::fs;
    use std::io::Read;
    use std::path::Path;
    use std::str;

    error_chain! {
        errors {
            HttpUploadCallFailed {
                description("failed to make http upload call")
                display("failed to make http upload call")
            }
        }
    }

    #[derive(Serialize, Debug)]
    struct DocumentMetadata<'a> {
        metadata: Metadata<'a>,
    }

    #[derive(Serialize, Debug)]
    struct Metadata<'a> {
        document: Document<'a>,
        #[serde(skip_serializing_if = "Option::is_none")] actions: Option<Actions<'a>>,
    }

    #[derive(Serialize, Debug)]
    struct Document<'a> {
        filename: &'a str,
        size: u64,
        #[serde(skip_serializing_if = "Option::is_none")] title: Option<&'a str>,
        #[serde(skip_serializing_if = "Option::is_none")] author: Option<&'a str>,
    }

    #[derive(Serialize, Debug)]
    struct Actions<'a> {
        #[serde(skip_serializing_if = "Option::is_none", rename(serialize = "add-tag"))] tags: Option<Vec<&'a str>>
    }

    impl<'a> DocumentMetadata<'a> {
        pub fn new(filename: &'a str, size: u64, title: Option<&'a str>, tags: Option<Vec<&'a str>>) -> Self {
            let document = Document { filename: filename, size: size, title: title, author: None };
            let actions = Actions { tags: tags };
            let metadata = Metadata { document: document, actions: Some(actions) };
            DocumentMetadata { metadata: metadata }
        }
    }

    pub fn upload_document(
        access_token: &str,
        file: &Path,
        filename: &str,
        mime: Mime,
        title: Option<&str>,
        tags: Option<Vec<&str>>)
        -> Result<String> {
        do_upload_document(access_token, file, filename, mime, title, tags)
            .chain_err(|| ErrorKind::HttpUploadCallFailed)
    }

    fn do_upload_document(
        access_token: &str,
        file: &Path,
        filename: &str,
        mime: Mime,
        title: Option<&str>,
        tags: Option<Vec<&str>>) -> Result<String> {
        let doc_metadata_json_bytes = create_doc_metadata(file, filename, title, tags)?.into_bytes();
        let boundary = generate_boundary(&doc_metadata_json_bytes);
        let boundary_bytes = boundary.clone().into_bytes();
        let nodes = create_multipart_nodes(
            doc_metadata_json_bytes, filename.to_string(), file, mime).chain_err(|| "Failed to create form-data")?;

        let ssl = NativeTlsClient::new().chain_err(|| "Failed to create TLS client")?;
        let connector = HttpsConnector::new(ssl);
        let url = ::hyper::Url::parse("https://api.centerdevice.de/v2/documents").chain_err(|| "Failed to parse URL")?;
        let mut client = Request::with_connector(Method::Post, url, &connector).chain_err(|| "Failed to create client")?;
        client.headers_mut().set(Authorization(Bearer { token: access_token.to_string() }));
        client.headers_mut().set(ContentType(mime!(Multipart / FormData; Boundary = (boundary))));
        client.headers_mut().set(Accept(vec![qitem(mime!(Application / Json; Charset = Utf8))]));

        let mut request = client.start().chain_err(|| "Failed to start HTTP connection")?;
        write_multipart(&mut request, &boundary_bytes, &nodes).chain_err(|| "Failed to send multipart form-data")?;
        let mut response = request.send().chain_err(|| "Failed to finish http request")?;

        let mut body = Vec::new();
        response.read_to_end(&mut body).chain_err(|| "Failed to read server response")?;
        let response_body = String::from_utf8_lossy(&body).to_string();

        Ok(response_body)
    }

    fn create_doc_metadata(file: &Path, filename: &str, title: Option<&str>, tags: Option<Vec<&str>>) -> Result<String> {
        let size = fs::metadata(file).chain_err(|| "Failed to get metadata for file")?.len();
        let doc_metadata = DocumentMetadata::new(filename, size, title, tags);
        let doc_metadata_json = serde_json::to_string(&doc_metadata).chain_err(|| "JSON serialization failed")?;

        verboseln(format!("document metadata = '{:?}'", doc_metadata_json));

        Ok(doc_metadata_json)
    }

    fn create_multipart_nodes(json_bytes: Vec<u8>, filename: String, file: &Path, mime: Mime) -> Result<Vec<Node>> {
        let mut nodes: Vec<Node> = Vec::with_capacity(2);

        let mut h = Headers::new();
        h.set(ContentType(mime!(Application / Json)));
        h.set(ContentDisposition {
            disposition: DispositionType::Ext("form-data".to_string()),
            parameters: vec![DispositionParam::Ext("name".to_string(), "metadata".to_string())],
        });
        nodes.push(Node::Part(Part {
            headers: h,
            body: json_bytes
        }));

        let mut h = Headers::new();
        h.set(ContentType(mime));
        h.set(ContentDisposition {
            disposition: DispositionType::Ext("form-data".to_string()),
            parameters: vec![DispositionParam::Ext("name".to_string(), "document".to_string()),
                             DispositionParam::Ext("filename".to_string(), filename)],
        });
        nodes.push(Node::File(FilePart::new(h, file)));

        Ok(nodes)
    }

    // CenterDevice / Jersey does not accept special characters in boundary; thus, we build it ourselves.
    fn generate_boundary(seed: &[u8]) -> String {
        let mut sha = Sha256::new();
        sha.input(seed);
        let output = format!("Boundary_{}", sha.result_str());

        output
    }
}<commit_msg>Add public collections to search<commit_after>pub use self::download::download_document;
pub use self::search::search_documents;
pub use self::upload::upload_document;

mod download {
    use utils::console::*;

    use hyper::Client;
    use hyper::client::Response;
    use hyper::header::{ContentType, ContentDisposition, ContentLength, DispositionParam, Authorization, Bearer};
    use hyper::net::HttpsConnector;
    use hyper_native_tls::NativeTlsClient;
    use std::fs::File;
    use std::io;
    use std::io::{Read, Write};
    use std::str;

    error_chain! {
        errors {
            HttpDownloadCallFailed {
                description("failed to make http download call")
                display("failed to make http download call")
            }

            FailedSetFilename {
                description("failed set filename from cli parameter and content disposition header")
                display("failed set filename from cli parameter and content disposition header")
            }

            FailedContentLength {
                description("failed get content length from response header")
                display("failed get content length from response header")
            }
        }
    }

    pub fn download_document(
        access_token: &str,
        filename: Option<&str>,
        document_id: &str) -> Result<()> {
        do_download_document(access_token, filename, document_id)
            .chain_err(|| ErrorKind::HttpDownloadCallFailed)
    }

    fn do_download_document(
        access_token: &str,
        filename: Option<&str>,
        document_id: &str) -> Result<()> {
        let ssl = NativeTlsClient::new().chain_err(|| "Failed to create TLS client")?;
        let connector = HttpsConnector::new(ssl);
        let client = Client::with_connector(connector);

        let url = format!("https://api.centerdevice.de/v2/document/{}", document_id);
        let request = client.get(&url)
            .header(Authorization(Bearer { token: access_token.to_string() }))
            .header(ContentType(mime!(Star/Star)));

        let mut response = request.send().chain_err(|| "Failed to finish http request")?;

        let filename = get_filename(filename, &response)?;
        let size = get_content_length(&response)? as usize;

        verbose(format!("Retrieving {} bytes ", size));
        let w_size = write_to_file(&filename, &mut response)?;
        verboseln("done.");

        if w_size != size {
            bail!("Retrieved number of bytes ({}) does not match expected bytes ({}).", w_size, size);
        }

        Ok(())
    }

    fn get_filename(filename: Option<&str>, response: &Response) -> Result<String> {
        let filename = if let Some(_filename) = filename {
            _filename
        } else {
            let mut _filename = None;
            let content_disposition: &ContentDisposition = response.headers.get()
                .ok_or(ErrorKind::FailedSetFilename)?;
            for cp in &content_disposition.parameters {
                if let DispositionParam::Filename(_, _, ref f) = *cp {
                    _filename = Some(
                        str::from_utf8(f).chain_err(|| ErrorKind::FailedSetFilename)?);
                    break;
                }
            }
            _filename.ok_or(ErrorKind::FailedSetFilename)?
        };

        Ok(filename.to_string())
    }

    fn get_content_length(response: &Response) -> Result<u64> {
        let content_length: &ContentLength = response.headers.get()
            .ok_or(ErrorKind::FailedContentLength)?;
        let &ContentLength(size) = content_length;
        Ok(size)
    }

    fn write_to_file(filename: &str, response: &mut Response) -> Result<usize> {
        let mut out = File::create(filename).chain_err(|| "Failed to create destination file")?;

        let mut buf = [0; 128 * 1024];
        let mut written: usize = 0;
        let mut mega_bytes: usize = 0;
        loop {
            let len = match response.read(&mut buf) {
                Ok(0) => break,  // EOF.
                Ok(len) => len,
                Err(ref err) if err.kind() == io::ErrorKind::Interrupted => continue,
                Err(_) => bail!("Could not read from server response")
            };
            written += len;
            if (written / (1024 * 1024)) - mega_bytes > 0 {
                mega_bytes += 1;
                verbose(".");
            }
            out.write_all(&buf[..len]).chain_err(|| "Could not write to file")?;
        }

        Ok(written)
    }
}

mod search {
    use utils::console::*;

    use hyper::Client;
    use hyper::header::{ContentType, Authorization, Bearer, Accept, qitem};
    use hyper::net::HttpsConnector;
    use hyper_native_tls::NativeTlsClient;
    use serde::Serialize;
    use serde_json;
    use std::io::Read;
    use std::str;

    error_chain! {
        errors {
            HttpSearchCallFailed {
                description("failed to make http search call")
                display("failed to make http search call")
            }
        }
    }

    #[derive(Serialize, Debug)]
    struct Search<'a> {
        action: &'a str,
        params: Params<'a>,
    }

    #[derive(Serialize, Debug)]
    struct Params<'a> {
        query: Query<'a>,
        filter: Filter<'a>,
        #[serde(skip_serializing_if = "Vec::is_empty")] named: Vec<Named<'a>>,
    }

    #[derive(Serialize, Debug)]
    struct Query<'a> {
        #[serde(skip_serializing_if = "Option::is_none")] text: Option<&'a str>,
    }

    #[derive(Serialize, Debug)]
    struct Filter<'a> {
        #[serde(skip_serializing_if = "Option::is_none")] filenames: Option<Vec<&'a str>>,
        #[serde(skip_serializing_if = "Option::is_none")] tags: Option<Vec<&'a str>>,
    }

    #[derive(Serialize, Debug)]
    struct Named<'a> {
        name: &'a str,
        params: Include,
    }

    #[derive(Serialize, Debug)]
    struct Include {
        include: bool
    }

    impl<'a> Search<'a> {
        pub fn new(filenames: Option<Vec<&'a str>>, tags: Option<Vec<&'a str>>, fulltext: Option<&'a str>) -> Self {
            let filter = Filter { filenames: filenames, tags: tags };
            let query = Query { text: fulltext };
            let includes = Include{ include: true };
            let named = vec![Named { name: "public-collections", params: includes }];
            let params = Params { query: query, filter: filter, named: named};

            Search { action: "search", params: params }
        }
    }

    pub fn search_documents(
        access_token: &str,
        filenames: Option<Vec<&str>>,
        tags: Option<Vec<&str>>,
        fulltext: Option<&str>) -> Result<String> {
        do_search_documents(access_token, filenames, tags, fulltext)
            .chain_err(|| ErrorKind::HttpSearchCallFailed)
    }

    fn do_search_documents(
        access_token: &str,
        filenames: Option<Vec<&str>>,
        tags: Option<Vec<&str>>,
        fulltext: Option<&str>) -> Result<String> {
        let search = Search::new(filenames, tags, fulltext);
        let search_json = serde_json::to_string(&search).chain_err(|| "JSON serialization failed")?;

        verboseln(format!("search = '{:?}'", search_json));

        let ssl = NativeTlsClient::new().chain_err(|| "Failed to create TLS client")?;
        let connector = HttpsConnector::new(ssl);
        let client = Client::with_connector(connector);

        let request = client.post("https://api.centerdevice.de/v2/documents")
            .header(Authorization(Bearer { token: access_token.to_string() }))
            .header(ContentType(mime!(Application / Json)))
            .header(Accept(vec![qitem(mime!(Application/ Json; Charset = Utf8))]))
            .body(&search_json);

        let mut response = request.send().chain_err(|| "Failed to finish http request")?;

        let mut body = Vec::new();
        response.read_to_end(&mut body).chain_err(|| "Failed to read server response")?;
        let response_body = String::from_utf8_lossy(&body).to_string();

        Ok(response_body)
    }
}

mod upload {
    use utils::console::*;

    use crypto::digest::Digest;
    use crypto::sha2::Sha256;
    use hyper::client::Request;
    use hyper::method::Method;
    use hyper::header::{Headers, ContentDisposition, DispositionParam, DispositionType, ContentType,
                        Authorization, Bearer, Accept, qitem};
    use hyper::net::HttpsConnector;
    use hyper_native_tls::NativeTlsClient;
    use mime::Mime;
    use mime_multipart::{Node, Part, FilePart, write_multipart};
    use serde_json;
    use std::fs;
    use std::io::Read;
    use std::path::Path;
    use std::str;

    error_chain! {
        errors {
            HttpUploadCallFailed {
                description("failed to make http upload call")
                display("failed to make http upload call")
            }
        }
    }

    #[derive(Serialize, Debug)]
    struct DocumentMetadata<'a> {
        metadata: Metadata<'a>,
    }

    #[derive(Serialize, Debug)]
    struct Metadata<'a> {
        document: Document<'a>,
        #[serde(skip_serializing_if = "Option::is_none")] actions: Option<Actions<'a>>,
    }

    #[derive(Serialize, Debug)]
    struct Document<'a> {
        filename: &'a str,
        size: u64,
        #[serde(skip_serializing_if = "Option::is_none")] title: Option<&'a str>,
        #[serde(skip_serializing_if = "Option::is_none")] author: Option<&'a str>,
    }

    #[derive(Serialize, Debug)]
    struct Actions<'a> {
        #[serde(skip_serializing_if = "Option::is_none", rename(serialize = "add-tag"))] tags: Option<Vec<&'a str>>
    }

    impl<'a> DocumentMetadata<'a> {
        pub fn new(filename: &'a str, size: u64, title: Option<&'a str>, tags: Option<Vec<&'a str>>) -> Self {
            let document = Document { filename: filename, size: size, title: title, author: None };
            let actions = Actions { tags: tags };
            let metadata = Metadata { document: document, actions: Some(actions) };
            DocumentMetadata { metadata: metadata }
        }
    }

    pub fn upload_document(
        access_token: &str,
        file: &Path,
        filename: &str,
        mime: Mime,
        title: Option<&str>,
        tags: Option<Vec<&str>>)
        -> Result<String> {
        do_upload_document(access_token, file, filename, mime, title, tags)
            .chain_err(|| ErrorKind::HttpUploadCallFailed)
    }

    fn do_upload_document(
        access_token: &str,
        file: &Path,
        filename: &str,
        mime: Mime,
        title: Option<&str>,
        tags: Option<Vec<&str>>) -> Result<String> {
        let doc_metadata_json_bytes = create_doc_metadata(file, filename, title, tags)?.into_bytes();
        let boundary = generate_boundary(&doc_metadata_json_bytes);
        let boundary_bytes = boundary.clone().into_bytes();
        let nodes = create_multipart_nodes(
            doc_metadata_json_bytes, filename.to_string(), file, mime).chain_err(|| "Failed to create form-data")?;

        let ssl = NativeTlsClient::new().chain_err(|| "Failed to create TLS client")?;
        let connector = HttpsConnector::new(ssl);
        let url = ::hyper::Url::parse("https://api.centerdevice.de/v2/documents").chain_err(|| "Failed to parse URL")?;
        let mut client = Request::with_connector(Method::Post, url, &connector).chain_err(|| "Failed to create client")?;
        client.headers_mut().set(Authorization(Bearer { token: access_token.to_string() }));
        client.headers_mut().set(ContentType(mime!(Multipart / FormData; Boundary = (boundary))));
        client.headers_mut().set(Accept(vec![qitem(mime!(Application / Json; Charset = Utf8))]));

        let mut request = client.start().chain_err(|| "Failed to start HTTP connection")?;
        write_multipart(&mut request, &boundary_bytes, &nodes).chain_err(|| "Failed to send multipart form-data")?;
        let mut response = request.send().chain_err(|| "Failed to finish http request")?;

        let mut body = Vec::new();
        response.read_to_end(&mut body).chain_err(|| "Failed to read server response")?;
        let response_body = String::from_utf8_lossy(&body).to_string();

        Ok(response_body)
    }

    fn create_doc_metadata(file: &Path, filename: &str, title: Option<&str>, tags: Option<Vec<&str>>) -> Result<String> {
        let size = fs::metadata(file).chain_err(|| "Failed to get metadata for file")?.len();
        let doc_metadata = DocumentMetadata::new(filename, size, title, tags);
        let doc_metadata_json = serde_json::to_string(&doc_metadata).chain_err(|| "JSON serialization failed")?;

        verboseln(format!("document metadata = '{:?}'", doc_metadata_json));

        Ok(doc_metadata_json)
    }

    fn create_multipart_nodes(json_bytes: Vec<u8>, filename: String, file: &Path, mime: Mime) -> Result<Vec<Node>> {
        let mut nodes: Vec<Node> = Vec::with_capacity(2);

        let mut h = Headers::new();
        h.set(ContentType(mime!(Application / Json)));
        h.set(ContentDisposition {
            disposition: DispositionType::Ext("form-data".to_string()),
            parameters: vec![DispositionParam::Ext("name".to_string(), "metadata".to_string())],
        });
        nodes.push(Node::Part(Part {
            headers: h,
            body: json_bytes
        }));

        let mut h = Headers::new();
        h.set(ContentType(mime));
        h.set(ContentDisposition {
            disposition: DispositionType::Ext("form-data".to_string()),
            parameters: vec![DispositionParam::Ext("name".to_string(), "document".to_string()),
                             DispositionParam::Ext("filename".to_string(), filename)],
        });
        nodes.push(Node::File(FilePart::new(h, file)));

        Ok(nodes)
    }

    // CenterDevice / Jersey does not accept special characters in boundary; thus, we build it ourselves.
    fn generate_boundary(seed: &[u8]) -> String {
        let mut sha = Sha256::new();
        sha.input(seed);
        let output = format!("Boundary_{}", sha.result_str());

        output
    }
}<|endoftext|>


<commit_before>//! Asynchronous DNS resolver

use cfg_if::cfg_if;
use log::trace;
use trust_dns_resolver::{
    config::{LookupIpStrategy, ResolverConfig, ResolverOpts},
    error::ResolveResult,
    TokioAsyncResolver,
};

/// Create a `trust-dns` asynchronous DNS resolver
pub async fn create_resolver(dns: Option<ResolverConfig>, _ipv6_first: bool) -> ResolveResult<TokioAsyncResolver> {
    // Customized dns resolution
    match dns {
        Some(conf) => {
            let mut resolver_opts = ResolverOpts::default();

            // Use Ipv4AndIpv6 strategy. Because Ipv4ThenIpv6 or Ipv6ThenIpv4 will return if the first query returned.
            // Since we want to use Happy Eyeballs to connnect to both IPv4 and IPv6 addresses, we need both A and AAAA records.
            resolver_opts.ip_strategy = LookupIpStrategy::Ipv4AndIpv6;

            trace!(
                "initializing DNS resolver with config {:?} opts {:?}",
                conf,
                resolver_opts
            );
            TokioAsyncResolver::tokio(conf, resolver_opts)
        }

        // To make this independent, if targeting macOS, BSD, Linux, or Windows, we can use the system's configuration
        // Android doesn't have /etc/resolv.conf.
        None => {
            cfg_if! {
                if #[cfg(any(all(unix, not(target_os = "android")), windows))] {
                    use trust_dns_resolver::{name_server::TokioHandle, system_conf::read_system_conf};

                    // use the system resolver configuration
                    let (config, mut opts) = match read_system_conf() {
                        Ok(o) => o,
                        Err(err) => {
                            use log::error;

                            error!("failed to initialize DNS resolver with system-config, error: {}", err);

                            // From::from is required because on error type is different on Windows
                            #[allow(clippy::useless_conversion)]
                            return Err(From::from(err));
                        }
                    };

                    // NOTE: timeout will be set by config (for example, /etc/resolv.conf on UNIX-like system)
                    //
                    // Only ip_strategy should be changed. Why Ipv4AndIpv6? See comments above.
                    opts.ip_strategy = LookupIpStrategy::Ipv4AndIpv6;

                    trace!(
                        "initializing DNS resolver with system-config {:?} opts {:?}",
                        config,
                        opts
                    );

                    TokioAsyncResolver::new(config, opts, TokioHandle)
                } else {
                    use trust_dns_resolver::error::ResolveError;

                    Err(ResolveError::from("current platform doesn't support trust-dns resolver with system configured".to_owned()))
                }
            }
        }
    }
}
<commit_msg>make clippy happy, ResolverOpts initlalize with Default::default()<commit_after>//! Asynchronous DNS resolver

use cfg_if::cfg_if;
use log::trace;
use trust_dns_resolver::{
    config::{LookupIpStrategy, ResolverConfig, ResolverOpts},
    error::ResolveResult,
    TokioAsyncResolver,
};

/// Create a `trust-dns` asynchronous DNS resolver
pub async fn create_resolver(dns: Option<ResolverConfig>, _ipv6_first: bool) -> ResolveResult<TokioAsyncResolver> {
    // Customized dns resolution
    match dns {
        Some(conf) => {
            let resolver_opts = ResolverOpts {
                // Use Ipv4AndIpv6 strategy. Because Ipv4ThenIpv6 or Ipv6ThenIpv4 will return if the first query returned.
                // Since we want to use Happy Eyeballs to connnect to both IPv4 and IPv6 addresses, we need both A and AAAA records.
                ip_strategy: LookupIpStrategy::Ipv4AndIpv6,
                ..ResolverOpts::default()
            };

            trace!(
                "initializing DNS resolver with config {:?} opts {:?}",
                conf,
                resolver_opts
            );
            TokioAsyncResolver::tokio(conf, resolver_opts)
        }

        // To make this independent, if targeting macOS, BSD, Linux, or Windows, we can use the system's configuration
        // Android doesn't have /etc/resolv.conf.
        None => {
            cfg_if! {
                if #[cfg(any(all(unix, not(target_os = "android")), windows))] {
                    use trust_dns_resolver::{name_server::TokioHandle, system_conf::read_system_conf};

                    // use the system resolver configuration
                    let (config, mut opts) = match read_system_conf() {
                        Ok(o) => o,
                        Err(err) => {
                            use log::error;

                            error!("failed to initialize DNS resolver with system-config, error: {}", err);

                            // From::from is required because on error type is different on Windows
                            #[allow(clippy::useless_conversion)]
                            return Err(From::from(err));
                        }
                    };

                    // NOTE: timeout will be set by config (for example, /etc/resolv.conf on UNIX-like system)
                    //
                    // Only ip_strategy should be changed. Why Ipv4AndIpv6? See comments above.
                    opts.ip_strategy = LookupIpStrategy::Ipv4AndIpv6;

                    trace!(
                        "initializing DNS resolver with system-config {:?} opts {:?}",
                        config,
                        opts
                    );

                    TokioAsyncResolver::new(config, opts, TokioHandle)
                } else {
                    use trust_dns_resolver::error::ResolveError;

                    Err(ResolveError::from("current platform doesn't support trust-dns resolver with system configured".to_owned()))
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::convert::From;

use ::{Player, WIDTH, HEIGHT};
use unit::{Unit, PovUnit, GeneralUnit};
use move_conditions::{ALL_DIRECTIONS, Move, MoveCondition};

#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct Field<T: Unit> {
    pub rows: [[Option<T>; WIDTH]; HEIGHT],
}

impl<T: Unit> Field<T> {
    pub fn new() -> Field<T> {
        let rows = [[None; WIDTH]; HEIGHT];
        Field {
            rows: rows,
        }
    }

    pub fn possible_moves(&self, player: Player, move_condition: &MoveCondition) -> Vec<Move> {
        let mut res = Vec::new();

        for (j, row) in self.rows.iter().enumerate() {
            for (i, _) in row.iter().enumerate().filter(|&(_, x)| {if let &Some(x) = x {x.owner() == player} else {false} }) {
                for direction in ALL_DIRECTIONS {
                    let movement = Move {from: (i, j), direction: *direction};
                    if move_condition.is_valid(movement) { res.push(movement); }
                }
            }
        }

        res
    }
}

#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct PovField {
    pub pov: Player,
    pub field: Field<PovUnit>,
}

impl<'a> From<(&'a Field<GeneralUnit>, Player)> for PovField {
    fn from( data: (&Field<GeneralUnit>, Player) ) -> PovField {
        let (ref field, player) = data;
        let mut rows = [[None; WIDTH]; HEIGHT];

        for (i, ref row) in field.rows.iter().enumerate() {
            for (j, unit) in row.iter().enumerate() {
                if let Some(unit) = *unit {
                    rows[i][j] = Some( PovUnit::from( (unit, player) ) );
                }
            }
        }

        PovField {
            pov: player,
            field: Field{ rows: rows },
        }
    }
}
<commit_msg>Simple test for possible_moves method<commit_after>use std::convert::From;

use ::{Player, WIDTH, HEIGHT};
use unit::{Unit, PovUnit, GeneralUnit};
use move_conditions::{ALL_DIRECTIONS, Move, MoveCondition};

#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct Field<T: Unit> {
    pub rows: [[Option<T>; WIDTH]; HEIGHT],
}

impl<T: Unit> Field<T> {
    pub fn new() -> Field<T> {
        let rows = [[None; WIDTH]; HEIGHT];
        Field {
            rows: rows,
        }
    }

    pub fn possible_moves(&self, player: Player, move_condition: &MoveCondition) -> Vec<Move> {
        let mut res = Vec::new();

        for (j, row) in self.rows.iter().enumerate() {
            for (i, _) in row.iter().enumerate().filter(|&(_, x)| {if let &Some(x) = x {x.owner() == player} else {false} }) {
                for direction in ALL_DIRECTIONS {
                    let movement = Move {from: (i, j), direction: *direction};
                    if move_condition.is_valid(movement) { res.push(movement); }
                }
            }
        }

        res
    }
}

#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct PovField {
    pub pov: Player,
    pub field: Field<PovUnit>,
}

impl<'a> From<(&'a Field<GeneralUnit>, Player)> for PovField {
    fn from( data: (&Field<GeneralUnit>, Player) ) -> PovField {
        let (ref field, player) = data;
        let mut rows = [[None; WIDTH]; HEIGHT];

        for (i, ref row) in field.rows.iter().enumerate() {
            for (j, unit) in row.iter().enumerate() {
                if let Some(unit) = *unit {
                    rows[i][j] = Some( PovUnit::from( (unit, player) ) );
                }
            }
        }

        PovField {
            pov: player,
            field: Field{ rows: rows },
        }
    }
}

#[test]
fn possible_moves_test() {
    use move_conditions::{Direction, OnlyForwardMove};
    use ::RPS;

    let mut field = Field::new();
    let move_condition = OnlyForwardMove;
    field.rows[0][0] = Some(GeneralUnit { rps: RPS::Rock, owner: Player::Blue, visible: false,});
    field.rows[0][1] = Some(GeneralUnit { rps: RPS::Rock, owner: Player::Red, visible: false,});
    field.rows[1][0] = Some(GeneralUnit { rps: RPS::Rock, owner: Player::Red, visible: false,});
    let moves = vec![Move {from: (1, 0), direction: Direction::Forward},
                     Move {from: (0, 1), direction: Direction::Forward}];
    assert_eq!(field.possible_moves(Player::Red, &move_condition), moves);
}
<|endoftext|>