<commit_before>//! # Socket code around `libc`
//!
//! ## Notes
//!
//! This module provides a low level one-to-one mapping between `libc` system call wrappers
//! with defaults specific to netlink sockets as well as a higher level API for simplification
//! of netlink code.

use std::io;
use std::os::unix::io::{AsRawFd,IntoRawFd,RawFd};
use std::marker::PhantomData;
use std::mem::{zeroed,size_of};
#[cfg(feature = "stream")]
use std::time::Duration;

use libc::{self,c_int,c_void};
#[cfg(feature = "evented")]
use mio::{self,Evented};
#[cfg(feature = "stream")]
use tokio::prelude::{Async,Stream};

use {Nl,MemRead,MemWrite};
#[cfg(feature = "stream")]
use MAX_NL_LENGTH;
use err::NlError;
use ffi::{NlFamily,GenlId,CtrlCmd,CtrlAttr,CtrlAttrMcastGrp,NlmF};
use genlhdr::GenlHdr;
use nlhdr::{NlHdr,NlAttrHdr};

/// Handle for the socket file descriptor
#[cfg(feature = "stream")]
pub struct NlSocket<I, P> {
    fd: c_int,
    poll: mio::Poll,
    data_type: PhantomData<I>,
    data_payload: PhantomData<P>,
}

/// Handle for the socket file descriptor
#[cfg(not(feature = "stream"))]
pub struct NlSocket<I, P> {
    fd: c_int,
    data_type: PhantomData<I>,
    data_payload: PhantomData<P>,
}

impl<I, P> NlSocket<I, P> where I: Nl, P: Nl {
    /// Wrapper around `socket()` syscall filling in the netlink-specific information
    #[cfg(feature = "stream")]
    pub fn new(proto: NlFamily) -> Result<Self, io::Error> {
        let fd = match unsafe {
            libc::socket(libc::AF_NETLINK, libc::SOCK_RAW, proto.into())
        } {
            i if i >= 0 => Ok(i),
            _ => Err(io::Error::last_os_error()),
        }?;
        let poll = mio::Poll::new()?;
        let socket = NlSocket { fd, poll, data_type: PhantomData, data_payload: PhantomData };
        socket.register(&socket.poll, mio::Token(0), mio::Ready::readable(), mio::PollOpt::edge())?;
        Ok(socket)
    }

    /// Wrapper around `socket()` syscall filling in the netlink-specific information
    #[cfg(not(feature = "stream"))]
    pub fn new(proto: NlFamily) -> Result<Self, io::Error> {
        let fd = match unsafe {
            libc::socket(libc::AF_NETLINK, libc::SOCK_RAW, proto.into())
        } {
            i if i >= 0 => Ok(i),
            _ => Err(io::Error::last_os_error()),
        }?;
        Ok(NlSocket { fd, data_type: PhantomData, data_payload: PhantomData })
    }

    /// Use this function to bind to a netlink ID and subscribe to groups. See netlink(7)
    /// man pages for more information on netlink IDs and groups.
    pub fn bind(&mut self, pid: Option<u32>, groups: Option<u32>) -> Result<(), io::Error> {
        let mut nladdr = unsafe { zeroed::<libc::sockaddr_nl>() };
        nladdr.nl_family = libc::AF_NETLINK as u16;
        nladdr.nl_pid = pid.unwrap_or(0);
        nladdr.nl_groups = groups.unwrap_or(0);
        match unsafe {
            libc::bind(self.fd, &nladdr as *const _ as *const libc::sockaddr,
                       size_of::<libc::sockaddr_nl>() as u32)
        } {
            i if i >= 0 => Ok(()),
            _ => Err(io::Error::last_os_error()),
        }
    }

    /// Send message encoded as byte slice to the netlink ID specified in the netlink header
    /// (`neli::nlhdr::NlHdr`).
    pub fn send(&mut self, buf: MemRead, flags: i32) -> Result<isize, io::Error> {
        match unsafe {
            libc::send(self.fd, buf.as_slice() as *const _ as *const c_void, buf.len(), flags)
        } {
            i if i >= 0 => Ok(i),
            _ => Err(io::Error::last_os_error()),
        }
    }

    /// Receive message encoded as byte slice from the netlink socket.
    pub fn recv<'a>(&mut self, mut buf: MemWrite<'a>, flags: i32)
            -> Result<MemRead<'a>, io::Error> {
        match unsafe {
            libc::recv(self.fd, buf.as_mut_slice() as *mut _ as *mut c_void, buf.len(), flags)
        } {
            i if i >= 0 => Ok(buf.shrink(i as usize).into()),
            _ => Err(io::Error::last_os_error()),
        }
    }

    /// Equivalent of `socket` and `bind` calls.
    pub fn connect(proto: NlFamily, pid: Option<u32>, groups: Option<u32>)
                   -> Result<Self, io::Error> {
        let mut s = try!(NlSocket::new(proto));
        try!(s.bind(pid, groups));
        Ok(s)
    }

    /// Convenience function for resolving a `&str` containing the multicast group name to a
    /// numeric netlink ID
    pub fn resolve_nl_mcast_group(family_name: &str, mcast_name: &str) -> Result<u32, NlError> {
        let mut socket = Self::connect(NlFamily::Generic, None, None)?;
        let attrs = vec![NlAttrHdr::new_str_payload(None, CtrlAttr::FamilyName, family_name)?];
        let genlhdr = GenlHdr::new(CtrlCmd::Getfamily, 2, attrs)?;
        let nlhdr = NlHdr::new(None, GenlId::Ctrl,
                               vec![NlmF::Request, NlmF::Ack], None, None, genlhdr);
        let mut mem_req = MemWrite::new_vec(Some(nlhdr.asize()));
        nlhdr.serialize(&mut mem_req)?;
        socket.send(mem_req.into(), 0)?;

        let mem_resp = MemWrite::new_vec(Some(4096));
        let mut mem_resp_recv = socket.recv(mem_resp, 0)?;
        let nlhdr = NlHdr::<GenlId, GenlHdr<CtrlCmd>>::deserialize(&mut mem_resp_recv)?;
        let mut handle = nlhdr.nl_payload.get_attr_handle::<CtrlAttr>();
        let mcast_groups = handle.get_nested_attributes::<u16>(CtrlAttr::McastGroups)?;
        let mut id = None;
        if let Some(iter) = mcast_groups.iter() {
            for attribute in iter {
                let attribute_len = attribute.nla_len;
                let mut handle = attribute.get_attr_handle();
                let string = handle.get_payload_with::<String>(CtrlAttrMcastGrp::Name,
                    Some(attribute_len as usize))?;
                if string.as_str() == mcast_name {
                    id = handle.get_payload_as::<u32>(CtrlAttrMcastGrp::Id).ok();
                }
            }
        }
        id.ok_or(NlError::new("Failed to resolve multicast group ID"))
    }
}

impl<I, P> AsRawFd for NlSocket<I, P> {
    fn as_raw_fd(&self) -> RawFd {
        self.fd
    }
}

impl<I, P> IntoRawFd for NlSocket<I, P> {
    fn into_raw_fd(self) -> RawFd {
        self.fd
    }
}

#[cfg(feature = "stream")]
impl<I, P> Stream for NlSocket<I, P> where I: Nl, P: Nl {
    type Item = NlHdr<I, P>;
    type Error = ();

    fn poll(&mut self) -> Result<Async<Option<Self::Item>>, Self::Error> {
        let mem = MemWrite::new_vec(Some(MAX_NL_LENGTH));
        let mut events = mio::Events::with_capacity(1);
        match self.poll.poll(&mut events, Some(Duration::from_secs(0))) {
            Ok(_) => (),
            Err(_) => return Err(()),
        };
        if let Some(event) = events.iter().nth(0) {
            if !event.readiness().is_readable() {
                return Ok(Async::NotReady);
            }
        }
        let mut mem_read = match self.recv(mem, 0) {
            Ok(mr) => mr,
            Err(_) => return Err(()),
        };
        if mem_read.as_slice().len() == 0 {
            return Ok(Async::Ready(None));
        }
        let hdr = match NlHdr::<I, P>::deserialize(&mut mem_read) {
            Ok(h) => h,
            Err(_) => return Err(()),
        };
        Ok(Async::Ready(Some(hdr)))
    }
}

#[cfg(feature = "evented")]
impl<I, P> Evented for NlSocket<I, P> {
    fn register(&self, poll: &mio::Poll, token: mio::Token, interest: mio::Ready,
                opts: mio::PollOpt) -> io::Result<()> {
        poll.register(&mio::unix::EventedFd(&self.as_raw_fd()), token, interest, opts)
    }

    fn reregister(&self, poll: &mio::Poll, token: mio::Token, interest: mio::Ready,
                  opts: mio::PollOpt) -> io::Result<()> {
        poll.reregister(&mio::unix::EventedFd(&self.as_raw_fd()), token, interest, opts)
    }

    fn deregister(&self, poll: &mio::Poll) -> io::Result<()> {
        poll.deregister(&mio::unix::EventedFd(&self.as_raw_fd()))
    }
}

impl<I, P> Drop for NlSocket<I, P> {
    /// Closes underlying file descriptor to avoid file descriptor leaks.
    fn drop(&mut self) {
        unsafe { libc::close(self.fd); }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use ffi::{CtrlCmd,Nlmsg};
    use genlhdr::GenlHdr;

    #[test]
    fn test_socket_creation() {
        match NlSocket::<Nlmsg, GenlHdr<CtrlCmd>>::connect(NlFamily::Generic, None, None) {
            Err(_) => panic!(),
            _ => (),
        }
    }
}
<commit_msg>Add send/recv convenience functions<commit_after>//! # Socket code around `libc`
//!
//! ## Notes
//!
//! This module provides a low level one-to-one mapping between `libc` system call wrappers
//! with defaults specific to netlink sockets as well as a higher level API for simplification
//! of netlink code.

use std::io;
use std::os::unix::io::{AsRawFd,IntoRawFd,RawFd};
use std::marker::PhantomData;
use std::mem::{zeroed,size_of};
#[cfg(feature = "stream")]
use std::time::Duration;

use libc::{self,c_int,c_void};
#[cfg(feature = "evented")]
use mio::{self,Evented};
#[cfg(feature = "stream")]
use tokio::prelude::{Async,Stream};

use {Nl,MemRead,MemWrite,MAX_NL_LENGTH};
use err::NlError;
use ffi::{NlFamily,GenlId,CtrlCmd,CtrlAttr,CtrlAttrMcastGrp,NlmF};
use genlhdr::GenlHdr;
use nlhdr::{NlHdr,NlAttrHdr};

/// Handle for the socket file descriptor
#[cfg(feature = "stream")]
pub struct NlSocket<T, P> {
    fd: c_int,
    poll: mio::Poll,
    data_type: PhantomData<T>,
    data_payload: PhantomData<P>,
}

/// Handle for the socket file descriptor
#[cfg(not(feature = "stream"))]
pub struct NlSocket<T, P> {
    fd: c_int,
    data_type: PhantomData<T>,
    data_payload: PhantomData<P>,
}

impl<T, P> NlSocket<T, P> where T: Nl, P: Nl {
    /// Wrapper around `socket()` syscall filling in the netlink-specific information
    #[cfg(feature = "stream")]
    pub fn new(proto: NlFamily) -> Result<Self, io::Error> {
        let fd = match unsafe {
            libc::socket(libc::AF_NETLINK, libc::SOCK_RAW, proto.into())
        } {
            i if i >= 0 => Ok(i),
            _ => Err(io::Error::last_os_error()),
        }?;
        let poll = mio::Poll::new()?;
        let socket = NlSocket { fd, poll, data_type: PhantomData, data_payload: PhantomData };
        socket.register(&socket.poll, mio::Token(0), mio::Ready::readable(), mio::PollOpt::edge())?;
        Ok(socket)
    }

