<commit_before>//! REPL for the gluon programming language
#![doc(html_root_url="https://docs.rs/gluon_repl/0.4.1")] // # GLUON

#[macro_use]
extern crate log;
#[cfg(feature = "env_logger")]
extern crate env_logger;
#[macro_use]
extern crate clap;
extern crate futures;

#[macro_use]
extern crate gluon_vm;
extern crate gluon;

use gluon::base;
use gluon::parser;
use gluon::check;
use gluon::vm;

use gluon::{new_vm, Compiler, Thread, Error, Result};
use gluon::vm::thread::ThreadInternal;
use gluon::vm::Error as VMError;

mod repl;

fn run_files<'s, I>(vm: &Thread, files: I) -> Result<()>
where
    I: Iterator<Item = &'s str>,
{
    let mut compiler = Compiler::new();
    for file in files {
        compiler.load_file(&vm, file)?;
    }
    Ok(())
}

#[cfg(feature = "env_logger")]
fn init_env_logger() {
    let _ = ::env_logger::init();
}

#[cfg(not(feature = "env_logger"))]
fn init_env_logger() {}

fn fmt_file(name: &str) -> Result<()> {
    use std::io::{Read, Seek, SeekFrom, Write};
    use std::fs::{File, OpenOptions};

    use gluon::base::pretty_print::ExprPrinter;
    use gluon::base::source::Source;

    let mut input_file = OpenOptions::new()
        .read(true)
        .write(true)
        .open(name)?;

    let mut buffer = String::new();
    input_file.read_to_string(&mut buffer)?;

    let mut backup = File::create(&format!("{}.bk", name))?;
    backup.write_all(buffer.as_bytes())?;

    let expr = Compiler::new().parse_expr("", &buffer)?;

    let source = Source::new(&buffer);
    let printer = ExprPrinter::new(&source);

    let output = printer.format(100, &expr);
    input_file.seek(SeekFrom::Start(0))?;
    input_file.write_all(output.as_bytes())?;
    Ok(())
}

fn main() {
    const GLUON_VERSION: &'static str = env!("CARGO_PKG_VERSION");

    // Need the extra stack size when compiling the program using the msvc compiler
    ::std::thread::Builder::new()
        .stack_size(2 * 1024 * 1024)
        .spawn(|| {
            init_env_logger();

            let matches = clap_app!(gluon =>
                (version: GLUON_VERSION)
                (about: "executes gluon programs")
                (@arg REPL: -i --interactive "Starts the repl")
                (@subcommand fmt =>
                    (about: "Formats gluon source code")
                    (@arg INPUT: ... "Formats each file")
                )
                (@arg INPUT: ... "Executes each file as a gluon program")
            ).get_matches();
            if let Some(fmt_matches) = matches.subcommand_matches("fmt") {
                if let Some(args) = fmt_matches.values_of("INPUT") {
                    for arg in args {
                        if let Err(err) = fmt_file(arg) {
                            println!("{}", err);
                            std::process::exit(1);
                        }
                    }
                } else {
                    println!("Expected input arguments to `fmt`");
                    std::process::exit(1);
                }
            } else if matches.is_present("REPL") {
                if let Err(err) = repl::run() {
                    println!("{}", err);
                }
            } else if let Some(args) = matches.values_of("INPUT") {
                let vm = new_vm();
                match run_files(&vm, args) {
                    Ok(()) => (),
                    Err(err @ Error::VM(VMError::Message(_))) => {
                        println!("{}\n{}", err, vm.context().stack.stacktrace(0));
                    }
                    Err(msg) => println!("{}", msg),
                }
            } else {
                println!("{}", matches.usage());
            }
        })
        .unwrap()
        .join()
        .unwrap();
}

#[cfg(test)]
mod tests {
    // If nothing else this suppresses the unused imports warnings when compiling in test mode
    #[test]
    fn execute_repl_help() {
        super::main();
    }
}
<commit_msg>Allow formatting from/to stdin/stdout<commit_after>//! REPL for the gluon programming language
#![doc(html_root_url="https://docs.rs/gluon_repl/0.4.1")] // # GLUON

#[macro_use]
extern crate log;
#[cfg(feature = "env_logger")]
extern crate env_logger;
#[macro_use]
extern crate clap;
extern crate futures;

#[macro_use]
extern crate gluon_vm;
extern crate gluon;

use std::io;

use gluon::base;
use gluon::parser;
use gluon::check;
use gluon::vm;

use gluon::{new_vm, Compiler, Thread, Error, Result};
use gluon::vm::thread::ThreadInternal;
use gluon::vm::Error as VMError;

mod repl;

fn run_files<'s, I>(vm: &Thread, files: I) -> Result<()>
where
    I: Iterator<Item = &'s str>,
{
    let mut compiler = Compiler::new();
    for file in files {
        compiler.load_file(&vm, file)?;
    }
    Ok(())
}

#[cfg(feature = "env_logger")]
fn init_env_logger() {
    let _ = ::env_logger::init();
}

#[cfg(not(feature = "env_logger"))]
fn init_env_logger() {}

fn format(writer: &mut io::Write, buffer: &str) -> Result<usize> {
    use gluon::base::pretty_print::ExprPrinter;
    use gluon::base::source::Source;

    let expr = Compiler::new().parse_expr("", buffer)?;

    let source = Source::new(buffer);
    let printer = ExprPrinter::new(&source);

    let output = printer.format(100, &expr);
    writer.write_all(output.as_bytes())?;
    Ok(output.len())
}

fn fmt_file(name: &str) -> Result<()> {
    use std::io::{Read, Seek, SeekFrom, Write};
    use std::fs::{File, OpenOptions};

    let mut input_file = OpenOptions::new()
        .read(true)
        .write(true)
        .open(name)?;

    let mut buffer = String::new();
    input_file.read_to_string(&mut buffer)?;

    {
        let mut backup = File::create(&format!("{}.bk", name))?;
        backup.write_all(buffer.as_bytes())?;
    }

    input_file.seek(SeekFrom::Start(0))?;
    let written = format(&mut input_file, &buffer)?;
    // Truncate the file to remove any data that were there before
    input_file.set_len(written as u64)?;
    Ok(())
}

fn fmt_stdio() -> Result<()> {
    use std::io::{Read, stdin, stdout};

    let mut buffer = String::new();
    stdin().read_to_string(&mut buffer)?;

    format(&mut stdout(), &buffer)?;
    Ok(())
}

fn main() {
    const GLUON_VERSION: &'static str = env!("CARGO_PKG_VERSION");

    // Need the extra stack size when compiling the program using the msvc compiler
    ::std::thread::Builder::new()
        .stack_size(2 * 1024 * 1024)
        .spawn(|| {
            init_env_logger();

            let matches = clap_app!(gluon =>
                (version: GLUON_VERSION)
                (about: "executes gluon programs")
                (@arg REPL: -i --interactive "Starts the repl")
                (@subcommand fmt =>
                    (about: "Formats gluon source code")
                    (@arg INPUT: ... "Formats each file")
                )
                (@arg INPUT: ... "Executes each file as a gluon program")
            ).get_matches();
            if let Some(fmt_matches) = matches.subcommand_matches("fmt") {
                if let Some(args) = fmt_matches.values_of("INPUT") {
                    for arg in args {
                        if let Err(err) = fmt_file(arg) {
                            println!("{}", err);
                            std::process::exit(1);
                        }
                    }
                } else {
                    if let Err(err) = fmt_stdio() {
                        println!("{}", err);
                        std::process::exit(1);
                    }
                }
            } else if matches.is_present("REPL") {
                if let Err(err) = repl::run() {
                    println!("{}", err);
                }
            } else if let Some(args) = matches.values_of("INPUT") {
                let vm = new_vm();
                match run_files(&vm, args) {
                    Ok(()) => (),
                    Err(err @ Error::VM(VMError::Message(_))) => {
                        println!("{}\n{}", err, vm.context().stack.stacktrace(0));
                    }
                    Err(msg) => println!("{}", msg),
                }
            } else {
                println!("{}", matches.usage());
            }
        })
        .unwrap()
        .join()
        .unwrap();
}

#[cfg(test)]
mod tests {
    // If nothing else this suppresses the unused imports warnings when compiling in test mode
    #[test]
    fn execute_repl_help() {
        super::main();
    }
}
<|endoftext|>


<commit_before>use std::{
    cell::RefCell,
    rc::Rc,
    sync::{Arc, Mutex},
};

use smithay::{
    backend::renderer::buffer_dimensions,
    reexports::wayland_server::{
        protocol::{wl_buffer, wl_surface},
        Display, UserDataMap,
    },
    utils::{Logical, Physical, Point, Rectangle, Size},
    wayland::{
        compositor::{
            compositor_init, is_sync_subsurface, with_states, with_surface_tree_upward,
            BufferAssignment, SurfaceAttributes, TraversalAction,
        },
        seat::Seat,
        shell::{
            wlr_layer::{LayerShellRequest, LayerSurfaceAttributes},
            xdg::{
                xdg_shell_init, Configure, ShellState as XdgShellState,
                XdgPopupSurfaceRoleAttributes, XdgRequest, XdgToplevelSurfaceRoleAttributes,
            },
        },
        Serial,
    },
};

//pub mod layer;
pub mod layout;
pub mod output;
pub mod window;
pub mod workspace;

use self::{
    layout::Layout,
    window::{Kind as SurfaceKind, PopupKind},
    workspace::Workspaces,
};
use crate::{
    backend::render::BufferTextures,
    state::Fireplace,
};

#[derive(Clone)]
pub struct ShellHandles {
    pub xdg_state: Arc<Mutex<XdgShellState>>,
    pub workspaces: Rc<RefCell<Workspaces>>,
    pub popups: Rc<RefCell<Vec<PopupKind>>>,
}

