<commit_before>//! TODO Documentation

use std::{panic, ptr};
use std::ffi::CStr;
use std::rc::{Rc, Weak};
use std::sync::atomic::{AtomicBool, Ordering};

use libc::c_float;
use wayland_sys::server::WAYLAND_SERVER_HANDLE;
use wlroots_sys::{wl_list, wl_output_transform, wlr_output, wlr_output_effective_resolution,
                  wlr_output_events, wlr_output_make_current, wlr_output_mode,
                  wlr_output_set_mode, wlr_output_set_transform, wlr_output_swap_buffers};

use super::output_layout::OutputLayoutHandle;
use super::output_mode::OutputMode;
use errors::{UpgradeHandleErr, UpgradeHandleResult};
use utils::c_to_rust_string;

use Surface;

struct OutputState {
    handle: Weak<AtomicBool>,
    layout_handle: Option<OutputLayoutHandle>
}

#[derive(Debug)]
pub struct Output {
    /// The structure that ensures weak handles to this structure are still alive.
    ///
    /// They contain weak handles, and will safely not use dead memory when this
    /// is freed by wlroots.
    ///
    /// If this is `None`, then this is from an upgraded `OutputHandle`, and
    /// the operations are **unchecked**.
    /// This is means safe operations might fail, but only if you use the unsafe
    /// marked function `upgrade` on a `OutputHandle`.
    liveliness: Option<Rc<AtomicBool>>,
    /// The output ptr that refers to this `Output`
    output: *mut wlr_output
}

/// A wrapper around a wlr_output.
#[derive(Debug)]
pub struct OutputHandle {
    /// The Rc that ensures that this handle is still alive.
    ///
    /// When wlroots deallocates the pointer associated with this handle,
    /// this can no longer be used.
    handle: Weak<AtomicBool>,
    /// The output ptr that refers to this `Output`
    output: *mut wlr_output
}

impl Output {
    /// Just like `std::clone::Clone`, but unsafe.
    ///
    /// # Unsafety
    /// You can create a reference leak using this method very easily,
    /// and it could make it so that weak handles to an output are dangling.
    ///
    /// This exists due to an issue in output_manager.rs that might be fixed
    /// with NLL, so if this is no longer necessary it should be removed asap.
    pub(crate) unsafe fn clone(&self) -> Output {
        Output { liveliness: self.liveliness.clone(),
                 output: self.output }
    }

    /// Makes a new `Output` from a `wlr_output`.
    ///
    /// # Safety
    /// This creates a totally new Output (e.g with its own reference count)
    /// so only do this once per `wlr_output`!
    pub(crate) unsafe fn new(output: *mut wlr_output) -> Self {
        (*output).data = ptr::null_mut();
        let liveliness = Rc::new(AtomicBool::new(false));
        let handle = Rc::downgrade(&liveliness);
        let state = Box::new(OutputState { handle,
                                           layout_handle: None });
        (*output).data = Box::into_raw(state) as *mut _;
        Output { liveliness: Some(liveliness),
                 output }
    }

    pub(crate) unsafe fn set_output_layout(&mut self, layout_handle: Option<OutputLayoutHandle>) {
        self.remove_from_output_layout();
        let user_data = self.user_data();
        if user_data.is_null() {
            return
        }
        let mut data = Box::from_raw(user_data);
        data.layout_handle = layout_handle;
        (*self.output).data = Box::into_raw(data) as *mut _;
    }

    unsafe fn user_data(&mut self) -> *mut OutputState {
        (*self.output).data as *mut _
    }

    /// Used to clear the pointer to an OutputLayout when the OutputLayout
    /// removes this Output from its listing.
    pub(crate) unsafe fn clear_output_layout_data(&mut self) {
        let user_data = self.user_data();
        if user_data.is_null() {
            return
        }
        let mut data = Box::from_raw(user_data);
        data.layout_handle = None;
        (*self.output).data = Box::into_raw(data) as *mut _;
    }

    /// Remove this Output from an OutputLayout, if it is part of an
    /// OutputLayout.
    pub(crate) unsafe fn remove_from_output_layout(&mut self) {
        let output_data = self.user_data();
        if output_data.is_null() {
            return
        }
        // Remove output from previous output layout.
        if let Some(mut layout_handle) = (*output_data).layout_handle.take() {
            match layout_handle.run(|layout| layout.remove(self)) {
                Ok(_) | Err(UpgradeHandleErr::AlreadyDropped) => self.clear_output_layout_data(),
                Err(UpgradeHandleErr::AlreadyBorrowed) => {
                    panic!("Could not add OutputLayout to Output user data!")
                }
            }
        }
    }

    /// Gets the OutputLayout this Output is a part of, if it is part
    /// of an OutputLayout.
    ///
    /// # Safety
    /// Note that this isn't exposed to user space, as they could easily
    /// create two mutable pointers to the same structure. We keep it internally
    /// though because we use it during the cleanup process.
    pub(crate) unsafe fn layout(&mut self) -> Option<OutputLayoutHandle> {
        let data = self.user_data();
        if data.is_null() {
            None
        } else {
            (*data).layout_handle.clone()
        }
    }

    /// Sets the best modesetting for an output.
    ///
    /// NOTE You _cannot_ call this when the output will be removed.
    ///
    /// I'm still marking it as safe though because we protect against that
    /// action in the output destruction callback.
    pub fn choose_best_mode(&mut self) {
        unsafe {
            let length = ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_list_length, self.modes() as _);
            if length > 0 {
                // TODO Better logging
                wlr_log!(L_DEBUG, "output added {:?}", self);
                let first_mode_ptr: *mut wlr_output_mode;
                first_mode_ptr = container_of!(&mut (*(*self.modes()).prev) as *mut _,
                                               wlr_output_mode,
                                               link);
                wlr_output_set_mode(self.as_ptr(), first_mode_ptr);
            }
        }
    }

    /// Gets the name of the output in UTF-8.
    pub fn name(&self) -> String {
        unsafe {
            CStr::from_ptr((*self.output).name.as_ptr()).to_string_lossy()
                                                        .into_owned()
        }
    }

    /// Gets the make of the output in UTF-8.
    pub fn make(&self) -> String {
        unsafe {
            c_to_rust_string((*self.output).make.as_ptr()).expect("Could not parse make as UTF-8")
        }
    }

    /// Gets the model of the output in UTF-8.
    pub fn model(&self) -> String {
        unsafe {
            c_to_rust_string((*self.output).model.as_ptr()).expect("Could not parse model as UTF-8")
        }
    }

    /// Gets the serial of the output in UTF-8.
    pub fn serial(&self) -> String {
        unsafe {
            c_to_rust_string((*self.output).serial.as_ptr()).expect("Could not parse serial as \
                                                                     UTF-8")
        }
    }

    /// Determines if the output is enabled or not.
    pub fn enabled(&self) -> bool {
        unsafe { (*self.output).enabled }
    }

    /// Get the scale of the output
    pub fn scale(&self) -> c_float {
        unsafe { (*self.output).scale }
    }

    /// Determines if the output should have its buffers swapped or not.
    pub fn needs_swap(&self) -> bool {
        unsafe { (*self.output).needs_swap }
    }

    pub fn current_mode(&self) -> Option<OutputMode> {
        unsafe {
            if (*self.output).current_mode.is_null() {
                None
            } else {
                Some(OutputMode::new((*self.output).current_mode))
            }
        }
    }

    pub fn fullscreen_surface(&self) -> Option<Surface> {
        unsafe {
            if (*self.output).fullscreen_surface.is_null() {
                None
            } else {
                Some(Surface::from_ptr((*self.output).fullscreen_surface))
            }
        }
    }

    /// Gets the output position in layout space reported to clients.
    pub fn layout_space_pos(&self) -> (i32, i32) {
        unsafe { ((*self.output).lx, (*self.output).ly) }
    }

    pub fn make_current(&mut self) {
        unsafe { wlr_output_make_current(self.output) }
    }

    pub fn swap_buffers(&mut self) {
        unsafe { wlr_output_swap_buffers(self.output) }
    }

    /// Get the dimensions of the output as (width, height).
    pub fn dimensions(&self) -> (i32, i32) {
        unsafe { ((*self.output).width, (*self.output).height) }
    }

    /// Get the physical dimensions of the output as (width, height).
    pub fn physical_dimensions(&self) -> (i32, i32) {
        unsafe { ((*self.output).phys_width, (*self.output).phys_height) }
    }

    pub fn effective_resolution(&self) -> (i32, i32) {
        unsafe {
            let (mut x, mut y) = (0, 0);
            wlr_output_effective_resolution(self.output, &mut x, &mut y);
            (x, y)
        }
    }

    pub fn transform_matrix(&self) -> [c_float; 16] {
        unsafe { (*self.output).transform_matrix }
    }

    pub fn transform(&mut self, transform: wl_output_transform) {
        unsafe {
            wlr_output_set_transform(self.output, transform);
        }
    }

    /// TODO Make safe
    pub unsafe fn modes(&self) -> *mut wl_list {
        &mut (*self.output).modes
    }

    /// TODO Make safe
    pub unsafe fn events(&self) -> wlr_output_events {
        (*self.output).events
    }

    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_output {
        self.output
    }

    /// Creates a weak reference to an `Output`.
    ///
    /// # Panics
    /// If this `Output` is a previously upgraded `OutputHandle`,
    /// then this function will panic.
    pub fn weak_reference(&self) -> OutputHandle {
        let arc = self.liveliness.as_ref()
                      .expect("Cannot downgrade a previously upgraded OutputHandle");
        OutputHandle { handle: Rc::downgrade(arc),
                       output: self.output }
    }

    unsafe fn from_handle(handle: &OutputHandle) -> Self {
        Output { liveliness: None,
                 output: handle.as_ptr() }
    }

    /// Manually set the lock used to determine if a double-borrow is
    /// occuring on this structure.
    ///
    /// # Panics
    /// Panics when trying to set the lock on an upgraded handle.
    pub(crate) unsafe fn set_lock(&self, val: bool) {
        self.liveliness.as_ref()
            .expect("Tried to set lock on borrowed Output")
            .store(val, Ordering::Release);
    }
}

impl Drop for Output {
    fn drop(&mut self) {
        // NOTE
        // We do _not_ need to call wlr_output_destroy for the output
        // That is handled by the backend automatically
        match self.liveliness {
            None => return,
            Some(ref liveliness) => {
                if Rc::strong_count(liveliness) == 1 {
                    wlr_log!(L_DEBUG, "Dropped output {:p}", self.output);
                    let weak_count = Rc::weak_count(liveliness);
                    if weak_count > 0 {
                        wlr_log!(L_DEBUG,
                                 "Still {} weak pointers to Output {:p}",
                                 weak_count,
                                 self.output);
                    }
                } else {
                    return
                }
            }
        }
        // TODO Move back up in the some after NLL is a thing.
        unsafe {
            self.remove_from_output_layout();
        }
    }
}

impl OutputHandle {
    /// Creates an OutputHandle from the raw pointer, using the saved
    /// user data to recreate the memory model.
    pub(crate) unsafe fn from_ptr(output: *mut wlr_output) -> Self {
        let data = Box::from_raw((*output).data as *mut OutputState);
        let handle = data.handle.clone();
        (*output).data = Box::into_raw(data) as *mut _;
        OutputHandle { handle, output }
    }

