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

extern crate libc;
extern crate num;

use self::libc::{c_char, c_double, c_float, c_int, c_uint};
use std::ffi::CString;

#[link(name = "arpack")]
extern {

    // single precision symmetric

    fn ssaupd_(ido: *mut c_int,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_float,
               resid: *mut c_float,
               ncv: *const c_int,
               v: *mut c_float,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut c_float,
               workl: *mut c_float,
               lworkl: *const c_int,
               info: *mut c_int);

    fn sseupd_(rvec: *const c_int,
               howmny: *const c_char,
               select: *mut c_int,
               d: *mut c_float,
               z: *mut c_float,
               ldz: *const c_int,
               sigma: *const c_float,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_float,
               resid: *mut c_float,
               ncv: *const c_int,
               v: *mut c_float,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut c_float,
               workl: *mut c_float,
               lworkl: *const c_int,
               ierr: *mut c_int);

    // double precision symmetric

    fn dsaupd_(ido: *mut c_int,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_double,
               resid: *mut c_double,
               ncv: *const c_int,
               v: *mut c_double,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut c_double,
               workl: *mut c_double,
               lworkl: *const c_int,
               info: *mut c_int);

    fn dseupd_(rvec: *const c_int,
               howmny: *const c_char,
               select: *mut c_int,
               d: *mut c_double,
               z: *mut c_double,
               ldz: *const c_int,
               sigma: *const c_double,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_double,
               resid: *mut c_double,
               ncv: *const c_int,
               v: *mut c_double,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut c_double,
               workl: *mut c_double,
               lworkl: *const c_int,
               ierr: *mut c_int);

}

pub enum Which {
    LargestMagnitude,
    SmallestMagnitude,
    LargestAlgebraic,
    SmallestAlgebraic,
    BothEnds,
}

fn which_to_str(which: Which) -> &'static str {
    match which {
        Which::LargestMagnitude => "LM",
        Which::SmallestMagnitude => "SM",
        Which::LargestAlgebraic => "LA",
        Which::SmallestAlgebraic => "SA",
        Which::BothEnds => "BE",
    }
}

// note: evals may potentially be modified even if there is an error.
fn dsaupd<F>(n: c_int,
             nev: c_int,
             mv_multiply: F,
             evals: &mut Vec<c_double>,
             evecs: Option<&mut Vec<c_double>>)
        where F : Fn(&[c_double]) -> Vec<c_double> {
    assert!(nev > 0);
    assert!(nev < n);

    let mut ido: c_int = 0;
    let bmat = CString::new("I").unwrap(); // not configurable, for now
    let which = CString::new(which_to_str(Which::SmallestAlgebraic)).unwrap();
    let tol: c_double = 0.0;
    let mut resid = vec![0.0 as c_double; n as usize];
    let ncv = {
        let possible_ncv: c_int = 4 * nev;
        if possible_ncv > n {
            n
        } else {
            possible_ncv
        }
    };
    let ldv: c_int = n;
    let mut v = vec![0.0 as c_double; (ldv * ncv) as usize];
    let mut iparam = vec![1 as c_int, 0, 3 * n, 0, 0, 0, 1, 0, 0, 0, 0];
    // fixme: may wish to tune iparam[2] differently.
    let mut ipntr = vec![0 as c_int; 11];
    let mut workd = vec![0.0 as c_double; 3 * n as usize];
    let lworkl: c_int = ncv * (ncv + 8);
    let mut workl = vec![0.0 as c_double; lworkl as usize];
    let mut info: c_int = 0;

    loop {
        unsafe {
            dsaupd_(&mut ido, bmat.as_ptr(), &n, which.as_ptr(), &nev, &tol,
                    resid.as_mut_ptr(), &ncv, v.as_mut_ptr(), &ldv,
                    iparam.as_mut_ptr(), ipntr.as_mut_ptr(), workd.as_mut_ptr(),
                    workl.as_mut_ptr(), &lworkl, &mut info);
        }

        if ido != 1 && ido != -1 {
            break;
        }

        // fixme: seems overkill
        let output = {
            let in_slice = &workd[((ipntr[0] - 1) as usize)..((ipntr[0] - 1 + n) as usize)];
            mv_multiply(in_slice)
        };
        let out_slice = &mut workd[((ipntr[1] - 1) as usize)..((ipntr[1] - 1 + n) as usize)];
        out_slice.clone_from_slice(output.as_slice());
    }

    if info < 0 {
        // fixme: return error using enum
        return;
    }

    let rvec: c_int = match evecs {
        Some(ref evecs) => 1,
        None => 0
    };
    let mut select = vec![0 as c_int; ncv as usize];
    evals.clear(); // called ``d`` in arpack
    evals.resize(nev as usize, 0.0);
    let sigma: c_double = 0.0;
    let mut ierr: c_int = 0;

    let howmny = CString::new("A").unwrap();
    unsafe {
        dseupd_(&rvec, howmny.as_ptr(), select.as_mut_ptr(), evals.as_mut_ptr(),
                v.as_mut_ptr(), &ldv, &sigma, bmat.as_ptr(),
	        &n, which.as_ptr(), &nev, &tol, resid.as_mut_ptr(), &ncv, v.as_mut_ptr(), &ldv,
	        iparam.as_mut_ptr(), ipntr.as_mut_ptr(), workd.as_mut_ptr(), workl.as_mut_ptr(), &lworkl, &mut ierr);
    }

    if ierr != 0 {
        // fixme: return error code
        return;
    }

    match evecs {
        Some(evecs) => {
            // copy the vector.  fixme: seems overkill.
            evecs.clear();
            evecs.resize((nev * n) as usize, 0.0);
            evecs.as_mut_slice().clone_from_slice(v.as_slice());
        },
        None => ()
    };
}

#[cfg(test)]
mod tests {

    extern crate libc;

    use super::dsaupd;
    use self::test::Bencher;
    use self::libc::c_double;

    #[test]
    fn test_dsaupd() {
        let mut evals: Vec<c_double> = Vec::new();
        let mut evecs: Vec<c_double> = Vec::new();
        dsaupd(8, 2, |slice: &[c_double]| {
            // FIXME: this is probably more involved than necessary
            slice.to_vec().move_iter().map(|i| 2.0 * i).collect()
        }, &mut evals, Some(&mut evecs));
    }

    #[bench]
    fn benchmark_dsaupd(b: &mut Bencher) {
        b.iter(|| test_dsaupd());
    }

}
<commit_msg>Remove unused import<commit_after>// Copyright 2014 James R. Garrison
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate libc;
extern crate num;

use self::libc::{c_char, c_double, c_float, c_int};
use std::ffi::CString;

#[link(name = "arpack")]
extern {

    // single precision symmetric

    fn ssaupd_(ido: *mut c_int,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_float,
               resid: *mut c_float,
               ncv: *const c_int,
               v: *mut c_float,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut c_float,
               workl: *mut c_float,
               lworkl: *const c_int,
               info: *mut c_int);

    fn sseupd_(rvec: *const c_int,
               howmny: *const c_char,
               select: *mut c_int,
               d: *mut c_float,
               z: *mut c_float,
               ldz: *const c_int,
               sigma: *const c_float,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_float,
               resid: *mut c_float,
               ncv: *const c_int,
               v: *mut c_float,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut c_float,
               workl: *mut c_float,
               lworkl: *const c_int,
               ierr: *mut c_int);

    // double precision symmetric

    fn dsaupd_(ido: *mut c_int,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_double,
               resid: *mut c_double,
               ncv: *const c_int,
               v: *mut c_double,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut c_double,
               workl: *mut c_double,
               lworkl: *const c_int,
               info: *mut c_int);

    fn dseupd_(rvec: *const c_int,
               howmny: *const c_char,
               select: *mut c_int,
               d: *mut c_double,
               z: *mut c_double,
               ldz: *const c_int,
               sigma: *const c_double,
               bmat: *const c_char,
               n: *const c_int,
               which: *const c_char,
               nev: *const c_int,
               tol: *const c_double,
               resid: *mut c_double,
               ncv: *const c_int,
               v: *mut c_double,
               ldv: *const c_int,
               iparam: *mut c_int,
               ipntr: *mut c_int,
               workd: *mut c_double,
               workl: *mut c_double,
               lworkl: *const c_int,
               ierr: *mut c_int);

}

pub enum Which {
    LargestMagnitude,
    SmallestMagnitude,
    LargestAlgebraic,
    SmallestAlgebraic,
    BothEnds,
}

fn which_to_str(which: Which) -> &'static str {
    match which {
        Which::LargestMagnitude => "LM",
        Which::SmallestMagnitude => "SM",
        Which::LargestAlgebraic => "LA",
        Which::SmallestAlgebraic => "SA",
        Which::BothEnds => "BE",
    }
}