    /// Wrapper around `socket()` syscall filling in the netlink-specific information
    #[cfg(not(feature = "stream"))]
    pub fn new(proto: NlFamily) -> Result<Self, io::Error> {
        let fd = match unsafe {
            libc::socket(libc::AF_NETLINK, libc::SOCK_RAW, proto.into())
        } {
            i if i >= 0 => Ok(i),
            _ => Err(io::Error::last_os_error()),
        }?;
        Ok(NlSocket { fd, data_type: PhantomData, data_payload: PhantomData })
    }

    /// Use this function to bind to a netlink ID and subscribe to groups. See netlink(7)
    /// man pages for more information on netlink IDs and groups.
    pub fn bind(&mut self, pid: Option<u32>, groups: Option<u32>) -> Result<(), io::Error> {
        let mut nladdr = unsafe { zeroed::<libc::sockaddr_nl>() };
        nladdr.nl_family = libc::AF_NETLINK as u16;
        nladdr.nl_pid = pid.unwrap_or(0);
        nladdr.nl_groups = groups.unwrap_or(0);
        match unsafe {
            libc::bind(self.fd, &nladdr as *const _ as *const libc::sockaddr,
                       size_of::<libc::sockaddr_nl>() as u32)
        } {
            i if i >= 0 => Ok(()),
            _ => Err(io::Error::last_os_error()),
        }
    }

    /// Send message encoded as byte slice to the netlink ID specified in the netlink header
    /// (`neli::nlhdr::NlHdr`).
    pub fn send(&mut self, buf: MemRead, flags: i32) -> Result<isize, io::Error> {
        match unsafe {
            libc::send(self.fd, buf.as_slice() as *const _ as *const c_void, buf.len(), flags)
        } {
            i if i >= 0 => Ok(i),
            _ => Err(io::Error::last_os_error()),
        }
    }

    /// Convenience function to send an `NlHdr` struct
    pub fn send_nl(&mut self, msg: NlHdr<T, P>, buf_sz: Option<usize>) -> Result<(), NlError> {
        let mut mem = MemWrite::new_vec(buf_sz.or(Some(MAX_NL_LENGTH)));
        msg.serialize(&mut mem)?;
        self.send(mem.into(), 0)?;
        Ok(())
    }

    /// Receive message encoded as byte slice from the netlink socket.
    pub fn recv<'a>(&mut self, mut buf: MemWrite<'a>, flags: i32)
            -> Result<MemRead<'a>, io::Error> {
        match unsafe {
            libc::recv(self.fd, buf.as_mut_slice() as *mut _ as *mut c_void, buf.len(), flags)
        } {
            i if i >= 0 => Ok(buf.shrink(i as usize).into()),
            _ => Err(io::Error::last_os_error()),
        }
    }

    /// Convenience function to receive an `NlHdr` struct
    pub fn recv_nl(&mut self, buf_sz: Option<usize>) -> Result<NlHdr<T, P>, NlError> {
        let mem_write = MemWrite::new_vec(buf_sz.or(Some(MAX_NL_LENGTH)));
        let mut mem_read = self.recv(mem_write, 0)?;
        Ok(NlHdr::<T, P>::deserialize(&mut mem_read)?)
    }

    /// Equivalent of `socket` and `bind` calls.
    pub fn connect(proto: NlFamily, pid: Option<u32>, groups: Option<u32>)
                   -> Result<Self, io::Error> {
        let mut s = try!(NlSocket::new(proto));
        try!(s.bind(pid, groups));
        Ok(s)
    }
}

impl NlSocket<GenlId, GenlHdr<CtrlCmd>> {
    /// Create generic netlink resolution socket
    pub fn new_genl() -> Result<NlSocket<GenlId, GenlHdr<CtrlCmd>>, io::Error> {
        Self::connect(NlFamily::Generic, None, None)
    }

    fn get_genl_family(&mut self, family_name: &str)
            -> Result<NlHdr<GenlId, GenlHdr<CtrlCmd>>, NlError> {
        let attrs = vec![NlAttrHdr::new_str_payload(None, CtrlAttr::FamilyName, family_name)?];
        let genlhdr = GenlHdr::new(CtrlCmd::Getfamily, 2, attrs)?;
        let nlhdr = NlHdr::new(None, GenlId::Ctrl,
                               vec![NlmF::Request, NlmF::Ack], None, None, genlhdr);
        let mut mem_req = MemWrite::new_vec(Some(nlhdr.asize()));
        nlhdr.serialize(&mut mem_req)?;
        self.send(mem_req.into(), 0)?;

        let mem_resp = MemWrite::new_vec(Some(4096));
        let mut mem_resp_recv = self.recv(mem_resp, 0)?;
        Ok(NlHdr::<GenlId, GenlHdr<CtrlCmd>>::deserialize(&mut mem_resp_recv)?)
    }

    /// Convenience function for resolving a `&str` containing the multicast group name to a
    /// numeric netlink ID
    pub fn resolve_genl_family(&mut self, family_name: &str) -> Result<u16, NlError> {
        let nlhdr = self.get_genl_family(family_name)?;
        let mut handle = nlhdr.nl_payload.get_attr_handle::<CtrlAttr>();
        Ok(handle.get_payload_as::<u16>(CtrlAttr::FamilyId)?)
    }

    /// Convenience function for resolving a `&str` containing the multicast group name to a
    /// numeric netlink ID
    pub fn resolve_nl_mcast_group(&mut self, family_name: &str, mcast_name: &str)
            -> Result<u32, NlError> {
        let nlhdr = self.get_genl_family(family_name)?;
        let mut handle = nlhdr.nl_payload.get_attr_handle::<CtrlAttr>();
        let mut mcast_groups = handle.get_nested_attributes::<u16>(CtrlAttr::McastGroups)?;
        mcast_groups.parse_nested_attributes()?;
        let mut id = None;
        if let Some(iter) = mcast_groups.iter() {
            for attribute in iter {
                let attribute_len = attribute.nla_len;
                let mut handle = attribute.get_attr_handle();
                let string = handle.get_payload_with::<String>(CtrlAttrMcastGrp::Name,
                    Some(attribute_len as usize))?;
                if string.as_str() == mcast_name {
                    id = handle.get_payload_as::<u32>(CtrlAttrMcastGrp::Id).ok();
                }
            }
        }
        id.ok_or(NlError::new("Failed to resolve multicast group ID"))
    }
}

impl<T, P> AsRawFd for NlSocket<T, P> {
    fn as_raw_fd(&self) -> RawFd {
        self.fd
    }
}

impl<T, P> IntoRawFd for NlSocket<T, P> {
    fn into_raw_fd(self) -> RawFd {
        self.fd
    }
}

#[cfg(feature = "stream")]
impl<T, P> Stream for NlSocket<T, P> where T: Nl, P: Nl {
    type Item = NlHdr<T, P>;
    type Error = ();

    fn poll(&mut self) -> Result<Async<Option<Self::Item>>, Self::Error> {
        let mem = MemWrite::new_vec(Some(MAX_NL_LENGTH));
        let mut events = mio::Events::with_capacity(1);
        match self.poll.poll(&mut events, Some(Duration::from_secs(0))) {
            Ok(_) => (),
            Err(_) => return Err(()),
        };
        if let Some(event) = events.iter().nth(0) {
            if !event.readiness().is_readable() {
                return Ok(Async::NotReady);
            }
        }
        let mut mem_read = match self.recv(mem, 0) {
            Ok(mr) => mr,
            Err(_) => return Err(()),
        };
        if mem_read.as_slice().len() == 0 {
            return Ok(Async::Ready(None));
        }
        let hdr = match NlHdr::<T, P>::deserialize(&mut mem_read) {
            Ok(h) => h,
            Err(_) => return Err(()),
        };
        Ok(Async::Ready(Some(hdr)))
    }
}

#[cfg(feature = "evented")]
impl<T, P> Evented for NlSocket<T, P> {
    fn register(&self, poll: &mio::Poll, token: mio::Token, interest: mio::Ready,
                opts: mio::PollOpt) -> io::Result<()> {
        poll.register(&mio::unix::EventedFd(&self.as_raw_fd()), token, interest, opts)
    }

    fn reregister(&self, poll: &mio::Poll, token: mio::Token, interest: mio::Ready,
                  opts: mio::PollOpt) -> io::Result<()> {
        poll.reregister(&mio::unix::EventedFd(&self.as_raw_fd()), token, interest, opts)
    }

    fn deregister(&self, poll: &mio::Poll) -> io::Result<()> {
        poll.deregister(&mio::unix::EventedFd(&self.as_raw_fd()))
    }
}

impl<T, P> Drop for NlSocket<T, P> {
    /// Closes underlying file descriptor to avoid file descriptor leaks.
    fn drop(&mut self) {
        unsafe { libc::close(self.fd); }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use ffi::{CtrlCmd,Nlmsg};
    use genlhdr::GenlHdr;

    #[test]
    fn test_socket_creation() {
       NlSocket::<Nlmsg, GenlHdr<CtrlCmd>>::connect(NlFamily::Generic, None, None).unwrap();
    }

    #[ignore]
    #[test]
    fn test_genl_family_resolve() {
        let mut sock = NlSocket::new_genl().unwrap();
        assert_eq!(19, sock.resolve_genl_family("nl80211").unwrap());
    }

    #[ignore]
    #[test]
    fn test_nl_mcast_group_resolve() {
        let mut sock = NlSocket::new_genl().unwrap();
        assert_eq!(5, sock.resolve_nl_mcast_group("nl80211", "mlme").unwrap());
    }
}
<|endoftext|>


<commit_before>use proc_macro2::{Span, TokenStream};
use syn::punctuated::Punctuated;
use syn::{Generics, Ident, Type, WhereClause};

pub fn bundle_impl(
    trait_name: &str,
    type_name: Ident,
    internal: bool,
    block: TokenStream,
) -> TokenStream {
    let const_name = Ident::new(
        &format!("_palette_derive_{}_for_{}", trait_name, type_name),
        Span::call_site(),
    );

    if internal {
        quote!{
            #[allow(non_snake_case, unused_attributes, unused_qualifications)]
            mod #const_name {
                extern crate num_traits as _num_traits;
                use super::#type_name;
                #block
            }
        }
    } else {
        quote!{
            #[allow(non_snake_case, unused_attributes, unused_qualifications)]
            mod #const_name {
                extern crate palette as _palette;
                extern crate num_traits as _num_traits;
                use super::#type_name;
                #block
            }
        }
    }
}

