<commit_before>use std::fmt;
use enum_set::CLike;
use bit_field::BitField;
use std::mem;

pub enum StackPointer {
    MSP(u32),
    PSP(u32),
}

pub struct PSR {
    pub value: u32,
}

pub trait Apsr {
    fn get_n(&self) -> bool;
    fn set_n(&mut self, n: bool);

    fn get_z(&self) -> bool;
    fn set_z(&mut self, z: bool);

    fn get_c(&self) -> bool;
    fn set_c(&mut self, c: bool);

    fn get_v(&self) -> bool;
    fn set_v(&mut self, v: bool);

    fn get_q(&self) -> bool;
    fn set_q(&mut self, q: bool);
}

pub trait Ipsr {
    fn get_exception_number(&self) -> u8;
}

// Execution Program Status register
//
// A view to PSR register containing the data.
pub trait Epsr {
    fn set_t(&mut self, t: bool);
    fn get_t(&self) -> bool;
}

impl Apsr for PSR {
    fn get_n(&self) -> bool {
        (*self).value.get_bit(31)
    }
    fn set_n(&mut self, n: bool) {
        (*self).value.set_bit(31, n);
    }

    fn get_z(&self) -> bool {
        (*self).value.get_bit(30)
    }
    fn set_z(&mut self, z: bool) {
        (*self).value.set_bit(30, z);
    }

    fn get_c(&self) -> bool {
        (*self).value.get_bit(29)
    }
    fn set_c(&mut self, c: bool) {
        (*self).value.set_bit(29, c);
    }
    fn get_v(&self) -> bool {
        (*self).value.get_bit(28)
    }
    fn set_v(&mut self, v: bool) {
        (*self).value.set_bit(28, v);
    }

    fn get_q(&self) -> bool {
        (*self).value.get_bit(27)
    }
    fn set_q(&mut self, q: bool) {
        (*self).value.set_bit(27, q);
    }
}

impl Epsr for PSR {
    fn get_t(&self) -> bool {
        (*self).value.get_bit(24)
    }
    fn set_t(&mut self, n: bool) {
        (*self).value.set_bit(24, n);
    }
}

impl Ipsr for PSR {
    fn get_exception_number(&self) -> u8 {
        (*self).value.get_bits(0..6) as u8
    }
}

#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u32)]
pub enum Reg {
    R0,
    R1,
    R2,
    R3,
    R4,
    R5,
    R6,
    R7,
    R8,
    R9,
    R10,
    R11,
    R12,
    SP,
    LR,
    PC,
}

#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u32)]
pub enum SpecialReg {
    APSR,
    IAPSR,
    EAPSR,
    XPSR,
    IPSR,
    EPSR,
    IEPSR,
    MSP,
    PSP,
    PRIMASK,
    CONTROL,
}

impl CLike for Reg {
    fn to_u32(&self) -> u32 {
        *self as u32
    }

    unsafe fn from_u32(v: u32) -> Reg {
        mem::transmute(v)
    }
}

impl Reg {
    pub fn value(&self) -> usize {
        match *self {
            Reg::R0 => 0,
            Reg::R1 => 1,
            Reg::R2 => 2,
            Reg::R3 => 3,
            Reg::R4 => 4,
            Reg::R5 => 5,
            Reg::R6 => 6,
            Reg::R7 => 7,
            Reg::R8 => 8,
            Reg::R9 => 9,
            Reg::R10 => 10,
            Reg::R11 => 11,
            Reg::R12 => 12,
            Reg::SP => 13,
            Reg::LR => 14,
            Reg::PC => 15,
        }
    }

    pub fn from_u16(n: u16) -> Option<Reg> {
        match n {
            0 => Some(Reg::R0),
            1 => Some(Reg::R1),
            2 => Some(Reg::R2),
            3 => Some(Reg::R3),
            4 => Some(Reg::R4),
            5 => Some(Reg::R5),
            6 => Some(Reg::R6),
            7 => Some(Reg::R7),
            8 => Some(Reg::R8),
            9 => Some(Reg::R9),
            10 => Some(Reg::R10),
            11 => Some(Reg::R11),
            12 => Some(Reg::R12),
            13 => Some(Reg::SP),
            14 => Some(Reg::LR),
            15 => Some(Reg::PC),
            _ => None,
        }
    }
}

impl From<u8> for Reg {
    fn from(value: u8) -> Self {
        match value & 0xf {
            0 => Reg::R0,
            1 => Reg::R1,
            2 => Reg::R2,
            3 => Reg::R3,
            4 => Reg::R4,
            5 => Reg::R5,
            6 => Reg::R6,
            7 => Reg::R7,
            8 => Reg::R8,
            9 => Reg::R9,
            10 => Reg::R10,
            11 => Reg::R11,
            12 => Reg::R12,
            13 => Reg::SP,
            14 => Reg::LR,
            15 => Reg::PC,
            _ => Reg::R0,
        }
    }
}

impl From<Reg> for u8 {
    fn from(value: Reg) -> Self {
        match value {
            Reg::R0 => 0,
            Reg::R1 => 1,
            Reg::R2 => 2,
            Reg::R3 => 3,
            Reg::R4 => 4,
            Reg::R5 => 5,
            Reg::R6 => 6,
            Reg::R7 => 7,
            Reg::R8 => 8,
            Reg::R9 => 9,
            Reg::R10 => 10,
            Reg::R11 => 11,
            Reg::R12 => 12,
            Reg::SP => 13,
            Reg::LR => 14,
            Reg::PC => 15,
        }
    }
}

impl From<Reg> for usize {
    fn from(value: Reg) -> Self {
        match value {
            Reg::R0 => 0,
            Reg::R1 => 1,
            Reg::R2 => 2,
            Reg::R3 => 3,
            Reg::R4 => 4,
            Reg::R5 => 5,
            Reg::R6 => 6,
            Reg::R7 => 7,
            Reg::R8 => 8,
            Reg::R9 => 9,
            Reg::R10 => 10,
            Reg::R11 => 11,
            Reg::R12 => 12,
            Reg::SP => 13,
            Reg::LR => 14,
            Reg::PC => 15,
        }
    }
}

impl From<u8> for SpecialReg {
    fn from(value: u8) -> Self {
        match value & 0x1f {
            0 => SpecialReg::APSR,
            1 => SpecialReg::IAPSR,
            2 => SpecialReg::EAPSR,
            3 => SpecialReg::XPSR,
            5 => SpecialReg::IPSR,
            6 => SpecialReg::EPSR,
            7 => SpecialReg::IEPSR,
            8 => SpecialReg::MSP,
            9 => SpecialReg::PSP,
            16 => SpecialReg::PRIMASK,
            20 => SpecialReg::CONTROL,
            _ => SpecialReg::APSR,
        }
    }
}

impl fmt::Display for Reg {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Reg::R0 => write!(f, "R0"),
            Reg::R1 => write!(f, "R1"),
            Reg::R2 => write!(f, "R2"),
            Reg::R3 => write!(f, "R3"),
            Reg::R4 => write!(f, "R4"),
            Reg::R5 => write!(f, "R5"),
            Reg::R6 => write!(f, "R6"),
            Reg::R7 => write!(f, "R7"),
            Reg::R8 => write!(f, "R8"),
            Reg::R9 => write!(f, "R9"),
            Reg::R10 => write!(f, "R10"),
            Reg::R11 => write!(f, "R11"),
            Reg::R12 => write!(f, "R12"),
            Reg::SP => write!(f, "SP"),
            Reg::LR => write!(f, "LR"),
            Reg::PC => write!(f, "PC"),
        }
    }
}

impl fmt::Display for SpecialReg {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            SpecialReg::APSR => write!(f, "APSR"),
            SpecialReg::IAPSR => write!(f, "IAPSR"),
            SpecialReg::EAPSR => write!(f, "EAPSR"),
            SpecialReg::XPSR => write!(f, "XPSR"),
            SpecialReg::IPSR => write!(f, "IPSR"),
            SpecialReg::EPSR => write!(f, "EPSR"),
            SpecialReg::IEPSR => write!(f, "IEPSR"),
            SpecialReg::MSP => write!(f, "MSP"),
            SpecialReg::PSP => write!(f, "PSP"),
            SpecialReg::PRIMASK => write!(f, "PRIMASK"),
            SpecialReg::CONTROL => write!(f, "CONTROL"),
        }
    }
}