pub fn init_shell(display: Rc<RefCell<Display>>) -> ShellHandles {
    // Create the compositor
    compositor_init(
        &mut *display.borrow_mut(),
        move |surface, mut ddata| {
            let state = ddata.get::<Fireplace>().unwrap();
            let mut workspaces = state.workspaces.borrow_mut();
            let mut popups = state.popups.borrow_mut();
            surface_commit(&surface, &mut *workspaces, &mut *popups)
        },
        None,
    );

    let popups = Rc::new(RefCell::new(Vec::new()));
    let workspaces = Rc::new(RefCell::new(Workspaces::new(display.clone())));

    // init the xdg_shell
    let (xdg_shell_state, _, _) = xdg_shell_init(
        &mut *display.borrow_mut(),
        move |shell_event, mut ddata| {
            let state = ddata.get::<Fireplace>().unwrap();
            let mut workspaces = state.workspaces.borrow_mut();
            let mut popups = state.popups.borrow_mut();
            match shell_event {
                XdgRequest::NewToplevel { surface } => {
                    let seat = state.last_active_seat();
                    let space = workspaces.space_by_seat(&seat).unwrap();
                    space.new_toplevel(SurfaceKind::Xdg(surface));
                }
                XdgRequest::NewPopup { surface, .. /*TODO*/ } => {
                    popups.push(PopupKind::Xdg(surface));
                }
                XdgRequest::Move {
                    surface,
                    seat,
                    serial,
                } => {
                    let seat = Seat::from_resource(&seat).unwrap();
                    // TODO: touch move.
                    let pointer = seat.get_pointer().unwrap();

                    // Check that this surface has a click grab.
                    if !pointer.has_grab(serial) {
                        return;
                    }

                    let start_data = pointer.grab_start_data().unwrap();

                    // If the focus was for a different surface, ignore the request.
                    if start_data.focus.is_none()
                        || !start_data
                            .focus
                            .as_ref()
                            .unwrap()
                            .0
                            .as_ref()
                            .same_client_as(surface.get_surface().unwrap().as_ref())
                    {
                        return;
                    }

                    let toplevel = SurfaceKind::Xdg(surface.clone());

                    let space = workspaces.space_by_seat(&seat).unwrap();
                    space.move_request(toplevel, &seat, serial, start_data)
                }
                XdgRequest::Resize {
                    surface,
                    seat,
                    serial,
                    edges,
                } => {
                    let seat = Seat::from_resource(&seat).unwrap();
                    // TODO: touch resize.
                    let pointer = seat.get_pointer().unwrap();

                    // Check that this surface has a click grab.
                    if !pointer.has_grab(serial) {
                        return;
                    }

                    let start_data = pointer.grab_start_data().unwrap();

                    // If the focus was for a different surface, ignore the request.
                    if start_data.focus.is_none()
                        || !start_data
                            .focus
                            .as_ref()
                            .unwrap()
                            .0
                            .as_ref()
                            .same_client_as(surface.get_surface().unwrap().as_ref())
                    {
                        return;
                    }

                    let toplevel = SurfaceKind::Xdg(surface.clone());

                    let space = workspaces.space_by_seat(&seat).unwrap();
                    space.resize_request(toplevel, &seat, serial, start_data, edges)
                }
                XdgRequest::AckConfigure {
                    surface,
                    configure: Configure::Toplevel(configure),
                    ..
                } => {
                    if let Some(space) = workspaces.space_by_surface(&surface) {
                        space.ack_configure(surface, configure);
                    }
                }
                XdgRequest::Fullscreen {
                    surface, output, ..
                } => {
                    // NOTE: This is only one part of the solution. We can set the
                    // location and configure size here, but the surface should be rendered fullscreen
                    // independently from its buffer size
                    if let Some(wl_surface) = surface.get_surface() {
                        let toplevel = SurfaceKind::Xdg(surface.clone());
                        if let Some(space) = if let Some(output) = output {
                            if let Some(output_requested) = workspaces
                                .output_by_wl(&output)
                                .map(|x| String::from(x.name()))
                            {
                                let space_requested_id = workspaces
                                    .space_by_output_name(&output_requested)
                                    .map(|x| x.id());
                                let current_space_id =
                                    workspaces.space_by_surface(&wl_surface).map(|x| x.id());
                                if space_requested_id != current_space_id {
                                    if let Some(current_space) =
                                        workspaces.space_by_surface(&wl_surface)
                                    {
                                        current_space.remove_toplevel(toplevel.clone());
                                    }
                                    if let Some(space) =
                                        workspaces.space_by_output_name(&output_requested)
                                    {
                                        space.new_toplevel(toplevel.clone());
                                    }
                                }
                                workspaces.space_by_output_name(&output_requested)
                            } else {
                                None
                            }
                        } else {
                            workspaces.space_by_surface(&wl_surface)
                        } {
                            space.fullscreen_request(toplevel, true);
                        }
                    }
                }
                XdgRequest::UnFullscreen { surface } => {
                    if let Some(wl_surface) = surface.get_surface() {
                        if let Some(space) = workspaces.space_by_surface(wl_surface) {
                            let toplevel = SurfaceKind::Xdg(surface.clone());
                            space.fullscreen_request(toplevel, false);
                        }
                    }
                }
                XdgRequest::Maximize { surface } => {
                    if let Some(wl_surface) = surface.get_surface() {
                        if let Some(space) = workspaces.space_by_surface(wl_surface) {
                            let toplevel = SurfaceKind::Xdg(surface.clone());
                            space.maximize_request(toplevel, true);
                        }
                    }
                }
                XdgRequest::UnMaximize { surface } => {
                    if let Some(wl_surface) = surface.get_surface() {
                        if let Some(space) = workspaces.space_by_surface(wl_surface) {
                            let toplevel = SurfaceKind::Xdg(surface.clone());
                            space.maximize_request(toplevel, false);
                        }
                    }
                }
                _ => (),
            }
        },
        None,
    );

    /*
    smithay::wayland::shell::wlr_layer::wlr_layer_shell_init(
        &mut *display.borrow_mut(),
        move |event, mut ddata| match event {
            LayerShellRequest::NewLayerSurface {
                surface,
                output,
                layer,
                ..
            } => {
                let output_map = layer_output_map.borrow();
                let anvil_state = ddata.get::<AnvilState<BackendData>>().unwrap();

                let output = output.and_then(|output| output_map.find_by_output(&output));
                let output = output.unwrap_or_else(|| {
                    output_map
                        .find_by_position(anvil_state.pointer_location.to_i32_round())
                        .unwrap_or_else(|| output_map.with_primary().unwrap())
                });

                if let Some(wl_surface) = surface.get_surface() {
                    output.add_layer_surface(wl_surface.clone());

                    layer_window_map.borrow_mut().layers.insert(surface, layer);
                }
            }
            LayerShellRequest::AckConfigure { .. } => {}
        },
        log.clone(),
    );
    */

    ShellHandles {
        xdg_state: xdg_shell_state,
        workspaces,
        popups,
    }
}

#[derive(Default)]
pub struct SurfaceData {
    pub buffer: Option<wl_buffer::WlBuffer>,
    pub texture: Option<BufferTextures>,
    pub geometry: Option<Rectangle<i32, Logical>>,
    pub buffer_dimensions: Option<Size<i32, Physical>>,
    pub buffer_scale: i32,
    pub userdata: UserDataMap,
}

impl SurfaceData {
    pub fn update_buffer(&mut self, attrs: &mut SurfaceAttributes) {
        match attrs.buffer.take() {
            Some(BufferAssignment::NewBuffer { buffer, .. }) => {
                // new contents
                self.buffer_dimensions = buffer_dimensions(&buffer);
                self.buffer_scale = attrs.buffer_scale;
                if let Some(old_buffer) = std::mem::replace(&mut self.buffer, Some(buffer)) {
                    old_buffer.release();
                }
                self.texture = None;
            }
            Some(BufferAssignment::Removed) => {
                // remove the contents
                self.buffer = None;
                self.buffer_dimensions = None;
                self.texture = None;
            }
            None => {}
        }
    }

    /// Returns the size of the surface.
    pub fn size(&self) -> Option<Size<i32, Logical>> {
        self.buffer_dimensions
            .map(|dims| dims.to_logical(self.buffer_scale))
    }

    /// Checks if the surface's input region contains the point.
    pub fn contains_point(&self, attrs: &SurfaceAttributes, point: Point<f64, Logical>) -> bool {
        let size = match self.size() {
            None => return false, // If the surface has no size, it can't have an input region.
            Some(size) => size,
        };

        let rect = Rectangle {
            loc: (0, 0).into(),
            size,
        }
        .to_f64();

        // The input region is always within the surface itself, so if the surface itself doesn't contain the
        // point we can return false.
        if !rect.contains(point) {
            return false;
        }

        // If there's no input region, we're done.
        if attrs.input_region.is_none() {
            return true;
        }

        attrs
            .input_region
            .as_ref()
            .unwrap()
            .contains(point.to_i32_floor())
    }

    /// Send the frame callback if it had been requested
    pub fn send_frame(attrs: &mut SurfaceAttributes, time: u32) {
        for callback in attrs.frame_callbacks.drain(..) {
            callback.done(time);
        }
    }

    pub fn userdata(&self) -> &UserDataMap {
        &self.userdata
    }
}

fn surface_commit(
    surface: &wl_surface::WlSurface,
    workspaces: &mut Workspaces,
    popups: &mut Vec<PopupKind>,
) {
    #[cfg(feature = "xwayland")]
    super::xwayland::commit_hook(surface);

    if !is_sync_subsurface(surface) {
        // Update the buffer of all child surfaces
        with_surface_tree_upward(
            surface,
            (),
            |_, _, _| TraversalAction::DoChildren(()),
            |_, states, _| {
                states
                    .data_map
                    .insert_if_missing(|| RefCell::new(SurfaceData::default()));
                let mut data = states
                    .data_map
                    .get::<RefCell<SurfaceData>>()
                    .unwrap()
                    .borrow_mut();
                data.update_buffer(&mut *states.cached_state.current::<SurfaceAttributes>());
            },
            |_, _, _| true,
        );
    }

    let toplevel = workspaces.toplevel_by_surface(surface);
    if let Some(toplevel) = toplevel {
        // send the initial configure if relevant
        #[allow(irrefutable_let_patterns)]
        if let SurfaceKind::Xdg(ref toplevel) = toplevel {
            let initial_configure_sent = with_states(surface, |states| {
                states
                    .data_map
                    .get::<Mutex<XdgToplevelSurfaceRoleAttributes>>()
                    .unwrap()
                    .lock()
                    .unwrap()
                    .initial_configure_sent
            })
            .unwrap();
            if !initial_configure_sent {
                toplevel.send_configure();
            }
        }

        if let Some(space) = workspaces.space_by_surface(surface) {
            space.commit(toplevel.clone());
        }
    }

    if let Some(popup) = popups.iter().find(|x| x.get_surface() == Some(surface)) {
        let PopupKind::Xdg(ref popup) = popup;
        let initial_configure_sent = with_states(surface, |states| {
            states
                .data_map
                .get::<Mutex<XdgPopupSurfaceRoleAttributes>>()
                .unwrap()
                .lock()
                .unwrap()
                .initial_configure_sent
        })
        .unwrap();
        if !initial_configure_sent {
            // TODO: properly recompute the geometry with the whole of positioner state
            popup.send_configure();
        }
    }

    /*
    if let Some(layer) = window_map.layers.find(surface) {
        // send the initial configure if relevant
        let initial_configure_sent = with_states(surface, |states| {
            states
                .data_map
                .get::<Mutex<LayerSurfaceAttributes>>()
                .unwrap()
                .lock()
                .unwrap()
                .initial_configure_sent
        })
        .unwrap();
        if !initial_configure_sent {
            layer.surface.send_configure();
        }

        if let Some(output) = output_map.borrow().find_by_layer_surface(surface) {
            window_map.layers.arange_layers(output);
        }
    }
    */
}

pub fn child_popups<'a>(popups: impl DoubleEndedIterator<Item=&'a PopupKind>, base: &'a wl_surface::WlSurface) -> impl Iterator<Item=&'a PopupKind> {
    popups
        .rev()
        .filter(move |w| w.parent().as_ref() == Some(base))
}
<commit_msg>shell: Fixup wrong buffer releases in buffer reuse edge-cases<commit_after>use std::{
    cell::RefCell,
    rc::Rc,
    sync::{Arc, Mutex},
};