pub fn path(path: &[&str], internal: bool) -> TokenStream {
    let path = path
        .into_iter()
        .map(|&ident| Ident::new(ident, Span::call_site()));

    if internal {
        quote!{::#(#path)::*}
    } else {
        quote!{self::_palette::#(#path)::*}
    }
}

pub fn path_type(path: &[&str], internal: bool) -> Type {
    let path = path
        .into_iter()
        .map(|&ident| Ident::new(ident, Span::call_site()));

    if internal {
        parse_quote!{::#(#path)::*}
    } else {
        parse_quote!{self::_palette::#(#path)::*}
    }
}

pub fn color_path(color: &str, internal: bool) -> TokenStream {
    match color {
        "Luma" => path(&["luma", "Luma"], internal),
        "Rgb" => path(&["rgb", "Rgb"], internal),
        _ => path(&[color], internal),
    }
}

pub fn add_missing_where_clause(generics: &mut Generics) {
    if generics.where_clause.is_none() {
        generics.where_clause = Some(WhereClause {
            where_token: Token![where](Span::call_site()),
            predicates: Punctuated::new(),
        })
    }
}
<commit_msg>Import everything from the parent scope in derives<commit_after>use proc_macro2::{Span, TokenStream};
use syn::punctuated::Punctuated;
use syn::{Generics, Ident, Type, WhereClause};

pub fn bundle_impl(
    trait_name: &str,
    type_name: Ident,
    internal: bool,
    block: TokenStream,
) -> TokenStream {
    let const_name = Ident::new(
        &format!("_palette_derive_{}_for_{}", trait_name, type_name),
        Span::call_site(),
    );

    if internal {
        quote!{
            #[allow(non_snake_case, unused_attributes, unused_qualifications)]
            mod #const_name {
                extern crate num_traits as _num_traits;
                use super::*;
                #block
            }
        }
    } else {
        quote!{
            #[allow(non_snake_case, unused_attributes, unused_qualifications)]
            mod #const_name {
                extern crate palette as _palette;
                extern crate num_traits as _num_traits;
                use super::*;
                #block
            }
        }
    }
}

pub fn path(path: &[&str], internal: bool) -> TokenStream {
    let path = path
        .into_iter()
        .map(|&ident| Ident::new(ident, Span::call_site()));

    if internal {
        quote!{::#(#path)::*}
    } else {
        quote!{self::_palette::#(#path)::*}
    }
}

pub fn path_type(path: &[&str], internal: bool) -> Type {
    let path = path
        .into_iter()
        .map(|&ident| Ident::new(ident, Span::call_site()));

    if internal {
        parse_quote!{::#(#path)::*}
    } else {
        parse_quote!{self::_palette::#(#path)::*}
    }
}

pub fn color_path(color: &str, internal: bool) -> TokenStream {
    match color {
        "Luma" => path(&["luma", "Luma"], internal),
        "Rgb" => path(&["rgb", "Rgb"], internal),
        _ => path(&[color], internal),
    }
}

pub fn add_missing_where_clause(generics: &mut Generics) {
    if generics.where_clause.is_none() {
        generics.where_clause = Some(WhereClause {
            where_token: Token![where](Span::call_site()),
            predicates: Punctuated::new(),
        })
    }
}
<|endoftext|>


<commit_before>//! Module containing `TaskStatus` type and trait impls

use serde::Serialize;
use serde::Serializer;
use serde::Deserialize;
use serde::Deserializer;
use serde::de::Error;
use serde::de::Visitor;

/// Enum for status taskwarrior supports.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum TaskStatus {
    /// Pening status type
    Pending,

    /// Deleted status type
    Deleted,

    /// Completed status type
    Completed,

    /// Waiting status type
    Waiting,

    /// Recurring status type
    Recurring
}

impl Serialize for TaskStatus {

    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer
    {
        serializer.serialize_str(
            match self {
                &TaskStatus::Pending   => "pending",
                &TaskStatus::Deleted   => "deleted",
                &TaskStatus::Completed => "completed",
                &TaskStatus::Waiting   => "waiting",
                &TaskStatus::Recurring => "recurring",
            }
        )
    }

}

impl Deserialize for TaskStatus {
    fn deserialize<D>(deserializer: &mut D) -> Result<TaskStatus, D::Error>
        where D: Deserializer
    {
        struct TaskStatusVisitor;

        impl Visitor for TaskStatusVisitor {
            type Value = TaskStatus;

            fn visit_str<E>(&mut self, value: &str) -> Result<TaskStatus, E>
                where E: Error
            {
                match value {
                    "pending"   => Ok(TaskStatus::Pending),
                    "deleted"   => Ok(TaskStatus::Deleted),
                    "completed" => Ok(TaskStatus::Completed),
                    "waiting"   => Ok(TaskStatus::Waiting),
                    "recurring" => Ok(TaskStatus::Recurring),
                    _           => Err(Error::custom("expected one of pending, deleted, completed, waiting, recurring")),
                }
            }
        }

        deserializer.deserialize(TaskStatusVisitor)
    }
}

<commit_msg>Impl Display for TaskStatus<commit_after>//! Module containing `TaskStatus` type and trait impls

use std::fmt::{Display, Formatter};
use std::fmt::Error as FmtError;

use serde::Serialize;
use serde::Serializer;
use serde::Deserialize;
use serde::Deserializer;
use serde::de::Error;
use serde::de::Visitor;

/// Enum for status taskwarrior supports.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum TaskStatus {
    /// Pening status type
    Pending,

    /// Deleted status type
    Deleted,

    /// Completed status type
    Completed,

    /// Waiting status type
    Waiting,

    /// Recurring status type
    Recurring
}

impl Display for TaskStatus {

    fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
        match self {
            &TaskStatus::Pending   => write!(fmt, "Pending"),
            &TaskStatus::Deleted   => write!(fmt, "Deleted"),
            &TaskStatus::Completed => write!(fmt, "Completed"),
            &TaskStatus::Waiting   => write!(fmt, "Waiting"),
            &TaskStatus::Recurring => write!(fmt, "Recurring"),
        }
    }
}

impl Serialize for TaskStatus {

    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: Serializer
    {
        serializer.serialize_str(
            match self {
                &TaskStatus::Pending   => "pending",
                &TaskStatus::Deleted   => "deleted",
                &TaskStatus::Completed => "completed",
                &TaskStatus::Waiting   => "waiting",
                &TaskStatus::Recurring => "recurring",
            }
        )
    }

}

impl Deserialize for TaskStatus {
    fn deserialize<D>(deserializer: &mut D) -> Result<TaskStatus, D::Error>
        where D: Deserializer
    {
        struct TaskStatusVisitor;

        impl Visitor for TaskStatusVisitor {
            type Value = TaskStatus;

            fn visit_str<E>(&mut self, value: &str) -> Result<TaskStatus, E>
                where E: Error
            {
                match value {
                    "pending"   => Ok(TaskStatus::Pending),
                    "deleted"   => Ok(TaskStatus::Deleted),
                    "completed" => Ok(TaskStatus::Completed),
                    "waiting"   => Ok(TaskStatus::Waiting),
                    "recurring" => Ok(TaskStatus::Recurring),
                    _           => Err(Error::custom("expected one of pending, deleted, completed, waiting, recurring")),
                }
            }
        }

        deserializer.deserialize(TaskStatusVisitor)
    }
}

<|endoftext|>


<commit_before>// Copyright (c) 2017 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

//! Raspberry Pi system-related tools.
//!
//! Use `DeviceInfo` to identify what Raspberry Pi model and SoC the software is
//! running on. This information is used internally to calculate the correct memory
//! locations for the various BCM283x peripherals.

use std::fmt;
use std::fs::File;
use std::io::{BufReader, BufRead};
use std::result;

const BCM2708_PERIPHERAL_BASE: u32 = 0x20000000;
const BCM2709_PERIPHERAL_BASE: u32 = 0x3f000000;
const BCM2710_PERIPHERAL_BASE: u32 = 0x3f000000;
const GPIO_OFFSET: u32 = 0x200000;

quick_error! {
    #[derive(Debug)]
/// Errors that can occur when trying to identify the Raspberry Pi hardware.
    pub enum Error {
/// Unknown SoC.
///
/// Based on the output of `/proc/cpuinfo`, it wasn't possible to identify the SoC used by the
/// Raspberry Pi. While running the library on an unknown Raspberry Pi model is acceptable,
/// identifying the SoC is required because the memory address for the GPIO peripheral
/// depends on it.
        UnknownSoC { description("unknown SoC") }
/// Can't access `/proc/cpuinfo`.
///
/// Unable to read the contents of `/proc/cpuinfo`. This could be an issue with permissions, or
/// a Linux distribution is used that doesn't provide access to this virtual file.
        CantAccessProcCPUInfo { description("can't access /proc/cpuinfo") }
    }
}

/// Result type returned from methods that can have `system::Error`s.
pub type Result<T> = result::Result<T, Error>;

#[derive(Debug, PartialEq, Copy, Clone)]
/// Identifiable Raspberry Pi models.
pub enum Model {
    RaspberryPiA,
    RaspberryPiAPlus,
    RaspberryPiB,
    RaspberryPiBPlus,
    RaspberryPi2B,
    RaspberryPi3B,
    RaspberryPiComputeModule,
    RaspberryPiComputeModule3,
    RaspberryPiZero,
    RaspberryPiZeroW,
    Unknown,
}

impl fmt::Display for Model {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Model::RaspberryPiA => write!(f, "Raspberry Pi A"),
            Model::RaspberryPiAPlus => write!(f, "Raspberry Pi A+"),
            Model::RaspberryPiB => write!(f, "Raspberry Pi B"),
            Model::RaspberryPiBPlus => write!(f, "Raspberry Pi B+"),
            Model::RaspberryPi2B => write!(f, "Raspberry Pi 2 B"),
            Model::RaspberryPi3B => write!(f, "Raspberry Pi 3 B"),
            Model::RaspberryPiComputeModule => write!(f, "Raspberry Pi Compute Module"),
            Model::RaspberryPiComputeModule3 => write!(f, "Raspberry Pi Compute Module 3"),
            Model::RaspberryPiZero => write!(f, "Raspberry Pi Zero"),
            Model::RaspberryPiZeroW => write!(f, "Raspberry Pi Zero W"),
            Model::Unknown => write!(f, "Unknown"),
        }
    }
}

#[derive(Debug, PartialEq, Copy, Clone)]
/// Identifiable Raspberry Pi SoCs.
pub enum SoC {
    BCM2835,
    BCM2836,
    BCM2837,
}

impl fmt::Display for SoC {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            SoC::BCM2835 => write!(f, "BCM2835"),
            SoC::BCM2836 => write!(f, "BCM2836"),
            SoC::BCM2837 => write!(f, "BCM2837"),
        }
    }
}

/// Retrieves Raspberry Pi device information.
pub struct DeviceInfo {
    model: Model,
    soc: SoC,
    peripheral_base: u32,
    gpio_offset: u32,
}

impl DeviceInfo {
    /// Constructs a new `DeviceInfo`.
    pub fn new() -> Result<DeviceInfo> {
        // Parse hardware/revision from /proc/cpuinfo to figure out model/SoC
        let proc_cpuinfo = BufReader::new(match File::open("/proc/cpuinfo") {
            Err(_) => return Err(Error::CantAccessProcCPUInfo),
            Ok(file) => file,
        });

        let mut hardware: String = String::new();
        let mut revision: String = String::new();
        for line_result in proc_cpuinfo.lines() {
            if let Ok(line) = line_result {
                if line.starts_with("Hardware\t: ") {
                    hardware = String::from(&line[11..]);
                } else if line.starts_with("Revision\t: ") {
                    revision = String::from(&line[11..]).to_lowercase();
                }
            }
        }

        let model = if revision.len() >= 6 {
            // Newer revisions consist of at least 6 characters
            match &revision[revision.len() - 3..revision.len() - 1] {
                "00" => Model::RaspberryPiA,
                "01" => Model::RaspberryPiB,
                "02" => Model::RaspberryPiAPlus,
                "03" => Model::RaspberryPiBPlus,
                "04" => Model::RaspberryPi2B,
                "06" => Model::RaspberryPiComputeModule,
                "08" => Model::RaspberryPi3B,
                "09" => Model::RaspberryPiZero,
                "0a" => Model::RaspberryPiComputeModule3,
                "0c" => Model::RaspberryPiZeroW,
                _ => Model::Unknown,
            }
        } else if revision.len() == 4 {
            // Older revisions are 4 characters long
            match &revision[..] {
                "0007" | "0008" | "0009" | "0015" => Model::RaspberryPiA,
                "Beta" | "0002" | "0003" | "0004" | "0005" | "0006" | "000d" | "000e" | "000f" => {
                    Model::RaspberryPiB
                }
                "0012" => Model::RaspberryPiAPlus,
                "0010" | "0013" => Model::RaspberryPiBPlus,
                "0011" | "0014" => Model::RaspberryPiComputeModule,
                _ => Model::Unknown,
            }
        } else {
            Model::Unknown
        };

        // Make sure we're actually running on a supported SoC
        match &hardware[..] {
            "BCM2708" | "BCM2835" => {
                Ok(DeviceInfo {
                    model: model,
                    soc: SoC::BCM2835,
                    peripheral_base: BCM2708_PERIPHERAL_BASE,
                    gpio_offset: GPIO_OFFSET,
                })
            }
            "BCM2709" | "BCM2836" => {
                Ok(DeviceInfo {
                    model: model,
                    soc: SoC::BCM2836,
                    peripheral_base: BCM2709_PERIPHERAL_BASE,
                    gpio_offset: GPIO_OFFSET,
                })
            }
            "BCM2710" | "BCM2837" => {
                Ok(DeviceInfo {
                    model: model,
                    soc: SoC::BCM2837,
                    peripheral_base: BCM2710_PERIPHERAL_BASE,
                    gpio_offset: GPIO_OFFSET,
                })
            }
            _ => Err(Error::UnknownSoC),
        }
    }

