<commit_before>#![allow(non_camel_case_types)]

use libc::*;
use std::sync::{StaticMutex, MUTEX_INIT};
use std::error::Error;
use std::fmt;
use std::mem;
use std::ptr::null;

static NFQ_LOCK: StaticMutex = MUTEX_INIT;

#[derive(Debug)]
enum ErrorReason {
    OpenHandle,
    Bind,
    Unbind,
    CreateQueue,
    SetQueueMode,
    SetQueueMaxlen,
    Unknown
}

pub struct NFQError {
    reason: ErrorReason,
    description: String,
    cause: Option<Error>,
}

impl fmt::Debug for NFQError {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let msg = format!("{:?}: {:?} (cause: {:?})",
                          self.reason, self.description, self.cause);
        formatter.write_str(msg.as_slice())
    }
}

impl fmt::Display for NFQError {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let msg = format!("{:?} ({:?})", self.reason, self.description);
        formatter.write_str(msg.as_slice())
    }
}

impl Error for NFQError {
    fn description(&self) -> &str {
        self.description.as_slice()
    }
    fn cause(&self) -> Option<&Error> {
        self.cause.as_ref().map(|c| &**c)
    }
}

impl<E: Error> From<E> for NFQError {
    fn from(err: E) -> NFQError {
        NFQError {
            reason: ErrorReason::Unknown,
            description: err.description().to_string(),
            cause: Some(err),
        }
    }
}

fn error(reason: ErrorReason, msg: &str, res: Option<c_int>) -> NFQError {
    let errno = unsafe { nfq_errno };
    let desc = match res {
        Some(r) => format!("{} (errno: {}, res: {})", msg, errno, r),
        None => format!("{}, (errno: {})", msg, errno)
    };
    NFQError {
        reason: reason,
        description: desc,
        cause: None,
    }
}

#[link(name="netfilter_queue")]
extern {
    static mut nfq_errno: c_int;
}

// NFQ Handle

#[repr(C)]
struct nfq_handle;

#[repr(C)]
pub enum ProtoFamily {
    INET = 2,
    INET6 = 10,
}

#[link(name="netfilter_queue")]
extern {
    fn nfq_open() -> *mut nfq_handle;
    fn nfq_close(handle: *mut nfq_handle) -> c_int;

    fn nfq_bind_pf(handle: *mut nfq_handle, pf: uint16_t) -> c_int;
    fn nfq_unbind_pf(handle: *mut nfq_handle, pf: uint16_t) -> c_int;
}

pub struct NFQHandle {
    ptr: *mut nfq_handle,
}

impl Drop for NFQHandle {
    fn drop(&mut self) {
        let ret = unsafe { nfq_close(self.ptr) };
        if ret != 0 {
            panic!("Failed to close nfq handle");
        }
    }
}

impl NFQHandle {
    pub fn new() -> Result<NFQHandle, NFQError> {
        let _g = NFQ_LOCK.lock().unwrap();

        let ptr = unsafe { nfq_open() };
        if ptr.is_null() {
            Err(error(ErrorReason::OpenHandle, "Failed to allocate NFQHandle", None))
        } else {
            Ok(NFQHandle{ ptr: ptr })
        }
    }

    pub fn bind(&mut self, proto: ProtoFamily) -> Result<(), NFQError> {
        let _g = NFQ_LOCK.lock().unwrap();

        let res = unsafe { nfq_bind_pf(self.ptr, proto as uint16_t) };
        if res < 0 {
            Err(error(ErrorReason::Bind, "Failed to bind packet filter", Some(res)))
        } else {
            Ok(())
        }
    }

    pub fn unbind(&mut self, proto: ProtoFamily) -> Result<(), NFQError> {
        let _g = NFQ_LOCK.lock().unwrap();

        let res = unsafe { nfq_unbind_pf(self.ptr, proto as uint16_t) };
        if res < 0 {
            Err(error(ErrorReason::Bind, "Failed to unbind packet filter", Some(res)))
        } else {
            Ok(())
        }
    }

}

// NFQ Queue
#[repr(C)]
struct nfq_q_handle;

#[repr(C)]
struct nfgenmsg;

#[repr(C)]
struct nfq_data;

pub struct NFGenMsg {
    ptr: *mut nfgenmsg
}
pub struct NFQData {
    ptr: *mut nfq_data
}

#[repr(C)]
struct CallbackData<A> {
    ctx: *mut A,
    func: fn(ctx: &mut A, msg: &NFGenMsg, ad: &NFQData) -> c_int
}

#[link(name="netfilter_queue")]
extern {
    fn nfq_create_queue(handle: *mut nfq_handle,
                        num: uint16_t,
                        cb: extern "C" fn(h: *mut nfq_q_handle,
                                          nfmsg: *mut nfgenmsg,
                                          nfad: *mut nfq_data,
                                          data: *mut c_void) -> c_int,
                        data: *mut c_void) -> *mut nfq_q_handle;
    fn nfq_destroy_queue(handle: *mut nfq_q_handle) -> c_int;
}

pub struct NFQQueue<A> {
    ptr: *mut nfq_q_handle,
    cb_data: CallbackData<A>,
    ctx: A
}

extern fn queue_callback<A>(h: *mut nfq_q_handle,
                            nfmsg: *mut nfgenmsg,
                            nfad: *mut nfq_data,
                            cdata: *mut c_void) -> c_int {
    let data: &CallbackData<A> = unsafe { mem::transmute(cdata) };
    let msg = NFGenMsg { ptr: nfmsg };
    let ad = NFQData { ptr: nfad };
    let mut ctx = match unsafe { data.ctx.as_mut() } {
        Some(c) => c,
        None => panic!("Could not deref ctx pointer")
    };
    (data.func)(ctx, &msg, &ad) as c_int
}

impl<A> NFQQueue<A> {
    pub fn new(h: &NFQHandle,
               num: u16,
               ctx: A,
               cb: fn(ctx: &mut A,
                      msg: &NFGenMsg,
                      ad: &NFQData) -> c_int
               ) -> Result<NFQQueue<A>, NFQError> {
        let _g = NFQ_LOCK.lock().unwrap();

        let fpointer: *const nfq_q_handle = null();
        let apointer: *const A = null();
        // So we initialise the queue obj as empty apart from the ctx
        // This is so we can take references to the mem inside
        let mut queue = NFQQueue {
            ctx: ctx,
            // Will be set after nfq_create_queue
            ptr: fpointer as *mut nfq_q_handle,
            cb_data: CallbackData{
                // Will be set to reference to queue.ctx
                ctx: apointer as *mut A,
                func: cb
            }
        };

        let ctxp: *mut A = &mut queue.ctx;
        queue.cb_data.ctx = ctxp;

        let ptr = unsafe { nfq_create_queue(h.ptr,
                                            num,
                                            queue_callback::<A>,
                                            mem::transmute(&queue.cb_data)) };
        if ptr.is_null() {
            Err(error("Failed to create queue"))
        } else {
            queue.ptr = ptr;
            Ok(queue)
        }
    }
}

impl<A> Drop for NFQQueue<A> {
    fn drop(&mut self) {
        let ret = unsafe { nfq_destroy_queue(self.ptr) };
        if ret != 0 {
            panic!("Failed to destroy nfq queue");
        }
    }
}
<commit_msg>Fix NFQError box errors<commit_after>#![allow(non_camel_case_types)]

use libc::*;
use std::sync::{StaticMutex, MUTEX_INIT};
use std::error::Error;
use std::fmt;
use std::mem;
use std::ptr::null;

static NFQ_LOCK: StaticMutex = MUTEX_INIT;

#[derive(Debug)]
enum ErrorReason {
    OpenHandle,
    Bind,
    Unbind,
    CreateQueue,
    SetQueueMode,
    SetQueueMaxlen,
    Unknown
}

pub struct NFQError {
    reason: ErrorReason,
    description: String,
    cause: Option<Box<Error>>,
}

impl fmt::Debug for NFQError {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let msg = format!("{:?}: {:?} (cause: {:?})",
                          self.reason, self.description, self.cause);
        formatter.write_str(msg.as_ref())
    }
}

impl fmt::Display for NFQError {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let msg = format!("{:?} ({:?})", self.reason, self.description);
        formatter.write_str(msg.as_ref())
    }
}

impl Error for NFQError {
    fn description(&self) -> &str {
        self.description.as_ref()
    }
    fn cause(&self) -> Option<&Error> {
        self.cause.as_ref().map(|c| &**c)
    }
}

impl<E: Error + 'static> From<E> for NFQError {
    fn from(err: E) -> NFQError {
        NFQError {
            reason: ErrorReason::Unknown,
            description: err.description().to_string(),
            cause: Some(Box::new(err)),
        }
    }
}

fn error(reason: ErrorReason, msg: &str, res: Option<c_int>) -> NFQError {
    let errno = unsafe { nfq_errno };
    let desc = match res {
        Some(r) => format!("{} (errno: {}, res: {})", msg, errno, r),
        None => format!("{}, (errno: {})", msg, errno)
    };
    NFQError {
        reason: reason,
        description: desc,
        cause: None,
    }
}

#[link(name="netfilter_queue")]
extern {
    static mut nfq_errno: c_int;
}

// NFQ Handle

#[repr(C)]
struct nfq_handle;

#[repr(C)]
pub enum ProtoFamily {
    INET = 2,
    INET6 = 10,
}

#[link(name="netfilter_queue")]
extern {
    fn nfq_open() -> *mut nfq_handle;
    fn nfq_close(handle: *mut nfq_handle) -> c_int;

    fn nfq_bind_pf(handle: *mut nfq_handle, pf: uint16_t) -> c_int;
    fn nfq_unbind_pf(handle: *mut nfq_handle, pf: uint16_t) -> c_int;
}

pub struct NFQHandle {
    ptr: *mut nfq_handle,
}

impl Drop for NFQHandle {
    fn drop(&mut self) {
        let ret = unsafe { nfq_close(self.ptr) };
        if ret != 0 {
            panic!("Failed to close nfq handle");
        }
    }
}

impl NFQHandle {
    pub fn new() -> Result<NFQHandle, NFQError> {
        let _g = NFQ_LOCK.lock().unwrap();

        let ptr = unsafe { nfq_open() };
        if ptr.is_null() {
            Err(error(ErrorReason::OpenHandle, "Failed to allocate NFQHandle", None))
        } else {
            Ok(NFQHandle{ ptr: ptr })
        }
    }

    pub fn bind(&mut self, proto: ProtoFamily) -> Result<(), NFQError> {
        let _g = NFQ_LOCK.lock().unwrap();

        let res = unsafe { nfq_bind_pf(self.ptr, proto as uint16_t) };
        if res < 0 {
            Err(error(ErrorReason::Bind, "Failed to bind packet filter", Some(res)))
        } else {
            Ok(())
        }
    }

    pub fn unbind(&mut self, proto: ProtoFamily) -> Result<(), NFQError> {
        let _g = NFQ_LOCK.lock().unwrap();

        let res = unsafe { nfq_unbind_pf(self.ptr, proto as uint16_t) };
        if res < 0 {
            Err(error(ErrorReason::Bind, "Failed to unbind packet filter", Some(res)))
        } else {
            Ok(())
        }
    }

}

// NFQ Queue
#[repr(C)]
struct nfq_q_handle;

#[repr(C)]
struct nfgenmsg;