pub struct Control {
    pub n_priv: bool,
    pub sp_sel: bool,
}

impl From<Control> for u8 {
    fn from(control: Control) -> Self {
        control.n_priv as u8 + ((control.sp_sel as u8) << 1)
    }
}
<commit_msg>Keep from_u16() for now<commit_after>use std::fmt;
use enum_set::CLike;
use bit_field::BitField;
use std::mem;

pub enum StackPointer {
    MSP(u32),
    PSP(u32),
}

pub struct PSR {
    pub value: u32,
}

pub trait Apsr {
    fn get_n(&self) -> bool;
    fn set_n(&mut self, n: bool);

    fn get_z(&self) -> bool;
    fn set_z(&mut self, z: bool);

    fn get_c(&self) -> bool;
    fn set_c(&mut self, c: bool);

    fn get_v(&self) -> bool;
    fn set_v(&mut self, v: bool);

    fn get_q(&self) -> bool;
    fn set_q(&mut self, q: bool);
}

pub trait Ipsr {
    fn get_exception_number(&self) -> u8;
}

// Execution Program Status register
//
// A view to PSR register containing the data.
pub trait Epsr {
    fn set_t(&mut self, t: bool);
    fn get_t(&self) -> bool;
}

impl Apsr for PSR {
    fn get_n(&self) -> bool {
        (*self).value.get_bit(31)
    }
    fn set_n(&mut self, n: bool) {
        (*self).value.set_bit(31, n);
    }

    fn get_z(&self) -> bool {
        (*self).value.get_bit(30)
    }
    fn set_z(&mut self, z: bool) {
        (*self).value.set_bit(30, z);
    }

    fn get_c(&self) -> bool {
        (*self).value.get_bit(29)
    }
    fn set_c(&mut self, c: bool) {
        (*self).value.set_bit(29, c);
    }
    fn get_v(&self) -> bool {
        (*self).value.get_bit(28)
    }
    fn set_v(&mut self, v: bool) {
        (*self).value.set_bit(28, v);
    }

    fn get_q(&self) -> bool {
        (*self).value.get_bit(27)
    }
    fn set_q(&mut self, q: bool) {
        (*self).value.set_bit(27, q);
    }
}

impl Epsr for PSR {
    fn get_t(&self) -> bool {
        (*self).value.get_bit(24)
    }
    fn set_t(&mut self, n: bool) {
        (*self).value.set_bit(24, n);
    }
}

impl Ipsr for PSR {
    fn get_exception_number(&self) -> u8 {
        (*self).value.get_bits(0..6) as u8
    }
}

#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u32)]
pub enum Reg {
    R0,
    R1,
    R2,
    R3,
    R4,
    R5,
    R6,
    R7,
    R8,
    R9,
    R10,
    R11,
    R12,
    SP,
    LR,
    PC,
}

#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u32)]
pub enum SpecialReg {
    APSR,
    IAPSR,
    EAPSR,
    XPSR,
    IPSR,
    EPSR,
    IEPSR,
    MSP,
    PSP,
    PRIMASK,
    CONTROL,
}

impl CLike for Reg {
    fn to_u32(&self) -> u32 {
        *self as u32
    }

    unsafe fn from_u32(v: u32) -> Reg {
        mem::transmute(v)
    }
}

impl Reg {
    pub fn value(&self) -> usize {
        match *self {
            Reg::R0 => 0,
            Reg::R1 => 1,
            Reg::R2 => 2,
            Reg::R3 => 3,
            Reg::R4 => 4,
            Reg::R5 => 5,
            Reg::R6 => 6,
            Reg::R7 => 7,
            Reg::R8 => 8,
            Reg::R9 => 9,
            Reg::R10 => 10,
            Reg::R11 => 11,
            Reg::R12 => 12,
            Reg::SP => 13,
            Reg::LR => 14,
            Reg::PC => 15,
        }
    }

    pub fn from_u16(n: u16) -> Option<Reg> {
        match n {
            0 => Some(Reg::R0),
            1 => Some(Reg::R1),
            2 => Some(Reg::R2),
            3 => Some(Reg::R3),
            4 => Some(Reg::R4),
            5 => Some(Reg::R5),
            6 => Some(Reg::R6),
            7 => Some(Reg::R7),
            8 => Some(Reg::R8),
            9 => Some(Reg::R9),
            10 => Some(Reg::R10),
            11 => Some(Reg::R11),
            12 => Some(Reg::R12),
            13 => Some(Reg::SP),
            14 => Some(Reg::LR),
            15 => Some(Reg::PC),
            _ => None,
        }
    }
}

impl From<u8> for Reg {
    fn from(value: u8) -> Self {
        match value & 0xf {
            0 => Reg::R0,
            1 => Reg::R1,
            2 => Reg::R2,
            3 => Reg::R3,
            4 => Reg::R4,
            5 => Reg::R5,
            6 => Reg::R6,
            7 => Reg::R7,
            8 => Reg::R8,
            9 => Reg::R9,
            10 => Reg::R10,
            11 => Reg::R11,
            12 => Reg::R12,
            13 => Reg::SP,
            14 => Reg::LR,
            15 => Reg::PC,
            _ => Reg::R0,
        }
    }
}

impl From<Reg> for u8 {
    fn from(value: Reg) -> Self {
        match value {
            Reg::R0 => 0,
            Reg::R1 => 1,
            Reg::R2 => 2,
            Reg::R3 => 3,
            Reg::R4 => 4,
            Reg::R5 => 5,
            Reg::R6 => 6,
            Reg::R7 => 7,
            Reg::R8 => 8,
            Reg::R9 => 9,
            Reg::R10 => 10,
            Reg::R11 => 11,
            Reg::R12 => 12,
            Reg::SP => 13,
            Reg::LR => 14,
            Reg::PC => 15,
        }
    }
}

impl From<Reg> for usize {
    fn from(value: Reg) -> Self {
        match value {
            Reg::R0 => 0,
            Reg::R1 => 1,
            Reg::R2 => 2,
            Reg::R3 => 3,
            Reg::R4 => 4,
            Reg::R5 => 5,
            Reg::R6 => 6,
            Reg::R7 => 7,
            Reg::R8 => 8,
            Reg::R9 => 9,
            Reg::R10 => 10,
            Reg::R11 => 11,
            Reg::R12 => 12,
            Reg::SP => 13,
            Reg::LR => 14,
            Reg::PC => 15,
        }
    }
}

impl SpecialReg {
    pub fn from_u16(n: u16) -> Option<SpecialReg> {
        match n {
            0 => Some(SpecialReg::APSR),
            1 => Some(SpecialReg::IAPSR),
            2 => Some(SpecialReg::EAPSR),
            3 => Some(SpecialReg::XPSR),
            5 => Some(SpecialReg::IPSR),
            6 => Some(SpecialReg::EPSR),
            7 => Some(SpecialReg::IEPSR),
            8 => Some(SpecialReg::MSP),
            9 => Some(SpecialReg::PSP),
            16 => Some(SpecialReg::PRIMASK),
            20 => Some(SpecialReg::CONTROL),
            _ => None,
        }
    }
}

impl From<u8> for SpecialReg {
    fn from(value: u8) -> Self {
        match value & 0x1f {
            0 => SpecialReg::APSR,
            1 => SpecialReg::IAPSR,
            2 => SpecialReg::EAPSR,
            3 => SpecialReg::XPSR,
            5 => SpecialReg::IPSR,
            6 => SpecialReg::EPSR,
            7 => SpecialReg::IEPSR,
            8 => SpecialReg::MSP,
            9 => SpecialReg::PSP,
            16 => SpecialReg::PRIMASK,
            20 => SpecialReg::CONTROL,
            _ => SpecialReg::APSR,
        }
    }
}

impl fmt::Display for Reg {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Reg::R0 => write!(f, "R0"),
            Reg::R1 => write!(f, "R1"),
            Reg::R2 => write!(f, "R2"),
            Reg::R3 => write!(f, "R3"),
            Reg::R4 => write!(f, "R4"),
            Reg::R5 => write!(f, "R5"),
            Reg::R6 => write!(f, "R6"),
            Reg::R7 => write!(f, "R7"),
            Reg::R8 => write!(f, "R8"),
            Reg::R9 => write!(f, "R9"),
            Reg::R10 => write!(f, "R10"),
            Reg::R11 => write!(f, "R11"),
            Reg::R12 => write!(f, "R12"),
            Reg::SP => write!(f, "SP"),
            Reg::LR => write!(f, "LR"),
            Reg::PC => write!(f, "PC"),
        }
    }
}