use smithay::{
    backend::renderer::buffer_dimensions,
    reexports::wayland_server::{
        protocol::{wl_buffer, wl_surface},
        Display, UserDataMap,
    },
    utils::{Logical, Physical, Point, Rectangle, Size},
    wayland::{
        compositor::{
            compositor_init, is_sync_subsurface, with_states, with_surface_tree_upward,
            BufferAssignment, SurfaceAttributes, TraversalAction,
        },
        seat::Seat,
        shell::{
            wlr_layer::{LayerShellRequest, LayerSurfaceAttributes},
            xdg::{
                xdg_shell_init, Configure, ShellState as XdgShellState,
                XdgPopupSurfaceRoleAttributes, XdgRequest, XdgToplevelSurfaceRoleAttributes,
            },
        },
        Serial,
    },
};

//pub mod layer;
pub mod layout;
pub mod output;
pub mod window;
pub mod workspace;

use self::{
    layout::Layout,
    window::{Kind as SurfaceKind, PopupKind},
    workspace::Workspaces,
};
use crate::{
    backend::render::BufferTextures,
    state::Fireplace,
};

#[derive(Clone)]
pub struct ShellHandles {
    pub xdg_state: Arc<Mutex<XdgShellState>>,
    pub workspaces: Rc<RefCell<Workspaces>>,
    pub popups: Rc<RefCell<Vec<PopupKind>>>,
}

pub fn init_shell(display: Rc<RefCell<Display>>) -> ShellHandles {
    // Create the compositor
    compositor_init(
        &mut *display.borrow_mut(),
        move |surface, mut ddata| {
            let state = ddata.get::<Fireplace>().unwrap();
            let mut workspaces = state.workspaces.borrow_mut();
            let mut popups = state.popups.borrow_mut();
            surface_commit(&surface, &mut *workspaces, &mut *popups)
        },
        None,
    );

    let popups = Rc::new(RefCell::new(Vec::new()));
    let workspaces = Rc::new(RefCell::new(Workspaces::new(display.clone())));

    // init the xdg_shell
    let (xdg_shell_state, _, _) = xdg_shell_init(
        &mut *display.borrow_mut(),
        move |shell_event, mut ddata| {
            let state = ddata.get::<Fireplace>().unwrap();
            let mut workspaces = state.workspaces.borrow_mut();
            let mut popups = state.popups.borrow_mut();
            match shell_event {
                XdgRequest::NewToplevel { surface } => {
                    let seat = state.last_active_seat();
                    let space = workspaces.space_by_seat(&seat).unwrap();
                    space.new_toplevel(SurfaceKind::Xdg(surface));
                }
                XdgRequest::NewPopup { surface, .. /*TODO*/ } => {
                    popups.push(PopupKind::Xdg(surface));
                }
                XdgRequest::Move {
                    surface,
                    seat,
                    serial,
                } => {
                    let seat = Seat::from_resource(&seat).unwrap();
                    // TODO: touch move.
                    let pointer = seat.get_pointer().unwrap();

                    // Check that this surface has a click grab.
                    if !pointer.has_grab(serial) {
                        return;
                    }

                    let start_data = pointer.grab_start_data().unwrap();

                    // If the focus was for a different surface, ignore the request.
                    if start_data.focus.is_none()
                        || !start_data
                            .focus
                            .as_ref()
                            .unwrap()
                            .0
                            .as_ref()
                            .same_client_as(surface.get_surface().unwrap().as_ref())
                    {
                        return;
                    }

                    let toplevel = SurfaceKind::Xdg(surface.clone());

                    let space = workspaces.space_by_seat(&seat).unwrap();
                    space.move_request(toplevel, &seat, serial, start_data)
                }
                XdgRequest::Resize {
                    surface,
                    seat,
                    serial,
                    edges,
                } => {
                    let seat = Seat::from_resource(&seat).unwrap();
                    // TODO: touch resize.
                    let pointer = seat.get_pointer().unwrap();

                    // Check that this surface has a click grab.
                    if !pointer.has_grab(serial) {
                        return;
                    }

                    let start_data = pointer.grab_start_data().unwrap();

                    // If the focus was for a different surface, ignore the request.
                    if start_data.focus.is_none()
                        || !start_data
                            .focus
                            .as_ref()
                            .unwrap()
                            .0
                            .as_ref()
                            .same_client_as(surface.get_surface().unwrap().as_ref())
                    {
                        return;
                    }

                    let toplevel = SurfaceKind::Xdg(surface.clone());

                    let space = workspaces.space_by_seat(&seat).unwrap();
                    space.resize_request(toplevel, &seat, serial, start_data, edges)
                }
                XdgRequest::AckConfigure {
                    surface,
                    configure: Configure::Toplevel(configure),
                    ..
                } => {
                    if let Some(space) = workspaces.space_by_surface(&surface) {
                        space.ack_configure(surface, configure);
                    }
                }
                XdgRequest::Fullscreen {
                    surface, output, ..
                } => {
                    // NOTE: This is only one part of the solution. We can set the
                    // location and configure size here, but the surface should be rendered fullscreen
                    // independently from its buffer size
                    if let Some(wl_surface) = surface.get_surface() {
                        let toplevel = SurfaceKind::Xdg(surface.clone());
                        if let Some(space) = if let Some(output) = output {
                            if let Some(output_requested) = workspaces
                                .output_by_wl(&output)
                                .map(|x| String::from(x.name()))
                            {
                                let space_requested_id = workspaces
                                    .space_by_output_name(&output_requested)
                                    .map(|x| x.id());
                                let current_space_id =
                                    workspaces.space_by_surface(&wl_surface).map(|x| x.id());
                                if space_requested_id != current_space_id {
                                    if let Some(current_space) =
                                        workspaces.space_by_surface(&wl_surface)
                                    {
                                        current_space.remove_toplevel(toplevel.clone());
                                    }
                                    if let Some(space) =
                                        workspaces.space_by_output_name(&output_requested)
                                    {
                                        space.new_toplevel(toplevel.clone());
                                    }
                                }
                                workspaces.space_by_output_name(&output_requested)
                            } else {
                                None
                            }
                        } else {
                            workspaces.space_by_surface(&wl_surface)
                        } {
                            space.fullscreen_request(toplevel, true);
                        }
                    }
                }
                XdgRequest::UnFullscreen { surface } => {
                    if let Some(wl_surface) = surface.get_surface() {
                        if let Some(space) = workspaces.space_by_surface(wl_surface) {
                            let toplevel = SurfaceKind::Xdg(surface.clone());
                            space.fullscreen_request(toplevel, false);
                        }
                    }
                }
                XdgRequest::Maximize { surface } => {
                    if let Some(wl_surface) = surface.get_surface() {
                        if let Some(space) = workspaces.space_by_surface(wl_surface) {
                            let toplevel = SurfaceKind::Xdg(surface.clone());
                            space.maximize_request(toplevel, true);
                        }
                    }
                }
                XdgRequest::UnMaximize { surface } => {
                    if let Some(wl_surface) = surface.get_surface() {
                        if let Some(space) = workspaces.space_by_surface(wl_surface) {
                            let toplevel = SurfaceKind::Xdg(surface.clone());
                            space.maximize_request(toplevel, false);
                        }
                    }
                }
                _ => (),
            }
        },
        None,
    );

    /*
    smithay::wayland::shell::wlr_layer::wlr_layer_shell_init(
        &mut *display.borrow_mut(),
        move |event, mut ddata| match event {
            LayerShellRequest::NewLayerSurface {
                surface,
                output,
                layer,
                ..
            } => {
                let output_map = layer_output_map.borrow();
                let anvil_state = ddata.get::<AnvilState<BackendData>>().unwrap();

                let output = output.and_then(|output| output_map.find_by_output(&output));
                let output = output.unwrap_or_else(|| {
                    output_map
                        .find_by_position(anvil_state.pointer_location.to_i32_round())
                        .unwrap_or_else(|| output_map.with_primary().unwrap())
                });

                if let Some(wl_surface) = surface.get_surface() {
                    output.add_layer_surface(wl_surface.clone());

                    layer_window_map.borrow_mut().layers.insert(surface, layer);
                }
            }
            LayerShellRequest::AckConfigure { .. } => {}
        },
        log.clone(),
    );
    */

    ShellHandles {
        xdg_state: xdg_shell_state,
        workspaces,
        popups,
    }
}

#[derive(Default)]
pub struct SurfaceData {
    pub buffer: Option<wl_buffer::WlBuffer>,
    pub texture: Option<BufferTextures>,
    pub geometry: Option<Rectangle<i32, Logical>>,
    pub buffer_dimensions: Option<Size<i32, Physical>>,
    pub buffer_scale: i32,
    pub userdata: UserDataMap,
}

impl SurfaceData {
    pub fn update_buffer(&mut self, attrs: &mut SurfaceAttributes) {
        match attrs.buffer.take() {
            Some(BufferAssignment::NewBuffer { buffer, .. }) => {
                // new contents
                self.buffer_dimensions = buffer_dimensions(&buffer);
                self.buffer_scale = attrs.buffer_scale;

                if let Some(old_buffer) = std::mem::replace(&mut self.buffer, Some(buffer)) {
                    if &old_buffer != self.buffer.as_ref().unwrap() {
                    old_buffer.release();
                    }
                }
                self.texture = None;
            }
            Some(BufferAssignment::Removed) => {
                // remove the contents
                if let Some(buffer) = self.buffer.take() {
                    buffer.release();
                };
                self.buffer_dimensions = None;
                self.texture = None;
            }
            None => {}
        }
    }

    /// Returns the size of the surface.
    pub fn size(&self) -> Option<Size<i32, Logical>> {
        self.buffer_dimensions
            .map(|dims| dims.to_logical(self.buffer_scale))
    }

    /// Checks if the surface's input region contains the point.
    pub fn contains_point(&self, attrs: &SurfaceAttributes, point: Point<f64, Logical>) -> bool {
        let size = match self.size() {
            None => return false, // If the surface has no size, it can't have an input region.
            Some(size) => size,
        };

        let rect = Rectangle {
            loc: (0, 0).into(),
            size,
        }
        .to_f64();

        // The input region is always within the surface itself, so if the surface itself doesn't contain the
        // point we can return false.
        if !rect.contains(point) {
            return false;
        }

        // If there's no input region, we're done.
        if attrs.input_region.is_none() {
            return true;
        }

        attrs
            .input_region
            .as_ref()
            .unwrap()
            .contains(point.to_i32_floor())
    }

    /// Send the frame callback if it had been requested
    pub fn send_frame(attrs: &mut SurfaceAttributes, time: u32) {
        for callback in attrs.frame_callbacks.drain(..) {
            callback.done(time);
        }
    }

    pub fn userdata(&self) -> &UserDataMap {
        &self.userdata
    }
}

