<commit_before>//!
//! Raw communication channel to the FUSE kernel driver.
//!

use std::io;
use std::ffi::{CString, CStr, OsStr};
use std::os::unix::ffi::OsStrExt;
use std::path::{PathBuf, Path};
use libc::{c_char, c_int, c_void, size_t};
use fuse::{fuse_args, fuse_mount_compat25};

// Libc provides iovec based I/O using readv and writev functions
#[allow(dead_code, non_camel_case_types)]
mod libc {
    use libc::{c_char, c_int, c_void, size_t, ssize_t};

    /// Iovec data structure for readv and writev calls.
    #[repr(C)]
    pub struct iovec {
        pub iov_base: *const c_void,
        pub iov_len: size_t,
    }

    extern "system" {
        /// Read data from fd into multiple buffers
        pub fn readv (fd: c_int, iov: *mut iovec, iovcnt: c_int) -> ssize_t;
        /// Write data from multiple buffers to fd
        pub fn writev (fd: c_int, iov: *const iovec, iovcnt: c_int) -> ssize_t;

        pub fn realpath (file_name: *const c_char, resolved_name: *mut c_char) -> *const c_char;

        #[cfg(target_os = "macos")]
        pub fn unmount(dir: *const c_char, flags: c_int) -> c_int;
        #[cfg(not(target_os = "macos"))]
        pub fn umount(dir: *const c_char) -> c_int;
    }

    /// Max length for path names. 4096 should be reasonable safe (OS X uses 1024, Linux uses 4096)
    pub const PATH_MAX: usize = 4096;
}

/// Wrapper around libc's realpath.  Returns the errno value if the real path cannot be obtained.
/// FIXME: Use Rust's realpath method once available in std (see also https://github.com/mozilla/rust/issues/11857)
fn real_path (path: &CStr) -> io::Result<CString> {
    let mut resolved: Vec<c_char> = Vec::with_capacity(libc::PATH_MAX);
    unsafe {
        if libc::realpath(path.as_ptr(), resolved.as_mut_ptr()).is_null() {
            Err(io::Error::last_os_error())
        } else {
            // Using CStr::from_ptr gets the correct string length via strlen()
            let cresolved = CStr::from_ptr(resolved.as_ptr());
            Ok(CString::new(cresolved.to_bytes()).unwrap())
        }
    }
}

/// Helper function to provide options as a fuse_args struct
/// (which contains an argc count and an argv pointer)
fn with_fuse_args<T, F: FnOnce(&fuse_args) -> T> (options: &[&OsStr], f: F) -> T {
    let mut args: Vec<CString> = vec![CString::new("rust-fuse").unwrap()];
    args.extend(options.iter().map(|s| CString::new(s.as_bytes()).unwrap() ));
    let argptrs: Vec<*const i8> = args.iter().map(|s| s.as_ptr()).collect();
    f(&fuse_args { argc: argptrs.len() as i32, argv: argptrs.as_ptr(), allocated: 0 })
}

/// A raw communication channel to the FUSE kernel driver
pub struct Channel {
    mountpoint: PathBuf,
    fd: c_int,
}

impl Channel {
    /// Create a new communication channel to the kernel driver by mounting the
    /// given path. The kernel driver will delegate filesystem operations of
    /// the given path to the channel. If the channel is dropped, the path is
    /// unmounted.
    pub fn new (mountpoint: &Path, options: &[&OsStr]) -> io::Result<Channel> {
        let mnt = try!(CString::new(mountpoint.as_os_str().as_bytes()));
        real_path(&mnt).and_then(|mnt| {
            with_fuse_args(options, |args| {
                let fd = unsafe { fuse_mount_compat25(mnt.as_ptr(), args) };
                if fd < 0 {
                    Err(io::Error::last_os_error())
                } else {
                    let mountpoint = PathBuf::from(<OsStr as OsStrExt>::from_bytes(mnt.as_bytes()));
                    Ok(Channel { mountpoint: mountpoint, fd: fd })
                }
            })
        })
    }

    /// Return path of the mounted filesystem
    pub fn mountpoint (&self) -> &Path {
        &self.mountpoint
    }

    /// Receives data up to the capacity of the given buffer (can block).
    pub fn receive (&self, buffer: &mut Vec<u8>) -> io::Result<()> {
        let rc = unsafe { ::libc::read(self.fd, buffer.as_ptr() as *mut c_void, buffer.capacity() as size_t) };
        if rc < 0 {
            Err(io::Error::last_os_error())
        } else {
            unsafe { buffer.set_len(rc as usize); }
            Ok(())
        }
    }

    /// Returns a sender object for this channel. The sender object can be
    /// used to send to the channel. Multiple sender objects can be used
    /// and they can safely be sent to other threads.
    pub fn sender (&self) -> ChannelSender {
        // Since write/writev syscalls are threadsafe, we can simply create
        // a sender by using the same fd and use it in other threads. Only
        // the channel closes the fd when dropped. If any sender is used after
        // dropping the channel, it'll return an EBADF error.
        ChannelSender { fd: self.fd }
    }
}

impl Drop for Channel {
    fn drop (&mut self) {
        // TODO: send ioctl FUSEDEVIOCSETDAEMONDEAD on OS X before closing the fd
        // Close the communication channel to the kernel driver
        // (closing it before unnmount prevents sync unmount deadlock)
        unsafe { ::libc::close(self.fd); }
        // Unmount this channel's mount point
        let _ = unmount(&self.mountpoint);
    }
}

#[derive(Clone, Copy)]
pub struct ChannelSender {
    fd: c_int,
}

impl ChannelSender {
    /// Send all data in the slice of slice of bytes in a single write (can block).
    pub fn send (&self, buffer: &[&[u8]]) -> io::Result<()> {
        let iovecs: Vec<libc::iovec> = buffer.iter().map(|d| {
            libc::iovec { iov_base: d.as_ptr() as *const c_void, iov_len: d.len() as size_t }
        }).collect();
        let rc = unsafe { libc::writev(self.fd, iovecs.as_ptr(), iovecs.len() as c_int) };
        if rc < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(())
        }
    }
}

/// Unmount an arbitrary mount point
pub fn unmount (mountpoint: &Path) -> io::Result<()> {
    // fuse_unmount_compat22 unfortunately doesn't return a status. Additionally,
    // it attempts to call realpath, which in turn calls into the filesystem. So
    // if the filesystem returns an error, the unmount does not take place, with
    // no indication of the error available to the caller. So we call unmount
    // directly, which is what osxfuse does anyway, since we already converted
    // to the real path when we first mounted.

    #[cfg(target_os = "macos")] #[inline]
    fn libc_umount (mnt: &CStr) -> c_int { unsafe { libc::unmount(mnt.as_ptr(), 0) } }

    #[cfg(not(target_os = "macos"))] #[inline]
    fn libc_umount (mnt: &CStr) -> c_int {
        use fuse::fuse_unmount_compat22;
        use std::io::ErrorKind::PermissionDenied;

        let rc = unsafe { libc::umount(mnt.as_ptr()) };
        if rc < 0 && io::Error::last_os_error().kind() == PermissionDenied {
            // Linux always returns EPERM for non-root users.  We have to let the
            // library go through the setuid-root "fusermount -u" to unmount.
            unsafe { fuse_unmount_compat22(mnt.as_ptr()); }
            0
        } else {
            rc
        }
    }

    let mnt = try!(CString::new(mountpoint.as_os_str().as_bytes()));
    let rc = libc_umount(&mnt);
    if rc < 0 {
        Err(io::Error::last_os_error())
    } else {
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use super::with_fuse_args;
    use std::ffi::{CStr, OsStr};

    #[test]
    fn fuse_args () {
        with_fuse_args(&[OsStr::new("foo"), OsStr::new("bar")], |args| {
            assert_eq!(args.argc, 3);
            assert_eq!(unsafe { CStr::from_ptr(*args.argv.offset(0)).to_bytes() }, b"rust-fuse");
            assert_eq!(unsafe { CStr::from_ptr(*args.argv.offset(1)).to_bytes() }, b"foo");
            assert_eq!(unsafe { CStr::from_ptr(*args.argv.offset(2)).to_bytes() }, b"bar");
        });
    }
}
<commit_msg>Note the probable replacement for realpath()<commit_after>//!
//! Raw communication channel to the FUSE kernel driver.
//!

use std::io;
use std::ffi::{CString, CStr, OsStr};
use std::os::unix::ffi::OsStrExt;
use std::path::{PathBuf, Path};
use libc::{c_char, c_int, c_void, size_t};
use fuse::{fuse_args, fuse_mount_compat25};

// Libc provides iovec based I/O using readv and writev functions
#[allow(dead_code, non_camel_case_types)]
mod libc {
    use libc::{c_char, c_int, c_void, size_t, ssize_t};

    /// Iovec data structure for readv and writev calls.
    #[repr(C)]
    pub struct iovec {
        pub iov_base: *const c_void,
        pub iov_len: size_t,
    }

    extern "system" {
        /// Read data from fd into multiple buffers
        pub fn readv (fd: c_int, iov: *mut iovec, iovcnt: c_int) -> ssize_t;
        /// Write data from multiple buffers to fd
        pub fn writev (fd: c_int, iov: *const iovec, iovcnt: c_int) -> ssize_t;

        pub fn realpath (file_name: *const c_char, resolved_name: *mut c_char) -> *const c_char;

        #[cfg(target_os = "macos")]
        pub fn unmount(dir: *const c_char, flags: c_int) -> c_int;
        #[cfg(not(target_os = "macos"))]
        pub fn umount(dir: *const c_char) -> c_int;
    }

    /// Max length for path names. 4096 should be reasonable safe (OS X uses 1024, Linux uses 4096)
    pub const PATH_MAX: usize = 4096;
}

/// Wrapper around libc's realpath.  Returns the errno value if the real path cannot be obtained.
/// FIXME: Use std::fs::canonicalize() once stable (rust-lang/rust#27706)
fn real_path (path: &CStr) -> io::Result<CString> {
    let mut resolved: Vec<c_char> = Vec::with_capacity(libc::PATH_MAX);
    unsafe {
        if libc::realpath(path.as_ptr(), resolved.as_mut_ptr()).is_null() {
            Err(io::Error::last_os_error())
        } else {
            // Using CStr::from_ptr gets the correct string length via strlen()
            let cresolved = CStr::from_ptr(resolved.as_ptr());
            Ok(CString::new(cresolved.to_bytes()).unwrap())
        }
    }
}

/// Helper function to provide options as a fuse_args struct
/// (which contains an argc count and an argv pointer)
fn with_fuse_args<T, F: FnOnce(&fuse_args) -> T> (options: &[&OsStr], f: F) -> T {
    let mut args: Vec<CString> = vec![CString::new("rust-fuse").unwrap()];
    args.extend(options.iter().map(|s| CString::new(s.as_bytes()).unwrap() ));
    let argptrs: Vec<*const i8> = args.iter().map(|s| s.as_ptr()).collect();
    f(&fuse_args { argc: argptrs.len() as i32, argv: argptrs.as_ptr(), allocated: 0 })
}

/// A raw communication channel to the FUSE kernel driver
pub struct Channel {
    mountpoint: PathBuf,
    fd: c_int,
}

impl Channel {
    /// Create a new communication channel to the kernel driver by mounting the
    /// given path. The kernel driver will delegate filesystem operations of
    /// the given path to the channel. If the channel is dropped, the path is
    /// unmounted.
    pub fn new (mountpoint: &Path, options: &[&OsStr]) -> io::Result<Channel> {
        let mnt = try!(CString::new(mountpoint.as_os_str().as_bytes()));
        real_path(&mnt).and_then(|mnt| {
            with_fuse_args(options, |args| {
                let fd = unsafe { fuse_mount_compat25(mnt.as_ptr(), args) };
                if fd < 0 {
                    Err(io::Error::last_os_error())
                } else {
                    let mountpoint = PathBuf::from(<OsStr as OsStrExt>::from_bytes(mnt.as_bytes()));
                    Ok(Channel { mountpoint: mountpoint, fd: fd })
                }
            })
        })
    }

    /// Return path of the mounted filesystem
    pub fn mountpoint (&self) -> &Path {
        &self.mountpoint
    }

    /// Receives data up to the capacity of the given buffer (can block).
    pub fn receive (&self, buffer: &mut Vec<u8>) -> io::Result<()> {
        let rc = unsafe { ::libc::read(self.fd, buffer.as_ptr() as *mut c_void, buffer.capacity() as size_t) };
        if rc < 0 {
            Err(io::Error::last_os_error())
        } else {
            unsafe { buffer.set_len(rc as usize); }
            Ok(())
        }
    }

    /// Returns a sender object for this channel. The sender object can be
    /// used to send to the channel. Multiple sender objects can be used
    /// and they can safely be sent to other threads.
    pub fn sender (&self) -> ChannelSender {
        // Since write/writev syscalls are threadsafe, we can simply create
        // a sender by using the same fd and use it in other threads. Only
        // the channel closes the fd when dropped. If any sender is used after
        // dropping the channel, it'll return an EBADF error.
        ChannelSender { fd: self.fd }
    }
}

impl Drop for Channel {
    fn drop (&mut self) {
        // TODO: send ioctl FUSEDEVIOCSETDAEMONDEAD on OS X before closing the fd
        // Close the communication channel to the kernel driver
        // (closing it before unnmount prevents sync unmount deadlock)
        unsafe { ::libc::close(self.fd); }
        // Unmount this channel's mount point
        let _ = unmount(&self.mountpoint);
    }
}

#[derive(Clone, Copy)]
pub struct ChannelSender {
    fd: c_int,
}

impl ChannelSender {
    /// Send all data in the slice of slice of bytes in a single write (can block).
    pub fn send (&self, buffer: &[&[u8]]) -> io::Result<()> {
        let iovecs: Vec<libc::iovec> = buffer.iter().map(|d| {
            libc::iovec { iov_base: d.as_ptr() as *const c_void, iov_len: d.len() as size_t }
        }).collect();
        let rc = unsafe { libc::writev(self.fd, iovecs.as_ptr(), iovecs.len() as c_int) };
        if rc < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(())
        }
    }
}