// note: evals may potentially be modified even if there is an error.
fn dsaupd<F>(n: c_int,
             nev: c_int,
             mv_multiply: F,
             evals: &mut Vec<c_double>,
             evecs: Option<&mut Vec<c_double>>)
        where F : Fn(&[c_double]) -> Vec<c_double> {
    assert!(nev > 0);
    assert!(nev < n);

    let mut ido: c_int = 0;
    let bmat = CString::new("I").unwrap(); // not configurable, for now
    let which = CString::new(which_to_str(Which::SmallestAlgebraic)).unwrap();
    let tol: c_double = 0.0;
    let mut resid = vec![0.0 as c_double; n as usize];
    let ncv = {
        let possible_ncv: c_int = 4 * nev;
        if possible_ncv > n {
            n
        } else {
            possible_ncv
        }
    };
    let ldv: c_int = n;
    let mut v = vec![0.0 as c_double; (ldv * ncv) as usize];
    let mut iparam = vec![1 as c_int, 0, 3 * n, 0, 0, 0, 1, 0, 0, 0, 0];
    // fixme: may wish to tune iparam[2] differently.
    let mut ipntr = vec![0 as c_int; 11];
    let mut workd = vec![0.0 as c_double; 3 * n as usize];
    let lworkl: c_int = ncv * (ncv + 8);
    let mut workl = vec![0.0 as c_double; lworkl as usize];
    let mut info: c_int = 0;

    loop {
        unsafe {
            dsaupd_(&mut ido, bmat.as_ptr(), &n, which.as_ptr(), &nev, &tol,
                    resid.as_mut_ptr(), &ncv, v.as_mut_ptr(), &ldv,
                    iparam.as_mut_ptr(), ipntr.as_mut_ptr(), workd.as_mut_ptr(),
                    workl.as_mut_ptr(), &lworkl, &mut info);
        }

        if ido != 1 && ido != -1 {
            break;
        }

        // fixme: seems overkill
        let output = {
            let in_slice = &workd[((ipntr[0] - 1) as usize)..((ipntr[0] - 1 + n) as usize)];
            mv_multiply(in_slice)
        };
        let out_slice = &mut workd[((ipntr[1] - 1) as usize)..((ipntr[1] - 1 + n) as usize)];
        out_slice.clone_from_slice(output.as_slice());
    }

    if info < 0 {
        // fixme: return error using enum
        return;
    }

    let rvec: c_int = match evecs {
        Some(ref evecs) => 1,
        None => 0
    };
    let mut select = vec![0 as c_int; ncv as usize];
    evals.clear(); // called ``d`` in arpack
    evals.resize(nev as usize, 0.0);
    let sigma: c_double = 0.0;
    let mut ierr: c_int = 0;

    let howmny = CString::new("A").unwrap();
    unsafe {
        dseupd_(&rvec, howmny.as_ptr(), select.as_mut_ptr(), evals.as_mut_ptr(),
                v.as_mut_ptr(), &ldv, &sigma, bmat.as_ptr(),
	        &n, which.as_ptr(), &nev, &tol, resid.as_mut_ptr(), &ncv, v.as_mut_ptr(), &ldv,
	        iparam.as_mut_ptr(), ipntr.as_mut_ptr(), workd.as_mut_ptr(), workl.as_mut_ptr(), &lworkl, &mut ierr);
    }

    if ierr != 0 {
        // fixme: return error code
        return;
    }

    match evecs {
        Some(evecs) => {
            // copy the vector.  fixme: seems overkill.
            evecs.clear();
            evecs.resize((nev * n) as usize, 0.0);
            evecs.as_mut_slice().clone_from_slice(v.as_slice());
        },
        None => ()
    };
}

#[cfg(test)]
mod tests {

    extern crate libc;

    use super::dsaupd;
    use self::test::Bencher;
    use self::libc::c_double;

    #[test]
    fn test_dsaupd() {
        let mut evals: Vec<c_double> = Vec::new();
        let mut evecs: Vec<c_double> = Vec::new();
        dsaupd(8, 2, |slice: &[c_double]| {
            // FIXME: this is probably more involved than necessary
            slice.to_vec().move_iter().map(|i| 2.0 * i).collect()
        }, &mut evals, Some(&mut evecs));
    }

    #[bench]
    fn benchmark_dsaupd(b: &mut Bencher) {
        b.iter(|| test_dsaupd());
    }

}
<|endoftext|>


<commit_before>use {Errno, Result};
use libc::{self, c_int};
use std::os::unix::io::RawFd;
use std::ptr;
use std::mem;
use ::Error;

bitflags!(
    #[repr(C)]
    pub flags EpollFlags: u32 {
        const EPOLLIN = libc::EPOLLIN as u32,
        const EPOLLPRI = libc::EPOLLPRI as u32,
        const EPOLLOUT = libc::EPOLLOUT as u32,
        const EPOLLRDNORM = libc::EPOLLRDNORM as u32,
        const EPOLLRDBAND = libc::EPOLLRDBAND as u32,
        const EPOLLWRNORM = libc::EPOLLWRNORM as u32,
        const EPOLLWRBAND = libc::EPOLLWRBAND as u32,
        const EPOLLMSG = libc::EPOLLMSG as u32,
        const EPOLLERR = libc::EPOLLERR as u32,
        const EPOLLHUP = libc::EPOLLHUP as u32,
        const EPOLLRDHUP = libc::EPOLLRDHUP as u32,
        const EPOLLEXCLUSIVE = 1 << 28,
        const EPOLLWAKEUP = libc::EPOLLWAKEUP as u32,
        const EPOLLONESHOT = libc::EPOLLONESHOT as u32,
        const EPOLLET = libc::EPOLLET as u32,
    }
);

#[derive(Clone, Copy, Eq, PartialEq)]
#[repr(C)]
pub enum EpollOp {
    EpollCtlAdd = 1,
    EpollCtlDel = 2,
    EpollCtlMod = 3
}

libc_bitflags!{
    pub flags EpollCreateFlags: c_int {
        EPOLL_CLOEXEC,
    }
}

#[derive(Clone, Copy)]
#[repr(C)]
pub struct EpollEvent {
    event: libc::epoll_event,
}

impl EpollEvent {
    pub fn new(events: EpollFlags, data: u64) -> Self {
        EpollEvent { event: libc::epoll_event { events: events.bits(), u64: data } }
    }

    pub fn empty() -> Self {
        unsafe { mem::zeroed::<EpollEvent>() }
    }

    pub fn events(&self) -> EpollFlags {
        EpollFlags::from_bits(self.event.events).unwrap()
    }

    pub fn data(&self) -> u64 {
        self.event.u64
    }
}

impl<'a> Into<&'a mut EpollEvent> for Option<&'a mut EpollEvent> {
    #[inline]
    fn into(self) -> &'a mut EpollEvent {
        match self {
            Some(epoll_event) => epoll_event,
            None => unsafe { &mut *ptr::null_mut::<EpollEvent>() }
        }
    }
}

#[inline]
pub fn epoll_create() -> Result<RawFd> {
    let res = unsafe { libc::epoll_create(1024) };

    Errno::result(res)
}

#[inline]
pub fn epoll_create1(flags: EpollCreateFlags) -> Result<RawFd> {
    let res = unsafe { libc::epoll_create1(flags.bits()) };

    Errno::result(res)
}

#[inline]
pub fn epoll_ctl<'a, T>(epfd: RawFd, op: EpollOp, fd: RawFd, event: T) -> Result<()>
    where T: Into<&'a mut EpollEvent>
{
    let event: &mut EpollEvent = event.into();
    if event as *const EpollEvent == ptr::null() && op != EpollOp::EpollCtlDel {
        Err(Error::Sys(Errno::EINVAL))
    } else {
        let res = unsafe { libc::epoll_ctl(epfd, op as c_int, fd, &mut event.event) };
        Errno::result(res).map(drop)
    }
}

#[inline]
pub fn epoll_wait(epfd: RawFd, events: &mut [EpollEvent], timeout_ms: isize) -> Result<usize> {
    let res = unsafe {
        libc::epoll_wait(epfd, events.as_mut_ptr() as *mut libc::epoll_event, events.len() as c_int, timeout_ms as c_int)
    };

    Errno::result(res).map(|r| r as usize)
}
<commit_msg>Fix the inner type of EpollFlags<commit_after>use {Errno, Result};
use libc::{self, c_int};
use std::os::unix::io::RawFd;
use std::ptr;
use std::mem;
use ::Error;

bitflags!(
    #[repr(C)]
    pub flags EpollFlags: libc::c_int {
        const EPOLLIN = libc::EPOLLIN,
        const EPOLLPRI = libc::EPOLLPRI,
        const EPOLLOUT = libc::EPOLLOUT,
        const EPOLLRDNORM = libc::EPOLLRDNORM,
        const EPOLLRDBAND = libc::EPOLLRDBAND,
        const EPOLLWRNORM = libc::EPOLLWRNORM,
        const EPOLLWRBAND = libc::EPOLLWRBAND,
        const EPOLLMSG = libc::EPOLLMSG,
        const EPOLLERR = libc::EPOLLERR,
        const EPOLLHUP = libc::EPOLLHUP,
        const EPOLLRDHUP = libc::EPOLLRDHUP,
        const EPOLLEXCLUSIVE = 1 << 28,
        const EPOLLWAKEUP = libc::EPOLLWAKEUP,
        const EPOLLONESHOT = libc::EPOLLONESHOT,
        const EPOLLET = libc::EPOLLET,
    }
);

#[derive(Clone, Copy, Eq, PartialEq)]
#[repr(C)]
pub enum EpollOp {
    EpollCtlAdd = 1,
    EpollCtlDel = 2,
    EpollCtlMod = 3
}

libc_bitflags!{
    pub flags EpollCreateFlags: c_int {
        EPOLL_CLOEXEC,
    }
}

#[derive(Clone, Copy)]
#[repr(C)]
pub struct EpollEvent {
    event: libc::epoll_event,
}

impl EpollEvent {
    pub fn new(events: EpollFlags, data: u64) -> Self {
        EpollEvent { event: libc::epoll_event { events: events.bits() as u32, u64: data } }
    }

    pub fn empty() -> Self {
        unsafe { mem::zeroed::<EpollEvent>() }
    }

    pub fn events(&self) -> EpollFlags {
        EpollFlags::from_bits(self.event.events as libc::c_int).unwrap()
    }

    pub fn data(&self) -> u64 {
        self.event.u64
    }
}

impl<'a> Into<&'a mut EpollEvent> for Option<&'a mut EpollEvent> {
    #[inline]
    fn into(self) -> &'a mut EpollEvent {
        match self {
            Some(epoll_event) => epoll_event,
            None => unsafe { &mut *ptr::null_mut::<EpollEvent>() }
        }
    }
}

#[inline]
pub fn epoll_create() -> Result<RawFd> {
    let res = unsafe { libc::epoll_create(1024) };

    Errno::result(res)
}