fn surface_commit(
    surface: &wl_surface::WlSurface,
    workspaces: &mut Workspaces,
    popups: &mut Vec<PopupKind>,
) {
    #[cfg(feature = "xwayland")]
    super::xwayland::commit_hook(surface);

    if !is_sync_subsurface(surface) {
        // Update the buffer of all child surfaces
        with_surface_tree_upward(
            surface,
            (),
            |_, _, _| TraversalAction::DoChildren(()),
            |_, states, _| {
                states
                    .data_map
                    .insert_if_missing(|| RefCell::new(SurfaceData::default()));
                let mut data = states
                    .data_map
                    .get::<RefCell<SurfaceData>>()
                    .unwrap()
                    .borrow_mut();
                data.update_buffer(&mut *states.cached_state.current::<SurfaceAttributes>());
            },
            |_, _, _| true,
        );
    }

    let toplevel = workspaces.toplevel_by_surface(surface);
    if let Some(toplevel) = toplevel {
        // send the initial configure if relevant
        #[allow(irrefutable_let_patterns)]
        if let SurfaceKind::Xdg(ref toplevel) = toplevel {
            let initial_configure_sent = with_states(surface, |states| {
                states
                    .data_map
                    .get::<Mutex<XdgToplevelSurfaceRoleAttributes>>()
                    .unwrap()
                    .lock()
                    .unwrap()
                    .initial_configure_sent
            })
            .unwrap();
            if !initial_configure_sent {
                toplevel.send_configure();
            }
        }

        if let Some(space) = workspaces.space_by_surface(surface) {
            space.commit(toplevel.clone());
        }
    }

    if let Some(popup) = popups.iter().find(|x| x.get_surface() == Some(surface)) {
        let PopupKind::Xdg(ref popup) = popup;
        let initial_configure_sent = with_states(surface, |states| {
            states
                .data_map
                .get::<Mutex<XdgPopupSurfaceRoleAttributes>>()
                .unwrap()
                .lock()
                .unwrap()
                .initial_configure_sent
        })
        .unwrap();
        if !initial_configure_sent {
            // TODO: properly recompute the geometry with the whole of positioner state
            popup.send_configure();
        }
    }

    /*
    if let Some(layer) = window_map.layers.find(surface) {
        // send the initial configure if relevant
        let initial_configure_sent = with_states(surface, |states| {
            states
                .data_map
                .get::<Mutex<LayerSurfaceAttributes>>()
                .unwrap()
                .lock()
                .unwrap()
                .initial_configure_sent
        })
        .unwrap();
        if !initial_configure_sent {
            layer.surface.send_configure();
        }

        if let Some(output) = output_map.borrow().find_by_layer_surface(surface) {
            window_map.layers.arange_layers(output);
        }
    }
    */
}

pub fn child_popups<'a>(popups: impl DoubleEndedIterator<Item=&'a PopupKind>, base: &'a wl_surface::WlSurface) -> impl Iterator<Item=&'a PopupKind> {
    popups
        .rev()
        .filter(move |w| w.parent().as_ref() == Some(base))
}
<|endoftext|>


<commit_before>use std::mem;
use std::fmt;
use std::ptr;
use std::iter;

use rand::{thread_rng, Rng};

// 32
const DEFAULT_LEVEL: usize = 3;

type Link<T> = Option<Box<T>>;

#[allow(raw_pointer_derive)]
#[derive(Debug)]
struct Rawlink<T> {
    p: *mut T,
}

impl<T> Copy for Rawlink<T> {}
unsafe impl<T:Send> Send for Rawlink<T> {}
unsafe impl<T:Sync> Sync for Rawlink<T> {}

fn random_level() -> usize {
    let mut rng = thread_rng();
    let mut level = 0;
    loop {
        if rng.gen_weighted_bool(2) {
            level += 1;
            continue;
        }
        break;
    }

    level
}

#[derive(Debug)]
pub struct SkipNode<Key,E> {
    key: Key,
    it: E,
    next: Link<SkipNode<Key,E>>,
    prev: Rawlink<SkipNode<Key,E>>,
    // level 0 to DEFAULT_LEVEL
    forward: Vec<Rawlink<SkipNode<Key,E>>>,
}

impl<Key: PartialOrd, E> SkipNode<Key,E> {
    // level: 0 ~ DEFAULT_LEVEL
    fn new(key: Key, it: E, level: usize) -> SkipNode<Key,E> {
        SkipNode {
            key: key,
            it: it,
            next: None,
            prev: Rawlink::none(),
            forward: iter::repeat(Rawlink::none()).take(level).collect(),
        }
    }

    #[inline]
    fn level(&self) -> usize {
        self.forward.len()
    }

    fn to_ptr(&mut self) -> Rawlink<SkipNode<Key,E>> {
        Rawlink::some(self)
    }

    fn adjust_head(&mut self, new_level: usize) {
        let diff = new_level - self.level();
        if diff > 0 {
            self.forward.append(&mut iter::repeat(Rawlink::none()).take(diff).collect())
        }
    }

    fn insert(&mut self, key: Key, it: E, level: usize) {
    }
}

pub struct SkipList<Key,E> {
    head: Link<SkipNode<Key,E>>,
    forward: Vec<Rawlink<SkipNode<Key,E>>>,
    level: usize,
    size: usize,
}

impl<Key: PartialOrd + fmt::Debug, E: fmt::Debug> SkipList<Key,E> {
    /// create new empty SkipList
    pub fn new() -> SkipList<Key, E> {
        SkipList {
            head: None,
            forward: iter::repeat(Rawlink::none()).take(DEFAULT_LEVEL).collect(),
            level: DEFAULT_LEVEL,
            size: 0,
        }
    }

    pub fn level(&self) -> usize {
        self.level
    }

    pub fn contains_key(&self, key: &Key) -> bool {
        self.find(key).is_some()
    }

    pub fn find(&self, key: &Key) -> Option<&E> {
        let level = self.level();
        let mut x = self.forward[level-1];
        for i in (0..level).rev() {
            while x.resolve().map_or(false, |n| n.forward[i].is_some()) &&
                x.resolve().map_or(false, |n| n.forward[i].resolve().unwrap().key < *key) {
                    let nx = x.resolve().map_or_else(Rawlink::none, |n| n.forward[i] );
                    x = nx;
                }
        }

        while x.resolve().map_or(false, |n| n.next.is_some()) &&
            x.resolve().map_or(false, |n| n.next.as_ref().unwrap().key < *key) {
                let nx = x.resolve_mut().map_or_else(Rawlink::none, |n| {
                    n.next.as_mut().map_or_else(Rawlink::none, |n| Rawlink::some(&mut **n))
                });
                x = nx
            }

        x.resolve().map_or(None, |n| {
            if n.key == *key {
                Some(&n.it)
            } else {
                None
            }
        })
    }

    fn adjust_head(&mut self, new_level: usize) {
        let diff = new_level - self.level;
        if diff > 0 {
            self.forward.append(&mut iter::repeat(Rawlink::none()).take(diff).collect())
        }
    }

    // Due to head node must be of same level as List,
    // inserting with decreasing order will lead to almost same bad performance as a linked list
    pub fn insert(&mut self, key: Key, it: E) {
        let mut new_level = random_level();
        if new_level > self.level { // new node will be deepest
            self.adjust_head(new_level);
            self.level = new_level;
        }
        self.size += 1;

        if self.head.is_none() {
            new_level = self.level;
            self.head = Some(Box::new(SkipNode::new(key, it, new_level)));
            let p = Rawlink::from(&mut self.head);
            for i in 0..new_level {
                self.forward[i] = p;
            }
        } else if self.head.as_ref().map_or(false, |n| n.key > key) {
            new_level = self.level;
            // insert at head
            let mut new_node = Some(Box::new(SkipNode::new(key, it, new_level)));
            let new_link = new_node.as_mut().map_or_else(Rawlink::none, |n| {
                Rawlink::some(&mut **n)
            });

            for i in 0..new_level {
                new_node.as_mut().map(|n| {
                    n.forward[i] = self.forward[i]
                });
            }

            for i in 0..new_level {
                self.forward[i] = new_link
            }

            new_node.as_mut().map(|n| n.next = self.head.take());
            self.head = new_node;
        } else {
            let mut x = self.head.as_mut().map_or_else(Rawlink::none, |n| {
                Rawlink::some(&mut **n)
            });
            // insert normally
            let mut update: Vec<Rawlink<SkipNode<Key,E>>> = self.forward[..new_level].to_vec();
            if new_level > 0 {  // need to insert skip pointers
                x = update[new_level-1];
                for i in (0..new_level).rev() {
                    while x.resolve().map_or(false, |n| n.forward[i].is_some()) &&
                        x.resolve().map_or(false, |n| n.forward[i].resolve().unwrap().key < key) {
                            let nx = x.resolve().map_or_else(Rawlink::none, |n| n.forward[i] );
                            x = nx;
                        }
                    update[i] = x.resolve_mut().map_or_else(Rawlink::none, |n| {
                        Rawlink::some(&mut *n)
                    });
                }
            }

            let mut y = x.resolve_mut().map_or_else(Rawlink::none, |n| {
                Rawlink::some(&mut *n)
            });
            // When head node level is lower than current
            if y.is_none() {
                println!("update => {:?}", update);
                y = self.head.as_mut().map_or_else(Rawlink::none, |n| {
                    Rawlink::some(&mut **n)
                });
            }
            while y.resolve().map_or(false, |n| n.next.is_some()) &&
                y.resolve().map_or(false, |n| n.next.as_ref().unwrap().key < key) {
                    let ny = y.resolve_mut().map_or_else(Rawlink::none, |n| {
                        n.next.as_mut().map_or_else(Rawlink::none, |n| Rawlink::some(&mut **n))
                    });
                    y = ny
                }
            assert!(y.is_some());
            // create node and insert
            let mut new_node = Some(Box::new(SkipNode::new(key, it, self.level)));
            let new_link = new_node.as_mut().map_or_else(Rawlink::none, |n| {
                Rawlink::some(&mut **n)
            });

            for i in 0..new_level {
                new_node.as_mut().map(|n| {
                    n.forward[i] = update[i].resolve_mut().map_or_else(Rawlink::none, |nx| {
                        nx.forward[i]
                    });
                });
                // if update is empty, then update head node's link
                update[i].resolve_mut().map_or_else(|| {
                    self.forward[i] = new_link;
                },
                    |prev| {
                    prev.forward[i] = new_link;
                });
            }

            // move in
            y.resolve_mut().map(|n| {
                new_node.as_mut().map(|new| {
                    new.next = n.next.take();
                });
                n.next = new_node;
            });
        }
    }

