<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::audionode::MAX_CHANNEL_COUNT;
use dom::bindings::cell::DomRefCell;
use dom::bindings::codegen::Bindings::AudioBufferBinding::{self, AudioBufferMethods, AudioBufferOptions};
use dom::bindings::error::{Error, Fallible};
use dom::bindings::num::Finite;
use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
use dom::bindings::root::DomRoot;
use dom::window::Window;
use dom_struct::dom_struct;
use js::jsapi::{Heap, JSContext, JSObject, JS_StealArrayBufferContents};
use js::rust::CustomAutoRooterGuard;
use js::typedarray::{CreateWith, Float32Array};
use servo_media::audio::buffer_source_node::AudioBuffer as ServoMediaAudioBuffer;
use std::ptr::{self, NonNull};

type JSAudioChannel = Heap<*mut JSObject>;

#[dom_struct]
pub struct AudioBuffer {
    reflector_: Reflector,
    js_channels: DomRefCell<Vec<JSAudioChannel>>,
    #[ignore_malloc_size_of = "servo_media"]
    shared_channels: DomRefCell<ServoMediaAudioBuffer>,
    sample_rate: f32,
    length: u32,
    duration: f64,
    number_of_channels: u32,
}

impl AudioBuffer {
    #[allow(unrooted_must_root)]
    #[allow(unsafe_code)]
    pub fn new_inherited(cx: *mut JSContext,
                         number_of_channels: u32,
                         length: u32,
                         sample_rate: f32) -> AudioBuffer {
        let initial_data = vec![0.; length as usize];
        let mut js_channels: Vec<JSAudioChannel> = Vec::with_capacity(number_of_channels as usize);
        for _ in 0..number_of_channels {
            rooted!(in (cx) let mut array = ptr::null_mut::<JSObject>());
            let _ = unsafe {
                Float32Array::create(cx, CreateWith::Slice(initial_data.as_slice()), array.handle_mut())
            };
            let js_channel = Heap::default();
            js_channel.set(array.get());
            js_channels.push(js_channel);
        }
        AudioBuffer {
            reflector_: Reflector::new(),
            js_channels: DomRefCell::new(js_channels),
            shared_channels: DomRefCell::new(ServoMediaAudioBuffer::new(number_of_channels as u8, length as usize)),
            sample_rate,
            length,
            duration: length as f64 / sample_rate as f64,
            number_of_channels,
        }
    }

    #[allow(unrooted_must_root)]
    pub fn new(global: &Window,
               number_of_channels: u32,
               length: u32,
               sample_rate: f32) -> DomRoot<AudioBuffer> {
        let buffer = AudioBuffer::new_inherited(global.get_cx(), number_of_channels, length, sample_rate);
        reflect_dom_object(Box::new(buffer), global, AudioBufferBinding::Wrap)
    }

    pub fn Constructor(window: &Window,
                       options: &AudioBufferOptions) -> Fallible<DomRoot<AudioBuffer>> {
        if options.numberOfChannels > MAX_CHANNEL_COUNT {
            return Err(Error::NotSupported);
        }
        Ok(AudioBuffer::new(window, options.numberOfChannels, options.length, *options.sampleRate))
    }

    #[allow(unsafe_code)]
    fn restore_js_channel_data(&self, cx: *mut JSContext) -> bool {
        for (i, channel) in self.js_channels.borrow_mut().iter().enumerate() {
            if !channel.get().is_null() {
                // Already have data in JS array.
                continue;
            }

            // Move the channel data from shared_channels to js_channels.
            rooted!(in (cx) let mut array = ptr::null_mut::<JSObject>());
            let shared_channel = (*self.shared_channels.borrow_mut()).buffers.remove(i);
            if unsafe {
                Float32Array::create(cx, CreateWith::Slice(&shared_channel), array.handle_mut())
            }.is_err() {
                return false;
            }
            channel.set(array.get());
        }

        true
    }

    /// https://webaudio.github.io/web-audio-api/#acquire-the-content
    #[allow(unsafe_code)]
    pub fn acquire_contents(&self) -> Option<ServoMediaAudioBuffer> {
        let cx = self.global().get_cx();
        for (i, channel) in self.js_channels.borrow_mut().iter().enumerate() {
            // Step 1.
            if channel.get().is_null() {
                return None;
            }

            // Step 2.
            let channel_data = unsafe {
                typedarray!(in(cx) let array: Float32Array = channel.get());
                if let Ok(array) = array {
                    // XXX TypedArrays API does not expose a way to steal the buffer's
                    //     content.
                    let data = array.to_vec();
                    let _ = JS_StealArrayBufferContents(cx, channel.handle());
                    data
                } else {
                    return None;
                }
            };

            channel.set(ptr::null_mut());

            // Step 3.
            (*self.shared_channels.borrow_mut()).buffers[i] = channel_data;

            // Step 4 will complete turning shared_channels
            // data into js_channels ArrayBuffers in restore_js_channel_data.
        }

        self.js_channels.borrow_mut().clear();

        Some((*self.shared_channels.borrow()).clone())
    }
}

impl AudioBufferMethods for AudioBuffer {
    /// https://webaudio.github.io/web-audio-api/#dom-audiobuffer-samplerate
    fn SampleRate(&self) -> Finite<f32> {
        Finite::wrap(self.sample_rate)
    }

    /// https://webaudio.github.io/web-audio-api/#dom-audiobuffer-length
    fn Length(&self) -> u32 {
        self.length
    }

    /// https://webaudio.github.io/web-audio-api/#dom-audiobuffer-duration
    fn Duration(&self) -> Finite<f64> {
        Finite::wrap(self.duration)
    }

    /// https://webaudio.github.io/web-audio-api/#dom-audiobuffer-numberofchannels
    fn NumberOfChannels(&self) -> u32 {
        self.number_of_channels
    }

    /// https://webaudio.github.io/web-audio-api/#dom-audiobuffer-getchanneldata
    #[allow(unsafe_code)]
    unsafe fn GetChannelData(&self, cx: *mut JSContext, channel: u32) -> Fallible<NonNull<JSObject>> {
        if channel >= self.number_of_channels {
            return Err(Error::IndexSize);
        }

        if !self.restore_js_channel_data(cx) {
            return Err(Error::JSFailed);
        }

        Ok(NonNull::new_unchecked(self.js_channels.borrow()[channel as usize].get()))
    }

    fn CopyFromChannel(&self,
                       _destination: CustomAutoRooterGuard<Float32Array>,
                       _channel_number: u32,
                       _start_in_channel: u32) -> Fallible<()> {
        // XXX
        Ok(())
    }

    fn CopyToChannel(&self,
                     _source: CustomAutoRooterGuard<Float32Array>,
                     _channel_number: u32,
                     _start_in_channel: u32) -> Fallible<()> {
        // XXX
        Ok(())
    }
}
<commit_msg>AudioBuffer CopyFromChannel and CopyToChannel<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::audionode::MAX_CHANNEL_COUNT;
use dom::bindings::cell::DomRefCell;
use dom::bindings::codegen::Bindings::AudioBufferBinding::{self, AudioBufferMethods, AudioBufferOptions};
use dom::bindings::error::{Error, Fallible};
use dom::bindings::num::Finite;
use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
use dom::bindings::root::DomRoot;
use dom::window::Window;
use dom_struct::dom_struct;
use js::jsapi::{Heap, JSContext, JSObject, JS_StealArrayBufferContents};
use js::rust::CustomAutoRooterGuard;
use js::typedarray::{CreateWith, Float32Array};
use servo_media::audio::buffer_source_node::AudioBuffer as ServoMediaAudioBuffer;
use std::cmp::min;
use std::ptr::{self, NonNull};

type JSAudioChannel = Heap<*mut JSObject>;

#[dom_struct]
pub struct AudioBuffer {
    reflector_: Reflector,
    js_channels: DomRefCell<Vec<JSAudioChannel>>,
    #[ignore_malloc_size_of = "servo_media"]
    shared_channels: DomRefCell<ServoMediaAudioBuffer>,
    sample_rate: f32,
    length: u32,
    duration: f64,
    number_of_channels: u32,
}

impl AudioBuffer {
    #[allow(unrooted_must_root)]
    #[allow(unsafe_code)]
    pub fn new_inherited(cx: *mut JSContext,
                         number_of_channels: u32,
                         length: u32,
                         sample_rate: f32) -> AudioBuffer {
        let initial_data = vec![0.; length as usize];
        let mut js_channels: Vec<JSAudioChannel> = Vec::with_capacity(number_of_channels as usize);
        for _ in 0..number_of_channels {
            rooted!(in (cx) let mut array = ptr::null_mut::<JSObject>());
            let _ = unsafe {
                Float32Array::create(cx, CreateWith::Slice(initial_data.as_slice()), array.handle_mut())
            };
            let js_channel = Heap::default();
            js_channel.set(array.get());
            js_channels.push(js_channel);
        }
        AudioBuffer {
            reflector_: Reflector::new(),
            js_channels: DomRefCell::new(js_channels),
            shared_channels: DomRefCell::new(ServoMediaAudioBuffer::new(number_of_channels as u8, length as usize)),
            sample_rate,
            length,
            duration: length as f64 / sample_rate as f64,
            number_of_channels,
        }
    }

    #[allow(unrooted_must_root)]
    pub fn new(global: &Window,
               number_of_channels: u32,
               length: u32,
               sample_rate: f32) -> DomRoot<AudioBuffer> {
        let buffer = AudioBuffer::new_inherited(global.get_cx(), number_of_channels, length, sample_rate);
        reflect_dom_object(Box::new(buffer), global, AudioBufferBinding::Wrap)
    }

    pub fn Constructor(window: &Window,
                       options: &AudioBufferOptions) -> Fallible<DomRoot<AudioBuffer>> {
        if options.numberOfChannels > MAX_CHANNEL_COUNT {
            return Err(Error::NotSupported);
        }
        Ok(AudioBuffer::new(window, options.numberOfChannels, options.length, *options.sampleRate))
    }

    #[allow(unsafe_code)]
    fn restore_js_channel_data(&self, cx: *mut JSContext) -> bool {
        for (i, channel) in self.js_channels.borrow_mut().iter().enumerate() {
            if !channel.get().is_null() {
                // Already have data in JS array.
                continue;
            }

            // Move the channel data from shared_channels to js_channels.
            rooted!(in (cx) let mut array = ptr::null_mut::<JSObject>());
            let shared_channel = (*self.shared_channels.borrow_mut()).buffers.remove(i);
            if unsafe {
                Float32Array::create(cx, CreateWith::Slice(&shared_channel), array.handle_mut())
            }.is_err() {
                return false;
            }
            channel.set(array.get());
        }

        true
    }

    // https://webaudio.github.io/web-audio-api/#acquire-the-content
    #[allow(unsafe_code)]
    pub fn acquire_contents(&self) -> Option<ServoMediaAudioBuffer> {
        let cx = self.global().get_cx();
        for (i, channel) in self.js_channels.borrow_mut().iter().enumerate() {
            // Step 1.
            if channel.get().is_null() {
                return None;
            }

            // Step 2.
            let channel_data = unsafe {
                typedarray!(in(cx) let array: Float32Array = channel.get());
                if let Ok(array) = array {
                    // XXX TypedArrays API does not expose a way to steal the buffer's
                    //     content.
                    let data = array.to_vec();
                    let _ = JS_StealArrayBufferContents(cx, channel.handle());
                    data
                } else {
                    return None;
                }
            };

            channel.set(ptr::null_mut());

            // Step 3.
            (*self.shared_channels.borrow_mut()).buffers[i] = channel_data;

            // Step 4 will complete turning shared_channels
            // data into js_channels ArrayBuffers in restore_js_channel_data.
        }

        self.js_channels.borrow_mut().clear();

        Some((*self.shared_channels.borrow()).clone())
    }
}

impl AudioBufferMethods for AudioBuffer {
    // https://webaudio.github.io/web-audio-api/#dom-audiobuffer-samplerate
    fn SampleRate(&self) -> Finite<f32> {
        Finite::wrap(self.sample_rate)
    }