#[inline]
pub fn epoll_create1(flags: EpollCreateFlags) -> Result<RawFd> {
    let res = unsafe { libc::epoll_create1(flags.bits()) };

    Errno::result(res)
}

#[inline]
pub fn epoll_ctl<'a, T>(epfd: RawFd, op: EpollOp, fd: RawFd, event: T) -> Result<()>
    where T: Into<&'a mut EpollEvent>
{
    let event: &mut EpollEvent = event.into();
    if event as *const EpollEvent == ptr::null() && op != EpollOp::EpollCtlDel {
        Err(Error::Sys(Errno::EINVAL))
    } else {
        let res = unsafe { libc::epoll_ctl(epfd, op as c_int, fd, &mut event.event) };
        Errno::result(res).map(drop)
    }
}

#[inline]
pub fn epoll_wait(epfd: RawFd, events: &mut [EpollEvent], timeout_ms: isize) -> Result<usize> {
    let res = unsafe {
        libc::epoll_wait(epfd, events.as_mut_ptr() as *mut libc::epoll_event, events.len() as c_int, timeout_ms as c_int)
    };

    Errno::result(res).map(|r| r as usize)
}
<|endoftext|>


<commit_before>/*
gl/src/gl_wrapper/shader.rs, 2017-07-14

Copyright (c) 2017 Juuso Tuononen

This file is licensed under

Apache License, Version 2.0

or

MIT License
*/

use super::gl_raw;
use self::gl_raw::types::*;

use std::ffi::{CString, IntoStringError};
use std::ptr;
use std::error::Error;

#[derive(Debug)]
pub enum ShaderType {
    Vertex,
    Fragment,
}

impl ShaderType {
    fn as_gl_enum(self) -> GLenum {
        match self {
            ShaderType::Fragment => gl_raw::FRAGMENT_SHADER,
            ShaderType::Vertex => gl_raw::VERTEX_SHADER,
        }
    }
}

pub struct Shader {
    shader_id: GLuint,
}

impl Shader {
    pub fn new(shader_type: ShaderType, shader_text: CString) -> Result<Shader, String> {
        let shader_type: GLenum = shader_type.as_gl_enum();
        let shader;

        unsafe {
            shader = Shader { shader_id: gl_raw::CreateShader(shader_type) };

            gl_raw::ShaderSource(shader.id(), 1, &shader_text.as_ptr(), ptr::null());
            gl_raw::CompileShader(shader.id());
        }

        let mut status: GLint = 0;

        unsafe {
            gl_raw::GetShaderiv(shader.id(), gl_raw::COMPILE_STATUS, &mut status);
        }

        if status == 0 {
            match Shader::get_shader_log(&shader) {
                Ok(message) => Err(message),
                Err(into_string_error) => Err(into_string_error.description().to_string()),
            }
        } else {
            Ok(shader)
        }
    }

    fn id(&self) -> GLuint {
        self.shader_id
    }

    fn get_shader_log(shader: &Shader) -> Result<String, IntoStringError> {
        let mut log_length: GLint = 0;

        unsafe {
            gl_raw::GetShaderiv(shader.id(), gl_raw::INFO_LOG_LENGTH, &mut log_length);
        }

        let buffer = create_string_buffer(log_length as usize).into_raw();

        unsafe {
            gl_raw::GetShaderInfoLog(shader.id(), log_length, ptr::null_mut(), buffer);
            CString::from_raw(buffer).into_string()
        }
    }
}

impl Drop for Shader {
    fn drop(&mut self) {
        unsafe {
            gl_raw::DeleteShader(self.shader_id);
        }
    }
}

pub struct Program {
    program_id: GLuint,
}

impl Drop for Program {
    fn drop(&mut self) {
        unsafe {
            gl_raw::DeleteProgram(self.program_id);
        }
    }
}

impl Program {
    pub fn new(shader1: Shader, shader2: Shader) -> Result<Program, String> {
        let program;

        unsafe {
            program = Program { program_id: gl_raw::CreateProgram() };

            gl_raw::AttachShader(shader1.id(), program.id());
            gl_raw::AttachShader(shader2.id(), program.id());
            gl_raw::LinkProgram(program.id());
        }

        let mut status: GLint = 0;

        unsafe {
            gl_raw::GetProgramiv(program.id(), gl_raw::LINK_STATUS, &mut status);
        }

        if status == 0 {
            match Program::get_program_log(&program) {
                Ok(message) => Err(message),
                Err(into_string_error) => Err(into_string_error.description().to_string()),
            }
        } else {
            Ok(program)
        }
    }

    pub fn use_program(&self){
        unsafe {
            gl_raw::UseProgram(self.program_id);
        }
    }

    pub(crate) fn id(&self) -> GLuint {
        self.program_id
    }

    fn get_program_log(program: &Program) -> Result<String, IntoStringError> {
        let mut log_length: GLint = 0;

        unsafe {
            gl_raw::GetProgramiv(program.id(), gl_raw::INFO_LOG_LENGTH, &mut log_length);
        }

        let buffer = create_string_buffer(log_length as usize).into_raw();

        unsafe {
            gl_raw::GetProgramInfoLog(program.id(), log_length, ptr::null_mut(), buffer );
            CString::from_raw(buffer).into_string()
        }
    }
}

fn create_string_buffer(len: usize) -> CString {
    let mut buffer: Vec<u8> = Vec::with_capacity(len);

    for _ in 0..len {
        buffer.push(b' ');
    }

    if buffer.len() != len {
        panic!("buffer and log length differs");
    }

    CString::new(buffer).unwrap()
}

<commit_msg>Fix for Program::new<commit_after>/*
gl/src/gl_wrapper/shader.rs, 2017-07-14

Copyright (c) 2017 Juuso Tuononen

This file is licensed under

Apache License, Version 2.0

or

MIT License
*/

use super::gl_raw;
use self::gl_raw::types::*;

use std::ffi::{CString, IntoStringError};
use std::ptr;
use std::error::Error;

#[derive(Debug)]
pub enum ShaderType {
    Vertex,
    Fragment,
}

impl ShaderType {
    fn as_gl_enum(self) -> GLenum {
        match self {
            ShaderType::Fragment => gl_raw::FRAGMENT_SHADER,
            ShaderType::Vertex => gl_raw::VERTEX_SHADER,
        }
    }
}

pub struct Shader {
    shader_id: GLuint,
}

impl Shader {
    pub fn new(shader_type: ShaderType, shader_text: CString) -> Result<Shader, String> {
        let shader_type: GLenum = shader_type.as_gl_enum();
        let shader;

        unsafe {
            shader = Shader { shader_id: gl_raw::CreateShader(shader_type) };

            gl_raw::ShaderSource(shader.id(), 1, &shader_text.as_ptr(), ptr::null());
            gl_raw::CompileShader(shader.id());
        }

        let mut status: GLint = 0;

        unsafe {
            gl_raw::GetShaderiv(shader.id(), gl_raw::COMPILE_STATUS, &mut status);
        }

        if status == 0 {
            match Shader::get_shader_log(&shader) {
                Ok(message) => Err(message),
                Err(into_string_error) => Err(into_string_error.description().to_string()),
            }
        } else {
            Ok(shader)
        }
    }

    fn id(&self) -> GLuint {
        self.shader_id
    }

    fn get_shader_log(shader: &Shader) -> Result<String, IntoStringError> {
        let mut log_length: GLint = 0;

        unsafe {
            gl_raw::GetShaderiv(shader.id(), gl_raw::INFO_LOG_LENGTH, &mut log_length);
        }

        let buffer = create_string_buffer(log_length as usize).into_raw();

        unsafe {
            gl_raw::GetShaderInfoLog(shader.id(), log_length, ptr::null_mut(), buffer);
            CString::from_raw(buffer).into_string()
        }
    }
}

impl Drop for Shader {
    fn drop(&mut self) {
        unsafe {
            gl_raw::DeleteShader(self.shader_id);
        }
    }
}

pub struct Program {
    program_id: GLuint,
}

impl Drop for Program {
    fn drop(&mut self) {
        unsafe {
            gl_raw::DeleteProgram(self.program_id);
        }
    }
}

impl Program {
    pub fn new(shader1: Shader, shader2: Shader) -> Result<Program, String> {
        let program;

        unsafe {
            program = Program { program_id: gl_raw::CreateProgram() };

            gl_raw::AttachShader(program.id(), shader1.id());
            gl_raw::AttachShader(program.id(), shader2.id());
            gl_raw::LinkProgram(program.id());
        }

        let mut status: GLint = 0;

        unsafe {
            gl_raw::GetProgramiv(program.id(), gl_raw::LINK_STATUS, &mut status);
        }

        if status == 0 {
            match Program::get_program_log(&program) {
                Ok(message) => Err(message),
                Err(into_string_error) => Err(into_string_error.description().to_string()),
            }
        } else {
            Ok(program)
        }
    }

    pub fn use_program(&self){
        unsafe {
            gl_raw::UseProgram(self.program_id);
        }
    }

    pub(crate) fn id(&self) -> GLuint {
        self.program_id
    }

    fn get_program_log(program: &Program) -> Result<String, IntoStringError> {
        let mut log_length: GLint = 0;

        unsafe {
            gl_raw::GetProgramiv(program.id(), gl_raw::INFO_LOG_LENGTH, &mut log_length);
        }

        let buffer = create_string_buffer(log_length as usize).into_raw();

        unsafe {
            gl_raw::GetProgramInfoLog(program.id(), log_length, ptr::null_mut(), buffer );
            CString::from_raw(buffer).into_string()
        }
    }
}

fn create_string_buffer(len: usize) -> CString {
    let mut buffer: Vec<u8> = Vec::with_capacity(len);

    for _ in 0..len {
        buffer.push(b' ');
    }

    if buffer.len() != len {
        panic!("buffer and log length differs");
    }

    CString::new(buffer).unwrap()
}