    /// Returns a reference to the Raspberry Pi model identified by parsing the
    /// contents of `/proc/cpuinfo`.
    pub fn model(&self) -> &Model {
        &self.model
    }

    /// Returns a reference to the SoC identified by parsing the contents of `/proc/cpuinfo`.
    pub fn soc(&self) -> &SoC {
        &self.soc
    }

    /// Returns the base memory address for the BCM283x peripherals.
    pub fn peripheral_base(&self) -> u32 {
        self.peripheral_base
    }

    /// Returns the offset memory address for the GPIO section.
    pub fn gpio_offset(&self) -> u32 {
        self.gpio_offset
    }
}
<commit_msg>Change acronyms in struct/enum names to CamelCase<commit_after>// Copyright (c) 2017 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

//! Raspberry Pi system-related tools.
//!
//! Use `DeviceInfo` to identify what Raspberry Pi model and SoC the software is
//! running on. This information is used internally to calculate the correct memory
//! locations for the various BCM283x peripherals.

use std::fmt;
use std::fs::File;
use std::io::{BufReader, BufRead};
use std::result;

const BCM2708_PERIPHERAL_BASE: u32 = 0x20000000;
const BCM2709_PERIPHERAL_BASE: u32 = 0x3f000000;
const BCM2710_PERIPHERAL_BASE: u32 = 0x3f000000;
const GPIO_OFFSET: u32 = 0x200000;

quick_error! {
    #[derive(Debug)]
/// Errors that can occur when trying to identify the Raspberry Pi hardware.
    pub enum Error {
/// Unknown SoC.
///
/// Based on the output of `/proc/cpuinfo`, it wasn't possible to identify the SoC used by the
/// Raspberry Pi. While running the library on an unknown Raspberry Pi model is acceptable,
/// identifying the SoC is required because the memory address for the GPIO peripheral
/// depends on it.
        UnknownSoC { description("unknown SoC") }
/// Can't access `/proc/cpuinfo`.
///
/// Unable to read the contents of `/proc/cpuinfo`. This could be an issue with permissions, or
/// a Linux distribution is used that doesn't provide access to this virtual file.
        CantAccessProcCpuInfo { description("can't access /proc/cpuinfo") }
    }
}

/// Result type returned from methods that can have `system::Error`s.
pub type Result<T> = result::Result<T, Error>;

#[derive(Debug, PartialEq, Copy, Clone)]
/// Identifiable Raspberry Pi models.
pub enum Model {
    RaspberryPiA,
    RaspberryPiAPlus,
    RaspberryPiB,
    RaspberryPiBPlus,
    RaspberryPi2B,
    RaspberryPi3B,
    RaspberryPiComputeModule,
    RaspberryPiComputeModule3,
    RaspberryPiZero,
    RaspberryPiZeroW,
    Unknown,
}

impl fmt::Display for Model {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Model::RaspberryPiA => write!(f, "Raspberry Pi A"),
            Model::RaspberryPiAPlus => write!(f, "Raspberry Pi A+"),
            Model::RaspberryPiB => write!(f, "Raspberry Pi B"),
            Model::RaspberryPiBPlus => write!(f, "Raspberry Pi B+"),
            Model::RaspberryPi2B => write!(f, "Raspberry Pi 2 B"),
            Model::RaspberryPi3B => write!(f, "Raspberry Pi 3 B"),
            Model::RaspberryPiComputeModule => write!(f, "Raspberry Pi Compute Module"),
            Model::RaspberryPiComputeModule3 => write!(f, "Raspberry Pi Compute Module 3"),
            Model::RaspberryPiZero => write!(f, "Raspberry Pi Zero"),
            Model::RaspberryPiZeroW => write!(f, "Raspberry Pi Zero W"),
            Model::Unknown => write!(f, "Unknown"),
        }
    }
}

#[derive(Debug, PartialEq, Copy, Clone)]
/// Identifiable Raspberry Pi SoCs.
pub enum SoC {
    Bcm2835,
    Bcm2836,
    Bcm2837,
}

impl fmt::Display for SoC {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            SoC::Bcm2835 => write!(f, "BCM2835"),
            SoC::Bcm2836 => write!(f, "BCM2836"),
            SoC::Bcm2837 => write!(f, "BCM2837"),
        }
    }
}

/// Retrieves Raspberry Pi device information.
pub struct DeviceInfo {
    model: Model,
    soc: SoC,
    peripheral_base: u32,
    gpio_offset: u32,
}

impl DeviceInfo {
    /// Constructs a new `DeviceInfo`.
    pub fn new() -> Result<DeviceInfo> {
        // Parse hardware/revision from /proc/cpuinfo to figure out model/SoC
        let proc_cpuinfo = BufReader::new(match File::open("/proc/cpuinfo") {
            Err(_) => return Err(Error::CantAccessProcCpuInfo),
            Ok(file) => file,
        });

        let mut hardware: String = String::new();
        let mut revision: String = String::new();
        for line_result in proc_cpuinfo.lines() {
            if let Ok(line) = line_result {
                if line.starts_with("Hardware\t: ") {
                    hardware = String::from(&line[11..]);
                } else if line.starts_with("Revision\t: ") {
                    revision = String::from(&line[11..]).to_lowercase();
                }
            }
        }

        let model = if revision.len() >= 6 {
            // Newer revisions consist of at least 6 characters
            match &revision[revision.len() - 3..revision.len() - 1] {
                "00" => Model::RaspberryPiA,
                "01" => Model::RaspberryPiB,
                "02" => Model::RaspberryPiAPlus,
                "03" => Model::RaspberryPiBPlus,
                "04" => Model::RaspberryPi2B,
                "06" => Model::RaspberryPiComputeModule,
                "08" => Model::RaspberryPi3B,
                "09" => Model::RaspberryPiZero,
                "0a" => Model::RaspberryPiComputeModule3,
                "0c" => Model::RaspberryPiZeroW,
                _ => Model::Unknown,
            }
        } else if revision.len() == 4 {
            // Older revisions are 4 characters long
            match &revision[..] {
                "0007" | "0008" | "0009" | "0015" => Model::RaspberryPiA,
                "Beta" | "0002" | "0003" | "0004" | "0005" | "0006" | "000d" | "000e" | "000f" => {
                    Model::RaspberryPiB
                }
                "0012" => Model::RaspberryPiAPlus,
                "0010" | "0013" => Model::RaspberryPiBPlus,
                "0011" | "0014" => Model::RaspberryPiComputeModule,
                _ => Model::Unknown,
            }
        } else {
            Model::Unknown
        };

        // Make sure we're actually running on a supported SoC
        match &hardware[..] {
            "BCM2708" | "BCM2835" => {
                Ok(DeviceInfo {
                    model: model,
                    soc: SoC::Bcm2835,
                    peripheral_base: BCM2708_PERIPHERAL_BASE,
                    gpio_offset: GPIO_OFFSET,
                })
            }
            "BCM2709" | "BCM2836" => {
                Ok(DeviceInfo {
                    model: model,
                    soc: SoC::Bcm2836,
                    peripheral_base: BCM2709_PERIPHERAL_BASE,
                    gpio_offset: GPIO_OFFSET,
                })
            }
            "BCM2710" | "BCM2837" => {
                Ok(DeviceInfo {
                    model: model,
                    soc: SoC::Bcm2837,
                    peripheral_base: BCM2710_PERIPHERAL_BASE,
                    gpio_offset: GPIO_OFFSET,
                })
            }
            _ => Err(Error::UnknownSoC),
        }
    }

    /// Returns a reference to the Raspberry Pi model identified by parsing the
    /// contents of `/proc/cpuinfo`.
    pub fn model(&self) -> &Model {
        &self.model
    }

    /// Returns a reference to the SoC identified by parsing the contents of `/proc/cpuinfo`.
    pub fn soc(&self) -> &SoC {
        &self.soc
    }

    /// Returns the base memory address for the BCM283x peripherals.
    pub fn peripheral_base(&self) -> u32 {
        self.peripheral_base
    }

    /// Returns the offset memory address for the GPIO section.
    pub fn gpio_offset(&self) -> u32 {
        self.gpio_offset
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use {Word, Result};
use private::layout::{CapTable, StructReader, StructBuilder, StructSize, PointerBuilder, PointerReader};

use std::marker::PhantomData;

pub trait FromStructReader<'a> {
    fn new(reader : StructReader<'a>) -> Self;
}

pub trait HasStructSize {
    fn struct_size() -> StructSize;
}

pub trait FromStructBuilder<'a> {
    fn new(struct_builder: StructBuilder<'a>) -> Self;
}

pub trait FromPointerReader<'a> : Sized {
    fn get_from_pointer(reader: &PointerReader<'a>) -> Result<Self>;
}

/// Associated types hackery that allows us to reason about Cap'n Proto types
/// without needing to give them a lifetime `'a`.
///
/// If `Foo` is a Cap'n Proto struct and `Bar` is a Rust-native struct, then
/// `foo::Reader<'a>` is to `foo::Owned` as `&'a Bar` is to `Bar`, and
/// `foo::Builder<'a>` is to `foo::Owned` as `&'a mut Bar` is to `Bar`.
/// The relationship is formalized by an `impl <'a> capnp::traits::Owned<'a> for foo::Owned`.
/// Because Cap'n Proto struct layout differs from Rust struct layout,
/// `foo::Owned` cannot be an inhabited type; it is useful nonetheless
/// as a type parameter, e.g. for a generic container that owns a Cap'n Proto message
/// of type `T: for<'a> capnp::traits::Owned<'a>`.
pub trait Owned<'a> {
    type Reader: FromPointerReader<'a> + SetPointerBuilder<Self::Builder>;
    type Builder: FromPointerBuilder<'a>;
}

pub trait OwnedStruct<'a> {
    type Reader: FromStructReader<'a> + SetPointerBuilder<Self::Builder>;
    type Builder: FromStructBuilder<'a> + HasStructSize;
}

pub trait Pipelined {
    type Pipeline;
}

pub trait FromPointerReaderRefDefault<'a> {
    fn get_from_pointer(reader: &PointerReader<'a>, default_value: *const Word) -> Self;
}

pub trait FromPointerBuilder<'a> : Sized {
    fn init_pointer(PointerBuilder<'a>, u32) -> Self;
    fn get_from_pointer(builder: PointerBuilder<'a>) -> Result<Self>;
}

pub trait FromPointerBuilderRefDefault<'a> {
    fn get_from_pointer(builder: PointerBuilder<'a>, default_value: *const Word) -> Self;
}

pub trait SetPointerBuilder<To> {
    fn set_pointer_builder<'a>(PointerBuilder<'a>, Self) -> Result<()>;

    // TODO(apibump): fold this into set_pointer_builder by adding a bool parameter.
    fn set_pointer_canonical<'a>(PointerBuilder<'a>, Self) -> Result<()> where Self: Sized {
        unimplemented!()
    }
}

pub trait Imbue<'a> {
    fn imbue(&mut self, &'a CapTable);
}

pub trait ImbueMut<'a> {
    fn imbue_mut(&mut self, &'a mut CapTable);
}

pub trait HasTypeId {
    fn type_id() -> u64;
}

pub trait ToU16 {
    fn to_u16(self) -> u16;
}