    pub fn remove(&mut self, key: &Key) -> Option<E> {
        if self.head.is_none() {
            return None;
        }
        let level = self.level();
        let mut x = self.forward[level-1];
        let mut left = x;

        for i in (0..level).rev() {
            while x.resolve().map_or(false, |n| n.forward[i].is_some()) &&
                x.resolve().map_or(false, |n| n.forward[i].resolve().unwrap().key < *key) {
                    let nx = x.resolve().map_or_else(Rawlink::none, |n| n.forward[i] );
                    x = nx;
                }
        }

        while x.resolve().map_or(false, |n| n.next.is_some()) &&
            x.resolve().map_or(false, |n| n.next.as_ref().unwrap().key < *key) {
                let nx = x.resolve_mut().map_or_else(Rawlink::none, |n| {
                    n.next.as_mut().map_or_else(Rawlink::none, |n| Rawlink::some(&mut **n))
                });
                left = x;
                x = nx
            }

        if !x.resolve().map_or(false, |n| n.key == *key ) {
            None
        } else if x.p == left.p && x.is_some() {
            println!("fuck equels");
            // this means remove head
            let head = self.head.take().unwrap();
            // remove box
            let head = *head;
            let SkipNode { it, next, forward, .. } = head;
            self.head = next;
            self.forward = forward;
            self.head.as_mut().map(|n| n.adjust_head(level));
            Some(it)
        } else {
            unimplemented!()
        }
    }

    pub fn size(&self) -> usize {
        self.size
    }
}

impl<Key: PartialOrd + fmt::Display + fmt::Debug, E: fmt::Debug> fmt::Display for SkipList<Key,E> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.head.is_none() {
            write!(f, "<empty skip list>")
        } else {
            write!(f, "\nlv0 ");
            let mut x = self.head.as_ref();
            while x.is_some() {
                write!(f, "{} --> ", x.as_ref().map_or_else(String::new, |n| format!("{}", n.key)));
                x = x.as_ref().map_or(None, |n| n.next.as_ref());
            }
            writeln!(f, "");
            for i in 0..self.level {
                write!(f, "lv{} ", i+1);
                let mut x = self.forward[i];
                while x.is_some() {
                    write!(f, "{} ..> ",
                           x.resolve().map_or_else(String::new, |n| format!("{}", n.key)));
                    if x.resolve().map_or(false, |n| n.level() <= i) {
                        break;
                    }
                    x = x.resolve().map_or_else(Rawlink::none, |n| n.forward[i]);
                }
                writeln!(f, "");
            }
            Ok(())
        }
    }
}

/// Rawlink is a type like Option<T> but for holding a raw mutable pointer.
impl<T> Rawlink<T> {
    /// Like `Option::None` for Rawlink.
    fn none() -> Rawlink<T> {
        Rawlink{p: ptr::null_mut()}
    }

    /// Like `Option::Some` for Rawlink
    fn some(n: &mut T) -> Rawlink<T> {
        Rawlink{p: n}
    }

    fn is_some(&self) -> bool {
        !self.is_none()
    }

    fn is_none(&self) -> bool {
        self.p.is_null()
    }

    fn take(&mut self) -> Rawlink<T> {
        mem::replace(self, Rawlink::none())
    }

    /// Convert the `Rawlink` into an immutable Option value.
    fn resolve<'a>(&self) -> Option<&'a T> {
        if self.p.is_null() {
            None
        } else {
            Some(unsafe { &*self.p })
        }
    }

    /// Convert the `Rawlink` into a mutable Option value.
    fn resolve_mut<'a>(&mut self) -> Option<&'a mut T> {
        if self.p.is_null() {
            None
        } else {
            Some(unsafe { &mut *self.p })
        }
    }
}

impl<'a, Key, E> From<&'a mut Link<SkipNode<Key, E>>> for Rawlink<SkipNode<Key, E>> {
    fn from(node: &'a mut Link<SkipNode<Key, E>>) -> Self {
        match node.as_mut() {
            None => Rawlink::none(),
            Some(ptr) => Rawlink::some(&mut **ptr),
        }
    }
}

impl<T> Clone for Rawlink<T> {
    #[inline]
    fn clone(&self) -> Rawlink<T> {
        Rawlink{p: self.p}
    }
}

#[test]
fn test_skip_list() {
    let mut list: SkipList<i32, ()> = SkipList::new();

    let mut rng = thread_rng();

    //let vals = vec![ -18130, 16865, -1813, 1686, -181, 168, -18, 16];
    for i in 0 .. 10 {
        let val = rng.gen_range(0, 2000);
        // let val = vals[i];
        println!("DEBUG {} insert => {}", i+1, val);
        list.insert(val, ());
    }

    println!("list => {}", list);
    println!("level => {}", list.level());

    list.insert(20, ());
    println!("has(20) => {}", list.contains_key(&20));
    println!("list => {}", list);

    list.remove(&20);
    println!("list => {}", list);
}
<commit_msg>skip_list: fix head remove bug<commit_after>use std::mem;
use std::fmt;
use std::ptr;
use std::iter;

use rand::{thread_rng, Rng};

const DEFAULT_LEVEL: usize = 4;

type Link<T> = Option<Box<T>>;

#[allow(raw_pointer_derive)]
#[derive(Debug)]
struct Rawlink<T> {
    p: *mut T,
}

impl<T> Copy for Rawlink<T> {}
unsafe impl<T:Send> Send for Rawlink<T> {}
unsafe impl<T:Sync> Sync for Rawlink<T> {}

fn random_level() -> usize {
    let mut rng = thread_rng();
    let mut level = 0;
    loop {
        if rng.gen_weighted_bool(2) {
            level += 1;
            continue;
        }
        break;
    }

    level
}

#[derive(Debug)]
pub struct SkipNode<Key,E> {
    key: Key,
    it: E,
    next: Link<SkipNode<Key,E>>,
    prev: Rawlink<SkipNode<Key,E>>,
    // level 0 to DEFAULT_LEVEL
    forward: Vec<Rawlink<SkipNode<Key,E>>>,
}

impl<Key: PartialOrd, E> SkipNode<Key,E> {
    // level: 0 ~ DEFAULT_LEVEL
    fn new(key: Key, it: E, level: usize) -> SkipNode<Key,E> {
        SkipNode {
            key: key,
            it: it,
            next: None,
            prev: Rawlink::none(),
            forward: iter::repeat(Rawlink::none()).take(level).collect(),
        }
    }

    #[inline]
    fn level(&self) -> usize {
        self.forward.len()
    }

    fn to_ptr(&mut self) -> Rawlink<SkipNode<Key,E>> {
        Rawlink::some(self)
    }

    fn promote_level(&mut self, new_level: usize, forward: Vec<Rawlink<Self>>) {
        let level = self.level();
        for i in level .. new_level {
            self.forward.push(forward[i]);
        }
        assert!(self.level() == new_level, "promote_level()");
    }

    fn insert(&mut self, key: Key, it: E, level: usize) {
    }
}

pub struct SkipList<Key,E> {
    head: Link<SkipNode<Key,E>>,
    forward: Vec<Rawlink<SkipNode<Key,E>>>,
    level: usize,
    size: usize,
}

impl<Key: PartialOrd + fmt::Debug, E: fmt::Debug> SkipList<Key,E> {
    /// create new empty SkipList
    pub fn new() -> SkipList<Key, E> {
        SkipList {
            head: None,
            forward: iter::repeat(Rawlink::none()).take(DEFAULT_LEVEL).collect(),
            level: DEFAULT_LEVEL,
            size: 0,
        }
    }

    pub fn level(&self) -> usize {
        self.level
    }

    pub fn contains_key(&self, key: &Key) -> bool {
        self.find(key).is_some()
    }

    pub fn find(&self, key: &Key) -> Option<&E> {
        let level = self.level();
        let mut x = self.forward[level-1];
        for i in (0..level).rev() {
            while x.resolve().map_or(false, |n| n.forward[i].is_some()) &&
                x.resolve().map_or(false, |n| n.forward[i].resolve().unwrap().key < *key) {
                    let nx = x.resolve().map_or_else(Rawlink::none, |n| n.forward[i] );
                    x = nx;
                }
        }

        while x.resolve().map_or(false, |n| n.next.is_some()) &&
            x.resolve().map_or(false, |n| n.next.as_ref().unwrap().key < *key) {
                let nx = x.resolve_mut().map_or_else(Rawlink::none, |n| {
                    n.next.as_mut().map_or_else(Rawlink::none, |n| Rawlink::some(&mut **n))
                });
                x = nx
            }

        x.resolve().map_or(None, |n| {
            if n.key == *key {
                Some(&n.it)
            } else {
                None
            }
        })
    }

    fn adjust_head(&mut self, new_level: usize) {
        let diff = new_level - self.level;
        let head_link  = Rawlink::from(&mut self.head);
        let level = self.level();

        for i in level .. new_level {
            self.forward.push(head_link);
            self.head.as_mut().map(|n| n.forward.push(Rawlink::none()));
        }
        assert_eq!(self.forward.len(), new_level);
        assert_eq!(self.head.as_ref().map_or(new_level, |n| n.level()), new_level);
    }

    // Due to head node must be of same level as List,
    // inserting with decreasing order will lead to almost same bad performance as a linked list
    pub fn insert(&mut self, key: Key, it: E) {
        let mut new_level = random_level();
        if new_level > self.level { // new node will be deepest
            self.adjust_head(new_level);
            self.level = new_level;
        }
        self.size += 1;

        if self.head.is_none() {
            new_level = self.level;
            self.head = Some(Box::new(SkipNode::new(key, it, new_level)));
            let p = Rawlink::from(&mut self.head);
            for i in 0..new_level {
                self.forward[i] = p;
            }
        } else if self.head.as_ref().map_or(false, |n| n.key > key) {
            new_level = self.level;
            // insert at head
            let mut new_node = Some(Box::new(SkipNode::new(key, it, new_level)));
            let new_link = new_node.as_mut().map_or_else(Rawlink::none, |n| {
                Rawlink::some(&mut **n)
            });

            for i in 0..new_level {
                new_node.as_mut().map(|n| {
                    n.forward[i] = self.forward[i]
                });
            }

            for i in 0..new_level {
                self.forward[i] = new_link
            }

            new_node.as_mut().map(|n| n.next = self.head.take());
            self.head = new_node;
        } else {
            println!("crash0");

            let mut x = self.head.as_mut().map_or_else(Rawlink::none, |n| {
                Rawlink::some(&mut **n)
            });
            // insert normally
            let mut update: Vec<Rawlink<SkipNode<Key,E>>> = self.forward[..new_level].to_vec();
            if new_level > 0 {  // need to insert skip pointers
                println!("new level => {}", new_level);
                x = update[new_level-1];
                println!("crash2");
                for i in (0..new_level).rev() {
                    while x.resolve().map_or(false, |n| n.forward[i].is_some()) &&
                        x.resolve().map_or(false, |n| n.forward[i].resolve().unwrap().key < key) {
                            let nx = x.resolve().map_or_else(Rawlink::none, |n| n.forward[i] );
                            x = nx;
                        }
                    update[i] = x.resolve_mut().map_or_else(Rawlink::none, |n| {
                        Rawlink::some(&mut *n)
                    });
                }
            }

            println!("crash1");
            let mut y = x.resolve_mut().map_or_else(Rawlink::none, |n| {
                Rawlink::some(&mut *n)
            });
            // When head node level is lower than current
            if y.is_none() {
                println!("update => {:?}", update);
                y = self.head.as_mut().map_or_else(Rawlink::none, |n| {
                    Rawlink::some(&mut **n)
                });
            }
            while y.resolve().map_or(false, |n| n.next.is_some()) &&
                y.resolve().map_or(false, |n| n.next.as_ref().unwrap().key < key) {
                    let ny = y.resolve_mut().map_or_else(Rawlink::none, |n| {
                        n.next.as_mut().map_or_else(Rawlink::none, |n| Rawlink::some(&mut **n))
                    });
                    y = ny
                }
            assert!(y.is_some());
            // create node and insert
            let mut new_node = Some(Box::new(SkipNode::new(key, it, self.level)));
            let new_link = new_node.as_mut().map_or_else(Rawlink::none, |n| {
                Rawlink::some(&mut **n)
            });

            for i in 0..new_level {
                new_node.as_mut().map(|n| {
                    n.forward[i] = update[i].resolve_mut().map_or_else(Rawlink::none, |nx| {
                        nx.forward[i]
                    });
                });
                // if update is empty, then update head node's link
                update[i].resolve_mut().map_or_else(|| {
                    self.forward[i] = new_link;
                },
                    |prev| {
                    prev.forward[i] = new_link;
                });
            }

            // move in
            y.resolve_mut().map(|n| {
                new_node.as_mut().map(|new| {
                    new.next = n.next.take();
                });
                n.next = new_node;
            });
        }
    }

