<commit_before>//! Implementation of input backend trait for types provided by `libinput`

use backend::SeatInternal;
use backend::input::{InputBackend, InputHandler, Seat, SeatCapabilities, MouseButton};
use input::{Libinput, Device, Seat as LibinputSeat, DeviceCapability};
use input::event::*;

use std::io::Error as IoError;
use std::collections::hash_map::{DefaultHasher, Entry, HashMap};
use std::hash::{Hash, Hasher};

struct SeatDesc {
    seat: Seat,
    pointer: (u32, u32),
}

pub struct LibinputInputBackend {
    context: Libinput,
    devices: Vec<Device>,
    seats: HashMap<LibinputSeat, SeatDesc>,
    handler: Option<Box<InputHandler<LibinputInputBackend> + 'static>>,
    logger: ::slog::Logger,
}

impl InputBackend for LibinputInputBackend {
    type InputConfig = [Device];
    type EventError = IoError;

    fn set_handler<H: InputHandler<Self> + 'static>(&mut self, mut handler: H) {
        if self.handler.is_some() {
            self.clear_handler();
        }
        info!(self.logger, "New input handler set.");
        for desc in self.seats.values() {
            trace!(self.logger, "Calling on_seat_created with {:?}", desc.seat);
            handler.on_seat_created(&desc.seat);
        }
        self.handler = Some(Box::new(handler));
    }

    fn get_handler(&mut self) -> Option<&mut InputHandler<Self>> {
        self.handler
            .as_mut()
            .map(|handler| handler as &mut InputHandler<Self>)
    }

    fn clear_handler(&mut self) {
        if let Some(mut handler) = self.handler.take() {
            for desc in self.seats.values() {
                trace!(self.logger, "Calling on_seat_destroyed with {:?}", desc.seat);
                handler.on_seat_destroyed(&desc.seat);
            }
            info!(self.logger, "Removing input handler");
        }
    }

    fn input_config(&mut self) -> &mut Self::InputConfig {
        &mut self.devices
    }

    fn set_cursor_position(&mut self, _x: u32, _y: u32) -> Result<(), ()> {
        // FIXME later.
        // This will be doable with the hardware cursor api and probably some more cases
        warn!(self.logger, "Setting the cursor position is currently unsupported by the libinput backend");
        Err(())
    }

    fn dispatch_new_events(&mut self) -> Result<(), IoError> {
        self.context.dispatch()?;
        for event in &mut self.context {
            match event {
                Event::Device(device_event) => {
                    use input::event::device::*;
                    match device_event {
                        DeviceEvent::Added(device_added_event) => {
                            let added = device_added_event.into_event().device();

                            let new_caps = SeatCapabilities {
                                pointer: added.has_capability(DeviceCapability::Pointer),
                                keyboard: added.has_capability(DeviceCapability::Keyboard),
                                touch: added.has_capability(DeviceCapability::Touch),
                            };

                            let device_seat = added.seat();
                            self.devices.push(added);

                            match self.seats.entry(device_seat) {
                                Entry::Occupied(mut seat_entry) => {
                                    let old_seat = seat_entry.get_mut();
                                    {
                                        let caps = old_seat.seat.capabilities_mut();
                                        caps.pointer = new_caps.pointer || caps.pointer;
                                        caps.keyboard = new_caps.keyboard || caps.keyboard;
                                        caps.touch = new_caps.touch || caps.touch;
                                    }
                                    if let Some(ref mut handler) = self.handler {
                                        trace!(self.logger, "Calling on_seat_changed with {:?}", old_seat.seat);
                                        handler.on_seat_changed(&old_seat.seat);
                                    }
                                },
                                Entry::Vacant(seat_entry) => {
                                    let mut hasher = DefaultHasher::default();
                                    seat_entry.key().hash(&mut hasher);
                                    let desc = seat_entry.insert(SeatDesc {
                                        seat: Seat::new(hasher.finish(), new_caps),
                                        pointer: (0, 0) //FIXME: What position to assume? Maybe center of the screen instead. Probably call `set_cursor_position` after this.
                                    });
                                    if let Some(ref mut handler) = self.handler {
                                        trace!(self.logger, "Calling on_seat_created with {:?}", desc.seat);
                                        handler.on_seat_created(&desc.seat);
                                    }
                                }
                            }
                        },
                        DeviceEvent::Removed(device_removed_event) => {
                            let removed = device_removed_event.into_event().device();

                            // remove device
                            self.devices.retain(|dev| *dev == removed);

                            let device_seat = removed.seat();

                            // update capabilities, so they appear correctly on `on_seat_changed` and `on_seat_destroyed`.
                            if let Some(desc) = self.seats.get_mut(&device_seat) {
                                let caps = desc.seat.capabilities_mut();
                                caps.pointer = self.devices.iter().filter(|x| x.seat() == device_seat).any(|x| x.has_capability(DeviceCapability::Pointer));
                                caps.keyboard = self.devices.iter().filter(|x| x.seat() == device_seat).any(|x| x.has_capability(DeviceCapability::Keyboard));
                                caps.touch = self.devices.iter().filter(|x| x.seat() == device_seat).any(|x| x.has_capability(DeviceCapability::Touch));
                            } else {
                                panic!("Seat changed that was never created")
                            }

                            // check if the seat has any other devices
                            if !self.devices.iter().any(|x| x.seat() == device_seat) {
                                // it has not, lets destroy it
                                if let Some(desc) = self.seats.remove(&device_seat) {
                                    if let Some(ref mut handler) = self.handler {
                                        trace!(self.logger, "Calling on_seat_destroyed with {:?}", desc.seat);
                                        handler.on_seat_destroyed(&desc.seat);
                                    }
                                } else {
                                    panic!("Seat destroyed that was never created");
                                }
                            } else {
                                // it has, notify about updates
                                if let Some(ref mut handler) = self.handler {
                                    let desc = self.seats.get(&device_seat).unwrap();
                                    trace!(self.logger, "Calling on_seat_changed with {:?}", desc.seat);
                                    handler.on_seat_changed(&desc.seat);
                                }
                            }
                        },
                    }
                    if let Some(ref mut handler) = self.handler {
                       handler.on_input_config_changed(&mut self.devices);
                    }
                },
                Event::Touch(touch_event) => {
                    use ::input::event::touch::*;
                    if let Some(ref mut handler) = self.handler {
                        let device_seat = touch_event.device().seat();
                        handler.on_touch(&self.seats.get(&device_seat).expect("Recieved key event of non existing Seat").seat,
                                         touch_event.time(), touch_event.into())
                    }
                },
                Event::Keyboard(keyboard_event) => {
                    use ::input::event::keyboard::*;
                    match keyboard_event {
                        KeyboardEvent::Key(event) => {
                            if let Some(ref mut handler) = self.handler {
                                let device_seat = event.device().seat();
                                handler.on_keyboard_key(&self.seats.get(&device_seat).expect("Recieved key event of non existing Seat").seat,
                                                        event.time(), event.key(), event.key_state().into(), event.seat_key_count());
                            }
                        }
                    }
                },
                Event::Pointer(pointer_event) => {
                    use ::input::event::pointer::*;
                    match pointer_event {
                        PointerEvent::Motion(motion_event) => {
                            let device_seat = motion_event.device().seat();
                            let desc = self.seats.get_mut(&device_seat).expect("Recieved pointer event of non existing Seat");
                            desc.pointer.0 += motion_event.dx() as u32;
                            desc.pointer.1 += motion_event.dy() as u32;
                            if let Some(ref mut handler) = self.handler {
                                handler.on_pointer_move(&desc.seat, motion_event.time(), desc.pointer);
                            }
                        },
                        PointerEvent::MotionAbsolute(motion_event) => {
                            let device_seat = motion_event.device().seat();
                            let desc = self.seats.get_mut(&device_seat).expect("Recieved pointer event of non existing Seat");
                            desc.pointer = (
                                motion_event.absolute_x_transformed(
                                /*FIXME: global.get_focused_output_for_seat(&desc.seat).width() or something like that*/ 1280) as u32,
                                motion_event.absolute_y_transformed(
                                /*FIXME: global.get_focused_output_for_seat(&desc.seat).height() or something like that*/ 800) as u32,
                            );
                            if let Some(ref mut handler) = self.handler {
                                handler.on_pointer_move(&desc.seat, motion_event.time(), desc.pointer);
                            }
                        },
                        PointerEvent::Axis(axis_event) => {
                            if let Some(ref mut handler) = self.handler {
                                let device_seat = axis_event.device().seat();
                                let desc = self.seats.get_mut(&device_seat).expect("Recieved pointer event of non existing Seat");
                                if axis_event.has_axis(Axis::Vertical) {
                                    handler.on_pointer_scroll(&desc.seat, axis_event.time(), ::backend::input::Axis::Vertical,
                                                              axis_event.axis_source().into(), match axis_event.axis_source() {
                                                                  AxisSource::Finger | AxisSource::Continuous => axis_event.axis_value(Axis::Vertical),
                                                                  AxisSource::Wheel | AxisSource::WheelTilt => axis_event.axis_value_discrete(Axis::Vertical).unwrap(),
                                                              });
                                }
                                if axis_event.has_axis(Axis::Horizontal) {
                                    handler.on_pointer_scroll(&desc.seat, axis_event.time(), ::backend::input::Axis::Horizontal,
                                                              axis_event.axis_source().into(), match axis_event.axis_source() {
                                                                  AxisSource::Finger | AxisSource::Continuous => axis_event.axis_value(Axis::Horizontal),
                                                                  AxisSource::Wheel | AxisSource::WheelTilt => axis_event.axis_value_discrete(Axis::Horizontal).unwrap(),
                                                              });
                                }
                            }
                        },
                        PointerEvent::Button(button_event) => {
                            if let Some(ref mut handler) = self.handler {
                                let device_seat = button_event.device().seat();
                                let desc = self.seats.get_mut(&device_seat).expect("Recieved pointer event of non existing Seat");
                                handler.on_pointer_button(&desc.seat, button_event.time(), match button_event.button() {
                                    0x110 => MouseButton::Left,
                                    0x111 => MouseButton::Right,
                                    0x112 => MouseButton::Middle,
                                    x => MouseButton::Other(x as u8),
                                }, button_event.button_state().into());
                            }
                        }
                    }
                },
                _ => {}, //FIXME: What to do with the rest.
            }
        };
        Ok(())
    }
}