    // https://webaudio.github.io/web-audio-api/#dom-audiobuffer-length
    fn Length(&self) -> u32 {
        self.length
    }

    // https://webaudio.github.io/web-audio-api/#dom-audiobuffer-duration
    fn Duration(&self) -> Finite<f64> {
        Finite::wrap(self.duration)
    }

    // https://webaudio.github.io/web-audio-api/#dom-audiobuffer-numberofchannels
    fn NumberOfChannels(&self) -> u32 {
        self.number_of_channels
    }

    // https://webaudio.github.io/web-audio-api/#dom-audiobuffer-getchanneldata
    #[allow(unsafe_code)]
    unsafe fn GetChannelData(&self, cx: *mut JSContext, channel: u32) -> Fallible<NonNull<JSObject>> {
        if channel >= self.number_of_channels {
            return Err(Error::IndexSize);
        }

        if !self.restore_js_channel_data(cx) {
            return Err(Error::JSFailed);
        }

        Ok(NonNull::new_unchecked(self.js_channels.borrow()[channel as usize].get()))
    }

    // https://webaudio.github.io/web-audio-api/#dom-audiobuffer-copyfromchannel
    #[allow(unsafe_code)]
    fn CopyFromChannel(&self,
                       mut destination: CustomAutoRooterGuard<Float32Array>,
                       channel_number: u32,
                       start_in_channel: u32) -> Fallible<()> {
        if channel_number >= self.number_of_channels || start_in_channel > self.length {
            return Err(Error::IndexSize);
        }

        let bytes_to_copy = min(self.length - start_in_channel, destination.len() as u32) as usize;
        let cx = self.global().get_cx();
        let channel_number = channel_number as usize;
        let offset = start_in_channel as usize;
        let mut dest = Vec::with_capacity(destination.len());
        // let destination = unsafe { destination.as_mut_slice() };

        // We either copy form js_channels or shared_channels.

        let js_channel = self.js_channels.borrow()[channel_number].get();
        if !js_channel.is_null() {
            typedarray!(in(cx) let array: Float32Array = js_channel);
            if let Ok(array) = array {
                let data = unsafe { array.as_slice() };
                dest.extend_from_slice(&data[offset..offset + bytes_to_copy]);
                return Ok(());
            }
        }

        if let Some(shared_channel) = self.shared_channels.borrow().buffers.get(channel_number) {
            dest.extend_from_slice(&shared_channel.as_slice()[offset..offset + bytes_to_copy]);
        }

        unsafe { destination.update(&dest); }

        Ok(())
    }