/// Unmount an arbitrary mount point
pub fn unmount (mountpoint: &Path) -> io::Result<()> {
    // fuse_unmount_compat22 unfortunately doesn't return a status. Additionally,
    // it attempts to call realpath, which in turn calls into the filesystem. So
    // if the filesystem returns an error, the unmount does not take place, with
    // no indication of the error available to the caller. So we call unmount
    // directly, which is what osxfuse does anyway, since we already converted
    // to the real path when we first mounted.

    #[cfg(target_os = "macos")] #[inline]
    fn libc_umount (mnt: &CStr) -> c_int { unsafe { libc::unmount(mnt.as_ptr(), 0) } }

    #[cfg(not(target_os = "macos"))] #[inline]
    fn libc_umount (mnt: &CStr) -> c_int {
        use fuse::fuse_unmount_compat22;
        use std::io::ErrorKind::PermissionDenied;

        let rc = unsafe { libc::umount(mnt.as_ptr()) };
        if rc < 0 && io::Error::last_os_error().kind() == PermissionDenied {
            // Linux always returns EPERM for non-root users.  We have to let the
            // library go through the setuid-root "fusermount -u" to unmount.
            unsafe { fuse_unmount_compat22(mnt.as_ptr()); }
            0
        } else {
            rc
        }
    }

    let mnt = try!(CString::new(mountpoint.as_os_str().as_bytes()));
    let rc = libc_umount(&mnt);
    if rc < 0 {
        Err(io::Error::last_os_error())
    } else {
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use super::with_fuse_args;
    use std::ffi::{CStr, OsStr};

    #[test]
    fn fuse_args () {
        with_fuse_args(&[OsStr::new("foo"), OsStr::new("bar")], |args| {
            assert_eq!(args.argc, 3);
            assert_eq!(unsafe { CStr::from_ptr(*args.argv.offset(0)).to_bytes() }, b"rust-fuse");
            assert_eq!(unsafe { CStr::from_ptr(*args.argv.offset(1)).to_bytes() }, b"foo");
            assert_eq!(unsafe { CStr::from_ptr(*args.argv.offset(2)).to_bytes() }, b"bar");
        });
    }
}
<|endoftext|>


<commit_before>pub fn find_words(words: Vec<String>) -> Vec<String> {
    use std::collections::HashSet;
    let one = {
        let mut temp = HashSet::new();
        for c in vec![b'q', b'w', b'e', b'r', b't', b'y', b'u', b'i', b'o', b'p'] {
            temp.insert(c);
        }
        temp
    };

    let two = {
        let mut temp = HashSet::new();
        for c in vec![b'a', b's', b'd', b'f', b'g', b'g', b'h', b'j', b'k', b'l'] {
            temp.insert(c);
        }
        temp
    };

    let three = {
        let mut temp = HashSet::new();
        for c in vec![b'z', b'x', b'c', b'v', b'b', b'n', b'm'] {
            temp.insert(c);
        }
        temp
    };

    let re = words.iter().map(|x| {
        let low_x = x.to_lowercase();
        let mut bytes = low_x.bytes();
        let temp_set = {
            let first = bytes.next().unwrap();
            let a = if one.contains(&first) {
                &one
            } else if two.contains(&first) {
                &two
            } else {
                &three
            };
            a
        };

        if bytes.all(|x| temp_set.contains(&x)) {
            return x.clone();
        } else {
            "".to_string()
        }
    });

    re.filter(|x| x != "").collect::<Vec<String>>()
}

fn main() {
    dbg!(find_words(vec![
        String::from("Hello"),
        String::from("Alaska"),
        String::from("Dad"),
        String::from("Peace")
    ]));
}
<commit_msg>use new way to make hashset<commit_after>pub fn find_words(words: Vec<String>) -> Vec<String> {
    use std::collections::HashSet;
    let one = {
        let temp: HashSet<u8> = "qwertyuiop".as_bytes().iter().cloned().collect();
        //for c in vec![b'q', b'w', b'e', b'r', b't', b'y', b'u', b'i', b'o', b'p'] {
        //    temp.insert(c);
        //}
        temp
    };
    //dbg!(&one);

    let two = {
        let temp: HashSet<u8> = "asdfghjkl".as_bytes().iter().cloned().collect();
        // for c in vec![b'a', b's', b'd', b'f', b'g', b'g', b'h', b'j', b'k', b'l'] {
        //     temp.insert(c);
        // }
        temp
    };
    //dbg!(&two);

    let three = {
        let temp: HashSet<u8> = "zxcvbnm".as_bytes().iter().cloned().collect();
        // let _ = "zxcvbnm".as_bytes().iter().map(|by| {
        //     temp.insert(by);
        // }); //=> ??????

        // for c in vec![b'z', b'x', b'c', b'v', b'b', b'n', b'm'] {
        //     temp.insert(c);
        // }
        temp
    };
    //dbg!(&three);

    let re = words.iter().map(|x| {
        let low_x = x.to_lowercase();
        let mut bytes = low_x.bytes();
        let temp_set = {
            let first = bytes.next().unwrap();
            let a = if one.contains(&first) {
                &one
            } else if two.contains(&first) {
                &two
            } else {
                &three
            };
            a
        };

        if bytes.all(|x| temp_set.contains(&x)) {
            return x.clone();
        } else {
            "".to_string()
        }
    });

    re.filter(|x| x != "").collect::<Vec<String>>()
}

fn main() {
    dbg!(find_words(vec![
        String::from("Hello"),
        String::from("Alaska"),
        String::from("Dad"),
        String::from("Peace")
    ]));
}
<|endoftext|>


<commit_before>//! Root mean square calculation over a signal.
//!
//! The primary type of interest in this module is the [**Rms**](./struct.Rms).

use std::collections::VecDeque;

/// Iteratively extracts the RMS (root mean square) envelope from a window over a signal of
/// samples.
#[derive(Clone, Debug)]
pub struct Rms {
    /// The ringbuffer of sample squares (i.e. `sample.powf(2.0)`) used to calculate the RMS per
    /// sample.
    ///
    /// When a new sample is received, the **Rms** pops the front sample_square and adds the new
    /// sample_square to the back.
    window: VecDeque<f32>,
    /// The sum total of all sample_squares currently within the **Rms**'s `window` ring buffer.
    sum: f32,
}

impl Rms {

    /// Construct a new **Rms**.
    pub fn new(n_window_frames: usize) -> Self {
        Rms {
            window: (0..n_window_frames).map(|_| 0.0).collect(),
            sum: 0.0,
        }
    }

    /// Zeroes the sum and the buffer of the `window`.
    pub fn reset(&mut self) {
        for sample_square in &mut self.window {
            *sample_square = 0.0;
        }
        self.sum = 0.0;
    }

    /// Set the size of the `window` as a number of frames.
    ///
    /// If the current window length is longer than the given length, the difference will be popped
    /// from the front of the `window` while adjusting the `sum` accordingly.
    ///
    /// If the current window length is shorter than the given length, the difference will be
    /// pushed to the front of the `window` using an averaged frame in order to retain the current
    /// RMS.
    ///
    /// If the length already is already correct, no re-sizing occurs.
    pub fn set_window_frames(&mut self, n_window_frames: usize) {
        let len = self.window.len();
        if len == n_window_frames {
            return;

        // If our window is too long, truncate it from the front (removing the olest frames).
        } else if len > n_window_frames {
            let diff = len - n_window_frames;
            for _ in 0..diff {
                self.pop_front();
            }

        // If our window is too short, extend it using fake frames.
        //
        // We'll generate the fake samples as the current average to avoid affecting the `window`'s
        // RMS output as much as possible.
        } else if len < n_window_frames {
            let diff = n_window_frames - len;
            let avg = self.sum / self.window.len() as f32;
            for _ in 0..diff {
                // Push the new fake samples onto the front so they are the first to be removed.
                self.window.push_front(avg);
                self.sum += avg;
            }
        }
    }

    /// The length of the window as a number of frames.
    #[inline]
    pub fn window_frames(&self) -> usize {
        self.window.len()
    }

    /// The next RMS given the new sample in the sequence.
    ///
    /// The **Rms** pops its front sample and adds the new sample to the back.
    ///
    /// The yielded RMS is the RMS of all sample squares in the `window` after the new sample is
    /// added.
    ///
    /// Returns `0.0` if the `window` is empty.
    #[inline]
    pub fn next(&mut self, new_sample: f32) -> f32 {
        // If our **Window** has no length, there's nothing to calculate.
        if self.window.len() == 0 {
            return 0.0;
        }
        self.pop_front();
        self.push_back(new_sample);
        self.calc_rms()
    }

    /// Remove the front sample and subtract it from the `sum`.
    fn pop_front(&mut self) {
        let removed_sample_square = self.window.pop_front().unwrap();
        self.sum -= removed_sample_square;
        // Don't let floating point rounding errors put us below 0.0.
        if self.sum < 0.0 {
            self.sum = 0.0;
        }
    }

    /// Determines the square of the given sample, pushes it back onto our buffer and adds it to
    /// the `sum`.
    fn push_back(&mut self, new_sample: f32) {
        // Push back the new sample_square and add it to the `sum`.
        let new_sample_square = new_sample.powf(2.0);
        self.window.push_back(new_sample_square);
        self.sum += new_sample_square;
    }

    /// Calculate the RMS for the **Window** in its current state.
    fn calc_rms(&self) -> f32 {
        (self.sum / self.window.len() as f32).sqrt()
    }

}

<commit_msg>Change Rms to support tracking of arbitrary sample::Frames, rather than just f32 samples. This allows typifying the number of channels in the EnvelopeDetector.<commit_after>//! Root mean square calculation over a signal.
//!
//! The primary type of interest in this module is the [**Rms**](./struct.Rms).

use sample::{FloatSample, Frame, Sample};
use std;

/// Iteratively extracts the RMS (root mean square) envelope from a window over a signal of
/// sample `Frame`s.
#[derive(Clone, Debug)]
pub struct Rms<F>
    where F: Frame,
{
    /// The type of `Frame`s for which the RMS will be calculated.
    frame: std::marker::PhantomData<F>,
    /// The ringbuffer of frame sample squares (i.e. `sample * sample`) used to calculate the RMS
    /// per sample.
    ///
    /// When a new sample is received, the **Rms** pops the front sample_square and adds the new
    /// sample_square to the back.
    window: std::collections::VecDeque<F::Float>,
    /// The sum total of all sample_squares currently within the **Rms**'s `window` ring buffer.
    sum: F::Float,
}

impl<F> Rms<F>
    where F: Frame,
{

    /// Construct a new **Rms**.
    pub fn new(n_window_frames: usize) -> Self {
        Rms {
            frame: std::marker::PhantomData,
            window: (0..n_window_frames).map(|_| Frame::equilibrium()).collect(),
            sum: Frame::equilibrium(),
        }
    }

    /// Zeroes the sum and the buffer of the `window`.
    pub fn reset(&mut self) {
        for sample_square in &mut self.window {
            *sample_square = Frame::equilibrium();
        }
        self.sum = Frame::equilibrium();
    }

    /// Set the size of the `window` as a number of frames.
    ///
    /// If the current window length is longer than the given length, the difference will be popped
    /// from the front of the `window` while adjusting the `sum` accordingly.
    ///
    /// If the current window length is shorter than the given length, the difference will be
    /// pushed to the front of the `window` using frames at signal equilibrium.
    ///
    /// If the length already is already correct, no re-sizing occurs.
    pub fn set_window_frames(&mut self, n_window_frames: usize) {
        let len = self.window.len();
        if len == n_window_frames {
            return;

        // If our window is too long, truncate it from the front (removing the olest frames).
        } else if len > n_window_frames {
            let diff = len - n_window_frames;
            for _ in 0..diff {
                self.pop_front();
            }

        // If our window is too short, we'll zero-pad the front of the ringbuffer (this way, the
        // padded zeroes will be the first to be removed).
        } else if len < n_window_frames {
            let diff = n_window_frames - len;
            for _ in 0..diff {
                self.window.push_front(Frame::equilibrium());
            }
        }
    }

    /// The length of the window as a number of frames.
    #[inline]
    pub fn window_frames(&self) -> usize {
        self.window.len()
    }

    /// The next RMS given the new frame in the sequence.
    ///
    /// The **Rms** pops its front frame and adds the new frame to the back.
    ///
    /// The yielded RMS is the RMS of all frame squares in the `window` after the new frame is
    /// added.
    ///
    /// Returns `Frame::equilibrium` if the `window` is empty.
    #[inline]
    pub fn next(&mut self, new_frame: F) -> F {
        // If our **Window** has no length, there's nothing to calculate.
        if self.window.len() == 0 {
            return Frame::equilibrium();
        }
        self.pop_front();
        self.push_back(new_frame.to_float_frame());
        self.calc_rms()
    }

    /// Remove the front frame and subtract it from the `sum` frame.
    fn pop_front(&mut self) {
        let removed_sample_square = self.window.pop_front().unwrap();
        self.sum = self.sum.zip_map(removed_sample_square, |s, r| {
            let diff = s - r;
            // Don't let floating point rounding errors put us below 0.0.
            if diff < Sample::equilibrium() { Sample::equilibrium() } else { diff }
        });
    }

    /// Determines the square of the given frame, pushes it back onto our buffer and adds it to
    /// the `sum`.
    fn push_back(&mut self, new_frame: F::Float) {
        // Push back the new frame_square and add it to the `sum`.
        let new_frame_square = new_frame.zip_map(new_frame, |a, b| a * b);
        self.window.push_back(new_frame_square);
        self.sum = self.sum.add_amp(new_frame_square);
    }

    /// Calculate the RMS for the **Window** in its current state.
    fn calc_rms(&self) -> F {
        let num_frames_f = Sample::from_sample(self.window.len() as f32);
        self.sum.map(|s| (s / num_frames_f).sample_sqrt().to_sample::<F::Sample>())
    }

}
<|endoftext|>


<commit_before>use serde::ser::{Serialize, Serializer};

use types::chat::*;
use types::message::*;
use types::primitive::*;
use types::reply_markup::*;

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum ChatId<'a> {
    ById(Integer),
    ByUsername(&'a str),
}

impl<'a> ChatId<'a> {
    pub fn from_id(id: Integer) -> Self {
        ChatId::ById(id)
    }

    pub fn from_username(username: &'a str) -> Self {
        ChatId::ByUsername(username)
    }
}

impl<'a> Serialize for ChatId<'a> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        match *self {
            ChatId::ById(id) => serializer.serialize_i64(id),
            ChatId::ByUsername(username) => serializer.serialize_str(username),
        }
    }
}