pub trait FromU16 : Sized {
    fn from_u16(value: u16) -> ::std::result::Result<Self, ::NotInSchema>;
}

pub trait IndexMove<I, T> {
    fn index_move(&self, index: I) -> T;
}

pub struct ListIter<T, U> {
    marker: PhantomData<U>,
    list: T,
    index: u32,
    size: u32,
}

impl <T, U> ListIter<T, U>{
    pub fn new(list: T, size: u32) -> ListIter<T, U> {
        ListIter { list: list, index: 0, size: size, marker: PhantomData }
    }
}

impl <U, T : IndexMove<u32, U>> ::std::iter::Iterator for ListIter<T, U> {
    type Item = U;
    fn next(&mut self) -> ::std::option::Option<U> {
        if self.index < self.size {
            let result = self.list.index_move(self.index);
            self.index += 1;
            Some(result)
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>){
        (self.size as usize, Some(self.size as usize))
    }

    fn nth(&mut self, p: usize) -> Option<U>{
        if p < self.size as usize {
            self.index = p as u32;
            let result = self.list.index_move(self.index);
            Some(result)
        } else {
            None
        }
    }
}

impl <U, T: IndexMove<u32, U>> ::std::iter::ExactSizeIterator for ListIter<T, U>{
    fn len(&self) -> usize{
        self.size as usize
    }
}

impl <U, T: IndexMove<u32, U>> ::std::iter::DoubleEndedIterator for ListIter<T, U>{
    fn next_back(&mut self) -> ::std::option::Option<U> {
        if self.size > self.index {
            self.size -= 1;
            Some(self.list.index_move(self.size))
        } else {
            None
        }
    }
}
<commit_msg>remove imprecise usage of uninhabited from Owned docstring<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use {Word, Result};
use private::layout::{CapTable, StructReader, StructBuilder, StructSize, PointerBuilder, PointerReader};

use std::marker::PhantomData;

pub trait FromStructReader<'a> {
    fn new(reader : StructReader<'a>) -> Self;
}

pub trait HasStructSize {
    fn struct_size() -> StructSize;
}

pub trait FromStructBuilder<'a> {
    fn new(struct_builder: StructBuilder<'a>) -> Self;
}

pub trait FromPointerReader<'a> : Sized {
    fn get_from_pointer(reader: &PointerReader<'a>) -> Result<Self>;
}

/// Associated types hackery that allows us to reason about Cap'n Proto types
/// without needing to give them a lifetime `'a`.
///
/// If `Foo` is a Cap'n Proto struct and `Bar` is a Rust-native struct, then
/// `foo::Reader<'a>` is to `foo::Owned` as `&'a Bar` is to `Bar`, and
/// `foo::Builder<'a>` is to `foo::Owned` as `&'a mut Bar` is to `Bar`.
/// The relationship is formalized by an `impl <'a> capnp::traits::Owned<'a> for foo::Owned`.
/// Because Cap'n Proto struct layout differs from Rust struct layout, a `foo::Owned` value
/// cannot be used for anything interesting on its own; the `foo::Owned` type is useful
/// nonetheless as a type parameter, e.g. for a generic container that owns a Cap'n Proto
/// message of type `T: for<'a> capnp::traits::Owned<'a>`.
pub trait Owned<'a> {
    type Reader: FromPointerReader<'a> + SetPointerBuilder<Self::Builder>;
    type Builder: FromPointerBuilder<'a>;
}

pub trait OwnedStruct<'a> {
    type Reader: FromStructReader<'a> + SetPointerBuilder<Self::Builder>;
    type Builder: FromStructBuilder<'a> + HasStructSize;
}

pub trait Pipelined {
    type Pipeline;
}

pub trait FromPointerReaderRefDefault<'a> {
    fn get_from_pointer(reader: &PointerReader<'a>, default_value: *const Word) -> Self;
}

pub trait FromPointerBuilder<'a> : Sized {
    fn init_pointer(PointerBuilder<'a>, u32) -> Self;
    fn get_from_pointer(builder: PointerBuilder<'a>) -> Result<Self>;
}

pub trait FromPointerBuilderRefDefault<'a> {
    fn get_from_pointer(builder: PointerBuilder<'a>, default_value: *const Word) -> Self;
}

pub trait SetPointerBuilder<To> {
    fn set_pointer_builder<'a>(PointerBuilder<'a>, Self) -> Result<()>;

    // TODO(apibump): fold this into set_pointer_builder by adding a bool parameter.
    fn set_pointer_canonical<'a>(PointerBuilder<'a>, Self) -> Result<()> where Self: Sized {
        unimplemented!()
    }
}

pub trait Imbue<'a> {
    fn imbue(&mut self, &'a CapTable);
}

pub trait ImbueMut<'a> {
    fn imbue_mut(&mut self, &'a mut CapTable);
}

pub trait HasTypeId {
    fn type_id() -> u64;
}

pub trait ToU16 {
    fn to_u16(self) -> u16;
}

pub trait FromU16 : Sized {
    fn from_u16(value: u16) -> ::std::result::Result<Self, ::NotInSchema>;
}

pub trait IndexMove<I, T> {
    fn index_move(&self, index: I) -> T;
}

pub struct ListIter<T, U> {
    marker: PhantomData<U>,
    list: T,
    index: u32,
    size: u32,
}

impl <T, U> ListIter<T, U>{
    pub fn new(list: T, size: u32) -> ListIter<T, U> {
        ListIter { list: list, index: 0, size: size, marker: PhantomData }
    }
}

impl <U, T : IndexMove<u32, U>> ::std::iter::Iterator for ListIter<T, U> {
    type Item = U;
    fn next(&mut self) -> ::std::option::Option<U> {
        if self.index < self.size {
            let result = self.list.index_move(self.index);
            self.index += 1;
            Some(result)
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>){
        (self.size as usize, Some(self.size as usize))
    }

    fn nth(&mut self, p: usize) -> Option<U>{
        if p < self.size as usize {
            self.index = p as u32;
            let result = self.list.index_move(self.index);
            Some(result)
        } else {
            None
        }
    }
}

impl <U, T: IndexMove<u32, U>> ::std::iter::ExactSizeIterator for ListIter<T, U>{
    fn len(&self) -> usize{
        self.size as usize
    }
}

impl <U, T: IndexMove<u32, U>> ::std::iter::DoubleEndedIterator for ListIter<T, U>{
    fn next_back(&mut self) -> ::std::option::Option<U> {
        if self.size > self.index {
            self.size -= 1;
            Some(self.list.index_move(self.size))
        } else {
            None
        }
    }
}
<|endoftext|>


<commit_before>//! Write points to a `Write`.
//!
//! Simple writes can be done with a `Writer`, but if you need to configure your output file, use a
//! `Builder`.

use std::fs::File;
use std::io::{BufWriter, Seek, SeekFrom, Write};
use std::path::Path;

use {Error, Result};
use builder::Builder;
use header::{Header, WriteHeader};
use point::{Point, WritePoint};
use utils::{Bounds, Triple};
use vlr::{Vlr, WriteVlr};

/// Write LAS points to a `Write`.
///
/// This struct implements `Drop`, so the LAS data are finalized (the header is re-written) when
/// the `Writer` goes out of scope. This will panic if there is an error while closing the file, so
/// if you're worried about panics you will need to use `Writer::close` instead.
#[derive(Debug)]
pub struct Writer<W: Seek + Write> {
    bounds: Bounds<f64>,
    closed: bool,
    header: Header,
    point_count: u32,
    point_count_by_return: [u32; 5],
    vlrs: Vec<Vlr>,
    write: W,
}

impl Writer<BufWriter<File>> {
    /// Creates a default `Writer` that will write points out to a file at the path.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::Writer;
    /// let writer = Writer::from_path("/dev/null").unwrap();
    /// ```
    pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Writer<BufWriter<File>>> {
        File::create(path).map_err(Error::from).and_then(|f| Writer::default(BufWriter::new(f)))
    }
}

impl<W: Seek + Write> Writer<W> {
    fn from(builder: &Builder, write: W) -> Writer<W> {
        Writer {
            bounds: Default::default(),
            closed: false,
            header: builder.header,
            point_count: 0,
            point_count_by_return: [0; 5],
            vlrs: builder.vlrs.clone(),
            write: write,
        }
    }

    /// Creates a new writer from a `Builder` and a `Write`.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::Writer;
    /// use std::io::Cursor;
    /// use las::Builder;
    /// let writer = Writer::new(&Builder::new(), Cursor::new(Vec::new())).unwrap();
    /// ```
    pub fn new(builder: &Builder, write: W) -> Result<Writer<W>> {
        let mut writer = Writer::from(builder, write);
        try!(writer.write_header());
        Ok(writer)
    }

    /// Creates a new default writer.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::io::Cursor;
    /// # use las::Writer;
    /// let writer = Writer::default(Cursor::new(Vec::new())).unwrap();
    /// ```
    pub fn default(write: W) -> Result<Writer<W>> {
        Builder::new().writer(write)
    }

    /// Writes a point.
    ///
    /// # Examples
    ///
    ///
    /// ```
    /// use std::io::Cursor;
    /// # use las::Writer;
    /// let mut writer = Writer::default(Cursor::new(Vec::new())).unwrap();
    /// writer.write(&Default::default()).unwrap();
    /// ```
    pub fn write(&mut self, point: &Point) -> Result<()> {
        if self.closed {
            return Err(Error::ClosedWriter);
        }
        try!(self.write.write_point(point,
                                    self.header.transforms,
                                    self.header.point_format,
                                    self.header.extra_bytes));
        self.point_count += 1;
        if point.return_number.is_valid() {
            self.point_count_by_return[u8::from(point.return_number) as usize - 1] += 1;
        }
        self.bounds.grow(Triple {
            x: point.x,
            y: point.y,
            z: point.z,
        });
        Ok(())
    }

    fn write_header(&mut self) -> Result<()> {
        // TODO test point count by return, offsets, etc
        self.header.point_count = self.point_count;
        self.header.bounds = self.bounds;
        try!(self.write.seek(SeekFrom::Start(0)));
        try!(self.write.write_header(self.header));
        for vlr in &self.vlrs {
            try!(self.write.write_vlr(vlr));
        }
        Ok(())
    }

    /// Closes this writer.
    ///
    /// After the writer is closed, and future calls to `write` will error.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::io::Cursor;
    /// # use las::Writer;
    /// let mut writer = Writer::default(Cursor::new(Vec::new())).unwrap();
    /// assert!(writer.write(&Default::default()).is_ok());
    /// writer.close().unwrap();
    /// assert!(writer.write(&Default::default()).is_err());
    /// ```
    pub fn close(&mut self) -> Result<()> {
        if self.closed {
            return Err(Error::ClosedWriter);
        }
        try!(self.write_header());
        self.closed = true;
        Ok(())
    }
}

impl<W: Seek + Write> Drop for Writer<W> {
    fn drop(&mut self) {
        if !self.closed {
            if let Err(err) = self.close() {
                error!("Error while dropping writer: {}", err);
            }
        }
    }
}

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

    use std::io::Cursor;

    use builder::Builder;
    use point::{Classification, Color, NumberOfReturns, Point, ReturnNumber, ScanDirection};
    use reader::Reader;
    use utils::Bounds;
    use version::Version;

    fn point() -> Point {
        Point {
            x: 1.,
            y: 2.,
            z: 3.,
            intensity: 4,
            return_number: ReturnNumber::from(1),
            number_of_returns: NumberOfReturns::from(0b00010000),
            scan_direction: ScanDirection::Positive,
            edge_of_flight_line: false,
            classification: Classification::from(2),
            scan_angle_rank: 2,
            user_data: 3,
            point_source_id: 4,
            gps_time: Some(5.),
            color: Some(Color {
                red: 6,
                green: 7,
                blue: 8,
            }),
            extra_bytes: Vec::new(),
        }
    }