<|endoftext|>


<commit_before>//!

use std::marker::PhantomData;

use super::{
    context::GraphicsContext,
    gpu::{
        arc::{ArcBindGroup, ArcBindGroupLayout, ArcBuffer, ArcShaderModule},
        bind_group::BindGroupBuilder,
    },
    image::Image,
    sampler::Sampler,
};
use crevice::std140::Std140;
use wgpu::util::DeviceExt;

/// A custom fragment shader that can be used to render with shader effects.
///
/// Adapted from the `shader.rs` example:
/// ```rust
/// # use ggez::*;
/// # use ggez::graphics::*;
/// #[derive(AsStd140)]
/// struct Dim {
///     rate: f32,
/// }
///
/// struct MainState {}
///
/// impl event::EventHandler for MainState {
/// #   fn update(&mut self, _ctx: &mut Context) -> Result<(), GameError> { Ok(()) }
///     fn draw(&mut self, ctx: &mut Context) -> GameResult {
///         let mut canvas = graphics::Canvas::from_frame(&ctx.gfx, Color::BLACK);
///         let dim = Dim { rate: 0.5 };
///         // NOTE: This is for simplicity; do not recreate your shader every frame like this!
///         //       For more info look at the full example.
///         let shader = Shader::from_wgsl(
///             &ctx.gfx,
///             include_str!("../resources/dimmer.wgsl"),
///             "main"
///         );
///         let params = ShaderParams::new(&mut ctx.gfx, &dim, &[], &[]);
///         params.set_uniforms(&ctx.gfx, &dim);
///
///         canvas.set_shader(shader);
///         canvas.set_shader_params(params);
///         // draw something...
///         canvas.finish(&mut ctx.gfx)
///     }
/// }
/// ```
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Shader {
    pub(crate) fragment: ArcShaderModule,
    pub(crate) fs_entry: String,
}

impl Shader {
    /// Creates a shader from a WGSL string.
    pub fn from_wgsl(gfx: &GraphicsContext, wgsl: &str, fs_entry: &str) -> Self {
        let module = ArcShaderModule::new(gfx.wgpu.device.create_shader_module(
            &wgpu::ShaderModuleDescriptor {
                label: None,
                source: wgpu::ShaderSource::Wgsl(wgsl.into()),
            },
        ));

        Shader {
            fragment: module,
            fs_entry: fs_entry.into(),
        }
    }
}

pub use crevice::std140::AsStd140;

/// Parameters that can be passed to a custom shader, including uniforms, images, and samplers.
#[derive(Debug, PartialEq, Eq)]
pub struct ShaderParams<Uniforms: AsStd140> {
    pub(crate) uniforms: ArcBuffer,
    pub(crate) layout: ArcBindGroupLayout,
    pub(crate) bind_group: ArcBindGroup,
    _marker: PhantomData<Uniforms>,
}

impl<Uniforms: AsStd140> ShaderParams<Uniforms> {
    /// Creates a new [ShaderParams], initialized with the given uniforms, images, and samplers.
    pub fn new(
        gfx: &mut GraphicsContext,
        uniforms: &Uniforms,
        images: &[&Image],
        samplers: &[Sampler],
    ) -> Self {
        let uniforms = ArcBuffer::new(gfx.wgpu.device.create_buffer_init(
            &wgpu::util::BufferInitDescriptor {
                label: None,
                usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
                contents: uniforms.as_std140().as_bytes(),
            },
        ));

        let samplers = samplers
            .iter()
            .map(|&sampler| gfx.sampler_cache.get(&gfx.wgpu.device, sampler))
            .collect::<Vec<_>>();

        let mut builder = BindGroupBuilder::new();
        builder = builder.buffer(
            &uniforms,
            0,
            wgpu::ShaderStages::VERTEX_FRAGMENT,
            wgpu::BufferBindingType::Uniform,
            false,
            None,
        );

        for image in images {
            builder = builder.image(&image.view, wgpu::ShaderStages::FRAGMENT);
        }

        for sampler in &samplers {
            builder = builder.sampler(sampler, wgpu::ShaderStages::FRAGMENT);
        }

        let (bind_group, layout) = builder.create(&gfx.wgpu.device, &mut gfx.bind_group_cache);

        ShaderParams {
            uniforms,
            layout,
            bind_group,
            _marker: PhantomData,
        }
    }

    /// Updates the uniform data.
    pub fn set_uniforms(&self, gfx: &GraphicsContext, uniforms: &Uniforms) {
        gfx.wgpu
            .queue
            .write_buffer(&self.uniforms, 0, uniforms.as_std140().as_bytes());
    }
}

impl<Uniforms: AsStd140> Clone for ShaderParams<Uniforms> {
    fn clone(&self) -> Self {
        Self {
            uniforms: self.uniforms.clone(),
            layout: self.layout.clone(),
            bind_group: self.bind_group.clone(),
            _marker: PhantomData,
        }
    }
}

pub use wgpu::{BlendComponent, BlendFactor, BlendOperation};

/// Describes the blend mode used when drawing images.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct BlendMode {
    /// The blend mode for the color channels.
    pub color: BlendComponent,
    /// The blend mode for the alpha channel.
    pub alpha: BlendComponent,
}

impl BlendMode {
    /// When combining two fragments, add their values together, saturating
    /// at 1.0
    pub const ADD: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::SrcAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::OneMinusDstAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
    };

    /// When combining two fragments, subtract the source value from the
    /// destination value
    pub const SUBTRACT: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::SrcAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::ReverseSubtract,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::Zero,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
    };

    /// When combining two fragments, add the value of the source times its
    /// alpha channel with the value of the destination multiplied by the inverse
    /// of the source alpha channel. Has the usual transparency effect: mixes the
    /// two colors using a fraction of each one specified by the alpha of the source.
    pub const ALPHA: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::SrcAlpha,
            dst_factor: BlendFactor::OneMinusSrcAlpha,
            operation: BlendOperation::Add,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::OneMinusDstAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
    };

    /// When combining two fragments, subtract the destination color from a constant
    /// color using the source color as weight. Has an invert effect with the constant
    /// color as base and source color controlling displacement from the base color.
    /// A white source color and a white value results in plain invert. The output
    /// alpha is same as destination alpha.
    pub const INVERT: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::Constant,
            dst_factor: BlendFactor::Src,
            operation: BlendOperation::Subtract,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::Zero,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
    };

    /// When combining two fragments, multiply their values together (including alpha)
    pub const MULTIPLY: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::Dst,
            dst_factor: BlendFactor::Zero,
            operation: BlendOperation::Add,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::DstAlpha,
            dst_factor: BlendFactor::Zero,
            operation: BlendOperation::Add,
        },
    };

    /// When combining two fragments, choose the source value (including source alpha)
    pub const REPLACE: Self = BlendMode {
        color: wgpu::BlendState::REPLACE.color,
        alpha: wgpu::BlendState::REPLACE.alpha,
    };

    /// When combining two fragments, choose the lighter value
    pub const LIGHTEN: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::SrcAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Max,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::OneMinusDstAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
    };

    /// When combining two fragments, choose the darker value
    pub const DARKEN: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::SrcAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Min,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::OneMinusDstAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
    };

    /// When using premultiplied alpha, use this.
    ///
    /// You usually want to use this blend mode for drawing canvases
    /// containing semi-transparent imagery.
    /// For an explanation on this see: <https://github.com/ggez/ggez/issues/694#issuecomment-853724926>
    pub const PREMULTIPLIED: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::One,
            dst_factor: BlendFactor::OneMinusSrcAlpha,
            operation: BlendOperation::Add,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::OneMinusDstAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
    };
}
<commit_msg>added `/* ... */`<commit_after>//!

use std::marker::PhantomData;

use super::{
    context::GraphicsContext,
    gpu::{
        arc::{ArcBindGroup, ArcBindGroupLayout, ArcBuffer, ArcShaderModule},
        bind_group::BindGroupBuilder,
    },
    image::Image,
    sampler::Sampler,
};
use crevice::std140::Std140;
use wgpu::util::DeviceExt;

/// A custom fragment shader that can be used to render with shader effects.
///
/// Adapted from the `shader.rs` example:
/// ```rust
/// # use ggez::*;
/// # use ggez::graphics::*;
/// #[derive(AsStd140)]
/// struct Dim {
///     rate: f32,
/// }
///
/// struct MainState {}
///
/// impl event::EventHandler for MainState {
/// #   fn update(&mut self, _ctx: &mut Context) -> Result<(), GameError> { Ok(()) }
///     fn draw(&mut self, ctx: &mut Context) -> GameResult {
///         let mut canvas = graphics::Canvas::from_frame(&ctx.gfx, Color::BLACK);
///         let dim = Dim { rate: 0.5 };
///         // NOTE: This is for simplicity; do not recreate your shader every frame like this!
///         //       For more info look at the full example.
///         let shader = Shader::from_wgsl(
///             &ctx.gfx,
///             include_str!("../resources/dimmer.wgsl"),
///             "main"
///         );
///         let params = ShaderParams::new(&mut ctx.gfx, &dim, &[], &[]);
///         params.set_uniforms(&ctx.gfx, &dim);
///
///         canvas.set_shader(shader);
///         canvas.set_shader_params(params);
///         // draw something...
///         canvas.finish(&mut ctx.gfx)
///     }
///
///     /* ... */
/// }
/// ```
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Shader {
    pub(crate) fragment: ArcShaderModule,
    pub(crate) fs_entry: String,
}

impl Shader {
    /// Creates a shader from a WGSL string.
    pub fn from_wgsl(gfx: &GraphicsContext, wgsl: &str, fs_entry: &str) -> Self {
        let module = ArcShaderModule::new(gfx.wgpu.device.create_shader_module(
            &wgpu::ShaderModuleDescriptor {
                label: None,
                source: wgpu::ShaderSource::Wgsl(wgsl.into()),
            },
        ));

        Shader {
            fragment: module,
            fs_entry: fs_entry.into(),
        }
    }
}