    pub fn remove(&mut self, key: &Key) -> Option<E> {
        if self.head.is_none() {
            return None;
        }
        let level = self.level();
        let mut x = self.forward[level-1];
        let mut left = x;

        for i in (0..level).rev() {
            while x.resolve().map_or(false, |n| n.forward[i].is_some()) &&
                x.resolve().map_or(false, |n| n.forward[i].resolve().unwrap().key < *key) {
                    let nx = x.resolve().map_or_else(Rawlink::none, |n| n.forward[i] );
                    x = nx;
                }
        }

        while x.resolve().map_or(false, |n| n.next.is_some()) &&
            x.resolve().map_or(false, |n| n.next.as_ref().unwrap().key < *key) {
                let nx = x.resolve_mut().map_or_else(Rawlink::none, |n| {
                    n.next.as_mut().map_or_else(Rawlink::none, |n| Rawlink::some(&mut **n))
                });
                left = x;
                x = nx
            }

        if !x.resolve().map_or(false, |n| n.key == *key ) {
            None
        } else if x.p == left.p && x.is_some() {
            println!("fuck equels");
            // this means remove head
            let head = self.head.take().unwrap();
            let head = *head;   // unwrap Box
            let SkipNode { it, next, forward, .. } = head;
            let mut new_head = next;

            // calculate new level, means, only head nodes
            let new_level = forward.iter().take_while(|nx| nx.is_some()).count();

            self.forward = iter::repeat(Rawlink::from(&mut new_head)).take(new_level).collect();
            self.level = new_level;

            new_head.as_mut().map(|n| n.promote_level(new_level, forward));
            self.head = new_head;

            Some(it)
        } else {
            unimplemented!()
        }
    }

    pub fn size(&self) -> usize {
        self.size
    }
}

impl<Key: PartialOrd + fmt::Display + fmt::Debug, E: fmt::Debug> fmt::Display for SkipList<Key,E> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.head.is_none() {
            write!(f, "<empty skip list>")
        } else {
            write!(f, "\nlv0 ");
            let mut x = self.head.as_ref();
            while x.is_some() {
                write!(f, "{} --> ", x.as_ref().map_or_else(String::new, |n| format!("{}", n.key)));
                x = x.as_ref().map_or(None, |n| n.next.as_ref());
            }
            writeln!(f, "");
            for i in 0..self.level {
                write!(f, "lv{} ", i+1);
                let mut x = self.forward[i];
                while x.is_some() {
                    write!(f, "{} ..> ",
                           x.resolve().map_or_else(String::new, |n| format!("{}", n.key)));
                    if x.resolve().map_or(false, |n| n.level() <= i) {
                        break;
                    }
                    x = x.resolve().map_or_else(Rawlink::none, |n| n.forward[i]);
                }
                writeln!(f, "");
            }
            Ok(())
        }
    }
}

/// Rawlink is a type like Option<T> but for holding a raw mutable pointer.
impl<T> Rawlink<T> {
    /// Like `Option::None` for Rawlink.
    fn none() -> Rawlink<T> {
        Rawlink{p: ptr::null_mut()}
    }

    /// Like `Option::Some` for Rawlink
    fn some(n: &mut T) -> Rawlink<T> {
        Rawlink{p: n}
    }

    fn is_some(&self) -> bool {
        !self.is_none()
    }

    fn is_none(&self) -> bool {
        self.p.is_null()
    }

    fn take(&mut self) -> Rawlink<T> {
        mem::replace(self, Rawlink::none())
    }

    /// Convert the `Rawlink` into an immutable Option value.
    fn resolve<'a>(&self) -> Option<&'a T> {
        if self.p.is_null() {
            None
        } else {
            Some(unsafe { &*self.p })
        }
    }

    /// Convert the `Rawlink` into a mutable Option value.
    fn resolve_mut<'a>(&mut self) -> Option<&'a mut T> {
        if self.p.is_null() {
            None
        } else {
            Some(unsafe { &mut *self.p })
        }
    }
}

impl<'a, Key, E> From<&'a mut Link<SkipNode<Key, E>>> for Rawlink<SkipNode<Key, E>> {
    fn from(node: &'a mut Link<SkipNode<Key, E>>) -> Self {
        match node.as_mut() {
            None => Rawlink::none(),
            Some(ptr) => Rawlink::some(&mut **ptr),
        }
    }
}

impl<T> Clone for Rawlink<T> {
    #[inline]
    fn clone(&self) -> Rawlink<T> {
        Rawlink{p: self.p}
    }
}

#[test]
fn test_skip_list() {
    let mut list: SkipList<i32, ()> = SkipList::new();

    let mut rng = thread_rng();

    //let vals = vec![ -18130, 16865, -1813, 1686, -181, 168, -18, 16];
    for i in 0 .. 10 {
        let val = rng.gen_range(0, 2000);
        // let val = vals[i];
        println!("list => {}", list);
        println!("DEBUG {} insert => {}", i+1, val);
        list.insert(val, ());
    }

    println!("list => {}", list);
    println!("level => {}", list.level());

    list.insert(20, ());
    println!("has(20) => {}", list.contains_key(&20));
    println!("list => {}", list);

    list.remove(&20);
    println!("list => {}", list);
}
<|endoftext|>


<commit_before>//! Contatins code relating to the engine's scripting capability.

#[cfg(test)]
mod test;

use std::collections::HashMap;
use std::error::Error;
use std::fmt::{Debug, Display, Formatter};
use std::fmt;

use hlua::{Lua, LuaError, LuaFunction, LuaTable};
use hlua::any::AnyLuaValue;

/// The engine lua standard library. Contains functionality relating to making a game with the engine.
///
/// Exposed as the module "buildstation" to lua code.
const ENGINE_STD: &'static str = include_str!("enginestd.lua");

/// A piece of code run before the main script.
const PRELUDE: &'static str = include_str!("prelude.lua");

/// Handles the scripts, their state, and their execution.
pub struct Engine<'lua> {
    /// The interpreter used for the scripts.
    pub interpreter: Lua<'lua>,
}

impl<'lua> Engine<'lua> {
    /// Constructs a script::Engine and loads the given scripts.
    ///
    /// The interpreter is initalized with the lua standard library, and the engine std.
    ///
    /// The prelude_buildengine.modules table is initalized with the source code of the scripts passed through the scripts parameter,
    /// sans the init entry, which is executed.
    pub fn new(mut scripts: HashMap<String, String>) -> Result<Self, LuaError> {
        scripts.insert("buildengine".to_owned(), ENGINE_STD.to_owned());
        let mut lua = Lua::new();
        lua.openlibs();
        lua.execute::<()>(PRELUDE).expect("error in prelude module of engine");
        let mut main = "".to_owned();
        {
            // Set up module table.
            let mut prelude_table: LuaTable<_> = lua.get("prelude_buildengine")
                                                    .expect("loaded prelude but \
                                                             prelude_buildengine table was not \
                                                             found");
            let mut modules = prelude_table.empty_array("modules");
            for script in scripts {
                let (name, body) = script;
                if name == "init".to_owned() {
                    main = body;
                    continue;
                }
                modules.set(name, body);
            }
        }
        try!(lua.execute::<()>(&main));
        Ok(Engine { interpreter: lua })
    }

    /// Call a given lua event with the given arguments.
    ///
    /// This calls every event with the name, with first the arguments vector passed, then the return of the last event,
    /// then the return of that event, and so on, untill all events of the name have been called.
    /// The returns of that event is then returned.
    pub fn exec_event(&mut self,
                      event_name: String,
                      mut args: Vec<AnyLuaValue>)
                      -> Result<Vec<AnyLuaValue>, ExecEventError> {
        args.insert(0, AnyLuaValue::LuaString(event_name));
        {
            let mut prelude_table: LuaTable<_> = self.interpreter
                                                     .get("prelude_buildengine")
                                                     .expect("the prelude_table wasn't found. \
                                                              was the prelude properly loaded?");
            let a_event: Option<_> = prelude_table.get::<LuaFunction<_>, _>("activate_event");
            if a_event.is_none() {
                return Err(ExecEventError::EngineStdNotImported);
            }
        }
        match self.call_prelude_fn("activate_event", args) {
            Ok(Some(ret)) => Ok(any_lua_to_vec(ret)),
            Ok(None) => Ok(Vec::new()),
            Err(err) => Err(err.into()),
        }
    }

    /// Call the given lua function in the prelude table with the given arguments.
    pub fn call_prelude_fn(&mut self,
                           fn_to_call: &str,
                           args: Vec<AnyLuaValue>)
                           -> Result<Option<AnyLuaValue>, LuaError> {
        let mut prelude_table: LuaTable<_> = self.interpreter
                                                 .get("prelude_buildengine")
                                                 .expect("the prelude_table wasn't found. was \
                                                          the prelude properly loaded?");
        prelude_table.set("fn_to_call", fn_to_call);
        prelude_table.set("args", args);
        {
            let mut call_fn_lua: LuaFunction<_> = prelude_table.get("call_prelude_fn")
                                                               .expect("prelude_buildengine.\
                                                                        call_prelude_fn not \
                                                                        found. was the prelude \
                                                                        properly loaded?");
            try!(call_fn_lua.call::<()>());
        }
        let ret: Option<AnyLuaValue> = prelude_table.get("ret");
        Ok(ret)
    }
}

impl<'lua> Debug for Engine<'lua> {
    fn fmt(&self, _fmt: &mut Formatter) -> Result<(), fmt::Error> {
        Ok(())
    }
}

/// An error that can ocour executing an event.
#[derive(Debug)]
pub enum ExecEventError {
    /// The buildengine standard library was not imported, so events aren't avalable.
    EngineStdNotImported,
    /// A lua error ocoured executing the event.
    LuaError(LuaError),
}