impl<'a> From<Integer> for ChatId<'a> {
    fn from(value: Integer) -> ChatId<'a> {
        ChatId::from_id(value)
    }
}

impl<'a> From<&'a Chat> for ChatId<'a> {
    fn from(value: &'a Chat) -> ChatId<'a> {
        ChatId::from_id(value.id())
    }
}

macro_rules! from_chat_type {
    ($chat: ident) => {
        impl<'a> From<&'a $chat> for ChatId<'a> {
            fn from(value: &'a $chat) -> ChatId<'a> {
                ChatId::from_id(value.id)
            }
        }
    };
}

from_chat_type!(User);
from_chat_type!(Group);
from_chat_type!(Supergroup);
from_chat_type!(Channel);

#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub enum ParseMode {
    Markdown,
    HTML
}

impl Serialize for ParseMode {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        serializer.serialize_str(match *self {
            ParseMode::Markdown => "markdown",
            ParseMode::HTML => "HTML",
        })
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum ReplyMarkup {
    InlineKeyboardMarkup(InlineKeyboardMarkup),
    ReplyKeyboardMarkup(ReplyKeyboardMarkup),
    ReplyKeyboardRemove(ReplyKeyboardRemove),
    ForceReply(ForceReply),
}

impl Serialize for ReplyMarkup {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        match *self {
            ReplyMarkup::InlineKeyboardMarkup(ref value) => value.serialize(serializer),
            ReplyMarkup::ReplyKeyboardMarkup(ref value) => value.serialize(serializer),
            ReplyMarkup::ReplyKeyboardRemove(ref value) => value.serialize(serializer),
            ReplyMarkup::ForceReply(ref value) => value.serialize(serializer),
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct ReplyTo(pub Integer);

impl Serialize for ReplyTo {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        serializer.serialize_i64(self.0)
    }
}

impl From<Integer> for ReplyTo {
    fn from(value: Integer) -> Self {
        ReplyTo(value)
    }
}

impl<'a> From<&'a Message> for ReplyTo {
    fn from(value: &Message) -> Self {
        ReplyTo(value.id)
    }
}
<commit_msg>feat: add Request trait that is mapping from request type and response type for now<commit_after>use serde::ser::{Serialize, Serializer};

use types::chat::*;
use types::message::*;
use types::primitive::*;
use types::reply_markup::*;

pub trait Request {
    type Response;
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum ChatId<'a> {
    ById(Integer),
    ByUsername(&'a str),
}

impl<'a> ChatId<'a> {
    pub fn from_id(id: Integer) -> Self {
        ChatId::ById(id)
    }

    pub fn from_username(username: &'a str) -> Self {
        ChatId::ByUsername(username)
    }
}

impl<'a> Serialize for ChatId<'a> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        match *self {
            ChatId::ById(id) => serializer.serialize_i64(id),
            ChatId::ByUsername(username) => serializer.serialize_str(username),
        }
    }
}

impl<'a> From<Integer> for ChatId<'a> {
    fn from(value: Integer) -> ChatId<'a> {
        ChatId::from_id(value)
    }
}