impl fmt::Display for SpecialReg {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            SpecialReg::APSR => write!(f, "APSR"),
            SpecialReg::IAPSR => write!(f, "IAPSR"),
            SpecialReg::EAPSR => write!(f, "EAPSR"),
            SpecialReg::XPSR => write!(f, "XPSR"),
            SpecialReg::IPSR => write!(f, "IPSR"),
            SpecialReg::EPSR => write!(f, "EPSR"),
            SpecialReg::IEPSR => write!(f, "IEPSR"),
            SpecialReg::MSP => write!(f, "MSP"),
            SpecialReg::PSP => write!(f, "PSP"),
            SpecialReg::PRIMASK => write!(f, "PRIMASK"),
            SpecialReg::CONTROL => write!(f, "CONTROL"),
        }
    }
}

pub struct Control {
    pub n_priv: bool,
    pub sp_sel: bool,
}

impl From<Control> for u8 {
    fn from(control: Control) -> Self {
        control.n_priv as u8 + ((control.sp_sel as u8) << 1)
    }
}
<|endoftext|>


<commit_before>//! Server Requests
//!
//! These are requests that a `hyper::Server` receives, and include its method,
//! target URI, headers, and message body.
use std::io::{self, Read};
use std::net::SocketAddr;

use buffer::BufReader;
use net::NetworkStream;
use version::{HttpVersion};
use method::Method::{self, Get, Head};
use header::{Headers, ContentLength, TransferEncoding};
use http::h1::{self, Incoming, HttpReader};
use http::h1::HttpReader::{SizedReader, ChunkedReader, EmptyReader};
use uri::RequestUri;

/// A request bundles several parts of an incoming `NetworkStream`, given to a `Handler`.
pub struct Request<'a, 'b: 'a> {
    /// The IP address of the remote connection.
    pub remote_addr: SocketAddr,
    /// The `Method`, such as `Get`, `Post`, etc.
    pub method: Method,
    /// The headers of the incoming request.
    pub headers: Headers,
    /// The target request-uri for this request.
    pub uri: RequestUri,
    /// The version of HTTP for this request.
    pub version: HttpVersion,
    body: HttpReader<&'a mut BufReader<&'b mut NetworkStream>>
}

impl<'a, 'b: 'a> Request<'a, 'b> {
    /// Create a new Request, reading the StartLine and Headers so they are
    /// immediately useful.
    pub fn new(mut stream: &'a mut BufReader<&'b mut NetworkStream>, addr: SocketAddr)
        -> ::Result<Request<'a, 'b>> {

        let Incoming { version, subject: (method, uri), headers } = try!(h1::parse_request(stream));
        debug!("Request Line: {:?} {:?} {:?}", method, uri, version);
        debug!("{:?}", headers);

        let body = if method == Get || method == Head {
            EmptyReader(stream)
        } else if headers.has::<ContentLength>() {
            match headers.get::<ContentLength>() {
                Some(&ContentLength(len)) => SizedReader(stream, len),
                None => unreachable!()
            }
        } else if headers.has::<TransferEncoding>() {
            todo!("check for Transfer-Encoding: chunked");
            ChunkedReader(stream, None)
        } else {
            EmptyReader(stream)
        };

        Ok(Request {
            remote_addr: addr,
            method: method,
            uri: uri,
            headers: headers,
            version: version,
            body: body
        })
    }

    /// Get a reference to the underlying `NetworkStream`.
    #[inline]
    pub fn downcast_ref<T: NetworkStream>(&self) -> Option<&T> {
        self.body.get_ref().get_ref().downcast_ref()
    }

    /// Get a reference to the underlying Ssl stream, if connected
    /// over HTTPS.
    ///
    /// # Example
    ///
    /// ```rust
    /// # extern crate hyper;
    /// # #[cfg(feature = "openssl")]
    /// extern crate openssl;
    /// # #[cfg(feature = "openssl")]
    /// use openssl::ssl::SslStream;
    /// # fn main() {}
    /// # #[cfg(feature = "openssl")]
    /// # fn doc_ssl(req: hyper::server::Request) {
    /// let maybe_ssl = req.ssl::<SslStream>();
    /// # }
    /// ```
    #[inline]
    pub fn ssl<T: NetworkStream>(&self) -> Option<&T> {
        use ::net::HttpsStream;
        match self.downcast_ref() {
            Some(&HttpsStream::Https(ref s)) => Some(s),
            _ => None
        }
    }

    /// Deconstruct a Request into its constituent parts.
    #[inline]
    pub fn deconstruct(self) -> (SocketAddr, Method, Headers,
                                 RequestUri, HttpVersion,
                                 HttpReader<&'a mut BufReader<&'b mut NetworkStream>>) {
        (self.remote_addr, self.method, self.headers,
         self.uri, self.version, self.body)
    }
}

impl<'a, 'b> Read for Request<'a, 'b> {
    #[inline]
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.body.read(buf)
    }
}

#[cfg(test)]
mod tests {
    use buffer::BufReader;
    use header::{Host, TransferEncoding, Encoding};
    use net::NetworkStream;
    use mock::MockStream;
    use super::Request;

    use std::io::{self, Read};
    use std::net::SocketAddr;

    fn sock(s: &str) -> SocketAddr {
        s.parse().unwrap()
    }

    fn read_to_string(mut req: Request) -> io::Result<String> {
        let mut s = String::new();
        try!(req.read_to_string(&mut s));
        Ok(s)
    }

    #[test]
    fn test_get_empty_body() {
        let mut mock = MockStream::with_input(b"\
            GET / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            \r\n\
            I'm a bad request.\r\n\
        ");

        // FIXME: Use Type ascription
        let mock: &mut NetworkStream = &mut mock;
        let mut stream = BufReader::new(mock);

        let req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();
        assert_eq!(read_to_string(req).unwrap(), "".to_owned());
    }

    #[test]
    fn test_head_empty_body() {
        let mut mock = MockStream::with_input(b"\
            HEAD / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            \r\n\
            I'm a bad request.\r\n\
        ");

        // FIXME: Use Type ascription
        let mock: &mut NetworkStream = &mut mock;
        let mut stream = BufReader::new(mock);

        let req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();
        assert_eq!(read_to_string(req).unwrap(), "".to_owned());
    }

    #[test]
    fn test_post_empty_body() {
        let mut mock = MockStream::with_input(b"\
            POST / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            \r\n\
            I'm a bad request.\r\n\
        ");

        // FIXME: Use Type ascription
        let mock: &mut NetworkStream = &mut mock;
        let mut stream = BufReader::new(mock);

        let req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();
        assert_eq!(read_to_string(req).unwrap(), "".to_owned());
    }

    #[test]
    fn test_parse_chunked_request() {
        let mut mock = MockStream::with_input(b"\
            POST / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            Transfer-Encoding: chunked\r\n\
            \r\n\
            1\r\n\
            q\r\n\
            2\r\n\
            we\r\n\
            2\r\n\
            rt\r\n\
            0\r\n\
            \r\n"
        );

        // FIXME: Use Type ascription
        let mock: &mut NetworkStream = &mut mock;
        let mut stream = BufReader::new(mock);

        let req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();

        // The headers are correct?
        match req.headers.get::<Host>() {
            Some(host) => {
                assert_eq!("example.domain", host.hostname);
            },
            None => panic!("Host header expected!"),
        };
        match req.headers.get::<TransferEncoding>() {
            Some(encodings) => {
                assert_eq!(1, encodings.len());
                assert_eq!(Encoding::Chunked, encodings[0]);
            }
            None => panic!("Transfer-Encoding: chunked expected!"),
        };
        // The content is correctly read?
        assert_eq!(read_to_string(req).unwrap(), "qwert".to_owned());
    }