impl From<::input::event::keyboard::KeyState> for ::backend::input::KeyState {
    fn from(libinput: ::input::event::keyboard::KeyState) -> Self {
        match libinput {
            ::input::event::keyboard::KeyState::Pressed => ::backend::input::KeyState::Pressed,
            ::input::event::keyboard::KeyState::Released => ::backend::input::KeyState::Released,
        }
    }
}

impl From<::input::event::pointer::AxisSource> for ::backend::input::AxisSource {
    fn from(libinput: ::input::event::pointer::AxisSource) -> Self {
        match libinput {
            ::input::event::pointer::AxisSource::Finger => ::backend::input::AxisSource::Finger,
            ::input::event::pointer::AxisSource::Continuous => ::backend::input::AxisSource::Continuous,
            ::input::event::pointer::AxisSource::Wheel => ::backend::input::AxisSource::Wheel,
            ::input::event::pointer::AxisSource::WheelTilt => ::backend::input::AxisSource::WheelTilt,
        }
    }
}

impl From<::input::event::pointer::ButtonState> for ::backend::input::MouseButtonState {
    fn from(libinput: ::input::event::pointer::ButtonState) -> Self {
        match libinput {
            ::input::event::pointer::ButtonState::Pressed => ::backend::input::MouseButtonState::Pressed,
            ::input::event::pointer::ButtonState::Released => ::backend::input::MouseButtonState::Released,
        }
    }
}

impl From<::input::event::touch::TouchEvent> for ::backend::input::TouchEvent {
    fn from(libinput: ::input::event::touch::TouchEvent) -> Self {
        use ::input::event::touch::{TouchEventSlot, TouchEventPosition};
        use ::backend::TouchSlotInternal;

        match libinput {
            ::input::event::touch::TouchEvent::Down(down_event) => ::backend::input::TouchEvent::Down {
                slot: down_event.slot().map(|x| ::backend::input::TouchSlot::new(x)),
                x: down_event.x_transformed(/*FIXME: global.get_focused_output_for_seat(&desc.seat).width() or something like that*/ 1280),
                y: down_event.x_transformed(/*FIXME: global.get_focused_output_for_seat(&desc.seat).height() or something like that*/ 800),
            },
            ::input::event::touch::TouchEvent::Motion(motion_event) => ::backend::input::TouchEvent::Motion {
                slot: motion_event.slot().map(|x| ::backend::input::TouchSlot::new(x)),
                x: motion_event.x_transformed(/*FIXME: global.get_focused_output_for_seat(&desc.seat).width() or something like that*/ 1280),
                y: motion_event.x_transformed(/*FIXME: global.get_focused_output_for_seat(&desc.seat).height() or something like that*/ 800),
            },
            ::input::event::touch::TouchEvent::Up(up_event) => ::backend::input::TouchEvent::Up {
                slot: up_event.slot().map(|x| ::backend::input::TouchSlot::new(x)),
            },
            ::input::event::touch::TouchEvent::Cancel(cancel_event) => ::backend::input::TouchEvent::Cancel {
                slot: cancel_event.slot().map(|x| ::backend::input::TouchSlot::new(x)),
            },
            ::input::event::touch::TouchEvent::Frame(_) => ::backend::input::TouchEvent::Frame,
        }
    }
}
<commit_msg>Add more logging<commit_after>//! Implementation of input backend trait for types provided by `libinput`

use backend::SeatInternal;
use backend::input::{InputBackend, InputHandler, Seat, SeatCapabilities, MouseButton};
use input::{Libinput, Device, Seat as LibinputSeat, DeviceCapability};
use input::event::*;

use std::io::Error as IoError;
use std::collections::hash_map::{DefaultHasher, Entry, HashMap};
use std::hash::{Hash, Hasher};

struct SeatDesc {
    seat: Seat,
    pointer: (u32, u32),
}

pub struct LibinputInputBackend {
    context: Libinput,
    devices: Vec<Device>,
    seats: HashMap<LibinputSeat, SeatDesc>,
    handler: Option<Box<InputHandler<LibinputInputBackend> + 'static>>,
    logger: ::slog::Logger,
}

impl InputBackend for LibinputInputBackend {
    type InputConfig = [Device];
    type EventError = IoError;

    fn set_handler<H: InputHandler<Self> + 'static>(&mut self, mut handler: H) {
        if self.handler.is_some() {
            self.clear_handler();
        }
        info!(self.logger, "New input handler set.");
        for desc in self.seats.values() {
            trace!(self.logger, "Calling on_seat_created with {:?}", desc.seat);
            handler.on_seat_created(&desc.seat);
        }
        self.handler = Some(Box::new(handler));
    }

    fn get_handler(&mut self) -> Option<&mut InputHandler<Self>> {
        self.handler
            .as_mut()
            .map(|handler| handler as &mut InputHandler<Self>)
    }

    fn clear_handler(&mut self) {
        if let Some(mut handler) = self.handler.take() {
            for desc in self.seats.values() {
                trace!(self.logger, "Calling on_seat_destroyed with {:?}", desc.seat);
                handler.on_seat_destroyed(&desc.seat);
            }
            info!(self.logger, "Removing input handler");
        }
    }

    fn input_config(&mut self) -> &mut Self::InputConfig {
        &mut self.devices
    }

    fn set_cursor_position(&mut self, _x: u32, _y: u32) -> Result<(), ()> {
        // FIXME later.
        // This will be doable with the hardware cursor api and probably some more cases
        warn!(self.logger, "Setting the cursor position is currently unsupported by the libinput backend");
        Err(())
    }

    fn dispatch_new_events(&mut self) -> Result<(), IoError> {
        self.context.dispatch()?;
        for event in &mut self.context {
            match event {
                Event::Device(device_event) => {
                    use input::event::device::*;
                    match device_event {
                        DeviceEvent::Added(device_added_event) => {
                            let added = device_added_event.into_event().device();

                            let new_caps = SeatCapabilities {
                                pointer: added.has_capability(DeviceCapability::Pointer),
                                keyboard: added.has_capability(DeviceCapability::Keyboard),
                                touch: added.has_capability(DeviceCapability::Touch),
                            };

                            let device_seat = added.seat();
                            self.devices.push(added);

                            match self.seats.entry(device_seat) {
                                Entry::Occupied(mut seat_entry) => {
                                    let old_seat = seat_entry.get_mut();
                                    {
                                        let caps = old_seat.seat.capabilities_mut();
                                        caps.pointer = new_caps.pointer || caps.pointer;
                                        caps.keyboard = new_caps.keyboard || caps.keyboard;
                                        caps.touch = new_caps.touch || caps.touch;
                                    }
                                    if let Some(ref mut handler) = self.handler {
                                        trace!(self.logger, "Calling on_seat_changed with {:?}", old_seat.seat);
                                        handler.on_seat_changed(&old_seat.seat);
                                    }
                                },
                                Entry::Vacant(seat_entry) => {
                                    let mut hasher = DefaultHasher::default();
                                    seat_entry.key().hash(&mut hasher);
                                    let desc = seat_entry.insert(SeatDesc {
                                        seat: Seat::new(hasher.finish(), new_caps),
                                        pointer: (0, 0) //FIXME: What position to assume? Maybe center of the screen instead. Probably call `set_cursor_position` after this.
                                    });
                                    if let Some(ref mut handler) = self.handler {
                                        trace!(self.logger, "Calling on_seat_created with {:?}", desc.seat);
                                        handler.on_seat_created(&desc.seat);
                                    }
                                }
                            }
                        },
                        DeviceEvent::Removed(device_removed_event) => {
                            let removed = device_removed_event.into_event().device();

                            // remove device
                            self.devices.retain(|dev| *dev == removed);

                            let device_seat = removed.seat();

                            // update capabilities, so they appear correctly on `on_seat_changed` and `on_seat_destroyed`.
                            if let Some(desc) = self.seats.get_mut(&device_seat) {
                                let caps = desc.seat.capabilities_mut();
                                caps.pointer = self.devices.iter().filter(|x| x.seat() == device_seat).any(|x| x.has_capability(DeviceCapability::Pointer));
                                caps.keyboard = self.devices.iter().filter(|x| x.seat() == device_seat).any(|x| x.has_capability(DeviceCapability::Keyboard));
                                caps.touch = self.devices.iter().filter(|x| x.seat() == device_seat).any(|x| x.has_capability(DeviceCapability::Touch));
                            } else {
                                panic!("Seat changed that was never created")
                            }

                            // check if the seat has any other devices
                            if !self.devices.iter().any(|x| x.seat() == device_seat) {
                                // it has not, lets destroy it
                                if let Some(desc) = self.seats.remove(&device_seat) {
                                    if let Some(ref mut handler) = self.handler {
                                        trace!(self.logger, "Calling on_seat_destroyed with {:?}", desc.seat);
                                        handler.on_seat_destroyed(&desc.seat);
                                    }
                                } else {
                                    panic!("Seat destroyed that was never created");
                                }
                            } else {
                                // it has, notify about updates
                                if let Some(ref mut handler) = self.handler {
                                    let desc = self.seats.get(&device_seat).unwrap();
                                    trace!(self.logger, "Calling on_seat_changed with {:?}", desc.seat);
                                    handler.on_seat_changed(&desc.seat);
                                }
                            }
                        },
                    }
                    if let Some(ref mut handler) = self.handler {
                       handler.on_input_config_changed(&mut self.devices);
                    }
                },
                Event::Touch(touch_event) => {
                    use ::input::event::touch::*;
                    if let Some(ref mut handler) = self.handler {
                        let device_seat = touch_event.device().seat();
                        trace!(self.logger, "Calling on_touch with {:?}", touch_event);
                        handler.on_touch(&self.seats.get(&device_seat).expect("Recieved key event of non existing Seat").seat,
                                         touch_event.time(), touch_event.into())
                    }
                },
                Event::Keyboard(keyboard_event) => {
                    use ::input::event::keyboard::*;
                    match keyboard_event {
                        KeyboardEvent::Key(key_event) => {
                            if let Some(ref mut handler) = self.handler {
                                trace!(self.logger, "Calling on_keyboard_key with {:?}", key_event);
                                let device_seat = key_event.device().seat();
                                handler.on_keyboard_key(&self.seats.get(&device_seat).expect("Recieved key event of non existing Seat").seat,
                                                        key_event.time(), key_event.key(), key_event.key_state().into(), key_event.seat_key_count());
                            }
                        }
                    }
                },
                Event::Pointer(pointer_event) => {
                    use ::input::event::pointer::*;
                    match pointer_event {
                        PointerEvent::Motion(motion_event) => {
                            let device_seat = motion_event.device().seat();
                            let desc = self.seats.get_mut(&device_seat).expect("Recieved pointer event of non existing Seat");
                            desc.pointer.0 += motion_event.dx() as u32;
                            desc.pointer.1 += motion_event.dy() as u32;
                            if let Some(ref mut handler) = self.handler {
                                trace!(self.logger, "Calling on_pointer_move with {:?}", desc.pointer);
                                handler.on_pointer_move(&desc.seat, motion_event.time(), desc.pointer);
                            }
                        },
                        PointerEvent::MotionAbsolute(motion_event) => {
                            let device_seat = motion_event.device().seat();
                            let desc = self.seats.get_mut(&device_seat).expect("Recieved pointer event of non existing Seat");
                            desc.pointer = (
                                motion_event.absolute_x_transformed(
                                /*FIXME: global.get_focused_output_for_seat(&desc.seat).width() or something like that*/ 1280) as u32,
                                motion_event.absolute_y_transformed(
                                /*FIXME: global.get_focused_output_for_seat(&desc.seat).height() or something like that*/ 800) as u32,
                            );
                            if let Some(ref mut handler) = self.handler {
                                trace!(self.logger, "Calling on_pointer_move with {:?}", desc.pointer);
                                handler.on_pointer_move(&desc.seat, motion_event.time(), desc.pointer);
                            }
                        },
                        PointerEvent::Axis(axis_event) => {
                            if let Some(ref mut handler) = self.handler {
                                let device_seat = axis_event.device().seat();
                                let desc = self.seats.get_mut(&device_seat).expect("Recieved pointer event of non existing Seat");
                                if axis_event.has_axis(Axis::Vertical) {
                                    let value = match axis_event.axis_source() {
                                        AxisSource::Finger | AxisSource::Continuous => axis_event.axis_value(Axis::Vertical),
                                        AxisSource::Wheel | AxisSource::WheelTilt => axis_event.axis_value_discrete(Axis::Vertical).unwrap(),
                                    };
                                    trace!(self.logger, "Calling on_pointer_scroll on Axis::Vertical from {:?} with {:?}", axis_event.axis_source(), value);
                                    handler.on_pointer_scroll(&desc.seat, axis_event.time(), ::backend::input::Axis::Vertical,
                                                              axis_event.axis_source().into(), value);
                                }
                                if axis_event.has_axis(Axis::Horizontal) {
                                    let value = match axis_event.axis_source() {
                                        AxisSource::Finger | AxisSource::Continuous => axis_event.axis_value(Axis::Horizontal),
                                        AxisSource::Wheel | AxisSource::WheelTilt => axis_event.axis_value_discrete(Axis::Horizontal).unwrap(),
                                    };
                                    trace!(self.logger, "Calling on_pointer_scroll on Axis::Horizontal from {:?} with {:?}", axis_event.axis_source(), value);
                                    handler.on_pointer_scroll(&desc.seat, axis_event.time(), ::backend::input::Axis::Horizontal,
                                                              axis_event.axis_source().into(), value);
                                }
                            }
                        },
                        PointerEvent::Button(button_event) => {
                            if let Some(ref mut handler) = self.handler {
                                let device_seat = button_event.device().seat();
                                let desc = self.seats.get_mut(&device_seat).expect("Recieved pointer event of non existing Seat");
                                trace!(self.logger, "Calling on_pointer_button with {:?}", button_event.button());
                                handler.on_pointer_button(&desc.seat, button_event.time(), match button_event.button() {
                                    0x110 => MouseButton::Left,
                                    0x111 => MouseButton::Right,
                                    0x112 => MouseButton::Middle,
                                    x => MouseButton::Other(x as u8),
                                }, button_event.button_state().into());
                            }
                        }
                    }
                },
                _ => {}, //FIXME: What to do with the rest.
            }
        };
        Ok(())
    }
}