pub use crevice::std140::AsStd140;

/// Parameters that can be passed to a custom shader, including uniforms, images, and samplers.
#[derive(Debug, PartialEq, Eq)]
pub struct ShaderParams<Uniforms: AsStd140> {
    pub(crate) uniforms: ArcBuffer,
    pub(crate) layout: ArcBindGroupLayout,
    pub(crate) bind_group: ArcBindGroup,
    _marker: PhantomData<Uniforms>,
}

impl<Uniforms: AsStd140> ShaderParams<Uniforms> {
    /// Creates a new [ShaderParams], initialized with the given uniforms, images, and samplers.
    pub fn new(
        gfx: &mut GraphicsContext,
        uniforms: &Uniforms,
        images: &[&Image],
        samplers: &[Sampler],
    ) -> Self {
        let uniforms = ArcBuffer::new(gfx.wgpu.device.create_buffer_init(
            &wgpu::util::BufferInitDescriptor {
                label: None,
                usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
                contents: uniforms.as_std140().as_bytes(),
            },
        ));

        let samplers = samplers
            .iter()
            .map(|&sampler| gfx.sampler_cache.get(&gfx.wgpu.device, sampler))
            .collect::<Vec<_>>();

        let mut builder = BindGroupBuilder::new();
        builder = builder.buffer(
            &uniforms,
            0,
            wgpu::ShaderStages::VERTEX_FRAGMENT,
            wgpu::BufferBindingType::Uniform,
            false,
            None,
        );

        for image in images {
            builder = builder.image(&image.view, wgpu::ShaderStages::FRAGMENT);
        }

        for sampler in &samplers {
            builder = builder.sampler(sampler, wgpu::ShaderStages::FRAGMENT);
        }

        let (bind_group, layout) = builder.create(&gfx.wgpu.device, &mut gfx.bind_group_cache);

        ShaderParams {
            uniforms,
            layout,
            bind_group,
            _marker: PhantomData,
        }
    }

    /// Updates the uniform data.
    pub fn set_uniforms(&self, gfx: &GraphicsContext, uniforms: &Uniforms) {
        gfx.wgpu
            .queue
            .write_buffer(&self.uniforms, 0, uniforms.as_std140().as_bytes());
    }
}

impl<Uniforms: AsStd140> Clone for ShaderParams<Uniforms> {
    fn clone(&self) -> Self {
        Self {
            uniforms: self.uniforms.clone(),
            layout: self.layout.clone(),
            bind_group: self.bind_group.clone(),
            _marker: PhantomData,
        }
    }
}

pub use wgpu::{BlendComponent, BlendFactor, BlendOperation};

/// Describes the blend mode used when drawing images.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct BlendMode {
    /// The blend mode for the color channels.
    pub color: BlendComponent,
    /// The blend mode for the alpha channel.
    pub alpha: BlendComponent,
}

impl BlendMode {
    /// When combining two fragments, add their values together, saturating
    /// at 1.0
    pub const ADD: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::SrcAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::OneMinusDstAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
    };

    /// When combining two fragments, subtract the source value from the
    /// destination value
    pub const SUBTRACT: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::SrcAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::ReverseSubtract,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::Zero,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
    };

    /// When combining two fragments, add the value of the source times its
    /// alpha channel with the value of the destination multiplied by the inverse
    /// of the source alpha channel. Has the usual transparency effect: mixes the
    /// two colors using a fraction of each one specified by the alpha of the source.
    pub const ALPHA: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::SrcAlpha,
            dst_factor: BlendFactor::OneMinusSrcAlpha,
            operation: BlendOperation::Add,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::OneMinusDstAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
    };

    /// When combining two fragments, subtract the destination color from a constant
    /// color using the source color as weight. Has an invert effect with the constant
    /// color as base and source color controlling displacement from the base color.
    /// A white source color and a white value results in plain invert. The output
    /// alpha is same as destination alpha.
    pub const INVERT: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::Constant,
            dst_factor: BlendFactor::Src,
            operation: BlendOperation::Subtract,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::Zero,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
    };

    /// When combining two fragments, multiply their values together (including alpha)
    pub const MULTIPLY: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::Dst,
            dst_factor: BlendFactor::Zero,
            operation: BlendOperation::Add,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::DstAlpha,
            dst_factor: BlendFactor::Zero,
            operation: BlendOperation::Add,
        },
    };

    /// When combining two fragments, choose the source value (including source alpha)
    pub const REPLACE: Self = BlendMode {
        color: wgpu::BlendState::REPLACE.color,
        alpha: wgpu::BlendState::REPLACE.alpha,
    };

    /// When combining two fragments, choose the lighter value
    pub const LIGHTEN: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::SrcAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Max,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::OneMinusDstAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
    };

    /// When combining two fragments, choose the darker value
    pub const DARKEN: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::SrcAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Min,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::OneMinusDstAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
    };

    /// When using premultiplied alpha, use this.
    ///
    /// You usually want to use this blend mode for drawing canvases
    /// containing semi-transparent imagery.
    /// For an explanation on this see: <https://github.com/ggez/ggez/issues/694#issuecomment-853724926>
    pub const PREMULTIPLIED: Self = BlendMode {
        color: BlendComponent {
            src_factor: BlendFactor::One,
            dst_factor: BlendFactor::OneMinusSrcAlpha,
            operation: BlendOperation::Add,
        },
        alpha: BlendComponent {
            src_factor: BlendFactor::OneMinusDstAlpha,
            dst_factor: BlendFactor::One,
            operation: BlendOperation::Add,
        },
    };
}
<|endoftext|>


<commit_before>// http://rosettacode.org/wiki/Handle_a_signal

extern crate libc;
extern crate time;

use std::mem;
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
use std::thread;
use std::time::Duration;

#[cfg(unix)]
use libc::SIGINT;

#[cfg(unix)]
fn main() {
    // The time between ticks of our counter.
    let duration = Duration::from_secs(1) / 2;
    // "SIGINT received" global variable.
    static mut GOT_SIGINT: AtomicBool = ATOMIC_BOOL_INIT;
    unsafe {
        // Initially, "SIGINT received" is false.
        GOT_SIGINT.store(false, Ordering::Release);
        // Interrupt handler that handles the SIGINT signal
        unsafe fn handle_sigint() {
            // It is dangerous to perform any system calls in interrupts, so just set the atomic
            // "SIGINT received" global to true when it arrives.
            GOT_SIGINT.store(true, Ordering::Release);
        }
        // Make handle_sigint the signal handler for SIGINT.
        libc::signal(SIGINT, mem::transmute(handle_sigint));
    }
    // Get the start time...
    let start = time::precise_time_ns();
    // Integer counter
    let mut i = 0u32;
    // Every `duration`...
    loop {
        thread::sleep(duration);
        // Break if SIGINT was handled
        if unsafe { GOT_SIGINT.load(Ordering::Acquire) } {
            break;
        }
        // Otherwise, increment and display the integer and continue the loop.
        i += 1;
        println!("{}", i);
    }
    // Get the end time.
    let end = time::precise_time_ns();
    // Compute the difference
    let diff = Duration::from_millis((end - start) / 1000000);
    // Print the difference and exit
    println!("Program has run for {} seconds", diff.as_secs());
}

#[cfg(not(unix))]
fn main() {
    println!("Not supported on this platform");
}
<commit_msg>Remove compile warnings for signal handling solution<commit_after>// http://rosettacode.org/wiki/Handle_a_signal

extern crate libc;
extern crate time;

#[cfg(unix)]
fn main() {
    use std::mem;
    use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
    use std::thread;
    use std::time::Duration;
    use libc::SIGINT;
    // The time between ticks of our counter.
    let duration = Duration::from_secs(1) / 2;
    // "SIGINT received" global variable.
    static mut GOT_SIGINT: AtomicBool = ATOMIC_BOOL_INIT;
    unsafe {
        // Initially, "SIGINT received" is false.
        GOT_SIGINT.store(false, Ordering::Release);
        // Interrupt handler that handles the SIGINT signal
        unsafe fn handle_sigint() {
            // It is dangerous to perform any system calls in interrupts, so just set the atomic
            // "SIGINT received" global to true when it arrives.
            GOT_SIGINT.store(true, Ordering::Release);
        }
        // Make handle_sigint the signal handler for SIGINT.
        libc::signal(SIGINT, mem::transmute(handle_sigint));
    }
    // Get the start time...
    let start = time::precise_time_ns();
    // Integer counter
    let mut i = 0u32;
    // Every `duration`...
    loop {
        thread::sleep(duration);
        // Break if SIGINT was handled
        if unsafe { GOT_SIGINT.load(Ordering::Acquire) } {
            break;
        }
        // Otherwise, increment and display the integer and continue the loop.
        i += 1;
        println!("{}", i);
    }
    // Get the end time.
    let end = time::precise_time_ns();
    // Compute the difference
    let diff = Duration::from_millis((end - start) / 1000000);
    // Print the difference and exit
    println!("Program has run for {} seconds", diff.as_secs());
}