    // https://webaudio.github.io/web-audio-api/#dom-audiobuffer-copytochannel
    #[allow(unsafe_code)]
    fn CopyToChannel(&self,
                     source: CustomAutoRooterGuard<Float32Array>,
                     channel_number: u32,
                     start_in_channel: u32) -> Fallible<()> {
        if channel_number >= self.number_of_channels || start_in_channel > (source.len() as u32) {
            return Err(Error::IndexSize);
        }

        let cx = self.global().get_cx();
        if !self.restore_js_channel_data(cx) {
            return Err(Error::JSFailed);
        }

        let js_channel = self.js_channels.borrow()[channel_number as usize].get();
        if js_channel.is_null() {
            // The array buffer was detached.
            return Err(Error::IndexSize);
        }

        typedarray!(in(cx) let array: Float32Array = js_channel);
        if let Ok(mut array) = array {
            let bytes_to_copy = min(self.length - start_in_channel, source.len() as u32) as usize;
            let offset = start_in_channel as usize;
            unsafe { array.update(&source.as_slice()[offset..offset + bytes_to_copy]); }
        } else {
            return Err(Error::IndexSize);
        }

        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::mem;
use std::num::Int;
use error::{MioResult, MioError};
use net::{AddressFamily, SockAddr, IPv4Addr, SocketType};
use net::SocketType::{Dgram, Stream};
use net::SockAddr::{InetAddr, UnixAddr};
use net::AddressFamily::{Inet, Inet6, Unix};
pub use std::old_io::net::ip::IpAddr;

mod nix {
    pub use nix::{c_int, NixError};
    pub use nix::fcntl::{Fd, O_NONBLOCK, O_CLOEXEC};
    pub use nix::errno::EINPROGRESS;
    pub use nix::sys::socket::*;
    pub use nix::unistd::*;
}

/*
 *
 * ===== Awakener =====
 *
 */

pub struct PipeAwakener {
    reader: IoDesc,
    writer: IoDesc
}

impl PipeAwakener {
    pub fn new() -> MioResult<PipeAwakener> {
        let (rd, wr) = try!(pipe());

        Ok(PipeAwakener {
            reader: rd,
            writer: wr
        })
    }

    pub fn wakeup(&self) -> MioResult<()> {
        write(&self.writer, b"0x01")
            .map(|_| ())
    }

    pub fn desc(&self) -> &IoDesc {
        &self.reader
    }

    pub fn cleanup(&self) {
        let mut buf: [u8; 128] = unsafe { mem::uninitialized() };

        loop {
            // Consume data until all bytes are purged
            match read(&self.reader, buf.as_mut_slice()) {
                Ok(_) => {}
                Err(_) => return
            }
        }
    }
}

/// Represents the OS's handle to the IO instance. In this case, it is the file
/// descriptor.
#[derive(Debug)]
pub struct IoDesc {
    pub fd: nix::Fd
}

impl Drop for IoDesc {
    fn drop(&mut self) {
        let _ = nix::close(self.fd);
    }
}

/*
 *
 * ===== Pipes =====
 *
 */

pub fn pipe() -> MioResult<(IoDesc, IoDesc)> {
    let (rd, wr) = try!(nix::pipe2(nix::O_NONBLOCK | nix::O_CLOEXEC)
                        .map_err(MioError::from_nix_error));

    Ok((IoDesc { fd: rd }, IoDesc { fd: wr }))
}

/*
 *
 * ===== Sockets =====
 *
 */

pub fn socket(af: AddressFamily, sock_type: SocketType) -> MioResult<IoDesc> {
    let family = match af {
        Inet  => nix::AF_INET,
        Inet6 => nix::AF_INET6,
        Unix  => nix::AF_UNIX
    };

    let socket_type = match sock_type {
        Dgram  => nix::SOCK_DGRAM,
        Stream => nix::SOCK_STREAM
    };

    Ok(IoDesc {
        fd: try!(nix::socket(family, socket_type, nix::SOCK_NONBLOCK | nix::SOCK_CLOEXEC)
                    .map_err(MioError::from_nix_error))
    })
}

pub fn connect(io: &IoDesc, addr: &SockAddr) -> MioResult<bool> {
    match nix::connect(io.fd, &from_sockaddr(addr)) {
        Ok(_) => Ok(true),
        Err(e) => {
            match e {
                nix::NixError::Sys(nix::EINPROGRESS) => Ok(false),
                _ => Err(MioError::from_nix_error(e))
            }
        }
    }
}

pub fn bind(io: &IoDesc, addr: &SockAddr) -> MioResult<()> {
    nix::bind(io.fd, &from_sockaddr(addr))
        .map_err(MioError::from_nix_error)
}

pub fn listen(io: &IoDesc, backlog: usize) -> MioResult<()> {
    nix::listen(io.fd, backlog)
        .map_err(MioError::from_nix_error)
}

pub fn accept(io: &IoDesc) -> MioResult<IoDesc> {
    Ok(IoDesc {
        fd: try!(nix::accept4(io.fd, nix::SOCK_NONBLOCK | nix::SOCK_CLOEXEC)
                     .map_err(MioError::from_nix_error))
    })
}

#[inline]
pub fn recvfrom(io: &IoDesc, buf: &mut [u8]) -> MioResult<(usize, SockAddr)> {
    match nix::recvfrom(io.fd, buf).map_err(MioError::from_nix_error) {
        Ok((cnt, addr)) => Ok((cnt, to_sockaddr(&addr))),
        Err(e) => Err(e)
    }
}

#[inline]
pub fn sendto(io: &IoDesc, buf: &[u8], tgt: &SockAddr) -> MioResult<usize> {
    let res = try!(nix::sendto(io.fd, buf, &from_sockaddr(tgt), nix::MSG_DONTWAIT).map_err(MioError::from_nix_error));
    Ok(res)
}

#[inline]
pub fn read(io: &IoDesc, dst: &mut [u8]) -> MioResult<usize> {
    let res = try!(nix::read(io.fd, dst).map_err(MioError::from_nix_error));

    if res == 0 {
        return Err(MioError::eof());
    }

    Ok(res)
}

#[inline]
pub fn write(io: &IoDesc, src: &[u8]) -> MioResult<usize> {
    nix::write(io.fd, src).map_err(MioError::from_nix_error)
}

// ===== Socket options =====

pub fn reuseaddr(_io: &IoDesc) -> MioResult<usize> {
    unimplemented!()
}

pub fn set_reuseaddr(io: &IoDesc, val: bool) -> MioResult<()> {
    let v: nix::c_int = if val { 1 } else { 0 };

    nix::setsockopt(io.fd, nix::SOL_SOCKET, nix::SO_REUSEADDR, &v)
        .map_err(MioError::from_nix_error)
}

pub fn set_reuseport(io: &IoDesc, val: bool) -> MioResult<()> {
    let v: nix::c_int = if val { 1 } else { 0 };

    nix::setsockopt(io.fd, nix::SOL_SOCKET, nix::SO_REUSEPORT, &v)
        .map_err(MioError::from_nix_error)
}

pub fn set_tcp_nodelay(io: &IoDesc, val: bool) -> MioResult<()> {
    let v: nix::c_int = if val { 1 } else { 0 };

    nix::setsockopt(io.fd, nix::IPPROTO_TCP, nix::TCP_NODELAY, &v)
        .map_err(MioError::from_nix_error)
}

pub fn join_multicast_group(io: &IoDesc, addr: &IpAddr, interface: &Option<IpAddr>) -> MioResult<()> {
    let grp_req = try!(make_ip_mreq(addr, interface));

    nix::setsockopt(io.fd, nix::IPPROTO_IP, nix::IP_ADD_MEMBERSHIP, &grp_req)
        .map_err(MioError::from_nix_error)
}

pub fn leave_multicast_group(io: &IoDesc, addr: &IpAddr, interface: &Option<IpAddr>) -> MioResult<()> {
    let grp_req = try!(make_ip_mreq(addr, interface));

    nix::setsockopt(io.fd, nix::IPPROTO_IP, nix::IP_ADD_MEMBERSHIP, &grp_req)
        .map_err(MioError::from_nix_error)
}

pub fn set_multicast_ttl(io: &IoDesc, val: u8) -> MioResult<()> {
    let v: nix::IpMulticastTtl = val;

    nix::setsockopt(io.fd, nix::IPPROTO_IP, nix::IP_MULTICAST_TTL, &v)
        .map_err(MioError::from_nix_error)
}

pub fn linger(io: &IoDesc) -> MioResult<usize> {
    let mut linger: nix::linger = unsafe { mem::uninitialized() };

    try!(nix::getsockopt(io.fd, nix::SOL_SOCKET, nix::SO_LINGER, &mut linger)
            .map_err(MioError::from_nix_error));

    if linger.l_onoff > 0 {
        Ok(linger.l_linger as usize)
    } else {
        Ok(0)
    }
}

pub fn getpeername(io: &IoDesc) -> MioResult<SockAddr> {
    let sa : nix::sockaddr_in = unsafe { mem::zeroed() };
    let mut a = nix::SockAddr::SockIpV4(sa);

    try!(nix::getpeername(io.fd, &mut a).map_err(MioError::from_nix_error));

    Ok(to_sockaddr(&a))
}

pub fn getsockname(io: &IoDesc) -> MioResult<SockAddr> {
    let sa : nix::sockaddr_in = unsafe { mem::zeroed() };
    let mut a = nix::SockAddr::SockIpV4(sa);

    try!(nix::getsockname(io.fd, &mut a).map_err(MioError::from_nix_error));

    Ok(to_sockaddr(&a))
}

pub fn set_linger(io: &IoDesc, dur_s: usize) -> MioResult<()> {
    let linger = nix::linger {
        l_onoff: (if dur_s > 0 { 1is } else { 0is }) as nix::c_int,
        l_linger: dur_s as nix::c_int
    };

    nix::setsockopt(io.fd, nix::SOL_SOCKET, nix::SO_LINGER, &linger)
        .map_err(MioError::from_nix_error)
}

fn make_ip_mreq(group_addr: &IpAddr, iface_addr: &Option<IpAddr>) -> MioResult<nix::ip_mreq> {
    Ok(nix::ip_mreq {
        imr_multiaddr: from_ip_addr_to_inaddr(&Some(*group_addr)),
        imr_interface: from_ip_addr_to_inaddr(iface_addr)
    })
}

fn from_ip_addr_to_inaddr(addr: &Option<IpAddr>) -> nix::in_addr {
    match *addr {
        Some(ip) => {
            match ip {
                IPv4Addr(a, b, c, d) => ipv4_to_inaddr(a, b, c, d),
                _ => unimplemented!()
            }
        }
        None => nix::in_addr { s_addr: nix::INADDR_ANY }
    }
}

fn to_sockaddr(addr: &nix::SockAddr) -> SockAddr {
    match *addr {
        nix::SockAddr::SockIpV4(sin) => {
            InetAddr(u32be_to_ipv4(sin.sin_addr.s_addr), Int::from_be(sin.sin_port))
        }
        nix::SockAddr::SockUnix(addr) => {
            let mut str_path = String::new();
            for c in addr.sun_path.iter() {
                if *c == 0 { break; }
                str_path.push(*c as u8 as char);
            }

            UnixAddr(Path::new(str_path))
        }
        _ => unimplemented!()
    }
}

fn from_sockaddr(addr: &SockAddr) -> nix::SockAddr {
    use std::mem;

    match *addr {
        InetAddr(ip, port) => {
            match ip {
                IPv4Addr(a, b, c, d) => {
                    let mut addr: nix::sockaddr_in = unsafe { mem::zeroed() };

                    addr.sin_family = nix::AF_INET as nix::sa_family_t;
                    addr.sin_port = port.to_be();
                    addr.sin_addr = ipv4_to_inaddr(a, b, c, d);

                    nix::SockAddr::SockIpV4(addr)
                }
                _ => unimplemented!()
            }
        }
        UnixAddr(ref path) => {
            let mut addr: nix::sockaddr_un = unsafe { mem::zeroed() };

            addr.sun_family = nix::AF_UNIX as nix::sa_family_t;

            let c_path_ptr = path.as_vec();
            assert!(c_path_ptr.len() < addr.sun_path.len());
            for (sp_iter, path_iter) in addr.sun_path.iter_mut().zip(c_path_ptr.iter()) {
                *sp_iter = *path_iter as i8;
            }

            nix::SockAddr::SockUnix(addr)
        }
    }
}

fn ipv4_to_u32(a: u8, b: u8, c: u8, d: u8) -> nix::InAddrT {
    Int::from_be(((a as u32) << 24) |
                 ((b as u32) << 16) |
                 ((c as u32) <<  8) |
                 ((d as u32) <<  0))
}

fn u32be_to_ipv4(net: u32) -> IpAddr {
    u32_to_ipv4(Int::from_be(net))
}

fn u32_to_ipv4(net: u32) -> IpAddr {
    IPv4Addr(((net >> 24) & 0xff) as u8,
         ((net >> 16) & 0xff) as u8,
         ((net >> 8) & 0xff) as u8,
         (net & 0xff) as u8)
}

fn ipv4_to_inaddr(a: u8, b: u8, c: u8, d: u8) -> nix::in_addr {
    nix::in_addr {
        s_addr: ipv4_to_u32(a, b, c, d)
    }
}

<commit_msg>Implement IoHandle for IoDesc<commit_after>use std::mem;
use std::num::Int;
use error::{MioResult, MioError};
use io::IoHandle;
use net::{AddressFamily, SockAddr, IPv4Addr, SocketType};
use net::SocketType::{Dgram, Stream};
use net::SockAddr::{InetAddr, UnixAddr};
use net::AddressFamily::{Inet, Inet6, Unix};
pub use std::old_io::net::ip::IpAddr;

mod nix {
    pub use nix::{c_int, NixError};
    pub use nix::fcntl::{Fd, O_NONBLOCK, O_CLOEXEC};
    pub use nix::errno::EINPROGRESS;
    pub use nix::sys::socket::*;
    pub use nix::unistd::*;
}

/*
 *
 * ===== Awakener =====
 *
 */

pub struct PipeAwakener {
    reader: IoDesc,
    writer: IoDesc
}

impl PipeAwakener {
    pub fn new() -> MioResult<PipeAwakener> {
        let (rd, wr) = try!(pipe());

        Ok(PipeAwakener {
            reader: rd,
            writer: wr
        })
    }

    pub fn wakeup(&self) -> MioResult<()> {
        write(&self.writer, b"0x01")
            .map(|_| ())
    }

    pub fn desc(&self) -> &IoDesc {
        &self.reader
    }

    pub fn cleanup(&self) {
        let mut buf: [u8; 128] = unsafe { mem::uninitialized() };

        loop {
            // Consume data until all bytes are purged
            match read(&self.reader, buf.as_mut_slice()) {
                Ok(_) => {}
                Err(_) => return
            }
        }
    }
}

/// Represents the OS's handle to the IO instance. In this case, it is the file
/// descriptor.
#[derive(Debug)]
pub struct IoDesc {
    pub fd: nix::Fd
}

impl IoHandle for IoDesc {
    fn desc(&self) -> &IoDesc {
        self
    }
}

impl Drop for IoDesc {
    fn drop(&mut self) {
        let _ = nix::close(self.fd);
    }
}

/*
 *
 * ===== Pipes =====
 *
 */

pub fn pipe() -> MioResult<(IoDesc, IoDesc)> {
    let (rd, wr) = try!(nix::pipe2(nix::O_NONBLOCK | nix::O_CLOEXEC)
                        .map_err(MioError::from_nix_error));

    Ok((IoDesc { fd: rd }, IoDesc { fd: wr }))
}

/*
 *
 * ===== Sockets =====
 *
 */

pub fn socket(af: AddressFamily, sock_type: SocketType) -> MioResult<IoDesc> {
    let family = match af {
        Inet  => nix::AF_INET,
        Inet6 => nix::AF_INET6,
        Unix  => nix::AF_UNIX
    };

    let socket_type = match sock_type {
        Dgram  => nix::SOCK_DGRAM,
        Stream => nix::SOCK_STREAM
    };

    Ok(IoDesc {
        fd: try!(nix::socket(family, socket_type, nix::SOCK_NONBLOCK | nix::SOCK_CLOEXEC)
                    .map_err(MioError::from_nix_error))
    })
}

pub fn connect(io: &IoDesc, addr: &SockAddr) -> MioResult<bool> {
    match nix::connect(io.fd, &from_sockaddr(addr)) {
        Ok(_) => Ok(true),
        Err(e) => {
            match e {
                nix::NixError::Sys(nix::EINPROGRESS) => Ok(false),
                _ => Err(MioError::from_nix_error(e))
            }
        }
    }
}

pub fn bind(io: &IoDesc, addr: &SockAddr) -> MioResult<()> {
    nix::bind(io.fd, &from_sockaddr(addr))
        .map_err(MioError::from_nix_error)
}

pub fn listen(io: &IoDesc, backlog: usize) -> MioResult<()> {
    nix::listen(io.fd, backlog)
        .map_err(MioError::from_nix_error)
}

pub fn accept(io: &IoDesc) -> MioResult<IoDesc> {
    Ok(IoDesc {
        fd: try!(nix::accept4(io.fd, nix::SOCK_NONBLOCK | nix::SOCK_CLOEXEC)
                     .map_err(MioError::from_nix_error))
    })
}

#[inline]
pub fn recvfrom(io: &IoDesc, buf: &mut [u8]) -> MioResult<(usize, SockAddr)> {
    match nix::recvfrom(io.fd, buf).map_err(MioError::from_nix_error) {
        Ok((cnt, addr)) => Ok((cnt, to_sockaddr(&addr))),
        Err(e) => Err(e)
    }
}

#[inline]
pub fn sendto(io: &IoDesc, buf: &[u8], tgt: &SockAddr) -> MioResult<usize> {
    let res = try!(nix::sendto(io.fd, buf, &from_sockaddr(tgt), nix::MSG_DONTWAIT).map_err(MioError::from_nix_error));
    Ok(res)
}

#[inline]
pub fn read(io: &IoDesc, dst: &mut [u8]) -> MioResult<usize> {
    let res = try!(nix::read(io.fd, dst).map_err(MioError::from_nix_error));

    if res == 0 {
        return Err(MioError::eof());
    }

    Ok(res)
}

#[inline]
pub fn write(io: &IoDesc, src: &[u8]) -> MioResult<usize> {
    nix::write(io.fd, src).map_err(MioError::from_nix_error)
}

// ===== Socket options =====

pub fn reuseaddr(_io: &IoDesc) -> MioResult<usize> {
    unimplemented!()
}

pub fn set_reuseaddr(io: &IoDesc, val: bool) -> MioResult<()> {
    let v: nix::c_int = if val { 1 } else { 0 };

    nix::setsockopt(io.fd, nix::SOL_SOCKET, nix::SO_REUSEADDR, &v)
        .map_err(MioError::from_nix_error)
}

pub fn set_reuseport(io: &IoDesc, val: bool) -> MioResult<()> {
    let v: nix::c_int = if val { 1 } else { 0 };

    nix::setsockopt(io.fd, nix::SOL_SOCKET, nix::SO_REUSEPORT, &v)
        .map_err(MioError::from_nix_error)
}

pub fn set_tcp_nodelay(io: &IoDesc, val: bool) -> MioResult<()> {
    let v: nix::c_int = if val { 1 } else { 0 };

    nix::setsockopt(io.fd, nix::IPPROTO_TCP, nix::TCP_NODELAY, &v)
        .map_err(MioError::from_nix_error)
}

pub fn join_multicast_group(io: &IoDesc, addr: &IpAddr, interface: &Option<IpAddr>) -> MioResult<()> {
    let grp_req = try!(make_ip_mreq(addr, interface));

    nix::setsockopt(io.fd, nix::IPPROTO_IP, nix::IP_ADD_MEMBERSHIP, &grp_req)
        .map_err(MioError::from_nix_error)
}

pub fn leave_multicast_group(io: &IoDesc, addr: &IpAddr, interface: &Option<IpAddr>) -> MioResult<()> {
    let grp_req = try!(make_ip_mreq(addr, interface));

    nix::setsockopt(io.fd, nix::IPPROTO_IP, nix::IP_ADD_MEMBERSHIP, &grp_req)
        .map_err(MioError::from_nix_error)
}

pub fn set_multicast_ttl(io: &IoDesc, val: u8) -> MioResult<()> {
    let v: nix::IpMulticastTtl = val;

    nix::setsockopt(io.fd, nix::IPPROTO_IP, nix::IP_MULTICAST_TTL, &v)
        .map_err(MioError::from_nix_error)
}

pub fn linger(io: &IoDesc) -> MioResult<usize> {
    let mut linger: nix::linger = unsafe { mem::uninitialized() };

    try!(nix::getsockopt(io.fd, nix::SOL_SOCKET, nix::SO_LINGER, &mut linger)
            .map_err(MioError::from_nix_error));

    if linger.l_onoff > 0 {
        Ok(linger.l_linger as usize)
    } else {
        Ok(0)
    }
}

pub fn getpeername(io: &IoDesc) -> MioResult<SockAddr> {
    let sa : nix::sockaddr_in = unsafe { mem::zeroed() };
    let mut a = nix::SockAddr::SockIpV4(sa);

    try!(nix::getpeername(io.fd, &mut a).map_err(MioError::from_nix_error));

    Ok(to_sockaddr(&a))
}

pub fn getsockname(io: &IoDesc) -> MioResult<SockAddr> {
    let sa : nix::sockaddr_in = unsafe { mem::zeroed() };
    let mut a = nix::SockAddr::SockIpV4(sa);

    try!(nix::getsockname(io.fd, &mut a).map_err(MioError::from_nix_error));

    Ok(to_sockaddr(&a))
}

pub fn set_linger(io: &IoDesc, dur_s: usize) -> MioResult<()> {
    let linger = nix::linger {
        l_onoff: (if dur_s > 0 { 1is } else { 0is }) as nix::c_int,
        l_linger: dur_s as nix::c_int
    };

    nix::setsockopt(io.fd, nix::SOL_SOCKET, nix::SO_LINGER, &linger)
        .map_err(MioError::from_nix_error)
}

fn make_ip_mreq(group_addr: &IpAddr, iface_addr: &Option<IpAddr>) -> MioResult<nix::ip_mreq> {
    Ok(nix::ip_mreq {
        imr_multiaddr: from_ip_addr_to_inaddr(&Some(*group_addr)),
        imr_interface: from_ip_addr_to_inaddr(iface_addr)
    })
}

fn from_ip_addr_to_inaddr(addr: &Option<IpAddr>) -> nix::in_addr {
    match *addr {
        Some(ip) => {
            match ip {
                IPv4Addr(a, b, c, d) => ipv4_to_inaddr(a, b, c, d),
                _ => unimplemented!()
            }
        }
        None => nix::in_addr { s_addr: nix::INADDR_ANY }
    }
}

fn to_sockaddr(addr: &nix::SockAddr) -> SockAddr {
    match *addr {
        nix::SockAddr::SockIpV4(sin) => {
            InetAddr(u32be_to_ipv4(sin.sin_addr.s_addr), Int::from_be(sin.sin_port))
        }
        nix::SockAddr::SockUnix(addr) => {
            let mut str_path = String::new();
            for c in addr.sun_path.iter() {
                if *c == 0 { break; }
                str_path.push(*c as u8 as char);
            }

            UnixAddr(Path::new(str_path))
        }
        _ => unimplemented!()
    }
}

fn from_sockaddr(addr: &SockAddr) -> nix::SockAddr {
    use std::mem;

    match *addr {
        InetAddr(ip, port) => {
            match ip {
                IPv4Addr(a, b, c, d) => {
                    let mut addr: nix::sockaddr_in = unsafe { mem::zeroed() };

                    addr.sin_family = nix::AF_INET as nix::sa_family_t;
                    addr.sin_port = port.to_be();
                    addr.sin_addr = ipv4_to_inaddr(a, b, c, d);

                    nix::SockAddr::SockIpV4(addr)
                }
                _ => unimplemented!()
            }
        }
        UnixAddr(ref path) => {
            let mut addr: nix::sockaddr_un = unsafe { mem::zeroed() };

            addr.sun_family = nix::AF_UNIX as nix::sa_family_t;

            let c_path_ptr = path.as_vec();
            assert!(c_path_ptr.len() < addr.sun_path.len());
            for (sp_iter, path_iter) in addr.sun_path.iter_mut().zip(c_path_ptr.iter()) {
                *sp_iter = *path_iter as i8;
            }

            nix::SockAddr::SockUnix(addr)
        }
    }
}

fn ipv4_to_u32(a: u8, b: u8, c: u8, d: u8) -> nix::InAddrT {
    Int::from_be(((a as u32) << 24) |
                 ((b as u32) << 16) |
                 ((c as u32) <<  8) |
                 ((d as u32) <<  0))
}

fn u32be_to_ipv4(net: u32) -> IpAddr {
    u32_to_ipv4(Int::from_be(net))
}

fn u32_to_ipv4(net: u32) -> IpAddr {
    IPv4Addr(((net >> 24) & 0xff) as u8,
         ((net >> 16) & 0xff) as u8,
         ((net >> 8) & 0xff) as u8,
         (net & 0xff) as u8)
}

fn ipv4_to_inaddr(a: u8, b: u8, c: u8, d: u8) -> nix::in_addr {
    nix::in_addr {
        s_addr: ipv4_to_u32(a, b, c, d)
    }
}

<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use freetype::freetype::FT_Add_Default_Modules;
use freetype::freetype::FT_Done_Library;
use freetype::freetype::FT_Library;
use freetype::freetype::FT_Memory;
use freetype::freetype::FT_MemoryRec_;
use freetype::freetype::FT_New_Library;
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use servo_allocator::usable_size;
use std::mem;
use std::os::raw::{c_long, c_void};
use std::ptr;
use std::rc::Rc;

// We pass a |User| struct -- via an opaque |void*| -- to FreeType each time a new instance is
// created. FreeType passes it back to the ft_alloc/ft_realloc/ft_free callbacks. We use it to
// record the memory usage of each FreeType instance.
pub struct User {
    size: usize,
}

// FreeType doesn't require any particular alignment for allocations.
const FT_ALIGNMENT: usize = 1;

extern fn ft_alloc(mem: FT_Memory, req_size: c_long) -> *mut c_void {
    assert!(FT_ALIGNMENT == 1);
    let mut vec = Vec::<u8>::with_capacity(req_size as usize);
    let ptr = vec.as_mut_ptr() as *mut c_void;
    mem::forget(vec);

    unsafe {
        let actual_size = usable_size(ptr as *const _);
        let user = (*mem).user as *mut User;
        (*user).size += actual_size;
    }

    ptr
}

extern fn ft_free(mem: FT_Memory, ptr: *mut c_void) {
    unsafe {
        let actual_size = usable_size(ptr as *const _);
        let user = (*mem).user as *mut User;
        (*user).size -= actual_size;

        assert!(FT_ALIGNMENT == 1);
        mem::drop(Vec::<u8>::from_raw_parts(ptr as *mut u8, actual_size, 0))
    }
}

extern fn ft_realloc(mem: FT_Memory, old_size: c_long, new_req_size: c_long,
                     old_ptr: *mut c_void) -> *mut c_void {
    let old_actual_size;
    let mut vec;
    unsafe {
        old_actual_size = usable_size(old_ptr as *const _);
        let old_size = old_size as usize;
        vec = Vec::<u8>::from_raw_parts(old_ptr as *mut u8, old_size, old_size);
    };

    let new_req_size = new_req_size as usize;
    if new_req_size > old_actual_size {
        vec.reserve_exact(new_req_size - old_actual_size)
    } else if new_req_size < old_actual_size {
        vec.truncate(new_req_size);
        vec.shrink_to_fit()
    }

    let new_ptr = vec.as_mut_ptr() as *mut c_void;
    mem::forget(vec);

    unsafe {
        let new_actual_size = usable_size(new_ptr as *const _);
        let user = (*mem).user as *mut User;
        (*user).size += new_actual_size;
        (*user).size -= old_actual_size;
    }

    new_ptr
}

// A |*mut User| field in a struct triggers a "use of `#[derive]` with a raw pointer" warning from
// rustc. But using a typedef avoids this, so...
pub type UserPtr = *mut User;

// WARNING: We need to be careful how we use this struct. See the comment about Rc<> in
// FontContextHandle.
#[derive(Clone, Debug)]
pub struct FreeTypeLibraryHandle {
    pub ctx: FT_Library,
    mem: FT_Memory,
    user: UserPtr,
}

impl Drop for FreeTypeLibraryHandle {
    fn drop(&mut self) {
        assert!(!self.ctx.is_null());
        unsafe {
            FT_Done_Library(self.ctx);
            Box::from_raw(self.mem);
            Box::from_raw(self.user);
        }
    }
}

impl MallocSizeOf for FreeTypeLibraryHandle {
    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
        unsafe {
            (*self.user).size +
                ops.malloc_size_of(self.ctx as *const _) +
                ops.malloc_size_of(self.mem as *const _) +
                ops.malloc_size_of(self.user as *const _)
        }
    }
}

#[derive(Clone, Debug)]
pub struct FontContextHandle {
    // WARNING: FreeTypeLibraryHandle contains raw pointers, is clonable, and also implements
    // `Drop`. This field needs to be Rc<> to make sure that the `drop` function is only called
    // once, otherwise we'll get crashes. Yuk.
    pub ctx: Rc<FreeTypeLibraryHandle>,
}

impl MallocSizeOf for FontContextHandle {
    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
        self.ctx.size_of(ops)
    }
}