    fn check_point(point: &Point) {
        assert_eq!(1., point.x);
        assert_eq!(2., point.y);
        assert_eq!(3., point.z);
        assert_eq!(4, point.intensity);
        assert_eq!(1, point.return_number);
        assert_eq!(2, point.number_of_returns);
        assert_eq!(ScanDirection::Positive, point.scan_direction);
        assert!(!point.edge_of_flight_line);
        assert_eq!(2, point.classification);
        assert_eq!(2, point.scan_angle_rank);
        assert_eq!(3, point.user_data);
        assert_eq!(4, point.point_source_id);
    }

    fn check_point_0(point: Point) {
        check_point(&point);
        assert!(point.gps_time.is_none());
        assert!(point.color.is_none());
    }

    fn check_point_1(point: Point) {
        check_point(&point);
        assert_eq!(5., point.gps_time.unwrap());
        assert!(point.color.is_none());
    }

    fn check_point_2(point: Point) {
        check_point(&point);
        assert!(point.gps_time.is_none());
        let color = point.color.unwrap();
        assert_eq!(6, color.red);
        assert_eq!(7, color.green);
        assert_eq!(8, color.blue);
    }

    fn check_point_3(point: Point) {
        check_point(&point);
        assert_eq!(5., point.gps_time.unwrap());
        let color = point.color.unwrap();
        assert_eq!(6, color.red);
        assert_eq!(7, color.green);
        assert_eq!(8, color.blue);
    }

    #[test]
    fn write_zero_points() {
        let mut cursor = Cursor::new(Vec::new());
        Writer::default(&mut cursor).unwrap();
        cursor.set_position(0);
        let mut reader = Reader::new(cursor).unwrap();
        assert!(reader.read().unwrap().is_none());
    }

    #[test]
    fn write_one_point_default() {
        let mut cursor = Cursor::new(Vec::new());
        {
            let mut writer = Writer::default(&mut cursor).unwrap();
            writer.write(&point()).unwrap();
        }
        cursor.set_position(0);
        let mut reader = Reader::new(cursor).unwrap();
        check_point_0(reader.read().unwrap().unwrap());
        assert!(reader.read().unwrap().is_none());
    }

    #[test]
    fn write_one_point_format_1() {
        let mut cursor = Cursor::new(Vec::new());
        {
            let mut builder = Builder::new();
            builder.header.point_format = 1.into();
            let mut writer = builder.writer(&mut cursor).unwrap();
            writer.write(&point()).unwrap();
        }
        cursor.set_position(0);
        let mut reader = Reader::new(cursor).unwrap();
        check_point_1(reader.read().unwrap().unwrap());
        assert!(reader.read().unwrap().is_none());
    }

    #[test]
    fn write_one_point_format_2() {
        let mut cursor = Cursor::new(Vec::new());
        {
            let mut builder = Builder::new();
            builder.header.point_format = 2.into();
            let mut writer = builder.writer(&mut cursor).unwrap();
            writer.write(&point()).unwrap();
        }
        cursor.set_position(0);
        let mut reader = Reader::new(cursor).unwrap();
        check_point_2(reader.read().unwrap().unwrap());
        assert!(reader.read().unwrap().is_none());
    }

    #[test]
    fn write_one_point_format_3() {
        let mut cursor = Cursor::new(Vec::new());
        {
            let mut builder = Builder::new();
            builder.header.point_format = 3.into();
            let mut writer = builder.writer(&mut cursor).unwrap();
            writer.write(&point()).unwrap();
        }
        cursor.set_position(0);
        let mut reader = Reader::new(cursor).unwrap();
        check_point_3(reader.read().unwrap().unwrap());
        assert!(reader.read().unwrap().is_none());
    }

    #[test]
    fn try_write_point_format_1_no_time() {
        let mut builder = Builder::new();
        builder.header.point_format = 1.into();
        let mut writer = builder.writer(Cursor::new(Vec::new())).unwrap();
        let mut point = point();
        point.gps_time = None;
        assert!(writer.write(&point).is_err());
    }

    #[test]
    fn try_write_point_format_2_no_color() {
        let mut builder = Builder::new();
        builder.header.point_format = 2.into();
        let mut writer = builder.writer(Cursor::new(Vec::new())).unwrap();
        let mut point = point();
        point.color = None;
        assert!(writer.write(&point).is_err());
    }

    #[test]
    fn write_point_count() {
        let mut cursor = Cursor::new(Vec::new());
        {
            let mut writer = Writer::default(&mut cursor).unwrap();
            writer.write(&point()).unwrap();
        }
        cursor.set_position(0);
        assert_eq!(1, Reader::new(cursor).unwrap().header.point_count);
    }

    #[test]
    fn write_two_points() {
        let mut cursor = Cursor::new(Vec::new());
        {
            let mut writer = Writer::default(&mut cursor).unwrap();
            writer.write(&point()).unwrap();
            writer.write(&point()).unwrap();
        }
        cursor.set_position(0);
        let mut reader = Reader::new(cursor).unwrap();
        assert!(reader.read().unwrap().is_some());
        assert!(reader.read().unwrap().is_some());
        assert!(reader.read().unwrap().is_none());
    }

    #[test]
    fn write_bounds() {
        let mut cursor = Cursor::new(Vec::new());
        {
            let mut writer = Writer::default(&mut cursor).unwrap();
            writer.write(&point()).unwrap();
        }
        cursor.set_position(0);
        let reader = Reader::new(cursor).unwrap();
        assert_eq!(Bounds::new(1., 2., 3., 1., 2., 3.), reader.header.bounds);
    }

    #[test]
    fn close_the_writer() {
        let mut writer = Writer::default(Cursor::new(Vec::new())).unwrap();
        writer.close().is_ok();
        assert!(writer.write(&point()).is_err());
        assert!(writer.close().is_err());
    }

    #[test]
    fn write_version() {
        let mut cursor = Cursor::new(Vec::new());
        let mut builder = Builder::new();
        builder.header.version = (1, 0).into();
        builder.writer(&mut cursor).unwrap();
        cursor.set_position(0);
        assert_eq!(Version::from((1, 0)),
                   Reader::new(&mut cursor).unwrap().header.version);
    }

    #[test]
    fn write_zero_return_number() {
        let mut writer = Writer::default(Cursor::new(Vec::new())).unwrap();
        writer.write(&Default::default()).unwrap();
    }

    #[test]
    fn write_extra_bytes() {
        let mut cursor = Cursor::new(Vec::new());
        {
            let mut builder = Builder::new();
            builder.header.extra_bytes = 5;
            let mut writer = builder.writer(&mut cursor).unwrap();
            let mut point = point();
            point.extra_bytes = b"Hello".to_vec();
            writer.write(&point).unwrap();
        }
        cursor.set_position(0);
        let point = Reader::new(cursor).unwrap().read_to_end().unwrap().pop().unwrap();
        assert_eq!(b"Hello", &point.extra_bytes[..]);
    }

    #[test]
    fn writer_from_path() {
        assert!(Writer::from_path("/dev/null").is_ok());
    }

    #[test]
    fn builder_writer_for_path() {
        assert!(Builder::new().writer_from_path("/dev/null").is_ok());
    }

    #[test]
    fn disallow_file_source_id_wipe() {
        let mut builder = Builder::new();
        builder.header.file_source_id = 1;
        builder.header.version = (1, 0).into();
        assert!(builder.writer(Cursor::new(Vec::new())).is_err());
    }

    #[test]
    fn disallow_global_encoding_downcast() {
        let mut builder = Builder::new();
        builder.header.global_encoding = 1.into();
        builder.header.version = (1, 0).into();
        assert!(builder.writer(Cursor::new(Vec::new())).is_err());
    }
}
<commit_msg>Use default more in `Writer::from`<commit_after>//! Write points to a `Write`.
//!
//! Simple writes can be done with a `Writer`, but if you need to configure your output file, use a
//! `Builder`.

use std::fs::File;
use std::io::{BufWriter, Seek, SeekFrom, Write};
use std::path::Path;

use {Error, Result};
use builder::Builder;
use header::{Header, WriteHeader};
use point::{Point, WritePoint};
use utils::{Bounds, Triple};
use vlr::{Vlr, WriteVlr};

/// Write LAS points to a `Write`.
///
/// This struct implements `Drop`, so the LAS data are finalized (the header is re-written) when
/// the `Writer` goes out of scope. This will panic if there is an error while closing the file, so
/// if you're worried about panics you will need to use `Writer::close` instead.
#[derive(Debug)]
pub struct Writer<W: Seek + Write> {
    bounds: Bounds<f64>,
    closed: bool,
    header: Header,
    point_count: u32,
    point_count_by_return: [u32; 5],
    vlrs: Vec<Vlr>,
    write: W,
}

impl Writer<BufWriter<File>> {
    /// Creates a default `Writer` that will write points out to a file at the path.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::Writer;
    /// let writer = Writer::from_path("/dev/null").unwrap();
    /// ```
    pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Writer<BufWriter<File>>> {
        File::create(path).map_err(Error::from).and_then(|f| Writer::default(BufWriter::new(f)))
    }
}

impl<W: Seek + Write> Writer<W> {
    fn from(builder: &Builder, write: W) -> Writer<W> {
        Writer {
            bounds: Default::default(),
            closed: false,
            header: builder.header,
            point_count: Default::default(),
            point_count_by_return: Default::default(),
            vlrs: builder.vlrs.clone(),
            write: write,
        }
    }

    /// Creates a new writer from a `Builder` and a `Write`.
    ///
    /// # Examples
    ///
    /// ```
    /// # use las::Writer;
    /// use std::io::Cursor;
    /// use las::Builder;
    /// let writer = Writer::new(&Builder::new(), Cursor::new(Vec::new())).unwrap();
    /// ```
    pub fn new(builder: &Builder, write: W) -> Result<Writer<W>> {
        let mut writer = Writer::from(builder, write);
        try!(writer.write_header());
        Ok(writer)
    }

    /// Creates a new default writer.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::io::Cursor;
    /// # use las::Writer;
    /// let writer = Writer::default(Cursor::new(Vec::new())).unwrap();
    /// ```
    pub fn default(write: W) -> Result<Writer<W>> {
        Builder::new().writer(write)
    }

    /// Writes a point.
    ///
    /// # Examples
    ///
    ///
    /// ```
    /// use std::io::Cursor;
    /// # use las::Writer;
    /// let mut writer = Writer::default(Cursor::new(Vec::new())).unwrap();
    /// writer.write(&Default::default()).unwrap();
    /// ```
    pub fn write(&mut self, point: &Point) -> Result<()> {
        if self.closed {
            return Err(Error::ClosedWriter);
        }
        try!(self.write.write_point(point,
                                    self.header.transforms,
                                    self.header.point_format,
                                    self.header.extra_bytes));
        self.point_count += 1;
        if point.return_number.is_valid() {
            self.point_count_by_return[u8::from(point.return_number) as usize - 1] += 1;
        }
        self.bounds.grow(Triple {
            x: point.x,
            y: point.y,
            z: point.z,
        });
        Ok(())
    }

    fn write_header(&mut self) -> Result<()> {
        // TODO test point count by return, offsets, etc
        self.header.point_count = self.point_count;
        self.header.bounds = self.bounds;
        try!(self.write.seek(SeekFrom::Start(0)));
        try!(self.write.write_header(self.header));
        for vlr in &self.vlrs {
            try!(self.write.write_vlr(vlr));
        }
        Ok(())
    }

    /// Closes this writer.
    ///
    /// After the writer is closed, and future calls to `write` will error.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::io::Cursor;
    /// # use las::Writer;
    /// let mut writer = Writer::default(Cursor::new(Vec::new())).unwrap();
    /// assert!(writer.write(&Default::default()).is_ok());
    /// writer.close().unwrap();
    /// assert!(writer.write(&Default::default()).is_err());
    /// ```
    pub fn close(&mut self) -> Result<()> {
        if self.closed {
            return Err(Error::ClosedWriter);
        }
        try!(self.write_header());
        self.closed = true;
        Ok(())
    }
}