impl Display for ExecEventError {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
        match *self {
            ExecEventError::EngineStdNotImported => {
                write!(fmt,
                       "the standard library for the engine was not imported while trying to \
                        execute an event")
            }
            ExecEventError::LuaError(ref err) => {
                write!(fmt,
                       "an unknown lua error occoured while executing an event: {:?}", err)
            }
        }
    }
}

impl Error for ExecEventError {
    fn description(&self) -> &str {
        match *self {
            ExecEventError::EngineStdNotImported => {
                "the standard library for the engine was not imported while trying to execute an \
                 event"
            }
            ExecEventError::LuaError(ref _err) => {
                "an unknown lua error occoured while executing an event."
            }
        }
    }
}

impl From<LuaError> for ExecEventError {
    fn from(err: LuaError) -> Self {
        ExecEventError::LuaError(err)
    }
}

/// Converts a lua array with whole, numeric keys to a rust vector.
pub fn any_lua_to_vec(any: AnyLuaValue) -> Vec<AnyLuaValue> {
    let as_array = match any {
        AnyLuaValue::LuaArray(arr) => arr, // Ye a pirate!
        AnyLuaValue::LuaOther => return Vec::new(), // Basically only nil passes through here.
        _ => panic!("called any_lua_to_vec on a non-array lua value: {:?}", any),
    };
    let mut vec: Vec<AnyLuaValue> = Vec::new();
    for value in as_array {
        let (index, value) = value;
        let index = match index {
            AnyLuaValue::LuaNumber(num) => num,
            _ => panic!("called any_lua_to_vec on array with non-number indexes"),
        };
        let index = index as usize;
        vec.insert(index, value);
    }
    vec
}
<commit_msg>Update script::any_lua_to_vec according to the newest version of hlua<commit_after>//! Contatins code relating to the engine's scripting capability.

#[cfg(test)]
mod test;

use std::collections::HashMap;
use std::error::Error;
use std::fmt::{Debug, Display, Formatter};
use std::fmt;

use hlua::{Lua, LuaError, LuaFunction, LuaTable};
use hlua::any::AnyLuaValue;

/// The engine lua standard library. Contains functionality relating to making a game with the engine.
///
/// Exposed as the module "buildstation" to lua code.
const ENGINE_STD: &'static str = include_str!("enginestd.lua");

/// A piece of code run before the main script.
const PRELUDE: &'static str = include_str!("prelude.lua");

/// Handles the scripts, their state, and their execution.
pub struct Engine<'lua> {
    /// The interpreter used for the scripts.
    pub interpreter: Lua<'lua>,
}

impl<'lua> Engine<'lua> {
    /// Constructs a script::Engine and loads the given scripts.
    ///
    /// The interpreter is initalized with the lua standard library, and the engine std.
    ///
    /// The prelude_buildengine.modules table is initalized with the source code of the scripts passed through the scripts parameter,
    /// sans the init entry, which is executed.
    pub fn new(mut scripts: HashMap<String, String>) -> Result<Self, LuaError> {
        scripts.insert("buildengine".to_owned(), ENGINE_STD.to_owned());
        let mut lua = Lua::new();
        lua.openlibs();
        lua.execute::<()>(PRELUDE).expect("error in prelude module of engine");
        let mut main = "".to_owned();
        {
            // Set up module table.
            let mut prelude_table: LuaTable<_> = lua.get("prelude_buildengine")
                                                    .expect("loaded prelude but \
                                                             prelude_buildengine table was not \
                                                             found");
            let mut modules = prelude_table.empty_array("modules");
            for script in scripts {
                let (name, body) = script;
                if name == "init".to_owned() {
                    main = body;
                    continue;
                }
                modules.set(name, body);
            }
        }
        try!(lua.execute::<()>(&main));
        Ok(Engine { interpreter: lua })
    }

    /// Call a given lua event with the given arguments.
    ///
    /// This calls every event with the name, with first the arguments vector passed, then the return of the last event,
    /// then the return of that event, and so on, untill all events of the name have been called.
    /// The returns of that event is then returned.
    pub fn exec_event(&mut self,
                      event_name: String,
                      mut args: Vec<AnyLuaValue>)
                      -> Result<Vec<AnyLuaValue>, ExecEventError> {
        args.insert(0, AnyLuaValue::LuaString(event_name));
        {
            let mut prelude_table: LuaTable<_> = self.interpreter
                                                     .get("prelude_buildengine")
                                                     .expect("the prelude_table wasn't found. \
                                                              was the prelude properly loaded?");
            let a_event: Option<_> = prelude_table.get::<LuaFunction<_>, _>("activate_event");
            if a_event.is_none() {
                return Err(ExecEventError::EngineStdNotImported);
            }
        }
        match self.call_prelude_fn("activate_event", args) {
            Ok(Some(ret)) => Ok(any_lua_to_vec(ret)),
            Ok(None) => Ok(Vec::new()),
            Err(err) => Err(err.into()),
        }
    }

    /// Call the given lua function in the prelude table with the given arguments.
    pub fn call_prelude_fn(&mut self,
                           fn_to_call: &str,
                           args: Vec<AnyLuaValue>)
                           -> Result<Option<AnyLuaValue>, LuaError> {
        let mut prelude_table: LuaTable<_> = self.interpreter
                                                 .get("prelude_buildengine")
                                                 .expect("the prelude_table wasn't found. was \
                                                          the prelude properly loaded?");
        prelude_table.set("fn_to_call", fn_to_call);
        prelude_table.set("args", args);
        {
            let mut call_fn_lua: LuaFunction<_> = prelude_table.get("call_prelude_fn")
                                                               .expect("prelude_buildengine.\
                                                                        call_prelude_fn not \
                                                                        found. was the prelude \
                                                                        properly loaded?");
            try!(call_fn_lua.call::<()>());
        }
        let ret: Option<AnyLuaValue> = prelude_table.get("ret");
        Ok(ret)
    }
}

impl<'lua> Debug for Engine<'lua> {
    fn fmt(&self, _fmt: &mut Formatter) -> Result<(), fmt::Error> {
        Ok(())
    }
}

/// An error that can ocour executing an event.
#[derive(Debug)]
pub enum ExecEventError {
    /// The buildengine standard library was not imported, so events aren't avalable.
    EngineStdNotImported,
    /// A lua error ocoured executing the event.
    LuaError(LuaError),
}

impl Display for ExecEventError {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
        match *self {
            ExecEventError::EngineStdNotImported => {
                write!(fmt,
                       "the standard library for the engine was not imported while trying to \
                        execute an event")
            }
            ExecEventError::LuaError(ref err) => {
                write!(fmt,
                       "an unknown lua error occoured while executing an event: {:?}", err)
            }
        }
    }
}

impl Error for ExecEventError {
    fn description(&self) -> &str {
        match *self {
            ExecEventError::EngineStdNotImported => {
                "the standard library for the engine was not imported while trying to execute an \
                 event"
            }
            ExecEventError::LuaError(ref _err) => {
                "an unknown lua error occoured while executing an event."
            }
        }
    }
}

impl From<LuaError> for ExecEventError {
    fn from(err: LuaError) -> Self {
        ExecEventError::LuaError(err)
    }
}

/// Converts a lua array with whole, numeric keys to a rust vector.
pub fn any_lua_to_vec(any: AnyLuaValue) -> Vec<AnyLuaValue> {
    let as_array = match any {
        AnyLuaValue::LuaArray(arr) => arr, // Ye a pirate!
        _ => panic!("called any_lua_to_vec on a non-array lua value: {:?}", any),
    };
    let mut vec: Vec<AnyLuaValue> = Vec::new();
    for value in as_array {
        let (index, value) = value;
        let index = match index {
            AnyLuaValue::LuaNumber(num) => num,
            _ => panic!("called any_lua_to_vec on array with non-number indexes"),
        };
        let index = index as usize;
        vec.insert(index, value);
    }
    vec
}
<|endoftext|>


<commit_before>use crate::deserialize::{self, FromSql};
use crate::mysql::{Mysql, MysqlValue, NumericRepresentation};
use crate::result::Error::DeserializationError;
use crate::sql_types::{BigInt, Binary, Double, Float, Integer, SmallInt, Text};
use std::convert::TryInto;
use std::error::Error;
use std::str::{self, FromStr};

fn decimal_to_integer<T>(bytes: &[u8]) -> deserialize::Result<T>
where
    T: FromStr,
    T::Err: Error + Send + Sync + 'static,
{
    let string = str::from_utf8(bytes)?;
    let mut splited = string.split('.');
    let integer_portion = splited.next().unwrap_or_default();
    let _decimal_portion = splited.next().unwrap_or_default();
    if splited.next().is_some() {
        Err(format!("Invalid decimal format: {:?}", string).into())
    } else {
        Ok(integer_portion.parse()?)
    }
}

fn f32_to_i64(f: f32) -> deserialize::Result<i64> {
    use std::i64;

    if f <= i64::MAX as f32 && f >= i64::MIN as f32 {
        Ok(f.trunc() as i64)
    } else {
        Err(Box::new(DeserializationError(
            "Numeric overflow/underflow occurred".into(),
        )) as _)
    }
}

fn f64_to_i64(f: f64) -> deserialize::Result<i64> {
    use std::i64;

    if f <= i64::MAX as f64 && f >= i64::MIN as f64 {
        Ok(f.trunc() as i64)
    } else {
        Err(Box::new(DeserializationError(
            "Numeric overflow/underflow occurred".into(),
        )) as _)
    }
}

#[cfg(feature = "mysql_backend")]
impl FromSql<SmallInt, Mysql> for i16 {
    fn from_sql(value: MysqlValue<'_>) -> deserialize::Result<Self> {
        match value.numeric_value()? {
            NumericRepresentation::Tiny(x) => Ok(x.into()),
            NumericRepresentation::Small(x) => Ok(x),
            NumericRepresentation::Medium(x) => x.try_into().map_err(|_| {
                Box::new(DeserializationError(
                    "Numeric overflow/underflow occurred".into(),
                )) as _
            }),
            NumericRepresentation::Big(x) => x.try_into().map_err(|_| {
                Box::new(DeserializationError(
                    "Numeric overflow/underflow occured".into(),
                )) as _
            }),
            NumericRepresentation::Float(x) => f32_to_i64(x)?.try_into().map_err(|_| {
                Box::new(DeserializationError(
                    "Numeric overflow/underflow occured".into(),
                )) as _
            }),
            NumericRepresentation::Double(x) => f64_to_i64(x)?.try_into().map_err(|_| {
                Box::new(DeserializationError(
                    "Numeric overflow/underflow occured".into(),
                )) as _
            }),
            NumericRepresentation::Decimal(bytes) => decimal_to_integer(bytes),
        }
    }
}