impl FontContextHandle {
    pub fn new() -> FontContextHandle {
        let user = Box::into_raw(Box::new(User {
            size: 0,
        }));
        let mem = Box::into_raw(Box::new(FT_MemoryRec_ {
            user: user as *mut c_void,
            alloc: Some(ft_alloc),
            free: Some(ft_free),
            realloc: Some(ft_realloc),
        }));
        unsafe {
            let mut ctx: FT_Library = ptr::null_mut();

            let result = FT_New_Library(mem, &mut ctx);
            if !result.succeeded() { panic!("Unable to initialize FreeType library"); }

            FT_Add_Default_Modules(ctx);

            FontContextHandle {
                ctx: Rc::new(FreeTypeLibraryHandle { ctx: ctx, mem: mem, user: user }),
            }
        }
    }
}
<commit_msg>Auto merge of #19011 - mbrubeck:realloc, r=glennw<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use freetype::freetype::FT_Add_Default_Modules;
use freetype::freetype::FT_Done_Library;
use freetype::freetype::FT_Library;
use freetype::freetype::FT_Memory;
use freetype::freetype::FT_MemoryRec_;
use freetype::freetype::FT_New_Library;
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use servo_allocator::usable_size;
use std::mem;
use std::os::raw::{c_long, c_void};
use std::ptr;
use std::rc::Rc;

// We pass a |User| struct -- via an opaque |void*| -- to FreeType each time a new instance is
// created. FreeType passes it back to the ft_alloc/ft_realloc/ft_free callbacks. We use it to
// record the memory usage of each FreeType instance.
pub struct User {
    size: usize,
}

// FreeType doesn't require any particular alignment for allocations.
const FT_ALIGNMENT: usize = 1;

extern fn ft_alloc(mem: FT_Memory, req_size: c_long) -> *mut c_void {
    assert!(FT_ALIGNMENT == 1);
    let mut vec = Vec::<u8>::with_capacity(req_size as usize);
    let ptr = vec.as_mut_ptr() as *mut c_void;
    mem::forget(vec);

    unsafe {
        let actual_size = usable_size(ptr as *const _);
        let user = (*mem).user as *mut User;
        (*user).size += actual_size;
    }

    ptr
}

extern fn ft_free(mem: FT_Memory, ptr: *mut c_void) {
    unsafe {
        let actual_size = usable_size(ptr as *const _);
        let user = (*mem).user as *mut User;
        (*user).size -= actual_size;

        assert!(FT_ALIGNMENT == 1);
        mem::drop(Vec::<u8>::from_raw_parts(ptr as *mut u8, actual_size, 0))
    }
}

extern fn ft_realloc(mem: FT_Memory, _old_size: c_long, new_req_size: c_long,
                     old_ptr: *mut c_void) -> *mut c_void {
    let old_actual_size;
    let mut vec;
    unsafe {
        old_actual_size = usable_size(old_ptr as *const _);
        let old_size = old_actual_size as usize;
        vec = Vec::<u8>::from_raw_parts(old_ptr as *mut u8, old_size, old_size);
    };

    let new_req_size = new_req_size as usize;
    if new_req_size > old_actual_size {
        vec.reserve_exact(new_req_size - old_actual_size)
    } else if new_req_size < old_actual_size {
        vec.truncate(new_req_size);
        vec.shrink_to_fit()
    }

    let new_ptr = vec.as_mut_ptr() as *mut c_void;
    mem::forget(vec);

    unsafe {
        let new_actual_size = usable_size(new_ptr as *const _);
        let user = (*mem).user as *mut User;
        (*user).size += new_actual_size;
        (*user).size -= old_actual_size;
    }

    new_ptr
}

// A |*mut User| field in a struct triggers a "use of `#[derive]` with a raw pointer" warning from
// rustc. But using a typedef avoids this, so...
pub type UserPtr = *mut User;

// WARNING: We need to be careful how we use this struct. See the comment about Rc<> in
// FontContextHandle.
#[derive(Clone, Debug)]
pub struct FreeTypeLibraryHandle {
    pub ctx: FT_Library,
    mem: FT_Memory,
    user: UserPtr,
}