    /// Upgrades the output handle to a reference to the backing `Output`.
    ///
    /// # Unsafety
    /// This function is unsafe, because it creates an unbound `Output`
    /// which may live forever..
    /// But no output lives forever and might be disconnected at any time.
    pub(crate) unsafe fn upgrade(&self) -> UpgradeHandleResult<Output> {
        self.handle.upgrade()
            .ok_or(UpgradeHandleErr::AlreadyDropped)
            // NOTE
            // We drop the Rc here because having two would allow a dangling
            // pointer to exist!
            .and_then(|check| {
                let output = Output::from_handle(self);
                if check.load(Ordering::Acquire) {
                    return Err(UpgradeHandleErr::AlreadyBorrowed)
                }
                check.store(true, Ordering::Release);
                Ok(output)
            })
    }

    /// Run a function on the referenced Output, if it still exists
    ///
    /// Returns the result of the function, if successful
    ///
    /// # Safety
    /// By enforcing a rather harsh limit on the lifetime of the output
    /// to a short lived scope of an anonymous function,
    /// this function ensures the Output does not live longer
    /// than it exists.
    ///
    /// # Panics
    /// This function will panic if multiple mutable borrows are detected.
    /// This will happen if you call `upgrade` directly within this callback,
    /// or if you run this function within the another run to the same `Output`.
    ///
    /// So don't nest `run` calls and everything will be ok :).
    pub fn run<F, R>(&mut self, runner: F) -> UpgradeHandleResult<R>
        where F: FnOnce(&mut Output) -> R
    {
        let mut output = unsafe { self.upgrade()? };
        let res = panic::catch_unwind(panic::AssertUnwindSafe(|| runner(&mut output)));
        self.handle.upgrade().map(|check| {
                                      // Sanity check that it hasn't been tampered with.
                                      if !check.load(Ordering::Acquire) {
                                          wlr_log!(L_ERROR,
                                                   "After running output callback, mutable lock \
                                                    was false for: {:?}",
                                                   output);
                                          panic!("Lock in incorrect state!");
                                      }
                                      check.store(false, Ordering::Release);
                                  });
        match res {
            Ok(res) => Ok(res),
            Err(err) => panic::resume_unwind(err)
        }
    }

    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_output {
        self.output
    }
}

impl PartialEq for OutputHandle {
    fn eq(&self, other: &OutputHandle) -> bool {
        self.output == other.output
    }
}

impl Eq for OutputHandle {}
<commit_msg>Fixed getting modes for Output<commit_after>//! TODO Documentation

use std::{panic, ptr};
use std::ffi::CStr;
use std::rc::{Rc, Weak};
use std::sync::atomic::{AtomicBool, Ordering};

use libc::c_float;
use wayland_sys::server::WAYLAND_SERVER_HANDLE;
use wlroots_sys::{wl_output_transform, wlr_output, wlr_output_effective_resolution,
                  wlr_output_events, wlr_output_make_current, wlr_output_mode,
                  wlr_output_set_mode, wlr_output_set_transform, wlr_output_swap_buffers};

use super::output_layout::OutputLayoutHandle;
use super::output_mode::OutputMode;
use errors::{UpgradeHandleErr, UpgradeHandleResult};
use utils::c_to_rust_string;

use Surface;

struct OutputState {
    handle: Weak<AtomicBool>,
    layout_handle: Option<OutputLayoutHandle>
}

#[derive(Debug)]
pub struct Output {
    /// The structure that ensures weak handles to this structure are still alive.
    ///
    /// They contain weak handles, and will safely not use dead memory when this
    /// is freed by wlroots.
    ///
    /// If this is `None`, then this is from an upgraded `OutputHandle`, and
    /// the operations are **unchecked**.
    /// This is means safe operations might fail, but only if you use the unsafe
    /// marked function `upgrade` on a `OutputHandle`.
    liveliness: Option<Rc<AtomicBool>>,
    /// The output ptr that refers to this `Output`
    output: *mut wlr_output
}

/// A wrapper around a wlr_output.
#[derive(Debug)]
pub struct OutputHandle {
    /// The Rc that ensures that this handle is still alive.
    ///
    /// When wlroots deallocates the pointer associated with this handle,
    /// this can no longer be used.
    handle: Weak<AtomicBool>,
    /// The output ptr that refers to this `Output`
    output: *mut wlr_output
}

impl Output {
    /// Just like `std::clone::Clone`, but unsafe.
    ///
    /// # Unsafety
    /// You can create a reference leak using this method very easily,
    /// and it could make it so that weak handles to an output are dangling.
    ///
    /// This exists due to an issue in output_manager.rs that might be fixed
    /// with NLL, so if this is no longer necessary it should be removed asap.
    pub(crate) unsafe fn clone(&self) -> Output {
        Output { liveliness: self.liveliness.clone(),
                 output: self.output }
    }

    /// Makes a new `Output` from a `wlr_output`.
    ///
    /// # Safety
    /// This creates a totally new Output (e.g with its own reference count)
    /// so only do this once per `wlr_output`!
    pub(crate) unsafe fn new(output: *mut wlr_output) -> Self {
        (*output).data = ptr::null_mut();
        let liveliness = Rc::new(AtomicBool::new(false));
        let handle = Rc::downgrade(&liveliness);
        let state = Box::new(OutputState { handle,
                                           layout_handle: None });
        (*output).data = Box::into_raw(state) as *mut _;
        Output { liveliness: Some(liveliness),
                 output }
    }

    pub(crate) unsafe fn set_output_layout(&mut self, layout_handle: Option<OutputLayoutHandle>) {
        self.remove_from_output_layout();
        let user_data = self.user_data();
        if user_data.is_null() {
            return
        }
        let mut data = Box::from_raw(user_data);
        data.layout_handle = layout_handle;
        (*self.output).data = Box::into_raw(data) as *mut _;
    }

    unsafe fn user_data(&mut self) -> *mut OutputState {
        (*self.output).data as *mut _
    }

    /// Used to clear the pointer to an OutputLayout when the OutputLayout
    /// removes this Output from its listing.
    pub(crate) unsafe fn clear_output_layout_data(&mut self) {
        let user_data = self.user_data();
        if user_data.is_null() {
            return
        }
        let mut data = Box::from_raw(user_data);
        data.layout_handle = None;
        (*self.output).data = Box::into_raw(data) as *mut _;
    }

    /// Remove this Output from an OutputLayout, if it is part of an
    /// OutputLayout.
    pub(crate) unsafe fn remove_from_output_layout(&mut self) {
        let output_data = self.user_data();
        if output_data.is_null() {
            return
        }
        // Remove output from previous output layout.
        if let Some(mut layout_handle) = (*output_data).layout_handle.take() {
            match layout_handle.run(|layout| layout.remove(self)) {
                Ok(_) | Err(UpgradeHandleErr::AlreadyDropped) => self.clear_output_layout_data(),
                Err(UpgradeHandleErr::AlreadyBorrowed) => {
                    panic!("Could not add OutputLayout to Output user data!")
                }
            }
        }
    }

    /// Gets the OutputLayout this Output is a part of, if it is part
    /// of an OutputLayout.
    ///
    /// # Safety
    /// Note that this isn't exposed to user space, as they could easily
    /// create two mutable pointers to the same structure. We keep it internally
    /// though because we use it during the cleanup process.
    pub(crate) unsafe fn layout(&mut self) -> Option<OutputLayoutHandle> {
        let data = self.user_data();
        if data.is_null() {
            None
        } else {
            (*data).layout_handle.clone()
        }
    }

    /// Sets the best modesetting for an output.
    ///
    /// NOTE You _cannot_ call this when the output will be removed.
    ///
    /// I'm still marking it as safe though because we protect against that
    /// action in the output destruction callback.
    pub fn choose_best_mode(&mut self) {
        unsafe {
            let modes = (*self.output).modes;
            let length = ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                                       wl_list_length,
                                       &modes as *const _ as _);
            if length > 0 {
                // TODO Better logging
                wlr_log!(L_DEBUG, "output added {:?}", self);
                let first_mode_ptr: *mut wlr_output_mode;
                first_mode_ptr = container_of!(&mut (*modes.prev) as *mut _, wlr_output_mode, link);
                wlr_output_set_mode(self.as_ptr(), first_mode_ptr);
            }
        }
    }

    /// Gets the name of the output in UTF-8.
    pub fn name(&self) -> String {
        unsafe {
            CStr::from_ptr((*self.output).name.as_ptr()).to_string_lossy()
                                                        .into_owned()
        }
    }

    /// Gets the make of the output in UTF-8.
    pub fn make(&self) -> String {
        unsafe {
            c_to_rust_string((*self.output).make.as_ptr()).expect("Could not parse make as UTF-8")
        }
    }

    /// Gets the model of the output in UTF-8.
    pub fn model(&self) -> String {
        unsafe {
            c_to_rust_string((*self.output).model.as_ptr()).expect("Could not parse model as UTF-8")
        }
    }

    /// Gets the serial of the output in UTF-8.
    pub fn serial(&self) -> String {
        unsafe {
            c_to_rust_string((*self.output).serial.as_ptr()).expect("Could not parse serial as \
                                                                     UTF-8")
        }
    }

    /// Determines if the output is enabled or not.
    pub fn enabled(&self) -> bool {
        unsafe { (*self.output).enabled }
    }

    /// Get the scale of the output
    pub fn scale(&self) -> c_float {
        unsafe { (*self.output).scale }
    }

    /// Determines if the output should have its buffers swapped or not.
    pub fn needs_swap(&self) -> bool {
        unsafe { (*self.output).needs_swap }
    }

    pub fn current_mode(&self) -> Option<OutputMode> {
        unsafe {
            if (*self.output).current_mode.is_null() {
                None
            } else {
                Some(OutputMode::new((*self.output).current_mode))
            }
        }
    }

    pub fn fullscreen_surface(&self) -> Option<Surface> {
        unsafe {
            if (*self.output).fullscreen_surface.is_null() {
                None
            } else {
                Some(Surface::from_ptr((*self.output).fullscreen_surface))
            }
        }
    }

    /// Gets the output position in layout space reported to clients.
    pub fn layout_space_pos(&self) -> (i32, i32) {
        unsafe { ((*self.output).lx, (*self.output).ly) }
    }

    pub fn make_current(&mut self) {
        unsafe { wlr_output_make_current(self.output) }
    }

    pub fn swap_buffers(&mut self) {
        unsafe { wlr_output_swap_buffers(self.output) }
    }

    /// Get the dimensions of the output as (width, height).
    pub fn dimensions(&self) -> (i32, i32) {
        unsafe { ((*self.output).width, (*self.output).height) }
    }

    /// Get the physical dimensions of the output as (width, height).
    pub fn physical_dimensions(&self) -> (i32, i32) {
        unsafe { ((*self.output).phys_width, (*self.output).phys_height) }
    }

    pub fn effective_resolution(&self) -> (i32, i32) {
        unsafe {
            let (mut x, mut y) = (0, 0);
            wlr_output_effective_resolution(self.output, &mut x, &mut y);
            (x, y)
        }
    }

    pub fn transform_matrix(&self) -> [c_float; 16] {
        unsafe { (*self.output).transform_matrix }
    }

    pub fn transform(&mut self, transform: wl_output_transform) {
        unsafe {
            wlr_output_set_transform(self.output, transform);
        }
    }

    /// Get the modes associated with this output.
    ///
    /// Note that some backends may have zero modes.
    pub fn modes(&self) -> Vec<OutputMode> {
        unsafe {
            let mut result = vec![];
            wl_list_for_each!((*self.output).modes, link, (mode: wlr_output_mode) => {
                result.push(OutputMode::new(mode))
            });
            result
        }
    }

    /// TODO Make safe
    pub unsafe fn events(&self) -> wlr_output_events {
        (*self.output).events
    }

    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_output {
        self.output
    }

    /// Creates a weak reference to an `Output`.
    ///
    /// # Panics
    /// If this `Output` is a previously upgraded `OutputHandle`,
    /// then this function will panic.
    pub fn weak_reference(&self) -> OutputHandle {
        let arc = self.liveliness.as_ref()
                      .expect("Cannot downgrade a previously upgraded OutputHandle");
        OutputHandle { handle: Rc::downgrade(arc),
                       output: self.output }
    }

    unsafe fn from_handle(handle: &OutputHandle) -> Self {
        Output { liveliness: None,
                 output: handle.as_ptr() }
    }

    /// Manually set the lock used to determine if a double-borrow is
    /// occuring on this structure.
    ///
    /// # Panics
    /// Panics when trying to set the lock on an upgraded handle.
    pub(crate) unsafe fn set_lock(&self, val: bool) {
        self.liveliness.as_ref()
            .expect("Tried to set lock on borrowed Output")
            .store(val, Ordering::Release);
    }
}