    /// Tests that when a chunk size is not a valid radix-16 number, an error
    /// is returned.
    #[test]
    fn test_invalid_chunk_size_not_hex_digit() {
        let mut mock = MockStream::with_input(b"\
            POST / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            Transfer-Encoding: chunked\r\n\
            \r\n\
            X\r\n\
            1\r\n\
            0\r\n\
            \r\n"
        );

        // FIXME: Use Type ascription
        let mock: &mut NetworkStream = &mut mock;
        let mut stream = BufReader::new(mock);

        let req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();

        assert!(read_to_string(req).is_err());
    }

    /// Tests that when a chunk size contains an invalid extension, an error is
    /// returned.
    #[test]
    fn test_invalid_chunk_size_extension() {
        let mut mock = MockStream::with_input(b"\
            POST / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            Transfer-Encoding: chunked\r\n\
            \r\n\
            1 this is an invalid extension\r\n\
            1\r\n\
            0\r\n\
            \r\n"
        );

        // FIXME: Use Type ascription
        let mock: &mut NetworkStream = &mut mock;
        let mut stream = BufReader::new(mock);

        let req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();

        assert!(read_to_string(req).is_err());
    }

    /// Tests that when a valid extension that contains a digit is appended to
    /// the chunk size, the chunk is correctly read.
    #[test]
    fn test_chunk_size_with_extension() {
        let mut mock = MockStream::with_input(b"\
            POST / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            Transfer-Encoding: chunked\r\n\
            \r\n\
            1;this is an extension with a digit 1\r\n\
            1\r\n\
            0\r\n\
            \r\n"
        );

        // FIXME: Use Type ascription
        let mock: &mut NetworkStream = &mut mock;
        let mut stream = BufReader::new(mock);

        let req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();

        assert_eq!(read_to_string(req).unwrap(), "1".to_owned());
    }

}
<commit_msg>docs(server): fix request.ssl() example to use SslStream<HttpStream><commit_after>//! Server Requests
//!
//! These are requests that a `hyper::Server` receives, and include its method,
//! target URI, headers, and message body.
use std::io::{self, Read};
use std::net::SocketAddr;

use buffer::BufReader;
use net::NetworkStream;
use version::{HttpVersion};
use method::Method::{self, Get, Head};
use header::{Headers, ContentLength, TransferEncoding};
use http::h1::{self, Incoming, HttpReader};
use http::h1::HttpReader::{SizedReader, ChunkedReader, EmptyReader};
use uri::RequestUri;

/// A request bundles several parts of an incoming `NetworkStream`, given to a `Handler`.
pub struct Request<'a, 'b: 'a> {
    /// The IP address of the remote connection.
    pub remote_addr: SocketAddr,
    /// The `Method`, such as `Get`, `Post`, etc.
    pub method: Method,
    /// The headers of the incoming request.
    pub headers: Headers,
    /// The target request-uri for this request.
    pub uri: RequestUri,
    /// The version of HTTP for this request.
    pub version: HttpVersion,
    body: HttpReader<&'a mut BufReader<&'b mut NetworkStream>>
}

impl<'a, 'b: 'a> Request<'a, 'b> {
    /// Create a new Request, reading the StartLine and Headers so they are
    /// immediately useful.
    pub fn new(mut stream: &'a mut BufReader<&'b mut NetworkStream>, addr: SocketAddr)
        -> ::Result<Request<'a, 'b>> {

        let Incoming { version, subject: (method, uri), headers } = try!(h1::parse_request(stream));
        debug!("Request Line: {:?} {:?} {:?}", method, uri, version);
        debug!("{:?}", headers);

        let body = if method == Get || method == Head {
            EmptyReader(stream)
        } else if headers.has::<ContentLength>() {
            match headers.get::<ContentLength>() {
                Some(&ContentLength(len)) => SizedReader(stream, len),
                None => unreachable!()
            }
        } else if headers.has::<TransferEncoding>() {
            todo!("check for Transfer-Encoding: chunked");
            ChunkedReader(stream, None)
        } else {
            EmptyReader(stream)
        };

        Ok(Request {
            remote_addr: addr,
            method: method,
            uri: uri,
            headers: headers,
            version: version,
            body: body
        })
    }

    /// Get a reference to the underlying `NetworkStream`.
    #[inline]
    pub fn downcast_ref<T: NetworkStream>(&self) -> Option<&T> {
        self.body.get_ref().get_ref().downcast_ref()
    }

    /// Get a reference to the underlying Ssl stream, if connected
    /// over HTTPS.
    ///
    /// # Example
    ///
    /// ```rust
    /// # extern crate hyper;
    /// # #[cfg(feature = "openssl")]
    /// extern crate openssl;
    /// # #[cfg(feature = "openssl")]
    /// use openssl::ssl::SslStream;
    /// use hyper::net::HttpStream;
    /// # fn main() {}
    /// # #[cfg(feature = "openssl")]
    /// # fn doc_ssl(req: hyper::server::Request) {
    /// let maybe_ssl = req.ssl::<SslStream<HttpStream>>();
    /// # }
    /// ```
    #[inline]
    pub fn ssl<T: NetworkStream>(&self) -> Option<&T> {
        use ::net::HttpsStream;
        match self.downcast_ref() {
            Some(&HttpsStream::Https(ref s)) => Some(s),
            _ => None
        }
    }

    /// Deconstruct a Request into its constituent parts.
    #[inline]
    pub fn deconstruct(self) -> (SocketAddr, Method, Headers,
                                 RequestUri, HttpVersion,
                                 HttpReader<&'a mut BufReader<&'b mut NetworkStream>>) {
        (self.remote_addr, self.method, self.headers,
         self.uri, self.version, self.body)
    }
}

impl<'a, 'b> Read for Request<'a, 'b> {
    #[inline]
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.body.read(buf)
    }
}

#[cfg(test)]
mod tests {
    use buffer::BufReader;
    use header::{Host, TransferEncoding, Encoding};
    use net::NetworkStream;
    use mock::MockStream;
    use super::Request;

    use std::io::{self, Read};
    use std::net::SocketAddr;

    fn sock(s: &str) -> SocketAddr {
        s.parse().unwrap()
    }

    fn read_to_string(mut req: Request) -> io::Result<String> {
        let mut s = String::new();
        try!(req.read_to_string(&mut s));
        Ok(s)
    }

    #[test]
    fn test_get_empty_body() {
        let mut mock = MockStream::with_input(b"\
            GET / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            \r\n\
            I'm a bad request.\r\n\
        ");

        // FIXME: Use Type ascription
        let mock: &mut NetworkStream = &mut mock;
        let mut stream = BufReader::new(mock);

        let req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();
        assert_eq!(read_to_string(req).unwrap(), "".to_owned());
    }

    #[test]
    fn test_head_empty_body() {
        let mut mock = MockStream::with_input(b"\
            HEAD / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            \r\n\
            I'm a bad request.\r\n\
        ");

        // FIXME: Use Type ascription
        let mock: &mut NetworkStream = &mut mock;
        let mut stream = BufReader::new(mock);

        let req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();
        assert_eq!(read_to_string(req).unwrap(), "".to_owned());
    }

    #[test]
    fn test_post_empty_body() {
        let mut mock = MockStream::with_input(b"\
            POST / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            \r\n\
            I'm a bad request.\r\n\
        ");

        // FIXME: Use Type ascription
        let mock: &mut NetworkStream = &mut mock;
        let mut stream = BufReader::new(mock);

        let req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();
        assert_eq!(read_to_string(req).unwrap(), "".to_owned());
    }

    #[test]
    fn test_parse_chunked_request() {
        let mut mock = MockStream::with_input(b"\
            POST / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            Transfer-Encoding: chunked\r\n\
            \r\n\
            1\r\n\
            q\r\n\
            2\r\n\
            we\r\n\
            2\r\n\
            rt\r\n\
            0\r\n\
            \r\n"
        );

        // FIXME: Use Type ascription
        let mock: &mut NetworkStream = &mut mock;
        let mut stream = BufReader::new(mock);

        let req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();

        // The headers are correct?
        match req.headers.get::<Host>() {
            Some(host) => {
                assert_eq!("example.domain", host.hostname);
            },
            None => panic!("Host header expected!"),
        };
        match req.headers.get::<TransferEncoding>() {
            Some(encodings) => {
                assert_eq!(1, encodings.len());
                assert_eq!(Encoding::Chunked, encodings[0]);
            }
            None => panic!("Transfer-Encoding: chunked expected!"),
        };
        // The content is correctly read?
        assert_eq!(read_to_string(req).unwrap(), "qwert".to_owned());
    }