impl Drop for FreeTypeLibraryHandle {
    fn drop(&mut self) {
        assert!(!self.ctx.is_null());
        unsafe {
            FT_Done_Library(self.ctx);
            Box::from_raw(self.mem);
            Box::from_raw(self.user);
        }
    }
}

impl MallocSizeOf for FreeTypeLibraryHandle {
    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
        unsafe {
            (*self.user).size +
                ops.malloc_size_of(self.ctx as *const _) +
                ops.malloc_size_of(self.mem as *const _) +
                ops.malloc_size_of(self.user as *const _)
        }
    }
}

#[derive(Clone, Debug)]
pub struct FontContextHandle {
    // WARNING: FreeTypeLibraryHandle contains raw pointers, is clonable, and also implements
    // `Drop`. This field needs to be Rc<> to make sure that the `drop` function is only called
    // once, otherwise we'll get crashes. Yuk.
    pub ctx: Rc<FreeTypeLibraryHandle>,
}

impl MallocSizeOf for FontContextHandle {
    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
        self.ctx.size_of(ops)
    }
}

impl FontContextHandle {
    pub fn new() -> FontContextHandle {
        let user = Box::into_raw(Box::new(User {
            size: 0,
        }));
        let mem = Box::into_raw(Box::new(FT_MemoryRec_ {
            user: user as *mut c_void,
            alloc: Some(ft_alloc),
            free: Some(ft_free),
            realloc: Some(ft_realloc),
        }));
        unsafe {
            let mut ctx: FT_Library = ptr::null_mut();

            let result = FT_New_Library(mem, &mut ctx);
            if !result.succeeded() { panic!("Unable to initialize FreeType library"); }

            FT_Add_Default_Modules(ctx);

            FontContextHandle {
                ctx: Rc::new(FreeTypeLibraryHandle { ctx: ctx, mem: mem, user: user }),
            }
        }
    }
}
<|endoftext|>


<commit_before>use super::tree;
use super::entropy;

pub fn create_tree<C:PartialEq, T:entropy::Classified<C>>(_dataset:&Vec<(T, C)>, _classes:Vec<C>)
                                                          -> Box<tree::Node<T>> {

    Box::new(tree::Node{data:None, left:None, rigth:None})
}
<commit_msg>bit more ID3<commit_after>use super::tree;
use super::entropy;

use std::fmt::Display as Display;
use std::fmt::Debug as Debug;

pub fn create_tree<C:PartialEq+Clone+Debug, T:entropy::Classified<C>+Display+Clone>(dataset:&Vec<(T, C)>, classes:&Vec<C>)
                                                          -> Box<tree::Node<T>> {
    let set:Vec<T> = dataset.iter().map(|x| x.0.clone()).collect();
    let entropies:Vec<(C, f64)> = classes.iter().map(|c| (c.clone(), entropy::gain(&set, &classes, c))).collect();

    for s in entropies {
        println!("{:?}", s)
    }

    Box::new(tree::Node{data:None, left:None, rigth:None})
}
<|endoftext|>


<commit_before>use metric::{Measured, Line, Grapheme, Metric};
use super::{NodeLink, LeafRepr };

use self::Value::*;

use std::cell::Cell;
use std::convert;
use std::default::Default;
use std::fmt;
use std::ops;

/// A lazily-evaluated field
#[derive(Clone)]
struct Lazy<T: Copy>(Cell<Option<T>>);

impl<T> Lazy<T>
where T: Copy {

    /// Get the value of the field if it has been computed
    ///
    /// # Returns
    /// - `Some(T)` if the value of this field has been computed
    /// - `None` if the field has yet to be computed
    #[inline]
    pub fn get(&self) -> Option<T> { self.0.get() }

    /// Get the value of the field, or compute it
    ///
    /// # Arguments
    /// - `f`: a function returning type `T` to use to calculate the value of
    ///        the field if it has not already been calculated
    ///
    /// # Returns
    /// - If the field has already been evaluated, the value of the field.
    /// - If the field has not been evaluated, the value of `f`
    #[inline]
    pub fn get_or_else<F>(&self, f: F) -> T
    where F: FnOnce() -> T {
        if let Some(value) = self.0.get() {
            value
        } else {
            let value = f();
            self.0.set(Some(value));
            value
        }
    }

    #[inline]
    pub fn new() -> Self {
        Lazy(Cell::new(None))
    }

}

impl<T> Default for Lazy<T>
where T: Copy {
    fn default() -> Self {
        Self::new()
    }
}

impl<T> fmt::Debug for Lazy<T>
where T: fmt::Debug
    , T: Copy {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.0.get() { Some(value) => value.fmt(f)
                           , None => write!(f, "?")

        }
    }
}

macro_rules! lazy_field {
    ($method: ident, $field: ident, $ty:ty) => {
        #[inline] fn $method(&self) -> $ty {
            self.$field.get_or_else(|| { self.value.$method() })
        }

    }
}

/// A `Node`.
#[derive(Clone, Default)]
pub struct Node { len: Lazy<usize>
                , weight: Lazy<usize>
                , line_count: Lazy<Line>
                , line_weight: Lazy<Line>
                , grapheme_count: Lazy<Grapheme>
                , grapheme_weight: Lazy<Grapheme>
                , pub value: Value
                }

impl Node {
    pub fn new(value: Value) -> Self {
        Node { value: value, ..Default::default() }
    }

    pub fn spanning(&self, i: usize, span_len: usize) -> (&Node, usize)
    where Node: Measured<usize> {
        assert!(self.len() >= span_len);
        match **self {
            Branch { ref right, ref left } if < Node as Measured<usize>>::measure_weight(self) < i => {
                // if this node is a branch, and the weight is less than the
                // index, where the span begins, then the first index of the
                // span is on the right side
                let span_i = or_zero!(i, left.len());
                assert!(or_zero!(right.len(), span_i) >= span_len);
                right.spanning(span_i, span_len)
            }
          , Branch { ref left, .. }
            // if the left child is long enough to contain the entire span,
            // walk to the left child
            if or_zero!(left.len(), i) >= span_len => left.spanning(i, span_len)
         ,  Leaf(_) | Branch {..} =>
            // if this function has walked as far as a leaf node,
            // then that leaf must be the spanning node. return it;
            //
            // otherwise, if the node is a branch node and the span is longer
            // than the left child, then this node must be the minimum
            // spanning node
            (self, i)
        }
    }
}

impl fmt::Display for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.strings()
            .fold(Ok(()), |r, string| r.and_then(|_| write!(f, "{}", string)))
    }
}

impl fmt::Debug for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!( f, "{:?}{}{}{}{}{}{}"
              , self.value
              , self.len.get().map(|l| format!(" length: {:?},", l))
                    .unwrap_or_else(|| { String::new() })
              , self.weight.get().map(|w| format!(" weight: {:?},", w))
                    .unwrap_or_else(|| { String::new() })
              , self.grapheme_count.get().map(|w| format!("length: {:?},", w))
                    .unwrap_or_else(|| { String::new() })
              , self.grapheme_weight.get().map(|w| format!("weight: {:?},", w))
                    .unwrap_or_else(|| { String::new() })
              , self.line_count.get().map(|w| format!("length: {:?},", w))
                    .unwrap_or_else(|| { String::new() })
              , self.line_weight.get().map(|w| format!("weight: {:?},", w))
                    .unwrap_or_else(|| { String::new() })
              )
    }
}

impl convert::Into<NodeLink> for Node {
    #[inline] fn into(self) -> NodeLink {
        NodeLink::new(self)
    }
}

impl ops::Deref for Node {
    type Target = Value;
    fn deref(&self) -> &Value { &self.value }
}

impl Measured<usize> for Node {

        #[inline] fn to_byte_index(&self, index: usize) -> Option<usize>  {
             Some(index)
        }

        lazy_field!(measure, len, usize);
        lazy_field!(measure_weight, weight, usize);

}

impl Measured<Grapheme> for Node {

        #[inline] fn to_byte_index(&self, index: Grapheme) -> Option<usize>  {
            self.value.to_byte_index(index)
        }

        lazy_field!(measure, grapheme_count, Grapheme);
        lazy_field!(measure_weight, grapheme_weight, Grapheme);

}

impl Measured<Line> for Node {

        #[inline] fn to_byte_index(&self, index: Line) -> Option<usize>  {
            self.value.to_byte_index(index)
        }

        lazy_field!(measure, line_count, Line);
        lazy_field!(measure_weight, line_weight, Line);

}

impl<M> ops::Index<M> for Node
where M: Metric
    , Node: Measured<M>
    , LeafRepr: Measured<M>
    {
    type Output = str;

    fn index(&self, i: M) -> &str {
        let len = self.measure();
        assert!( i < len
               , "Node::index: index {:?} out of bounds (length {:?})", i, len);
        match **self {
            Leaf(ref string) => {
                let idx = string.to_byte_index(i)
                                .expect("index out of bounds!");
                &string[idx..idx+1]
            }
          , Branch { ref right, .. } if len < i =>
                &right[i - len]
          , Branch { ref left, .. } => &left[i]
        }
    }
}

/// A `Node` in the `Rope`'s tree.
///
/// A `Node` is either a `Leaf` holding a `String`, or a
/// a `Branch` concatenating together two `Node`s.
#[derive(Clone)]
pub enum Value {
    /// A leaf node
    Leaf(LeafRepr)
  , /// A branch concatenating together `l`eft and `r`ight nodes.
    Branch { /// The left branch node
             left: NodeLink
           , /// The right branch node
             right: NodeLink }
}

impl Value {
    #[inline]
    pub fn new_branch(left: NodeLink, right: NodeLink) -> Self {
        Branch { left: left, right: right }
    }
}

impl<M> Measured<M> for Value
where M: Metric
    , LeafRepr: Measured<M>
    , Node: Measured<M>
{
    fn to_byte_index(&self, index: M) -> Option<usize> {
        unimplemented!()
    }

    fn measure(&self) -> M {
        match *self {
            Leaf(ref r) => r.measure()
          , Branch { ref left, ref right } =>
                left.measure() + right.measure()
        }
    }

    fn measure_weight(&self) -> M {
        match *self {
            Leaf(ref r) => r.measure_weight()
          , Branch { ref left, ref right } =>
                left.measure()
        }
    }

}

impl convert::Into<Node> for Value {
    #[inline] fn into(self) -> Node {
        Node::new(self)
    }
}

impl Default for Value {
    fn default() -> Self {
        Leaf(LeafRepr::default())
    }
}

impl fmt::Debug for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Leaf(ref r) => write!(f, "Leaf({:?})", r)
          , Branch { ref left, ref right } => write!( f, "Branch({:?}, {:?})"
                                                    , left
                                                    , right)
        }
    }
}
<commit_msg>style(rope internals): remove unused pattern binding<commit_after>use metric::{Measured, Line, Grapheme, Metric};
use super::{NodeLink, LeafRepr };

use self::Value::*;

use std::cell::Cell;
use std::convert;
use std::default::Default;
use std::fmt;
use std::ops;

/// A lazily-evaluated field
#[derive(Clone)]
struct Lazy<T: Copy>(Cell<Option<T>>);

impl<T> Lazy<T>
where T: Copy {

    /// Get the value of the field if it has been computed
    ///
    /// # Returns
    /// - `Some(T)` if the value of this field has been computed
    /// - `None` if the field has yet to be computed
    #[inline]
    pub fn get(&self) -> Option<T> { self.0.get() }

    /// Get the value of the field, or compute it
    ///
    /// # Arguments
    /// - `f`: a function returning type `T` to use to calculate the value of
    ///        the field if it has not already been calculated
    ///
    /// # Returns
    /// - If the field has already been evaluated, the value of the field.
    /// - If the field has not been evaluated, the value of `f`
    #[inline]
    pub fn get_or_else<F>(&self, f: F) -> T
    where F: FnOnce() -> T {
        if let Some(value) = self.0.get() {
            value
        } else {
            let value = f();
            self.0.set(Some(value));
            value
        }
    }

    #[inline]
    pub fn new() -> Self {
        Lazy(Cell::new(None))
    }

}