impl Drop for Output {
    fn drop(&mut self) {
        // NOTE
        // We do _not_ need to call wlr_output_destroy for the output
        // That is handled by the backend automatically
        match self.liveliness {
            None => return,
            Some(ref liveliness) => {
                if Rc::strong_count(liveliness) == 1 {
                    wlr_log!(L_DEBUG, "Dropped output {:p}", self.output);
                    let weak_count = Rc::weak_count(liveliness);
                    if weak_count > 0 {
                        wlr_log!(L_DEBUG,
                                 "Still {} weak pointers to Output {:p}",
                                 weak_count,
                                 self.output);
                    }
                } else {
                    return
                }
            }
        }
        // TODO Move back up in the some after NLL is a thing.
        unsafe {
            self.remove_from_output_layout();
        }
    }
}

impl OutputHandle {
    /// Creates an OutputHandle from the raw pointer, using the saved
    /// user data to recreate the memory model.
    pub(crate) unsafe fn from_ptr(output: *mut wlr_output) -> Self {
        let data = Box::from_raw((*output).data as *mut OutputState);
        let handle = data.handle.clone();
        (*output).data = Box::into_raw(data) as *mut _;
        OutputHandle { handle, output }
    }

    /// Upgrades the output handle to a reference to the backing `Output`.
    ///
    /// # Unsafety
    /// This function is unsafe, because it creates an unbound `Output`
    /// which may live forever..
    /// But no output lives forever and might be disconnected at any time.
    pub(crate) unsafe fn upgrade(&self) -> UpgradeHandleResult<Output> {
        self.handle.upgrade()
            .ok_or(UpgradeHandleErr::AlreadyDropped)
            // NOTE
            // We drop the Rc here because having two would allow a dangling
            // pointer to exist!
            .and_then(|check| {
                let output = Output::from_handle(self);
                if check.load(Ordering::Acquire) {
                    return Err(UpgradeHandleErr::AlreadyBorrowed)
                }
                check.store(true, Ordering::Release);
                Ok(output)
            })
    }

    /// Run a function on the referenced Output, if it still exists
    ///
    /// Returns the result of the function, if successful
    ///
    /// # Safety
    /// By enforcing a rather harsh limit on the lifetime of the output
    /// to a short lived scope of an anonymous function,
    /// this function ensures the Output does not live longer
    /// than it exists.
    ///
    /// # Panics
    /// This function will panic if multiple mutable borrows are detected.
    /// This will happen if you call `upgrade` directly within this callback,
    /// or if you run this function within the another run to the same `Output`.
    ///
    /// So don't nest `run` calls and everything will be ok :).
    pub fn run<F, R>(&mut self, runner: F) -> UpgradeHandleResult<R>
        where F: FnOnce(&mut Output) -> R
    {
        let mut output = unsafe { self.upgrade()? };
        let res = panic::catch_unwind(panic::AssertUnwindSafe(|| runner(&mut output)));
        self.handle.upgrade().map(|check| {
                                      // Sanity check that it hasn't been tampered with.
                                      if !check.load(Ordering::Acquire) {
                                          wlr_log!(L_ERROR,
                                                   "After running output callback, mutable lock \
                                                    was false for: {:?}",
                                                   output);
                                          panic!("Lock in incorrect state!");
                                      }
                                      check.store(false, Ordering::Release);
                                  });
        match res {
            Ok(res) => Ok(res),
            Err(err) => panic::resume_unwind(err)
        }
    }

    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_output {
        self.output
    }
}

impl PartialEq for OutputHandle {
    fn eq(&self, other: &OutputHandle) -> bool {
        self.output == other.output
    }
}

impl Eq for OutputHandle {}
<|endoftext|>


<commit_before>use std::io;
use std::str::FromStr;

fn min_pair(a: & Option<(f32, f32)>, b: & Option<(f32, f32)>) -> Option<(f32, f32)> {
    return match (*a, *b) {
        (None, None) => None,
        (_, None) => *a,
        (None, _) => *b,
        (Some(at), Some(bt)) =>
            if (at.1 - at.0) >= (bt.1 - bt.0) { *a } else { *b }
    }
}

fn minmax(seq: & Vec<f32>, adj: bool) -> Option<(f32, f32)> {
    let mut min: (usize, &f32) = (0, &seq[0]);
    let mut max: (usize, &f32) = (0, &seq[0]);

    for (i, e) in seq.iter().enumerate() {
        if e < min.1 {
            min = (i, e);
        }
        if e > max.1 {
            max = (i, e);
        }
    }

    if min.1 == max.1 {
        return None;
    }
    if min.0 > max.0 {
        let spl;
        let s1: Vec<f32>;
        let s2: Vec<f32>;
        let mm1: Option<(f32, f32)>;
        let mm2: Option<(f32, f32)>;

        spl = seq.split_at(max.0 + 1);
        s1 = spl.0.to_vec();
        s2 = spl.1.to_vec();
        if s1.len() == 0 || s2.len() == 0 {
            return None;
        }
        mm1 = minmax(& s1, true);
        mm2 = minmax(& s2, true);
        return min_pair(&mm1, &mm2);
    }
    if adj && min.0 + 1 == max.0 {
        let mut s1: Vec<f32> = seq.clone();
        let mut s2: Vec<f32> = seq.clone();

        let mm1: Option<(f32, f32)>;
        let mm2: Option<(f32, f32)>;

        s1.remove(min.0);
        s2.remove(max.0);

        mm1 = minmax(& s1, false);
        mm2 = minmax(& s2, false);
        return min_pair(&mm1, &mm2);
    }

    return Some((*min.1, *max.1));
}

fn main() {
    let mut input = String::new();
    let market: Vec<f32>;
    let mm: Option<(f32, f32)>;

    io::stdin().read_line(&mut input);
    market = input.split_whitespace()
        .map(|e| f32::from_str(e).unwrap())
        .collect();

    mm = minmax(&market, true);
    match mm {
        None => println!("No result"),
        Some(v) => println!("{} {}", v.0, v.1),
    }
}
<commit_msg>Replaced vec references with slices.<commit_after>use std::io;
use std::str::FromStr;

fn min_pair(a: & Option<(f32, f32)>, b: & Option<(f32, f32)>) -> Option<(f32, f32)> {
    return match (*a, *b) {
        (None, None) => None,
        (_, None) => *a,
        (None, _) => *b,
        (Some(at), Some(bt)) =>
            if (at.1 - at.0) >= (bt.1 - bt.0) { *a } else { *b }
    }
}

fn minmax(seq: &[f32], adj: bool) -> Option<(f32, f32)> {
    let mut min: (usize, &f32) = (0, &seq[0]);
    let mut max: (usize, &f32) = (0, &seq[0]);

    for (i, e) in seq.iter().enumerate() {
        if e < min.1 {
            min = (i, e);
        }
        if e > max.1 {
            max = (i, e);
        }
    }

    if min.1 == max.1 {
        return None;
    }
    if min.0 > max.0 {
        let spl;
        let s1: &[f32];
        let s2: &[f32];
        let mm1: Option<(f32, f32)>;
        let mm2: Option<(f32, f32)>;

        spl = seq.split_at(max.0 + 1);
        s1 = spl.0;
        s2 = spl.1;
        if s1.len() == 0 || s2.len() == 0 {
            return None;
        }
        mm1 = minmax(& s1, true);
        mm2 = minmax(& s2, true);
        return min_pair(&mm1, &mm2);
    }
    if adj && min.0 + 1 == max.0 {
        let mut s1: Vec<f32> = seq.clone().to_vec();
        let mut s2: Vec<f32> = seq.clone().to_vec();

        let mm1: Option<(f32, f32)>;
        let mm2: Option<(f32, f32)>;

        s1.remove(min.0);
        s2.remove(max.0);

        mm1 = minmax(& s1, false);
        mm2 = minmax(& s2, false);
        return min_pair(&mm1, &mm2);
    }

    return Some((*min.1, *max.1));
}

fn main() {
    let mut input = String::new();
    let market: Vec<f32>;
    let mm: Option<(f32, f32)>;

    io::stdin().read_line(&mut input);
    market = input.split_whitespace()
        .map(|e| f32::from_str(e).unwrap())
        .collect();

    mm = minmax(&market, true);
    match mm {
        None => println!("No result"),
        Some(v) => println!("{} {}", v.0, v.1),
    }
}
<|endoftext|>


<commit_before>use super::respan::respan;
use proc_macro2::{Group, Spacing, Span, TokenStream, TokenTree};
use quote::{quote, quote_spanned};
use std::{iter::FromIterator, mem};
use syn::{
    parse_quote,
    punctuated::Punctuated,
    visit_mut::{self, VisitMut},
    DeriveInput, ExprPath, Macro, Path, PathArguments, QSelf, Type, TypePath,
};

pub fn replace_receiver(input: &mut DeriveInput) {
    let self_ty = {
        let ident = &input.ident;
        let ty_generics = input.generics.split_for_impl().1;
        parse_quote!(#ident #ty_generics)
    };
    let mut visitor = ReplaceReceiver(&self_ty);
    visitor.visit_generics_mut(&mut input.generics);
    visitor.visit_data_mut(&mut input.data);
}

struct ReplaceReceiver<'a>(&'a TypePath);