impl From<::input::event::keyboard::KeyState> for ::backend::input::KeyState {
    fn from(libinput: ::input::event::keyboard::KeyState) -> Self {
        match libinput {
            ::input::event::keyboard::KeyState::Pressed => ::backend::input::KeyState::Pressed,
            ::input::event::keyboard::KeyState::Released => ::backend::input::KeyState::Released,
        }
    }
}

impl From<::input::event::pointer::AxisSource> for ::backend::input::AxisSource {
    fn from(libinput: ::input::event::pointer::AxisSource) -> Self {
        match libinput {
            ::input::event::pointer::AxisSource::Finger => ::backend::input::AxisSource::Finger,
            ::input::event::pointer::AxisSource::Continuous => ::backend::input::AxisSource::Continuous,
            ::input::event::pointer::AxisSource::Wheel => ::backend::input::AxisSource::Wheel,
            ::input::event::pointer::AxisSource::WheelTilt => ::backend::input::AxisSource::WheelTilt,
        }
    }
}

impl From<::input::event::pointer::ButtonState> for ::backend::input::MouseButtonState {
    fn from(libinput: ::input::event::pointer::ButtonState) -> Self {
        match libinput {
            ::input::event::pointer::ButtonState::Pressed => ::backend::input::MouseButtonState::Pressed,
            ::input::event::pointer::ButtonState::Released => ::backend::input::MouseButtonState::Released,
        }
    }
}

impl From<::input::event::touch::TouchEvent> for ::backend::input::TouchEvent {
    fn from(libinput: ::input::event::touch::TouchEvent) -> Self {
        use ::input::event::touch::{TouchEventSlot, TouchEventPosition};
        use ::backend::TouchSlotInternal;

        match libinput {
            ::input::event::touch::TouchEvent::Down(down_event) => ::backend::input::TouchEvent::Down {
                slot: down_event.slot().map(|x| ::backend::input::TouchSlot::new(x)),
                x: down_event.x_transformed(/*FIXME: global.get_focused_output_for_seat(&desc.seat).width() or something like that*/ 1280),
                y: down_event.x_transformed(/*FIXME: global.get_focused_output_for_seat(&desc.seat).height() or something like that*/ 800),
            },
            ::input::event::touch::TouchEvent::Motion(motion_event) => ::backend::input::TouchEvent::Motion {
                slot: motion_event.slot().map(|x| ::backend::input::TouchSlot::new(x)),
                x: motion_event.x_transformed(/*FIXME: global.get_focused_output_for_seat(&desc.seat).width() or something like that*/ 1280),
                y: motion_event.x_transformed(/*FIXME: global.get_focused_output_for_seat(&desc.seat).height() or something like that*/ 800),
            },
            ::input::event::touch::TouchEvent::Up(up_event) => ::backend::input::TouchEvent::Up {
                slot: up_event.slot().map(|x| ::backend::input::TouchSlot::new(x)),
            },
            ::input::event::touch::TouchEvent::Cancel(cancel_event) => ::backend::input::TouchEvent::Cancel {
                slot: cancel_event.slot().map(|x| ::backend::input::TouchSlot::new(x)),
            },
            ::input::event::touch::TouchEvent::Frame(_) => ::backend::input::TouchEvent::Frame,
        }
    }
}
<|endoftext|>


<commit_before>/// Creates a [`Vec`] containing the arguments.
///
/// `vec!` allows `Vec`s to be defined with the same syntax as array expressions.
/// There are two forms of this macro:
///
/// - Create a [`Vec`] containing a given list of elements:
///
/// ```
/// let v = vec![1, 2, 3];
/// assert_eq!(v[0], 1);
/// assert_eq!(v[1], 2);
/// assert_eq!(v[2], 3);
/// ```
///
/// - Create a [`Vec`] from a given element and size:
///
/// ```
/// let v = vec![1; 3];
/// assert_eq!(v, [1, 1, 1]);
/// ```
///
/// Note that unlike array expressions this syntax supports all elements
/// which implement [`Clone`] and the number of elements doesn't have to be
/// a constant.
///
/// This will use `clone` to duplicate an expression, so one should be careful
/// using this with types having a nonstandard `Clone` implementation. For
/// example, `vec![Rc::new(1); 5]` will create a vector of five references
/// to the same boxed integer value, not five references pointing to independently
/// boxed integers.
///
/// [`Vec`]: ../std/vec/struct.Vec.html
/// [`Clone`]: ../std/clone/trait.Clone.html
#[cfg(not(test))]
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(box_syntax)]
macro_rules! vec {
    ($elem:expr; $n:expr) => (
        $crate::vec::from_elem($elem, $n)
    );
    ($($x:expr),*) => (
        <[_]>::into_vec(box [$($x),*])
    );
    ($($x:expr,)*) => ($crate::vec![$($x),*])
}

// HACK(japaric): with cfg(test) the inherent `[T]::into_vec` method, which is
// required for this macro definition, is not available. Instead use the
// `slice::into_vec`  function which is only available with cfg(test)
// NB see the slice::hack module in slice.rs for more information
#[cfg(test)]
macro_rules! vec {
    ($elem:expr; $n:expr) => (
        $crate::vec::from_elem($elem, $n)
    );
    ($($x:expr),*) => (
        $crate::slice::into_vec(box [$($x),*])
    );
    ($($x:expr,)*) => (vec![$($x),*])
}