#[repr(C)]
struct nfq_data;

pub struct NFGenMsg {
    ptr: *mut nfgenmsg
}
pub struct NFQData {
    ptr: *mut nfq_data
}

#[repr(C)]
struct CallbackData<A> {
    ctx: *mut A,
    func: fn(ctx: &mut A, msg: &NFGenMsg, ad: &NFQData) -> c_int
}

enum NFQCopyMode {
    NONE = 0,
    META = 1,
    PACKET = 2
}

pub enum CopyMode {
    None,
    Metadata,
    Packet(u16)
}

#[link(name="netfilter_queue")]
extern {
    fn nfq_create_queue(handle: *mut nfq_handle,
                        num: uint16_t,
                        cb: extern "C" fn(h: *mut nfq_q_handle,
                                          nfmsg: *mut nfgenmsg,
                                          nfad: *mut nfq_data,
                                          data: *mut c_void) -> c_int,
                        data: *mut c_void) -> *mut nfq_q_handle;
    fn nfq_destroy_queue(handle: *mut nfq_q_handle) -> c_int;

    fn nfq_fd(handle: *mut nfq_handle) -> c_int;
    fn nfq_handle_packet(handle: *mut nfq_handle,
                         buf: *mut u8,
                         len: c_int) -> c_int;
    fn nfq_set_mode(handle: *mut nfq_q_handle,
                    mode: uint8_t,
                    range: uint32_t) -> c_int;
    fn nfq_set_queue_maxlen(handle: *mut nfq_q_handle,
                            queuelen: uint32_t) -> c_int;
    fn nfq_set_verdict(handle: *mut nfq_q_handle,
                       id: uint32_t,
                       verdict: uint32_t,
                       data_len: uint32_t,
                       buf: *const u8) -> c_int;
}

pub struct NFQQueue<A> {
    ptr: *mut nfq_q_handle,
    cb_data: CallbackData<A>,
    ctx: A
}

extern fn queue_callback<A>(h: *mut nfq_q_handle,
                            nfmsg: *mut nfgenmsg,
                            nfad: *mut nfq_data,
                            cdata: *mut c_void) -> c_int {
    let data: &CallbackData<A> = unsafe { mem::transmute(cdata) };
    let msg = NFGenMsg { ptr: nfmsg };
    let ad = NFQData { ptr: nfad };
    let mut ctx = match unsafe { data.ctx.as_mut() } {
        Some(c) => c,
        None => panic!("Could not deref ctx pointer")
    };
    (data.func)(ctx, &msg, &ad) as c_int
}

impl<A> NFQQueue<A> {
    pub fn new(h: &NFQHandle,
               num: u16,
               ctx: A,
               cb: fn(ctx: &mut A,
                      msg: &NFGenMsg,
                      ad: &NFQData) -> c_int
               ) -> Result<NFQQueue<A>, NFQError> {
        let _g = NFQ_LOCK.lock().unwrap();

        let fpointer: *const nfq_q_handle = null();
        let apointer: *const A = null();
        // So we initialise the queue obj as empty apart from the ctx
        // This is so we can take references to the mem inside
        let mut queue = NFQQueue {
            ctx: ctx,
            // Will be set after nfq_create_queue
            ptr: fpointer as *mut nfq_q_handle,
            cb_data: CallbackData{
                // Will be set to reference to queue.ctx
                ctx: apointer as *mut A,
                func: cb
            }
        };

        let ctxp: *mut A = &mut queue.ctx;
        queue.cb_data.ctx = ctxp;

        let ptr = unsafe { nfq_create_queue(h.ptr,
                                            num,
                                            queue_callback::<A>,
                                            mem::transmute(&queue.cb_data)) };
        if ptr.is_null() {
            Err(error(ErrorReason::CreateQueue, "Failed to create queue", None))
        } else {
            queue.ptr = ptr;
            Ok(queue)
        }
    }

    pub fn mode(&mut self, mode: CopyMode) -> Result<(), NFQError> {
        let cmode = match mode {
            CopyMode::None => NFQCopyMode::NONE,
            CopyMode::Metadata => NFQCopyMode::META,
            CopyMode::Packet(_) => NFQCopyMode::PACKET
        } as uint8_t;
        let range = match mode {
            CopyMode::Packet(r) => r,
            _ => 0
        } as uint16_t;

        let res = unsafe { nfq_set_mode(self.ptr, mode, range) };
        if res != 0 {
            Err(error(ErrorReason::SetQueueMode, "Failed to set queue mode", Some(res)))
        } else {
            Ok(())
        }
    }

    pub fn queue_maxlen(&mut self, len: u32) -> Result<(), NFQError> {
        let res = unsafe { nfq_set_queue_maxlen(self.ptr, len as uint32_t) };
        if res != 0 {
            Err(error(ErrorReason::SetQueueMaxlen, "Failed to set queue maxlen", Some(res)))
        } else {
            Ok(())
        }
    }
}

impl<A> Drop for NFQQueue<A> {
    fn drop(&mut self) {
        let ret = unsafe { nfq_destroy_queue(self.ptr) };
        if ret != 0 {
            panic!("Failed to destroy nfq queue");
        }
    }
}
<|endoftext|>


<commit_before>use std::path::PathBuf;
use iron::modifiers::Header;
use self::super::{Options, Error};
use mime_guess::guess_mime_type_opt;
use self::super::util::{html_response, file_contains, ERROR_HTML, DIRECTORY_LISTING_HTML};
use iron::{headers, status, method, mime, IronResult, Listening, Response, TypeMap, Request, Handler, Iron};

#[derive(Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
pub struct HttpHandler {
    pub hosted_directory: (String, PathBuf),
    pub follow_symlinks: bool,
}

impl HttpHandler {
    pub fn new(opts: &Options) -> HttpHandler {
        HttpHandler {
            hosted_directory: opts.hosted_directory.clone(),
            follow_symlinks: opts.follow_symlinks,
        }
    }
}

impl Handler for HttpHandler {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        match req.method {
            method::Options => self.handle_options(req),
            method::Get => self.handle_get(req),
            method::Head => {
                self.handle_get(req).map(|mut r| {
                    r.body = None;
                    r
                })
            }
            method::Trace => self.handle_trace(req),
            _ => self.handle_bad_method(req),
        }
    }
}

impl HttpHandler {
    fn handle_options(&self, req: &mut Request) -> IronResult<Response> {
        println!("{} asked for options", req.remote_addr);
        Ok(Response::with((status::Ok, Header(headers::Allow(vec![method::Options, method::Get, method::Head, method::Trace])))))
    }

    fn handle_get(&self, req: &mut Request) -> IronResult<Response> {
        let req_p = req.url.path().into_iter().filter(|p| !p.is_empty()).fold(self.hosted_directory.1.clone(), |cur, pp| cur.join(pp));
        if !req_p.exists() {
            self.handle_get_nonexistant(req, req_p)
        } else if req_p.metadata().unwrap().file_type().is_symlink() && !self.follow_symlinks {
            self.handle_get_unfollowable_symlink(req, req_p)
        } else if req_p.is_file() {
            self.handle_get_file(req, req_p)
        } else {
            self.handle_get_dir(req, req_p)
        }
    }

    fn handle_get_nonexistant(&self, req: &mut Request, req_p: PathBuf) -> IronResult<Response> {
        println!("{} requested nonexistant file {}", req.remote_addr, req_p.display());
        Ok(Response::with((status::NotFound,
                           "text/html;charset=utf-8".parse::<mime::Mime>().unwrap(),
                           html_response(ERROR_HTML,
                                         vec!["404 Not Found".to_string(),
                                              format!("The requested entity \"{}\" doesn't exist.",
                                                      &req.url.path().into_iter().fold("".to_string(), |cur, pp| cur + "/" + pp)[1..]),
                                              "".to_string()]))))
    }

    fn handle_get_unfollowable_symlink(&self, req: &mut Request, req_p: PathBuf) -> IronResult<Response> {
        println!("{} requested unfollowable symlink {}", req.remote_addr, req_p.display());
        Ok(Response::with((status::Forbidden,
                           "text/html;charset=utf-8".parse::<mime::Mime>().unwrap(),
                           html_response(ERROR_HTML,
                                         vec!["403 Forbidden".to_string(),
                                              format!("No permission to follow symlink \"{}\".",
                                                      &req.url.path().into_iter().fold("".to_string(), |cur, pp| cur + "/" + pp)[1..]),
                                              "
Ask the server administrator to pass \"-s\" to <samp>http</samp> if you think this is unintended.
"
                                                  .to_string()]))))
    }

    fn handle_get_file(&self, req: &mut Request, req_p: PathBuf) -> IronResult<Response> {
        let mime_type = guess_mime_type_opt(&req_p).unwrap_or_else(|| if file_contains(&req_p, 0) {
            "application/octet-stream".parse().unwrap()
        } else {
            "text/plain".parse().unwrap()
        });
        println!("{} was served file {} as {}", req.remote_addr, req_p.display(), mime_type);
        Ok(Response::with((status::Ok, mime_type, req_p)))
    }

    fn handle_get_dir(&self, req: &mut Request, req_p: PathBuf) -> IronResult<Response> {
        let relpath = (req.url.path().into_iter().fold("".to_string(), |cur, pp| cur + "/" + pp)[1..].to_string() + "/").replace("//", "/");
        println!("{} was served directory listing for {}", req.remote_addr, req_p.display());
        Ok(Response::with((status::Ok,
                           "text/html;charset=utf-8".parse::<mime::Mime>().unwrap(),
                           html_response(DIRECTORY_LISTING_HTML,
                                         vec![relpath.clone(),
                                              req_p.read_dir()
                                                  .unwrap()
                                                  .map(Result::unwrap)
                                                  .filter(|f| self.follow_symlinks || !f.metadata().unwrap().file_type().is_symlink())
                                                  .fold("".to_string(), |cur, f| {
                let fname = f.file_name().into_string().unwrap() +
                            if !f.file_type().unwrap().is_file() {
                    "/"
                } else {
                    ""
                };
                cur + "
" + &fname + "
\n"
            })]))))
    }

    fn handle_trace(&self, req: &mut Request) -> IronResult<Response> {
        println!("{} requested TRACE", req.remote_addr);

        let mut hdr = req.headers.clone();
        hdr.set(headers::ContentType("message/http".parse().unwrap()));

        Ok(Response {
            status: Some(status::Ok),
            headers: hdr,
            extensions: TypeMap::new(),
            body: None,
        })
    }

    fn handle_bad_method(&self, req: &mut Request) -> IronResult<Response> {
        println!("{} used invalid request method {}", req.remote_addr, req.method);
        Ok(Response::with((status::NotImplemented,
                           "text/html;charset=utf-8".parse::<mime::Mime>().unwrap(),
                           html_response(ERROR_HTML,
                                         vec!["501 Not Implemented".to_string(),
                                              "This operation was not implemented.".to_string(),
                                              format!("
Unsupported request method: {}.
Supported methods: OPTIONS, GET, HEAD AND TRACE.
",
                                                      req.method)]))))
    }
}