impl<W: Seek + Write> Drop for Writer<W> {
    fn drop(&mut self) {
        if !self.closed {
            if let Err(err) = self.close() {
                error!("Error while dropping writer: {}", err);
            }
        }
    }
}

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

    use std::io::Cursor;

    use builder::Builder;
    use point::{Classification, Color, NumberOfReturns, Point, ReturnNumber, ScanDirection};
    use reader::Reader;
    use utils::Bounds;
    use version::Version;

    fn point() -> Point {
        Point {
            x: 1.,
            y: 2.,
            z: 3.,
            intensity: 4,
            return_number: ReturnNumber::from(1),
            number_of_returns: NumberOfReturns::from(0b00010000),
            scan_direction: ScanDirection::Positive,
            edge_of_flight_line: false,
            classification: Classification::from(2),
            scan_angle_rank: 2,
            user_data: 3,
            point_source_id: 4,
            gps_time: Some(5.),
            color: Some(Color {
                red: 6,
                green: 7,
                blue: 8,
            }),
            extra_bytes: Vec::new(),
        }
    }

    fn check_point(point: &Point) {
        assert_eq!(1., point.x);
        assert_eq!(2., point.y);
        assert_eq!(3., point.z);
        assert_eq!(4, point.intensity);
        assert_eq!(1, point.return_number);
        assert_eq!(2, point.number_of_returns);
        assert_eq!(ScanDirection::Positive, point.scan_direction);
        assert!(!point.edge_of_flight_line);
        assert_eq!(2, point.classification);
        assert_eq!(2, point.scan_angle_rank);
        assert_eq!(3, point.user_data);
        assert_eq!(4, point.point_source_id);
    }

    fn check_point_0(point: Point) {
        check_point(&point);
        assert!(point.gps_time.is_none());
        assert!(point.color.is_none());
    }

    fn check_point_1(point: Point) {
        check_point(&point);
        assert_eq!(5., point.gps_time.unwrap());
        assert!(point.color.is_none());
    }

    fn check_point_2(point: Point) {
        check_point(&point);
        assert!(point.gps_time.is_none());
        let color = point.color.unwrap();
        assert_eq!(6, color.red);
        assert_eq!(7, color.green);
        assert_eq!(8, color.blue);
    }

    fn check_point_3(point: Point) {
        check_point(&point);
        assert_eq!(5., point.gps_time.unwrap());
        let color = point.color.unwrap();
        assert_eq!(6, color.red);
        assert_eq!(7, color.green);
        assert_eq!(8, color.blue);
    }

    #[test]
    fn write_zero_points() {
        let mut cursor = Cursor::new(Vec::new());
        Writer::default(&mut cursor).unwrap();
        cursor.set_position(0);
        let mut reader = Reader::new(cursor).unwrap();
        assert!(reader.read().unwrap().is_none());
    }

    #[test]
    fn write_one_point_default() {
        let mut cursor = Cursor::new(Vec::new());
        {
            let mut writer = Writer::default(&mut cursor).unwrap();
            writer.write(&point()).unwrap();
        }
        cursor.set_position(0);
        let mut reader = Reader::new(cursor).unwrap();
        check_point_0(reader.read().unwrap().unwrap());
        assert!(reader.read().unwrap().is_none());
    }

    #[test]
    fn write_one_point_format_1() {
        let mut cursor = Cursor::new(Vec::new());
        {
            let mut builder = Builder::new();
            builder.header.point_format = 1.into();
            let mut writer = builder.writer(&mut cursor).unwrap();
            writer.write(&point()).unwrap();
        }
        cursor.set_position(0);
        let mut reader = Reader::new(cursor).unwrap();
        check_point_1(reader.read().unwrap().unwrap());
        assert!(reader.read().unwrap().is_none());
    }

    #[test]
    fn write_one_point_format_2() {
        let mut cursor = Cursor::new(Vec::new());
        {
            let mut builder = Builder::new();
            builder.header.point_format = 2.into();
            let mut writer = builder.writer(&mut cursor).unwrap();
            writer.write(&point()).unwrap();
        }
        cursor.set_position(0);
        let mut reader = Reader::new(cursor).unwrap();
        check_point_2(reader.read().unwrap().unwrap());
        assert!(reader.read().unwrap().is_none());
    }

    #[test]
    fn write_one_point_format_3() {
        let mut cursor = Cursor::new(Vec::new());
        {
            let mut builder = Builder::new();
            builder.header.point_format = 3.into();
            let mut writer = builder.writer(&mut cursor).unwrap();
            writer.write(&point()).unwrap();
        }
        cursor.set_position(0);
        let mut reader = Reader::new(cursor).unwrap();
        check_point_3(reader.read().unwrap().unwrap());
        assert!(reader.read().unwrap().is_none());
    }

    #[test]
    fn try_write_point_format_1_no_time() {
        let mut builder = Builder::new();
        builder.header.point_format = 1.into();
        let mut writer = builder.writer(Cursor::new(Vec::new())).unwrap();
        let mut point = point();
        point.gps_time = None;
        assert!(writer.write(&point).is_err());
    }

    #[test]
    fn try_write_point_format_2_no_color() {
        let mut builder = Builder::new();
        builder.header.point_format = 2.into();
        let mut writer = builder.writer(Cursor::new(Vec::new())).unwrap();
        let mut point = point();
        point.color = None;
        assert!(writer.write(&point).is_err());
    }

    #[test]
    fn write_point_count() {
        let mut cursor = Cursor::new(Vec::new());
        {
            let mut writer = Writer::default(&mut cursor).unwrap();
            writer.write(&point()).unwrap();
        }
        cursor.set_position(0);
        assert_eq!(1, Reader::new(cursor).unwrap().header.point_count);
    }

    #[test]
    fn write_two_points() {
        let mut cursor = Cursor::new(Vec::new());
        {
            let mut writer = Writer::default(&mut cursor).unwrap();
            writer.write(&point()).unwrap();
            writer.write(&point()).unwrap();
        }
        cursor.set_position(0);
        let mut reader = Reader::new(cursor).unwrap();
        assert!(reader.read().unwrap().is_some());
        assert!(reader.read().unwrap().is_some());
        assert!(reader.read().unwrap().is_none());
    }

    #[test]
    fn write_bounds() {
        let mut cursor = Cursor::new(Vec::new());
        {
            let mut writer = Writer::default(&mut cursor).unwrap();
            writer.write(&point()).unwrap();
        }
        cursor.set_position(0);
        let reader = Reader::new(cursor).unwrap();
        assert_eq!(Bounds::new(1., 2., 3., 1., 2., 3.), reader.header.bounds);
    }

    #[test]
    fn close_the_writer() {
        let mut writer = Writer::default(Cursor::new(Vec::new())).unwrap();
        writer.close().is_ok();
        assert!(writer.write(&point()).is_err());
        assert!(writer.close().is_err());
    }

    #[test]
    fn write_version() {
        let mut cursor = Cursor::new(Vec::new());
        let mut builder = Builder::new();
        builder.header.version = (1, 0).into();
        builder.writer(&mut cursor).unwrap();
        cursor.set_position(0);
        assert_eq!(Version::from((1, 0)),
                   Reader::new(&mut cursor).unwrap().header.version);
    }

    #[test]
    fn write_zero_return_number() {
        let mut writer = Writer::default(Cursor::new(Vec::new())).unwrap();
        writer.write(&Default::default()).unwrap();
    }

    #[test]
    fn write_extra_bytes() {
        let mut cursor = Cursor::new(Vec::new());
        {
            let mut builder = Builder::new();
            builder.header.extra_bytes = 5;
            let mut writer = builder.writer(&mut cursor).unwrap();
            let mut point = point();
            point.extra_bytes = b"Hello".to_vec();
            writer.write(&point).unwrap();
        }
        cursor.set_position(0);
        let point = Reader::new(cursor).unwrap().read_to_end().unwrap().pop().unwrap();
        assert_eq!(b"Hello", &point.extra_bytes[..]);
    }

    #[test]
    fn writer_from_path() {
        assert!(Writer::from_path("/dev/null").is_ok());
    }

    #[test]
    fn builder_writer_for_path() {
        assert!(Builder::new().writer_from_path("/dev/null").is_ok());
    }

    #[test]
    fn disallow_file_source_id_wipe() {
        let mut builder = Builder::new();
        builder.header.file_source_id = 1;
        builder.header.version = (1, 0).into();
        assert!(builder.writer(Cursor::new(Vec::new())).is_err());
    }

    #[test]
    fn disallow_global_encoding_downcast() {
        let mut builder = Builder::new();
        builder.header.global_encoding = 1.into();
        builder.header.version = (1, 0).into();
        assert!(builder.writer(Cursor::new(Vec::new())).is_err());
    }
}
<|endoftext|>


<commit_before>// Implements http://rosettacode.org/wiki/Sieve_of_Eratosthenes

use std::iter::{range_inclusive, range_step};

fn int_sqrt(n: uint) -> uint {
    (n as f64).sqrt() as uint
}

// Return the prime numbers up to limit
fn simple_sieve(limit: uint) -> Vec<uint> {
    if limit < 2 {
        return vec!();
    }

    let mut primes = Vec::from_elem(limit + 1, true);

    for prime in range_inclusive(2, int_sqrt(limit) + 1) {
        if *primes.get(prime) {
            for multiple in range_step(prime * prime, limit + 1, prime) {
                *primes.get_mut(multiple) = false
            }
        }
    }

    range_inclusive(2, limit).filter(|&n| *primes.get(n)).collect()
}

#[cfg(not(test))]
fn main() {
    println!("{}", simple_sieve(100))
}

#[test]
fn test_basic() {
    let primes = simple_sieve(30);
    assert!(primes.as_slice() == [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]);
}
<commit_msg>sieve_eratothenes to us eindex.<commit_after>// Implements http://rosettacode.org/wiki/Sieve_of_Eratosthenes

use std::iter::{range_inclusive, range_step};

fn int_sqrt(n: uint) -> uint {
    (n as f64).sqrt() as uint
}

// Return the prime numbers up to limit
fn simple_sieve(limit: uint) -> Vec<uint> {
    if limit < 2 {
        return vec!();
    }

    let mut primes = Vec::from_elem(limit + 1, true);

    for prime in range_inclusive(2, int_sqrt(limit) + 1) {
        if primes[prime] {
            for multiple in range_step(prime * prime, limit + 1, prime) {
                *primes.get_mut(multiple) = false
            }
        }
    }

    range_inclusive(2, limit).filter(|&n| primes[n]).collect()
}

#[cfg(not(test))]
fn main() {
    println!("{}", simple_sieve(100))
}

#[test]
fn test_basic() {
    let primes = simple_sieve(30);
    assert!(primes.as_slice() == [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]);
}
<|endoftext|>


<commit_before>#[crate_id = "github.com/csherratt/snowmew#snowmew-render:0.1"];
#[license = "ASL2"];
#[crate_type = "lib"];
#[comment = "A game engine in rust"];
#[allow(dead_code)];

extern mod std;
extern mod glfw;
extern mod cgmath;
extern mod snowmew;
extern mod cow;
extern mod gl;
extern mod OpenCL;
extern mod ovr = "ovr-rs";

use std::ptr;
use std::vec;
use std::comm::{Chan, Port};

//use drawlist::Drawlist;
use drawlist::{Expand, DrawCommand, Draw, BindShader, BindVertexBuffer, SetMatrix};

use cgmath::matrix::{Mat4, Matrix};
use cow::join::join_maps;

use snowmew::core::{object_key};
use snowmew::camera::Camera;

use snowmew::display::Display;

mod db;
mod shader;
mod vertex_buffer;
mod drawlist;
mod drawlist_cl;
mod hmd;