/// Creates a `String` using interpolation of runtime expressions.
///
/// The first argument `format!` receives is a format string. This must be a string
/// literal. The power of the formatting string is in the `{}`s contained.
///
/// Additional parameters passed to `format!` replace the `{}`s within the
/// formatting string in the order given unless named or positional parameters
/// are used; see [`std::fmt`][fmt] for more information.
///
/// A common use for `format!` is concatenation and interpolation of strings.
/// The same convention is used with [`print!`] and [`write!`] macros,
/// depending on the intended destination of the string.
///
/// To convert a single value to a string, use the [`to_string`] method. This
/// will use the [`Display`] formatting trait.
///
/// [fmt]: ../std/fmt/index.html
/// [`print!`]: ../std/macro.print.html
/// [`write!`]: ../std/macro.write.html
/// [`to_string`]: ../std/string/trait.ToString.html
/// [`Display`]: ../std/fmt/trait.Display.html
///
/// # Panics
///
/// `format!` panics if a formatting trait implementation returns an error.
/// This indicates an incorrect implementation
/// since `fmt::Write for String` never returns an error itself.
///
/// # Examples
///
/// ```
/// format!("test");
/// format!("hello {}", "world!");
/// format!("x = {}, y = {y}", 10, y = 30);
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! format {
    ($($arg:tt)*) => {{
        let res = $crate::fmt::format($crate::__export::format_args!($($arg)*));
        res
    }}
}
<commit_msg>Rollup merge of #70632 - tspiteri:vec-new, r=sfackler<commit_after>/// Creates a [`Vec`] containing the arguments.
///
/// `vec!` allows `Vec`s to be defined with the same syntax as array expressions.
/// There are two forms of this macro:
///
/// - Create a [`Vec`] containing a given list of elements:
///
/// ```
/// let v = vec![1, 2, 3];
/// assert_eq!(v[0], 1);
/// assert_eq!(v[1], 2);
/// assert_eq!(v[2], 3);
/// ```
///
/// - Create a [`Vec`] from a given element and size:
///
/// ```
/// let v = vec![1; 3];
/// assert_eq!(v, [1, 1, 1]);
/// ```
///
/// Note that unlike array expressions this syntax supports all elements
/// which implement [`Clone`] and the number of elements doesn't have to be
/// a constant.
///
/// This will use `clone` to duplicate an expression, so one should be careful
/// using this with types having a nonstandard `Clone` implementation. For
/// example, `vec![Rc::new(1); 5]` will create a vector of five references
/// to the same boxed integer value, not five references pointing to independently
/// boxed integers.
///
/// [`Vec`]: ../std/vec/struct.Vec.html
/// [`Clone`]: ../std/clone/trait.Clone.html
#[cfg(not(test))]
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(box_syntax)]
macro_rules! vec {
    () => (
        $crate::vec::Vec::new()
    );
    ($elem:expr; $n:expr) => (
        $crate::vec::from_elem($elem, $n)
    );
    ($($x:expr),*) => (
        <[_]>::into_vec(box [$($x),*])
    );
    ($($x:expr,)*) => ($crate::vec![$($x),*])
}

// HACK(japaric): with cfg(test) the inherent `[T]::into_vec` method, which is
// required for this macro definition, is not available. Instead use the
// `slice::into_vec`  function which is only available with cfg(test)
// NB see the slice::hack module in slice.rs for more information
#[cfg(test)]
macro_rules! vec {
    () => (
        $crate::vec::Vec::new()
    );
    ($elem:expr; $n:expr) => (
        $crate::vec::from_elem($elem, $n)
    );
    ($($x:expr),*) => (
        $crate::slice::into_vec(box [$($x),*])
    );
    ($($x:expr,)*) => (vec![$($x),*])
}

/// Creates a `String` using interpolation of runtime expressions.
///
/// The first argument `format!` receives is a format string. This must be a string
/// literal. The power of the formatting string is in the `{}`s contained.
///
/// Additional parameters passed to `format!` replace the `{}`s within the
/// formatting string in the order given unless named or positional parameters
/// are used; see [`std::fmt`][fmt] for more information.
///
/// A common use for `format!` is concatenation and interpolation of strings.
/// The same convention is used with [`print!`] and [`write!`] macros,
/// depending on the intended destination of the string.
///
/// To convert a single value to a string, use the [`to_string`] method. This
/// will use the [`Display`] formatting trait.
///
/// [fmt]: ../std/fmt/index.html
/// [`print!`]: ../std/macro.print.html
/// [`write!`]: ../std/macro.write.html
/// [`to_string`]: ../std/string/trait.ToString.html
/// [`Display`]: ../std/fmt/trait.Display.html
///
/// # Panics
///
/// `format!` panics if a formatting trait implementation returns an error.
/// This indicates an incorrect implementation
/// since `fmt::Write for String` never returns an error itself.
///
/// # Examples
///
/// ```
/// format!("test");
/// format!("hello {}", "world!");
/// format!("x = {}, y = {y}", 10, y = 30);
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! format {
    ($($arg:tt)*) => {{
        let res = $crate::fmt::format($crate::__export::format_args!($($arg)*));
        res
    }}
}
<|endoftext|>


<commit_before>#![feature(no_std)]
#![feature(const_fn)]
#![no_std]
#![no_builtins]

#[macro_use]
extern crate uni;
extern crate xen;

pub mod event;
pub mod arch;
pub mod libc;

extern {
    fn main(_: isize, _: *const *const u8) -> isize;
}

// 8KB
const STACK_SIZE: usize = 8192;

#[no_mangle]
#[allow(non_upper_case_globals)]
#[link_section=".stack"]
pub static rust_stack: [u8; STACK_SIZE] = [0; STACK_SIZE];

fn init() {
    self::arch::init();

    println!("Uni.rs is booting");

    // Memory initialization is unsafe
    unsafe {
        let (heap_start, heap_size) = arch::init_memory();

        uni::allocator::init(heap_start, heap_size);
    }

    event::init();

    unsafe {
        uni::console::console().init_input();
    }

    xen::enable_upcalls();
}

#[no_mangle]
pub extern "C" fn uni_rust_entry() -> ! {
    let app_ret;

    init();

    unsafe {
        app_ret = main(0, core::ptr::null());
    }

    xen::disable_upcalls();

    uni::console::console().flush();

    xen::sched::poweroff(app_ret as xen::defs::Ulong);

    panic!("Failed to poweroff the machine !");
}
<commit_msg>libboot: main is now called inside a thread<commit_after>#![feature(no_std)]
#![feature(const_fn)]
#![no_std]
#![no_builtins]

#[macro_use]
extern crate uni;
extern crate xen;

pub mod event;
pub mod arch;
pub mod libc;

extern {
    fn main(_: isize, _: *const *const u8) -> isize;
}

use uni::thread::Scheduler;

// 8KB
const STACK_SIZE: usize = 8192;

#[no_mangle]
#[allow(non_upper_case_globals)]
#[link_section=".stack"]
pub static rust_stack: [u8; STACK_SIZE] = [0; STACK_SIZE];

#[no_mangle]
pub extern "C" fn uni_rust_entry() -> ! {
    self::arch::init();

    println!("Uni.rs is booting");

    // Memory initialization is unsafe
    unsafe {
        let (heap_start, heap_size) = arch::init_memory();

        uni::allocator::init(heap_start, heap_size);
    }

    event::init();

    unsafe {
        uni::console::console().init_input();
    }

    xen::enable_upcalls();

    println!("Creating main thread");

    // Spawn main thread
    Scheduler::spawn(|| {
        let app_ret = unsafe {
            main(0, core::ptr::null())
        };

        xen::disable_upcalls();

        uni::console::console().flush();

        xen::sched::poweroff(app_ret as xen::defs::Ulong);

        panic!("Failed to poweroff the machine !");
    });

    println!("Starting scheduler");

    Scheduler::schedule();

    unreachable!();
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Takeru Ohta <phjgt308@gmail.com>
//
// This software is released under the MIT License,
// see the LICENSE file at the top-level directory.

use std::mem;
use std::rc::Rc;
use std::cmp::PartialEq;
use std::hash::Hash;
use std::hash::Hasher;
use WordId;
use Char;

#[derive(Eq,Clone)]
pub struct Node {
    pub ch: Char,
    pub is_terminal: bool,
    pub child: Option<Rc<Node>>,
    pub sibling: Option<Rc<Node>>,
    child_total: u32,
    sibling_total: u32,
}

pub type NodeAddr = usize;

impl PartialEq for Node {
    fn eq(&self, other: &Node) -> bool {
        (self.child.as_ref().map(|n| n.addr()) == other.child.as_ref().map(|n| n.addr()) &&
         self.sibling.as_ref().map(|n| n.addr()) == other.sibling.as_ref().map(|n| n.addr()) &&
         self.ch == other.ch && self.is_terminal == other.is_terminal)
    }
}

impl Hash for Node {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.ch.hash(state);
        self.is_terminal.hash(state);
        self.child.as_ref().map(|n| n.addr()).hash(state);
        self.sibling.as_ref().map(|n| n.addr()).hash(state);
    }
}

impl Node {
    pub fn new(ch: Char) -> Self {
        Node {
            ch: ch,
            is_terminal: false,
            child: None,
            sibling: None,
            child_total: 0,
            sibling_total: 0,
        }
    }

    pub fn len(&self) -> usize {
        (self.is_terminal as u32 + self.child_total + self.sibling_total) as usize
    }

    pub fn id_offset(&self) -> WordId {
        self.sibling_total
    }

    pub fn fix(&mut self) {
        self.child_total = self.child.as_ref().map_or(0, |n| n.len() as u32);
        self.sibling_total = self.sibling.as_ref().map_or(0, |n| n.len() as u32);
    }