pub fn try_ports<H: Handler + Clone>(hndlr: H, from: u16, up_to: u16) -> Result<Listening, Error> {
    for port in from..up_to {
        match Iron::new(hndlr.clone()).http(("0.0.0.0", port)) {
            Ok(server) => return Ok(server),
            Err(error) => {
                if !error.to_string().contains("port") {
                    return Err(Error::Io {
                        desc: "server",
                        op: "start",
                        more: None,
                    });
                }
            }
        }
    }

    Err(Error::Io {
        desc: "server",
        op: "start",
        more: Some("no free ports"),
    })
}
<commit_msg>Don't bleed symlink info<commit_after>use std::path::PathBuf;
use iron::modifiers::Header;
use self::super::{Options, Error};
use mime_guess::guess_mime_type_opt;
use self::super::util::{html_response, file_contains, ERROR_HTML, DIRECTORY_LISTING_HTML};
use iron::{headers, status, method, mime, IronResult, Listening, Response, TypeMap, Request, Handler, Iron};

#[derive(Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
pub struct HttpHandler {
    pub hosted_directory: (String, PathBuf),
    pub follow_symlinks: bool,
}

impl HttpHandler {
    pub fn new(opts: &Options) -> HttpHandler {
        HttpHandler {
            hosted_directory: opts.hosted_directory.clone(),
            follow_symlinks: opts.follow_symlinks,
        }
    }
}

impl Handler for HttpHandler {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        match req.method {
            method::Options => self.handle_options(req),
            method::Get => self.handle_get(req),
            method::Head => {
                self.handle_get(req).map(|mut r| {
                    r.body = None;
                    r
                })
            }
            method::Trace => self.handle_trace(req),
            _ => self.handle_bad_method(req),
        }
    }
}

impl HttpHandler {
    fn handle_options(&self, req: &mut Request) -> IronResult<Response> {
        println!("{} asked for options", req.remote_addr);
        Ok(Response::with((status::Ok, Header(headers::Allow(vec![method::Options, method::Get, method::Head, method::Trace])))))
    }

    fn handle_get(&self, req: &mut Request) -> IronResult<Response> {
        let req_p = req.url.path().into_iter().filter(|p| !p.is_empty()).fold(self.hosted_directory.1.clone(), |cur, pp| cur.join(pp));
        if !req_p.exists() || (req_p.metadata().unwrap().file_type().is_symlink() && !self.follow_symlinks) {
            self.handle_get_nonexistant(req, req_p)
        } else if req_p.is_file() {
            self.handle_get_file(req, req_p)
        } else {
            self.handle_get_dir(req, req_p)
        }
    }

    fn handle_get_nonexistant(&self, req: &mut Request, req_p: PathBuf) -> IronResult<Response> {
        println!("{} requested nonexistant file {}", req.remote_addr, req_p.display());
        Ok(Response::with((status::NotFound,
                           "text/html;charset=utf-8".parse::<mime::Mime>().unwrap(),
                           html_response(ERROR_HTML,
                                         vec!["404 Not Found".to_string(),
                                              format!("The requested entity \"{}\" doesn't exist.",
                                                      &req.url.path().into_iter().fold("".to_string(), |cur, pp| cur + "/" + pp)[1..]),
                                              "".to_string()]))))
    }

    fn handle_get_file(&self, req: &mut Request, req_p: PathBuf) -> IronResult<Response> {
        let mime_type = guess_mime_type_opt(&req_p).unwrap_or_else(|| if file_contains(&req_p, 0) {
            "application/octet-stream".parse().unwrap()
        } else {
            "text/plain".parse().unwrap()
        });
        println!("{} was served file {} as {}", req.remote_addr, req_p.display(), mime_type);
        Ok(Response::with((status::Ok, mime_type, req_p)))
    }

    fn handle_get_dir(&self, req: &mut Request, req_p: PathBuf) -> IronResult<Response> {
        let relpath = (req.url.path().into_iter().fold("".to_string(), |cur, pp| cur + "/" + pp)[1..].to_string() + "/").replace("//", "/");
        println!("{} was served directory listing for {}", req.remote_addr, req_p.display());
        Ok(Response::with((status::Ok,
                           "text/html;charset=utf-8".parse::<mime::Mime>().unwrap(),
                           html_response(DIRECTORY_LISTING_HTML,
                                         vec![relpath.clone(),
                                              req_p.read_dir()
                                                  .unwrap()
                                                  .map(Result::unwrap)
                                                  .filter(|f| self.follow_symlinks || !f.metadata().unwrap().file_type().is_symlink())
                                                  .fold("".to_string(), |cur, f| {
                let fname = f.file_name().into_string().unwrap() +
                            if !f.file_type().unwrap().is_file() {
                    "/"
                } else {
                    ""
                };
                cur + "
" + &fname + "
\n"
            })]))))
    }

    fn handle_trace(&self, req: &mut Request) -> IronResult<Response> {
        println!("{} requested TRACE", req.remote_addr);

        let mut hdr = req.headers.clone();
        hdr.set(headers::ContentType("message/http".parse().unwrap()));

        Ok(Response {
            status: Some(status::Ok),
            headers: hdr,
            extensions: TypeMap::new(),
            body: None,
        })
    }

    fn handle_bad_method(&self, req: &mut Request) -> IronResult<Response> {
        println!("{} used invalid request method {}", req.remote_addr, req.method);
        Ok(Response::with((status::NotImplemented,
                           "text/html;charset=utf-8".parse::<mime::Mime>().unwrap(),
                           html_response(ERROR_HTML,
                                         vec!["501 Not Implemented".to_string(),
                                              "This operation was not implemented.".to_string(),
                                              format!("
Unsupported request method: {}.
Supported methods: OPTIONS, GET, HEAD AND TRACE.
",
                                                      req.method)]))))
    }
}

pub fn try_ports<H: Handler + Clone>(hndlr: H, from: u16, up_to: u16) -> Result<Listening, Error> {
    for port in from..up_to {
        match Iron::new(hndlr.clone()).http(("0.0.0.0", port)) {
            Ok(server) => return Ok(server),
            Err(error) => {
                if !error.to_string().contains("port") {
                    return Err(Error::Io {
                        desc: "server",
                        op: "start",
                        more: None,
                    });
                }
            }
        }
    }

    Err(Error::Io {
        desc: "server",
        op: "start",
        more: Some("no free ports"),
    })
}
<|endoftext|>


<commit_before>// Copyright 2017 GFX developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

use super::*;

use cocoa_foundation::foundation::NSUInteger;
use objc::runtime::{NO, YES};

#[repr(u64)]
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum MTLBlendFactor {
    Zero = 0,
    One = 1,
    SourceColor = 2,
    OneMinusSourceColor = 3,
    SourceAlpha = 4,
    OneMinusSourceAlpha = 5,
    DestinationColor = 6,
    OneMinusDestinationColor = 7,
    DestinationAlpha = 8,
    OneMinusDestinationAlpha = 9,
    SourceAlphaSaturated = 10,
    BlendColor = 11,
    OneMinusBlendColor = 12,
    BlendAlpha = 13,
    OneMinusBlendAlpha = 14,
    Source1Color = 15,
    OneMinusSource1Color = 16,
    Source1Alpha = 17,
    OneMinusSource1Alpha = 18,
}

#[repr(u64)]
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum MTLBlendOperation {
    Add = 0,
    Subtract = 1,
    ReverseSubtract = 2,
    Min = 3,
    Max = 4,
}

bitflags! {
    pub struct MTLColorWriteMask: NSUInteger {
        const Red   = 0x1 << 3;
        const Green = 0x1 << 2;
        const Blue  = 0x1 << 1;
        const Alpha = 0x1 << 0;
    }
}

#[repr(u64)]
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum MTLPrimitiveTopologyClass {
    Unspecified = 0,
    Point = 1,
    Line = 2,
    Triangle = 3,
}

pub enum MTLRenderPipelineColorAttachmentDescriptor {}

foreign_obj_type! {
    type CType = MTLRenderPipelineColorAttachmentDescriptor;
    pub struct RenderPipelineColorAttachmentDescriptor;
    pub struct RenderPipelineColorAttachmentDescriptorRef;
}

impl RenderPipelineColorAttachmentDescriptorRef {
    pub fn pixel_format(&self) -> MTLPixelFormat {
        unsafe { msg_send![self, pixelFormat] }
    }

    pub fn set_pixel_format(&self, pixel_format: MTLPixelFormat) {
        unsafe { msg_send![self, setPixelFormat: pixel_format] }
    }

    pub fn is_blending_enabled(&self) -> bool {
        unsafe {
            match msg_send![self, isBlendingEnabled] {
                YES => true,
                NO => false,
                _ => unreachable!(),
            }
        }
    }

    pub fn set_blending_enabled(&self, enabled: bool) {
        unsafe { msg_send![self, setBlendingEnabled: enabled] }
    }

    pub fn source_rgb_blend_factor(&self) -> MTLBlendFactor {
        unsafe { msg_send![self, sourceRGBBlendFactor] }
    }

    pub fn set_source_rgb_blend_factor(&self, blend_factor: MTLBlendFactor) {
        unsafe { msg_send![self, setSourceRGBBlendFactor: blend_factor] }
    }

    pub fn destination_rgb_blend_factor(&self) -> MTLBlendFactor {
        unsafe { msg_send![self, destinationRGBBlendFactor] }
    }

    pub fn set_destination_rgb_blend_factor(&self, blend_factor: MTLBlendFactor) {
        unsafe { msg_send![self, setDestinationRGBBlendFactor: blend_factor] }
    }

    pub fn rgb_blend_operation(&self) -> MTLBlendOperation {
        unsafe { msg_send![self, rgbBlendOperation] }
    }

    pub fn set_rgb_blend_operation(&self, blend_operation: MTLBlendOperation) {
        unsafe { msg_send![self, setRgbBlendOperation: blend_operation] }
    }

    pub fn source_alpha_blend_factor(&self) -> MTLBlendFactor {
        unsafe { msg_send![self, sourceAlphaBlendFactor] }
    }

    pub fn set_source_alpha_blend_factor(&self, blend_factor: MTLBlendFactor) {
        unsafe { msg_send![self, setSourceAlphaBlendFactor: blend_factor] }
    }

    pub fn destination_alpha_blend_factor(&self) -> MTLBlendFactor {
        unsafe { msg_send![self, destinationAlphaBlendFactor] }
    }

    pub fn set_destination_alpha_blend_factor(&self, blend_factor: MTLBlendFactor) {
        unsafe { msg_send![self, setDestinationAlphaBlendFactor: blend_factor] }
    }

    pub fn alpha_blend_operation(&self) -> MTLBlendOperation {
        unsafe { msg_send![self, alphaBlendOperation] }
    }

    pub fn set_alpha_blend_operation(&self, blend_operation: MTLBlendOperation) {
        unsafe { msg_send![self, setAlphaBlendOperation: blend_operation] }
    }

    pub fn write_mask(&self) -> MTLColorWriteMask {
        unsafe { msg_send![self, writeMask] }
    }

    pub fn set_write_mask(&self, mask: MTLColorWriteMask) {
        unsafe { msg_send![self, setWriteMask: mask] }
    }
}

pub enum MTLRenderPipelineReflection {}

foreign_obj_type! {
    type CType = MTLRenderPipelineReflection;
    pub struct RenderPipelineReflection;
    pub struct RenderPipelineReflectionRef;
}