#[cfg(not(unix))]
fn main() {
    println!("Not supported on this platform");
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate milagro_crypto;
use self::milagro_crypto::randapi::Random;
use self::milagro_crypto::big::wrappers::MODBYTES;
use self::milagro_crypto::ff::FF;
use self::milagro_crypto::hash::wrappers::hash256;
use self::rand::os::OsRng;
use self::rand::Rng;
use services::crypto::constants::{
    BIG_SIZE,
    BN_MASK,
    PRIMES,
    NUM_PRIMES,
    LARGE_PRIME
};
use services::crypto::types::{ByteOrder};

pub fn generate_random_seed() -> [u8; 32] {
    let mut seed: [u8; 32] = [0; 32];
    let mut rng = OsRng::new().unwrap();
    rng.fill_bytes(&mut seed);
    seed
}

pub fn generate_big_random(size: usize) -> FF {
    let seed = generate_random_seed();
    let mut rng = Random::new(seed);

    let b_size: usize = size / 8 + 1; // number of bytes for mod value
    let big_size: usize = (b_size + MODBYTES - 1) / MODBYTES; // number of BIGs for mod value

    // init mod bytes with 0 and set 1 in proper place
    let mut bytes = vec![0; big_size * MODBYTES];
    bytes[big_size * MODBYTES - b_size] = (1 as u8).wrapping_shl((size - (b_size - 1) * 8) as u32);

    let bv = FF::from_bytes(&bytes[0..], big_size * MODBYTES, BIG_SIZE);
    let r = FF::randomnum(&bv, &mut rng);
    r
}

pub fn generate_prime(size: usize) -> FF {
    let seed = generate_random_seed();
    let mut rng = Random::new(seed);
    let mut iteration = 0;
    let mut is_prime = false;

    let mut prime = generate_big_random(size);
    let mut prime_bytes = prime.to_bytes();
    let length = prime_bytes.len();
    let last_byte = prime_bytes[length - 1];
    prime_bytes[length - 1] = last_byte | 3;
    prime = FF::from_bytes(&prime_bytes, length, BIG_SIZE);
    while !is_prime {
        prime.inc(4);
        iteration += 1;
        is_prime = FF::is_prime(&prime, &mut rng);
    }
    debug!("Iteration: {}\nFound prime: {}", iteration, prime);

    prime
}

pub fn generate_prime_2p_plus_1(size: usize) -> FF {
    let seed = generate_random_seed();
    let mut rng = Random::new(seed);
    let (mut is_prime, mut iteration) = (false, 0);
    let mut prime = FF::new(BIG_SIZE);

    while !is_prime {
        iteration += 1;
        prime = generate_prime(size);
        let mut prime_for_check = FF::mul(&prime, &FF::from_hex("2", BIG_SIZE));
        prime_for_check.inc(1);
        is_prime = FF::is_prime(&prime_for_check, &mut rng);
        debug!("Iteration: {}\nFound prime: {}\nis_prime: {}\n", iteration, prime, is_prime);
    }
    prime
}

pub fn random_qr(n: &FF){

}

fn random_in_range(start: &FF, end: &FF) {
    let sub = end - start;
    let size = significant_bits(&sub);
    let mut random_number = generate_big_random(size);
    //        while (&random_number + start) > *end {
    //            random_number.rand(sub.num_bits(), MSB_MAYBE_ZERO, false).unwrap();
    //        }
    //    &random_number + start
    debug!("start: {}\nend: {}\nsub: {}\nrandom: {}", start, end, sub, random_number);
}

pub fn encode_attribute(attribute: &str, byte_order: ByteOrder) {
    //    let mut result = hash(MessageDigest::sha256(), attribute.as_bytes()).unwrap();
    //    let index = result.iter().position(|&value| value == 0);
    //    if let Some(position) = index {
    //        result.truncate(position);
    //    }
    //    if let ByteOrder::Little = byte_order {
    //        result.reverse();
    //    }
    //    let encoded_attribute = AnoncredsService::transform_byte_array_to_big_integer(&result);
    //    encoded_attribute.to_dec_str().unwrap().to_string()
}

fn significant_bytes(n: &FF) -> Vec<u8> {
    let mut bytes = n.to_bytes();
    let length = bytes.len();
    let index = bytes.iter().position(|&value| value != 0);
    if let Some(index) = index {
        bytes.reverse();
        bytes.truncate(length - index);
        bytes.reverse();
    }
    bytes
}

fn significant_bits(n: &FF) -> usize {
    let bytes = significant_bytes(n);
    let mut result = (bytes.len() - 1) * 8;
    result += format!("{:b}", bytes[0]).len();
    result
}

fn generate_probable_prime(size: usize) {
    let mut random_number = generate_big_random(size);
    let mut mods: Vec<FF> = Vec::new();
    for i in 1..NUM_PRIMES {
        debug!("{}", i);
        let bytes = random_number.to_bytes();
        let mut new_random = FF::from_bytes(&bytes, size, BIG_SIZE);
        let prime = FF::from_hex(&format!("{:x}", PRIMES[i])[..], BIG_SIZE);
        FF::modulus(&mut new_random, &prime);
        mods.push(new_random);
    }
    //TODO loop for mods check
}

pub fn get_hash_as_int(num: FF) -> FF {
    let array_bytes: Vec<u8> = num.to_bytes();

    let index = array_bytes.iter().position(|&value| value != 0).unwrap_or(array_bytes.len());

    let mut sha256: hash256 = hash256::new();

    for byte in array_bytes[index..].iter() {
        sha256.process(*byte);
    }

    let mut hashed_array: Vec<u8> =
        sha256.hash().iter()
            .map(|v| *v as u8)
            .collect();

    hashed_array.reverse();

    FF::from_bytes(&hashed_array[..], hashed_array.len(), 2)
}

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

    #[test]
    fn random_in_range_works() {
        ::env_logger::init().unwrap();

        let random1 = generate_big_random(20);
        let random2 = generate_big_random(30);
        let a = random_in_range(&random1, &random2);
    }
}<commit_msg>finished random_in_range function<commit_after>extern crate rand;
extern crate milagro_crypto;
use self::milagro_crypto::randapi::Random;
use self::milagro_crypto::big::wrappers::MODBYTES;
use self::milagro_crypto::ff::FF;
use self::milagro_crypto::hash::wrappers::hash256;
use self::rand::os::OsRng;
use self::rand::Rng;
use services::crypto::constants::{
    BIG_SIZE,
    BN_MASK,
    PRIMES,
    NUM_PRIMES,
    LARGE_PRIME
};
use services::crypto::types::{ByteOrder};

pub fn generate_random_seed() -> [u8; 32] {
    let mut seed: [u8; 32] = [0; 32];
    let mut rng = OsRng::new().unwrap();
    rng.fill_bytes(&mut seed);
    seed
}

pub fn generate_big_random(size: usize) -> FF {
    let seed = generate_random_seed();
    let mut rng = Random::new(seed);

    let b_size: usize = size / 8 + 1; // number of bytes for mod value
    let big_size: usize = (b_size + MODBYTES - 1) / MODBYTES; // number of BIGs for mod value

    // init mod bytes with 0 and set 1 in proper place
    let mut bytes = vec![0; big_size * MODBYTES];
    bytes[big_size * MODBYTES - b_size] = (1 as u8).wrapping_shl((size - (b_size - 1) * 8) as u32);

    let bv = FF::from_bytes(&bytes[0..], big_size * MODBYTES, BIG_SIZE);
    let r = FF::randomnum(&bv, &mut rng);
    r
}

pub fn generate_prime(size: usize) -> FF {
    let seed = generate_random_seed();
    let mut rng = Random::new(seed);
    let mut iteration = 0;
    let mut is_prime = false;

    let mut prime = generate_big_random(size);
    let mut prime_bytes = prime.to_bytes();
    let length = prime_bytes.len();
    let last_byte = prime_bytes[length - 1];
    prime_bytes[length - 1] = last_byte | 3;
    prime = FF::from_bytes(&prime_bytes, length, BIG_SIZE);
    while !is_prime {
        prime.inc(4);
        iteration += 1;
        is_prime = FF::is_prime(&prime, &mut rng);
    }
    debug!("Iteration: {}\nFound prime: {}", iteration, prime);

    prime
}

pub fn generate_prime_2p_plus_1(size: usize) -> FF {
    let seed = generate_random_seed();
    let mut rng = Random::new(seed);
    let (mut is_prime, mut iteration) = (false, 0);
    let mut prime = FF::new(BIG_SIZE);

    while !is_prime {
        iteration += 1;
        prime = generate_prime(size);
        let mut prime_for_check = FF::mul(&prime, &FF::from_hex("2", BIG_SIZE));
        prime_for_check.inc(1);
        is_prime = FF::is_prime(&prime_for_check, &mut rng);
        debug!("Iteration: {}\nFound prime: {}\nis_prime: {}\n", iteration, prime, is_prime);
    }
    prime
}

pub fn random_qr(n: &FF){

}

fn random_in_range(start: &FF, end: &FF) -> FF {
    let sub = end - start;
    let size = significant_bits(&sub);
    let mut random_number = generate_big_random(size);

    while (&random_number + start) > *end {
        random_number = generate_big_random(size);
    }

    random_number = &random_number + start;
    debug!("start: {}\nend: {}\nsub: {}\nrandom: {}", start, end, sub, random_number);
    random_number
}

pub fn encode_attribute(attribute: &str, byte_order: ByteOrder) {
    //    let mut result = hash(MessageDigest::sha256(), attribute.as_bytes()).unwrap();
    //    let index = result.iter().position(|&value| value == 0);
    //    if let Some(position) = index {
    //        result.truncate(position);
    //    }
    //    if let ByteOrder::Little = byte_order {
    //        result.reverse();
    //    }
    //    let encoded_attribute = AnoncredsService::transform_byte_array_to_big_integer(&result);
    //    encoded_attribute.to_dec_str().unwrap().to_string()
}

fn significant_bytes(n: &FF) -> Vec<u8> {
    let mut bytes = n.to_bytes();
    let length = bytes.len();
    let index = bytes.iter().position(|&value| value != 0);
    if let Some(index) = index {
        bytes.reverse();
        bytes.truncate(length - index);
        bytes.reverse();
    }
    bytes
}

fn significant_bits(n: &FF) -> usize {
    let bytes = significant_bytes(n);
    let mut result = (bytes.len() - 1) * 8;
    result += format!("{:b}", bytes[0]).len();
    result
}