    /// Tests that when a chunk size is not a valid radix-16 number, an error
    /// is returned.
    #[test]
    fn test_invalid_chunk_size_not_hex_digit() {
        let mut mock = MockStream::with_input(b"\
            POST / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            Transfer-Encoding: chunked\r\n\
            \r\n\
            X\r\n\
            1\r\n\
            0\r\n\
            \r\n"
        );

        // FIXME: Use Type ascription
        let mock: &mut NetworkStream = &mut mock;
        let mut stream = BufReader::new(mock);

        let req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();

        assert!(read_to_string(req).is_err());
    }

    /// Tests that when a chunk size contains an invalid extension, an error is
    /// returned.
    #[test]
    fn test_invalid_chunk_size_extension() {
        let mut mock = MockStream::with_input(b"\
            POST / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            Transfer-Encoding: chunked\r\n\
            \r\n\
            1 this is an invalid extension\r\n\
            1\r\n\
            0\r\n\
            \r\n"
        );

        // FIXME: Use Type ascription
        let mock: &mut NetworkStream = &mut mock;
        let mut stream = BufReader::new(mock);

        let req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();

        assert!(read_to_string(req).is_err());
    }

    /// Tests that when a valid extension that contains a digit is appended to
    /// the chunk size, the chunk is correctly read.
    #[test]
    fn test_chunk_size_with_extension() {
        let mut mock = MockStream::with_input(b"\
            POST / HTTP/1.1\r\n\
            Host: example.domain\r\n\
            Transfer-Encoding: chunked\r\n\
            \r\n\
            1;this is an extension with a digit 1\r\n\
            1\r\n\
            0\r\n\
            \r\n"
        );

        // FIXME: Use Type ascription
        let mock: &mut NetworkStream = &mut mock;
        let mut stream = BufReader::new(mock);

        let req = Request::new(&mut stream, sock("127.0.0.1:80")).unwrap();

        assert_eq!(read_to_string(req).unwrap(), "1".to_owned());
    }

}
<|endoftext|>


<commit_before>use std::net::{
    IpAddr,
    Ipv4Addr,
    Ipv6Addr,
};
use c_ares;
use futures;
use futures::Future;

use error::Error;
use host::HostResults;
use resolver::{
    Options,
    Resolver,
};

/// The type of future returned by methods on the `FutureResolver`.
pub type CAresFuture<T> = futures::BoxFuture<T, c_ares::Error>;

/// An asynchronous DNS resolver, which returns results as
/// `futures::Future`s.
pub struct FutureResolver {
    inner: Resolver,
}

impl FutureResolver {
    /// Create a new `FutureResolver`, using default `Options`.
    pub fn new() -> Result<FutureResolver, Error> {
        let options = Options::default();
        Self::with_options(options)
    }

    /// Create a new `FutureResolver`, with the given `Options`.
    pub fn with_options(options: Options) -> Result<FutureResolver, Error> {
        let inner = Resolver::with_options(options)?;
        let resolver = FutureResolver {
            inner: inner,
        };
        Ok(resolver)
    }

    /// Set the list of servers to contact, instead of the servers specified
    /// in resolv.conf or the local named.
    ///
    /// String format is `host[:port]`.  IPv6 addresses with ports require
    /// square brackets eg `[2001:4860:4860::8888]:53`.
    pub fn set_servers(
        &mut self,
        servers: &[&str]) -> Result<&mut Self, c_ares::Error> {
        self.inner.set_servers(servers)?;
        Ok(self)
    }

    /// Set the local IPv4 address from which to make queries.
    pub fn set_local_ipv4(&mut self, ipv4: &Ipv4Addr) -> &mut Self {
        self.inner.set_local_ipv4(ipv4);
        self
    }

    /// Set the local IPv6 address from which to make queries.
    pub fn set_local_ipv6(&mut self, ipv6: &Ipv6Addr) -> &mut Self {
        self.inner.set_local_ipv6(ipv6);
        self
    }

    /// Set the local device from which to make queries.
    pub fn set_local_device(&mut self, device: &str) -> &mut Self {
        self.inner.set_local_device(device);
        self
    }