    pub fn children(&self) -> Children {
        Children { curr: self.child.clone() }
    }

    pub fn take_children(&mut self) -> Children {
        Children { curr: self.child.take() }
    }

    pub fn addr(&self) -> NodeAddr {
        unsafe { mem::transmute(self) }
    }
}

#[derive(Clone)]
pub struct Children {
    curr: Option<Rc<Node>>,
}

impl Iterator for Children {
    type Item = Rc<Node>;

    fn next(&mut self) -> Option<Self::Item> {
        self.curr.take().map(|mut child| {
            self.curr = Rc::get_mut(&mut child)
                            .map(|c| c.sibling.take())
                            .unwrap_or_else(|| child.sibling.clone());
            child
        })
    }
}
<commit_msg>Replace unnnessary unsafe code to safe equivalent<commit_after>// Copyright (c) 2015 Takeru Ohta <phjgt308@gmail.com>
//
// This software is released under the MIT License,
// see the LICENSE file at the top-level directory.

use std::rc::Rc;
use std::cmp::PartialEq;
use std::hash::Hash;
use std::hash::Hasher;
use WordId;
use Char;

#[derive(Eq,Clone)]
pub struct Node {
    pub ch: Char,
    pub is_terminal: bool,
    pub child: Option<Rc<Node>>,
    pub sibling: Option<Rc<Node>>,
    child_total: u32,
    sibling_total: u32,
}

pub type NodeAddr = *const Node;

impl PartialEq for Node {
    fn eq(&self, other: &Node) -> bool {
        (self.child.as_ref().map(|n| n.addr()) == other.child.as_ref().map(|n| n.addr()) &&
         self.sibling.as_ref().map(|n| n.addr()) == other.sibling.as_ref().map(|n| n.addr()) &&
         self.ch == other.ch && self.is_terminal == other.is_terminal)
    }
}

impl Hash for Node {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.ch.hash(state);
        self.is_terminal.hash(state);
        self.child.as_ref().map(|n| n.addr()).hash(state);
        self.sibling.as_ref().map(|n| n.addr()).hash(state);
    }
}

impl Node {
    pub fn new(ch: Char) -> Self {
        Node {
            ch: ch,
            is_terminal: false,
            child: None,
            sibling: None,
            child_total: 0,
            sibling_total: 0,
        }
    }

    pub fn len(&self) -> usize {
        (self.is_terminal as u32 + self.child_total + self.sibling_total) as usize
    }

    pub fn id_offset(&self) -> WordId {
        self.sibling_total
    }

    pub fn fix(&mut self) {
        self.child_total = self.child.as_ref().map_or(0, |n| n.len() as u32);
        self.sibling_total = self.sibling.as_ref().map_or(0, |n| n.len() as u32);
    }

    pub fn children(&self) -> Children {
        Children { curr: self.child.clone() }
    }

    pub fn take_children(&mut self) -> Children {
        Children { curr: self.child.take() }
    }

    pub fn addr(&self) -> NodeAddr {
        self as NodeAddr
    }
}

#[derive(Clone)]
pub struct Children {
    curr: Option<Rc<Node>>,
}

impl Iterator for Children {
    type Item = Rc<Node>;

    fn next(&mut self) -> Option<Self::Item> {
        self.curr.take().map(|mut child| {
            self.curr = Rc::get_mut(&mut child)
                            .map(|c| c.sibling.take())
                            .unwrap_or_else(|| child.sibling.clone());
            child
        })
    }
}
<|endoftext|>


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

use std::fs;
use std::fs::File;
use std::io::{Read, Write};
use std::path;

use bindgen::config::{Config, Language};
use bindgen::ir::{
    Constant, Function, ItemContainer, ItemMap, Path as BindgenPath, Static, Struct,
};
use bindgen::writer::{Source, SourceWriter};

/// A bindings header that can be written.
pub struct Bindings {
    pub config: Config,
    /// The map from path to struct, used to lookup whether a given type is a
    /// transparent struct. This is needed to generate code for constants.
    struct_map: ItemMap<Struct>,
    globals: Vec<Static>,
    constants: Vec<Constant>,
    items: Vec<ItemContainer>,
    functions: Vec<Function>,
}

impl Bindings {
    pub(crate) fn new(
        config: Config,
        struct_map: ItemMap<Struct>,
        constants: Vec<Constant>,
        globals: Vec<Static>,
        items: Vec<ItemContainer>,
        functions: Vec<Function>,
    ) -> Bindings {
        Bindings {
            config,
            struct_map,
            globals,
            constants,
            items,
            functions,
        }
    }

    // FIXME(emilio): What to do when the configuration doesn't match?
    pub fn struct_is_transparent(&self, path: &BindgenPath) -> bool {
        let mut any = false;
        self.struct_map.for_items(path, |s| any |= s.is_transparent);
        any
    }

    pub fn struct_exists(&self, path: &BindgenPath) -> bool {
        let mut any = false;
        self.struct_map.for_items(path, |_| any = true);
        any
    }

    pub fn write_to_file<P: AsRef<path::Path>>(&self, path: P) -> bool {
        // Don't compare files if we've never written this file before
        if !path.as_ref().is_file() {
            if let Some(parent) = path::Path::new(path.as_ref()).parent() {
                fs::create_dir_all(parent).unwrap();
            }
            self.write(File::create(path).unwrap());
            return true;
        }

        let mut new_file_contents = Vec::new();
        self.write(&mut new_file_contents);

        let mut old_file_contents = Vec::new();
        {
            let mut old_file = File::open(&path).unwrap();
            old_file.read_to_end(&mut old_file_contents).unwrap();
        }

        if old_file_contents != new_file_contents {
            let mut new_file = File::create(&path).unwrap();
            new_file.write_all(&new_file_contents).unwrap();
            true
        } else {
            false
        }
    }

    pub fn write_headers<F: Write>(&self, out: &mut SourceWriter<F>) {
        if let Some(ref f) = self.config.header {
            out.new_line_if_not_start();
            write!(out, "{}", f);
            out.new_line();
        }
        if let Some(ref f) = self.config.include_guard {
            out.new_line_if_not_start();
            write!(out, "#ifndef {}", f);
            out.new_line();
            write!(out, "#define {}", f);
            out.new_line();
        }
        if self.config.include_version {
            out.new_line_if_not_start();
            write!(
                out,
                "/* Generated with cbindgen:{} */",
                ::bindgen::config::VERSION
            );
            out.new_line();
        }
        if let Some(ref f) = self.config.autogen_warning {
            out.new_line_if_not_start();
            write!(out, "{}", f);
            out.new_line();
        }

        out.new_line_if_not_start();
        if !self.config.no_includes {
            if self.config.language == Language::C {
                out.write("#include <stdarg.h>");
                out.new_line();
                out.write("#include <stdbool.h>");
                out.new_line();
                out.write("#include <stdint.h>");
                out.new_line();
                out.write("#include <stdlib.h>");
                out.new_line();
            } else {
                out.write("#include <cstdarg>");
                out.new_line();
                out.write("#include <cstdint>");
                out.new_line();
                out.write("#include <cstdlib>");
                out.new_line();
                out.write("#include <new>");
                out.new_line();
                if self.config.enumeration.cast_assert_name.is_none()
                    && (self.config.enumeration.derive_mut_casts
                        || self.config.enumeration.derive_const_casts)
                {
                    out.write("#include <cassert>");
                    out.new_line();
                }
            }
        }

        for include in &self.config.sys_includes {
            write!(out, "#include <{}>", include);
            out.new_line();
        }

        for include in &self.config.includes {
            write!(out, "#include \"{}\"", include);
            out.new_line();
        }
    }

    pub fn write<F: Write>(&self, file: F) {
        let mut out = SourceWriter::new(file, self);

        if !self.config.no_includes
            || !self.config.includes.is_empty()
            || !self.config.sys_includes.is_empty()
        {
            self.write_headers(&mut out);
        }

        if self.config.language == Language::Cxx {
            self.open_namespaces(&mut out);
        }

        for constant in &self.constants {
            if constant.ty.is_primitive_or_ptr_primitive() {
                out.new_line_if_not_start();
                constant.write(&self.config, &mut out, None);
                out.new_line();
            }
        }

        for item in &self.items {
            if item
                .deref()
                .annotations()
                .bool("no-export")
                .unwrap_or(false)
            {
                continue;
            }

            out.new_line_if_not_start();
            match *item {
                ItemContainer::Constant(..) => unreachable!(),
                ItemContainer::Static(..) => unreachable!(),
                ItemContainer::Enum(ref x) => x.write(&self.config, &mut out),
                ItemContainer::Struct(ref x) => x.write(&self.config, &mut out),
                ItemContainer::Union(ref x) => x.write(&self.config, &mut out),
                ItemContainer::OpaqueItem(ref x) => x.write(&self.config, &mut out),
                ItemContainer::Typedef(ref x) => x.write(&self.config, &mut out),
            }
            out.new_line();
        }

        for constant in &self.constants {
            if !constant.ty.is_primitive_or_ptr_primitive() {
                out.new_line_if_not_start();
                constant.write(&self.config, &mut out, None);
                out.new_line();
            }
        }

        if !self.functions.is_empty() || !self.globals.is_empty() {
            if self.config.language == Language::C && self.config.cpp_compat {
                out.new_line_if_not_start();
                out.write("#ifdef __cplusplus");
            }

            if self.config.language == Language::Cxx || self.config.cpp_compat {
                out.new_line();
                out.write("extern \"C\" {");
                out.new_line();
            }

            if self.config.language == Language::C && self.config.cpp_compat {
                out.write("#endif // __cplusplus");
                out.new_line();
            }

            for global in &self.globals {
                out.new_line_if_not_start();
                global.write(&self.config, &mut out);
                out.new_line();
            }

            for function in &self.functions {
                out.new_line_if_not_start();
                function.write(&self.config, &mut out);
                out.new_line();
            }

            if self.config.language == Language::C && self.config.cpp_compat {
                out.new_line();
                out.write("#ifdef __cplusplus");
            }

            if self.config.language == Language::Cxx || self.config.cpp_compat {
                out.new_line();
                out.write("} // extern \"C\"");
                out.new_line();
            }

            if self.config.language == Language::C && self.config.cpp_compat {
                out.write("#endif // __cplusplus");
                out.new_line();
            }
        }

        if self.config.language == Language::Cxx {
            self.close_namespaces(&mut out);
        }

        if let Some(ref f) = self.config.include_guard {
            out.new_line_if_not_start();
            if self.config.language == Language::C {
                write!(out, "#endif /* {} */", f);
            } else {
                write!(out, "#endif // {}", f);
            }
            out.new_line();
        }
        if let Some(ref f) = self.config.trailer {
            out.new_line_if_not_start();
            write!(out, "{}", f);
            out.new_line();
        }
    }