impl RenderPipelineReflection {
    #[cfg(feature = "private")]
    pub unsafe fn new(
        vertex_data: *mut std::ffi::c_void,
        fragment_data: *mut std::ffi::c_void,
        vertex_desc: *mut std::ffi::c_void,
        device: &DeviceRef,
        options: u64,
        flags: u64,
    ) -> Self {
        let class = class!(MTLRenderPipelineReflection);
        let this: RenderPipelineReflection = msg_send![class, alloc];
        let this_alias: *mut Object = msg_send![this.as_ref(), initWithVertexData:vertex_data
                                                                fragmentData:fragment_data
                                                serializedVertexDescriptor:vertex_desc
                                                                    device:device
                                                                    options:options
                                                                        flags:flags];
        if this_alias.is_null() {
            panic!("[MTLRenderPipelineReflection init] failed");
        }
        this
    }
}

impl RenderPipelineReflectionRef {
    pub fn fragment_arguments(&self) -> &Array<Argument> {
        unsafe { msg_send![self, fragmentArguments] }
    }

    pub fn vertex_arguments(&self) -> &Array<Argument> {
        unsafe { msg_send![self, vertexArguments] }
    }
}

pub enum MTLRenderPipelineDescriptor {}

foreign_obj_type! {
    type CType = MTLRenderPipelineDescriptor;
    pub struct RenderPipelineDescriptor;
    pub struct RenderPipelineDescriptorRef;
}

impl RenderPipelineDescriptor {
    pub fn new() -> Self {
        unsafe {
            let class = class!(MTLRenderPipelineDescriptor);
            msg_send![class, new]
        }
    }
}

impl RenderPipelineDescriptorRef {
    pub fn label(&self) -> &str {
        unsafe {
            let label = msg_send![self, label];
            crate::nsstring_as_str(label)
        }
    }

    pub fn set_label(&self, label: &str) {
        unsafe {
            let nslabel = crate::nsstring_from_str(label);
            let () = msg_send![self, setLabel: nslabel];
        }
    }

    pub fn vertex_function(&self) -> Option<&FunctionRef> {
        unsafe { msg_send![self, vertexFunction] }
    }

    pub fn set_vertex_function(&self, function: Option<&FunctionRef>) {
        unsafe { msg_send![self, setVertexFunction: function] }
    }

    pub fn fragment_function(&self) -> Option<&FunctionRef> {
        unsafe { msg_send![self, fragmentFunction] }
    }

    pub fn set_fragment_function(&self, function: Option<&FunctionRef>) {
        unsafe { msg_send![self, setFragmentFunction: function] }
    }

    pub fn vertex_descriptor(&self) -> Option<&VertexDescriptorRef> {
        unsafe { msg_send![self, vertexDescriptor] }
    }

    pub fn set_vertex_descriptor(&self, descriptor: Option<&VertexDescriptorRef>) {
        unsafe { msg_send![self, setVertexDescriptor: descriptor] }
    }

    pub fn sample_count(&self) -> NSUInteger {
        unsafe { msg_send![self, sampleCount] }
    }

    pub fn set_sample_count(&self, count: NSUInteger) {
        unsafe { msg_send![self, setSampleCount: count] }
    }

    pub fn max_vertex_amplification_count(&self) -> NSUInteger {
        unsafe { msg_send![self, maxVertexAmplificationCount] }
    }

    pub fn set_max_vertex_amplification_count(&self, count: NSUInteger) {
        unsafe { msg_send![self, setMaxVertexAmplificationCount: count] }
    }

    pub fn is_alpha_to_coverage_enabled(&self) -> bool {
        unsafe {
            match msg_send![self, isAlphaToCoverageEnabled] {
                YES => true,
                NO => false,
                _ => unreachable!(),
            }
        }
    }

    pub fn set_alpha_to_coverage_enabled(&self, enabled: bool) {
        unsafe { msg_send![self, setAlphaToCoverageEnabled: enabled] }
    }

    pub fn is_alpha_to_one_enabled(&self) -> bool {
        unsafe {
            match msg_send![self, isAlphaToOneEnabled] {
                YES => true,
                NO => false,
                _ => unreachable!(),
            }
        }
    }

    pub fn set_alpha_to_one_enabled(&self, enabled: bool) {
        unsafe { msg_send![self, setAlphaToOneEnabled: enabled] }
    }

    pub fn is_rasterization_enabled(&self) -> bool {
        unsafe {
            match msg_send![self, isRasterizationEnabled] {
                YES => true,
                NO => false,
                _ => unreachable!(),
            }
        }
    }

    pub fn set_rasterization_enabled(&self, enabled: bool) {
        unsafe { msg_send![self, setRasterizationEnabled: enabled] }
    }

    pub fn color_attachments(&self) -> &RenderPipelineColorAttachmentDescriptorArrayRef {
        unsafe { msg_send![self, colorAttachments] }
    }

    pub fn depth_attachment_pixel_format(&self) -> MTLPixelFormat {
        unsafe { msg_send![self, depthAttachmentPixelFormat] }
    }

    pub fn set_depth_attachment_pixel_format(&self, pixel_format: MTLPixelFormat) {
        unsafe { msg_send![self, setDepthAttachmentPixelFormat: pixel_format] }
    }

    pub fn stencil_attachment_pixel_format(&self) -> MTLPixelFormat {
        unsafe { msg_send![self, stencilAttachmentPixelFormat] }
    }

    pub fn set_stencil_attachment_pixel_format(&self, pixel_format: MTLPixelFormat) {
        unsafe { msg_send![self, setStencilAttachmentPixelFormat: pixel_format] }
    }

    pub fn input_primitive_topology(&self) -> MTLPrimitiveTopologyClass {
        unsafe { msg_send![self, inputPrimitiveTopology] }
    }

    pub fn set_input_primitive_topology(&self, topology: MTLPrimitiveTopologyClass) {
        unsafe { msg_send![self, setInputPrimitiveTopology: topology] }
    }

    #[cfg(feature = "private")]
    pub unsafe fn serialize_vertex_data(&self) -> *mut std::ffi::c_void {
        use std::ptr;
        let flags = 0;
        let err: *mut Object = ptr::null_mut();
        msg_send![self, newSerializedVertexDataWithFlags:flags
                                                    error:err]
    }

    #[cfg(feature = "private")]
    pub unsafe fn serialize_fragment_data(&self) -> *mut std::ffi::c_void {
        msg_send![self, serializeFragmentData]
    }

    pub fn support_indirect_command_buffers(&self) -> bool {
        unsafe {
            match msg_send![self, supportIndirectCommandBuffers] {
                YES => true,
                NO => false,
                _ => unreachable!(),
            }
        }
    }

    pub fn set_support_indirect_command_buffers(&self, support: bool) {
        unsafe { msg_send![self, setSupportIndirectCommandBuffers: support] }
    }

    pub fn vertex_buffers(&self) -> Option<&PipelineBufferDescriptorArrayRef> {
        unsafe { msg_send![self, vertexBuffers] }
    }

    pub fn fragment_buffers(&self) -> Option<&PipelineBufferDescriptorArrayRef> {
        unsafe { msg_send![self, fragmentBuffers] }
    }

    pub fn reset(&self) {
        unsafe { msg_send![self, reset] }
    }
}

pub enum MTLRenderPipelineState {}

foreign_obj_type! {
    type CType = MTLRenderPipelineState;
    pub struct RenderPipelineState;
    pub struct RenderPipelineStateRef;
}

impl RenderPipelineStateRef {
    pub fn label(&self) -> &str {
        unsafe {
            let label = msg_send![self, label];
            crate::nsstring_as_str(label)
        }
    }

    pub fn set_label(&self, label: &str) {
        unsafe {
            let nslabel = crate::nsstring_from_str(label);
            let () = msg_send![self, setLabel: nslabel];
        }
    }
}

pub enum MTLRenderPipelineColorAttachmentDescriptorArray {}

foreign_obj_type! {
    type CType = MTLRenderPipelineColorAttachmentDescriptorArray;
    pub struct RenderPipelineColorAttachmentDescriptorArray;
    pub struct RenderPipelineColorAttachmentDescriptorArrayRef;
}

impl RenderPipelineColorAttachmentDescriptorArrayRef {
    pub fn object_at(
        &self,
        index: NSUInteger,
    ) -> Option<&RenderPipelineColorAttachmentDescriptorRef> {
        unsafe { msg_send![self, objectAtIndexedSubscript: index] }
    }