    /// Look up the A records associated with `name`.
    pub fn query_a(&self, name: &str) -> CAresFuture<c_ares::AResults> {
        let (c, p) = futures::oneshot();
        self.inner.query_a(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Search for the A records associated with `name`.
    pub fn search_a(&self, name: &str) -> CAresFuture<c_ares::AResults> {
        let (c, p) = futures::oneshot();
        self.inner.search_a(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Look up the AAAA records associated with `name`.
    pub fn query_aaaa(&self, name: &str)  -> CAresFuture<c_ares::AAAAResults> {
        let (c, p) = futures::oneshot();
        self.inner.query_aaaa(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Search for the AAAA records associated with `name`.
    pub fn search_aaaa(&self, name: &str) -> CAresFuture<c_ares::AAAAResults> {
        let (c, p) = futures::oneshot();
        self.inner.search_aaaa(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Look up the CNAME records associated with `name`.
    pub fn query_cname(&self, name: &str)
        -> CAresFuture<c_ares::CNameResults> {
        let (c, p) = futures::oneshot();
        self.inner.query_cname(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Search for the CNAME records associated with `name`.
    pub fn search_cname(&self, name: &str)
        -> CAresFuture<c_ares::CNameResults> {
        let (c, p) = futures::oneshot();
        self.inner.search_cname(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Look up the MX records associated with `name`.
    pub fn query_mx(&self, name: &str) -> CAresFuture<c_ares::MXResults> {
        let (c, p) = futures::oneshot();
        self.inner.query_mx(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Search for the MX records associated with `name`.
    pub fn search_mx(&self, name: &str) -> CAresFuture<c_ares::MXResults> {
        let (c, p) = futures::oneshot();
        self.inner.search_mx(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Look up the NAPTR records associated with `name`.
    pub fn query_naptr(&self, name: &str)
        -> CAresFuture<c_ares::NAPTRResults> {
        let (c, p) = futures::oneshot();
        self.inner.query_naptr(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Search for the NAPTR records associated with `name`.
    pub fn search_naptr(&self, name: &str)
        -> CAresFuture<c_ares::NAPTRResults> {
        let (c, p) = futures::oneshot();
        self.inner.search_naptr(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Look up the NS records associated with `name`.
    pub fn query_ns(&self, name: &str) -> CAresFuture<c_ares::NSResults> {
        let (c, p) = futures::oneshot();
        self.inner.query_ns(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Search for the NS records associated with `name`.
    pub fn search_ns(&self, name: &str) -> CAresFuture<c_ares::NSResults> {
        let (c, p) = futures::oneshot();
        self.inner.search_ns(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Look up the PTR records associated with `name`.
    pub fn query_ptr(&self, name: &str) -> CAresFuture<c_ares::PTRResults> {
        let (c, p) = futures::oneshot();
        self.inner.query_ptr(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Search for the PTR records associated with `name`.
    pub fn search_ptr(&self, name: &str) -> CAresFuture<c_ares::PTRResults> {
        let (c, p) = futures::oneshot();
        self.inner.search_ptr(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Look up the SOA records associated with `name`.
    pub fn query_soa(&self, name: &str) -> CAresFuture<c_ares::SOAResult> {
        let (c, p) = futures::oneshot();
        self.inner.query_soa(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Search for the SOA records associated with `name`.
    pub fn search_soa(&self, name: &str) -> CAresFuture<c_ares::SOAResult> {
        let (c, p) = futures::oneshot();
        self.inner.search_soa(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Look up the SRV records associated with `name`.
    pub fn query_srv(&self, name: &str) -> CAresFuture<c_ares::SRVResults> {
        let (c, p) = futures::oneshot();
        self.inner.query_srv(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Search for the SRV records associated with `name`.
    pub fn search_srv(&self, name: &str) -> CAresFuture<c_ares::SRVResults> {
        let (c, p) = futures::oneshot();
        self.inner.search_srv(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Look up the TXT records associated with `name`.
    pub fn query_txt(&self, name: &str) -> CAresFuture<c_ares::TXTResults> {
        let (c, p) = futures::oneshot();
        self.inner.query_txt(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Search for the TXT records associated with `name`.
    pub fn search_txt(&self, name: &str) -> CAresFuture<c_ares::TXTResults> {
        let (c, p) = futures::oneshot();
        self.inner.search_txt(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Perform a host query by address.
    ///
    /// This method is one of the very few places where this library performs
    /// strictly more allocation than the underlying `c-ares` code.  If this is
    /// a problem for you, you should prefer to use the analogous method on the
    /// `Resolver`.
    pub fn get_host_by_address(&self, address: &IpAddr)
        -> CAresFuture<HostResults> {
        let (c, p) = futures::oneshot();
        self.inner.get_host_by_address(address, move |result| {
            let _ = c.send(result.map(|h| h.into()));
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Perform a host query by name.
    ///
    /// This method is one of the very few places where this library performs
    /// strictly more allocation than the underlying `c-ares` code.  If this is
    /// a problem for you, you should prefer to use the analogous method on the
    /// `Resolver`.
    pub fn get_host_by_name(&self, name: &str, family: c_ares::AddressFamily)
        -> CAresFuture<HostResults> {
        let (c, p) = futures::oneshot();
        self.inner.get_host_by_name(name, family, move |result| {
            let _ = c.send(result.map(|h| h.into()));
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Cancel all requests made on this `FutureResolver`.
    pub fn cancel(&mut self) {
        self.inner.cancel()
    }
}
<commit_msg>Complete the fleshing out of the FutureResolver<commit_after>use std::net::{
    IpAddr,
    Ipv4Addr,
    Ipv6Addr,
};
use c_ares;
use futures;
use futures::Future;

use error::Error;
use host::HostResults;
use resolver::{
    Options,
    Resolver,
};

/// The type of future returned by methods on the `FutureResolver`.
pub type CAresFuture<T> = futures::BoxFuture<T, c_ares::Error>;

/// An asynchronous DNS resolver, which returns results as
/// `futures::Future`s.
pub struct FutureResolver {
    inner: Resolver,
}

impl FutureResolver {
    /// Create a new `FutureResolver`, using default `Options`.
    pub fn new() -> Result<FutureResolver, Error> {
        let options = Options::default();
        Self::with_options(options)
    }

    /// Create a new `FutureResolver`, with the given `Options`.
    pub fn with_options(options: Options) -> Result<FutureResolver, Error> {
        let inner = Resolver::with_options(options)?;
        let resolver = FutureResolver {
            inner: inner,
        };
        Ok(resolver)
    }

    /// Set the list of servers to contact, instead of the servers specified
    /// in resolv.conf or the local named.
    ///
    /// String format is `host[:port]`.  IPv6 addresses with ports require
    /// square brackets eg `[2001:4860:4860::8888]:53`.
    pub fn set_servers(
        &mut self,
        servers: &[&str]) -> Result<&mut Self, c_ares::Error> {
        self.inner.set_servers(servers)?;
        Ok(self)
    }

    /// Set the local IPv4 address from which to make queries.
    pub fn set_local_ipv4(&mut self, ipv4: &Ipv4Addr) -> &mut Self {
        self.inner.set_local_ipv4(ipv4);
        self
    }

    /// Set the local IPv6 address from which to make queries.
    pub fn set_local_ipv6(&mut self, ipv6: &Ipv6Addr) -> &mut Self {
        self.inner.set_local_ipv6(ipv6);
        self
    }

    /// Set the local device from which to make queries.
    pub fn set_local_device(&mut self, device: &str) -> &mut Self {
        self.inner.set_local_device(device);
        self
    }

    /// Look up the A records associated with `name`.
    pub fn query_a(&self, name: &str) -> CAresFuture<c_ares::AResults> {
        let (c, p) = futures::oneshot();
        self.inner.query_a(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Search for the A records associated with `name`.
    pub fn search_a(&self, name: &str) -> CAresFuture<c_ares::AResults> {
        let (c, p) = futures::oneshot();
        self.inner.search_a(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Look up the AAAA records associated with `name`.
    pub fn query_aaaa(&self, name: &str)  -> CAresFuture<c_ares::AAAAResults> {
        let (c, p) = futures::oneshot();
        self.inner.query_aaaa(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Search for the AAAA records associated with `name`.
    pub fn search_aaaa(&self, name: &str) -> CAresFuture<c_ares::AAAAResults> {
        let (c, p) = futures::oneshot();
        self.inner.search_aaaa(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Look up the CNAME records associated with `name`.
    pub fn query_cname(&self, name: &str)
        -> CAresFuture<c_ares::CNameResults> {
        let (c, p) = futures::oneshot();
        self.inner.query_cname(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Search for the CNAME records associated with `name`.
    pub fn search_cname(&self, name: &str)
        -> CAresFuture<c_ares::CNameResults> {
        let (c, p) = futures::oneshot();
        self.inner.search_cname(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Look up the MX records associated with `name`.
    pub fn query_mx(&self, name: &str) -> CAresFuture<c_ares::MXResults> {
        let (c, p) = futures::oneshot();
        self.inner.query_mx(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Search for the MX records associated with `name`.
    pub fn search_mx(&self, name: &str) -> CAresFuture<c_ares::MXResults> {
        let (c, p) = futures::oneshot();
        self.inner.search_mx(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Look up the NAPTR records associated with `name`.
    pub fn query_naptr(&self, name: &str)
        -> CAresFuture<c_ares::NAPTRResults> {
        let (c, p) = futures::oneshot();
        self.inner.query_naptr(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Search for the NAPTR records associated with `name`.
    pub fn search_naptr(&self, name: &str)
        -> CAresFuture<c_ares::NAPTRResults> {
        let (c, p) = futures::oneshot();
        self.inner.search_naptr(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Look up the NS records associated with `name`.
    pub fn query_ns(&self, name: &str) -> CAresFuture<c_ares::NSResults> {
        let (c, p) = futures::oneshot();
        self.inner.query_ns(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Search for the NS records associated with `name`.
    pub fn search_ns(&self, name: &str) -> CAresFuture<c_ares::NSResults> {
        let (c, p) = futures::oneshot();
        self.inner.search_ns(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Look up the PTR records associated with `name`.
    pub fn query_ptr(&self, name: &str) -> CAresFuture<c_ares::PTRResults> {
        let (c, p) = futures::oneshot();
        self.inner.query_ptr(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Search for the PTR records associated with `name`.
    pub fn search_ptr(&self, name: &str) -> CAresFuture<c_ares::PTRResults> {
        let (c, p) = futures::oneshot();
        self.inner.search_ptr(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Look up the SOA records associated with `name`.
    pub fn query_soa(&self, name: &str) -> CAresFuture<c_ares::SOAResult> {
        let (c, p) = futures::oneshot();
        self.inner.query_soa(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Search for the SOA records associated with `name`.
    pub fn search_soa(&self, name: &str) -> CAresFuture<c_ares::SOAResult> {
        let (c, p) = futures::oneshot();
        self.inner.search_soa(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Look up the SRV records associated with `name`.
    pub fn query_srv(&self, name: &str) -> CAresFuture<c_ares::SRVResults> {
        let (c, p) = futures::oneshot();
        self.inner.query_srv(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Search for the SRV records associated with `name`.
    pub fn search_srv(&self, name: &str) -> CAresFuture<c_ares::SRVResults> {
        let (c, p) = futures::oneshot();
        self.inner.search_srv(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Look up the TXT records associated with `name`.
    pub fn query_txt(&self, name: &str) -> CAresFuture<c_ares::TXTResults> {
        let (c, p) = futures::oneshot();
        self.inner.query_txt(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Search for the TXT records associated with `name`.
    pub fn search_txt(&self, name: &str) -> CAresFuture<c_ares::TXTResults> {
        let (c, p) = futures::oneshot();
        self.inner.search_txt(name, move |result| {
            let _ = c.send(result);
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Perform a host query by address.
    ///
    /// This method is one of the very few places where this library performs
    /// strictly more allocation than the underlying `c-ares` code.  If this is
    /// a problem for you, you should prefer to use the analogous method on the
    /// `Resolver`.
    pub fn get_host_by_address(&self, address: &IpAddr)
        -> CAresFuture<HostResults> {
        let (c, p) = futures::oneshot();
        self.inner.get_host_by_address(address, move |result| {
            let _ = c.send(result.map(|h| h.into()));
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Perform a host query by name.
    ///
    /// This method is one of the very few places where this library performs
    /// strictly more allocation than the underlying `c-ares` code.  If this is
    /// a problem for you, you should prefer to use the analogous method on the
    /// `Resolver`.
    pub fn get_host_by_name(&self, name: &str, family: c_ares::AddressFamily)
        -> CAresFuture<HostResults> {
        let (c, p) = futures::oneshot();
        self.inner.get_host_by_name(name, family, move |result| {
            let _ = c.send(result.map(|h| h.into()));
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Initiate a single-question DNS query for `name`.  The class and type of
    /// the query are per the provided parameters, taking values as defined in
    /// `arpa/nameser.h`.
    ///
    /// This method is one of the very few places where this library performs
    /// strictly more allocation than the underlying `c-ares` code.  If this is
    /// a problem for you, you should prefer to use the analogous method on the
    /// `Resolver`.
    ///
    /// This method is provided so that users can query DNS types for which
    /// `c-ares` does not provide a parser; or in case a third-party parser is
    /// preferred.  Usually, if a suitable `query_xxx()` is available, that
    /// should be used.
    pub fn query(&self, name: &str, dns_class: u16, query_type: u16)
        -> CAresFuture<Vec<u8>> {
        let (c, p) = futures::oneshot();
        self.inner.query(name, dns_class, query_type, move |result| {
            let _ = c.send(result.map(|h| h.to_owned()));
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Initiate a series of single-question DNS queries for `name`.  The
    /// class and type of the query are per the provided parameters, taking
    /// values as defined in `arpa/nameser.h`.
    ///
    /// This method is one of the very few places where this library performs
    /// strictly more allocation than the underlying `c-ares` code.  If this is
    /// a problem for you, you should prefer to use the analogous method on the
    /// `Resolver`.
    ///
    /// This method is provided so that users can query DNS types for which
    /// `c-ares` does not provide a parser; or in case a third-party parser is
    /// preferred.  Usually, if a suitable `query_xxx()` is available, that
    /// should be used.
    pub fn search(&self, name: &str, dns_class: u16, query_type: u16)
        -> CAresFuture<Vec<u8>> {
        let (c, p) = futures::oneshot();
        self.inner.search(name, dns_class, query_type, move |result| {
            let _ = c.send(result.map(|h| h.to_owned()));
        });
        p.map_err(|_| c_ares::Error::ECANCELLED)
            .and_then(futures::done)
            .boxed()
    }

    /// Cancel all requests made on this `FutureResolver`.
    pub fn cancel(&mut self) {
        self.inner.cancel()
    }
}
<|endoftext|>


<commit_before>use types::NumPlies;

use super::color::{White, Black};
use super::piece::{Piece, WK, WR, BK, BR, Pawn};
use super::square::{Square,File,Rank};
use super::moves::Move;
use super::pos::{self, Position};
use super::castle::{Kingside,Queenside};

pub fn make_move(p: &mut Position, m: &Move) {
    let from = m.from();
    let to = m.to();
    let curr_piece = p.at(from).unwrap();
    let curr_color = p.side_to_move();

    if m.capture_normal().is_some() || m.is_en_passant() || curr_piece.piece_type() == Pawn {
        p.set_ply_count(NumPlies(0));
    } else {
        let NumPlies(temp) = p.ply_count();
        p.set_ply_count(NumPlies(temp+1));
    }

    if let Some(castle_side) = m.castle() {

        //no en passant
        p.set_en_passant(None);

        let (rook_from, rook_to) = match (curr_color, castle_side) {
            (White, Kingside ) => (Square::new(File(7),Rank(0)), Square::new(File(5),Rank(0))),
            (White, Queenside) => (Square::new(File(0),Rank(0)), Square::new(File(3),Rank(0))),
            (Black, Kingside ) => (Square::new(File(7),Rank(7)), Square::new(File(5),Rank(7))),
            (Black, Queenside) => (Square::new(File(0),Rank(7)), Square::new(File(3),Rank(7))),
        };

        p.remove_at(from, curr_piece);
        p.set_at(to, curr_piece);
        let curr_rook = p.at(rook_from).unwrap();
        p.remove_at(rook_from, curr_rook);
        p.set_at(rook_to, curr_rook);

    } else if m.is_en_passant() {

        //no en passant after this
        p.set_en_passant(None);

        let captured = Square::new(to.file(), from.rank());
        let captured_piece = Piece::new(p.side_to_move().invert(), Pawn);

        p.remove_at(captured, captured_piece);
        p.remove_at(from, curr_piece);
        p.set_at(to, curr_piece);

    } else if let Some(promote_piece) = m.promote() {
        //no en passant
        p.set_en_passant(None);

        //change the board and promote
        if let Some(captured_piece) = m.capture_normal() {
            p.remove_at(to, captured_piece);
        }
        p.remove_at(from, curr_piece);
        p.set_at(to, Piece::new(curr_color, promote_piece));
    } else {

        if m.is_pawn_double_move() {
            p.set_en_passant(Some(to.file()));
        } else {
            p.set_en_passant(None);
        }

        //change the board
        if let Some(captured_piece) = m.capture_normal() {
            p.remove_at(to, captured_piece);
        }
        p.remove_at(from, curr_piece);
        p.set_at(to, curr_piece);
    }

    //castling
    if p.at(Square::new(File(4),Rank(0))) != Some(WK) {
        p.set_castle(Queenside, White, false);
        p.set_castle(Kingside , White, false);
    }
    if p.at(Square::new(File(0),Rank(0))) != Some(WR) {
        p.set_castle(Queenside, White, false);
    }
    if p.at(Square::new(File(7),Rank(0))) != Some(WR) {
        p.set_castle(Kingside , White, false);
    }
    if p.at(Square::new(File(4),Rank(7))) != Some(BK) {
        p.set_castle(Queenside, Black, false);
        p.set_castle(Kingside , Black, false);
    }
    if p.at(Square::new(File(0),Rank(7))) != Some(BR) {
        p.set_castle(Queenside, Black, false);
    }
    if p.at(Square::new(File(7),Rank(7))) != Some(BR) {
        p.set_castle(Kingside , Black, false);
    }

    p.swap_side_to_move();
}

pub fn unmake_move(p: &mut Position, m: &Move, extra_data: pos::ExtraData) {
    let from = m.from();
    let to = m.to();
    let curr_piece = p.at(to).unwrap();
    let curr_color = p.side_to_move().invert();

    if let Some(castle_side) = m.castle() {

        let (rook_from, rook_to) = match (curr_color, castle_side) {
            (White, Kingside ) => (Square::new(File(7),Rank(0)), Square::new(File(5),Rank(0))),
            (White, Queenside) => (Square::new(File(0),Rank(0)), Square::new(File(3),Rank(0))),
            (Black, Kingside ) => (Square::new(File(7),Rank(7)), Square::new(File(5),Rank(7))),
            (Black, Queenside) => (Square::new(File(0),Rank(7)), Square::new(File(3),Rank(7))),
        };

        p.remove_at(to, curr_piece);
        p.set_at(from, curr_piece);
        let curr_rook = p.at(rook_to).unwrap();
        p.remove_at(rook_to, curr_rook);
        p.set_at(rook_from, curr_rook);

    } else if m.is_en_passant() {

        let captured = Square::new(to.file(), from.rank());
        let captured_piece = Piece::new(curr_color.invert(), Pawn);

        p.set_at(captured, captured_piece);
        p.remove_at(to, curr_piece);
        p.set_at(from, curr_piece);

    } else if let Some(promote_piece) = m.promote() {

        p.remove_at(to, Piece::new(curr_color, promote_piece));
        p.set_at(to, curr_piece);
        if let Some(captured_piece) = m.capture_normal() {
            p.set_at(to, captured_piece);
        }

    } else {

        p.remove_at(to, curr_piece);
        p.set_at(from, curr_piece);
        if let Some(captured_piece) = m.capture_normal() {
            p.set_at(to, captured_piece);
        }

    }

    p.set_extra_data(extra_data);
    p.swap_side_to_move();
}
<commit_msg>Add logging to game::make_move()<commit_after>use types::NumPlies;

use super::color::{White, Black};
use super::piece::{Piece, WK, WR, BK, BR, Pawn};
use super::square::{Square,File,Rank};
use super::moves::Move;
use super::pos::{self, Position};
use super::castle::{Kingside,Queenside};

pub fn make_move(p: &mut Position, m: &Move) {

    debug!("make_move with move {:?}", *m);

    let from = m.from();
    let to = m.to();
    let curr_piece = p.at(from).unwrap();
    let curr_color = p.side_to_move();

    if m.capture_normal().is_some() || m.is_en_passant() || curr_piece.piece_type() == Pawn {
        p.set_ply_count(NumPlies(0));
    } else {
        let NumPlies(temp) = p.ply_count();
        p.set_ply_count(NumPlies(temp+1));
    }

    if let Some(castle_side) = m.castle() {

        //no en passant
        p.set_en_passant(None);

        let (rook_from, rook_to) = match (curr_color, castle_side) {
            (White, Kingside ) => (Square::new(File(7),Rank(0)), Square::new(File(5),Rank(0))),
            (White, Queenside) => (Square::new(File(0),Rank(0)), Square::new(File(3),Rank(0))),
            (Black, Kingside ) => (Square::new(File(7),Rank(7)), Square::new(File(5),Rank(7))),
            (Black, Queenside) => (Square::new(File(0),Rank(7)), Square::new(File(3),Rank(7))),
        };

        p.remove_at(from, curr_piece);
        p.set_at(to, curr_piece);
        let curr_rook = p.at(rook_from).unwrap();
        p.remove_at(rook_from, curr_rook);
        p.set_at(rook_to, curr_rook);

    } else if m.is_en_passant() {

        //no en passant after this
        p.set_en_passant(None);

        let captured = Square::new(to.file(), from.rank());
        let captured_piece = Piece::new(p.side_to_move().invert(), Pawn);

        p.remove_at(captured, captured_piece);
        p.remove_at(from, curr_piece);
        p.set_at(to, curr_piece);

    } else if let Some(promote_piece) = m.promote() {
        //no en passant
        p.set_en_passant(None);

        //change the board and promote
        if let Some(captured_piece) = m.capture_normal() {
            p.remove_at(to, captured_piece);
        }
        p.remove_at(from, curr_piece);
        p.set_at(to, Piece::new(curr_color, promote_piece));
    } else {

        if m.is_pawn_double_move() {
            p.set_en_passant(Some(to.file()));
        } else {
            p.set_en_passant(None);
        }

        //change the board
        if let Some(captured_piece) = m.capture_normal() {
            p.remove_at(to, captured_piece);
        }
        p.remove_at(from, curr_piece);
        p.set_at(to, curr_piece);
    }

    //castling
    if p.at(Square::new(File(4),Rank(0))) != Some(WK) {
        p.set_castle(Queenside, White, false);
        p.set_castle(Kingside , White, false);
    }
    if p.at(Square::new(File(0),Rank(0))) != Some(WR) {
        p.set_castle(Queenside, White, false);
    }
    if p.at(Square::new(File(7),Rank(0))) != Some(WR) {
        p.set_castle(Kingside , White, false);
    }
    if p.at(Square::new(File(4),Rank(7))) != Some(BK) {
        p.set_castle(Queenside, Black, false);
        p.set_castle(Kingside , Black, false);
    }
    if p.at(Square::new(File(0),Rank(7))) != Some(BR) {
        p.set_castle(Queenside, Black, false);
    }
    if p.at(Square::new(File(7),Rank(7))) != Some(BR) {
        p.set_castle(Kingside , Black, false);
    }

    p.swap_side_to_move();
}

pub fn unmake_move(p: &mut Position, m: &Move, extra_data: pos::ExtraData) {
    let from = m.from();
    let to = m.to();
    let curr_piece = p.at(to).unwrap();
    let curr_color = p.side_to_move().invert();

    if let Some(castle_side) = m.castle() {

        let (rook_from, rook_to) = match (curr_color, castle_side) {
            (White, Kingside ) => (Square::new(File(7),Rank(0)), Square::new(File(5),Rank(0))),
            (White, Queenside) => (Square::new(File(0),Rank(0)), Square::new(File(3),Rank(0))),
            (Black, Kingside ) => (Square::new(File(7),Rank(7)), Square::new(File(5),Rank(7))),
            (Black, Queenside) => (Square::new(File(0),Rank(7)), Square::new(File(3),Rank(7))),
        };

        p.remove_at(to, curr_piece);
        p.set_at(from, curr_piece);
        let curr_rook = p.at(rook_to).unwrap();
        p.remove_at(rook_to, curr_rook);
        p.set_at(rook_from, curr_rook);

    } else if m.is_en_passant() {

        let captured = Square::new(to.file(), from.rank());
        let captured_piece = Piece::new(curr_color.invert(), Pawn);

        p.set_at(captured, captured_piece);
        p.remove_at(to, curr_piece);
        p.set_at(from, curr_piece);

    } else if let Some(promote_piece) = m.promote() {

        p.remove_at(to, Piece::new(curr_color, promote_piece));
        p.set_at(to, curr_piece);
        if let Some(captured_piece) = m.capture_normal() {
            p.set_at(to, captured_piece);
        }

    } else {

        p.remove_at(to, curr_piece);
        p.set_at(from, curr_piece);
        if let Some(captured_piece) = m.capture_normal() {
            p.set_at(to, captured_piece);
        }

    }

    p.set_extra_data(extra_data);
    p.swap_side_to_move();
}
<|endoftext|>


<commit_before>use decoders::RawImage;
use imageops::{OpBuffer,ImageOp,Pipeline};

#[derive(Copy, Clone, Debug)]
pub struct OpGamma {
}

impl OpGamma {
  pub fn new(_img: &RawImage) -> OpGamma {
    OpGamma{}
  }
}

impl ImageOp for OpGamma {
  fn name(&self) -> &str {"gamma"}
  fn run(&self, pipeline: &Pipeline, buf: &OpBuffer) -> OpBuffer {
    if pipeline.linear {
      buf.clone()
    } else {
      gamma(pipeline.image, buf)
    }
  }
}

pub fn gamma(_: &RawImage, buf: &OpBuffer) -> OpBuffer {
  let mut buf = buf.clone();

  let g: f32 = 0.45;
  let f: f32 = 0.099;
  let min: f32 = 0.018;
  let mul: f32 = 4.5;

  let maxvals = 1 << 16; // 2^16 is enough precision for any output format
  let mut glookup: Vec<f32> = vec![0.0; maxvals+1];
  for i in 0..(maxvals+1) {
    let v = (i as f32) / (maxvals as f32);
    glookup[i] = if v <= min {
      mul * v
    } else {
      ((1.0+f) * v.powf(g)) - f
    }
  }

  buf.mutate_lines(&(|line: &mut [f32], _| {
    for pix in line.chunks_mut(1) {
      pix[0] = glookup[(pix[0].max(0.0)*(maxvals as f32)).min(maxvals as f32) as usize];
    }
  }));

  buf
}
<commit_msg>gamma: code cleanup<commit_after>use decoders::RawImage;
use imageops::{OpBuffer,ImageOp,Pipeline};

#[derive(Copy, Clone, Debug)]
pub struct OpGamma {
}

impl OpGamma {
  pub fn new(_img: &RawImage) -> OpGamma {
    OpGamma{}
  }
}

impl ImageOp for OpGamma {
  fn name(&self) -> &str {"gamma"}
  fn run(&self, pipeline: &Pipeline, buf: &OpBuffer) -> OpBuffer {
    if pipeline.linear {
      buf.clone()
    } else {
      let mut buf = buf.clone();

      let g: f32 = 0.45;
      let f: f32 = 0.099;
      let min: f32 = 0.018;
      let mul: f32 = 4.5;

      let maxvals = 1 << 16; // 2^16 is enough precision for any output format
      let mut glookup: Vec<f32> = vec![0.0; maxvals+1];
      for i in 0..(maxvals+1) {
        let v = (i as f32) / (maxvals as f32);
        glookup[i] = if v <= min {
          mul * v
        } else {
          ((1.0+f) * v.powf(g)) - f
        }
      }

      buf.mutate_lines(&(|line: &mut [f32], _| {
        for pix in line.chunks_mut(1) {
          pix[0] = glookup[(pix[0].max(0.0)*(maxvals as f32)).min(maxvals as f32) as usize];
        }
      }));

      buf
    }
  }
}
<|endoftext|>