    pub(crate) fn open_namespaces<F: Write>(&self, out: &mut SourceWriter<F>) {
        let mut wrote_namespace: bool = false;
        if let Some(ref namespace) = self.config.namespace {
            wrote_namespace = true;

            out.new_line();
            write!(out, "namespace {} {{", namespace);
        }
        if let Some(ref namespaces) = self.config.namespaces {
            wrote_namespace = true;
            for namespace in namespaces {
                out.new_line();
                write!(out, "namespace {} {{", namespace);
            }
        }
        if wrote_namespace {
            out.new_line();
        }
    }

    pub(crate) fn close_namespaces<F: Write>(&self, out: &mut SourceWriter<F>) {
        let mut wrote_namespace: bool = false;
        if let Some(ref namespaces) = self.config.namespaces {
            wrote_namespace = true;

            for namespace in namespaces.iter().rev() {
                out.new_line_if_not_start();
                write!(out, "}} // namespace {}", namespace);
            }
        }
        if let Some(ref namespace) = self.config.namespace {
            wrote_namespace = true;

            out.new_line_if_not_start();
            write!(out, "}} // namespace {}", namespace);
        }
        if wrote_namespace {
            out.new_line();
        }
    }
}
<commit_msg>Move checking configs related include into write_headers<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::fs;
use std::fs::File;
use std::io::{Read, Write};
use std::path;

use bindgen::config::{Config, Language};
use bindgen::ir::{
    Constant, Function, ItemContainer, ItemMap, Path as BindgenPath, Static, Struct,
};
use bindgen::writer::{Source, SourceWriter};

/// A bindings header that can be written.
pub struct Bindings {
    pub config: Config,
    /// The map from path to struct, used to lookup whether a given type is a
    /// transparent struct. This is needed to generate code for constants.
    struct_map: ItemMap<Struct>,
    globals: Vec<Static>,
    constants: Vec<Constant>,
    items: Vec<ItemContainer>,
    functions: Vec<Function>,
}

impl Bindings {
    pub(crate) fn new(
        config: Config,
        struct_map: ItemMap<Struct>,
        constants: Vec<Constant>,
        globals: Vec<Static>,
        items: Vec<ItemContainer>,
        functions: Vec<Function>,
    ) -> Bindings {
        Bindings {
            config,
            struct_map,
            globals,
            constants,
            items,
            functions,
        }
    }

    // FIXME(emilio): What to do when the configuration doesn't match?
    pub fn struct_is_transparent(&self, path: &BindgenPath) -> bool {
        let mut any = false;
        self.struct_map.for_items(path, |s| any |= s.is_transparent);
        any
    }

    pub fn struct_exists(&self, path: &BindgenPath) -> bool {
        let mut any = false;
        self.struct_map.for_items(path, |_| any = true);
        any
    }

    pub fn write_to_file<P: AsRef<path::Path>>(&self, path: P) -> bool {
        // Don't compare files if we've never written this file before
        if !path.as_ref().is_file() {
            if let Some(parent) = path::Path::new(path.as_ref()).parent() {
                fs::create_dir_all(parent).unwrap();
            }
            self.write(File::create(path).unwrap());
            return true;
        }

        let mut new_file_contents = Vec::new();
        self.write(&mut new_file_contents);

        let mut old_file_contents = Vec::new();
        {
            let mut old_file = File::open(&path).unwrap();
            old_file.read_to_end(&mut old_file_contents).unwrap();
        }

        if old_file_contents != new_file_contents {
            let mut new_file = File::create(&path).unwrap();
            new_file.write_all(&new_file_contents).unwrap();
            true
        } else {
            false
        }
    }

    pub fn write_headers<F: Write>(&self, out: &mut SourceWriter<F>) {
        if let Some(ref f) = self.config.header {
            out.new_line_if_not_start();
            write!(out, "{}", f);
            out.new_line();
        }
        if let Some(ref f) = self.config.include_guard {
            out.new_line_if_not_start();
            write!(out, "#ifndef {}", f);
            out.new_line();
            write!(out, "#define {}", f);
            out.new_line();
        }
        if self.config.include_version {
            out.new_line_if_not_start();
            write!(
                out,
                "/* Generated with cbindgen:{} */",
                ::bindgen::config::VERSION
            );
            out.new_line();
        }
        if let Some(ref f) = self.config.autogen_warning {
            out.new_line_if_not_start();
            write!(out, "{}", f);
            out.new_line();
        }

        if self.config.no_includes
            && self.config.sys_includes.is_empty()
            && self.config.includes.is_empty()
        {
            return;
        }

        out.new_line_if_not_start();

        if !self.config.no_includes {
            if self.config.language == Language::C {
                out.write("#include <stdarg.h>");
                out.new_line();
                out.write("#include <stdbool.h>");
                out.new_line();
                out.write("#include <stdint.h>");
                out.new_line();
                out.write("#include <stdlib.h>");
                out.new_line();
            } else {
                out.write("#include <cstdarg>");
                out.new_line();
                out.write("#include <cstdint>");
                out.new_line();
                out.write("#include <cstdlib>");
                out.new_line();
                out.write("#include <new>");
                out.new_line();
                if self.config.enumeration.cast_assert_name.is_none()
                    && (self.config.enumeration.derive_mut_casts
                        || self.config.enumeration.derive_const_casts)
                {
                    out.write("#include <cassert>");
                    out.new_line();
                }
            }
        }

        for include in &self.config.sys_includes {
            write!(out, "#include <{}>", include);
            out.new_line();
        }

        for include in &self.config.includes {
            write!(out, "#include \"{}\"", include);
            out.new_line();
        }
    }

    pub fn write<F: Write>(&self, file: F) {
        let mut out = SourceWriter::new(file, self);

        self.write_headers(&mut out);

        if self.config.language == Language::Cxx {
            self.open_namespaces(&mut out);
        }

        for constant in &self.constants {
            if constant.ty.is_primitive_or_ptr_primitive() {
                out.new_line_if_not_start();
                constant.write(&self.config, &mut out, None);
                out.new_line();
            }
        }

        for item in &self.items {
            if item
                .deref()
                .annotations()
                .bool("no-export")
                .unwrap_or(false)
            {
                continue;
            }

            out.new_line_if_not_start();
            match *item {
                ItemContainer::Constant(..) => unreachable!(),
                ItemContainer::Static(..) => unreachable!(),
                ItemContainer::Enum(ref x) => x.write(&self.config, &mut out),
                ItemContainer::Struct(ref x) => x.write(&self.config, &mut out),
                ItemContainer::Union(ref x) => x.write(&self.config, &mut out),
                ItemContainer::OpaqueItem(ref x) => x.write(&self.config, &mut out),
                ItemContainer::Typedef(ref x) => x.write(&self.config, &mut out),
            }
            out.new_line();
        }

        for constant in &self.constants {
            if !constant.ty.is_primitive_or_ptr_primitive() {
                out.new_line_if_not_start();
                constant.write(&self.config, &mut out, None);
                out.new_line();
            }
        }

        if !self.functions.is_empty() || !self.globals.is_empty() {
            if self.config.language == Language::C && self.config.cpp_compat {
                out.new_line_if_not_start();
                out.write("#ifdef __cplusplus");
            }

            if self.config.language == Language::Cxx || self.config.cpp_compat {
                out.new_line();
                out.write("extern \"C\" {");
                out.new_line();
            }

            if self.config.language == Language::C && self.config.cpp_compat {
                out.write("#endif // __cplusplus");
                out.new_line();
            }

            for global in &self.globals {
                out.new_line_if_not_start();
                global.write(&self.config, &mut out);
                out.new_line();
            }

            for function in &self.functions {
                out.new_line_if_not_start();
                function.write(&self.config, &mut out);
                out.new_line();
            }

            if self.config.language == Language::C && self.config.cpp_compat {
                out.new_line();
                out.write("#ifdef __cplusplus");
            }

            if self.config.language == Language::Cxx || self.config.cpp_compat {
                out.new_line();
                out.write("} // extern \"C\"");
                out.new_line();
            }

            if self.config.language == Language::C && self.config.cpp_compat {
                out.write("#endif // __cplusplus");
                out.new_line();
            }
        }

        if self.config.language == Language::Cxx {
            self.close_namespaces(&mut out);
        }

        if let Some(ref f) = self.config.include_guard {
            out.new_line_if_not_start();
            if self.config.language == Language::C {
                write!(out, "#endif /* {} */", f);
            } else {
                write!(out, "#endif // {}", f);
            }
            out.new_line();
        }
        if let Some(ref f) = self.config.trailer {
            out.new_line_if_not_start();
            write!(out, "{}", f);
            out.new_line();
        }
    }

    pub(crate) fn open_namespaces<F: Write>(&self, out: &mut SourceWriter<F>) {
        let mut wrote_namespace: bool = false;
        if let Some(ref namespace) = self.config.namespace {
            wrote_namespace = true;

            out.new_line();
            write!(out, "namespace {} {{", namespace);
        }
        if let Some(ref namespaces) = self.config.namespaces {
            wrote_namespace = true;
            for namespace in namespaces {
                out.new_line();
                write!(out, "namespace {} {{", namespace);
            }
        }
        if wrote_namespace {
            out.new_line();
        }
    }