impl<T> Default for Lazy<T>
where T: Copy {
    fn default() -> Self {
        Self::new()
    }
}

impl<T> fmt::Debug for Lazy<T>
where T: fmt::Debug
    , T: Copy {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.0.get() { Some(value) => value.fmt(f)
                           , None => write!(f, "?")

        }
    }
}

macro_rules! lazy_field {
    ($method: ident, $field: ident, $ty:ty) => {
        #[inline] fn $method(&self) -> $ty {
            self.$field.get_or_else(|| { self.value.$method() })
        }

    }
}

/// A `Node`.
#[derive(Clone, Default)]
pub struct Node { len: Lazy<usize>
                , weight: Lazy<usize>
                , line_count: Lazy<Line>
                , line_weight: Lazy<Line>
                , grapheme_count: Lazy<Grapheme>
                , grapheme_weight: Lazy<Grapheme>
                , pub value: Value
                }

impl Node {
    pub fn new(value: Value) -> Self {
        Node { value: value, ..Default::default() }
    }

    pub fn spanning(&self, i: usize, span_len: usize) -> (&Node, usize)
    where Node: Measured<usize> {
        assert!(self.len() >= span_len);
        match **self {
            Branch { ref right, ref left } if < Node as Measured<usize>>::measure_weight(self) < i => {
                // if this node is a branch, and the weight is less than the
                // index, where the span begins, then the first index of the
                // span is on the right side
                let span_i = or_zero!(i, left.len());
                assert!(or_zero!(right.len(), span_i) >= span_len);
                right.spanning(span_i, span_len)
            }
          , Branch { ref left, .. }
            // if the left child is long enough to contain the entire span,
            // walk to the left child
            if or_zero!(left.len(), i) >= span_len => left.spanning(i, span_len)
         ,  Leaf(_) | Branch {..} =>
            // if this function has walked as far as a leaf node,
            // then that leaf must be the spanning node. return it;
            //
            // otherwise, if the node is a branch node and the span is longer
            // than the left child, then this node must be the minimum
            // spanning node
            (self, i)
        }
    }
}

impl fmt::Display for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.strings()
            .fold(Ok(()), |r, string| r.and_then(|_| write!(f, "{}", string)))
    }
}

impl fmt::Debug for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!( f, "{:?}{}{}{}{}{}{}"
              , self.value
              , self.len.get().map(|l| format!(" length: {:?},", l))
                    .unwrap_or_else(|| { String::new() })
              , self.weight.get().map(|w| format!(" weight: {:?},", w))
                    .unwrap_or_else(|| { String::new() })
              , self.grapheme_count.get().map(|w| format!("length: {:?},", w))
                    .unwrap_or_else(|| { String::new() })
              , self.grapheme_weight.get().map(|w| format!("weight: {:?},", w))
                    .unwrap_or_else(|| { String::new() })
              , self.line_count.get().map(|w| format!("length: {:?},", w))
                    .unwrap_or_else(|| { String::new() })
              , self.line_weight.get().map(|w| format!("weight: {:?},", w))
                    .unwrap_or_else(|| { String::new() })
              )
    }
}

impl convert::Into<NodeLink> for Node {
    #[inline] fn into(self) -> NodeLink {
        NodeLink::new(self)
    }
}

impl ops::Deref for Node {
    type Target = Value;
    fn deref(&self) -> &Value { &self.value }
}

impl Measured<usize> for Node {

        #[inline] fn to_byte_index(&self, index: usize) -> Option<usize>  {
             Some(index)
        }

        lazy_field!(measure, len, usize);
        lazy_field!(measure_weight, weight, usize);

}

impl Measured<Grapheme> for Node {

        #[inline] fn to_byte_index(&self, index: Grapheme) -> Option<usize>  {
            self.value.to_byte_index(index)
        }

        lazy_field!(measure, grapheme_count, Grapheme);
        lazy_field!(measure_weight, grapheme_weight, Grapheme);

}

impl Measured<Line> for Node {

        #[inline] fn to_byte_index(&self, index: Line) -> Option<usize>  {
            self.value.to_byte_index(index)
        }

        lazy_field!(measure, line_count, Line);
        lazy_field!(measure_weight, line_weight, Line);

}

impl<M> ops::Index<M> for Node
where M: Metric
    , Node: Measured<M>
    , LeafRepr: Measured<M>
    {
    type Output = str;

    fn index(&self, i: M) -> &str {
        let len = self.measure();
        assert!( i < len
               , "Node::index: index {:?} out of bounds (length {:?})", i, len);
        match **self {
            Leaf(ref string) => {
                let idx = string.to_byte_index(i)
                                .expect("index out of bounds!");
                &string[idx..idx+1]
            }
          , Branch { ref right, .. } if len < i =>
                &right[i - len]
          , Branch { ref left, .. } => &left[i]
        }
    }
}

/// A `Node` in the `Rope`'s tree.
///
/// A `Node` is either a `Leaf` holding a `String`, or a
/// a `Branch` concatenating together two `Node`s.
#[derive(Clone)]
pub enum Value {
    /// A leaf node
    Leaf(LeafRepr)
  , /// A branch concatenating together `l`eft and `r`ight nodes.
    Branch { /// The left branch node
             left: NodeLink
           , /// The right branch node
             right: NodeLink }
}

impl Value {
    #[inline]
    pub fn new_branch(left: NodeLink, right: NodeLink) -> Self {
        Branch { left: left, right: right }
    }
}

impl<M> Measured<M> for Value
where M: Metric
    , LeafRepr: Measured<M>
    , Node: Measured<M>
{
    fn to_byte_index(&self, index: M) -> Option<usize> {
        unimplemented!()
    }

    fn measure(&self) -> M {
        match *self {
            Leaf(ref r) => r.measure()
          , Branch { ref left, ref right } =>
                left.measure() + right.measure()
        }
    }

    fn measure_weight(&self) -> M {
        match *self {
            Leaf(ref r) => r.measure_weight()
          , Branch { ref left, .. } => left.measure()
        }
    }

}

impl convert::Into<Node> for Value {
    #[inline] fn into(self) -> Node {
        Node::new(self)
    }
}

impl Default for Value {
    fn default() -> Self {
        Leaf(LeafRepr::default())
    }
}

impl fmt::Debug for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Leaf(ref r) => write!(f, "Leaf({:?})", r)
          , Branch { ref left, ref right } => write!( f, "Branch({:?}, {:?})"
                                                    , left
                                                    , right)
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::time::{Duration, Instant};

use futures::future::BoxFuture;

use crate::client::Context;
use crate::model::channel::Message;

type Check = for<'fut> fn(&'fut Context, &'fut Message) -> BoxFuture<'fut, bool>;

type DelayHook = for<'fut> fn(&'fut Context, &'fut Message) -> BoxFuture<'fut, ()>;

pub(crate) struct Ratelimit {
    pub delay: Duration,
    pub limit: Option<(Duration, u32)>,
}
pub(crate) struct UnitRatelimit {
    pub last_time: Option<Instant>,
    pub set_time: Instant,
    pub tickets: u32,
    pub awaiting: u32,
    pub is_first_try: bool,
}

impl UnitRatelimit {
    fn new(creation_time: Instant) -> Self {
        Self {
            last_time: None,
            set_time: creation_time,
            tickets: 0,
            awaiting: 0,
            is_first_try: true,
        }
    }
}

#[derive(Default)]
pub(crate) struct UnitRatelimitTimes {
    pub last_time: Option<Instant>,
    pub set_time: Option<Instant>,
}

/// A bucket offers fine-grained control over the execution of commands.
pub(crate) enum Bucket {
    /// The bucket will collect tickets for every invocation of a command.
    Global(TicketCounter),
    /// The bucket will collect tickets per user.
    User(TicketCounter),
    /// The bucket will collect tickets per guild.
    Guild(TicketCounter),
    /// The bucket will collect tickets per channel.
    Channel(TicketCounter),
    /// The bucket will collect tickets per category.
    ///
    /// This requires the cache, as messages do not contain their channel's
    /// category.
    #[cfg(feature = "cache")]
    Category(TicketCounter),
}

impl Bucket {
    #[inline]
    pub async fn take(&mut self, ctx: &Context, msg: &Message) -> Option<RateLimitInfo> {
        match self {
            Self::Global(counter) => counter.take(ctx, msg, 0).await,
            Self::User(counter) => counter.take(ctx, msg, msg.author.id.0).await,
            Self::Guild(counter) => {
                if let Some(guild_id) = msg.guild_id {
                    counter.take(ctx, msg, guild_id.0).await
                } else {
                    None
                }
            },
            Self::Channel(counter) => counter.take(ctx, msg, msg.channel_id.0).await,
            // This requires the cache, as messages do not contain their channel's
            // category.
            #[cfg(feature = "cache")]
            Self::Category(counter) => {
                if let Some(category_id) = msg.category_id(ctx).await {
                    counter.take(ctx, msg, category_id.0).await
                } else {
                    None
                }
            },
        }
    }

    #[inline]
    pub async fn give(&mut self, ctx: &Context, msg: &Message) {
        match self {
            Self::Global(counter) => counter.give(ctx, msg, 0).await,
            Self::User(counter) => counter.give(ctx, msg, msg.author.id.0).await,
            Self::Guild(counter) => {
                if let Some(guild_id) = msg.guild_id {
                    counter.give(ctx, msg, guild_id.0).await
                }
            },
            Self::Channel(counter) => counter.give(ctx, msg, msg.channel_id.0).await,
            // This requires the cache, as messages do not contain their channel's
            // category.
            #[cfg(feature = "cache")]
            Self::Category(counter) => {
                if let Some(category_id) = msg.category_id(ctx).await {
                    counter.give(ctx, msg, category_id.0).await
                }
            },
        }
    }
}

/// Keeps track of who owns how many tickets and when they accessed the last
/// time.
pub(crate) struct TicketCounter {
    pub ratelimit: Ratelimit,
    pub tickets_for: HashMap<u64, UnitRatelimit>,
    pub check: Option<Check>,
    pub delay_action: Option<DelayHook>,
    pub await_ratelimits: u32,
}

/// Contains information about a rate limit.
#[derive(Debug)]
pub struct RateLimitInfo {
    /// Time to elapse in order to invoke a command again.
    pub rate_limit: Duration,
    /// Amount of active delays by this target.
    pub active_delays: u32,
    /// Maximum delays that this target can invoke.
    pub max_delays: u32,
    /// Whether this is the first time the rate limit info has been
    /// returned for this target without the rate limit to elapse.
    pub is_first_try: bool,
    /// How the command invocation has been treated by the framework.
    pub action: RateLimitAction,
}

/// Action taken for the command invocation.
#[derive(Debug)]
pub enum RateLimitAction {
    /// Invocation has been delayed.
    Delayed,
    /// Tried to delay invocation but maximum of delays reached.
    FailedDelay,
    /// Cancelled the invocation due to time or ticket reasons.
    Cancelled,
}

impl RateLimitInfo {
    /// Gets the duration of the rate limit in seconds.
    #[inline]
    pub fn as_secs(&self) -> u64 {
        self.rate_limit.as_secs()
    }

    /// Gets the duration of the rate limit in milliseconds.
    #[inline]
    pub fn as_millis(&self) -> u128 {
        self.rate_limit.as_millis()
    }

    /// Gets the duration of the rate limit in microseconds.
    #[inline]
    pub fn as_micros(&self) -> u128 {
        self.rate_limit.as_micros()
    }
}