impl ReplaceReceiver<'_> {
    fn self_ty(&self, span: Span) -> TypePath {
        respan(self.0, span)
    }

    fn self_to_qself(&self, qself: &mut Option<QSelf>, path: &mut Path) {
        if path.leading_colon.is_some() {
            return;
        }

        // Make borrow checker happy
        {
            let first = &path.segments[0];
            if first.ident != "Self" || !first.arguments.is_empty() {
                return;
            }
        }

        if path.segments.len() == 1 {
            self.self_to_expr_path(path);
            return;
        }

        let span = path.segments[0].ident.span();
        *qself = Some(QSelf {
            lt_token: Token![<](span),
            ty: Box::new(self.self_ty(span).into()),
            position: 0,
            as_token: None,
            gt_token: Token![>](span),
        });

        path.leading_colon = Some(**path.segments.pairs().next().unwrap().punct().unwrap());

        let segments = mem::replace(&mut path.segments, Punctuated::new());
        path.segments = segments.into_pairs().skip(1).collect();
    }

    fn self_to_expr_path(&self, path: &mut Path) {
        if path.leading_colon.is_some() {
            return;
        }

        // Make borrow checker happy
        {
            let first = &path.segments[0];
            if first.ident != "Self" || !first.arguments.is_empty() {
                return;
            }
        }

        let self_ty = self.self_ty(path.segments[0].ident.span());
        let variant = mem::replace(path, self_ty.path);
        for segment in &mut path.segments {
            if let PathArguments::AngleBracketed(bracketed) = &mut segment.arguments {
                if bracketed.colon2_token.is_none() && !bracketed.args.is_empty() {
                    bracketed.colon2_token = Some(<Token![::]>::default());
                }
            }
        }
        if variant.segments.len() > 1 {
            path.segments.push_punct(<Token![::]>::default());
            path.segments.extend(variant.segments.into_pairs().skip(1));
        }
    }

    fn visit_token_stream(&self, tokens: &mut TokenStream) -> bool {
        let mut out = Vec::new();
        let mut modified = false;
        let mut iter = tokens.clone().into_iter().peekable();
        while let Some(tt) = iter.next() {
            match tt {
                TokenTree::Ident(ident) => {
                    if ident == "Self" {
                        modified = true;
                        let self_ty = self.self_ty(ident.span());
                        match iter.peek() {
                            Some(TokenTree::Punct(p))
                                if p.as_char() == ':' && p.spacing() == Spacing::Joint => {}
                            _ => {
                                out.extend(quote!(#self_ty));
                                continue;
                            }
                        }
                        let next = iter.next().unwrap();
                        match iter.peek() {
                            Some(TokenTree::Punct(p)) if p.as_char() == ':' => {
                                let span = ident.span();
                                out.extend(quote_spanned!(span=> <#self_ty>));
                            }
                            _ => out.extend(quote!(#self_ty)),
                        }
                        out.push(next);
                    } else {
                        out.push(TokenTree::Ident(ident));
                    }
                }
                TokenTree::Group(group) => {
                    let mut content = group.stream();
                    modified |= self.visit_token_stream(&mut content);
                    let mut new = Group::new(group.delimiter(), content);
                    new.set_span(group.span());
                    out.push(TokenTree::Group(new));
                }
                other => out.push(other),
            }
        }
        if modified {
            *tokens = TokenStream::from_iter(out);
        }
        modified
    }
}

impl VisitMut for ReplaceReceiver<'_> {
    // `Self` -> `Receiver`
    fn visit_type_mut(&mut self, ty: &mut Type) {
        let span = if let Type::Path(node) = ty {
            if node.qself.is_none() && node.path.is_ident("Self") {
                node.path.segments[0].ident.span()
            } else {
                self.visit_type_path_mut(node);
                return;
            }
        } else {
            visit_mut::visit_type_mut(self, ty);
            return;
        };
        *ty = self.self_ty(span).into();
    }

    // `Self::Assoc` -> `<Receiver>::Assoc`
    fn visit_type_path_mut(&mut self, ty: &mut TypePath) {
        if ty.qself.is_none() {
            self.self_to_qself(&mut ty.qself, &mut ty.path);
        }
        visit_mut::visit_type_path_mut(self, ty);
    }

    // `Self::method` -> `<Receiver>::method`
    fn visit_expr_path_mut(&mut self, expr: &mut ExprPath) {
        if expr.qself.is_none() {
            self.self_to_qself(&mut expr.qself, &mut expr.path);
        }
        visit_mut::visit_expr_path_mut(self, expr);
    }

    fn visit_macro_mut(&mut self, mac: &mut Macro) {
        // We can't tell in general whether `self` inside a macro invocation
        // refers to the self in the argument list or a different self
        // introduced within the macro. Heuristic: if the macro input contains
        // `fn`, then `self` is more likely to refer to something other than the
        // outer function's self argument.
        if !contains_fn(mac.tokens.clone()) {
            self.visit_token_stream(&mut mac.tokens);
        }
    }
}

fn contains_fn(tokens: TokenStream) -> bool {
    tokens.into_iter().any(|tt| match tt {
        TokenTree::Ident(ident) => ident == "fn",
        TokenTree::Group(group) => contains_fn(group.stream()),
        _ => false,
    })
}
<commit_msg>Pare down PR 1830<commit_after>use super::respan::respan;
use proc_macro2::Span;
use std::mem;
use syn::{
    parse_quote,
    punctuated::Punctuated,
    visit_mut::{self, VisitMut},
    DeriveInput, ExprPath, Path, PathArguments, QSelf, Type, TypePath,
};

pub fn replace_receiver(input: &mut DeriveInput) {
    let self_ty = {
        let ident = &input.ident;
        let ty_generics = input.generics.split_for_impl().1;
        parse_quote!(#ident #ty_generics)
    };
    let mut visitor = ReplaceReceiver(&self_ty);
    visitor.visit_generics_mut(&mut input.generics);
    visitor.visit_data_mut(&mut input.data);
}

struct ReplaceReceiver<'a>(&'a TypePath);

impl ReplaceReceiver<'_> {
    fn self_ty(&self, span: Span) -> TypePath {
        respan(self.0, span)
    }

    fn self_to_qself(&self, qself: &mut Option<QSelf>, path: &mut Path) {
        if path.leading_colon.is_some() {
            return;
        }

        // Make borrow checker happy
        {
            let first = &path.segments[0];
            if first.ident != "Self" || !first.arguments.is_empty() {
                return;
            }
        }

        if path.segments.len() == 1 {
            self.self_to_expr_path(path);
            return;
        }

        let span = path.segments[0].ident.span();
        *qself = Some(QSelf {
            lt_token: Token![<](span),
            ty: Box::new(self.self_ty(span).into()),
            position: 0,
            as_token: None,
            gt_token: Token![>](span),
        });

        path.leading_colon = Some(**path.segments.pairs().next().unwrap().punct().unwrap());

        let segments = mem::replace(&mut path.segments, Punctuated::new());
        path.segments = segments.into_pairs().skip(1).collect();
    }

    fn self_to_expr_path(&self, path: &mut Path) {
        if path.leading_colon.is_some() {
            return;
        }

        // Make borrow checker happy
        {
            let first = &path.segments[0];
            if first.ident != "Self" || !first.arguments.is_empty() {
                return;
            }
        }

        let self_ty = self.self_ty(path.segments[0].ident.span());
        let variant = mem::replace(path, self_ty.path);
        for segment in &mut path.segments {
            if let PathArguments::AngleBracketed(bracketed) = &mut segment.arguments {
                if bracketed.colon2_token.is_none() && !bracketed.args.is_empty() {
                    bracketed.colon2_token = Some(<Token![::]>::default());
                }
            }
        }
        if variant.segments.len() > 1 {
            path.segments.push_punct(<Token![::]>::default());
            path.segments.extend(variant.segments.into_pairs().skip(1));
        }
    }
}

impl VisitMut for ReplaceReceiver<'_> {
    // `Self` -> `Receiver`
    fn visit_type_mut(&mut self, ty: &mut Type) {
        let span = if let Type::Path(node) = ty {
            if node.qself.is_none() && node.path.is_ident("Self") {
                node.path.segments[0].ident.span()
            } else {
                self.visit_type_path_mut(node);
                return;
            }
        } else {
            visit_mut::visit_type_mut(self, ty);
            return;
        };
        *ty = self.self_ty(span).into();
    }

    // `Self::Assoc` -> `<Receiver>::Assoc`
    fn visit_type_path_mut(&mut self, ty: &mut TypePath) {
        if ty.qself.is_none() {
            self.self_to_qself(&mut ty.qself, &mut ty.path);
        }
        visit_mut::visit_type_path_mut(self, ty);
    }

    // `Self::method` -> `<Receiver>::method`
    fn visit_expr_path_mut(&mut self, expr: &mut ExprPath) {
        if expr.qself.is_none() {
            self.self_to_qself(&mut expr.qself, &mut expr.path);
        }
        visit_mut::visit_expr_path_mut(self, expr);
    }
}
<|endoftext|>


<commit_before>extern crate neat;
extern crate rand;
extern crate graph_neighbor_matching;
extern crate graph_io_gml;
extern crate closed01;
extern crate petgraph;
extern crate cppn;

mod common;

use neat::population::{Population, Unrated, Runner};
use neat::genomes::acyclic_network::{NodeType, Genome, GenomeDistance, Environment,
                                     ElementStrategy};
use neat::fitness::Fitness;
use neat::crossover::ProbabilisticCrossover;
use graph_neighbor_matching::{SimilarityMatrix, ScoreNorm, NodeColorMatching};
use graph_neighbor_matching::graph::{OwnedGraph, GraphBuilder};
use rand::{Rng, Closed01};
use std::marker::PhantomData;
use neat::mutate::MutateMethodWeighting;
use neat::gene::Gene;
use common::{load_graph, Mater, Neuron, NodeColors, convert_neuron_from_str};
use cppn::cppn::{Cppn, CppnNodeType};
use cppn::bipolar::BipolarActivationFunction;
use cppn::substrate::Substrate;
use cppn::position::{Position, Position2d};

type Node = CppnNodeType<BipolarActivationFunction>;

#[derive(Debug)]
struct FitnessEvaluator {
    target_graph: OwnedGraph<Neuron>,
}

// fn develop_graph_from_substrate<P: Position, T: Clone + Debug>(substrate: &Substrate<P, T>,
// cppn: &mut Cppn)
// -> OwnedGraph<T> {
// return graph;
// }
//
//

impl FitnessEvaluator {
    // A larger fitness means "better"
    fn fitness(&self, genome: &Genome<Node>) -> f32 {
        let mut substrate = Substrate::new();
        substrate.add_node(Position2d::new(-1.0, -1.0), Neuron::Input);
        substrate.add_node(Position2d::new(1.0, -1.0), Neuron::Input);
        substrate.add_node(Position2d::new(-1.0, 1.0), Neuron::Output);
        substrate.add_node(Position2d::new(0.0, 1.0), Neuron::Output);
        substrate.add_node(Position2d::new(1.0, 1.0), Neuron::Output);

        let mut cppn = Cppn::new(genome.network());

        // now develop the cppn. the result is a graph
        let mut builder = GraphBuilder::new();
        for (i, node) in substrate.nodes().iter().enumerate() {
            let _ = builder.add_node(i, node.data.clone());
        }
        for link in substrate.iter_links(&mut cppn, None) {
            if link.weight >= 0.0 && link.weight <= 1.0 {
                builder.add_edge(link.source_idx,
                                 link.target_idx,
                                 closed01::Closed01::new(link.weight as f32));
            }
        }
        let graph = builder.graph();
        println!("graph: {:#?}", graph);

        let mut s = SimilarityMatrix::new(&graph, &self.target_graph, NodeColors);
        s.iterate(50, 0.01);
        s.score_optimal_sum_norm(None, ScoreNorm::MaxDegree).get()
    }
}

struct ES;

impl ElementStrategy<Node> for ES {
    fn random_link_weight<R: Rng>(rng: &mut R) -> f64 {
        // XXX Choose a weight between -1 and 1?
        rng.gen()
    }

    fn random_node_type<R: Rng>(rng: &mut R) -> Node {
        let af = &[BipolarActivationFunction::Identity,
                   BipolarActivationFunction::Linear,
                   BipolarActivationFunction::Gaussian,
                   BipolarActivationFunction::Sigmoid,
                   BipolarActivationFunction::Sine];

        CppnNodeType::Hidden(*rng.choose(af).unwrap())
    }
}

const POP_SIZE: usize = 100;

fn main() {
    let mut rng = rand::thread_rng();

    let fitness_evaluator = FitnessEvaluator {
        target_graph: load_graph("examples/jeffress.gml", convert_neuron_from_str),
    };

    println!("{:?}", fitness_evaluator);

    // start with minimal random topology.
    let mut env: Environment<Node, ES> = Environment::new();

    let template_genome = {
        let mut genome = Genome::new();

        // 4 inputs (x1,y1,x2,y2)
        for _ in 0..4 {
            env.add_node_to_genome(&mut genome, CppnNodeType::Input);
        }

        // 1 output (y)
        env.add_node_to_genome(&mut genome, CppnNodeType::Output);

        // 1 bias node
        env.add_node_to_genome(&mut genome, CppnNodeType::Bias);

        genome
    };

    println!("{:#?}", template_genome);

    let mut initial_pop = Population::<_, Unrated>::new();

    for _ in 0..POP_SIZE {
        initial_pop.add_genome(Box::new(template_genome.clone()));
    }
    assert!(initial_pop.len() == POP_SIZE);

    let mut mater = Mater {
        p_crossover: Closed01(0.5),
        p_crossover_detail: ProbabilisticCrossover {
            prob_match_left: Closed01(0.5), /* NEAT always selects a random parent for matching genes */
            prob_disjoint_left: Closed01(0.9),
            prob_excess_left: Closed01(0.9),
            prob_disjoint_right: Closed01(0.15),
            prob_excess_right: Closed01(0.15),
        },
        mutate_weights: MutateMethodWeighting {
            w_modify_weight: 1,
            w_add_node: 1,
            w_add_connection: 1,
        },

        env: &mut env,
    };

    let compatibility = GenomeDistance {
        excess: 1.0,
        disjoint: 1.0,
        weight: 0.0,
    };

    let mut runner = Runner {
        pop_size: POP_SIZE,
        elite_percentage: Closed01(0.05),
        selection_percentage: Closed01(0.2),
        tournament_k: 3,
        compatibility_threshold: 1.0,
        compatibility: &compatibility,
        mate: &mut mater,
        fitness: &|genome| Fitness::new(fitness_evaluator.fitness(genome) as f64),
        _marker: PhantomData,
    };

    let (iter, new_pop) = runner.run(initial_pop,
                                     &|iter, pop| {
                                         iter >= 100 || pop.max_fitness().unwrap().get() > 0.99
                                     },
                                     &mut rng);

    let new_pop = new_pop.sort();

    println!("iter: {}", iter);
    println!("{:#?}", new_pop);
}
<commit_msg>Cleanup and silence warnings<commit_after>extern crate neat;
extern crate rand;
extern crate graph_neighbor_matching;
extern crate graph_io_gml;
extern crate closed01;
extern crate petgraph;
extern crate cppn;

mod common;

use neat::population::{Population, Unrated, Runner};
use neat::genomes::acyclic_network::{Genome, GenomeDistance, Environment, ElementStrategy};
use neat::fitness::Fitness;
use neat::crossover::ProbabilisticCrossover;
use graph_neighbor_matching::{SimilarityMatrix, ScoreNorm};
use graph_neighbor_matching::graph::{OwnedGraph, GraphBuilder};
use rand::{Rng, Closed01};
use std::marker::PhantomData;
use neat::mutate::MutateMethodWeighting;
use common::{load_graph, Mater, Neuron, NodeColors, convert_neuron_from_str};
use cppn::cppn::{Cppn, CppnNodeType};
use cppn::bipolar::BipolarActivationFunction;
use cppn::substrate::Substrate;
use cppn::position::Position2d;

type Node = CppnNodeType<BipolarActivationFunction>;

#[derive(Debug)]
struct FitnessEvaluator {
    target_graph: OwnedGraph<Neuron>,
}

impl FitnessEvaluator {
    // A larger fitness means "better"
    fn fitness(&self, genome: &Genome<Node>) -> f32 {
        let mut substrate = Substrate::new();
        substrate.add_node(Position2d::new(-1.0, -1.0), Neuron::Input);
        substrate.add_node(Position2d::new(1.0, -1.0), Neuron::Input);
        substrate.add_node(Position2d::new(-1.0, 1.0), Neuron::Output);
        substrate.add_node(Position2d::new(0.0, 1.0), Neuron::Output);
        substrate.add_node(Position2d::new(1.0, 1.0), Neuron::Output);

        let mut cppn = Cppn::new(genome.network());

        // now develop the cppn. the result is a graph
        let mut builder = GraphBuilder::new();
        for (i, node) in substrate.nodes().iter().enumerate() {
            let _ = builder.add_node(i, node.data.clone());
        }
        for link in substrate.iter_links(&mut cppn, None) {
            if link.weight >= 0.0 && link.weight <= 1.0 {
                builder.add_edge(link.source_idx,
                                 link.target_idx,
                                 closed01::Closed01::new(link.weight as f32));
            }
        }
        let graph = builder.graph();
        println!("graph: {:#?}", graph);

        let mut s = SimilarityMatrix::new(&graph, &self.target_graph, NodeColors);
        s.iterate(50, 0.01);
        s.score_optimal_sum_norm(None, ScoreNorm::MaxDegree).get()
    }
}

struct ES;

impl ElementStrategy<Node> for ES {
    fn random_link_weight<R: Rng>(rng: &mut R) -> f64 {
        // XXX Choose a weight between -1 and 1?
        rng.gen()
    }

    fn random_node_type<R: Rng>(rng: &mut R) -> Node {
        let af = &[BipolarActivationFunction::Identity,
                   BipolarActivationFunction::Linear,
                   BipolarActivationFunction::Gaussian,
                   BipolarActivationFunction::Sigmoid,
                   BipolarActivationFunction::Sine];

        CppnNodeType::Hidden(*rng.choose(af).unwrap())
    }
}

const POP_SIZE: usize = 100;

fn main() {
    let mut rng = rand::thread_rng();

    let fitness_evaluator = FitnessEvaluator {
        target_graph: load_graph("examples/jeffress.gml", convert_neuron_from_str),
    };

    println!("{:?}", fitness_evaluator);

    // start with minimal random topology.
    let mut env: Environment<Node, ES> = Environment::new();

    let template_genome = {
        let mut genome = Genome::new();

        // 4 inputs (x1,y1,x2,y2)
        for _ in 0..4 {
            env.add_node_to_genome(&mut genome, CppnNodeType::Input);
        }

        // 1 output (y)
        env.add_node_to_genome(&mut genome, CppnNodeType::Output);

        // 1 bias node
        env.add_node_to_genome(&mut genome, CppnNodeType::Bias);

        genome
    };

    println!("{:#?}", template_genome);

    let mut initial_pop = Population::<_, Unrated>::new();

    for _ in 0..POP_SIZE {
        initial_pop.add_genome(Box::new(template_genome.clone()));
    }
    assert!(initial_pop.len() == POP_SIZE);

    let mut mater = Mater {
        p_crossover: Closed01(0.5),
        p_crossover_detail: ProbabilisticCrossover {
            prob_match_left: Closed01(0.5), /* NEAT always selects a random parent for matching genes */
            prob_disjoint_left: Closed01(0.9),
            prob_excess_left: Closed01(0.9),
            prob_disjoint_right: Closed01(0.15),
            prob_excess_right: Closed01(0.15),
        },
        mutate_weights: MutateMethodWeighting {
            w_modify_weight: 1,
            w_add_node: 1,
            w_add_connection: 1,
        },

        env: &mut env,
    };

    let compatibility = GenomeDistance {
        excess: 1.0,
        disjoint: 1.0,
        weight: 0.0,
    };

    let mut runner = Runner {
        pop_size: POP_SIZE,
        elite_percentage: Closed01(0.05),
        selection_percentage: Closed01(0.2),
        tournament_k: 3,
        compatibility_threshold: 1.0,
        compatibility: &compatibility,
        mate: &mut mater,
        fitness: &|genome| Fitness::new(fitness_evaluator.fitness(genome) as f64),
        _marker: PhantomData,
    };

    let (iter, new_pop) = runner.run(initial_pop,
                                     &|iter, pop| {
                                         iter >= 100 || pop.max_fitness().unwrap().get() > 0.99
                                     },
                                     &mut rng);

    let new_pop = new_pop.sort();

    println!("iter: {}", iter);
    println!("{:#?}", new_pop);
}
<|endoftext|>


<commit_before>
use crate::prelude::*;

pub enum TypeSystemName {
    Automation,
    Raw,
}

/// Common trait for type systems.
pub trait TypeSystem : Clone + Copy {
    const AUTOMATION : TypeSystemName = TypeSystemName::Automation;
    const RAW : TypeSystemName = TypeSystemName::Raw;

    fn key() -> TypeSystemName;
}

/// Automation type system.
#[derive(Clone, Copy)]
pub struct AutomationTypeSystem;
impl TypeSystem for AutomationTypeSystem {
    fn key() -> TypeSystemName { TypeSystemName::Automation }
}

/// Raw type system.
#[derive(Clone, Copy)]
pub struct RawTypeSystem;
impl TypeSystem for RawTypeSystem {
    fn key() -> TypeSystemName { TypeSystemName::Raw }
}

/// Defines a type that has identical representation for both input and output directions.
pub trait BidirectionalTypeInfo {

    /// The name of the type.
    fn type_name() -> &'static str;
}

/// Defines details of the type that specify how to pass it as an input parameter.
pub trait InputTypeInfo {

    /// The name of the type.
    fn type_name() -> &'static str;
}

/// Defines details of the type that specify how to pass it as an output parameter.
pub trait OutputTypeInfo {

    /// The name of the type.
    fn type_name() -> &'static str;
}

/// Defines a type that is compatible with Intercom interfaces.
pub trait ExternType<TS: TypeSystem> : Sized {

    /// Type used when the Self type is encountered as an input parameter.
    type ExternInputType : InputTypeInfo;

    /// Type used when the Self type is encountered as an output type.
    type ExternOutputType : OutputTypeInfo;

    /// A possible temporary type used for converting `Self` into
    /// `ExternInputType` when calling Intercom interfaces from Rust.
    type OwnedExternType : IntercomFrom< Self > = Self;

    /// A possible temporary type used for converting `ExternInputType` into
    /// `Self` type when calling Rust through an Intercom interface.
    type OwnedNativeType : IntercomFrom< Self::ExternInputType > = Self;
}

/// A conversion that may fail by resulting in a `ComError .
pub trait IntercomFrom<TSource> : Sized {
    fn intercom_from( source : TSource ) -> ComResult<Self>;
}

/// Default identity blanket implementation.
impl<T> IntercomFrom<T> for T {
    default fn intercom_from( source: T ) -> ComResult<T> { Ok( source ) }
}

/// Blanket implementation for all cloneable instance references.
impl<TSource: Clone> IntercomFrom<&TSource> for TSource {
    fn intercom_from( source: &TSource ) -> ComResult<Self> {
        Ok( source.clone() )
    }
}

/// A conversion that may fail by resulting in a `ComError .
pub trait IntercomInto<TTarget> {
    fn intercom_into( self : Self ) -> ComResult<TTarget>;
}

/// Blanket implementation for reversing IntercomFrom into IntercomInto.
impl<TSource, TTarget: IntercomFrom<TSource>>
        IntercomInto<TTarget> for TSource
{
    default fn intercom_into( self: Self ) -> ComResult<TTarget> {
        TTarget::intercom_from( self )
    }
}

/// Bidirectional types can be used as input types.
impl<BT> InputTypeInfo for BT where BT: BidirectionalTypeInfo {

    /// The name of the type.
    fn type_name() -> &'static str { <BT as BidirectionalTypeInfo>::type_name() }
}

/// Bidirectional types can be used as output types.
impl<BT> OutputTypeInfo for BT where BT: BidirectionalTypeInfo {

    /// The name of the type.
    fn type_name() -> &'static str { <BT as BidirectionalTypeInfo>::type_name() }
}

/// A quick macro for implementing ExternType for various basic types that
/// should represent themselves.
///
/// Ideally we would use specialization here to implement ExternType for T,
/// but that prevents other crates from implementing a specialized version for
/// some reason.
macro_rules! self_extern {
    ( $t:ty ) => {

        impl BidirectionalTypeInfo for $t {

            /// The default name is the name of the type.
            fn type_name() -> &'static str { stringify!( $t ) }
        }

        impl<TS: TypeSystem> ExternType<TS> for $t {
            type ExternInputType = $t;
            type ExternOutputType = $t;
            type OwnedExternType = $t;
            type OwnedNativeType = $t;
        }
    }
}

// Define all types that should have built-in Self extern type.
self_extern!( () );
self_extern!( i8 );
self_extern!( i16 );
self_extern!( i32 );
self_extern!( i64 );
self_extern!( isize );
self_extern!( u8 );
self_extern!( u16 );
self_extern!( u32 );
self_extern!( u64 );
self_extern!( usize );
self_extern!( f32 );
self_extern!( f64 );
self_extern!( crate::raw::HRESULT );
self_extern!( crate::GUID );
self_extern!( std::ffi::c_void );

// Any raw pointer is passed as is.

impl<TPtr> BidirectionalTypeInfo for *mut TPtr where TPtr: BidirectionalTypeInfo {

    /// The name of the type.
    fn type_name() -> &'static str { <TPtr as BidirectionalTypeInfo>::type_name() }
}

impl<TS: TypeSystem, TPtr> ExternType<TS> for *mut TPtr where TPtr: BidirectionalTypeInfo {
    type ExternInputType = *mut TPtr;
    type ExternOutputType = *mut TPtr;
    type OwnedExternType = *mut TPtr;
    type OwnedNativeType = *mut TPtr;
}

impl<TPtr> BidirectionalTypeInfo for *const TPtr where TPtr: BidirectionalTypeInfo {

    /// The name of the type.
    fn type_name() -> &'static str { <TPtr as BidirectionalTypeInfo>::type_name() }
}

impl<TS: TypeSystem, TPtr> ExternType<TS> for *const TPtr where TPtr: BidirectionalTypeInfo {
    type ExternInputType = *const TPtr;
    type ExternOutputType = *const TPtr;
    type OwnedExternType = *const TPtr;
    type OwnedNativeType = *const TPtr;
}

/// `ComItf` extern type implementation.

impl<I: crate::ComInterface + ?Sized> BidirectionalTypeInfo for crate::ComItf<I>
    where I: BidirectionalTypeInfo
{

    /// The name of the type.
    fn type_name() -> &'static str { <I as BidirectionalTypeInfo>::type_name() }
}

impl<TS: TypeSystem, I: crate::ComInterface + ?Sized> ExternType<TS>
        for crate::ComItf<I>
    where I: BidirectionalTypeInfo
{

    type ExternInputType = crate::raw::InterfacePtr<TS, I>;
    type ExternOutputType = crate::raw::InterfacePtr<TS, I>;
    type OwnedExternType = crate::raw::InterfacePtr<TS, I>;
    type OwnedNativeType = crate::raw::InterfacePtr<TS, I>;
}

impl<TS: TypeSystem, I: crate::ComInterface + ?Sized> BidirectionalTypeInfo for crate::raw::InterfacePtr<TS, I>
    where I: BidirectionalTypeInfo
{

    /// The name of the type.
    fn type_name() -> &'static str { <I as BidirectionalTypeInfo>::type_name() }
}

impl<TS: TypeSystem, I: crate::ComInterface + ?Sized>
    IntercomFrom<crate::ComItf<I>> for crate::raw::InterfacePtr<TS, I>
{
    fn intercom_from( source: crate::ComItf<I> ) -> ComResult<Self> {
        Ok( crate::ComItf::ptr( &source ) )
    }
}

impl<TS: TypeSystem, I: crate::ComInterface + ?Sized>
    IntercomFrom<&crate::ComItf<I>> for crate::raw::InterfacePtr<TS, I>
{
    fn intercom_from( source: &crate::ComItf<I> ) -> ComResult<Self> {
        Ok( crate::ComItf::ptr( source ) )
    }
}

impl<TS: TypeSystem, I: crate::ComInterface + ?Sized>
    IntercomFrom<crate::raw::InterfacePtr<TS, I>> for crate::ComItf<I>
{
    fn intercom_from( source: crate::raw::InterfacePtr<TS, I> ) -> ComResult<Self> {
        crate::ComItf::maybe_wrap( source )
                .ok_or_else( || crate::ComError::E_INVALIDARG )
    }
}

impl<TS: TypeSystem, I: crate::ComInterface + ?Sized>
    IntercomFrom<&crate::raw::InterfacePtr<TS, I>> for crate::ComItf<I>
{
    fn intercom_from( source: &crate::raw::InterfacePtr<TS, I> ) -> ComResult<Self> {
        crate::ComItf::maybe_wrap( source.clone() )
                .ok_or_else( || crate::ComError::E_INVALIDARG )
    }
}

/// Defines the uninitialized values for out parameters when calling into
/// Intercom interfaces.
pub trait ExternDefault {
    unsafe fn extern_default() -> Self;
}

impl<T> ExternDefault for T {
    default unsafe fn extern_default() -> Self { std::mem::zeroed() }
}

impl<TPtr> ExternDefault for *const TPtr {
    default unsafe fn extern_default() -> Self { std::ptr::null() }
}
<commit_msg>Add indirection level to ...TypeInfo traits<commit_after>
use crate::prelude::*;

#[derive(
    Debug, Clone, Copy,
    Hash, PartialOrd, PartialEq,
)]
pub enum TypeSystemName {
    Automation,
    Raw,
}