    pub(crate) fn close_namespaces<F: Write>(&self, out: &mut SourceWriter<F>) {
        let mut wrote_namespace: bool = false;
        if let Some(ref namespaces) = self.config.namespaces {
            wrote_namespace = true;

            for namespace in namespaces.iter().rev() {
                out.new_line_if_not_start();
                write!(out, "}} // namespace {}", namespace);
            }
        }
        if let Some(ref namespace) = self.config.namespace {
            wrote_namespace = true;

            out.new_line_if_not_start();
            write!(out, "}} // namespace {}", namespace);
        }
        if wrote_namespace {
            out.new_line();
        }
    }
}
<|endoftext|>


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

use std::fs;
use std::fs::File;
use std::io::{Read, Write};
use std::path;

use bindgen::config::{Config, Language};
use bindgen::ir::{Constant, Function, ItemContainer, Static};
use bindgen::writer::{Source, SourceWriter};

/// A bindings header that can be written.
pub struct Bindings {
    config: Config,
    globals: Vec<Static>,
    constants: Vec<Constant>,
    items: Vec<ItemContainer>,
    functions: Vec<Function>,
}

impl Bindings {
    pub(crate) fn new(
        config: Config,
        constants: Vec<Constant>,
        globals: Vec<Static>,
        items: Vec<ItemContainer>,
        functions: Vec<Function>,
    ) -> Bindings {
        Bindings {
            config: config,
            globals: globals,
            constants: constants,
            items: items,
            functions: functions,
        }
    }

    pub fn write_to_file<P: AsRef<path::Path>>(&self, path: P) -> bool {
        // Don't compare files if we've never written this file before
        if !path.as_ref().is_file() {
            if let Some(parent) = path::Path::new(path.as_ref()).parent() {
                fs::create_dir_all(parent).unwrap();
            }
            self.write(File::create(path).unwrap());
            return true;
        }

        let mut new_file_contents = Vec::new();
        self.write(&mut new_file_contents);

        let mut old_file_contents = Vec::new();
        {
            let mut old_file = File::open(&path).unwrap();
            old_file.read_to_end(&mut old_file_contents).unwrap();
        }

        if old_file_contents != new_file_contents {
            let mut new_file = File::create(&path).unwrap();
            new_file.write_all(&new_file_contents).unwrap();
            true
        } else {
            false
        }
    }

    pub fn write_headers<F: Write>(&self, out: &mut SourceWriter<F>) {
        if let Some(ref f) = self.config.header {
            out.new_line_if_not_start();
            write!(out, "{}", f);
            out.new_line();
        }
        if let Some(ref f) = self.config.include_guard {
            out.new_line_if_not_start();
            write!(out, "#ifndef {}", f);
            out.new_line();
            write!(out, "#define {}", f);
            out.new_line();
        }
        if self.config.include_version {
            out.new_line_if_not_start();
            write!(
                out,
                "/* Generated with cbindgen:{} */",
                ::bindgen::config::VERSION
            );
            out.new_line();
        }
        if let Some(ref f) = self.config.autogen_warning {
            out.new_line_if_not_start();
            write!(out, "{}", f);
            out.new_line();
        }

        out.new_line_if_not_start();
        if self.config.language == Language::C {
            out.write("#include <stdarg.h>");
            out.new_line();
            out.write("#include <stdbool.h>");
            out.new_line();
            out.write("#include <stdint.h>");
            out.new_line();
            out.write("#include <stdlib.h>");
            out.new_line();
        } else {
            out.write("#include <cstdarg>");
            out.new_line();
            out.write("#include <cstdint>");
            out.new_line();
            out.write("#include <cstdlib>");
            out.new_line();
        }

        for include in &self.config.sys_includes {
            write!(out, "#include <{}>", include);
            out.new_line();
        }

        for include in &self.config.includes {
            write!(out, "#include \"{}\"", include);
            out.new_line();
        }
    }

    pub fn write<F: Write>(&self, file: F) {
        let mut out = SourceWriter::new(file, &self.config);

        if !self.config.no_includes {
            self.write_headers(&mut out);
        }

        if self.config.language == Language::Cxx {
            self.open_namespaces(&mut out);
        }

        for constant in &self.constants {
            if constant.ty.is_primitive_or_ptr_primitive() {
                out.new_line_if_not_start();
                constant.write(&self.config, &mut out);
                out.new_line();
            }
        }

        for item in &self.items {
            if item
                .deref()
                .annotations()
                .bool("no-export")
                .unwrap_or(false)
            {
                continue;
            }

            out.new_line_if_not_start();
            match item {
                &ItemContainer::Constant(..) => unreachable!(),
                &ItemContainer::Static(..) => unreachable!(),
                &ItemContainer::Enum(ref x) => x.write(&self.config, &mut out),
                &ItemContainer::Struct(ref x) => x.write(&self.config, &mut out),
                &ItemContainer::Union(ref x) => x.write(&self.config, &mut out),
                &ItemContainer::OpaqueItem(ref x) => x.write(&self.config, &mut out),
                &ItemContainer::Typedef(ref x) => x.write(&self.config, &mut out),
            }
            out.new_line();
        }

        for constant in &self.constants {
            if !constant.ty.is_primitive_or_ptr_primitive() {
                out.new_line_if_not_start();
                constant.write(&self.config, &mut out);
                out.new_line();
            }
        }

        if !self.functions.is_empty() || !self.globals.is_empty() {
            if self.config.language == Language::Cxx {
                out.new_line_if_not_start();
                out.write("extern \"C\" {");
                out.new_line();
            }

            for global in &self.globals {
                out.new_line_if_not_start();
                global.write(&self.config, &mut out);
                out.new_line();
            }

            for function in &self.functions {
                out.new_line_if_not_start();
                function.write(&self.config, &mut out);
                out.new_line();
            }

            if self.config.language == Language::Cxx {
                out.new_line_if_not_start();
                out.write("} // extern \"C\"");
                out.new_line();
            }
        }

        if self.config.language == Language::Cxx {
            self.close_namespaces(&mut out);
        }

        if let Some(ref f) = self.config.include_guard {
            out.new_line_if_not_start();
            if self.config.language == Language::C {
                write!(out, "#endif /* {} */", f);
            } else {
                write!(out, "#endif // {}", f);
            }
            out.new_line();
        }
        if let Some(ref f) = self.config.trailer {
            out.new_line_if_not_start();
            write!(out, "{}", f);
            out.new_line();
        }
    }

    pub(crate) fn open_namespaces<F: Write>(&self, out: &mut SourceWriter<F>) {
        let mut wrote_namespace: bool = false;
        if let Some(ref namespace) = self.config.namespace {
            wrote_namespace = true;

            out.new_line();
            write!(out, "namespace {} {{", namespace);
        }
        if let Some(ref namespaces) = self.config.namespaces {
            wrote_namespace = true;
            for namespace in namespaces {
                out.new_line();
                write!(out, "namespace {} {{", namespace);
            }
        }
        if wrote_namespace {
            out.new_line();
        }
    }

    pub(crate) fn close_namespaces<F: Write>(&self, out: &mut SourceWriter<F>) {
        let mut wrote_namespace: bool = false;
        if let Some(ref namespaces) = self.config.namespaces {
            wrote_namespace = true;

            for namespace in namespaces.iter().rev() {
                out.new_line_if_not_start();
                write!(out, "}} // namespace {}", namespace);
            }
        }
        if let Some(ref namespace) = self.config.namespace {
            wrote_namespace = true;

            out.new_line_if_not_start();
            write!(out, "}} // namespace {}", namespace);
        }
        if wrote_namespace {
            out.new_line();
        }
    }
}
<commit_msg>Added support to includes without default includes<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::fs;
use std::fs::File;
use std::io::{Read, Write};
use std::path;

use bindgen::config::{Config, Language};
use bindgen::ir::{Constant, Function, ItemContainer, Static};
use bindgen::writer::{Source, SourceWriter};

/// A bindings header that can be written.
pub struct Bindings {
    config: Config,
    globals: Vec<Static>,
    constants: Vec<Constant>,
    items: Vec<ItemContainer>,
    functions: Vec<Function>,
}

impl Bindings {
    pub(crate) fn new(
        config: Config,
        constants: Vec<Constant>,
        globals: Vec<Static>,
        items: Vec<ItemContainer>,
        functions: Vec<Function>,
    ) -> Bindings {
        Bindings {
            config: config,
            globals: globals,
            constants: constants,
            items: items,
            functions: functions,
        }
    }

    pub fn write_to_file<P: AsRef<path::Path>>(&self, path: P) -> bool {
        // Don't compare files if we've never written this file before
        if !path.as_ref().is_file() {
            if let Some(parent) = path::Path::new(path.as_ref()).parent() {
                fs::create_dir_all(parent).unwrap();
            }
            self.write(File::create(path).unwrap());
            return true;
        }

        let mut new_file_contents = Vec::new();
        self.write(&mut new_file_contents);

        let mut old_file_contents = Vec::new();
        {
            let mut old_file = File::open(&path).unwrap();
            old_file.read_to_end(&mut old_file_contents).unwrap();
        }

        if old_file_contents != new_file_contents {
            let mut new_file = File::create(&path).unwrap();
            new_file.write_all(&new_file_contents).unwrap();
            true
        } else {
            false
        }
    }