#[cfg(feature = "mysql_backend")]
impl FromSql<Integer, Mysql> for i32 {
    fn from_sql(value: MysqlValue<'_>) -> deserialize::Result<Self> {
        match value.numeric_value()? {
            NumericRepresentation::Tiny(x) => Ok(x.into()),
            NumericRepresentation::Small(x) => Ok(x.into()),
            NumericRepresentation::Medium(x) => Ok(x),
            NumericRepresentation::Big(x) => x.try_into().map_err(|_| {
                Box::new(DeserializationError(
                    "Numeric overflow/underflow occured".into(),
                )) as _
            }),
            NumericRepresentation::Float(x) => f32_to_i64(x).and_then(|i| {
                i.try_into().map_err(|_| {
                    Box::new(DeserializationError(
                        "Numeric overflow/underflow occured".into(),
                    )) as _
                })
            }),
            NumericRepresentation::Double(x) => f64_to_i64(x).and_then(|i| {
                i.try_into().map_err(|_| {
                    Box::new(DeserializationError(
                        "Numeric overflow/underflow occured".into(),
                    )) as _
                })
            }),
            NumericRepresentation::Decimal(bytes) => decimal_to_integer(bytes),
        }
    }
}

#[cfg(feature = "mysql_backend")]
impl FromSql<BigInt, Mysql> for i64 {
    fn from_sql(value: MysqlValue<'_>) -> deserialize::Result<Self> {
        match value.numeric_value()? {
            NumericRepresentation::Tiny(x) => Ok(x.into()),
            NumericRepresentation::Small(x) => Ok(x.into()),
            NumericRepresentation::Medium(x) => Ok(x.into()),
            NumericRepresentation::Big(x) => Ok(x),
            NumericRepresentation::Float(x) => f32_to_i64(x),
            NumericRepresentation::Double(x) => f64_to_i64(x),
            NumericRepresentation::Decimal(bytes) => decimal_to_integer(bytes),
        }
    }
}

#[cfg(feature = "mysql_backend")]
impl FromSql<Float, Mysql> for f32 {
    fn from_sql(value: MysqlValue<'_>) -> deserialize::Result<Self> {
        match value.numeric_value()? {
            NumericRepresentation::Tiny(x) => Ok(x.into()),
            NumericRepresentation::Small(x) => Ok(x.into()),
            NumericRepresentation::Medium(x) => Ok(x as Self),
            NumericRepresentation::Big(x) => Ok(x as Self),
            NumericRepresentation::Float(x) => Ok(x),
            NumericRepresentation::Double(x) => Ok(x as Self),
            NumericRepresentation::Decimal(bytes) => Ok(str::from_utf8(bytes)?.parse()?),
        }
    }
}

#[cfg(feature = "mysql_backend")]
impl FromSql<Double, Mysql> for f64 {
    fn from_sql(value: MysqlValue<'_>) -> deserialize::Result<Self> {
        match value.numeric_value()? {
            NumericRepresentation::Tiny(x) => Ok(x.into()),
            NumericRepresentation::Small(x) => Ok(x.into()),
            NumericRepresentation::Medium(x) => Ok(x.into()),
            NumericRepresentation::Big(x) => Ok(x as Self),
            NumericRepresentation::Float(x) => Ok(x.into()),
            NumericRepresentation::Double(x) => Ok(x),
            NumericRepresentation::Decimal(bytes) => Ok(str::from_utf8(bytes)?.parse()?),
        }
    }
}

#[cfg(feature = "mysql_backend")]
impl FromSql<Text, Mysql> for String {
    fn from_sql(value: MysqlValue<'_>) -> deserialize::Result<Self> {
        String::from_utf8(value.as_bytes().into()).map_err(Into::into)
    }
}

#[cfg(feature = "mysql_backend")]
impl FromSql<Binary, Mysql> for Vec<u8> {
    fn from_sql(value: MysqlValue<'_>) -> deserialize::Result<Self> {
        Ok(value.as_bytes().into())
    }
}
<commit_msg>Generalize `FromSql` impls for the Mysql backend<commit_after>use crate::deserialize::{self, FromSql};
use crate::mysql::{Mysql, MysqlValue, NumericRepresentation};
use crate::result::Error::DeserializationError;
use crate::sql_types::{BigInt, Binary, Double, Float, Integer, SmallInt, Text};
use std::convert::TryInto;
use std::error::Error;
use std::str::{self, FromStr};

fn decimal_to_integer<T>(bytes: &[u8]) -> deserialize::Result<T>
where
    T: FromStr,
    T::Err: Error + Send + Sync + 'static,
{
    let string = str::from_utf8(bytes)?;
    let mut splited = string.split('.');
    let integer_portion = splited.next().unwrap_or_default();
    let _decimal_portion = splited.next().unwrap_or_default();
    if splited.next().is_some() {
        Err(format!("Invalid decimal format: {:?}", string).into())
    } else {
        Ok(integer_portion.parse()?)
    }
}

fn f32_to_i64(f: f32) -> deserialize::Result<i64> {
    use std::i64;

    if f <= i64::MAX as f32 && f >= i64::MIN as f32 {
        Ok(f.trunc() as i64)
    } else {
        Err(Box::new(DeserializationError(
            "Numeric overflow/underflow occurred".into(),
        )) as _)
    }
}

fn f64_to_i64(f: f64) -> deserialize::Result<i64> {
    use std::i64;

    if f <= i64::MAX as f64 && f >= i64::MIN as f64 {
        Ok(f.trunc() as i64)
    } else {
        Err(Box::new(DeserializationError(
            "Numeric overflow/underflow occurred".into(),
        )) as _)
    }
}

#[cfg(feature = "mysql_backend")]
impl FromSql<SmallInt, Mysql> for i16 {
    fn from_sql(value: MysqlValue<'_>) -> deserialize::Result<Self> {
        match value.numeric_value()? {
            NumericRepresentation::Tiny(x) => Ok(x.into()),
            NumericRepresentation::Small(x) => Ok(x),
            NumericRepresentation::Medium(x) => x.try_into().map_err(|_| {
                Box::new(DeserializationError(
                    "Numeric overflow/underflow occurred".into(),
                )) as _
            }),
            NumericRepresentation::Big(x) => x.try_into().map_err(|_| {
                Box::new(DeserializationError(
                    "Numeric overflow/underflow occured".into(),
                )) as _
            }),
            NumericRepresentation::Float(x) => f32_to_i64(x)?.try_into().map_err(|_| {
                Box::new(DeserializationError(
                    "Numeric overflow/underflow occured".into(),
                )) as _
            }),
            NumericRepresentation::Double(x) => f64_to_i64(x)?.try_into().map_err(|_| {
                Box::new(DeserializationError(
                    "Numeric overflow/underflow occured".into(),
                )) as _
            }),
            NumericRepresentation::Decimal(bytes) => decimal_to_integer(bytes),
        }
    }
}

#[cfg(feature = "mysql_backend")]
impl FromSql<Integer, Mysql> for i32 {
    fn from_sql(value: MysqlValue<'_>) -> deserialize::Result<Self> {
        match value.numeric_value()? {
            NumericRepresentation::Tiny(x) => Ok(x.into()),
            NumericRepresentation::Small(x) => Ok(x.into()),
            NumericRepresentation::Medium(x) => Ok(x),
            NumericRepresentation::Big(x) => x.try_into().map_err(|_| {
                Box::new(DeserializationError(
                    "Numeric overflow/underflow occured".into(),
                )) as _
            }),
            NumericRepresentation::Float(x) => f32_to_i64(x).and_then(|i| {
                i.try_into().map_err(|_| {
                    Box::new(DeserializationError(
                        "Numeric overflow/underflow occured".into(),
                    )) as _
                })
            }),
            NumericRepresentation::Double(x) => f64_to_i64(x).and_then(|i| {
                i.try_into().map_err(|_| {
                    Box::new(DeserializationError(
                        "Numeric overflow/underflow occured".into(),
                    )) as _
                })
            }),
            NumericRepresentation::Decimal(bytes) => decimal_to_integer(bytes),
        }
    }
}

#[cfg(feature = "mysql_backend")]
impl FromSql<BigInt, Mysql> for i64 {
    fn from_sql(value: MysqlValue<'_>) -> deserialize::Result<Self> {
        match value.numeric_value()? {
            NumericRepresentation::Tiny(x) => Ok(x.into()),
            NumericRepresentation::Small(x) => Ok(x.into()),
            NumericRepresentation::Medium(x) => Ok(x.into()),
            NumericRepresentation::Big(x) => Ok(x),
            NumericRepresentation::Float(x) => f32_to_i64(x),
            NumericRepresentation::Double(x) => f64_to_i64(x),
            NumericRepresentation::Decimal(bytes) => decimal_to_integer(bytes),
        }
    }
}

#[cfg(feature = "mysql_backend")]
impl FromSql<Float, Mysql> for f32 {
    fn from_sql(value: MysqlValue<'_>) -> deserialize::Result<Self> {
        match value.numeric_value()? {
            NumericRepresentation::Tiny(x) => Ok(x.into()),
            NumericRepresentation::Small(x) => Ok(x.into()),
            NumericRepresentation::Medium(x) => Ok(x as Self),
            NumericRepresentation::Big(x) => Ok(x as Self),
            NumericRepresentation::Float(x) => Ok(x),
            NumericRepresentation::Double(x) => Ok(x as Self),
            NumericRepresentation::Decimal(bytes) => Ok(str::from_utf8(bytes)?.parse()?),
        }
    }
}

#[cfg(feature = "mysql_backend")]
impl FromSql<Double, Mysql> for f64 {
    fn from_sql(value: MysqlValue<'_>) -> deserialize::Result<Self> {
        match value.numeric_value()? {
            NumericRepresentation::Tiny(x) => Ok(x.into()),
            NumericRepresentation::Small(x) => Ok(x.into()),
            NumericRepresentation::Medium(x) => Ok(x.into()),
            NumericRepresentation::Big(x) => Ok(x as Self),
            NumericRepresentation::Float(x) => Ok(x.into()),
            NumericRepresentation::Double(x) => Ok(x),
            NumericRepresentation::Decimal(bytes) => Ok(str::from_utf8(bytes)?.parse()?),
        }
    }
}

/// The returned pointer is *only* valid for the lifetime to the argument of
/// `from_sql`. This impl is intended for uses where you want to write a new
/// impl in terms of `String`, but don't want to allocate. We have to return a
/// raw pointer instead of a reference with a lifetime due to the structure of
/// `FromSql`
#[cfg(feature = "mysql_backend")]
impl FromSql<Text, Mysql> for *const str {
    fn from_sql(value: MysqlValue<'_>) -> deserialize::Result<Self> {
        let string = str::from_utf8(value.as_bytes())?;
        Ok(string as *const str)
    }
}

/// The returned pointer is *only* valid for the lifetime to the argument of
/// `from_sql`. This impl is intended for uses where you want to write a new
/// impl in terms of `Vec<u8>`, but don't want to allocate. We have to return a
/// raw pointer instead of a reference with a lifetime due to the structure of
/// `FromSql`
#[cfg(feature = "mysql_backend")]
impl FromSql<Binary, Mysql> for *const [u8] {
    fn from_sql(value: MysqlValue<'_>) -> deserialize::Result<Self> {
        Ok(value.as_bytes() as *const [u8])
    }
}
<|endoftext|>