/// Common trait for type systems.
pub trait TypeSystem : Clone + Copy {
    const AUTOMATION : TypeSystemName = TypeSystemName::Automation;
    const RAW : TypeSystemName = TypeSystemName::Raw;

    fn key() -> TypeSystemName;
}

/// Automation type system.
#[derive(Clone, Copy)]
pub struct AutomationTypeSystem;
impl TypeSystem for AutomationTypeSystem {
    fn key() -> TypeSystemName { TypeSystemName::Automation }
}

/// Raw type system.
#[derive(Clone, Copy)]
pub struct RawTypeSystem;
impl TypeSystem for RawTypeSystem {
    fn key() -> TypeSystemName { TypeSystemName::Raw }
}

/// Defines a type that has identical representation for both input and output directions.
pub trait BidirectionalTypeInfo {

    /// The name of the type.
    fn type_name() -> &'static str;
    fn indirection_level() -> u32 { 0 }
}

/// Defines details of the type that specify how to pass it as an input parameter.
pub trait InputTypeInfo {

    /// The name of the type.
    fn type_name() -> &'static str;
    fn indirection_level() -> u32 { 0 }
}

/// Defines details of the type that specify how to pass it as an output parameter.
pub trait OutputTypeInfo {

    /// The name of the type.
    fn type_name() -> &'static str;
    fn indirection_level() -> u32 { 0 }
}