impl TicketCounter {
    /// Tries to check whether the invocation is permitted by the ticket counter
    /// and if a ticket can be taken; it does not return a
    /// a ticket but a duration until a ticket can be taken.
    ///
    /// The duration will be wrapped in an action for the caller to perform
    /// if wanted. This may inform them to directly cancel trying to take a ticket
    /// or delay the take until later.
    ///
    /// However there is no contract: It does not matter what
    /// the caller ends up doing, receiving some action eventually means
    /// no ticket can be taken and the duration must elapse.
    pub async fn take(&mut self, ctx: &Context, msg: &Message, id: u64) -> Option<RateLimitInfo> {
        if let Some(ref check) = self.check {
            if !(check)(ctx, msg).await {
                return None;
            }
        }

        let now = Instant::now();
        let Self {
            tickets_for,
            ratelimit,
            ..
        } = self;

        let ticket_owner = tickets_for.entry(id).or_insert_with(|| UnitRatelimit::new(now));

        // Check if too many tickets have been taken already.
        // If all tickets are exhausted, return the needed delay
        // for this invocation.
        if let Some((timespan, limit)) = ratelimit.limit {
            if (ticket_owner.tickets + 1) > limit {
                if let Some(ratelimit) =
                    (ticket_owner.set_time + timespan).checked_duration_since(now)
                {
                    let was_first_try = ticket_owner.is_first_try;

                    // Are delay limits left?
                    let action = if self.await_ratelimits > ticket_owner.awaiting {
                        ticket_owner.awaiting += 1;

                        if let Some(delay_action) = self.delay_action {
                            let ctx = ctx.clone();
                            let msg = msg.clone();

                            tokio::spawn(async move {
                                delay_action(&ctx, &msg).await;
                            });
                        }

                        RateLimitAction::Delayed
                    // Is this bucket utilising delay limits?
                    } else if self.await_ratelimits > 0 {
                        ticket_owner.is_first_try = false;

                        RateLimitAction::FailedDelay
                    } else {
                        ticket_owner.is_first_try = false;

                        RateLimitAction::Cancelled
                    };

                    return Some(RateLimitInfo {
                        rate_limit: ratelimit,
                        active_delays: ticket_owner.awaiting,
                        max_delays: self.await_ratelimits,
                        action,
                        is_first_try: was_first_try,
                    });
                } else {
                    ticket_owner.tickets = 0;
                    ticket_owner.set_time = now;
                }
            }
        }

        // Check if `ratelimit.delay`-time passed between the last and
        // the current invocation
        // If the time did not pass, return the needed delay for this
        // invocation.
        if let Some(ratelimit) =
            ticket_owner.last_time.and_then(|x| (x + ratelimit.delay).checked_duration_since(now))
        {
            let was_first_try = ticket_owner.is_first_try;

            // Are delay limits left?
            let action = if self.await_ratelimits > ticket_owner.awaiting {
                ticket_owner.awaiting += 1;

                if let Some(delay_action) = self.delay_action {
                    let ctx = ctx.clone();
                    let msg = msg.clone();

                    tokio::spawn(async move {
                        delay_action(&ctx, &msg).await;
                    });
                }

                RateLimitAction::Delayed
            // Is this bucket utilising delay limits?
            } else if self.await_ratelimits > 0 {
                ticket_owner.is_first_try = false;

                RateLimitAction::FailedDelay
            } else {
                RateLimitAction::Cancelled
            };

            return Some(RateLimitInfo {
                rate_limit: ratelimit,
                active_delays: ticket_owner.awaiting,
                max_delays: self.await_ratelimits,
                action,
                is_first_try: was_first_try,
            });
        } else {
            ticket_owner.awaiting = ticket_owner.awaiting.saturating_sub(1);
            ticket_owner.tickets += 1;
            ticket_owner.is_first_try = true;
            ticket_owner.last_time = Some(now);
        }

        None
    }

    /// Reverts the last ticket step performed by returning a ticket for the
    /// matching ticket holder.
    /// Only call this if the mutable owner already took a ticket in this
    /// atomic execution of calling `take` and `give`.
    pub async fn give(&mut self, ctx: &Context, msg: &Message, id: u64) {
        if let Some(ref check) = self.check {
            if !(check)(ctx, msg).await {
                return;
            }
        }

        if let Some(ticket_owner) = self.tickets_for.get_mut(&id) {
            // Remove a ticket if one is available.
            if ticket_owner.tickets > 0 {
                ticket_owner.tickets -= 1;
            }

            let delay = self.ratelimit.delay;
            // Substract one step of time that would have to pass.
            // This tries to bypass a problem of keeping track of when tickets
            // were taken.
            // When a ticket is taken, the bucket sets `last_time`, by
            // substracting the delay, once a ticket is allowed to be
            // taken.
            // If the value is set to `None` this could possibly reset the
            // bucket.
            ticket_owner.last_time = ticket_owner.last_time.and_then(|i| i.checked_sub(delay));
        }
    }
}

/// An error struct that can be returned from a command to set the
/// bucket one step back.
#[derive(Debug)]
pub struct RevertBucket;

impl std::fmt::Display for RevertBucket {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "RevertBucket")
    }
}

impl std::error::Error for RevertBucket {}

/// Decides what a bucket will use to collect tickets for.
#[derive(Debug)]
pub enum LimitedFor {
    /// The bucket will collect tickets for every invocation of a command.
    Global,
    /// The bucket will collect tickets per user.
    User,
    /// The bucket will collect tickets per guild.
    Guild,
    /// The bucket will collect tickets per channel.
    Channel,
    /// The bucket will collect tickets per category.
    ///
    /// This requires the cache, as messages do not contain their channel's
    /// category.
    #[cfg(feature = "cache")]
    Category,
}

impl Default for LimitedFor {
    /// We use the previous behaviour of buckets as default.
    fn default() -> Self {
        Self::User
    }
}

pub struct BucketBuilder {
    pub(crate) delay: Duration,
    pub(crate) time_span: Duration,
    pub(crate) limit: u32,
    pub(crate) check: Option<Check>,
    pub(crate) delay_action: Option<DelayHook>,
    pub(crate) limited_for: LimitedFor,
    pub(crate) await_ratelimits: u32,
}

impl Default for BucketBuilder {
    fn default() -> Self {
        Self {
            delay: Duration::default(),
            time_span: Duration::default(),
            limit: 1,
            check: None,
            delay_action: None,
            limited_for: LimitedFor::default(),
            await_ratelimits: 0,
        }
    }
}

impl BucketBuilder {
    /// A bucket collecting tickets per command invocation.
    pub fn new_global() -> Self {
        Self {
            limited_for: LimitedFor::Global,
            ..Default::default()
        }
    }

    /// A bucket collecting tickets per user.
    pub fn new_user() -> Self {
        Self {
            limited_for: LimitedFor::User,
            ..Default::default()
        }
    }

    /// A bucket collecting tickets per guild.
    pub fn new_guild() -> Self {
        Self {
            limited_for: LimitedFor::Guild,
            ..Default::default()
        }
    }

    /// A bucket collecting tickets per channel.
    pub fn new_channel() -> Self {
        Self {
            limited_for: LimitedFor::Channel,
            ..Default::default()
        }
    }

    /// A bucket collecting tickets per channel category.
    ///
    /// This requires the cache, as messages do not contain their channel's
    /// category.
    #[cfg(feature = "cache")]
    pub fn new_category() -> Self {
        Self {
            limited_for: LimitedFor::Category,
            ..Default::default()
        }
    }

    /// The "break" time between invocations of a command.
    ///
    /// Expressed in seconds.
    #[inline]
    pub fn delay(&mut self, secs: u64) -> &mut Self {
        self.delay = Duration::from_secs(secs);

        self
    }

    /// How long the bucket will apply for.
    ///
    /// Expressed in seconds.
    #[inline]
    pub fn time_span(&mut self, secs: u64) -> &mut Self {
        self.time_span = Duration::from_secs(secs);

        self
    }

    /// Number of invocations allowed per [`Self::time_span`].
    #[inline]
    pub fn limit(&mut self, n: u32) -> &mut Self {
        self.limit = n;

        self
    }

    /// Middleware confirming (or denying) that the bucket is eligible to apply.
    /// For instance, to limit the bucket to just one user.
    #[inline]
    pub fn check(&mut self, check: Check) -> &mut Self {
        self.check = Some(check);

        self
    }

    /// This function will be called once a user's invocation has been delayed.
    #[inline]
    pub fn delay_action(&mut self, action: DelayHook) -> &mut Self {
        self.delay_action = Some(action);

        self
    }

    /// Limit the bucket for a specific type of `target`.
    #[inline]
    pub fn limit_for(&mut self, target: LimitedFor) -> &mut Self {
        self.limited_for = target;

        self
    }

    /// If this is set to an `amount` greater than `0`, the invocation of the
    /// command will be delayed `amount` times instead of stopping command
    /// dispatch.
    ///
    /// By default this value is `0` and rate limits will cancel instead.
    #[inline]
    pub fn await_ratelimits(&mut self, amount: u32) -> &mut Self {
        self.await_ratelimits = amount;

        self
    }