fn generate_probable_prime(size: usize) {
    let mut random_number = generate_big_random(size);
    let mut mods: Vec<FF> = Vec::new();
    for i in 1..NUM_PRIMES {
        debug!("{}", i);
        let bytes = random_number.to_bytes();
        let mut new_random = FF::from_bytes(&bytes, size, BIG_SIZE);
        let prime = FF::from_hex(&format!("{:x}", PRIMES[i])[..], BIG_SIZE);
        FF::modulus(&mut new_random, &prime);
        mods.push(new_random);
    }
    //TODO loop for mods check
}

pub fn get_hash_as_int(num: FF) -> FF {
    let array_bytes: Vec<u8> = num.to_bytes();

    let index = array_bytes.iter().position(|&value| value != 0).unwrap_or(array_bytes.len());

    let mut sha256: hash256 = hash256::new();

    for byte in array_bytes[index..].iter() {
        sha256.process(*byte);
    }

    let mut hashed_array: Vec<u8> =
        sha256.hash().iter()
            .map(|v| *v as u8)
            .collect();

    hashed_array.reverse();

    FF::from_bytes(&hashed_array[..], hashed_array.len(), 2)
}

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

    #[test]
    fn random_in_range_works() {
        ::env_logger::init().unwrap();

        let start = generate_big_random(100);
        let mut end = generate_big_random(120);

        while end < start {
            end = generate_big_random(30);
        }

        let random = random_in_range(&start, &end);
        assert!((random > start) && (random < end));
    }
}<|endoftext|>


<commit_before>//! Log all requests in a format similar to Heroku's router, but with additional
//! information that we care about like User-Agent

use super::prelude::*;
use crate::util::request_header;
use conduit::Request;
use std::fmt;
use std::time::Instant;

#[allow(missing_debug_implementations)] // We can't
#[derive(Default)]
pub struct LogRequests {
    handler: Option<Box<dyn Handler>>,
}

impl AroundMiddleware for LogRequests {
    fn with_handler(&mut self, handler: Box<dyn Handler>) {
        self.handler = Some(handler);
    }
}

impl Handler for LogRequests {
    fn call(&self, req: &mut dyn Request) -> Result<Response, Box<dyn Error + Send>> {
        let request_start = Instant::now();
        let res = self.handler.as_ref().unwrap().call(req);
        let (level, response_code) = match res {
            Ok(ref r) => ("info", r.status.0),
            Err(_) => ("error", 500),
        };
        let response_time = request_start.elapsed();
        let response_time =
            response_time.as_secs() * 1000 + u64::from(response_time.subsec_nanos()) / 1_000_000;

        let metadata_length = req
            .extensions()
            .find::<u64>()
            .map_or(String::new(), |l| format!(" metadata_length={}", l));

        let slow_request = if response_time > 1000 {
            " SLOW REQUEST"
        } else {
            ""
        };

        let error = if let Err(ref e) = res {
            format!(" error=\"{}\"", e.to_string())
        } else {
            String::new()
        };

        println!(
            "at={level} method={method} path=\"{path}\" \
             request_id={request_id} fwd=\"{ip}\" service={time_ms}ms \
             status={status} user_agent=\"{user_agent}\"\
             {metadata_length}{error}{slow_request}",
            level = level,
            method = req.method(),
            path = FullPath(req),
            ip = request_header(req, "X-Real-Ip"),
            time_ms = response_time,
            user_agent = request_header(req, "User-Agent"),
            request_id = request_header(req, "X-Request-Id"),
            status = response_code,
            metadata_length = metadata_length,
            error = error,
            slow_request = slow_request,
        );

        res
    }
}

struct FullPath<'a>(&'a dyn Request);

impl<'a> fmt::Display for FullPath<'a> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.0.path())?;
        if let Some(q_string) = self.0.query_string() {
            write!(f, "?{}", q_string)?;
        }
        Ok(())
    }
}
<commit_msg>Avoid an additional allocation when logging errors<commit_after>//! Log all requests in a format similar to Heroku's router, but with additional
//! information that we care about like User-Agent

use super::prelude::*;
use crate::util::request_header;
use conduit::Request;
use std::fmt;
use std::time::Instant;

#[allow(missing_debug_implementations)] // We can't
#[derive(Default)]
pub struct LogRequests {
    handler: Option<Box<dyn Handler>>,
}

impl AroundMiddleware for LogRequests {
    fn with_handler(&mut self, handler: Box<dyn Handler>) {
        self.handler = Some(handler);
    }
}

impl Handler for LogRequests {
    fn call(&self, req: &mut dyn Request) -> Result<Response, Box<dyn Error + Send>> {
        let request_start = Instant::now();
        let res = self.handler.as_ref().unwrap().call(req);
        let (level, response_code) = match res {
            Ok(ref r) => ("info", r.status.0),
            Err(_) => ("error", 500),
        };
        let response_time = request_start.elapsed();
        let response_time =
            response_time.as_secs() * 1000 + u64::from(response_time.subsec_nanos()) / 1_000_000;

        let metadata_length = req
            .extensions()
            .find::<u64>()
            .map_or(String::new(), |l| format!(" metadata_length={}", l));

        let slow_request = if response_time > 1000 {
            " SLOW REQUEST"
        } else {
            ""
        };

        let error = if let Err(ref e) = res {
            format!(" error=\"{}\"", e)
        } else {
            String::new()
        };

        println!(
            "at={level} method={method} path=\"{path}\" \
             request_id={request_id} fwd=\"{ip}\" service={time_ms}ms \
             status={status} user_agent=\"{user_agent}\"\
             {metadata_length}{error}{slow_request}",
            level = level,
            method = req.method(),
            path = FullPath(req),
            ip = request_header(req, "X-Real-Ip"),
            time_ms = response_time,
            user_agent = request_header(req, "User-Agent"),
            request_id = request_header(req, "X-Request-Id"),
            status = response_code,
            metadata_length = metadata_length,
            error = error,
            slow_request = slow_request,
        );

        res
    }
}

struct FullPath<'a>(&'a dyn Request);

impl<'a> fmt::Display for FullPath<'a> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.0.path())?;
        if let Some(q_string) = self.0.query_string() {
            write!(f, "?{}", q_string)?;
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>pub mod application_command;
pub mod autocomplete;
pub mod message_component;
pub mod ping;

use application_command::ApplicationCommandInteraction;
use autocomplete::AutocompleteInteraction;
use bitflags::__impl_bitflags;
use message_component::MessageComponentInteraction;
use ping::PingInteraction;
use serde::de::{Deserialize, Deserializer, Error as DeError};
use serde::ser::{Serialize, Serializer};
use serde_json::Value;

use super::prelude::*;
use crate::internal::prelude::*;

#[derive(Clone, Debug)]
pub enum Interaction {
    Ping(PingInteraction),
    ApplicationCommand(ApplicationCommandInteraction),
    MessageComponent(MessageComponentInteraction),
    Autocomplete(AutocompleteInteraction),
}

impl Interaction {
    /// Gets the interaction Id.
    pub fn id(&self) -> InteractionId {
        match self {
            Interaction::Ping(i) => i.id,
            Interaction::ApplicationCommand(i) => i.id,
            Interaction::MessageComponent(i) => i.id,
            Interaction::Autocomplete(i) => i.id,
        }
    }

    /// Gets the interaction type
    pub fn kind(&self) -> InteractionType {
        match self {
            Interaction::Ping(_) => InteractionType::Ping,
            Interaction::ApplicationCommand(_) => InteractionType::ApplicationCommand,
            Interaction::MessageComponent(_) => InteractionType::MessageComponent,
            Interaction::Autocomplete(_) => InteractionType::Autocomplete,
        }
    }

    /// Gets the interaction application Id
    pub fn application_id(&self) -> ApplicationId {
        match self {
            Interaction::Ping(i) => i.application_id,
            Interaction::ApplicationCommand(i) => i.application_id,
            Interaction::MessageComponent(i) => i.application_id,
            Interaction::Autocomplete(i) => i.application_id,
        }
    }

    /// Gets the interaction token.
    pub fn token(&self) -> &str {
        match self {
            Interaction::Ping(ref i) => i.token.as_str(),
            Interaction::ApplicationCommand(i) => i.token.as_str(),
            Interaction::MessageComponent(i) => i.token.as_str(),
            Interaction::Autocomplete(i) => i.token.as_str(),
        }
    }

    /// Converts this to a [`PingInteraction`]
    pub fn ping(self) -> Option<PingInteraction> {
        match self {
            Interaction::Ping(i) => Some(i),
            _ => None,
        }
    }

    /// Converts this to an [`ApplicationCommandInteraction`]
    pub fn application_command(self) -> Option<ApplicationCommandInteraction> {
        match self {
            Interaction::ApplicationCommand(i) => Some(i),
            _ => None,
        }
    }

    /// Converts this to a [`MessageComponentInteraction`]
    pub fn message_component(self) -> Option<MessageComponentInteraction> {
        match self {
            Interaction::MessageComponent(i) => Some(i),
            _ => None,
        }
    }

    /// Converts this to a [`AutocompleteInteraction`]
    pub fn autocomplete(self) -> Option<AutocompleteInteraction> {
        match self {
            Interaction::Autocomplete(i) => Some(i),
            _ => None,
        }
    }
}

impl<'de> Deserialize<'de> for Interaction {
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
        let map = JsonMap::deserialize(deserializer)?;

        let kind = map
            .get("type")
            .ok_or_else(|| DeError::custom("expected type"))
            .and_then(InteractionType::deserialize)
            .map_err(DeError::custom)?;

        match kind {
            InteractionType::Ping => serde_json::from_value::<PingInteraction>(Value::Object(map))
                .map(Interaction::Ping)
                .map_err(DeError::custom),
            InteractionType::ApplicationCommand => {
                serde_json::from_value::<ApplicationCommandInteraction>(Value::Object(map))
                    .map(Interaction::ApplicationCommand)
                    .map_err(DeError::custom)
            },
            InteractionType::MessageComponent => {
                serde_json::from_value::<MessageComponentInteraction>(Value::Object(map))
                    .map(Interaction::MessageComponent)
                    .map_err(DeError::custom)
            },
            InteractionType::Autocomplete => {
                serde_json::from_value::<AutocompleteInteraction>(Value::Object(map))
                    .map(Interaction::Autocomplete)
                    .map_err(DeError::custom)
            },
            InteractionType::Unknown => Err(DeError::custom("Unknown interaction type")),
        }
    }
}