/// Defines a type that is compatible with Intercom interfaces.
pub trait ExternType<TS: TypeSystem> : Sized {

    /// Type used when the Self type is encountered as an input parameter.
    type ExternInputType : InputTypeInfo;

    /// Type used when the Self type is encountered as an output type.
    type ExternOutputType : OutputTypeInfo;

    /// A possible temporary type used for converting `Self` into
    /// `ExternInputType` when calling Intercom interfaces from Rust.
    type OwnedExternType : IntercomFrom< Self > = Self;

    /// A possible temporary type used for converting `ExternInputType` into
    /// `Self` type when calling Rust through an Intercom interface.
    type OwnedNativeType : IntercomFrom< Self::ExternInputType > = Self;
}

/// A conversion that may fail by resulting in a `ComError .
pub trait IntercomFrom<TSource> : Sized {
    fn intercom_from( source : TSource ) -> ComResult<Self>;
}

/// Default identity blanket implementation.
impl<T> IntercomFrom<T> for T {
    default fn intercom_from( source: T ) -> ComResult<T> { Ok( source ) }
}

/// Blanket implementation for all cloneable instance references.
impl<TSource: Clone> IntercomFrom<&TSource> for TSource {
    fn intercom_from( source: &TSource ) -> ComResult<Self> {
        Ok( source.clone() )
    }
}

/// A conversion that may fail by resulting in a `ComError .
pub trait IntercomInto<TTarget> {
    fn intercom_into( self : Self ) -> ComResult<TTarget>;
}

/// Blanket implementation for reversing IntercomFrom into IntercomInto.
impl<TSource, TTarget: IntercomFrom<TSource>>
        IntercomInto<TTarget> for TSource
{
    default fn intercom_into( self: Self ) -> ComResult<TTarget> {
        TTarget::intercom_from( self )
    }
}

/// Bidirectional types can be used as input types.
impl<BT> InputTypeInfo for BT where BT: BidirectionalTypeInfo {

    /// The name of the type.
    fn type_name() -> &'static str { <BT as BidirectionalTypeInfo>::type_name() }
    fn indirection_level() -> u32 { <BT as BidirectionalTypeInfo>::indirection_level() }
}

/// Bidirectional types can be used as output types.
impl<BT> OutputTypeInfo for BT where BT: BidirectionalTypeInfo {

    /// The name of the type.
    fn type_name() -> &'static str { <BT as BidirectionalTypeInfo>::type_name() }
    fn indirection_level() -> u32 { <BT as BidirectionalTypeInfo>::indirection_level() }
}

/// A quick macro for implementing ExternType for various basic types that
/// should represent themselves.
///
/// Ideally we would use specialization here to implement ExternType for T,
/// but that prevents other crates from implementing a specialized version for
/// some reason.
macro_rules! self_extern {
    ( $t:ty ) => {

        impl BidirectionalTypeInfo for $t {

            /// The default name is the name of the type.
            fn type_name() -> &'static str { stringify!( $t ) }
        }

        impl<TS: TypeSystem> ExternType<TS> for $t {
            type ExternInputType = $t;
            type ExternOutputType = $t;
            type OwnedExternType = $t;
            type OwnedNativeType = $t;
        }
    }
}