impl<'a> From<&'a Chat> for ChatId<'a> {
    fn from(value: &'a Chat) -> ChatId<'a> {
        ChatId::from_id(value.id())
    }
}

macro_rules! from_chat_type {
    ($chat: ident) => {
        impl<'a> From<&'a $chat> for ChatId<'a> {
            fn from(value: &'a $chat) -> ChatId<'a> {
                ChatId::from_id(value.id)
            }
        }
    };
}

from_chat_type!(User);
from_chat_type!(Group);
from_chat_type!(Supergroup);
from_chat_type!(Channel);

#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub enum ParseMode {
    Markdown,
    HTML
}

impl Serialize for ParseMode {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        serializer.serialize_str(match *self {
            ParseMode::Markdown => "markdown",
            ParseMode::HTML => "HTML",
        })
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum ReplyMarkup {
    InlineKeyboardMarkup(InlineKeyboardMarkup),
    ReplyKeyboardMarkup(ReplyKeyboardMarkup),
    ReplyKeyboardRemove(ReplyKeyboardRemove),
    ForceReply(ForceReply),
}

impl Serialize for ReplyMarkup {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        match *self {
            ReplyMarkup::InlineKeyboardMarkup(ref value) => value.serialize(serializer),
            ReplyMarkup::ReplyKeyboardMarkup(ref value) => value.serialize(serializer),
            ReplyMarkup::ReplyKeyboardRemove(ref value) => value.serialize(serializer),
            ReplyMarkup::ForceReply(ref value) => value.serialize(serializer),
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct ReplyTo(pub Integer);

impl Serialize for ReplyTo {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        serializer.serialize_i64(self.0)
    }
}

impl From<Integer> for ReplyTo {
    fn from(value: Integer) -> Self {
        ReplyTo(value)
    }
}

impl<'a> From<&'a Message> for ReplyTo {
    fn from(value: &Message) -> Self {
        ReplyTo(value.id)
    }
}
<|endoftext|>


<commit_before>//! # Custom `derive` pretending to be functional procedural macros on Rust 1.15
//!
//! This crate enables creating function-like macros (invoked as `foo!(...)`)
//! with a procedural component,
//! based on both custom `derive` (a.k.a. *Macros 1.1*) and `macro_rules!`.
//!
//! This convoluted mechanism enables such macros to run on stable Rust 1.15,
//! even though functional procedural macros (a.k.a. *Macros 2.0*) are not available yet.
//!
//! A library defining such a macro needs two crates: a “normal” one, and a `proc-macro` one.
//! In the example below we’ll call them `libfoo` and `libfoo-macros`, respectively.
//!
//! # Credits
//!
//! The trick that makes this crate work
//! is based on an idea from [David Tolnay](https://github.com/dtolnay).
//! Many thanks!
//!
//! # Example
//!
//! As a simple example, we’re going to re-implement the `stringify!` macro.
//! This is useless since `stringify!` already exists in the standard library,
//! and a bit absurd since this crate uses `stringify!` internally.
//!
//! Nevertheless, it serves as a simple example to demonstrate the use of this crate.
//!
//! ## The `proc-macro` crate
//!
//! The minimal `Cargo.toml` file is typical for Macros 1.1:
//!
//! ```toml
//! [package]
//! name = "libfoo-macros"
//! version = "1.0.0"
//!
//! [lib]
//! proc-macro = true
//! ```
//!
//! In the code, we define the procedural part of our macro in a function.
//! This function will not be used directly by end users,
//! but it still needs to be re-exported to them
//! (because of limitations in `macro_rules!`).
//!
//! To avoid name collisions, we include a long and explicit prefix in the function’s name.
//!
//! The function takes a string containing arbitrary Rust tokens,
//! and returns a string that is parsed as *items*.
//! The returned string can contain constants, statics, functions, `impl`s, etc.,
//! but not expressions directly.
//!
//! ```rust
//! #[macro_use] extern crate procedural_masquerade;
//! extern crate proc_macro;
//!
//! define_proc_macros! {
//!     #[allow(non_snake_case)]
//!     pub fn foo_internal__stringify_const(input: &str) -> String {
//!         format!("const STRINGIFIED: &'static str = {:?};", input)
//!     }
//! }
//! ```
//!
//! A less trivial macro would probably use
//! the [`syn`](https://github.com/dtolnay/syn/) crate to parse its input
//! and the [`quote`](https://github.com/dtolnay/quote) crate to generate its output.
//!
//! ## The library crate
//!
//! ```toml
//! [package]
//! name = "libfoo"
//! version = "1.0.0"
//!
//! [dependencies]
//! libfoo-macros = {path = "./macros", version = "1.0"}
//! ```
//!
//! ```rust
//! #[macro_use] extern crate libfoo_macros;  // (1)
//!
//! pub use libfoo_macros::*;  // (2)
//!
//! define_invoke_proc_macro!(libfoo__invoke_proc_macro);  // (3)
//!
//! #[macro_export]
//! macro_rules! foo_stringify {  // (4)
//!     ( $( $tts: tt ) ) => {
//!         {  // (5)
//!             libfoo__invoke_proc_macro! {  // (6)
//!                 foo_internal__stringify_const!( $( $tts ) )  // (7)
//!             }
//!             STRINGIFIED  // (8)
//!         }
//!     }
//! }
//! ```
//!
//! Let’s go trough the numbered lines one by one:
//!
//! 1. `libfoo` depends on `libfoo-macros`, and imports its macros.
//! 2. Everything exported by `libfoo-macros` (which is one custom `derive`)
//!    is re-exported to users of `libfoo`.
//!    They’re not expected to use it directly,
//!    but expansion of the `foo_stringify` macro needs it.
//! 3. This macro invocation defines yet another macro, called `libfoo__invoke_proc_macro`,
//!    which is also exported.
//!    This indirection is necessary
//!    because re-exporting `macro_rules!` macros doesn’t work currently,
//!    and once again it is used by the expansion of `foo_stringify`.
//!    Again, we use a long prefix to avoid name collisions.
//! 4. Finally, we define the macro that we really want.
//!    This one has a name that users will use.
//! 5. The expansion of this macro will define some items,
//!    whose names are not hygienic in `macro_rules`.
//!    So we wrap everything in an extra `{…}` block to prevent these names for leaking.
//! 6. Here we use the macro defined in (3),
//!    which allows us to write something that look like invoking a functional procedural macro,
//!    but really uses a custom `derive`.
//!    This will define a type called `ProceduralMasqueradeDummyType`,
//!    as a placeholder to use `derive`.
//!    If `libfoo__invoke_proc_macro!` is to be used more than once,
//!    each use needs to be nested in another block
//!    so that the names of multiple dummy types don’t collide.
//! 7. In addition to the dummy type,
//!    the items returned by our procedural component are inserted here.
//!    (In this case the `STRINGIFIED` constant.)
//! 8. Finally, we write the expression that we want the macro to evaluate to.
//!    This expression can use parts of `foo_stringify`’s input,
//!    it can contain control-flow statements like `return` or `continue`,
//!    and of course refer to procedurally-defined items.
//!
//! This macro can be used in an expression context.
//! It expands to a block-expression that contains some items (as an implementation detail)
//! and ends with another expression.
//!
//! ## For users
//!
//! Users of `libfoo` don’t need to worry about any of these implementation details.
//! They can use the `foo_stringify` macro as if it were a simle `macro_rules` macro:
//!
//! ```rust
//! #[macro_use] extern crate libfoo;
//!
//! fn main() {
//!     do_something(foo_stringify!(1 + 2));
//! }
//!
//! fn do_something(_: &str) { /* ... */ }
//! ```
//!
//! # More
//!
//! To see a more complex example, look at
//! [`cssparser`’s `src/macros.rs`](https://github.com/servo/rust-cssparser/blob/master/src/macros.rs)
//! and
//! [`cssparser-macros`’s `macros/lib.rs`](https://github.com/servo/rust-cssparser/blob/master/macros/lib.rs).

/// This macro wraps `&str -> String` functions
/// in custom `derive` implementations with `#[proc_macro_derive]`.
///
/// See crate documentation for details.
#[macro_export]
macro_rules! define_proc_macros {
    (
        $(
            $( #[$attr:meta] )*
            pub fn $proc_macro_name: ident ($input: ident : &str) -> String
            $body: block
        )+
    ) => {
        $(
            $( #[$attr] )*
            #[proc_macro_derive($proc_macro_name)]
            pub fn $proc_macro_name(derive_input: ::proc_macro::TokenStream)
                                    -> ::proc_macro::TokenStream {
                fn wrapped($input: &str) -> String {
                    $body
                }
                let derive_input_string = derive_input.to_string();
                wrapped($crate::_extract_input(&derive_input_string)).parse().unwrap()
            }
        )+
    }
}

/// Implementation detail of `define_proc_macros!`.
///
/// **This function is not part of the public API. It can change or be removed between any versions.**
#[doc(hidden)]
pub fn _extract_input(derive_input: &str) -> &str {
    let mut input = derive_input;

    for expected in &["#[allow(unused)]", "enum", "ProceduralMasqueradeDummyType", "{",
                     "Input", "=", "(0,", "stringify!", "("] {
        input = input.trim_left();
        assert!(input.starts_with(expected),
                "expected prefix {:?} not found in {:?}", expected, derive_input);
        input = &input[expected.len()..];
    }

    for expected in [")", ").0,", "}"].iter().rev() {
        input = input.trim_right();
        assert!(input.ends_with(expected),
                "expected suffix {:?} not found in {:?}", expected, derive_input);
        let end = input.len() - expected.len();
        input = &input[..end];
    }

    input
}

/// This macro expands to the definition of another macro (whose name is given as a parameter).
///
/// See crate documentation for details.
#[macro_export]
macro_rules! define_invoke_proc_macro {
    ($macro_name: ident) => {
        /// Implementation detail of other macros in this crate.
        #[doc(hidden)]
        #[macro_export]
        macro_rules! $macro_name {
            ($proc_macro_name: ident ! $paren: tt) => {
                #[derive($proc_macro_name)]
                #[allow(unused)]
                enum ProceduralMasqueradeDummyType {
                    // The magic happens here.
                    //
                    // We use an `enum` with an explicit discriminant
                    // because that is the only case where a type definition
                    // can contain a (const) expression.
                    //
                    // `(0, "foo").0` evalutes to 0, with the `"foo"` part ignored.
                    //
                    // By the time the `#[proc_macro_derive]` function
                    // implementing `#[derive($proc_macro_name)]` is called,
                    // `$paren` has already been replaced with the input of this inner macro,
                    // but `stringify!` has not been expanded yet.
                    //
                    // This how arbitrary tokens can be inserted
                    // in the input to the `#[proc_macro_derive]` function.
                    //
                    // Later, `stringify!(...)` is expanded into a string literal
                    // which is then ignored.
                    // Using `stringify!` enables passing arbitrary tokens
                    // rather than only what can be parsed as a const expression.
                    Input = (0, stringify! $paren ).0
                }
            }
        }
    }
}
<commit_msg>procedural-masquerade: Give more stack to procedural-masquerade macros.<commit_after>//! # Custom `derive` pretending to be functional procedural macros on Rust 1.15
//!
//! This crate enables creating function-like macros (invoked as `foo!(...)`)
//! with a procedural component,
//! based on both custom `derive` (a.k.a. *Macros 1.1*) and `macro_rules!`.
//!
//! This convoluted mechanism enables such macros to run on stable Rust 1.15,
//! even though functional procedural macros (a.k.a. *Macros 2.0*) are not available yet.
//!
//! A library defining such a macro needs two crates: a “normal” one, and a `proc-macro` one.
//! In the example below we’ll call them `libfoo` and `libfoo-macros`, respectively.
//!
//! # Credits
//!
//! The trick that makes this crate work
//! is based on an idea from [David Tolnay](https://github.com/dtolnay).
//! Many thanks!
//!
//! # Example
//!
//! As a simple example, we’re going to re-implement the `stringify!` macro.
//! This is useless since `stringify!` already exists in the standard library,
//! and a bit absurd since this crate uses `stringify!` internally.
//!
//! Nevertheless, it serves as a simple example to demonstrate the use of this crate.
//!
//! ## The `proc-macro` crate
//!
//! The minimal `Cargo.toml` file is typical for Macros 1.1:
//!
//! ```toml
//! [package]
//! name = "libfoo-macros"
//! version = "1.0.0"
//!
//! [lib]
//! proc-macro = true
//! ```
//!
//! In the code, we define the procedural part of our macro in a function.
//! This function will not be used directly by end users,
//! but it still needs to be re-exported to them
//! (because of limitations in `macro_rules!`).
//!
//! To avoid name collisions, we include a long and explicit prefix in the function’s name.
//!
//! The function takes a string containing arbitrary Rust tokens,
//! and returns a string that is parsed as *items*.
//! The returned string can contain constants, statics, functions, `impl`s, etc.,
//! but not expressions directly.
//!
//! ```rust
//! #[macro_use] extern crate procedural_masquerade;
//! extern crate proc_macro;
//!
//! define_proc_macros! {
//!     #[allow(non_snake_case)]
//!     pub fn foo_internal__stringify_const(input: &str) -> String {
//!         format!("const STRINGIFIED: &'static str = {:?};", input)
//!     }
//! }
//! ```
//!
//! A less trivial macro would probably use
//! the [`syn`](https://github.com/dtolnay/syn/) crate to parse its input
//! and the [`quote`](https://github.com/dtolnay/quote) crate to generate its output.
//!
//! ## The library crate
//!
//! ```toml
//! [package]
//! name = "libfoo"
//! version = "1.0.0"
//!
//! [dependencies]
//! libfoo-macros = {path = "./macros", version = "1.0"}
//! ```
//!
//! ```rust
//! #[macro_use] extern crate libfoo_macros;  // (1)
//!
//! pub use libfoo_macros::*;  // (2)
//!
//! define_invoke_proc_macro!(libfoo__invoke_proc_macro);  // (3)
//!
//! #[macro_export]
//! macro_rules! foo_stringify {  // (4)
//!     ( $( $tts: tt ) ) => {
//!         {  // (5)
//!             libfoo__invoke_proc_macro! {  // (6)
//!                 foo_internal__stringify_const!( $( $tts ) )  // (7)
//!             }
//!             STRINGIFIED  // (8)
//!         }
//!     }
//! }
//! ```
//!
//! Let’s go trough the numbered lines one by one:
//!
//! 1. `libfoo` depends on `libfoo-macros`, and imports its macros.
//! 2. Everything exported by `libfoo-macros` (which is one custom `derive`)
//!    is re-exported to users of `libfoo`.
//!    They’re not expected to use it directly,
//!    but expansion of the `foo_stringify` macro needs it.
//! 3. This macro invocation defines yet another macro, called `libfoo__invoke_proc_macro`,
//!    which is also exported.
//!    This indirection is necessary
//!    because re-exporting `macro_rules!` macros doesn’t work currently,
//!    and once again it is used by the expansion of `foo_stringify`.
//!    Again, we use a long prefix to avoid name collisions.
//! 4. Finally, we define the macro that we really want.
//!    This one has a name that users will use.
//! 5. The expansion of this macro will define some items,
//!    whose names are not hygienic in `macro_rules`.
//!    So we wrap everything in an extra `{…}` block to prevent these names for leaking.
//! 6. Here we use the macro defined in (3),
//!    which allows us to write something that look like invoking a functional procedural macro,
//!    but really uses a custom `derive`.
//!    This will define a type called `ProceduralMasqueradeDummyType`,
//!    as a placeholder to use `derive`.
//!    If `libfoo__invoke_proc_macro!` is to be used more than once,
//!    each use needs to be nested in another block
//!    so that the names of multiple dummy types don’t collide.
//! 7. In addition to the dummy type,
//!    the items returned by our procedural component are inserted here.
//!    (In this case the `STRINGIFIED` constant.)
//! 8. Finally, we write the expression that we want the macro to evaluate to.
//!    This expression can use parts of `foo_stringify`’s input,
//!    it can contain control-flow statements like `return` or `continue`,
//!    and of course refer to procedurally-defined items.
//!
//! This macro can be used in an expression context.
//! It expands to a block-expression that contains some items (as an implementation detail)
//! and ends with another expression.
//!
//! ## For users
//!
//! Users of `libfoo` don’t need to worry about any of these implementation details.
//! They can use the `foo_stringify` macro as if it were a simle `macro_rules` macro:
//!
//! ```rust
//! #[macro_use] extern crate libfoo;
//!
//! fn main() {
//!     do_something(foo_stringify!(1 + 2));
//! }
//!
//! fn do_something(_: &str) { /* ... */ }
//! ```
//!
//! # More
//!
//! To see a more complex example, look at
//! [`cssparser`’s `src/macros.rs`](https://github.com/servo/rust-cssparser/blob/master/src/macros.rs)
//! and
//! [`cssparser-macros`’s `macros/lib.rs`](https://github.com/servo/rust-cssparser/blob/master/macros/lib.rs).

/// This macro wraps `&str -> String` functions
/// in custom `derive` implementations with `#[proc_macro_derive]`.
///
/// See crate documentation for details.
#[macro_export]
macro_rules! define_proc_macros {
    (
        $(
            $( #[$attr:meta] )*
            pub fn $proc_macro_name: ident ($input: ident : &str) -> String
            $body: block
        )+
    ) => {
        $(
            $( #[$attr] )*
            #[proc_macro_derive($proc_macro_name)]
            pub fn $proc_macro_name(derive_input: ::proc_macro::TokenStream)
                                    -> ::proc_macro::TokenStream {
                fn wrapped($input: &str) -> String {
                    $body
                }

                // syn uses a huge amount of stack in debug mode.
                let derive_input_string = derive_input.to_string();
                let handle =
                    ::std::thread::Builder::new().stack_size(128 * 1024 * 1024).spawn(move || {
                        wrapped($crate::_extract_input(&derive_input_string))
                    }).unwrap();

                handle.join().unwrap().parse().unwrap()
            }
        )+
    }
}

/// Implementation detail of `define_proc_macros!`.
///
/// **This function is not part of the public API. It can change or be removed between any versions.**
#[doc(hidden)]
pub fn _extract_input(derive_input: &str) -> &str {
    let mut input = derive_input;

    for expected in &["#[allow(unused)]", "enum", "ProceduralMasqueradeDummyType", "{",
                     "Input", "=", "(0,", "stringify!", "("] {
        input = input.trim_left();
        assert!(input.starts_with(expected),
                "expected prefix {:?} not found in {:?}", expected, derive_input);
        input = &input[expected.len()..];
    }

    for expected in [")", ").0,", "}"].iter().rev() {
        input = input.trim_right();
        assert!(input.ends_with(expected),
                "expected suffix {:?} not found in {:?}", expected, derive_input);
        let end = input.len() - expected.len();
        input = &input[..end];
    }

    input
}

/// This macro expands to the definition of another macro (whose name is given as a parameter).
///
/// See crate documentation for details.
#[macro_export]
macro_rules! define_invoke_proc_macro {
    ($macro_name: ident) => {
        /// Implementation detail of other macros in this crate.
        #[doc(hidden)]
        #[macro_export]
        macro_rules! $macro_name {
            ($proc_macro_name: ident ! $paren: tt) => {
                #[derive($proc_macro_name)]
                #[allow(unused)]
                enum ProceduralMasqueradeDummyType {
                    // The magic happens here.
                    //
                    // We use an `enum` with an explicit discriminant
                    // because that is the only case where a type definition
                    // can contain a (const) expression.
                    //
                    // `(0, "foo").0` evalutes to 0, with the `"foo"` part ignored.
                    //
                    // By the time the `#[proc_macro_derive]` function
                    // implementing `#[derive($proc_macro_name)]` is called,
                    // `$paren` has already been replaced with the input of this inner macro,
                    // but `stringify!` has not been expanded yet.
                    //
                    // This how arbitrary tokens can be inserted
                    // in the input to the `#[proc_macro_derive]` function.
                    //
                    // Later, `stringify!(...)` is expanded into a string literal
                    // which is then ignored.
                    // Using `stringify!` enables passing arbitrary tokens
                    // rather than only what can be parsed as a const expression.
                    Input = (0, stringify! $paren ).0
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use super::gl_lib as gl;
use super::buffer::{ArrayBufferBinder, ElementArrayBufferBinder};
use super::program::{ProgramBinder};

pub struct Context {
    pub array_buffer: ArrayBufferBinder,
    pub element_array_buffer: ElementArrayBufferBinder,
    pub program: ProgramBinder
}

impl Context {
    pub unsafe fn current_context() -> Self {
        Context {
            array_buffer: ArrayBufferBinder,
            element_array_buffer: ElementArrayBufferBinder,
            program: ProgramBinder
        }
    }

    pub fn clear_color(&mut self, color: super::Color) {
        unsafe {
            gl::ClearColor(color.r, color.g, color.b, color.a);
        }
    }

    pub fn clear(&mut self, buffers: super::BufferBits) {
        unsafe {
            gl::Clear(buffers.bits())
        }
    }

    pub fn enable_vertex_attrib_array(&self, attrib: super::ProgramAttrib) {
        unsafe {
            gl::EnableVertexAttribArray(attrib.gl_index);
        }
    }
}

#[macro_export]
macro_rules! bind_array_buffer {
    ($gl:expr, $buffer:expr) => {
        $gl.array_buffer.bind($buffer)
    }
}

#[macro_export]
macro_rules! bind_element_array_buffer {
    ($gl:expr, $buffer:expr) => {
        $gl.element_array_buffer.bind($buffer)
    }
}

#[macro_export]
macro_rules! use_program {
    ($gl:expr, $program:expr) => {
        $gl.program.bind($program)
    }
}
<commit_msg>Add `Context.viewport()`<commit_after>use super::gl_lib as gl;
use super::gl_lib::types::*;
use super::types::{Color, Viewport, BufferBits};
use super::buffer::{ArrayBufferBinder, ElementArrayBufferBinder};
use super::program::{ProgramBinder, ProgramAttrib};

pub struct Context {
    pub array_buffer: ArrayBufferBinder,
    pub element_array_buffer: ElementArrayBufferBinder,
    pub program: ProgramBinder
}

impl Context {
    pub unsafe fn current_context() -> Self {
        Context {
            array_buffer: ArrayBufferBinder,
            element_array_buffer: ElementArrayBufferBinder,
            program: ProgramBinder
        }
    }

    pub fn clear_color(&mut self, color: Color) {
        unsafe {
            gl::ClearColor(color.r, color.g, color.b, color.a);
        }
    }

    pub fn clear(&mut self, buffers: BufferBits) {
        unsafe {
            gl::Clear(buffers.bits())
        }
    }

    pub fn enable_vertex_attrib_array(&self, attrib: ProgramAttrib) {
        unsafe {
            gl::EnableVertexAttribArray(attrib.gl_index);
        }
    }

    pub fn viewport(&self, viewport: Viewport) {
        unsafe {
            gl::Viewport(viewport.x as GLint,
                         viewport.y as GLint,
                         viewport.width as GLsizei,
                         viewport.height as GLsizei);
        }
    }
}

#[macro_export]
macro_rules! bind_array_buffer {
    ($gl:expr, $buffer:expr) => {
        $gl.array_buffer.bind($buffer)
    }
}

#[macro_export]
macro_rules! bind_element_array_buffer {
    ($gl:expr, $buffer:expr) => {
        $gl.element_array_buffer.bind($buffer)
    }
}

#[macro_export]
macro_rules! use_program {
    ($gl:expr, $program:expr) => {
        $gl.program.bind($program)
    }
}
<|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/. */

//! this is context class to use autograd.

extern crate std;

use super::float::FloatCratePrivate;

// TODO #[inline] where appropriate.

pub trait Context<InternalFloat>: ContextCratePrivate<InternalFloat> + std::marker::Sized where InternalFloat: std::num::Float {
    // public functions

    fn new_variable(&self, value: InternalFloat) -> super::float::Float<InternalFloat, Self> {
        FloatCratePrivate::new(value, <Self as ContextModulePrivate<InternalFloat>>::get_new_variable_index())
    }

    fn differentiate(&self, float: super::float::Float<InternalFloat, Self>) {
        // TODO The current implementation is not performant and dirty.
        unsafe {
            assert!(*<Self as ContextModulePrivate<InternalFloat>>::get_recorded_variables_count() <= self.capacity(),
                "There are more recorded variables, {}, than its capacity, {}. Memory is corrupted. Please consider using bigger capacity.",
                *<Self as ContextModulePrivate<InternalFloat>>::get_recorded_variables_count(), self.capacity());

            for i in (0..(*<Self as ContextModulePrivate<InternalFloat>>::get_recorded_variables_count())) {
                *<Self as ContextModulePrivate<InternalFloat>>::get_result_derivatives().offset(i as isize) = std::num::Float::zero();
            }

            *<Self as ContextModulePrivate<InternalFloat>>::get_result_derivatives().offset(float.float_get_index() as isize) = std::num::Float::one();
            for i in (0..(*<Self as ContextModulePrivate<InternalFloat>>::get_recorded_entries_count())).rev() {
                let lhs_index = *<Self as ContextModulePrivate<InternalFloat>>::get_lhs_indices().offset(i as isize);
                let rhs_index = *<Self as ContextModulePrivate<InternalFloat>>::get_rhs_indices().offset(i as isize);
                *<Self as ContextModulePrivate<InternalFloat>>::get_result_derivatives().offset(rhs_index as isize) =
                    *<Self as ContextModulePrivate<InternalFloat>>::get_result_derivatives().offset(rhs_index as isize)
                    + (*<Self as ContextModulePrivate<InternalFloat>>::get_result_derivatives().offset(lhs_index as isize)
                       * *<Self as ContextModulePrivate<InternalFloat>>::get_adjoints().offset(i as isize));
            }
        }
    }

    fn get_derivative(&self, float: super::float::Float<InternalFloat, Self>) -> InternalFloat {
        let float_index_offset = float.float_get_index() as isize;
        unsafe {
            *<Self as ContextModulePrivate<InternalFloat>>::get_result_derivatives().offset(float_index_offset)
        }
    }
}

pub trait ContextCratePrivate<InternalFloat>: ContextModulePrivate<InternalFloat> where InternalFloat: std::num::Float {
    fn unary_operation(adjoint: InternalFloat, rhs_index: usize) -> usize {
        let lhs_index = <Self as ContextModulePrivate<InternalFloat>>::get_new_variable_index();
        let recorded_entries_count_offset = <Self as ContextModulePrivate<InternalFloat>>::get_new_entry_index() as isize;
        unsafe {
            *<Self as ContextModulePrivate<InternalFloat>>::get_adjoints().offset(recorded_entries_count_offset) = adjoint;
            *<Self as ContextModulePrivate<InternalFloat>>::get_lhs_indices().offset(recorded_entries_count_offset) = lhs_index;
            *<Self as ContextModulePrivate<InternalFloat>>::get_rhs_indices().offset(recorded_entries_count_offset) = rhs_index;
        }
        lhs_index
    }

    fn binary_operation(adjoints: &[InternalFloat; 2],
                        rhs_indices: &[usize; 2]) -> usize {
        let lhs_index = <Self as ContextModulePrivate<InternalFloat>>::get_new_variable_index();
        let recorded_entries_count_offset_1 = <Self as ContextModulePrivate<InternalFloat>>::get_new_entry_index() as isize;
        let recorded_entries_count_offset_2 = <Self as ContextModulePrivate<InternalFloat>>::get_new_entry_index() as isize;

        unsafe {
            // TODO is indexing inefficient?
            *<Self as ContextModulePrivate<InternalFloat>>::get_adjoints().offset(recorded_entries_count_offset_1) = adjoints[0];
            *<Self as ContextModulePrivate<InternalFloat>>::get_lhs_indices().offset(recorded_entries_count_offset_1) = lhs_index;
            *<Self as ContextModulePrivate<InternalFloat>>::get_rhs_indices().offset(recorded_entries_count_offset_1) = rhs_indices[0];

            *<Self as ContextModulePrivate<InternalFloat>>::get_adjoints().offset(recorded_entries_count_offset_2) = adjoints[1];
            *<Self as ContextModulePrivate<InternalFloat>>::get_lhs_indices().offset(recorded_entries_count_offset_2) = lhs_index;
            *<Self as ContextModulePrivate<InternalFloat>>::get_rhs_indices().offset(recorded_entries_count_offset_2) = rhs_indices[1];
        }
        lhs_index
    }
}

pub trait ContextModulePrivate<InternalFloat> where InternalFloat: std::num::Float {
    fn get_new_variable_index() -> usize {
        let count = <Self as ContextModulePrivate<InternalFloat>>::get_recorded_variables_count();
        let index = *count;
        *count += 1;
        index
    }

    fn get_new_entry_index() -> usize {
        let count = <Self as ContextModulePrivate<InternalFloat>>::get_recorded_entries_count();
        let index = *count;
        *count += 1;
        index
    }

    fn capacity(&self) -> usize;

    fn get_recorded_variables_count() -> &'static mut usize;
    fn get_recorded_entries_count() -> &'static mut usize;
    // TODO use 'static lifetime instead?
    fn get_adjoints<'a>() -> &'a mut*mut InternalFloat;
    fn get_lhs_indices<'a>() -> &'a mut*mut usize;
    fn get_rhs_indices<'a>() -> &'a mut*mut usize;
    fn get_result_derivatives<'a>() -> &'a mut*mut InternalFloat;
}

#[macro_export]
macro_rules! new_autograd_context {
    ($InternalFloat:ty, $capacity:expr) => (
        {
            struct ContextImpl {
                capacity: usize,
                #[allow(dead_code)] // mutex_guard is active during its scope. No need to use directly.
                mutex_guard: std::sync::MutexGuard<'static ()>,
            }

            impl $crate::Context<$InternalFloat> for ContextImpl {
            }

            impl $crate::ContextCratePrivate<$InternalFloat> for ContextImpl {
            }

            impl $crate::ContextModulePrivate<$InternalFloat> for ContextImpl {
                fn capacity(&self) -> usize {
                    self.capacity
                }

                fn get_recorded_variables_count() -> &'static mut usize {
                    #[thread_local]
                    static mut ptr : usize = 0;
                    unsafe {
                        &mut ptr
                    }
                }
                fn get_recorded_entries_count() -> &'static mut usize {
                    #[thread_local]
                    static mut ptr : usize = 0;
                    unsafe {
                        &mut ptr
                    }
                }
                fn get_adjoints<'a>() -> &'a mut*mut $InternalFloat {
                    #[thread_local]
                    static mut ptr : *mut $InternalFloat = 0 as *mut $InternalFloat;
                    unsafe {
                        &mut ptr
                    }
                }
                fn get_lhs_indices<'a>() -> &'a mut*mut usize {
                    #[thread_local]
                    static mut ptr : *mut usize = 0 as *mut usize;
                    unsafe {
                        &mut ptr
                    }
                }
                fn get_rhs_indices<'a>() -> &'a mut*mut usize{
                    #[thread_local]
                    static mut ptr : *mut usize = 0 as *mut usize;
                    unsafe {
                        &mut ptr
                    }
                }

                fn get_result_derivatives<'a>() -> &'a mut*mut $InternalFloat {
                    #[thread_local]
                    static mut ptr : *mut $InternalFloat = 0 as *mut $InternalFloat;
                    unsafe {
                        &mut ptr
                    }
                }
            }

            impl ContextImpl {
                fn new(capacity: usize) -> Self {
                    let context;

                    #[thread_local]
                    static LOCK : std::sync::StaticMutex = std::sync::MUTEX_INIT;
                    match LOCK.try_lock() {
                        Ok(guard) => context = ContextImpl{capacity: capacity, mutex_guard: guard},
                        Err(std::sync::TryLockError::WouldBlock) => panic!("This Context instance is in use now. Note that a Context instance is allowed per construction location and per thread. Consequently, it cannot be recursively constructed unless it is destructed. This is a limitation caused by the thread local static variables usages in the current implementation."),
                        Err(std::sync::TryLockError::Poisoned(poison_error)) => panic!("{:?}", poison_error),
                    }

                    // TODO use checked_mul?
                    //      example : let usize_size = capacity.checked_mul(std::mem::size_of::<usize>()).expect("capacity overflow");
                    let usize_size = capacity * std::mem::size_of::<usize>();
                    let t_size = capacity * std::mem::size_of::<$InternalFloat>();
                    // std::rt::heap::allocate(t_size, mem::min_align_of::<InternalFloat>())

                    unsafe {
                        *<Self as $crate::ContextModulePrivate<$InternalFloat>>::get_recorded_variables_count() = 0;
                        *<Self as $crate::ContextModulePrivate<$InternalFloat>>::get_recorded_entries_count() = 0;
                        *<Self as $crate::ContextModulePrivate<$InternalFloat>>::get_adjoints() = std::rt::heap::allocate(t_size, std::mem::align_of::<$InternalFloat>()) as *mut $InternalFloat;
                        *<Self as $crate::ContextModulePrivate<$InternalFloat>>::get_lhs_indices() = std::rt::heap::allocate(usize_size, std::mem::align_of::<usize>()) as *mut usize;
                        *<Self as $crate::ContextModulePrivate<$InternalFloat>>::get_rhs_indices() = std::rt::heap::allocate(usize_size, std::mem::align_of::<usize>()) as *mut usize;
                        // TODO we don't have to allocate get_result_derivatives now, isn't it?
                        *<Self as $crate::ContextModulePrivate<$InternalFloat>>::get_result_derivatives() = std::rt::heap::allocate(t_size, std::mem::align_of::<$InternalFloat>()) as *mut $InternalFloat;
                    }
                    context
                }
            }

            impl std::ops::Drop for ContextImpl {
                fn drop(&mut self) {
                    // TODO Ideally we should detect overflow at the time it overflows. Similar to stack overflow problem. mprotect?
                    assert!(*<Self as $crate::ContextModulePrivate<$InternalFloat>>::get_recorded_variables_count() <= ($crate::ContextModulePrivate::<$InternalFloat>::capacity(self)),
                        "There are more recorded variables, {}, than its capacity, {}. Memory is corrupted. Please consider using bigger capacity.",
                        *<Self as $crate::ContextModulePrivate<$InternalFloat>>::get_recorded_variables_count(), ($crate::ContextModulePrivate::<$InternalFloat>::capacity(self)));

                    // TODO Do we want to reset these?
                    // *Context::<$InternalFloat>::get_recorded_variables_count(None::<Self>) = 0;
                    // *Context::<$InternalFloat>::get_adjoints(None::<Self>) = 0;

                    let usize_size = self.capacity * std::mem::size_of::<usize>();
                    let t_size = self.capacity * std::mem::size_of::<$InternalFloat>();

                    unsafe {
                        std::rt::heap::deallocate(*<Self as $crate::ContextModulePrivate<$InternalFloat>>::get_adjoints() as *mut u8, t_size, std::mem::align_of::<$InternalFloat>());
                        std::rt::heap::deallocate(*<Self as $crate::ContextModulePrivate<$InternalFloat>>::get_lhs_indices() as *mut u8, usize_size, std::mem::align_of::<usize>());
                        std::rt::heap::deallocate(*<Self as $crate::ContextModulePrivate<$InternalFloat>>::get_rhs_indices() as *mut u8, usize_size, std::mem::align_of::<usize>());
                        std::rt::heap::deallocate(*<Self as $crate::ContextModulePrivate<$InternalFloat>>::get_result_derivatives() as *mut u8, t_size, std::mem::align_of::<$InternalFloat>());
                    }
                }
            }

            ContextImpl::new($capacity)
        }
    )
}
<commit_msg>Add _ to mutex variables names instead of #[allow(dead_code)].<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/. */

//! this is context class to use autograd.

extern crate std;

use super::float::FloatCratePrivate;

// TODO #[inline] where appropriate.

pub trait Context<InternalFloat>: ContextCratePrivate<InternalFloat> + std::marker::Sized where InternalFloat: std::num::Float {
    // public functions

    fn new_variable(&self, value: InternalFloat) -> super::float::Float<InternalFloat, Self> {
        FloatCratePrivate::new(value, <Self as ContextModulePrivate<InternalFloat>>::get_new_variable_index())
    }

    fn differentiate(&self, float: super::float::Float<InternalFloat, Self>) {
        // TODO The current implementation is not performant and dirty.
        unsafe {
            assert!(*<Self as ContextModulePrivate<InternalFloat>>::get_recorded_variables_count() <= self.capacity(),
                "There are more recorded variables, {}, than its capacity, {}. Memory is corrupted. Please consider using bigger capacity.",
                *<Self as ContextModulePrivate<InternalFloat>>::get_recorded_variables_count(), self.capacity());

            for i in (0..(*<Self as ContextModulePrivate<InternalFloat>>::get_recorded_variables_count())) {
                *<Self as ContextModulePrivate<InternalFloat>>::get_result_derivatives().offset(i as isize) = std::num::Float::zero();
            }

            *<Self as ContextModulePrivate<InternalFloat>>::get_result_derivatives().offset(float.float_get_index() as isize) = std::num::Float::one();
            for i in (0..(*<Self as ContextModulePrivate<InternalFloat>>::get_recorded_entries_count())).rev() {
                let lhs_index = *<Self as ContextModulePrivate<InternalFloat>>::get_lhs_indices().offset(i as isize);
                let rhs_index = *<Self as ContextModulePrivate<InternalFloat>>::get_rhs_indices().offset(i as isize);
                *<Self as ContextModulePrivate<InternalFloat>>::get_result_derivatives().offset(rhs_index as isize) =
                    *<Self as ContextModulePrivate<InternalFloat>>::get_result_derivatives().offset(rhs_index as isize)
                    + (*<Self as ContextModulePrivate<InternalFloat>>::get_result_derivatives().offset(lhs_index as isize)
                       * *<Self as ContextModulePrivate<InternalFloat>>::get_adjoints().offset(i as isize));
            }
        }
    }

    fn get_derivative(&self, float: super::float::Float<InternalFloat, Self>) -> InternalFloat {
        let float_index_offset = float.float_get_index() as isize;
        unsafe {
            *<Self as ContextModulePrivate<InternalFloat>>::get_result_derivatives().offset(float_index_offset)
        }
    }
}

pub trait ContextCratePrivate<InternalFloat>: ContextModulePrivate<InternalFloat> where InternalFloat: std::num::Float {
    fn unary_operation(adjoint: InternalFloat, rhs_index: usize) -> usize {
        let lhs_index = <Self as ContextModulePrivate<InternalFloat>>::get_new_variable_index();
        let recorded_entries_count_offset = <Self as ContextModulePrivate<InternalFloat>>::get_new_entry_index() as isize;
        unsafe {
            *<Self as ContextModulePrivate<InternalFloat>>::get_adjoints().offset(recorded_entries_count_offset) = adjoint;
            *<Self as ContextModulePrivate<InternalFloat>>::get_lhs_indices().offset(recorded_entries_count_offset) = lhs_index;
            *<Self as ContextModulePrivate<InternalFloat>>::get_rhs_indices().offset(recorded_entries_count_offset) = rhs_index;
        }
        lhs_index
    }

    fn binary_operation(adjoints: &[InternalFloat; 2],
                        rhs_indices: &[usize; 2]) -> usize {
        let lhs_index = <Self as ContextModulePrivate<InternalFloat>>::get_new_variable_index();
        let recorded_entries_count_offset_1 = <Self as ContextModulePrivate<InternalFloat>>::get_new_entry_index() as isize;
        let recorded_entries_count_offset_2 = <Self as ContextModulePrivate<InternalFloat>>::get_new_entry_index() as isize;

        unsafe {
            // TODO is indexing inefficient?
            *<Self as ContextModulePrivate<InternalFloat>>::get_adjoints().offset(recorded_entries_count_offset_1) = adjoints[0];
            *<Self as ContextModulePrivate<InternalFloat>>::get_lhs_indices().offset(recorded_entries_count_offset_1) = lhs_index;
            *<Self as ContextModulePrivate<InternalFloat>>::get_rhs_indices().offset(recorded_entries_count_offset_1) = rhs_indices[0];

            *<Self as ContextModulePrivate<InternalFloat>>::get_adjoints().offset(recorded_entries_count_offset_2) = adjoints[1];
            *<Self as ContextModulePrivate<InternalFloat>>::get_lhs_indices().offset(recorded_entries_count_offset_2) = lhs_index;
            *<Self as ContextModulePrivate<InternalFloat>>::get_rhs_indices().offset(recorded_entries_count_offset_2) = rhs_indices[1];
        }
        lhs_index
    }
}

pub trait ContextModulePrivate<InternalFloat> where InternalFloat: std::num::Float {
    fn get_new_variable_index() -> usize {
        let count = <Self as ContextModulePrivate<InternalFloat>>::get_recorded_variables_count();
        let index = *count;
        *count += 1;
        index
    }

    fn get_new_entry_index() -> usize {
        let count = <Self as ContextModulePrivate<InternalFloat>>::get_recorded_entries_count();
        let index = *count;
        *count += 1;
        index
    }

    fn capacity(&self) -> usize;

    fn get_recorded_variables_count() -> &'static mut usize;
    fn get_recorded_entries_count() -> &'static mut usize;
    // TODO use 'static lifetime instead?
    fn get_adjoints<'a>() -> &'a mut*mut InternalFloat;
    fn get_lhs_indices<'a>() -> &'a mut*mut usize;
    fn get_rhs_indices<'a>() -> &'a mut*mut usize;
    fn get_result_derivatives<'a>() -> &'a mut*mut InternalFloat;
}

#[macro_export]
macro_rules! new_autograd_context {
    ($InternalFloat:ty, $capacity:expr) => (
        {
            struct ContextImpl {
                capacity: usize,
                _mutex_guard: std::sync::MutexGuard<'static ()>,
            }

            impl $crate::Context<$InternalFloat> for ContextImpl {
            }

            impl $crate::ContextCratePrivate<$InternalFloat> for ContextImpl {
            }

            impl $crate::ContextModulePrivate<$InternalFloat> for ContextImpl {
                fn capacity(&self) -> usize {
                    self.capacity
                }

                fn get_recorded_variables_count() -> &'static mut usize {
                    #[thread_local]
                    static mut ptr : usize = 0;
                    unsafe {
                        &mut ptr
                    }
                }
                fn get_recorded_entries_count() -> &'static mut usize {
                    #[thread_local]
                    static mut ptr : usize = 0;
                    unsafe {
                        &mut ptr
                    }
                }
                fn get_adjoints<'a>() -> &'a mut*mut $InternalFloat {
                    #[thread_local]
                    static mut ptr : *mut $InternalFloat = 0 as *mut $InternalFloat;
                    unsafe {
                        &mut ptr
                    }
                }
                fn get_lhs_indices<'a>() -> &'a mut*mut usize {
                    #[thread_local]
                    static mut ptr : *mut usize = 0 as *mut usize;
                    unsafe {
                        &mut ptr
                    }
                }
                fn get_rhs_indices<'a>() -> &'a mut*mut usize{
                    #[thread_local]
                    static mut ptr : *mut usize = 0 as *mut usize;
                    unsafe {
                        &mut ptr
                    }
                }

                fn get_result_derivatives<'a>() -> &'a mut*mut $InternalFloat {
                    #[thread_local]
                    static mut ptr : *mut $InternalFloat = 0 as *mut $InternalFloat;
                    unsafe {
                        &mut ptr
                    }
                }
            }

            impl ContextImpl {
                fn new(capacity: usize) -> Self {
                    let context;

                    #[thread_local]
                    static _MUTEX : std::sync::StaticMutex = std::sync::MUTEX_INIT;
                    match _MUTEX.try_lock() {
                        Ok(mutex_guard) => context = ContextImpl{capacity: capacity, _mutex_guard: mutex_guard},
                        Err(std::sync::TryLockError::WouldBlock) => panic!("This Context instance is in use now. Note that a Context instance is allowed per construction location and per thread. Consequently, it cannot be recursively constructed unless it is destructed. This is a limitation caused by the thread local static variables usages in the current implementation."),
                        Err(std::sync::TryLockError::Poisoned(poison_error)) => panic!("{:?}", poison_error),
                    }

                    // TODO use checked_mul?
                    //      example : let usize_size = capacity.checked_mul(std::mem::size_of::<usize>()).expect("capacity overflow");
                    let usize_size = capacity * std::mem::size_of::<usize>();
                    let t_size = capacity * std::mem::size_of::<$InternalFloat>();
                    // std::rt::heap::allocate(t_size, mem::min_align_of::<InternalFloat>())

                    unsafe {
                        *<Self as $crate::ContextModulePrivate<$InternalFloat>>::get_recorded_variables_count() = 0;
                        *<Self as $crate::ContextModulePrivate<$InternalFloat>>::get_recorded_entries_count() = 0;
                        *<Self as $crate::ContextModulePrivate<$InternalFloat>>::get_adjoints() = std::rt::heap::allocate(t_size, std::mem::align_of::<$InternalFloat>()) as *mut $InternalFloat;
                        *<Self as $crate::ContextModulePrivate<$InternalFloat>>::get_lhs_indices() = std::rt::heap::allocate(usize_size, std::mem::align_of::<usize>()) as *mut usize;
                        *<Self as $crate::ContextModulePrivate<$InternalFloat>>::get_rhs_indices() = std::rt::heap::allocate(usize_size, std::mem::align_of::<usize>()) as *mut usize;
                        // TODO we don't have to allocate get_result_derivatives now, isn't it?
                        *<Self as $crate::ContextModulePrivate<$InternalFloat>>::get_result_derivatives() = std::rt::heap::allocate(t_size, std::mem::align_of::<$InternalFloat>()) as *mut $InternalFloat;
                    }
                    context
                }
            }

            impl std::ops::Drop for ContextImpl {
                fn drop(&mut self) {
                    // TODO Ideally we should detect overflow at the time it overflows. Similar to stack overflow problem. mprotect?
                    assert!(*<Self as $crate::ContextModulePrivate<$InternalFloat>>::get_recorded_variables_count() <= ($crate::ContextModulePrivate::<$InternalFloat>::capacity(self)),
                        "There are more recorded variables, {}, than its capacity, {}. Memory is corrupted. Please consider using bigger capacity.",
                        *<Self as $crate::ContextModulePrivate<$InternalFloat>>::get_recorded_variables_count(), ($crate::ContextModulePrivate::<$InternalFloat>::capacity(self)));

                    // TODO Do we want to reset these?
                    // *Context::<$InternalFloat>::get_recorded_variables_count(None::<Self>) = 0;
                    // *Context::<$InternalFloat>::get_adjoints(None::<Self>) = 0;

                    let usize_size = self.capacity * std::mem::size_of::<usize>();
                    let t_size = self.capacity * std::mem::size_of::<$InternalFloat>();

                    unsafe {
                        std::rt::heap::deallocate(*<Self as $crate::ContextModulePrivate<$InternalFloat>>::get_adjoints() as *mut u8, t_size, std::mem::align_of::<$InternalFloat>());
                        std::rt::heap::deallocate(*<Self as $crate::ContextModulePrivate<$InternalFloat>>::get_lhs_indices() as *mut u8, usize_size, std::mem::align_of::<usize>());
                        std::rt::heap::deallocate(*<Self as $crate::ContextModulePrivate<$InternalFloat>>::get_rhs_indices() as *mut u8, usize_size, std::mem::align_of::<usize>());
                        std::rt::heap::deallocate(*<Self as $crate::ContextModulePrivate<$InternalFloat>>::get_result_derivatives() as *mut u8, t_size, std::mem::align_of::<$InternalFloat>());
                    }
                }
            }

            ContextImpl::new($capacity)
        }
    )
}
<|endoftext|>


<commit_before><commit_msg>Fix double free (unsafe rust, yay!)<commit_after><|endoftext|>


<commit_before>use std::default::Default;

use ast::Expr;
use ast::ExprType::*;
use ast::Function;
use ast::Stmt;
use ast::StmtType::*;

pub trait Visitor<'a> : Sized {
    type Returns : Default;

    fn visit_fct(&mut self, fct: &'a Function) -> Self::Returns {
        self.visit_stmt(&fct.block)
    }

    fn visit_expr(&mut self, e: &Expr) -> Self::Returns {
        walk_expr(self, e)
    }

    fn visit_stmt(&mut self, s: &Stmt) -> Self::Returns {
        walk_stmt(self, s)
    }
}

pub fn walk_stmt<'v, V: Visitor<'v>>(v: &mut V, s: &Stmt) -> V::Returns {
    match s.node {
        StmtVar(_, _, ref expr) => {
            if let Some(ref e) = *expr {
                v.visit_expr(e);
            }
        }

        StmtWhile(ref cond, ref block) => {
            v.visit_expr(cond);
            v.visit_stmt(block);
        }

        StmtLoop(ref block) => {
            v.visit_stmt(block);
        }

        StmtIf(ref cond, ref tblock, ref eblock) => {
            v.visit_expr(cond);
            v.visit_stmt(tblock);

            if let Some(ref b) = *eblock {
                v.visit_stmt(b);
            }
        }

        StmtExpr(ref e) => {
            v.visit_expr(e);
        }

        StmtBlock(ref stmts) => {
            for stmt in stmts {
                v.visit_stmt(stmt);
            }
        }

        StmtReturn(ref expr) => {
            if let Some(ref e) = *expr {
                v.visit_expr(e);
            }
        }

        StmtBreak => { }
        StmtContinue => { }
    }

    Default::default()
}

pub fn walk_expr<'v, V: Visitor<'v>>(v: &mut V, e: &Expr) -> V::Returns {
    match e.node {
        ExprUn(_, ref op) => {
            v.visit_expr(op);
        }

        ExprBin(_, ref left, ref right) => {
            v.visit_expr(left);
            v.visit_expr(right);
        }

        ExprAssign(ref left, ref right) => {
            v.visit_expr(left);
            v.visit_expr(right);
        }

        ExprLitInt(_) => {}
        ExprLitStr(_) => {}
        ExprLitBool(_) => {}
        ExprIdent(_) => {}
    }

    Default::default()
}

<commit_msg>removed visit_fct for visitor<commit_after>use std::default::Default;

use ast::Expr;
use ast::ExprType::*;
use ast::Function;
use ast::Stmt;
use ast::StmtType::*;

pub trait Visitor<'a> : Sized {
    type Returns : Default;

    fn visit_expr(&mut self, e: &Expr) -> Self::Returns {
        walk_expr(self, e)
    }

    fn visit_stmt(&mut self, s: &Stmt) -> Self::Returns {
        walk_stmt(self, s)
    }
}

pub fn walk_stmt<'v, V: Visitor<'v>>(v: &mut V, s: &Stmt) -> V::Returns {
    match s.node {
        StmtVar(_, _, ref expr) => {
            if let Some(ref e) = *expr {
                v.visit_expr(e);
            }
        }

        StmtWhile(ref cond, ref block) => {
            v.visit_expr(cond);
            v.visit_stmt(block);
        }

        StmtLoop(ref block) => {
            v.visit_stmt(block);
        }

        StmtIf(ref cond, ref tblock, ref eblock) => {
            v.visit_expr(cond);
            v.visit_stmt(tblock);

            if let Some(ref b) = *eblock {
                v.visit_stmt(b);
            }
        }

        StmtExpr(ref e) => {
            v.visit_expr(e);
        }

        StmtBlock(ref stmts) => {
            for stmt in stmts {
                v.visit_stmt(stmt);
            }
        }

        StmtReturn(ref expr) => {
            if let Some(ref e) = *expr {
                v.visit_expr(e);
            }
        }

        StmtBreak => { }
        StmtContinue => { }
    }

    Default::default()
}

pub fn walk_expr<'v, V: Visitor<'v>>(v: &mut V, e: &Expr) -> V::Returns {
    match e.node {
        ExprUn(_, ref op) => {
            v.visit_expr(op);
        }

        ExprBin(_, ref left, ref right) => {
            v.visit_expr(left);
            v.visit_expr(right);
        }

        ExprAssign(ref left, ref right) => {
            v.visit_expr(left);
            v.visit_expr(right);
        }

        ExprLitInt(_) => {}
        ExprLitStr(_) => {}
        ExprLitBool(_) => {}
        ExprIdent(_) => {}
    }

    Default::default()
}

<|endoftext|>