impl Serialize for Interaction {
    fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match self {
            Interaction::Ping(i) => PingInteraction::serialize(i, serializer),
            Interaction::ApplicationCommand(i) => {
                ApplicationCommandInteraction::serialize(i, serializer)
            },
            Interaction::MessageComponent(i) => {
                MessageComponentInteraction::serialize(i, serializer)
            },
            Interaction::Autocomplete(i) => AutocompleteInteraction::serialize(i, serializer),
        }
    }
}

/// The type of an Interaction.
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)]
#[non_exhaustive]
#[repr(u8)]
pub enum InteractionType {
    Ping = 1,
    ApplicationCommand = 2,
    MessageComponent = 3,
    Autocomplete = 4,
    Unknown = !0,
}

enum_number!(InteractionType {
    Ping,
    MessageComponent,
    ApplicationCommand,
    Autocomplete,
});

/// The flags for an interaction response.
#[derive(Clone, Serialize, Deserialize)]
#[non_exhaustive]
pub struct InteractionApplicationCommandCallbackDataFlags {
    bits: u64,
}

__impl_bitflags! {
    InteractionApplicationCommandCallbackDataFlags: u64 {
        /// Interaction message will only be visible to sender and will
        /// be quickly deleted.
        EPHEMERAL = 1 << 6;
    }
}

/// Sent when a [`Message`] is a response to an [`Interaction`].
///
/// [`Message`]: crate::model::channel::Message
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct MessageInteraction {
    /// The id of the interaction.
    pub id: InteractionId,
    /// The type of the interaction.
    #[serde(rename = "type")]
    pub kind: InteractionType,
    /// The name of the [`ApplicationCommand`].
    ///
    /// [`ApplicationCommand`]: crate::model::interactions::application_command::ApplicationCommand
    pub name: String,
    /// The user who invoked the interaction.
    pub user: User,
}

/// The available responses types for an interaction response.
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)]
#[non_exhaustive]
#[repr(u8)]
pub enum InteractionResponseType {
    Pong = 1,
    ChannelMessageWithSource = 4,
    DeferredChannelMessageWithSource = 5,
    DeferredUpdateMessage = 6,
    UpdateMessage = 7,
    Autocomplete = 8,
}
<commit_msg>Fix faulty (de)serialization of `InteractionApplicationCommandDataFlags` (#1600)<commit_after>pub mod application_command;
pub mod autocomplete;
pub mod message_component;
pub mod ping;

use application_command::ApplicationCommandInteraction;
use autocomplete::AutocompleteInteraction;
use bitflags::__impl_bitflags;
use message_component::MessageComponentInteraction;
use ping::PingInteraction;
use serde::de::{Deserialize, Deserializer, Error as DeError};
use serde::ser::{Serialize, Serializer};
use serde_json::Value;

use super::prelude::*;
use crate::internal::prelude::*;

#[derive(Clone, Debug)]
pub enum Interaction {
    Ping(PingInteraction),
    ApplicationCommand(ApplicationCommandInteraction),
    MessageComponent(MessageComponentInteraction),
    Autocomplete(AutocompleteInteraction),
}

impl Interaction {
    /// Gets the interaction Id.
    pub fn id(&self) -> InteractionId {
        match self {
            Interaction::Ping(i) => i.id,
            Interaction::ApplicationCommand(i) => i.id,
            Interaction::MessageComponent(i) => i.id,
            Interaction::Autocomplete(i) => i.id,
        }
    }

    /// Gets the interaction type
    pub fn kind(&self) -> InteractionType {
        match self {
            Interaction::Ping(_) => InteractionType::Ping,
            Interaction::ApplicationCommand(_) => InteractionType::ApplicationCommand,
            Interaction::MessageComponent(_) => InteractionType::MessageComponent,
            Interaction::Autocomplete(_) => InteractionType::Autocomplete,
        }
    }

    /// Gets the interaction application Id
    pub fn application_id(&self) -> ApplicationId {
        match self {
            Interaction::Ping(i) => i.application_id,
            Interaction::ApplicationCommand(i) => i.application_id,
            Interaction::MessageComponent(i) => i.application_id,
            Interaction::Autocomplete(i) => i.application_id,
        }
    }

    /// Gets the interaction token.
    pub fn token(&self) -> &str {
        match self {
            Interaction::Ping(ref i) => i.token.as_str(),
            Interaction::ApplicationCommand(i) => i.token.as_str(),
            Interaction::MessageComponent(i) => i.token.as_str(),
            Interaction::Autocomplete(i) => i.token.as_str(),
        }
    }

    /// Converts this to a [`PingInteraction`]
    pub fn ping(self) -> Option<PingInteraction> {
        match self {
            Interaction::Ping(i) => Some(i),
            _ => None,
        }
    }

    /// Converts this to an [`ApplicationCommandInteraction`]
    pub fn application_command(self) -> Option<ApplicationCommandInteraction> {
        match self {
            Interaction::ApplicationCommand(i) => Some(i),
            _ => None,
        }
    }

    /// Converts this to a [`MessageComponentInteraction`]
    pub fn message_component(self) -> Option<MessageComponentInteraction> {
        match self {
            Interaction::MessageComponent(i) => Some(i),
            _ => None,
        }
    }

    /// Converts this to a [`AutocompleteInteraction`]
    pub fn autocomplete(self) -> Option<AutocompleteInteraction> {
        match self {
            Interaction::Autocomplete(i) => Some(i),
            _ => None,
        }
    }
}

impl<'de> Deserialize<'de> for Interaction {
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
        let map = JsonMap::deserialize(deserializer)?;

        let kind = map
            .get("type")
            .ok_or_else(|| DeError::custom("expected type"))
            .and_then(InteractionType::deserialize)
            .map_err(DeError::custom)?;

        match kind {
            InteractionType::Ping => serde_json::from_value::<PingInteraction>(Value::Object(map))
                .map(Interaction::Ping)
                .map_err(DeError::custom),
            InteractionType::ApplicationCommand => {
                serde_json::from_value::<ApplicationCommandInteraction>(Value::Object(map))
                    .map(Interaction::ApplicationCommand)
                    .map_err(DeError::custom)
            },
            InteractionType::MessageComponent => {
                serde_json::from_value::<MessageComponentInteraction>(Value::Object(map))
                    .map(Interaction::MessageComponent)
                    .map_err(DeError::custom)
            },
            InteractionType::Autocomplete => {
                serde_json::from_value::<AutocompleteInteraction>(Value::Object(map))
                    .map(Interaction::Autocomplete)
                    .map_err(DeError::custom)
            },
            InteractionType::Unknown => Err(DeError::custom("Unknown interaction type")),
        }
    }
}

impl Serialize for Interaction {
    fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match self {
            Interaction::Ping(i) => PingInteraction::serialize(i, serializer),
            Interaction::ApplicationCommand(i) => {
                ApplicationCommandInteraction::serialize(i, serializer)
            },
            Interaction::MessageComponent(i) => {
                MessageComponentInteraction::serialize(i, serializer)
            },
            Interaction::Autocomplete(i) => AutocompleteInteraction::serialize(i, serializer),
        }
    }
}

/// The type of an Interaction.
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)]
#[non_exhaustive]
#[repr(u8)]
pub enum InteractionType {
    Ping = 1,
    ApplicationCommand = 2,
    MessageComponent = 3,
    Autocomplete = 4,
    Unknown = !0,
}

enum_number!(InteractionType {
    Ping,
    MessageComponent,
    ApplicationCommand,
    Autocomplete,
});

/// The flags for an interaction response.
#[derive(Clone)]
#[non_exhaustive]
pub struct InteractionApplicationCommandCallbackDataFlags {
    bits: u64,
}

__impl_bitflags! {
    InteractionApplicationCommandCallbackDataFlags: u64 {
        /// Interaction message will only be visible to sender and will
        /// be quickly deleted.
        EPHEMERAL = 1 << 6;
    }
}

impl<'de> Deserialize<'de> for InteractionApplicationCommandCallbackDataFlags {
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> StdResult<Self, D::Error> {
        Ok(Self::from_bits_truncate(u64::deserialize(deserializer)?))
    }
}

impl Serialize for InteractionApplicationCommandCallbackDataFlags {
    fn serialize<S: Serializer>(&self, serializer: S) -> StdResult<S::Ok, S::Error> {
        serializer.serialize_u64(self.bits())
    }
}

/// Sent when a [`Message`] is a response to an [`Interaction`].
///
/// [`Message`]: crate::model::channel::Message
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct MessageInteraction {
    /// The id of the interaction.
    pub id: InteractionId,
    /// The type of the interaction.
    #[serde(rename = "type")]
    pub kind: InteractionType,
    /// The name of the [`ApplicationCommand`].
    ///
    /// [`ApplicationCommand`]: crate::model::interactions::application_command::ApplicationCommand
    pub name: String,
    /// The user who invoked the interaction.
    pub user: User,
}

/// The available responses types for an interaction response.
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, PartialOrd, Ord)]
#[non_exhaustive]
#[repr(u8)]
pub enum InteractionResponseType {
    Pong = 1,
    ChannelMessageWithSource = 4,
    DeferredChannelMessageWithSource = 5,
    DeferredUpdateMessage = 6,
    UpdateMessage = 7,
    Autocomplete = 8,
}
<|endoftext|>