// Define all types that should have built-in Self extern type.
self_extern!( () );
self_extern!( i8 );
self_extern!( i16 );
self_extern!( i32 );
self_extern!( i64 );
self_extern!( isize );
self_extern!( u8 );
self_extern!( u16 );
self_extern!( u32 );
self_extern!( u64 );
self_extern!( usize );
self_extern!( f32 );
self_extern!( f64 );
self_extern!( crate::raw::HRESULT );
self_extern!( crate::GUID );

self_extern!( std::ffi::c_void );
self_extern!(TypeSystemName);

// Any raw pointer is passed as is.

impl<TPtr> BidirectionalTypeInfo for *mut TPtr where TPtr: BidirectionalTypeInfo {

    /// The name of the type.
    fn type_name() -> &'static str { <TPtr as BidirectionalTypeInfo>::type_name() }
    fn indirection_level() -> u32 { <TPtr as BidirectionalTypeInfo>::indirection_level() + 1 }
}

impl<TS: TypeSystem, TPtr> ExternType<TS> for *mut TPtr where TPtr: BidirectionalTypeInfo {
    type ExternInputType = *mut TPtr;
    type ExternOutputType = *mut TPtr;
    type OwnedExternType = *mut TPtr;
    type OwnedNativeType = *mut TPtr;
}

impl<TPtr> BidirectionalTypeInfo for *const TPtr where TPtr: BidirectionalTypeInfo {

    /// The name of the type.
    fn type_name() -> &'static str { <TPtr as BidirectionalTypeInfo>::type_name() }
    fn indirection_level() -> u32 { <TPtr as BidirectionalTypeInfo>::indirection_level() + 1 }
}

impl<TS: TypeSystem, TPtr> ExternType<TS> for *const TPtr where TPtr: BidirectionalTypeInfo {
    type ExternInputType = *const TPtr;
    type ExternOutputType = *const TPtr;
    type OwnedExternType = *const TPtr;
    type OwnedNativeType = *const TPtr;
}

/// `ComItf` extern type implementation.

impl<I: crate::ComInterface + ?Sized> BidirectionalTypeInfo for crate::ComItf<I>
    where I: BidirectionalTypeInfo
{

    /// The name of the type.
    fn type_name() -> &'static str { <I as BidirectionalTypeInfo>::type_name() }
    fn indirection_level() -> u32 { <I as BidirectionalTypeInfo>::indirection_level() + 1 }
}

impl<TS: TypeSystem, I: crate::ComInterface + ?Sized> ExternType<TS>
        for crate::ComItf<I>
    where I: BidirectionalTypeInfo
{

    type ExternInputType = crate::raw::InterfacePtr<TS, I>;
    type ExternOutputType = crate::raw::InterfacePtr<TS, I>;
    type OwnedExternType = crate::raw::InterfacePtr<TS, I>;
    type OwnedNativeType = crate::raw::InterfacePtr<TS, I>;
}

impl<TS: TypeSystem, I: crate::ComInterface + ?Sized> ExternType<TS>
        for crate::raw::InterfacePtr<TS, I>
    where I: BidirectionalTypeInfo
{

    type ExternInputType = crate::raw::InterfacePtr<TS, I>;
    type ExternOutputType = crate::raw::InterfacePtr<TS, I>;
    type OwnedExternType = crate::raw::InterfacePtr<TS, I>;
    type OwnedNativeType = crate::raw::InterfacePtr<TS, I>;
}

impl<I: crate::ComInterface + ?Sized> BidirectionalTypeInfo for crate::ComRc<I>
    where I: BidirectionalTypeInfo
{

    /// The name of the type.
    fn type_name() -> &'static str { <I as BidirectionalTypeInfo>::type_name() }
    fn indirection_level() -> u32 { <I as BidirectionalTypeInfo>::indirection_level() + 1 }
}

impl<TS: TypeSystem, I: crate::ComInterface + ?Sized> ExternType<TS>
        for crate::ComRc<I>
    where I: BidirectionalTypeInfo
{

    type ExternInputType = crate::raw::InterfacePtr<TS, I>;
    type ExternOutputType = crate::raw::InterfacePtr<TS, I>;
    type OwnedExternType = crate::raw::InterfacePtr<TS, I>;
    type OwnedNativeType = crate::raw::InterfacePtr<TS, I>;
}

impl<TS: TypeSystem, I: crate::ComInterface + ?Sized> BidirectionalTypeInfo for crate::raw::InterfacePtr<TS, I>
    where I: BidirectionalTypeInfo
{

    /// The name of the type.
    fn type_name() -> &'static str { <I as BidirectionalTypeInfo>::type_name() }
    fn indirection_level() -> u32 { <I as BidirectionalTypeInfo>::indirection_level() + 1 }
}

impl<TS: TypeSystem, I: crate::ComInterface + ?Sized>
    IntercomFrom<crate::ComItf<I>> for crate::raw::InterfacePtr<TS, I>
{
    fn intercom_from( source: crate::ComItf<I> ) -> ComResult<Self> {
        Ok( crate::ComItf::ptr( &source ) )
    }
}

impl<TS: TypeSystem, I: crate::ComInterface + ?Sized>
    IntercomFrom<&crate::ComItf<I>> for crate::raw::InterfacePtr<TS, I>
{
    fn intercom_from( source: &crate::ComItf<I> ) -> ComResult<Self> {
        Ok( crate::ComItf::ptr( source ) )
    }
}

impl<TS: TypeSystem, I: crate::ComInterface + ?Sized>
IntercomFrom<crate::ComRc<I>> for crate::raw::InterfacePtr<TS, I>
{
    fn intercom_from( source: crate::ComRc<I> ) -> ComResult<Self> {
        Ok( crate::ComItf::ptr( &crate::ComRc::detach( source ) ) )
    }
}

impl<TS: TypeSystem, I: crate::ComInterface + ?Sized>
    IntercomFrom<crate::raw::InterfacePtr<TS, I>> for crate::ComRc<I>
{
    fn intercom_from( source: crate::raw::InterfacePtr<TS, I> ) -> ComResult<Self> {
        Ok( crate::ComRc::attach(
            crate::ComItf::maybe_wrap( source )
                .ok_or_else( || crate::ComError::E_INVALIDARG )? ) )
    }
}

impl<TS: TypeSystem, I: crate::ComInterface + ?Sized>
    IntercomFrom<crate::raw::InterfacePtr<TS, I>> for crate::ComItf<I>
{
    fn intercom_from( source: crate::raw::InterfacePtr<TS, I> ) -> ComResult<Self> {
        crate::ComItf::maybe_wrap( source )
                .ok_or_else( || crate::ComError::E_INVALIDARG )
    }
}

impl<TS: TypeSystem, I: crate::ComInterface + ?Sized>
    IntercomFrom<&crate::raw::InterfacePtr<TS, I>> for crate::ComItf<I>
{
    fn intercom_from( source: &crate::raw::InterfacePtr<TS, I> ) -> ComResult<Self> {
        crate::ComItf::maybe_wrap( source.clone() )
                .ok_or_else( || crate::ComError::E_INVALIDARG )
    }
}

/// Defines the uninitialized values for out parameters when calling into
/// Intercom interfaces.
pub trait ExternDefault {
    unsafe fn extern_default() -> Self;
}

impl<T> ExternDefault for T {
    default unsafe fn extern_default() -> Self { std::mem::zeroed() }
}

impl<TPtr> ExternDefault for *const TPtr {
    default unsafe fn extern_default() -> Self { std::ptr::null() }
}
<|endoftext|>


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

use std::collections::VecDeque;
use std::net::SocketAddr;
use std::sync::{Arc, Mutex};

use futures::{future, Future, Sink, Stream};
use futures::sync::{mpsc, oneshot};

use tokio_core::reactor::Handle;

use error;
use resp;
use super::connect::{connect, ClientConnection};

type PairedConnectionBox = Box<Future<Item = PairedConnection, Error = error::Error>>;

/// The default starting point to use most default Redis functionality.
///
/// Returns a future that resolves to a `PairedConnection`.
pub fn paired_connect(addr: &SocketAddr, handle: &Handle) -> PairedConnectionBox {
    let handle = handle.clone();
    let paired_con = connect(addr, &handle)
        .map(move |connection| {
            let ClientConnection { sender, receiver } = connection;
            let (out_tx, out_rx) = mpsc::unbounded();
            let sender = out_rx.fold(sender, |sender, msg| sender.send(msg).map_err(|_| ()));
            let resp_queue: Arc<Mutex<VecDeque<oneshot::Sender<resp::RespValue>>>> =
                Arc::new(Mutex::new(VecDeque::new()));
            let receiver_queue = resp_queue.clone();
            let receiver = receiver.for_each(move |msg| {
                let mut queue = receiver_queue.lock().expect("Lock is tainted");
                let dest = queue.pop_front().expect("Queue is empty");
                match dest.send(msg) {
                    Ok(()) => Ok(()),
                    // Ignore error as the channel may have been legitimately closed in the meantime
                    Err(_) => Ok(())
                }
            });
            handle.spawn(sender.map(|_| ()));
            handle.spawn(receiver.map_err(|_| ()));
            PairedConnection {
                out_tx: out_tx,
                resp_queue: resp_queue,
            }
        })
        .map_err(|e| e.into());
    Box::new(paired_con)
}

pub struct PairedConnection {
    out_tx: mpsc::UnboundedSender<resp::RespValue>,
    resp_queue: Arc<Mutex<VecDeque<oneshot::Sender<resp::RespValue>>>>,
}

pub type SendBox<T> = Box<Future<Item = T, Error = error::Error>>;

#[macro_export]
macro_rules! faf {
    ($e:expr) => (
        {
            use $crate::client::paired::SendBox;
            use $crate::resp;
            let _:SendBox<resp::RespValue> = $e;
        }
    )
}

impl PairedConnection {
    /// Sends a command to Redis.
    ///
    /// The message must be in the format of a single RESP message (or a format for which a
    /// conversion trait is defined).  Returned is a future that resolves to the value returned
    /// from Redis.  The type must be one for which the `resp::FromResp` trait is defined.
    ///
    /// The future will fail for numerous reasons, including but not limited to: IO issues, conversion
    /// problems, and server-side errors being returned by Redis.
    ///
    /// Behind the scenes the message is queued up and sent to Redis asynchronously before the
    /// future is realised.  As such, it is guaranteed that messages are sent in the same order
    /// that `send` is called.
    pub fn send<R, T: resp::FromResp + 'static>(&self, msg: R) -> SendBox<T>
        where R: Into<resp::RespValue>
    {
        let (tx, rx) = oneshot::channel();
        let mut queue = self.resp_queue.lock().expect("Tainted queue");
        queue.push_back(tx);
        self.out_tx
            .unbounded_send(msg.into())
            .expect("Failed to send");
        let future = rx.then(|v| match v {
                                 Ok(v) => future::result(T::from_resp(v)),
                                 Err(e) => future::err(e.into()),
                             });
        Box::new(future)
    }
}

mod commands {
    use resp::{ToRespString, RespValue};

    use super::SendBox;

    impl super::PairedConnection {
        pub fn append<K, V>(&self, (key, value): (K, V)) -> SendBox<usize>
            where K: ToRespString,
                  V: ToRespString
        {
            self.send(RespValue::Array(vec!["APPEND".to_resp_string(),
                                            key.to_resp_string(),
                                            value.to_resp_string()]))
        }
    }

    // MARKER - all accounted for above this line