    /// Constructs the bucket.
    #[inline]
    pub(crate) fn construct(self) -> Bucket {
        let counter = TicketCounter {
            ratelimit: Ratelimit {
                delay: self.delay,
                limit: Some((self.time_span, self.limit)),
            },
            tickets_for: HashMap::new(),
            check: self.check,
            delay_action: self.delay_action,
            await_ratelimits: self.await_ratelimits,
        };

        match self.limited_for {
            LimitedFor::User => Bucket::User(counter),
            LimitedFor::Guild => Bucket::Guild(counter),
            LimitedFor::Channel => Bucket::Channel(counter),
            // This requires the cache, as messages do not contain their channel's
            // category.
            #[cfg(feature = "cache")]
            LimitedFor::Category => Bucket::Category(counter),
            LimitedFor::Global => Bucket::Global(counter),
        }
    }
}
<commit_msg>Remove unused structure in the framework (#1345)<commit_after>use std::collections::HashMap;
use std::time::{Duration, Instant};

use futures::future::BoxFuture;

use crate::client::Context;
use crate::model::channel::Message;

type Check = for<'fut> fn(&'fut Context, &'fut Message) -> BoxFuture<'fut, bool>;

type DelayHook = for<'fut> fn(&'fut Context, &'fut Message) -> BoxFuture<'fut, ()>;

pub(crate) struct Ratelimit {
    pub delay: Duration,
    pub limit: Option<(Duration, u32)>,
}
pub(crate) struct UnitRatelimit {
    pub last_time: Option<Instant>,
    pub set_time: Instant,
    pub tickets: u32,
    pub awaiting: u32,
    pub is_first_try: bool,
}

impl UnitRatelimit {
    fn new(creation_time: Instant) -> Self {
        Self {
            last_time: None,
            set_time: creation_time,
            tickets: 0,
            awaiting: 0,
            is_first_try: true,
        }
    }
}

/// A bucket offers fine-grained control over the execution of commands.
pub(crate) enum Bucket {
    /// The bucket will collect tickets for every invocation of a command.
    Global(TicketCounter),
    /// The bucket will collect tickets per user.
    User(TicketCounter),
    /// The bucket will collect tickets per guild.
    Guild(TicketCounter),
    /// The bucket will collect tickets per channel.
    Channel(TicketCounter),
    /// The bucket will collect tickets per category.
    ///
    /// This requires the cache, as messages do not contain their channel's
    /// category.
    #[cfg(feature = "cache")]
    Category(TicketCounter),
}

impl Bucket {
    #[inline]
    pub async fn take(&mut self, ctx: &Context, msg: &Message) -> Option<RateLimitInfo> {
        match self {
            Self::Global(counter) => counter.take(ctx, msg, 0).await,
            Self::User(counter) => counter.take(ctx, msg, msg.author.id.0).await,
            Self::Guild(counter) => {
                if let Some(guild_id) = msg.guild_id {
                    counter.take(ctx, msg, guild_id.0).await
                } else {
                    None
                }
            },
            Self::Channel(counter) => counter.take(ctx, msg, msg.channel_id.0).await,
            // This requires the cache, as messages do not contain their channel's
            // category.
            #[cfg(feature = "cache")]
            Self::Category(counter) => {
                if let Some(category_id) = msg.category_id(ctx).await {
                    counter.take(ctx, msg, category_id.0).await
                } else {
                    None
                }
            },
        }
    }

    #[inline]
    pub async fn give(&mut self, ctx: &Context, msg: &Message) {
        match self {
            Self::Global(counter) => counter.give(ctx, msg, 0).await,
            Self::User(counter) => counter.give(ctx, msg, msg.author.id.0).await,
            Self::Guild(counter) => {
                if let Some(guild_id) = msg.guild_id {
                    counter.give(ctx, msg, guild_id.0).await
                }
            },
            Self::Channel(counter) => counter.give(ctx, msg, msg.channel_id.0).await,
            // This requires the cache, as messages do not contain their channel's
            // category.
            #[cfg(feature = "cache")]
            Self::Category(counter) => {
                if let Some(category_id) = msg.category_id(ctx).await {
                    counter.give(ctx, msg, category_id.0).await
                }
            },
        }
    }
}

/// Keeps track of who owns how many tickets and when they accessed the last
/// time.
pub(crate) struct TicketCounter {
    pub ratelimit: Ratelimit,
    pub tickets_for: HashMap<u64, UnitRatelimit>,
    pub check: Option<Check>,
    pub delay_action: Option<DelayHook>,
    pub await_ratelimits: u32,
}

/// Contains information about a rate limit.
#[derive(Debug)]
pub struct RateLimitInfo {
    /// Time to elapse in order to invoke a command again.
    pub rate_limit: Duration,
    /// Amount of active delays by this target.
    pub active_delays: u32,
    /// Maximum delays that this target can invoke.
    pub max_delays: u32,
    /// Whether this is the first time the rate limit info has been
    /// returned for this target without the rate limit to elapse.
    pub is_first_try: bool,
    /// How the command invocation has been treated by the framework.
    pub action: RateLimitAction,
}

/// Action taken for the command invocation.
#[derive(Debug)]
pub enum RateLimitAction {
    /// Invocation has been delayed.
    Delayed,
    /// Tried to delay invocation but maximum of delays reached.
    FailedDelay,
    /// Cancelled the invocation due to time or ticket reasons.
    Cancelled,
}

impl RateLimitInfo {
    /// Gets the duration of the rate limit in seconds.
    #[inline]
    pub fn as_secs(&self) -> u64 {
        self.rate_limit.as_secs()
    }

    /// Gets the duration of the rate limit in milliseconds.
    #[inline]
    pub fn as_millis(&self) -> u128 {
        self.rate_limit.as_millis()
    }

    /// Gets the duration of the rate limit in microseconds.
    #[inline]
    pub fn as_micros(&self) -> u128 {
        self.rate_limit.as_micros()
    }
}

impl TicketCounter {
    /// Tries to check whether the invocation is permitted by the ticket counter
    /// and if a ticket can be taken; it does not return a
    /// a ticket but a duration until a ticket can be taken.
    ///
    /// The duration will be wrapped in an action for the caller to perform
    /// if wanted. This may inform them to directly cancel trying to take a ticket
    /// or delay the take until later.
    ///
    /// However there is no contract: It does not matter what
    /// the caller ends up doing, receiving some action eventually means
    /// no ticket can be taken and the duration must elapse.
    pub async fn take(&mut self, ctx: &Context, msg: &Message, id: u64) -> Option<RateLimitInfo> {
        if let Some(ref check) = self.check {
            if !(check)(ctx, msg).await {
                return None;
            }
        }

        let now = Instant::now();
        let Self {
            tickets_for,
            ratelimit,
            ..
        } = self;

        let ticket_owner = tickets_for.entry(id).or_insert_with(|| UnitRatelimit::new(now));

        // Check if too many tickets have been taken already.
        // If all tickets are exhausted, return the needed delay
        // for this invocation.
        if let Some((timespan, limit)) = ratelimit.limit {
            if (ticket_owner.tickets + 1) > limit {
                if let Some(ratelimit) =
                    (ticket_owner.set_time + timespan).checked_duration_since(now)
                {
                    let was_first_try = ticket_owner.is_first_try;

                    // Are delay limits left?
                    let action = if self.await_ratelimits > ticket_owner.awaiting {
                        ticket_owner.awaiting += 1;

                        if let Some(delay_action) = self.delay_action {
                            let ctx = ctx.clone();
                            let msg = msg.clone();

                            tokio::spawn(async move {
                                delay_action(&ctx, &msg).await;
                            });
                        }

                        RateLimitAction::Delayed
                    // Is this bucket utilising delay limits?
                    } else if self.await_ratelimits > 0 {
                        ticket_owner.is_first_try = false;

                        RateLimitAction::FailedDelay
                    } else {
                        ticket_owner.is_first_try = false;

                        RateLimitAction::Cancelled
                    };

                    return Some(RateLimitInfo {
                        rate_limit: ratelimit,
                        active_delays: ticket_owner.awaiting,
                        max_delays: self.await_ratelimits,
                        action,
                        is_first_try: was_first_try,
                    });
                } else {
                    ticket_owner.tickets = 0;
                    ticket_owner.set_time = now;
                }
            }
        }

        // Check if `ratelimit.delay`-time passed between the last and
        // the current invocation
        // If the time did not pass, return the needed delay for this
        // invocation.
        if let Some(ratelimit) =
            ticket_owner.last_time.and_then(|x| (x + ratelimit.delay).checked_duration_since(now))
        {
            let was_first_try = ticket_owner.is_first_try;

            // Are delay limits left?
            let action = if self.await_ratelimits > ticket_owner.awaiting {
                ticket_owner.awaiting += 1;

                if let Some(delay_action) = self.delay_action {
                    let ctx = ctx.clone();
                    let msg = msg.clone();

                    tokio::spawn(async move {
                        delay_action(&ctx, &msg).await;
                    });
                }

                RateLimitAction::Delayed
            // Is this bucket utilising delay limits?
            } else if self.await_ratelimits > 0 {
                ticket_owner.is_first_try = false;

                RateLimitAction::FailedDelay
            } else {
                RateLimitAction::Cancelled
            };

            return Some(RateLimitInfo {
                rate_limit: ratelimit,
                active_delays: ticket_owner.awaiting,
                max_delays: self.await_ratelimits,
                action,
                is_first_try: was_first_try,
            });
        } else {
            ticket_owner.awaiting = ticket_owner.awaiting.saturating_sub(1);
            ticket_owner.tickets += 1;
            ticket_owner.is_first_try = true;
            ticket_owner.last_time = Some(now);
        }

        None
    }

    /// Reverts the last ticket step performed by returning a ticket for the
    /// matching ticket holder.
    /// Only call this if the mutable owner already took a ticket in this
    /// atomic execution of calling `take` and `give`.
    pub async fn give(&mut self, ctx: &Context, msg: &Message, id: u64) {
        if let Some(ref check) = self.check {
            if !(check)(ctx, msg).await {
                return;
            }
        }

        if let Some(ticket_owner) = self.tickets_for.get_mut(&id) {
            // Remove a ticket if one is available.
            if ticket_owner.tickets > 0 {
                ticket_owner.tickets -= 1;
            }

            let delay = self.ratelimit.delay;
            // Substract one step of time that would have to pass.
            // This tries to bypass a problem of keeping track of when tickets
            // were taken.
            // When a ticket is taken, the bucket sets `last_time`, by
            // substracting the delay, once a ticket is allowed to be
            // taken.
            // If the value is set to `None` this could possibly reset the
            // bucket.
            ticket_owner.last_time = ticket_owner.last_time.and_then(|i| i.checked_sub(delay));
        }
    }
}

/// An error struct that can be returned from a command to set the
/// bucket one step back.
#[derive(Debug)]
pub struct RevertBucket;

impl std::fmt::Display for RevertBucket {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "RevertBucket")
    }
}

impl std::error::Error for RevertBucket {}

/// Decides what a bucket will use to collect tickets for.
#[derive(Debug)]
pub enum LimitedFor {
    /// The bucket will collect tickets for every invocation of a command.
    Global,
    /// The bucket will collect tickets per user.
    User,
    /// The bucket will collect tickets per guild.
    Guild,
    /// The bucket will collect tickets per channel.
    Channel,
    /// The bucket will collect tickets per category.
    ///
    /// This requires the cache, as messages do not contain their channel's
    /// category.
    #[cfg(feature = "cache")]
    Category,
}

impl Default for LimitedFor {
    /// We use the previous behaviour of buckets as default.
    fn default() -> Self {
        Self::User
    }
}

pub struct BucketBuilder {
    pub(crate) delay: Duration,
    pub(crate) time_span: Duration,
    pub(crate) limit: u32,
    pub(crate) check: Option<Check>,
    pub(crate) delay_action: Option<DelayHook>,
    pub(crate) limited_for: LimitedFor,
    pub(crate) await_ratelimits: u32,
}

impl Default for BucketBuilder {
    fn default() -> Self {
        Self {
            delay: Duration::default(),
            time_span: Duration::default(),
            limit: 1,
            check: None,
            delay_action: None,
            limited_for: LimitedFor::default(),
            await_ratelimits: 0,
        }
    }
}

impl BucketBuilder {
    /// A bucket collecting tickets per command invocation.
    pub fn new_global() -> Self {
        Self {
            limited_for: LimitedFor::Global,
            ..Default::default()
        }
    }

    /// A bucket collecting tickets per user.
    pub fn new_user() -> Self {
        Self {
            limited_for: LimitedFor::User,
            ..Default::default()
        }
    }

    /// A bucket collecting tickets per guild.
    pub fn new_guild() -> Self {
        Self {
            limited_for: LimitedFor::Guild,
            ..Default::default()
        }
    }

    /// A bucket collecting tickets per channel.
    pub fn new_channel() -> Self {
        Self {
            limited_for: LimitedFor::Channel,
            ..Default::default()
        }
    }

    /// A bucket collecting tickets per channel category.
    ///
    /// This requires the cache, as messages do not contain their channel's
    /// category.
    #[cfg(feature = "cache")]
    pub fn new_category() -> Self {
        Self {
            limited_for: LimitedFor::Category,
            ..Default::default()
        }
    }

    /// The "break" time between invocations of a command.
    ///
    /// Expressed in seconds.
    #[inline]
    pub fn delay(&mut self, secs: u64) -> &mut Self {
        self.delay = Duration::from_secs(secs);

        self
    }

    /// How long the bucket will apply for.
    ///
    /// Expressed in seconds.
    #[inline]
    pub fn time_span(&mut self, secs: u64) -> &mut Self {
        self.time_span = Duration::from_secs(secs);

        self
    }

    /// Number of invocations allowed per [`Self::time_span`].
    #[inline]
    pub fn limit(&mut self, n: u32) -> &mut Self {
        self.limit = n;

        self
    }

    /// Middleware confirming (or denying) that the bucket is eligible to apply.
    /// For instance, to limit the bucket to just one user.
    #[inline]
    pub fn check(&mut self, check: Check) -> &mut Self {
        self.check = Some(check);

        self
    }

    /// This function will be called once a user's invocation has been delayed.
    #[inline]
    pub fn delay_action(&mut self, action: DelayHook) -> &mut Self {
        self.delay_action = Some(action);

        self
    }

    /// Limit the bucket for a specific type of `target`.
    #[inline]
    pub fn limit_for(&mut self, target: LimitedFor) -> &mut Self {
        self.limited_for = target;

        self
    }

    /// If this is set to an `amount` greater than `0`, the invocation of the
    /// command will be delayed `amount` times instead of stopping command
    /// dispatch.
    ///
    /// By default this value is `0` and rate limits will cancel instead.
    #[inline]
    pub fn await_ratelimits(&mut self, amount: u32) -> &mut Self {
        self.await_ratelimits = amount;

        self
    }

    /// Constructs the bucket.
    #[inline]
    pub(crate) fn construct(self) -> Bucket {
        let counter = TicketCounter {
            ratelimit: Ratelimit {
                delay: self.delay,
                limit: Some((self.time_span, self.limit)),
            },
            tickets_for: HashMap::new(),
            check: self.check,
            delay_action: self.delay_action,
            await_ratelimits: self.await_ratelimits,
        };

        match self.limited_for {
            LimitedFor::User => Bucket::User(counter),
            LimitedFor::Guild => Bucket::Guild(counter),
            LimitedFor::Channel => Bucket::Channel(counter),
            // This requires the cache, as messages do not contain their channel's
            // category.
            #[cfg(feature = "cache")]
            LimitedFor::Category => Bucket::Category(counter),
            LimitedFor::Global => Bucket::Global(counter),
        }
    }
}
<|endoftext|>