    pub fn write_headers<F: Write>(&self, out: &mut SourceWriter<F>) {
        if let Some(ref f) = self.config.header {
            out.new_line_if_not_start();
            write!(out, "{}", f);
            out.new_line();
        }
        if let Some(ref f) = self.config.include_guard {
            out.new_line_if_not_start();
            write!(out, "#ifndef {}", f);
            out.new_line();
            write!(out, "#define {}", f);
            out.new_line();
        }
        if self.config.include_version {
            out.new_line_if_not_start();
            write!(
                out,
                "/* Generated with cbindgen:{} */",
                ::bindgen::config::VERSION
            );
            out.new_line();
        }
        if let Some(ref f) = self.config.autogen_warning {
            out.new_line_if_not_start();
            write!(out, "{}", f);
            out.new_line();
        }

        out.new_line_if_not_start();
        if !self.config.no_includes {
            if self.config.language == Language::C {
                out.write("#include <stdarg.h>");
                out.new_line();
                out.write("#include <stdbool.h>");
                out.new_line();
                out.write("#include <stdint.h>");
                out.new_line();
                out.write("#include <stdlib.h>");
                out.new_line();
            } else {
                out.write("#include <cstdarg>");
                out.new_line();
                out.write("#include <cstdint>");
                out.new_line();
                out.write("#include <cstdlib>");
                out.new_line();
            }

        }

        for include in &self.config.sys_includes {
            write!(out, "#include <{}>", include);
            out.new_line();
        }

        for include in &self.config.includes {
            write!(out, "#include \"{}\"", include);
            out.new_line();
        }
    }

    pub fn write<F: Write>(&self, file: F) {
        let mut out = SourceWriter::new(file, &self.config);

        if !self.config.no_includes || !self.config.includes.is_empty() || !self.config.sys_includes.is_empty() {
            self.write_headers(&mut out);
        }

        if self.config.language == Language::Cxx {
            self.open_namespaces(&mut out);
        }

        for constant in &self.constants {
            if constant.ty.is_primitive_or_ptr_primitive() {
                out.new_line_if_not_start();
                constant.write(&self.config, &mut out);
                out.new_line();
            }
        }

        for item in &self.items {
            if item
                .deref()
                .annotations()
                .bool("no-export")
                .unwrap_or(false)
            {
                continue;
            }

            out.new_line_if_not_start();
            match item {
                &ItemContainer::Constant(..) => unreachable!(),
                &ItemContainer::Static(..) => unreachable!(),
                &ItemContainer::Enum(ref x) => x.write(&self.config, &mut out),
                &ItemContainer::Struct(ref x) => x.write(&self.config, &mut out),
                &ItemContainer::Union(ref x) => x.write(&self.config, &mut out),
                &ItemContainer::OpaqueItem(ref x) => x.write(&self.config, &mut out),
                &ItemContainer::Typedef(ref x) => x.write(&self.config, &mut out),
            }
            out.new_line();
        }

        for constant in &self.constants {
            if !constant.ty.is_primitive_or_ptr_primitive() {
                out.new_line_if_not_start();
                constant.write(&self.config, &mut out);
                out.new_line();
            }
        }

        if !self.functions.is_empty() || !self.globals.is_empty() {
            if self.config.language == Language::Cxx {
                out.new_line_if_not_start();
                out.write("extern \"C\" {");
                out.new_line();
            }

            for global in &self.globals {
                out.new_line_if_not_start();
                global.write(&self.config, &mut out);
                out.new_line();
            }

            for function in &self.functions {
                out.new_line_if_not_start();
                function.write(&self.config, &mut out);
                out.new_line();
            }

            if self.config.language == Language::Cxx {
                out.new_line_if_not_start();
                out.write("} // extern \"C\"");
                out.new_line();
            }
        }

        if self.config.language == Language::Cxx {
            self.close_namespaces(&mut out);
        }

        if let Some(ref f) = self.config.include_guard {
            out.new_line_if_not_start();
            if self.config.language == Language::C {
                write!(out, "#endif /* {} */", f);
            } else {
                write!(out, "#endif // {}", f);
            }
            out.new_line();
        }
        if let Some(ref f) = self.config.trailer {
            out.new_line_if_not_start();
            write!(out, "{}", f);
            out.new_line();
        }
    }

    pub(crate) fn open_namespaces<F: Write>(&self, out: &mut SourceWriter<F>) {
        let mut wrote_namespace: bool = false;
        if let Some(ref namespace) = self.config.namespace {
            wrote_namespace = true;

            out.new_line();
            write!(out, "namespace {} {{", namespace);
        }
        if let Some(ref namespaces) = self.config.namespaces {
            wrote_namespace = true;
            for namespace in namespaces {
                out.new_line();
                write!(out, "namespace {} {{", namespace);
            }
        }
        if wrote_namespace {
            out.new_line();
        }
    }

    pub(crate) fn close_namespaces<F: Write>(&self, out: &mut SourceWriter<F>) {
        let mut wrote_namespace: bool = false;
        if let Some(ref namespaces) = self.config.namespaces {
            wrote_namespace = true;

            for namespace in namespaces.iter().rev() {
                out.new_line_if_not_start();
                write!(out, "}} // namespace {}", namespace);
            }
        }
        if let Some(ref namespace) = self.config.namespace {
            wrote_namespace = true;

            out.new_line_if_not_start();
            write!(out, "}} // namespace {}", namespace);
        }
        if wrote_namespace {
            out.new_line();
        }
    }
}
<|endoftext|>


<commit_before>extern crate errno;

use self::errno::errno;

/*
    Helper function to get errno
*/
pub fn get_errno_with_message(ret: i32) -> String {
    let e = errno();
    let code = e.0 as i32;
    format!("return code = {}, errno = {}, message = '{}'", ret, code, e)
}

/*
    Helper function that checks the error number and depending on the value converts a returned
    buffer to UTF String and returns that as the successful Result
*/
pub fn check_errno(ret: i32, buf: &mut Vec<u8>) -> Result<String, String> {
    if ret <= 0 {
        Err(get_errno_with_message(ret))
    } else {
        unsafe {
            buf.set_len(ret as usize);
        }

        match String::from_utf8(buf.to_vec()) {
            Ok(return_value) => Ok(return_value),
            Err(e) => Err(format!("Invalid UTF-8 sequence: {}", e))
        }
    }
}<commit_msg>Add tests for check_errno()<commit_after>use crate::errno::errno;

/*
    Helper function to get errno
*/
pub fn get_errno_with_message(ret: i32) -> String {
    let e = errno();
    let code = e.0 as i32;
    format!("return code = {}, errno = {}, message = '{}'", ret, code, e)
}

/// Helper function that depending on the `ret` value:
/// - is negative or 0, then form an error message from the `errno` value
/// - is positive, take `ret` as the length of the success message in `buf` in bytes
pub fn check_errno(ret: i32, buf: &mut Vec<u8>) -> Result<String, String> {
    if ret <= 0 {
        Err(get_errno_with_message(ret))
    } else {
        unsafe {
            buf.set_len(ret as usize);
        }

        match String::from_utf8(buf.to_vec()) {
            Ok(return_value) => Ok(return_value),
            Err(e) => Err(format!("Invalid UTF-8 sequence: {}", e))
        }
    }
}

#[cfg(test)]
mod test {
    use crate::errno::{set_errno, Errno};
    use super::check_errno;

    #[test]
    fn invalid_utf8() {
        let mut buf: Vec<u8> = vec!(255, 0, 0);

        // Test
        match check_errno(buf.len() as i32, &mut buf) {
            Err(msg) => assert_eq!(msg, "Invalid UTF-8 sequence: invalid utf-8 sequence of 1 bytes from index 0"),
            Ok(_) => panic!("Unexpected success"),
        }
    }

    #[test]
    fn positive_ret() {
        let message = "custom message";
        let mut buf: Vec<u8> = Vec::from(message.as_bytes());

        // Test
        match check_errno(buf.len() as i32, &mut buf) {
            Err(_) => panic!("Unexpected error"),
            Ok(mes) => assert_eq!(mes, message)
        }
    }

    #[test]
    fn negative_ret() {
        let mut buf: Vec<u8> = vec!();
        set_errno(Errno(-1));

        // Test
        match check_errno(-1, &mut buf) {
            Err(mes) => assert_eq!(mes, "return code = -1, errno = -1, message = 'Unknown error: -1'"),
            Ok(_) => panic!("Unexpected success")
        }
    }

    #[test]
    fn zero_ret() {
        let mut buf: Vec<u8> = vec!();
        set_errno(Errno(0));

        // Test
        match check_errno(0, &mut buf) {
            Err(mes) => assert_eq!(mes, "return code = 0, errno = 0, message = 'Undefined error: 0'"),
            Ok(_) => panic!("Unexpected success")
        }
    }

}<|endoftext|>


<commit_before>use chrono;                                     //Datetime Handling
use time;
use byteorder::{ReadBytesExt, LittleEndian};    //Reading little endian data structs
use std::io::{Error};
use std::fmt;
use std::fmt::{Display,Debug};
use std::io::Read;
use serde::{ser};

pub struct WinTimestamp(
    pub u64
);
impl WinTimestamp {
    pub fn to_datetime(&self) -> chrono::NaiveDateTime {
        // Get nanoseconds (100-nanosecond intervals)
        let t_micro = self.0 / 10;
        // Add microseconds to timestamp via Duration
        (
            chrono::NaiveDate::from_ymd(1601, 1, 1).and_hms_nano(0, 0, 0, 0) + // Win Epoc = 1601-01-01
            time::Duration::microseconds(t_micro as i64)
        ) as chrono::NaiveDateTime
    }
}
impl Display for WinTimestamp {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,"{}",self.to_datetime())
    }
}
impl Debug for WinTimestamp {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,"{}",self.to_datetime())
    }
}
impl ser::Serialize for WinTimestamp {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: ser::Serializer
    {
        serializer.serialize_str(&format!("{}", self.to_datetime()))
    }
}

#[allow(dead_code)]
// For tests
pub fn raw_to_wintimestamp<R: Read>(mut buffer: R)->Result<WinTimestamp,Error>{
    let win_timestamp: WinTimestamp = WinTimestamp(
        buffer.read_u64::<LittleEndian>().unwrap()
    );
    Ok(win_timestamp)
}
<commit_msg>removed in favor of r-winstructs lib<commit_after><|endoftext|>