    pub trait DelCommand {
        fn to_resp(&self) -> RespValue;
    }

    impl<'a, T: ToRespString> DelCommand for (T) {
        fn to_resp(&self) -> RespValue {
            RespValue::Array(vec!["DEL".to_resp_string(), self.to_resp_string()])
        }
    }

    impl<'a, T: ToRespString> DelCommand for (&'a [T]) {
        fn to_resp(&self) -> RespValue {
            let mut keys = Vec::with_capacity(self.len() + 1);
            keys.push("DEL".to_resp_string());
            keys.extend(self.iter().map(|key| key.to_resp_string()));
            RespValue::Array(keys)
        }
    }

    impl super::PairedConnection {
        pub fn del<C>(&self, cmd: C) -> SendBox<usize>
            where C: DelCommand
        {
            self.send(cmd.to_resp())
        }
    }

    #[cfg(test)]
    mod test {
        use futures::future;
        use futures::Future;

        use tokio_core::reactor::Core;

        fn setup() -> (Core, super::super::PairedConnectionBox) {
            let core = Core::new().unwrap();
            let handle = core.handle();
            let addr = "127.0.0.1:6379".parse().unwrap();

            (core, super::super::paired_connect(&addr, &handle))
        }

        fn setup_and_delete(keys: &[&str]) -> (Core, super::super::PairedConnectionBox) {
            let (mut core, connection) = setup();

            let delete = connection.and_then(|connection| connection.del(keys).map(|_| connection));

            let connection = core.run(delete).unwrap();
            (core, Box::new(future::ok(connection)))
        }

        #[test]
        fn append_test() {
            let (mut core, connection) = setup_and_delete(&["APPENDKEY"]);

            let connection = connection
                .and_then(|connection| connection.append(("APPENDKEY", "ABC")));

            let count = core.run(connection).unwrap();
            assert_eq!(count, 3);
        }

        #[test]
        fn del_test() {
            let (mut core, connection) = setup();

            let del_keys = "DEL_KEY";
            let connection = connection.and_then(|connection| connection.del((del_keys)));

            let _ = core.run(connection).unwrap();
        }

        #[test]
        fn del_test_string() {
            let (mut core, connection) = setup();

            let del_keys = String::from("DEL_KEY");
            let connection = connection.and_then(|connection| connection.del((del_keys)));

            let _ = core.run(connection).unwrap();
        }

        #[test]
        fn del_test_vec() {
            let (mut core, connection) = setup();

            let del_keys = vec!["DEL_KEY_1", "DEL_KEY_2"];
            let connection = connection
                .and_then(|connection| connection.del((del_keys.as_slice())));

            let _ = core.run(connection).unwrap();
        }

        #[test]
        fn del_test_vec_string() {
            let (mut core, connection) = setup();

            let del_keys = vec![String::from("DEL_KEY_1"), String::from("DEL_KEY_2")];
            let connection = connection
                .and_then(|connection| connection.del((del_keys.as_slice())));

            let _ = core.run(connection).unwrap();
        }

        #[test]
        fn del_test_ary() {
            let (mut core, connection) = setup();

            let del_keys = ["DEL_KEY_1", "DEL_KEY_2"];
            let connection = connection.and_then(|connection| connection.del((&del_keys[..])));

            let _ = core.run(connection).unwrap();
        }

        #[test]
        fn del_test_ary_string() {
            let (mut core, connection) = setup();

            let del_keys = [String::from("DEL_KEY_1"), String::from("DEL_KEY_2")];
            let connection = connection.and_then(|connection| connection.del((&del_keys[..])));

            let _ = core.run(connection).unwrap();
        }
    }
}<commit_msg>Macro for boiler-plate<commit_after>/*
 * Copyright 2017 Ben Ashford
 *
 * Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
 * http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
 * <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 * option. This file may not be copied, modified, or distributed
 * except according to those terms.
 */

use std::collections::VecDeque;
use std::net::SocketAddr;
use std::sync::{Arc, Mutex};

use futures::{future, Future, Sink, Stream};
use futures::sync::{mpsc, oneshot};

use tokio_core::reactor::Handle;

use error;
use resp;
use super::connect::{connect, ClientConnection};

type PairedConnectionBox = Box<Future<Item = PairedConnection, Error = error::Error>>;

/// The default starting point to use most default Redis functionality.
///
/// Returns a future that resolves to a `PairedConnection`.
pub fn paired_connect(addr: &SocketAddr, handle: &Handle) -> PairedConnectionBox {
    let handle = handle.clone();
    let paired_con = connect(addr, &handle)
        .map(move |connection| {
            let ClientConnection { sender, receiver } = connection;
            let (out_tx, out_rx) = mpsc::unbounded();
            let sender = out_rx.fold(sender, |sender, msg| sender.send(msg).map_err(|_| ()));
            let resp_queue: Arc<Mutex<VecDeque<oneshot::Sender<resp::RespValue>>>> =
                Arc::new(Mutex::new(VecDeque::new()));
            let receiver_queue = resp_queue.clone();
            let receiver = receiver.for_each(move |msg| {
                let mut queue = receiver_queue.lock().expect("Lock is tainted");
                let dest = queue.pop_front().expect("Queue is empty");
                match dest.send(msg) {
                    Ok(()) => Ok(()),
                    // Ignore error as the channel may have been legitimately closed in the meantime
                    Err(_) => Ok(())
                }
            });
            handle.spawn(sender.map(|_| ()));
            handle.spawn(receiver.map_err(|_| ()));
            PairedConnection {
                out_tx: out_tx,
                resp_queue: resp_queue,
            }
        })
        .map_err(|e| e.into());
    Box::new(paired_con)
}

pub struct PairedConnection {
    out_tx: mpsc::UnboundedSender<resp::RespValue>,
    resp_queue: Arc<Mutex<VecDeque<oneshot::Sender<resp::RespValue>>>>,
}

pub type SendBox<T> = Box<Future<Item = T, Error = error::Error>>;

#[macro_export]
macro_rules! faf {
    ($e:expr) => (
        {
            use $crate::client::paired::SendBox;
            use $crate::resp;
            let _:SendBox<resp::RespValue> = $e;
        }
    )
}

impl PairedConnection {
    /// Sends a command to Redis.
    ///
    /// The message must be in the format of a single RESP message (or a format for which a
    /// conversion trait is defined).  Returned is a future that resolves to the value returned
    /// from Redis.  The type must be one for which the `resp::FromResp` trait is defined.
    ///
    /// The future will fail for numerous reasons, including but not limited to: IO issues, conversion
    /// problems, and server-side errors being returned by Redis.
    ///
    /// Behind the scenes the message is queued up and sent to Redis asynchronously before the
    /// future is realised.  As such, it is guaranteed that messages are sent in the same order
    /// that `send` is called.
    pub fn send<R, T: resp::FromResp + 'static>(&self, msg: R) -> SendBox<T>
        where R: Into<resp::RespValue>
    {
        let (tx, rx) = oneshot::channel();
        let mut queue = self.resp_queue.lock().expect("Tainted queue");
        queue.push_back(tx);
        self.out_tx
            .unbounded_send(msg.into())
            .expect("Failed to send");
        let future = rx.then(|v| match v {
                                 Ok(v) => future::result(T::from_resp(v)),
                                 Err(e) => future::err(e.into()),
                             });
        Box::new(future)
    }
}

mod commands {
    use resp::{ToRespString, RespValue};

    use super::SendBox;

    macro_rules! resp_array {
        ($($e:expr),*) => {
            RespValue::Array(vec![
                $(
                    $e.to_resp_string(),
                )*
            ]);
        }
    }

    impl super::PairedConnection {
        pub fn append<K, V>(&self, (key, value): (K, V)) -> SendBox<usize>
            where K: ToRespString,
                  V: ToRespString
        {
            self.send(resp_array!["APPEND", key, value])
        }
    }

    // MARKER - all accounted for above this line

    pub trait DelCommand {
        fn to_resp(&self) -> RespValue;
    }

    impl<'a, T: ToRespString> DelCommand for (T) {
        fn to_resp(&self) -> RespValue {
            resp_array!["DEL", self]
        }
    }

    impl<'a, T: ToRespString> DelCommand for (&'a [T]) {
        fn to_resp(&self) -> RespValue {
            let mut keys = Vec::with_capacity(self.len() + 1);
            keys.push("DEL".to_resp_string());
            keys.extend(self.iter().map(|key| key.to_resp_string()));
            RespValue::Array(keys)
        }
    }

    impl super::PairedConnection {
        pub fn del<C>(&self, cmd: C) -> SendBox<usize>
            where C: DelCommand
        {
            self.send(cmd.to_resp())
        }
    }

    #[cfg(test)]
    mod test {
        use futures::future;
        use futures::Future;

        use tokio_core::reactor::Core;

        fn setup() -> (Core, super::super::PairedConnectionBox) {
            let core = Core::new().unwrap();
            let handle = core.handle();
            let addr = "127.0.0.1:6379".parse().unwrap();

            (core, super::super::paired_connect(&addr, &handle))
        }

        fn setup_and_delete(keys: &[&str]) -> (Core, super::super::PairedConnectionBox) {
            let (mut core, connection) = setup();

            let delete = connection.and_then(|connection| connection.del(keys).map(|_| connection));

            let connection = core.run(delete).unwrap();
            (core, Box::new(future::ok(connection)))
        }

        #[test]
        fn append_test() {
            let (mut core, connection) = setup_and_delete(&["APPENDKEY"]);

            let connection = connection
                .and_then(|connection| connection.append(("APPENDKEY", "ABC")));

            let count = core.run(connection).unwrap();
            assert_eq!(count, 3);
        }

        #[test]
        fn del_test() {
            let (mut core, connection) = setup();

            let del_keys = "DEL_KEY";
            let connection = connection.and_then(|connection| connection.del((del_keys)));

            let _ = core.run(connection).unwrap();
        }

        #[test]
        fn del_test_string() {
            let (mut core, connection) = setup();

            let del_keys = String::from("DEL_KEY");
            let connection = connection.and_then(|connection| connection.del((del_keys)));

            let _ = core.run(connection).unwrap();
        }

        #[test]
        fn del_test_vec() {
            let (mut core, connection) = setup();

            let del_keys = vec!["DEL_KEY_1", "DEL_KEY_2"];
            let connection = connection
                .and_then(|connection| connection.del((del_keys.as_slice())));

            let _ = core.run(connection).unwrap();
        }

        #[test]
        fn del_test_vec_string() {
            let (mut core, connection) = setup();

            let del_keys = vec![String::from("DEL_KEY_1"), String::from("DEL_KEY_2")];
            let connection = connection
                .and_then(|connection| connection.del((del_keys.as_slice())));

            let _ = core.run(connection).unwrap();
        }

        #[test]
        fn del_test_ary() {
            let (mut core, connection) = setup();

            let del_keys = ["DEL_KEY_1", "DEL_KEY_2"];
            let connection = connection.and_then(|connection| connection.del((&del_keys[..])));

            let _ = core.run(connection).unwrap();
        }

        #[test]
        fn del_test_ary_string() {
            let (mut core, connection) = setup();

            let del_keys = [String::from("DEL_KEY_1"), String::from("DEL_KEY_2")];
            let connection = connection.and_then(|connection| connection.del((&del_keys[..])));

            let _ = core.run(connection).unwrap();
        }
    }
}<|endoftext|>