pub struct RenderManager {
    db: db::Graphics,
    hmd: Option<hmd::HMD>,
    render_chan: Chan<(db::Graphics, object_key, Mat4<f32>)>,
    result_port: Port<Option<~[DrawCommand]>>,
}

fn render_db<'a>(db: db::Graphics, scene: object_key, camera: Mat4<f32>, chan: &Chan<Option<~[DrawCommand]>>)
{
    let mut list = Expand::new(join_maps(db.current.walk_in_camera(scene, &camera), db.current.walk_drawables()), &db);

    let mut out = vec::with_capacity(512);
    for cmd in list {
        out.push(cmd);

        if out.len() == 512 {
            chan.send(Some(out));
            out = vec::with_capacity(512);
        }
    }

    chan.send(Some(out));
    chan.send(None);
}

impl RenderManager
{
    pub fn new(db: snowmew::core::Database) -> RenderManager
    {
        // todo move!
        gl::Enable(gl::SCISSOR_TEST);
        gl::Enable(gl::DEPTH_TEST);
        gl::Enable(gl::CULL_FACE);
        gl::Enable(gl::LINE_SMOOTH);
        gl::Enable(gl::BLEND);
        gl::CullFace(gl::BACK);

        let (render_port, render_chan): (Port<(db::Graphics, object_key, Mat4<f32>)>, Chan<(db::Graphics, object_key, Mat4<f32>)>) = Chan::new();
        let (result_port, result_chan): (Port<Option<~[DrawCommand]>>, Chan<Option<~[DrawCommand]>>) = Chan::new();

        spawn(proc() {
            let result_chan = result_chan;
            //let (device, context, queue) = OpenCL::util::create_compute_context_prefer(OpenCL::util::GPU_PREFERED).unwrap();
            //let mut offload = ObjectCullOffloadContext::new(&context, &device, queue);

            for (db, scene, camera) in render_port.iter() {
                render_db(db, scene, camera, &result_chan);
            }
        });

        RenderManager {
            db: db::Graphics::new(db),
            hmd: None,
            result_port: result_port,
            render_chan: render_chan
        }
    }

    pub fn load(&mut self)
    {
        self.db.load();
    }

    pub fn update(&mut self, db: snowmew::core::Database)
    {
        self.db.update(db);
    }

    fn drawsink(&mut self, projection: Mat4<f32>)
    {
        let mut shader = None;
        for block in self.result_port.iter() {
            let block = match block {
                Some(block) => { block },
                None => {break;}
            };

            for &item in block.iter() {
                match item {
                    BindShader(id) => {
                        shader = self.db.shaders.find(&id);
                        shader.unwrap().bind();
                        shader.unwrap().set_projection(&projection);
                    },
                    BindVertexBuffer(id) => {
                        let vb = self.db.vertex.find(&id);
                        vb.unwrap().bind();
                    },
                    SetMatrix(mat) => {
                        shader.unwrap().set_position(&mat);
                    },
                    Draw(geo) => {
                        unsafe {
                            gl::DrawElements(gl::TRIANGLES, geo.count as i32, gl::UNSIGNED_INT, ptr::null());
                        }
                    },
                }
            }
        }
    }

    fn swap_buffers(&mut self, win: &mut Display)
    {
        win.swap_buffers();
        unsafe {
            gl::DrawElements(gl::TRIANGLES, 6i32, gl::UNSIGNED_INT, ptr::null());
            let sync = gl::FenceSync(gl::SYNC_GPU_COMMANDS_COMPLETE, 0);
            gl::ClientWaitSync(sync, gl::SYNC_FLUSH_COMMANDS_BIT, 1_000_000_000u64);
        }
    }

    pub fn render(&mut self, scene: object_key, camera: object_key, win: &mut Display)
    {
        if win.is_hmd() {
            self.render_vr(scene, camera, win)
        } else {
            self.render_normal(scene, camera, win)
        }
    }

    pub fn render_normal(&mut self, scene: object_key, camera: object_key, win: &mut Display)
    {
        let camera_rot = self.db.current.location(camera).unwrap().get().rot;
        let camera_trans = self.db.current.position(camera);
        let camera = Camera::new(camera_rot, camera_trans.clone()).get_matrices(win);

        let projection = camera.projection.mul_m(&camera.view);

        self.render_chan.send((self.db.clone(), scene, projection));

        gl::ClearColor(0., 0., 0., 1.);
        gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);

        self.drawsink(projection);

        self.swap_buffers(win);
    }

    fn render_vr(&mut self, scene: object_key, camera: object_key, win: &mut Display)
    {
        let hmd_info = win.hmd();

        if self.hmd.is_none() {
            self.hmd = Some(hmd::HMD::new(1.7, &hmd_info));
        }

        let camera_rot = self.db.current.location(camera).unwrap().get().rot;
        let camera_trans = self.db.current.position(camera);
        let (left, right) = Camera::new(camera_rot, camera_trans.clone()).get_matrices_ovr(win);

        self.hmd.unwrap().set_left(&self.db, &hmd_info);
        let projection = left.projection.mul_m(&left.view);
        self.render_chan.send((self.db.clone(), scene, projection));
        self.drawsink(projection);

        self.hmd.unwrap().set_right(&self.db, &hmd_info);
        let projection = right.projection.mul_m(&right.view);
        self.render_chan.send((self.db.clone(), scene, projection));
        self.drawsink(projection);

        self.hmd.unwrap().draw_screen(&self.db, &hmd_info);

        self.swap_buffers(win);
    }
}<commit_msg>added parallel ovr render<commit_after>#[crate_id = "github.com/csherratt/snowmew#snowmew-render:0.1"];
#[license = "ASL2"];
#[crate_type = "lib"];
#[comment = "A game engine in rust"];
#[allow(dead_code)];

extern mod std;
extern mod glfw;
extern mod cgmath;
extern mod snowmew;
extern mod cow;
extern mod gl;
extern mod OpenCL;
extern mod ovr = "ovr-rs";

use std::ptr;
use std::vec;
use std::comm::{Chan, Port};

//use drawlist::Drawlist;
use drawlist::{Expand, DrawCommand, Draw, BindShader, BindVertexBuffer, SetMatrix};

use cgmath::matrix::{Mat4, Matrix};
use cow::join::join_maps;

use snowmew::core::{object_key};
use snowmew::camera::Camera;

use snowmew::display::Display;

mod db;
mod shader;
mod vertex_buffer;
mod drawlist;
mod drawlist_cl;
mod hmd;

pub struct RenderManager {
    db: db::Graphics,
    hmd: Option<hmd::HMD>,
    render_chans: ~[Chan<(db::Graphics, object_key, Mat4<f32>)>],
    result_ports: ~[Port<Option<~[DrawCommand]>>]
}

fn render_db<'a>(db: db::Graphics, scene: object_key, camera: Mat4<f32>, chan: &Chan<Option<~[DrawCommand]>>)
{
    let mut list = Expand::new(join_maps(db.current.walk_in_camera(scene, &camera), db.current.walk_drawables()), &db);

    let mut out = vec::with_capacity(512);
    for cmd in list {
        out.push(cmd);

        if out.len() == 512 {
            chan.send(Some(out));
            out = vec::with_capacity(512);
        }
    }

    chan.send(Some(out));
    chan.send(None);
}

impl RenderManager
{
    pub fn new(db: snowmew::core::Database) -> RenderManager
    {
        // todo move!
        gl::Enable(gl::SCISSOR_TEST);
        gl::Enable(gl::DEPTH_TEST);
        gl::Enable(gl::CULL_FACE);
        gl::Enable(gl::LINE_SMOOTH);
        gl::Enable(gl::BLEND);
        gl::CullFace(gl::BACK);

        let mut result_ports = ~[];
        let mut render_chans = ~[];

        for _ in range(0, 2) {
            let (render_port, render_chan): (Port<(db::Graphics, object_key, Mat4<f32>)>, Chan<(db::Graphics, object_key, Mat4<f32>)>) = Chan::new();
            let (result_port, result_chan): (Port<Option<~[DrawCommand]>>, Chan<Option<~[DrawCommand]>>) = Chan::new();

            spawn(proc() {
                let result_chan = result_chan;
                for (db, scene, camera) in render_port.iter() {
                    render_db(db, scene, camera, &result_chan);
                }
            });

            result_ports.push(result_port);
            render_chans.push(render_chan);

        }

        RenderManager {
            db: db::Graphics::new(db),
            hmd: None,
            result_ports: result_ports,
            render_chans: render_chans
        }
    }

    pub fn load(&mut self)
    {
        self.db.load();
    }

    pub fn update(&mut self, db: snowmew::core::Database)
    {
        self.db.update(db);
    }

    fn drawsink(&mut self, projection: Mat4<f32>, port: int)
    {
        let mut shader = None;
        for block in self.result_ports[port].iter() {
            let block = match block {
                Some(block) => { block },
                None => {break;}
            };

            for &item in block.iter() {
                match item {
                    BindShader(id) => {
                        shader = self.db.shaders.find(&id);
                        shader.unwrap().bind();
                        shader.unwrap().set_projection(&projection);
                    },
                    BindVertexBuffer(id) => {
                        let vb = self.db.vertex.find(&id);
                        vb.unwrap().bind();
                    },
                    SetMatrix(mat) => {
                        shader.unwrap().set_position(&mat);
                    },
                    Draw(geo) => {
                        unsafe {
                            gl::DrawElements(gl::TRIANGLES, geo.count as i32, gl::UNSIGNED_INT, ptr::null());
                        }
                    },
                }
            }
        }
    }

    fn swap_buffers(&mut self, win: &mut Display)
    {
        win.swap_buffers();
        unsafe {
            gl::DrawElements(gl::TRIANGLES, 6i32, gl::UNSIGNED_INT, ptr::null());
            let sync = gl::FenceSync(gl::SYNC_GPU_COMMANDS_COMPLETE, 0);
            gl::ClientWaitSync(sync, gl::SYNC_FLUSH_COMMANDS_BIT, 1_000_000_000u64);
            gl::DeleteSync(sync);
        }
    }

    pub fn render(&mut self, scene: object_key, camera: object_key, win: &mut Display)
    {
        if win.is_hmd() {
            self.render_vr(scene, camera, win)
        } else {
            self.render_normal(scene, camera, win)
        }
    }

    fn render_normal(&mut self, scene: object_key, camera: object_key, win: &mut Display)
    {
        let camera_rot = self.db.current.location(camera).unwrap().get().rot;
        let camera_trans = self.db.current.position(camera);
        let camera = Camera::new(camera_rot, camera_trans.clone()).get_matrices(win);

        let projection = camera.projection.mul_m(&camera.view);

        self.render_chans[0].send((self.db.clone(), scene, projection));

        gl::ClearColor(0., 0., 0., 1.);
        gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);

        self.drawsink(projection, 0);

        self.swap_buffers(win);
    }

    fn render_vr(&mut self, scene: object_key, camera: object_key, win: &mut Display)
    {
        let hmd_info = win.hmd();

        if self.hmd.is_none() {
            self.hmd = Some(hmd::HMD::new(1.7, &hmd_info));
        }

        let camera_rot = self.db.current.location(camera).unwrap().get().rot;
        let camera_trans = self.db.current.position(camera);
        let (left, right) = Camera::new(camera_rot, camera_trans.clone()).get_matrices_ovr(win);

        let proj_left = left.projection.mul_m(&left.view);
        self.render_chans[0].send((self.db.clone(), scene, proj_left));
        let proj_right = right.projection.mul_m(&right.view);
        self.render_chans[1].send((self.db.clone(), scene, proj_right));

        self.hmd.unwrap().set_left(&self.db, &hmd_info);
        self.drawsink(proj_left, 0);

        self.hmd.unwrap().set_right(&self.db, &hmd_info);
        self.drawsink(proj_right, 1);

        self.hmd.unwrap().draw_screen(&self.db, &hmd_info);
        self.swap_buffers(win);
    }
}<|endoftext|>