    pub fn set_object_at(
        &self,
        index: NSUInteger,
        attachment: Option<&RenderPipelineColorAttachmentDescriptorRef>,
    ) {
        unsafe {
            msg_send![self, setObject:attachment
                   atIndexedSubscript:index]
        }
    }
}
<commit_msg>added device method to renderpipelinestate (#173)<commit_after>// Copyright 2017 GFX developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

use super::*;

use cocoa_foundation::foundation::NSUInteger;
use objc::runtime::{NO, YES};

#[repr(u64)]
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum MTLBlendFactor {
    Zero = 0,
    One = 1,
    SourceColor = 2,
    OneMinusSourceColor = 3,
    SourceAlpha = 4,
    OneMinusSourceAlpha = 5,
    DestinationColor = 6,
    OneMinusDestinationColor = 7,
    DestinationAlpha = 8,
    OneMinusDestinationAlpha = 9,
    SourceAlphaSaturated = 10,
    BlendColor = 11,
    OneMinusBlendColor = 12,
    BlendAlpha = 13,
    OneMinusBlendAlpha = 14,
    Source1Color = 15,
    OneMinusSource1Color = 16,
    Source1Alpha = 17,
    OneMinusSource1Alpha = 18,
}

#[repr(u64)]
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum MTLBlendOperation {
    Add = 0,
    Subtract = 1,
    ReverseSubtract = 2,
    Min = 3,
    Max = 4,
}

bitflags! {
    pub struct MTLColorWriteMask: NSUInteger {
        const Red   = 0x1 << 3;
        const Green = 0x1 << 2;
        const Blue  = 0x1 << 1;
        const Alpha = 0x1 << 0;
    }
}

#[repr(u64)]
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum MTLPrimitiveTopologyClass {
    Unspecified = 0,
    Point = 1,
    Line = 2,
    Triangle = 3,
}

pub enum MTLRenderPipelineColorAttachmentDescriptor {}

foreign_obj_type! {
    type CType = MTLRenderPipelineColorAttachmentDescriptor;
    pub struct RenderPipelineColorAttachmentDescriptor;
    pub struct RenderPipelineColorAttachmentDescriptorRef;
}

impl RenderPipelineColorAttachmentDescriptorRef {
    pub fn pixel_format(&self) -> MTLPixelFormat {
        unsafe { msg_send![self, pixelFormat] }
    }

    pub fn set_pixel_format(&self, pixel_format: MTLPixelFormat) {
        unsafe { msg_send![self, setPixelFormat: pixel_format] }
    }

    pub fn is_blending_enabled(&self) -> bool {
        unsafe {
            match msg_send![self, isBlendingEnabled] {
                YES => true,
                NO => false,
                _ => unreachable!(),
            }
        }
    }

    pub fn set_blending_enabled(&self, enabled: bool) {
        unsafe { msg_send![self, setBlendingEnabled: enabled] }
    }

    pub fn source_rgb_blend_factor(&self) -> MTLBlendFactor {
        unsafe { msg_send![self, sourceRGBBlendFactor] }
    }

    pub fn set_source_rgb_blend_factor(&self, blend_factor: MTLBlendFactor) {
        unsafe { msg_send![self, setSourceRGBBlendFactor: blend_factor] }
    }

    pub fn destination_rgb_blend_factor(&self) -> MTLBlendFactor {
        unsafe { msg_send![self, destinationRGBBlendFactor] }
    }

    pub fn set_destination_rgb_blend_factor(&self, blend_factor: MTLBlendFactor) {
        unsafe { msg_send![self, setDestinationRGBBlendFactor: blend_factor] }
    }

    pub fn rgb_blend_operation(&self) -> MTLBlendOperation {
        unsafe { msg_send![self, rgbBlendOperation] }
    }

    pub fn set_rgb_blend_operation(&self, blend_operation: MTLBlendOperation) {
        unsafe { msg_send![self, setRgbBlendOperation: blend_operation] }
    }

    pub fn source_alpha_blend_factor(&self) -> MTLBlendFactor {
        unsafe { msg_send![self, sourceAlphaBlendFactor] }
    }

    pub fn set_source_alpha_blend_factor(&self, blend_factor: MTLBlendFactor) {
        unsafe { msg_send![self, setSourceAlphaBlendFactor: blend_factor] }
    }

    pub fn destination_alpha_blend_factor(&self) -> MTLBlendFactor {
        unsafe { msg_send![self, destinationAlphaBlendFactor] }
    }

    pub fn set_destination_alpha_blend_factor(&self, blend_factor: MTLBlendFactor) {
        unsafe { msg_send![self, setDestinationAlphaBlendFactor: blend_factor] }
    }

    pub fn alpha_blend_operation(&self) -> MTLBlendOperation {
        unsafe { msg_send![self, alphaBlendOperation] }
    }

    pub fn set_alpha_blend_operation(&self, blend_operation: MTLBlendOperation) {
        unsafe { msg_send![self, setAlphaBlendOperation: blend_operation] }
    }

    pub fn write_mask(&self) -> MTLColorWriteMask {
        unsafe { msg_send![self, writeMask] }
    }

    pub fn set_write_mask(&self, mask: MTLColorWriteMask) {
        unsafe { msg_send![self, setWriteMask: mask] }
    }
}

pub enum MTLRenderPipelineReflection {}

foreign_obj_type! {
    type CType = MTLRenderPipelineReflection;
    pub struct RenderPipelineReflection;
    pub struct RenderPipelineReflectionRef;
}

impl RenderPipelineReflection {
    #[cfg(feature = "private")]
    pub unsafe fn new(
        vertex_data: *mut std::ffi::c_void,
        fragment_data: *mut std::ffi::c_void,
        vertex_desc: *mut std::ffi::c_void,
        device: &DeviceRef,
        options: u64,
        flags: u64,
    ) -> Self {
        let class = class!(MTLRenderPipelineReflection);
        let this: RenderPipelineReflection = msg_send![class, alloc];
        let this_alias: *mut Object = msg_send![this.as_ref(), initWithVertexData:vertex_data
                                                                fragmentData:fragment_data
                                                serializedVertexDescriptor:vertex_desc
                                                                    device:device
                                                                    options:options
                                                                        flags:flags];
        if this_alias.is_null() {
            panic!("[MTLRenderPipelineReflection init] failed");
        }
        this
    }
}

impl RenderPipelineReflectionRef {
    pub fn fragment_arguments(&self) -> &Array<Argument> {
        unsafe { msg_send![self, fragmentArguments] }
    }

    pub fn vertex_arguments(&self) -> &Array<Argument> {
        unsafe { msg_send![self, vertexArguments] }
    }
}

pub enum MTLRenderPipelineDescriptor {}

foreign_obj_type! {
    type CType = MTLRenderPipelineDescriptor;
    pub struct RenderPipelineDescriptor;
    pub struct RenderPipelineDescriptorRef;
}

impl RenderPipelineDescriptor {
    pub fn new() -> Self {
        unsafe {
            let class = class!(MTLRenderPipelineDescriptor);
            msg_send![class, new]
        }
    }
}

impl RenderPipelineDescriptorRef {
    pub fn label(&self) -> &str {
        unsafe {
            let label = msg_send![self, label];
            crate::nsstring_as_str(label)
        }
    }

    pub fn set_label(&self, label: &str) {
        unsafe {
            let nslabel = crate::nsstring_from_str(label);
            let () = msg_send![self, setLabel: nslabel];
        }
    }

    pub fn vertex_function(&self) -> Option<&FunctionRef> {
        unsafe { msg_send![self, vertexFunction] }
    }

    pub fn set_vertex_function(&self, function: Option<&FunctionRef>) {
        unsafe { msg_send![self, setVertexFunction: function] }
    }

    pub fn fragment_function(&self) -> Option<&FunctionRef> {
        unsafe { msg_send![self, fragmentFunction] }
    }

    pub fn set_fragment_function(&self, function: Option<&FunctionRef>) {
        unsafe { msg_send![self, setFragmentFunction: function] }
    }

    pub fn vertex_descriptor(&self) -> Option<&VertexDescriptorRef> {
        unsafe { msg_send![self, vertexDescriptor] }
    }

    pub fn set_vertex_descriptor(&self, descriptor: Option<&VertexDescriptorRef>) {
        unsafe { msg_send![self, setVertexDescriptor: descriptor] }
    }

    pub fn sample_count(&self) -> NSUInteger {
        unsafe { msg_send![self, sampleCount] }
    }

    pub fn set_sample_count(&self, count: NSUInteger) {
        unsafe { msg_send![self, setSampleCount: count] }
    }

    pub fn max_vertex_amplification_count(&self) -> NSUInteger {
        unsafe { msg_send![self, maxVertexAmplificationCount] }
    }

    pub fn set_max_vertex_amplification_count(&self, count: NSUInteger) {
        unsafe { msg_send![self, setMaxVertexAmplificationCount: count] }
    }

    pub fn is_alpha_to_coverage_enabled(&self) -> bool {
        unsafe {
            match msg_send![self, isAlphaToCoverageEnabled] {
                YES => true,
                NO => false,
                _ => unreachable!(),
            }
        }
    }

    pub fn set_alpha_to_coverage_enabled(&self, enabled: bool) {
        unsafe { msg_send![self, setAlphaToCoverageEnabled: enabled] }
    }

    pub fn is_alpha_to_one_enabled(&self) -> bool {
        unsafe {
            match msg_send![self, isAlphaToOneEnabled] {
                YES => true,
                NO => false,
                _ => unreachable!(),
            }
        }
    }

    pub fn set_alpha_to_one_enabled(&self, enabled: bool) {
        unsafe { msg_send![self, setAlphaToOneEnabled: enabled] }
    }

    pub fn is_rasterization_enabled(&self) -> bool {
        unsafe {
            match msg_send![self, isRasterizationEnabled] {
                YES => true,
                NO => false,
                _ => unreachable!(),
            }
        }
    }

    pub fn set_rasterization_enabled(&self, enabled: bool) {
        unsafe { msg_send![self, setRasterizationEnabled: enabled] }
    }

    pub fn color_attachments(&self) -> &RenderPipelineColorAttachmentDescriptorArrayRef {
        unsafe { msg_send![self, colorAttachments] }
    }

    pub fn depth_attachment_pixel_format(&self) -> MTLPixelFormat {
        unsafe { msg_send![self, depthAttachmentPixelFormat] }
    }

    pub fn set_depth_attachment_pixel_format(&self, pixel_format: MTLPixelFormat) {
        unsafe { msg_send![self, setDepthAttachmentPixelFormat: pixel_format] }
    }

    pub fn stencil_attachment_pixel_format(&self) -> MTLPixelFormat {
        unsafe { msg_send![self, stencilAttachmentPixelFormat] }
    }

    pub fn set_stencil_attachment_pixel_format(&self, pixel_format: MTLPixelFormat) {
        unsafe { msg_send![self, setStencilAttachmentPixelFormat: pixel_format] }
    }

    pub fn input_primitive_topology(&self) -> MTLPrimitiveTopologyClass {
        unsafe { msg_send![self, inputPrimitiveTopology] }
    }

    pub fn set_input_primitive_topology(&self, topology: MTLPrimitiveTopologyClass) {
        unsafe { msg_send![self, setInputPrimitiveTopology: topology] }
    }

    #[cfg(feature = "private")]
    pub unsafe fn serialize_vertex_data(&self) -> *mut std::ffi::c_void {
        use std::ptr;
        let flags = 0;
        let err: *mut Object = ptr::null_mut();
        msg_send![self, newSerializedVertexDataWithFlags:flags
                                                    error:err]
    }

    #[cfg(feature = "private")]
    pub unsafe fn serialize_fragment_data(&self) -> *mut std::ffi::c_void {
        msg_send![self, serializeFragmentData]
    }

    pub fn support_indirect_command_buffers(&self) -> bool {
        unsafe {
            match msg_send![self, supportIndirectCommandBuffers] {
                YES => true,
                NO => false,
                _ => unreachable!(),
            }
        }
    }

    pub fn set_support_indirect_command_buffers(&self, support: bool) {
        unsafe { msg_send![self, setSupportIndirectCommandBuffers: support] }
    }

    pub fn vertex_buffers(&self) -> Option<&PipelineBufferDescriptorArrayRef> {
        unsafe { msg_send![self, vertexBuffers] }
    }

    pub fn fragment_buffers(&self) -> Option<&PipelineBufferDescriptorArrayRef> {
        unsafe { msg_send![self, fragmentBuffers] }
    }

    pub fn reset(&self) {
        unsafe { msg_send![self, reset] }
    }
}

pub enum MTLRenderPipelineState {}

foreign_obj_type! {
    type CType = MTLRenderPipelineState;
    pub struct RenderPipelineState;
    pub struct RenderPipelineStateRef;
}

impl RenderPipelineStateRef {
    pub fn device(&self) -> &DeviceRef {
        unsafe { msg_send![self, device] }
    }

    pub fn label(&self) -> &str {
        unsafe {
            let label = msg_send![self, label];
            crate::nsstring_as_str(label)
        }
    }

    pub fn set_label(&self, label: &str) {
        unsafe {
            let nslabel = crate::nsstring_from_str(label);
            let () = msg_send![self, setLabel: nslabel];
        }
    }
}

pub enum MTLRenderPipelineColorAttachmentDescriptorArray {}

foreign_obj_type! {
    type CType = MTLRenderPipelineColorAttachmentDescriptorArray;
    pub struct RenderPipelineColorAttachmentDescriptorArray;
    pub struct RenderPipelineColorAttachmentDescriptorArrayRef;
}

impl RenderPipelineColorAttachmentDescriptorArrayRef {
    pub fn object_at(
        &self,
        index: NSUInteger,
    ) -> Option<&RenderPipelineColorAttachmentDescriptorRef> {
        unsafe { msg_send![self, objectAtIndexedSubscript: index] }
    }

    pub fn set_object_at(
        &self,
        index: NSUInteger,
        attachment: Option<&RenderPipelineColorAttachmentDescriptorRef>,
    ) {
        unsafe {
            msg_send![self, setObject:attachment
                   atIndexedSubscript:index]
        }
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io;
use std::io::Write;
#[cfg(windows)]
use std::io::{Seek, SeekFrom};
use std::path::Path;
#[cfg(unix)]
use std::os::unix::fs::FileExt;
#[cfg(windows)]
use std::os::windows::fs::FileExt;

use super::{ReadAt, WriteAt};

/// A wrapper for `File` that provides optimized random access through
/// `ReadAt` and `WriteAt`.
///
/// * On Unix the operating system is advised that reads will be in random
///   order (`FADV_RANDOM`).
/// * On Windows the implementation is orders of magnitude faster than `ReadAt`
///   directly on `File`.
///
/// # Examples
///
/// Read the fifth 512-byte sector of a file:
///
/// ```
/// # use std::error::Error;
/// #
/// # fn try_main() -> Result<(), Box<Error>> {
/// use positioned_io::{RandomAccessFile, ReadAt};
///
/// // open a file (note: binding does not need to be mut)
/// let raf = RandomAccessFile::open("tests/pi.txt")?;
///
/// // read up to 512 bytes
/// let mut buf = [0; 512];
/// let bytes_read = raf.read_at(2048, &mut buf)?;
/// #     assert!(buf.starts_with(b"4"));
/// #     Ok(())
/// # }
/// #
/// # fn main() {
/// #     try_main().unwrap();
/// # }
#[derive(Debug)]
pub struct RandomAccessFile {
    file: File,
    #[cfg(not(unix))]
    pos: u64,
}

impl RandomAccessFile {
    /// [Opens](https://doc.rust-lang.org/std/fs/struct.File.html#method.open)
    /// a file for random access.
    pub fn open<P: AsRef<Path>>(path: P) -> io::Result<RandomAccessFile> {
        RandomAccessFile::try_new(File::open(path)?)
    }

    /// Creates a `RandomAccessFile` wrapper around a `File`.
    pub fn try_new(file: File) -> io::Result<RandomAccessFile> {
        RandomAccessFile::try_new_impl(file)
    }

    #[cfg(unix)]
    fn try_new_impl(file: File) -> io::Result<RandomAccessFile> {
        unsafe {
            use std::os::unix::io::AsRawFd;
            libc::posix_fadvise(file.as_raw_fd(), 0, file.metadata()?.len() as i64, libc::POSIX_FADV_RANDOM);
        }

        Ok(RandomAccessFile { file })
    }

    #[cfg(not(unix))]
    fn try_new_impl(file: File) -> io::Result<RandomAccessFile> {
        Ok(RandomAccessFile {
            file,
            pos: file.seek(SeekFrom::Current(0))?,
        })
    }

    /// Tries to unwrap the inner `File`.
    pub fn try_into_inner(self) -> Result<File, (RandomAccessFile, io::Error)> {
        RandomAccessFile::try_into_inner_impl(self)
    }

    #[cfg(unix)]
    fn try_into_inner_impl(self) -> Result<File, (RandomAccessFile, io::Error)> {
        Ok(self.file)
    }

    #[cfg(not(unix))]
    fn try_into_inner_impl(self) -> Result<File, (RandomAccessFile, io::Error)> {
        match self.file.seek(SeekFrom::Start(self.pos)) {
            Ok(_) => Ok(self.file),
            Err(err) => Err((self, err)),
        }
    }
}

#[cfg(unix)]
impl ReadAt for RandomAccessFile {
    #[inline]
    fn read_at(&self, pos: u64, buf: &mut [u8]) -> io::Result<usize> {
        FileExt::read_at(&self.file, buf, pos)
    }
}

#[cfg(unix)]
impl WriteAt for RandomAccessFile {
    fn write_at(&mut self, pos: u64, buf: &[u8]) -> io::Result<usize> {
        FileExt::write_at(&self.file, buf, pos)
    }

    fn flush(&mut self) -> io::Result<()> {
        Write::flush(&mut self.file)
    }
}

#[cfg(windows)]
impl ReadAt for RandomAccessFile {
    #[inline]
    fn read_at(&self, pos: u64, buf: &mut [u8]) -> io::Result<usize> {
        FileExt::seek_read(&self.file, buf, pos)
    }
}

#[cfg(windows)]
impl WriteAt for RandomAccessFile {
    fn write_at(&mut self, pos: u64, buf: &[u8]) -> io::Result<usize> {
        FileExt::seek_write(&self.file, buf, pos)
    }

    fn flush(&mut self) -> io::Result<()> {
        Write::flush(&mut self.file)
    }
}
<commit_msg>yet another blind fix for windows<commit_after>use std::fs::File;
use std::io;
use std::io::Write;
#[cfg(windows)]
use std::io::{Seek, SeekFrom};
use std::path::Path;
#[cfg(unix)]
use std::os::unix::fs::FileExt;
#[cfg(windows)]
use std::os::windows::fs::FileExt;

use super::{ReadAt, WriteAt};

/// A wrapper for `File` that provides optimized random access through
/// `ReadAt` and `WriteAt`.
///
/// * On Unix the operating system is advised that reads will be in random
///   order (`FADV_RANDOM`).
/// * On Windows the implementation is orders of magnitude faster than `ReadAt`
///   directly on `File`.
///
/// # Examples
///
/// Read the fifth 512-byte sector of a file:
///
/// ```
/// # use std::error::Error;
/// #
/// # fn try_main() -> Result<(), Box<Error>> {
/// use positioned_io::{RandomAccessFile, ReadAt};
///
/// // open a file (note: binding does not need to be mut)
/// let raf = RandomAccessFile::open("tests/pi.txt")?;
///
/// // read up to 512 bytes
/// let mut buf = [0; 512];
/// let bytes_read = raf.read_at(2048, &mut buf)?;
/// #     assert!(buf.starts_with(b"4"));
/// #     Ok(())
/// # }
/// #
/// # fn main() {
/// #     try_main().unwrap();
/// # }
#[derive(Debug)]
pub struct RandomAccessFile {
    file: File,
    #[cfg(not(unix))]
    pos: u64,
}

impl RandomAccessFile {
    /// [Opens](https://doc.rust-lang.org/std/fs/struct.File.html#method.open)
    /// a file for random access.
    pub fn open<P: AsRef<Path>>(path: P) -> io::Result<RandomAccessFile> {
        RandomAccessFile::try_new(File::open(path)?)
    }

    /// Creates a `RandomAccessFile` wrapper around a `File`.
    pub fn try_new(file: File) -> io::Result<RandomAccessFile> {
        RandomAccessFile::try_new_impl(file)
    }

    #[cfg(unix)]
    fn try_new_impl(file: File) -> io::Result<RandomAccessFile> {
        unsafe {
            use std::os::unix::io::AsRawFd;
            libc::posix_fadvise(file.as_raw_fd(), 0, file.metadata()?.len() as i64, libc::POSIX_FADV_RANDOM);
        }

        Ok(RandomAccessFile { file })
    }

    #[cfg(not(unix))]
    fn try_new_impl(mut file: File) -> io::Result<RandomAccessFile> {
        let pos = file.seek(SeekFrom::Current(0))?;
        Ok(RandomAccessFile { file, pos })
    }

    /// Tries to unwrap the inner `File`.
    pub fn try_into_inner(self) -> Result<File, (RandomAccessFile, io::Error)> {
        RandomAccessFile::try_into_inner_impl(self)
    }

    #[cfg(unix)]
    fn try_into_inner_impl(self) -> Result<File, (RandomAccessFile, io::Error)> {
        Ok(self.file)
    }

    #[cfg(not(unix))]
    fn try_into_inner_impl(mut self) -> Result<File, (RandomAccessFile, io::Error)> {
        match self.file.seek(SeekFrom::Start(self.pos)) {
            Ok(_) => Ok(self.file),
            Err(err) => Err((self, err)),
        }
    }
}

#[cfg(unix)]
impl ReadAt for RandomAccessFile {
    #[inline]
    fn read_at(&self, pos: u64, buf: &mut [u8]) -> io::Result<usize> {
        FileExt::read_at(&self.file, buf, pos)
    }
}

#[cfg(unix)]
impl WriteAt for RandomAccessFile {
    fn write_at(&mut self, pos: u64, buf: &[u8]) -> io::Result<usize> {
        FileExt::write_at(&self.file, buf, pos)
    }

    fn flush(&mut self) -> io::Result<()> {
        Write::flush(&mut self.file)
    }
}

#[cfg(windows)]
impl ReadAt for RandomAccessFile {
    #[inline]
    fn read_at(&self, pos: u64, buf: &mut [u8]) -> io::Result<usize> {
        FileExt::seek_read(&self.file, buf, pos)
    }
}

#[cfg(windows)]
impl WriteAt for RandomAccessFile {
    fn write_at(&mut self, pos: u64, buf: &[u8]) -> io::Result<usize> {
        FileExt::seek_write(&self.file, buf, pos)
    }

    fn flush(&mut self) -> io::Result<()> {
        Write::flush(&mut self.file)
    }
}
<|endoftext|>


<commit_before>use std::result;

use collections::{Vec, String};

use byteorder::{ByteOrder, BigEndian, LittleEndian};

use serde::ser::{SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeMap,
                 SerializeTupleStruct};

use serde;

use defs::*;
use error::*;
use seq_serializer::*;
use map_variant_serializer::*;

pub struct Serializer<F: FnMut(&[u8]) -> Result<()>> {
    output: F,
}

impl<F: FnMut(&[u8]) -> Result<()>> Serializer<F> {
    pub const fn new(output: F) -> Serializer<F> {
        Serializer { output: output }
    }

    fn output(&mut self, buf: &[u8]) -> Result<()> {
        self.output.call_mut((buf,))
    }
}

impl<F: FnMut(&[u8]) -> Result<()>> serde::Serializer for Serializer<F> {
    type Ok = ();
    type Error = Error;

    type SerializeSeq = SeqSerializer<F>;
    type SerializeTuple = Self::SerializeSeq;
    type SerializeTupleStruct = Self::SerializeTuple;
    type SerializeTupleVariant = Self::SerializeTuple;

    type SerializeMap = SeqSerializer<F>;
    type SerializeStruct = Self::SerializeMap;
    type SerializeStructVariant = MapVariantSerializer<F>;

    fn serialize_bool(mut self, v: bool) -> Result<()> {
        if v {
            (self.output)(&[TRUE])
        } else {
            (self.output)(&[FALSE])
        }
    }

    fn serialize_i64(mut self, value: i64) -> Result<()> {
        if value >= FIXINT_MIN as i64 && value <= FIXINT_MAX as i64 {
            let mut buf = [0; U16_BYTES];
            LittleEndian::write_i16(&mut buf, value as i16);
            (self.output)(&buf[..1])
        } else if value >= i8::min_value() as i64 && value <= i8::max_value() as i64 {
            let mut buf = [0; U16_BYTES];
            LittleEndian::write_i16(&mut buf, value as i16);
            (self.output)(&[INT8, buf[0]])
        } else if value >= 0 && value <= u8::max_value() as i64 {
            let mut buf = [0; U16_BYTES];
            LittleEndian::write_i16(&mut buf, value as i16);
            (self.output)(&[UINT8, buf[0]])
        } else if value >= i16::min_value() as i64 && value <= i16::max_value() as i64 {
            let mut buf = [INT16; U16_BYTES + 1];
            BigEndian::write_i16(&mut buf[1..], value as i16);
            (self.output)(&buf)
        } else if value >= 0 && value <= u16::max_value() as i64 {
            let mut buf = [UINT16; U16_BYTES + 1];
            BigEndian::write_u16(&mut buf[1..], value as u16);
            (self.output)(&buf)
        } else if value >= i32::min_value() as i64 && value <= i32::max_value() as i64 {
            let mut buf = [INT32; U32_BYTES + 1];
            BigEndian::write_i32(&mut buf[1..], value as i32);
            (self.output)(&buf)
        } else if value >= 0 && value <= u32::max_value() as i64 {
            let mut buf = [UINT32; U16_BYTES + 1];
            BigEndian::write_u32(&mut buf[1..], value as u32);
            (self.output)(&buf)
        } else {
            let mut buf = [INT64; U64_BYTES + 1];
            BigEndian::write_i64(&mut buf[1..], value);
            (self.output)(&buf)
        }
    }

    fn serialize_i8(self, value: i8) -> Result<()> {
        self.serialize_i64(value as i64)
    }

    fn serialize_i16(self, value: i16) -> Result<()> {
        self.serialize_i64(value as i64)
    }

    fn serialize_i32(self, value: i32) -> Result<()> {
        self.serialize_i64(value as i64)
    }

    fn serialize_u64(mut self, value: u64) -> Result<()> {
        if value <= FIXINT_MAX as u64 {
            (self.output)(&[value as u8])
        } else if value <= u8::max_value() as u64 {
            (self.output)(&[UINT8, value as u8])
        } else if value <= u16::max_value() as u64 {
            let mut buf = [UINT16; U16_BYTES + 1];
            BigEndian::write_u16(&mut buf[1..], value as u16);
            (self.output)(&buf)
        } else if value <= u32::max_value() as u64 {
            let mut buf = [UINT32; U32_BYTES + 1];
            BigEndian::write_u32(&mut buf[1..], value as u32);
            (self.output)(&buf)
        } else {
            let mut buf = [UINT64; U64_BYTES + 1];
            BigEndian::write_u64(&mut buf[1..], value);
            (self.output)(&buf)
        }
    }

    fn serialize_u8(self, value: u8) -> Result<()> {
        self.serialize_u64(value as u64)
    }

    fn serialize_u16(self, value: u16) -> Result<()> {
        self.serialize_u64(value as u64)
    }

    fn serialize_u32(self, value: u32) -> Result<()> {
        self.serialize_u64(value as u64)
    }

    fn serialize_f32(mut self, value: f32) -> Result<()> {
        let mut buf = [FLOAT32; U32_BYTES + 1];
        BigEndian::write_f32(&mut buf[1..], value);
        (self.output)(&buf)
    }

    fn serialize_f64(mut self, value: f64) -> Result<()> {
        let mut buf = [FLOAT64; U64_BYTES + 1];
        BigEndian::write_f64(&mut buf[1..], value);
        (self.output)(&buf)
    }

    fn serialize_str(mut self, value: &str) -> Result<()> {
        if value.len() <= MAX_FIXSTR {
            try!((self.output)(&[value.len() as u8 | FIXSTR_MASK]));
        } else if value.len() <= MAX_STR8 {
            try!((self.output)(&[STR8, value.len() as u8]));
        } else if value.len() <= MAX_STR16 {
            let mut buf = [STR16; U16_BYTES + 1];
            BigEndian::write_u16(&mut buf[1..], value.len() as u16);
            try!((self.output)(&buf));
        } else if value.len() <= MAX_STR32 {
            let mut buf = [STR32; U32_BYTES + 1];
            BigEndian::write_u32(&mut buf[1..], value.len() as u32);
            try!((self.output)(&buf));
        } else {
            return Err(Error::simple(Reason::TooBig));
        }

        (self.output)(value.as_bytes())
    }

    fn serialize_char(self, v: char) -> Result<()> {
        let mut string = String::new();
        string.push(v);

        self.serialize_str(&*string)
    }

    fn serialize_unit(mut self) -> Result<()> {
        (self.output)(&[NIL])
    }

    fn serialize_unit_struct(self, _: &'static str) -> Result<()> {
        self.serialize_unit()
    }

    fn serialize_unit_variant(self, _: &'static str, index: usize, _: &'static str) -> Result<()> {
        self.serialize_u64(index as u64)
    }

    fn serialize_newtype_struct<T>(self, name: &'static str, value: &T) -> Result<()>
        where T: ?Sized + serde::Serialize
    {
        let mut seq = self.serialize_tuple_struct(name, 1)?;
        SerializeTupleStruct::serialize_field(&mut seq, &value)?;
        SerializeTupleStruct::end(seq)
    }

    fn serialize_newtype_variant<T>(self,
                                    name: &'static str,
                                    variant_index: usize,
                                    variant: &'static str,
                                    value: &T)
                                    -> Result<()>
        where T: ?Sized + serde::Serialize
    {
        let mut seq = self.serialize_tuple_variant(name, variant_index, variant, 1)?;
        SerializeTupleStruct::serialize_field(&mut seq, &value)?;
        SerializeTupleStruct::end(seq)
    }

    fn serialize_none(self) -> Result<()> {
        self.serialize_unit()
    }

    fn serialize_some<V>(self, value: &V) -> Result<()>
        where V: ?Sized + serde::Serialize
    {
        value.serialize(self)
    }

    fn serialize_seq(self, len: Option<usize>) -> result::Result<Self::SerializeSeq, Error> {
        Ok(SeqSerializer::new(self.output))
    }

    fn serialize_seq_fixed_size(self, size: usize) -> result::Result<Self::SerializeSeq, Error> {
        self.serialize_seq(Some(size))
    }

    fn serialize_tuple(self, len: usize) -> result::Result<Self::SerializeTuple, Error> {
        self.serialize_seq_fixed_size(len)
    }

    fn serialize_tuple_struct(self,
                              _: &'static str,
                              len: usize)
                              -> result::Result<Self::SerializeTupleStruct, Error> {
        self.serialize_tuple(len)
    }

    fn serialize_tuple_variant(self,
                               _: &'static str,
                               index: usize,
                               _: &'static str,
                               len: usize)
                               -> result::Result<Self::SerializeTupleVariant, Error> {
        let mut seq = self.serialize_tuple(len + 1)?;
        // serialize the variant index as an extra element at the front
        seq.serialize_element(&index)?;

        Ok(seq)
    }

    fn serialize_map(self, len: Option<usize>) -> result::Result<Self::SerializeMap, Error> {
        Ok(SeqSerializer::new(self.output))
    }

    fn serialize_struct(self,
                        _: &'static str,
                        len: usize)
                        -> result::Result<Self::SerializeStruct, Error> {
        self.serialize_map(Some(len))
    }

    fn serialize_struct_variant(self,
                                name: &'static str,
                                index: usize,
                                _: &'static str,
                                _: usize)
                                -> result::Result<Self::SerializeStructVariant, Error> {
        Ok(MapVariantSerializer::new(index, self.output))
    }

    fn serialize_bytes(mut self, value: &[u8]) -> Result<()> {
        if value.len() <= MAX_BIN8 {
            try!((self.output)(&[BIN8, value.len() as u8]));
        } else if value.len() <= MAX_BIN16 {
            let mut buf = [BIN16; U16_BYTES + 1];
            BigEndian::write_u16(&mut buf[1..], value.len() as u16);
            try!((self.output)(&buf));
        } else if value.len() <= MAX_BIN32 {
            let mut buf = [BIN32; U32_BYTES + 1];
            BigEndian::write_u32(&mut buf[1..], value.len() as u32);
            try!((self.output)(&buf));
        } else {
            return Err(Error::simple(Reason::TooBig));
        }

        (self.output)(value)
    }
}

#[cfg(test)]
mod test {
    use collections::{Vec, String};
    use collections::btree_map::BTreeMap;

    #[test]
    fn positive_fixint_test() {
        let v: u8 = 23;
        assert_eq!(::to_bytes(v).unwrap(), &[0x17]);
    }
    #[test]
    fn negative_fixint_test() {
        let v: i8 = -5;
        assert_eq!(::to_bytes(v).unwrap(), &[0xfb]);
    }

    #[test]
    fn uint8_test() {
        let v: u8 = 154;
        assert_eq!(::to_bytes(v).unwrap(), &[0xcc, 0x9a]);
    }

    #[test]
    fn fixstr_test() {
        let s: &str = "Hello World!";
        assert_eq!(::to_bytes(s).unwrap(),
                   &[0xac, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21]);
    }

    #[test]
    fn str8_test() {
        let s: &str = "The quick brown fox jumps over the lazy dog";
        let mut fixture: Vec<u8> = vec![];
        fixture.push(0xd9);
        fixture.push(s.len() as u8);
        fixture.extend_from_slice(s.as_bytes());
        assert_eq!(::to_bytes(s).unwrap(), fixture);
    }

    #[test]
    fn fixarr_test() {
        let v: Vec<u8> = vec![5, 8, 20, 231];
        assert_eq!(::to_bytes(v).unwrap(),
                   &[0x94, 0x05, 0x08, 0x14, 0xcc, 0xe7]);
    }

    #[test]
    fn array16_test() {
        let v: Vec<isize> = vec![-5, 16, 101, -45, 184, 89, 62, -233, -33, 304, 76, 90, 23, 108,
                                 45, -3, 2];
        assert_eq!(::to_bytes(v).unwrap(),
                   &[0xdc, 0x00, 0x11, 0xfb, 0x10, 0x65, 0xd0, 0xd3, 0xcc, 0xb8, 0x59, 0x3e,
                     0xd1, 0xff, 0x17, 0xd0, 0xdf, 0xd1, 0x01, 0x30, 0x4c, 0x5a, 0x17, 0x6c,
                     0x2d, 0xfd, 0x02]);
    }

    #[test]
    fn fixmap_test() {
        let mut map: BTreeMap<String, usize> = BTreeMap::new();
        map.insert("one".into(), 1);
        map.insert("two".into(), 2);
        map.insert("three".into(), 3);
        assert_eq!(::to_bytes(map).unwrap(),
                   &[0x83, 0xa3, 0x6f, 0x6e, 0x65, 0x01, 0xa5, 0x74, 0x68, 0x72, 0x65, 0x65,
                     0x03, 0xa3, 0x74, 0x77, 0x6f, 0x02]);
    }
}
<commit_msg>Remove some dead code<commit_after>use std::result;

use collections::{Vec, String};

use byteorder::{ByteOrder, BigEndian, LittleEndian};

use serde::ser::{SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeMap,
                 SerializeTupleStruct};

use serde;

use defs::*;
use error::*;
use seq_serializer::*;
use map_variant_serializer::*;

pub struct Serializer<F: FnMut(&[u8]) -> Result<()>> {
    output: F,
}

impl<F: FnMut(&[u8]) -> Result<()>> Serializer<F> {
    pub const fn new(output: F) -> Serializer<F> {
        Serializer { output: output }
    }
}

impl<F: FnMut(&[u8]) -> Result<()>> serde::Serializer for Serializer<F> {
    type Ok = ();
    type Error = Error;

    type SerializeSeq = SeqSerializer<F>;
    type SerializeTuple = Self::SerializeSeq;
    type SerializeTupleStruct = Self::SerializeTuple;
    type SerializeTupleVariant = Self::SerializeTuple;

    type SerializeMap = SeqSerializer<F>;
    type SerializeStruct = Self::SerializeMap;
    type SerializeStructVariant = MapVariantSerializer<F>;

    fn serialize_bool(mut self, v: bool) -> Result<()> {
        if v {
            (self.output)(&[TRUE])
        } else {
            (self.output)(&[FALSE])
        }
    }

    fn serialize_i64(mut self, value: i64) -> Result<()> {
        if value >= FIXINT_MIN as i64 && value <= FIXINT_MAX as i64 {
            let mut buf = [0; U16_BYTES];
            LittleEndian::write_i16(&mut buf, value as i16);
            (self.output)(&buf[..1])
        } else if value >= i8::min_value() as i64 && value <= i8::max_value() as i64 {
            let mut buf = [0; U16_BYTES];
            LittleEndian::write_i16(&mut buf, value as i16);
            (self.output)(&[INT8, buf[0]])
        } else if value >= 0 && value <= u8::max_value() as i64 {
            let mut buf = [0; U16_BYTES];
            LittleEndian::write_i16(&mut buf, value as i16);
            (self.output)(&[UINT8, buf[0]])
        } else if value >= i16::min_value() as i64 && value <= i16::max_value() as i64 {
            let mut buf = [INT16; U16_BYTES + 1];
            BigEndian::write_i16(&mut buf[1..], value as i16);
            (self.output)(&buf)
        } else if value >= 0 && value <= u16::max_value() as i64 {
            let mut buf = [UINT16; U16_BYTES + 1];
            BigEndian::write_u16(&mut buf[1..], value as u16);
            (self.output)(&buf)
        } else if value >= i32::min_value() as i64 && value <= i32::max_value() as i64 {
            let mut buf = [INT32; U32_BYTES + 1];
            BigEndian::write_i32(&mut buf[1..], value as i32);
            (self.output)(&buf)
        } else if value >= 0 && value <= u32::max_value() as i64 {
            let mut buf = [UINT32; U16_BYTES + 1];
            BigEndian::write_u32(&mut buf[1..], value as u32);
            (self.output)(&buf)
        } else {
            let mut buf = [INT64; U64_BYTES + 1];
            BigEndian::write_i64(&mut buf[1..], value);
            (self.output)(&buf)
        }
    }

    fn serialize_i8(self, value: i8) -> Result<()> {
        self.serialize_i64(value as i64)
    }

    fn serialize_i16(self, value: i16) -> Result<()> {
        self.serialize_i64(value as i64)
    }

    fn serialize_i32(self, value: i32) -> Result<()> {
        self.serialize_i64(value as i64)
    }

    fn serialize_u64(mut self, value: u64) -> Result<()> {
        if value <= FIXINT_MAX as u64 {
            (self.output)(&[value as u8])
        } else if value <= u8::max_value() as u64 {
            (self.output)(&[UINT8, value as u8])
        } else if value <= u16::max_value() as u64 {
            let mut buf = [UINT16; U16_BYTES + 1];
            BigEndian::write_u16(&mut buf[1..], value as u16);
            (self.output)(&buf)
        } else if value <= u32::max_value() as u64 {
            let mut buf = [UINT32; U32_BYTES + 1];
            BigEndian::write_u32(&mut buf[1..], value as u32);
            (self.output)(&buf)
        } else {
            let mut buf = [UINT64; U64_BYTES + 1];
            BigEndian::write_u64(&mut buf[1..], value);
            (self.output)(&buf)
        }
    }

    fn serialize_u8(self, value: u8) -> Result<()> {
        self.serialize_u64(value as u64)
    }

    fn serialize_u16(self, value: u16) -> Result<()> {
        self.serialize_u64(value as u64)
    }

    fn serialize_u32(self, value: u32) -> Result<()> {
        self.serialize_u64(value as u64)
    }

    fn serialize_f32(mut self, value: f32) -> Result<()> {
        let mut buf = [FLOAT32; U32_BYTES + 1];
        BigEndian::write_f32(&mut buf[1..], value);
        (self.output)(&buf)
    }

    fn serialize_f64(mut self, value: f64) -> Result<()> {
        let mut buf = [FLOAT64; U64_BYTES + 1];
        BigEndian::write_f64(&mut buf[1..], value);
        (self.output)(&buf)
    }

    fn serialize_str(mut self, value: &str) -> Result<()> {
        if value.len() <= MAX_FIXSTR {
            try!((self.output)(&[value.len() as u8 | FIXSTR_MASK]));
        } else if value.len() <= MAX_STR8 {
            try!((self.output)(&[STR8, value.len() as u8]));
        } else if value.len() <= MAX_STR16 {
            let mut buf = [STR16; U16_BYTES + 1];
            BigEndian::write_u16(&mut buf[1..], value.len() as u16);
            try!((self.output)(&buf));
        } else if value.len() <= MAX_STR32 {
            let mut buf = [STR32; U32_BYTES + 1];
            BigEndian::write_u32(&mut buf[1..], value.len() as u32);
            try!((self.output)(&buf));
        } else {
            return Err(Error::simple(Reason::TooBig));
        }

        (self.output)(value.as_bytes())
    }

    fn serialize_char(self, v: char) -> Result<()> {
        let mut string = String::new();
        string.push(v);

        self.serialize_str(&*string)
    }

    fn serialize_unit(mut self) -> Result<()> {
        (self.output)(&[NIL])
    }

    fn serialize_unit_struct(self, _: &'static str) -> Result<()> {
        self.serialize_unit()
    }

    fn serialize_unit_variant(self, _: &'static str, index: usize, _: &'static str) -> Result<()> {
        self.serialize_u64(index as u64)
    }

    fn serialize_newtype_struct<T>(self, name: &'static str, value: &T) -> Result<()>
        where T: ?Sized + serde::Serialize
    {
        let mut seq = self.serialize_tuple_struct(name, 1)?;
        SerializeTupleStruct::serialize_field(&mut seq, &value)?;
        SerializeTupleStruct::end(seq)
    }

    fn serialize_newtype_variant<T>(self,
                                    name: &'static str,
                                    variant_index: usize,
                                    variant: &'static str,
                                    value: &T)
                                    -> Result<()>
        where T: ?Sized + serde::Serialize
    {
        let mut seq = self.serialize_tuple_variant(name, variant_index, variant, 1)?;
        SerializeTupleStruct::serialize_field(&mut seq, &value)?;
        SerializeTupleStruct::end(seq)
    }

    fn serialize_none(self) -> Result<()> {
        self.serialize_unit()
    }

    fn serialize_some<V>(self, value: &V) -> Result<()>
        where V: ?Sized + serde::Serialize
    {
        value.serialize(self)
    }

    fn serialize_seq(self, len: Option<usize>) -> result::Result<Self::SerializeSeq, Error> {
        Ok(SeqSerializer::new(self.output))
    }

    fn serialize_seq_fixed_size(self, size: usize) -> result::Result<Self::SerializeSeq, Error> {
        self.serialize_seq(Some(size))
    }

    fn serialize_tuple(self, len: usize) -> result::Result<Self::SerializeTuple, Error> {
        self.serialize_seq_fixed_size(len)
    }

    fn serialize_tuple_struct(self,
                              _: &'static str,
                              len: usize)
                              -> result::Result<Self::SerializeTupleStruct, Error> {
        self.serialize_tuple(len)
    }

    fn serialize_tuple_variant(self,
                               _: &'static str,
                               index: usize,
                               _: &'static str,
                               len: usize)
                               -> result::Result<Self::SerializeTupleVariant, Error> {
        let mut seq = self.serialize_tuple(len + 1)?;
        // serialize the variant index as an extra element at the front
        seq.serialize_element(&index)?;

        Ok(seq)
    }

    fn serialize_map(self, len: Option<usize>) -> result::Result<Self::SerializeMap, Error> {
        Ok(SeqSerializer::new(self.output))
    }

    fn serialize_struct(self,
                        _: &'static str,
                        len: usize)
                        -> result::Result<Self::SerializeStruct, Error> {
        self.serialize_map(Some(len))
    }

    fn serialize_struct_variant(self,
                                name: &'static str,
                                index: usize,
                                _: &'static str,
                                _: usize)
                                -> result::Result<Self::SerializeStructVariant, Error> {
        Ok(MapVariantSerializer::new(index, self.output))
    }

    fn serialize_bytes(mut self, value: &[u8]) -> Result<()> {
        if value.len() <= MAX_BIN8 {
            try!((self.output)(&[BIN8, value.len() as u8]));
        } else if value.len() <= MAX_BIN16 {
            let mut buf = [BIN16; U16_BYTES + 1];
            BigEndian::write_u16(&mut buf[1..], value.len() as u16);
            try!((self.output)(&buf));
        } else if value.len() <= MAX_BIN32 {
            let mut buf = [BIN32; U32_BYTES + 1];
            BigEndian::write_u32(&mut buf[1..], value.len() as u32);
            try!((self.output)(&buf));
        } else {
            return Err(Error::simple(Reason::TooBig));
        }

        (self.output)(value)
    }
}

#[cfg(test)]
mod test {
    use collections::{Vec, String};
    use collections::btree_map::BTreeMap;

    #[test]
    fn positive_fixint_test() {
        let v: u8 = 23;
        assert_eq!(::to_bytes(v).unwrap(), &[0x17]);
    }
    #[test]
    fn negative_fixint_test() {
        let v: i8 = -5;
        assert_eq!(::to_bytes(v).unwrap(), &[0xfb]);
    }

    #[test]
    fn uint8_test() {
        let v: u8 = 154;
        assert_eq!(::to_bytes(v).unwrap(), &[0xcc, 0x9a]);
    }

    #[test]
    fn fixstr_test() {
        let s: &str = "Hello World!";
        assert_eq!(::to_bytes(s).unwrap(),
                   &[0xac, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21]);
    }

    #[test]
    fn str8_test() {
        let s: &str = "The quick brown fox jumps over the lazy dog";
        let mut fixture: Vec<u8> = vec![];
        fixture.push(0xd9);
        fixture.push(s.len() as u8);
        fixture.extend_from_slice(s.as_bytes());
        assert_eq!(::to_bytes(s).unwrap(), fixture);
    }

    #[test]
    fn fixarr_test() {
        let v: Vec<u8> = vec![5, 8, 20, 231];
        assert_eq!(::to_bytes(v).unwrap(),
                   &[0x94, 0x05, 0x08, 0x14, 0xcc, 0xe7]);
    }

    #[test]
    fn array16_test() {
        let v: Vec<isize> = vec![-5, 16, 101, -45, 184, 89, 62, -233, -33, 304, 76, 90, 23, 108,
                                 45, -3, 2];
        assert_eq!(::to_bytes(v).unwrap(),
                   &[0xdc, 0x00, 0x11, 0xfb, 0x10, 0x65, 0xd0, 0xd3, 0xcc, 0xb8, 0x59, 0x3e,
                     0xd1, 0xff, 0x17, 0xd0, 0xdf, 0xd1, 0x01, 0x30, 0x4c, 0x5a, 0x17, 0x6c,
                     0x2d, 0xfd, 0x02]);
    }

    #[test]
    fn fixmap_test() {
        let mut map: BTreeMap<String, usize> = BTreeMap::new();
        map.insert("one".into(), 1);
        map.insert("two".into(), 2);
        map.insert("three".into(), 3);
        assert_eq!(::to_bytes(map).unwrap(),
                   &[0x83, 0xa3, 0x6f, 0x6e, 0x65, 0x01, 0xa5, 0x74, 0x68, 0x72, 0x65, 0x65,
                     0x03, 0xa3, 0x74, 0x77, 0x6f, 0x02]);
    }
}
<|endoftext|>