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

use rand;

use smithay::{
    reexports::wayland_server::{
        protocol::{wl_buffer, wl_pointer::ButtonState, wl_shell_surface, wl_surface},
        Display,
    },
    utils::Rectangle,
    wayland::{
        compositor::{compositor_init, CompositorToken, RegionAttributes, SurfaceAttributes, SurfaceEvent},
        data_device::DnDIconRole,
        seat::{AxisFrame, CursorImageRole, GrabStartData, PointerGrab, PointerInnerHandle, Seat},
        shell::{
            legacy::{
                wl_shell_init, ShellRequest, ShellState as WlShellState, ShellSurfaceKind, ShellSurfaceRole,
            },
            xdg::{
                xdg_shell_init, PopupConfigure, ShellState as XdgShellState, ToplevelConfigure, XdgRequest,
                XdgSurfaceRole,
            },
        },
        SERIAL_COUNTER as SCOUNTER,
    },
};

use crate::window_map::{Kind as SurfaceKind, WindowMap};

define_roles!(Roles =>
    [ XdgSurface, XdgSurfaceRole ]
    [ ShellSurface, ShellSurfaceRole]
    [ DnDIcon, DnDIconRole ]
    [ CursorImage, CursorImageRole ]
);

pub type MyWindowMap = WindowMap<
    Roles,
    fn(&SurfaceAttributes) -> Option<(i32, i32)>,
    fn(&SurfaceAttributes, (f64, f64)) -> bool,
>;

pub type MyCompositorToken = CompositorToken<Roles>;

struct MoveSurfaceGrab {
    start_data: GrabStartData,
    window_map: Rc<RefCell<MyWindowMap>>,
    toplevel: SurfaceKind<Roles>,
    initial_window_location: (i32, i32),
}

impl PointerGrab for MoveSurfaceGrab {
    fn motion(
        &mut self,
        _handle: &mut PointerInnerHandle<'_>,
        location: (f64, f64),
        _focus: Option<(wl_surface::WlSurface, (f64, f64))>,
        _serial: u32,
        _time: u32,
    ) {
        let dx = location.0 - self.start_data.location.0;
        let dy = location.1 - self.start_data.location.1;
        let new_window_x = (self.initial_window_location.0 as f64 + dx) as i32;
        let new_window_y = (self.initial_window_location.1 as f64 + dy) as i32;

        self.window_map
            .borrow_mut()
            .set_location(&self.toplevel, (new_window_x, new_window_y));
    }

    fn button(
        &mut self,
        handle: &mut PointerInnerHandle<'_>,
        button: u32,
        state: ButtonState,
        serial: u32,
        time: u32,
    ) {
        handle.button(button, state, serial, time);
        if handle.current_pressed().is_empty() {
            // No more buttons are pressed, release the grab.
            handle.unset_grab(serial, time);
        }
    }

    fn axis(&mut self, handle: &mut PointerInnerHandle<'_>, details: AxisFrame) {
        handle.axis(details)
    }

    fn start_data(&self) -> &GrabStartData {
        &self.start_data
    }
}

pub fn init_shell(
    display: &mut Display,
    log: ::slog::Logger,
) -> (
    CompositorToken<Roles>,
    Arc<Mutex<XdgShellState<Roles>>>,
    Arc<Mutex<WlShellState<Roles>>>,
    Rc<RefCell<MyWindowMap>>,
) {
    // Create the compositor
    let (compositor_token, _, _) = compositor_init(
        display,
        move |request, surface, ctoken| match request {
            SurfaceEvent::Commit => surface_commit(&surface, ctoken),
            SurfaceEvent::Frame { callback } => callback
                .implement_closure(|_, _| unreachable!(), None::<fn(_)>, ())
                .done(0),
        },
        log.clone(),
    );

    // Init a window map, to track the location of our windows
    let window_map = Rc::new(RefCell::new(WindowMap::new(
        compositor_token,
        get_size as _,
        contains_point as _,
    )));

    // init the xdg_shell
    let xdg_window_map = window_map.clone();
    let (xdg_shell_state, _, _) = xdg_shell_init(
        display,
        compositor_token,
        move |shell_event| match shell_event {
            XdgRequest::NewToplevel { surface } => {
                // place the window at a random location in the [0;800]x[0;800] square
                use rand::distributions::{Distribution, Uniform};
                let range = Uniform::new(0, 800);
                let mut rng = rand::thread_rng();
                let x = range.sample(&mut rng);
                let y = range.sample(&mut rng);
                surface.send_configure(ToplevelConfigure {
                    size: None,
                    states: vec![],
                    serial: 42,
                });
                xdg_window_map
                    .borrow_mut()
                    .insert(SurfaceKind::Xdg(surface), (x, y));
            }
            XdgRequest::NewPopup { surface } => surface.send_configure(PopupConfigure {
                size: (10, 10),
                position: (10, 10),
                serial: 42,
            }),
            XdgRequest::Move {
                surface,
                seat,
                serial,
            } => {
                let seat = Seat::from_resource(&seat).unwrap();
                // TODO: touch move.
                let pointer = seat.get_pointer().unwrap();

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

                let toplevel = SurfaceKind::Xdg(surface);
                let initial_window_location = xdg_window_map.borrow().location(&toplevel).unwrap();

                let grab = MoveSurfaceGrab {
                    start_data,
                    window_map: xdg_window_map.clone(),
                    toplevel,
                    initial_window_location,
                };

                pointer.set_grab(grab, serial);
            }
            _ => (),
        },
        log.clone(),
    );

    // init the wl_shell
    let shell_window_map = window_map.clone();
    let (wl_shell_state, _) = wl_shell_init(
        display,
        compositor_token,
        move |req: ShellRequest<_>| {
            match req {
                ShellRequest::SetKind {
                    surface,
                    kind: ShellSurfaceKind::Toplevel,
                } => {
                    // place the window at a random location in the [0;800]x[0;800] square
                    use rand::distributions::{Distribution, Uniform};
                    let range = Uniform::new(0, 800);
                    let mut rng = rand::thread_rng();
                    let x = range.sample(&mut rng);
                    let y = range.sample(&mut rng);
                    surface.send_configure((0, 0), wl_shell_surface::Resize::None);
                    shell_window_map
                        .borrow_mut()
                        .insert(SurfaceKind::Wl(surface), (x, y));
                }
                ShellRequest::Move {
                    surface,
                    seat,
                    serial,
                } => {
                    let seat = Seat::from_resource(&seat).unwrap();
                    // TODO: touch move.
                    let pointer = seat.get_pointer().unwrap();

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

                    let toplevel = SurfaceKind::Wl(surface);
                    let initial_window_location = shell_window_map.borrow().location(&toplevel).unwrap();

                    let grab = MoveSurfaceGrab {
                        start_data,
                        window_map: shell_window_map.clone(),
                        toplevel,
                        initial_window_location,
                    };

                    pointer.set_grab(grab, serial);
                }
                _ => (),
            }
        },
        log.clone(),
    );

    (compositor_token, xdg_shell_state, wl_shell_state, window_map)
}

#[derive(Default)]
pub struct SurfaceData {
    pub buffer: Option<wl_buffer::WlBuffer>,
    pub texture: Option<crate::glium_drawer::TextureMetadata>,
    pub input_region: Option<RegionAttributes>,
}

fn surface_commit(surface: &wl_surface::WlSurface, token: CompositorToken<Roles>) {
    token.with_surface_data(surface, |attributes| {
        attributes.user_data.insert_if_missing(SurfaceData::default);
        let data = attributes.user_data.get_mut::<SurfaceData>().unwrap();

        data.input_region = attributes.input_region.clone();

        // we retrieve the contents of the associated buffer and copy it
        match attributes.buffer.take() {
            Some(Some((buffer, (_x, _y)))) => {
                // new contents
                // TODO: handle hotspot coordinates
                if let Some(old_buffer) = data.buffer.replace(buffer) {
                    old_buffer.release();
                }
                data.texture = None;
            }
            Some(None) => {
                // erase the contents
                if let Some(old_buffer) = data.buffer.take() {
                    old_buffer.release();
                }
                data.texture = None;
            }
            None => {}
        }
    });
}

fn get_size(attrs: &SurfaceAttributes) -> Option<(i32, i32)> {
    attrs.user_data.get::<SurfaceData>().and_then(|data| {
        data.texture
            .as_ref()
            .map(|ref meta| meta.dimensions)
            .map(|(x, y)| (x as i32, y as i32))
    })
}

fn contains_point(attrs: &SurfaceAttributes, point: (f64, f64)) -> bool {
    let (w, h) = match get_size(attrs) {
        None => return false, // If the surface has no size, it can't have an input region.
        Some(wh) => wh,
    };

    let rect = Rectangle {
        x: 0,
        y: 0,
        width: w,
        height: h,
    };

    let point = (point.0 as i32, point.1 as i32);

    // 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;
    }

    let input_region = &attrs.user_data.get::<SurfaceData>().unwrap().input_region;

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

    input_region.as_ref().unwrap().contains(point)
}
<commit_msg>anvil.shell: check that there's a grab before Move<commit_after>use std::{
    cell::RefCell,
    rc::Rc,
    sync::{Arc, Mutex},
};

use rand;

use smithay::{
    reexports::wayland_server::{
        protocol::{wl_buffer, wl_pointer::ButtonState, wl_shell_surface, wl_surface},
        Display,
    },
    utils::Rectangle,
    wayland::{
        compositor::{compositor_init, CompositorToken, RegionAttributes, SurfaceAttributes, SurfaceEvent},
        data_device::DnDIconRole,
        seat::{AxisFrame, CursorImageRole, GrabStartData, PointerGrab, PointerInnerHandle, Seat},
        shell::{
            legacy::{
                wl_shell_init, ShellRequest, ShellState as WlShellState, ShellSurfaceKind, ShellSurfaceRole,
            },
            xdg::{
                xdg_shell_init, PopupConfigure, ShellState as XdgShellState, ToplevelConfigure, XdgRequest,
                XdgSurfaceRole,
            },
        },
        SERIAL_COUNTER as SCOUNTER,
    },
};

use crate::window_map::{Kind as SurfaceKind, WindowMap};

define_roles!(Roles =>
    [ XdgSurface, XdgSurfaceRole ]
    [ ShellSurface, ShellSurfaceRole]
    [ DnDIcon, DnDIconRole ]
    [ CursorImage, CursorImageRole ]
);

pub type MyWindowMap = WindowMap<
    Roles,
    fn(&SurfaceAttributes) -> Option<(i32, i32)>,
    fn(&SurfaceAttributes, (f64, f64)) -> bool,
>;

pub type MyCompositorToken = CompositorToken<Roles>;

struct MoveSurfaceGrab {
    start_data: GrabStartData,
    window_map: Rc<RefCell<MyWindowMap>>,
    toplevel: SurfaceKind<Roles>,
    initial_window_location: (i32, i32),
}

impl PointerGrab for MoveSurfaceGrab {
    fn motion(
        &mut self,
        _handle: &mut PointerInnerHandle<'_>,
        location: (f64, f64),
        _focus: Option<(wl_surface::WlSurface, (f64, f64))>,
        _serial: u32,
        _time: u32,
    ) {
        let dx = location.0 - self.start_data.location.0;
        let dy = location.1 - self.start_data.location.1;
        let new_window_x = (self.initial_window_location.0 as f64 + dx) as i32;
        let new_window_y = (self.initial_window_location.1 as f64 + dy) as i32;

        self.window_map
            .borrow_mut()
            .set_location(&self.toplevel, (new_window_x, new_window_y));
    }

    fn button(
        &mut self,
        handle: &mut PointerInnerHandle<'_>,
        button: u32,
        state: ButtonState,
        serial: u32,
        time: u32,
    ) {
        handle.button(button, state, serial, time);
        if handle.current_pressed().is_empty() {
            // No more buttons are pressed, release the grab.
            handle.unset_grab(serial, time);
        }
    }

    fn axis(&mut self, handle: &mut PointerInnerHandle<'_>, details: AxisFrame) {
        handle.axis(details)
    }

    fn start_data(&self) -> &GrabStartData {
        &self.start_data
    }
}

pub fn init_shell(
    display: &mut Display,
    log: ::slog::Logger,
) -> (
    CompositorToken<Roles>,
    Arc<Mutex<XdgShellState<Roles>>>,
    Arc<Mutex<WlShellState<Roles>>>,
    Rc<RefCell<MyWindowMap>>,
) {
    // Create the compositor
    let (compositor_token, _, _) = compositor_init(
        display,
        move |request, surface, ctoken| match request {
            SurfaceEvent::Commit => surface_commit(&surface, ctoken),
            SurfaceEvent::Frame { callback } => callback
                .implement_closure(|_, _| unreachable!(), None::<fn(_)>, ())
                .done(0),
        },
        log.clone(),
    );

    // Init a window map, to track the location of our windows
    let window_map = Rc::new(RefCell::new(WindowMap::new(
        compositor_token,
        get_size as _,
        contains_point as _,
    )));

    // init the xdg_shell
    let xdg_window_map = window_map.clone();
    let (xdg_shell_state, _, _) = xdg_shell_init(
        display,
        compositor_token,
        move |shell_event| match shell_event {
            XdgRequest::NewToplevel { surface } => {
                // place the window at a random location in the [0;800]x[0;800] square
                use rand::distributions::{Distribution, Uniform};
                let range = Uniform::new(0, 800);
                let mut rng = rand::thread_rng();
                let x = range.sample(&mut rng);
                let y = range.sample(&mut rng);
                surface.send_configure(ToplevelConfigure {
                    size: None,
                    states: vec![],
                    serial: 42,
                });
                xdg_window_map
                    .borrow_mut()
                    .insert(SurfaceKind::Xdg(surface), (x, y));
            }
            XdgRequest::NewPopup { surface } => surface.send_configure(PopupConfigure {
                size: (10, 10),
                position: (10, 10),
                serial: 42,
            }),
            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();

                let toplevel = SurfaceKind::Xdg(surface);
                let initial_window_location = xdg_window_map.borrow().location(&toplevel).unwrap();

                let grab = MoveSurfaceGrab {
                    start_data,
                    window_map: xdg_window_map.clone(),
                    toplevel,
                    initial_window_location,
                };

                pointer.set_grab(grab, serial);
            }
            _ => (),
        },
        log.clone(),
    );

    // init the wl_shell
    let shell_window_map = window_map.clone();
    let (wl_shell_state, _) = wl_shell_init(
        display,
        compositor_token,
        move |req: ShellRequest<_>| {
            match req {
                ShellRequest::SetKind {
                    surface,
                    kind: ShellSurfaceKind::Toplevel,
                } => {
                    // place the window at a random location in the [0;800]x[0;800] square
                    use rand::distributions::{Distribution, Uniform};
                    let range = Uniform::new(0, 800);
                    let mut rng = rand::thread_rng();
                    let x = range.sample(&mut rng);
                    let y = range.sample(&mut rng);
                    surface.send_configure((0, 0), wl_shell_surface::Resize::None);
                    shell_window_map
                        .borrow_mut()
                        .insert(SurfaceKind::Wl(surface), (x, y));
                }
                ShellRequest::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();

                    let toplevel = SurfaceKind::Wl(surface);
                    let initial_window_location = shell_window_map.borrow().location(&toplevel).unwrap();

                    let grab = MoveSurfaceGrab {
                        start_data,
                        window_map: shell_window_map.clone(),
                        toplevel,
                        initial_window_location,
                    };

                    pointer.set_grab(grab, serial);
                }
                _ => (),
            }
        },
        log.clone(),
    );

    (compositor_token, xdg_shell_state, wl_shell_state, window_map)
}

#[derive(Default)]
pub struct SurfaceData {
    pub buffer: Option<wl_buffer::WlBuffer>,
    pub texture: Option<crate::glium_drawer::TextureMetadata>,
    pub input_region: Option<RegionAttributes>,
}

fn surface_commit(surface: &wl_surface::WlSurface, token: CompositorToken<Roles>) {
    token.with_surface_data(surface, |attributes| {
        attributes.user_data.insert_if_missing(SurfaceData::default);
        let data = attributes.user_data.get_mut::<SurfaceData>().unwrap();

        data.input_region = attributes.input_region.clone();

        // we retrieve the contents of the associated buffer and copy it
        match attributes.buffer.take() {
            Some(Some((buffer, (_x, _y)))) => {
                // new contents
                // TODO: handle hotspot coordinates
                if let Some(old_buffer) = data.buffer.replace(buffer) {
                    old_buffer.release();
                }
                data.texture = None;
            }
            Some(None) => {
                // erase the contents
                if let Some(old_buffer) = data.buffer.take() {
                    old_buffer.release();
                }
                data.texture = None;
            }
            None => {}
        }
    });
}

fn get_size(attrs: &SurfaceAttributes) -> Option<(i32, i32)> {
    attrs.user_data.get::<SurfaceData>().and_then(|data| {
        data.texture
            .as_ref()
            .map(|ref meta| meta.dimensions)
            .map(|(x, y)| (x as i32, y as i32))
    })
}

fn contains_point(attrs: &SurfaceAttributes, point: (f64, f64)) -> bool {
    let (w, h) = match get_size(attrs) {
        None => return false, // If the surface has no size, it can't have an input region.
        Some(wh) => wh,
    };

    let rect = Rectangle {
        x: 0,
        y: 0,
        width: w,
        height: h,
    };

    let point = (point.0 as i32, point.1 as i32);

    // 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;
    }

    let input_region = &attrs.user_data.get::<SurfaceData>().unwrap().input_region;

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

    input_region.as_ref().unwrap().contains(point)
}
<|endoftext|>


<commit_before>use std::sync::mpsc::{Sender, Receiver, channel};
use std::sync::Arc;

use {Allocate, Data, Push, Pull, Serialize};
use allocator::Process;
use networking::MessageHeader;

// A communicator intended for binary channels (networking, pipes, shared memory)
pub struct Binary {
    pub inner:      Process,    // inner Process (use for process-local channels)
    pub index:      usize,      // index of this worker
    pub peers:      usize,      // number of peer workers
    pub allocated:  usize,      // indicates how many channels have been allocated (locally).

    // for loading up state in the networking threads.
    pub readers:    Vec<Sender<((usize, usize), Sender<Vec<u8>>)>>,
    pub senders:    Vec<Sender<(MessageHeader, Vec<u8>)>>,
    pub log_sender: Arc<Fn(::logging::CommsSetup)->::logging::CommsLogger+Send+Sync>,
}

impl Binary {
    pub fn inner<'a>(&'a mut self) -> &'a mut Process { &mut self.inner }
}

// A Communicator backed by Sender<Vec<u8>>/Receiver<Vec<u8>> pairs (e.g. networking, shared memory, files, pipes)
impl Allocate for Binary {
    fn index(&self) -> usize { self.index }
    fn peers(&self) -> usize { self.peers }
    fn allocate<T:Data>(&mut self) -> (Vec<Box<Push<T>>>, Box<Pull<T>>, Option<usize>) {
        let mut pushers: Vec<Box<Push<T>>> = Vec::new();

        // we'll need process-local channels as well (no self-loop binary connection in this design; perhaps should allow)
        let inner_peers = self.inner.peers();
        let (inner_sends, inner_recv, _) = self.inner.allocate();

        // prep a pushable for each endpoint, multiplied by inner_peers
        for index in 0..self.readers.len() {
            for counter in 0..inner_peers {
                let mut target_index = index * inner_peers + counter;

                // we may need to increment target_index by inner_peers;
                if index >= self.index / inner_peers { target_index += inner_peers; }

                let header = MessageHeader {
                    channel:    self.allocated,
                    source:     self.index,
                    target:     target_index,
                    length:     0,
                    seqno:      0,
                };
                let logger = (self.log_sender)(::logging::CommsSetup {
                    process: self.index,
                    sender: true,
                    remote: Some(target_index),
                });
                pushers.push(Box::new(Pusher::new(header, self.senders[index].clone(), logger)));
            }
        }

        // splice inner_sends into the vector of pushables
        for (index, writer) in inner_sends.into_iter().enumerate() {
            pushers.insert(((self.index / inner_peers) * inner_peers) + index, writer);
        }

        // prep a Box<Pullable<T>> using inner_recv and fresh registered pullables
        let (send,recv) = channel();    // binary channel from binary listener to BinaryPullable<T>
        for reader in self.readers.iter() {
            reader.send(((self.index, self.allocated), send.clone())).unwrap();
        }

        let logger = (self.log_sender)(::logging::CommsSetup {
            process: self.index,
            sender: false,
            remote: None,
        });
        let pullable = Box::new(Puller::new(inner_recv, recv, logger));

        self.allocated += 1;

        (pushers, pullable, Some(self.allocated - 1))
    }
}

struct Pusher<T> {
    header:     MessageHeader,
    sender:     Sender<(MessageHeader, Vec<u8>)>,   // targets for each remote destination
    phantom:    ::std::marker::PhantomData<T>,
    log_sender: ::logging::CommsLogger,
}

impl<T> Pusher<T> {
    pub fn new(header: MessageHeader, sender: Sender<(MessageHeader, Vec<u8>)>, log_sender: ::logging::CommsLogger) -> Pusher<T> {
        Pusher {
            header:     header,
            sender:     sender,
            phantom:    ::std::marker::PhantomData,
            log_sender: log_sender,
        }
    }
}

impl<T:Data> Push<T> for Pusher<T> {
    #[inline] fn push(&mut self, element: &mut Option<T>) {
        if let Some(ref mut element) = *element {
            self.log_sender.when_enabled(|l| l.log(::logging::CommsEvent::Serialization(::logging::SerializationEvent {
                    seq_no: Some(self.header.seqno),
                    is_start: true,
                })));
            let mut bytes = Vec::new();
            <T as Serialize>::into_bytes(element, &mut bytes);
            let mut header = self.header;
            header.length = bytes.len();
            self.sender.send((header, bytes)).ok();     // TODO : should be unwrap()?
            self.log_sender.when_enabled(|l| l.log(::logging::CommsEvent::Serialization(::logging::SerializationEvent {
                    seq_no: Some(self.header.seqno),
                    is_start: true,
                })));
            self.header.seqno += 1;
        }
    }
}

struct Puller<T> {
    inner: Box<Pull<T>>,            // inner pullable (e.g. intra-process typed queue)
    current: Option<T>,
    receiver: Receiver<Vec<u8>>,    // source of serialized buffers
    log_sender: ::logging::CommsLogger,
}
impl<T:Data> Puller<T> {
    fn new(inner: Box<Pull<T>>, receiver: Receiver<Vec<u8>>, log_sender: ::logging::CommsLogger) -> Puller<T> {
        Puller { inner: inner, receiver: receiver, current: None, log_sender: log_sender }
    }
}

impl<T:Data> Pull<T> for Puller<T> {
    #[inline]
    fn pull(&mut self) -> &mut Option<T> {
        let inner = self.inner.pull();
        let log_sender = &self.log_sender;
        if inner.is_some() { inner }
        else {
            self.current = self.receiver.try_recv().ok().map(|mut bytes| {
                log_sender.when_enabled(|l| l.log(
                    ::logging::CommsEvent::Serialization(::logging::SerializationEvent {
                        seq_no: None,
                        is_start: true,
                    })));
                let result = <T as Serialize>::from_bytes(&mut bytes);
                log_sender.when_enabled(|l| l.log(
                    ::logging::CommsEvent::Serialization(::logging::SerializationEvent {
                        seq_no: None,
                        is_start: false,
                    })));
                result
            });
            &mut self.current
        }
    }
}
<commit_msg>fix incorrect is_start value in SerializationEvent<commit_after>use std::sync::mpsc::{Sender, Receiver, channel};
use std::sync::Arc;

use {Allocate, Data, Push, Pull, Serialize};
use allocator::Process;
use networking::MessageHeader;

// A communicator intended for binary channels (networking, pipes, shared memory)
pub struct Binary {
    pub inner:      Process,    // inner Process (use for process-local channels)
    pub index:      usize,      // index of this worker
    pub peers:      usize,      // number of peer workers
    pub allocated:  usize,      // indicates how many channels have been allocated (locally).

    // for loading up state in the networking threads.
    pub readers:    Vec<Sender<((usize, usize), Sender<Vec<u8>>)>>,
    pub senders:    Vec<Sender<(MessageHeader, Vec<u8>)>>,
    pub log_sender: Arc<Fn(::logging::CommsSetup)->::logging::CommsLogger+Send+Sync>,
}

impl Binary {
    pub fn inner<'a>(&'a mut self) -> &'a mut Process { &mut self.inner }
}

// A Communicator backed by Sender<Vec<u8>>/Receiver<Vec<u8>> pairs (e.g. networking, shared memory, files, pipes)
impl Allocate for Binary {
    fn index(&self) -> usize { self.index }
    fn peers(&self) -> usize { self.peers }
    fn allocate<T:Data>(&mut self) -> (Vec<Box<Push<T>>>, Box<Pull<T>>, Option<usize>) {
        let mut pushers: Vec<Box<Push<T>>> = Vec::new();

        // we'll need process-local channels as well (no self-loop binary connection in this design; perhaps should allow)
        let inner_peers = self.inner.peers();
        let (inner_sends, inner_recv, _) = self.inner.allocate();

        // prep a pushable for each endpoint, multiplied by inner_peers
        for index in 0..self.readers.len() {
            for counter in 0..inner_peers {
                let mut target_index = index * inner_peers + counter;

                // we may need to increment target_index by inner_peers;
                if index >= self.index / inner_peers { target_index += inner_peers; }

                let header = MessageHeader {
                    channel:    self.allocated,
                    source:     self.index,
                    target:     target_index,
                    length:     0,
                    seqno:      0,
                };
                let logger = (self.log_sender)(::logging::CommsSetup {
                    process: self.index,
                    sender: true,
                    remote: Some(target_index),
                });
                pushers.push(Box::new(Pusher::new(header, self.senders[index].clone(), logger)));
            }
        }

        // splice inner_sends into the vector of pushables
        for (index, writer) in inner_sends.into_iter().enumerate() {
            pushers.insert(((self.index / inner_peers) * inner_peers) + index, writer);
        }

        // prep a Box<Pullable<T>> using inner_recv and fresh registered pullables
        let (send,recv) = channel();    // binary channel from binary listener to BinaryPullable<T>
        for reader in self.readers.iter() {
            reader.send(((self.index, self.allocated), send.clone())).unwrap();
        }

        let logger = (self.log_sender)(::logging::CommsSetup {
            process: self.index,
            sender: false,
            remote: None,
        });
        let pullable = Box::new(Puller::new(inner_recv, recv, logger));

        self.allocated += 1;

        (pushers, pullable, Some(self.allocated - 1))
    }
}

struct Pusher<T> {
    header:     MessageHeader,
    sender:     Sender<(MessageHeader, Vec<u8>)>,   // targets for each remote destination
    phantom:    ::std::marker::PhantomData<T>,
    log_sender: ::logging::CommsLogger,
}

impl<T> Pusher<T> {
    pub fn new(header: MessageHeader, sender: Sender<(MessageHeader, Vec<u8>)>, log_sender: ::logging::CommsLogger) -> Pusher<T> {
        Pusher {
            header:     header,
            sender:     sender,
            phantom:    ::std::marker::PhantomData,
            log_sender: log_sender,
        }
    }
}

impl<T:Data> Push<T> for Pusher<T> {
    #[inline] fn push(&mut self, element: &mut Option<T>) {
        if let Some(ref mut element) = *element {
            self.log_sender.when_enabled(|l| l.log(::logging::CommsEvent::Serialization(::logging::SerializationEvent {
                    seq_no: Some(self.header.seqno),
                    is_start: true,
                })));
            let mut bytes = Vec::new();
            <T as Serialize>::into_bytes(element, &mut bytes);
            let mut header = self.header;
            header.length = bytes.len();
            self.sender.send((header, bytes)).ok();     // TODO : should be unwrap()?
            self.log_sender.when_enabled(|l| l.log(::logging::CommsEvent::Serialization(::logging::SerializationEvent {
                    seq_no: Some(self.header.seqno),
                    is_start: false,
                })));
            self.header.seqno += 1;
        }
    }
}

struct Puller<T> {
    inner: Box<Pull<T>>,            // inner pullable (e.g. intra-process typed queue)
    current: Option<T>,
    receiver: Receiver<Vec<u8>>,    // source of serialized buffers
    log_sender: ::logging::CommsLogger,
}
impl<T:Data> Puller<T> {
    fn new(inner: Box<Pull<T>>, receiver: Receiver<Vec<u8>>, log_sender: ::logging::CommsLogger) -> Puller<T> {
        Puller { inner: inner, receiver: receiver, current: None, log_sender: log_sender }
    }
}

impl<T:Data> Pull<T> for Puller<T> {
    #[inline]
    fn pull(&mut self) -> &mut Option<T> {
        let inner = self.inner.pull();
        let log_sender = &self.log_sender;
        if inner.is_some() { inner }
        else {
            self.current = self.receiver.try_recv().ok().map(|mut bytes| {
                log_sender.when_enabled(|l| l.log(
                    ::logging::CommsEvent::Serialization(::logging::SerializationEvent {
                        seq_no: None,
                        is_start: true,
                    })));
                let result = <T as Serialize>::from_bytes(&mut bytes);
                log_sender.when_enabled(|l| l.log(
                    ::logging::CommsEvent::Serialization(::logging::SerializationEvent {
                        seq_no: None,
                        is_start: false,
                    })));
                result
            });
            &mut self.current
        }
    }
}
<|endoftext|>


<commit_before>use std::iter::FromIterator;

struct Node<T> {
    data: T,
    next: Option<Box<Node<T>>>,
}

impl<T> Node<T> {
    fn new(data: T, next: Option<Box<Node<T>>>) -> Self {
        Node { data, next }
    }
}

pub struct LinkedListIter<'a, T: 'a> {
    node: &'a Option<Box<Node<T>>>,
}

impl<'a, T> Iterator for LinkedListIter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<&'a T> {
        if let Some(node) = self.node {
            self.node = &node.next;
            Some(&node.data)
        } else {
            None
        }
    }
}

pub struct LinkedListIntoIter<T> {
    node: Option<Box<Node<T>>>,
}

impl<T> Iterator for LinkedListIntoIter<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        if let Some(mut node) = self.node.take() {
            self.node = node.next.take();
            Some(node.data)
        } else {
            None
        }
    }
}

pub struct SimpleLinkedList<T> {
    head: Option<Box<Node<T>>>,
}

impl<T> SimpleLinkedList<T> {
    pub fn new() -> Self {
        SimpleLinkedList { head: None }
    }

    pub fn len(&self) -> usize {
        self.iter().count()
    }

    pub fn push(&mut self, element: T) {
        self.head = Some(Box::new(Node::new(element, self.head.take())));
    }

    pub fn pop(&mut self) -> Option<T> {
        if let Some(mut head) = self.head.take() {
            self.head = head.next.take();
            Some(head.data)
        } else {
            None
        }
    }

    pub fn peek(&self) -> Option<&T> {
        self.iter().next()
    }

    fn iter(&self) -> LinkedListIter<T> {
        LinkedListIter { node: &self.head }
    }
}

impl<T> FromIterator<T> for SimpleLinkedList<T> {
    fn from_iter<I>(iter: I) -> Self
    where
        I: IntoIterator<Item = T>,
    {
        let mut list = SimpleLinkedList::new();

        for i in iter {
            list.push(i);
        }

        list
    }
}

impl<T> IntoIterator for SimpleLinkedList<T> {
    type Item = T;
    type IntoIter = LinkedListIntoIter<T>;

    fn into_iter(self) -> LinkedListIntoIter<T> {
        LinkedListIntoIter { node: self.head }
    }
}

impl<T: Clone> SimpleLinkedList<T> {
    pub fn rev(&self) -> SimpleLinkedList<T> {
        self.iter().cloned().collect()
    }
}

impl<'a, T: Clone> From<&'a [T]> for SimpleLinkedList<T> {
    fn from(item: &[T]) -> Self {
        item.iter().cloned().collect()
    }
}

impl<T> Into<Vec<T>> for SimpleLinkedList<T> {
    fn into(self) -> Vec<T> {
        let mut vec = self.into_iter().collect::<Vec<_>>();

        vec.reverse();
        vec
    }
}
<commit_msg>Further improve solution for Simple Linked List<commit_after>use std::iter::FromIterator;

struct Node<T> {
    data: T,
    next: Option<Box<Node<T>>>,
}

impl<T> Node<T> {
    fn new(data: T, next: Option<Box<Node<T>>>) -> Self {
        Node { data, next }
    }
}

pub struct LinkedListIter<'a, T: 'a> {
    node: &'a Option<Box<Node<T>>>,
}

impl<'a, T> Iterator for LinkedListIter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<&'a T> {
        if let Some(node) = self.node {
            self.node = &node.next;
            Some(&node.data)
        } else {
            None
        }
    }
}

pub struct LinkedListIntoIter<T> {
    node: Option<Box<Node<T>>>,
}

impl<T> Iterator for LinkedListIntoIter<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        if let Some(mut node) = self.node.take() {
            self.node = node.next.take();
            Some(node.data)
        } else {
            None
        }
    }
}

pub struct SimpleLinkedList<T> {
    head: Option<Box<Node<T>>>,
}

impl<T> SimpleLinkedList<T> {
    pub fn new() -> Self {
        SimpleLinkedList { head: None }
    }

    pub fn len(&self) -> usize {
        self.iter().count()
    }

    pub fn push(&mut self, element: T) {
        self.head = Some(Box::new(Node::new(element, self.head.take())));
    }

    pub fn pop(&mut self) -> Option<T> {
        if let Some(mut head) = self.head.take() {
            self.head = head.next.take();
            Some(head.data)
        } else {
            None
        }
    }

    pub fn peek(&self) -> Option<&T> {
        self.iter().next()
    }

    fn iter(&self) -> LinkedListIter<T> {
        LinkedListIter { node: &self.head }
    }
}

impl<T> FromIterator<T> for SimpleLinkedList<T> {
    fn from_iter<I>(iter: I) -> Self
    where
        I: IntoIterator<Item = T>,
    {
        iter.into_iter()
            .fold(SimpleLinkedList::new(), |mut list, i| {
                list.push(i);
                list
            })
    }
}

impl<T> IntoIterator for SimpleLinkedList<T> {
    type Item = T;
    type IntoIter = LinkedListIntoIter<T>;

    fn into_iter(self) -> LinkedListIntoIter<T> {
        LinkedListIntoIter { node: self.head }
    }
}

impl<T: Clone> SimpleLinkedList<T> {
    pub fn rev(&self) -> SimpleLinkedList<T> {
        self.iter().cloned().collect()
    }
}

impl<'a, T: Clone> From<&'a [T]> for SimpleLinkedList<T> {
    fn from(item: &[T]) -> Self {
        item.iter().cloned().collect()
    }
}

impl<T> Into<Vec<T>> for SimpleLinkedList<T> {
    fn into(self) -> Vec<T> {
        let mut vec = self.into_iter().collect::<Vec<_>>();

        vec.reverse();
        vec
    }
}
<|endoftext|>


<commit_before>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Interfaces to the operating system provided random number
//! generators.

pub use self::imp::OsRng;

#[cfg(all(unix, not(target_os = "ios")))]
mod imp {
    extern crate libc;

    use io::{IoResult, File};
    use path::Path;
    use rand::Rng;
    use rand::reader::ReaderRng;
    use result::{Ok, Err};
    use slice::SlicePrelude;
    use mem;
    use os::errno;

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm")))]
    fn getrandom(buf: &mut [u8]) -> libc::c_long {
        extern "C" {
            fn syscall(number: libc::c_long, ...) -> libc::c_long;
        }

        #[cfg(target_arch = "x86_64")]
        const NR_GETRANDOM: libc::c_long = 318;
        #[cfg(target_arch = "x86")]
        const NR_GETRANDOM: libc::c_long = 355;
        #[cfg(target_arch = "arm")]
        const NR_GETRANDOM: libc::c_long = 384;

        unsafe {
            syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), 0u)
        }
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm"))))]
    fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 }

    fn getrandom_fill_bytes(v: &mut [u8]) {
        let mut read = 0;
        let len = v.len();
        while read < len {
            let result = getrandom(v[mut read..]);
            if result == -1 {
                let err = errno() as libc::c_int;
                if err == libc::EINTR {
                    continue;
                } else {
                    panic!("unexpected getrandom error: {}", err);
                }
            } else {
                read += result as uint;
            }
        }
    }

    fn getrandom_next_u32() -> u32 {
        let mut buf: [u8, ..4] = [0u8, ..4];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8, ..4], u32>(buf) }
    }

    fn getrandom_next_u64() -> u64 {
        let mut buf: [u8, ..8] = [0u8, ..8];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8, ..8], u64>(buf) }
    }

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm")))]
    fn is_getrandom_available() -> bool {
        use sync::atomic::{AtomicBool, INIT_ATOMIC_BOOL, Relaxed};

        static GETRANDOM_CHECKED: AtomicBool = INIT_ATOMIC_BOOL;
        static GETRANDOM_AVAILABLE: AtomicBool = INIT_ATOMIC_BOOL;

        if !GETRANDOM_CHECKED.load(Relaxed) {
            let mut buf: [u8, ..0] = [];
            let result = getrandom(&mut buf);
            let available = if result == -1 {
                let err = errno() as libc::c_int;
                err != libc::ENOSYS
            } else {
                true
            };
            GETRANDOM_AVAILABLE.store(available, Relaxed);
            GETRANDOM_CHECKED.store(true, Relaxed);
            available
        } else {
            GETRANDOM_AVAILABLE.load(Relaxed)
        }
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm"))))]
    fn is_getrandom_available() -> bool { false }

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    pub struct OsRng {
        inner: OsRngInner,
    }

    enum OsRngInner {
        OsGetrandomRng,
        OsReaderRng(ReaderRng<File>),
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            if is_getrandom_available() {
                return Ok(OsRng { inner: OsGetrandomRng });
            }

            let reader = try!(File::open(&Path::new("/dev/urandom")));
            let reader_rng = ReaderRng::new(reader);

            Ok(OsRng { inner: OsReaderRng(reader_rng) })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u32(),
                OsReaderRng(ref mut rng) => rng.next_u32(),
            }
        }
        fn next_u64(&mut self) -> u64 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u64(),
                OsReaderRng(ref mut rng) => rng.next_u64(),
            }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            match self.inner {
                OsGetrandomRng => getrandom_fill_bytes(v),
                OsReaderRng(ref mut rng) => rng.fill_bytes(v)
            }
        }
    }
}

#[cfg(target_os = "ios")]
mod imp {
    extern crate libc;

    use io::{IoResult};
    use kinds::marker;
    use mem;
    use os;
    use rand::Rng;
    use result::{Ok};
    use self::libc::{c_int, size_t};
    use slice::{SlicePrelude};

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    pub struct OsRng {
        marker: marker::NoCopy
    }

    #[repr(C)]
    struct SecRandom;

    #[allow(non_upper_case_globals)]
    static kSecRandomDefault: *const SecRandom = 0 as *const SecRandom;

    #[link(name = "Security", kind = "framework")]
    extern "C" {
        fn SecRandomCopyBytes(rnd: *const SecRandom,
                              count: size_t, bytes: *mut u8) -> c_int;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            Ok(OsRng {marker: marker::NoCopy} )
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 8];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t, v.as_mut_ptr())
            };
            if ret == -1 {
                panic!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    extern crate libc;

    use io::{IoResult, IoError};
    use mem;
    use ops::Drop;
    use os;
    use rand::Rng;
    use result::{Ok, Err};
    use self::libc::{DWORD, BYTE, LPCSTR, BOOL};
    use self::libc::types::os::arch::extra::{LONG_PTR};
    use slice::{SlicePrelude};

    type HCRYPTPROV = LONG_PTR;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    pub struct OsRng {
        hcryptprov: HCRYPTPROV
    }

    static PROV_RSA_FULL: DWORD = 1;
    static CRYPT_SILENT: DWORD = 64;
    static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;

    #[allow(non_snake_case)]
    extern "system" {
        fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
                                pszContainer: LPCSTR,
                                pszProvider: LPCSTR,
                                dwProvType: DWORD,
                                dwFlags: DWORD) -> BOOL;
        fn CryptGenRandom(hProv: HCRYPTPROV,
                          dwLen: DWORD,
                          pbBuffer: *mut BYTE) -> BOOL;
        fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            let mut hcp = 0;
            let ret = unsafe {
                CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
                                     PROV_RSA_FULL,
                                     CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
            };

            if ret == 0 {
                Err(IoError::last_error())
            } else {
                Ok(OsRng { hcryptprov: hcp })
            }
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 8];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                CryptGenRandom(self.hcryptprov, v.len() as DWORD,
                               v.as_mut_ptr())
            };
            if ret == 0 {
                panic!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }

    impl Drop for OsRng {
        fn drop(&mut self) {
            let ret = unsafe {
                CryptReleaseContext(self.hcryptprov, 0)
            };
            if ret == 0 {
                panic!("couldn't release context: {}", os::last_os_error());
            }
        }
    }
}

#[cfg(test)]
mod test {
    use prelude::*;

    use super::OsRng;
    use rand::Rng;
    use task;

    #[test]
    fn test_os_rng() {
        let mut r = OsRng::new().unwrap();

        r.next_u32();
        r.next_u64();

        let mut v = [0u8, .. 1000];
        r.fill_bytes(&mut v);
    }

    #[test]
    fn test_os_rng_tasks() {

        let mut txs = vec!();
        for _ in range(0u, 20) {
            let (tx, rx) = channel();
            txs.push(tx);
            task::spawn(proc() {
                // wait until all the tasks are ready to go.
                rx.recv();

                // deschedule to attempt to interleave things as much
                // as possible (XXX: is this a good test?)
                let mut r = OsRng::new().unwrap();
                task::deschedule();
                let mut v = [0u8, .. 1000];

                for _ in range(0u, 100) {
                    r.next_u32();
                    task::deschedule();
                    r.next_u64();
                    task::deschedule();
                    r.fill_bytes(&mut v);
                    task::deschedule();
                }
            })
        }

        // start all the tasks
        for tx in txs.iter() {
            tx.send(())
        }
    }
}
<commit_msg>Switch to purely namespaced enums<commit_after>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Interfaces to the operating system provided random number
//! generators.

pub use self::imp::OsRng;

#[cfg(all(unix, not(target_os = "ios")))]
mod imp {
    extern crate libc;

    use self::OsRngInner::*;

    use io::{IoResult, File};
    use path::Path;
    use rand::Rng;
    use rand::reader::ReaderRng;
    use result::{Ok, Err};
    use slice::SlicePrelude;
    use mem;
    use os::errno;

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm")))]
    fn getrandom(buf: &mut [u8]) -> libc::c_long {
        extern "C" {
            fn syscall(number: libc::c_long, ...) -> libc::c_long;
        }

        #[cfg(target_arch = "x86_64")]
        const NR_GETRANDOM: libc::c_long = 318;
        #[cfg(target_arch = "x86")]
        const NR_GETRANDOM: libc::c_long = 355;
        #[cfg(target_arch = "arm")]
        const NR_GETRANDOM: libc::c_long = 384;

        unsafe {
            syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), 0u)
        }
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm"))))]
    fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 }

    fn getrandom_fill_bytes(v: &mut [u8]) {
        let mut read = 0;
        let len = v.len();
        while read < len {
            let result = getrandom(v[mut read..]);
            if result == -1 {
                let err = errno() as libc::c_int;
                if err == libc::EINTR {
                    continue;
                } else {
                    panic!("unexpected getrandom error: {}", err);
                }
            } else {
                read += result as uint;
            }
        }
    }

    fn getrandom_next_u32() -> u32 {
        let mut buf: [u8, ..4] = [0u8, ..4];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8, ..4], u32>(buf) }
    }

    fn getrandom_next_u64() -> u64 {
        let mut buf: [u8, ..8] = [0u8, ..8];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8, ..8], u64>(buf) }
    }

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm")))]
    fn is_getrandom_available() -> bool {
        use sync::atomic::{AtomicBool, INIT_ATOMIC_BOOL, Relaxed};

        static GETRANDOM_CHECKED: AtomicBool = INIT_ATOMIC_BOOL;
        static GETRANDOM_AVAILABLE: AtomicBool = INIT_ATOMIC_BOOL;

        if !GETRANDOM_CHECKED.load(Relaxed) {
            let mut buf: [u8, ..0] = [];
            let result = getrandom(&mut buf);
            let available = if result == -1 {
                let err = errno() as libc::c_int;
                err != libc::ENOSYS
            } else {
                true
            };
            GETRANDOM_AVAILABLE.store(available, Relaxed);
            GETRANDOM_CHECKED.store(true, Relaxed);
            available
        } else {
            GETRANDOM_AVAILABLE.load(Relaxed)
        }
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm"))))]
    fn is_getrandom_available() -> bool { false }

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    pub struct OsRng {
        inner: OsRngInner,
    }

    enum OsRngInner {
        OsGetrandomRng,
        OsReaderRng(ReaderRng<File>),
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            if is_getrandom_available() {
                return Ok(OsRng { inner: OsGetrandomRng });
            }

            let reader = try!(File::open(&Path::new("/dev/urandom")));
            let reader_rng = ReaderRng::new(reader);

            Ok(OsRng { inner: OsReaderRng(reader_rng) })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u32(),
                OsReaderRng(ref mut rng) => rng.next_u32(),
            }
        }
        fn next_u64(&mut self) -> u64 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u64(),
                OsReaderRng(ref mut rng) => rng.next_u64(),
            }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            match self.inner {
                OsGetrandomRng => getrandom_fill_bytes(v),
                OsReaderRng(ref mut rng) => rng.fill_bytes(v)
            }
        }
    }
}

#[cfg(target_os = "ios")]
mod imp {
    extern crate libc;

    use io::{IoResult};
    use kinds::marker;
    use mem;
    use os;
    use rand::Rng;
    use result::{Ok};
    use self::libc::{c_int, size_t};
    use slice::{SlicePrelude};

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    pub struct OsRng {
        marker: marker::NoCopy
    }

    #[repr(C)]
    struct SecRandom;

    #[allow(non_upper_case_globals)]
    static kSecRandomDefault: *const SecRandom = 0 as *const SecRandom;

    #[link(name = "Security", kind = "framework")]
    extern "C" {
        fn SecRandomCopyBytes(rnd: *const SecRandom,
                              count: size_t, bytes: *mut u8) -> c_int;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            Ok(OsRng {marker: marker::NoCopy} )
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 8];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t, v.as_mut_ptr())
            };
            if ret == -1 {
                panic!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    extern crate libc;

    use io::{IoResult, IoError};
    use mem;
    use ops::Drop;
    use os;
    use rand::Rng;
    use result::{Ok, Err};
    use self::libc::{DWORD, BYTE, LPCSTR, BOOL};
    use self::libc::types::os::arch::extra::{LONG_PTR};
    use slice::{SlicePrelude};

    type HCRYPTPROV = LONG_PTR;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    pub struct OsRng {
        hcryptprov: HCRYPTPROV
    }

    static PROV_RSA_FULL: DWORD = 1;
    static CRYPT_SILENT: DWORD = 64;
    static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;

    #[allow(non_snake_case)]
    extern "system" {
        fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
                                pszContainer: LPCSTR,
                                pszProvider: LPCSTR,
                                dwProvType: DWORD,
                                dwFlags: DWORD) -> BOOL;
        fn CryptGenRandom(hProv: HCRYPTPROV,
                          dwLen: DWORD,
                          pbBuffer: *mut BYTE) -> BOOL;
        fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            let mut hcp = 0;
            let ret = unsafe {
                CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
                                     PROV_RSA_FULL,
                                     CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
            };

            if ret == 0 {
                Err(IoError::last_error())
            } else {
                Ok(OsRng { hcryptprov: hcp })
            }
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 8];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                CryptGenRandom(self.hcryptprov, v.len() as DWORD,
                               v.as_mut_ptr())
            };
            if ret == 0 {
                panic!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }

    impl Drop for OsRng {
        fn drop(&mut self) {
            let ret = unsafe {
                CryptReleaseContext(self.hcryptprov, 0)
            };
            if ret == 0 {
                panic!("couldn't release context: {}", os::last_os_error());
            }
        }
    }
}

#[cfg(test)]
mod test {
    use prelude::*;

    use super::OsRng;
    use rand::Rng;
    use task;

    #[test]
    fn test_os_rng() {
        let mut r = OsRng::new().unwrap();

        r.next_u32();
        r.next_u64();

        let mut v = [0u8, .. 1000];
        r.fill_bytes(&mut v);
    }

    #[test]
    fn test_os_rng_tasks() {

        let mut txs = vec!();
        for _ in range(0u, 20) {
            let (tx, rx) = channel();
            txs.push(tx);
            task::spawn(proc() {
                // wait until all the tasks are ready to go.
                rx.recv();

                // deschedule to attempt to interleave things as much
                // as possible (XXX: is this a good test?)
                let mut r = OsRng::new().unwrap();
                task::deschedule();
                let mut v = [0u8, .. 1000];

                for _ in range(0u, 100) {
                    r.next_u32();
                    task::deschedule();
                    r.next_u64();
                    task::deschedule();
                    r.fill_bytes(&mut v);
                    task::deschedule();
                }
            })
        }

        // start all the tasks
        for tx in txs.iter() {
            tx.send(())
        }
    }
}
<|endoftext|>


<commit_before>use bls::Keypair;
use std::fs;
use std::fs::File;
use std::io::{Error, ErrorKind};
use std::path::PathBuf;
use types::ChainSpec;

/// Stores the core configuration for this validator instance.
#[derive(Clone)]
pub struct ClientConfig {
    pub data_dir: PathBuf,
    pub key_dir: PathBuf,
    pub server: String,
    pub spec: ChainSpec,
}

const DEFAULT_LIGHTHOUSE_DIR: &str = ".lighthouse-validators";
const DEFAULT_KEYSTORE_SUBDIR: &str = "keystore";

impl ClientConfig {
    /// Build a new configuration from defaults.
    pub fn default() -> Result<Self, Error> {
        let data_dir = {
            let home = dirs::home_dir().expect("Unable to determine home dir.");
            home.join(DEFAULT_LIGHTHOUSE_DIR)
        };
        fs::create_dir_all(&data_dir)?;

        let key_dir = data_dir.join(DEFAULT_KEYSTORE_SUBDIR);
        fs::create_dir_all(&key_dir)?;

        let server = "localhost:50051".to_string();
        let spec = ChainSpec::foundation();
        Ok(Self {
            data_dir,
            key_dir,
            server,
            spec,
        })
    }

    // Try to load keys from datadir, or fail
    pub fn fetch_keys(&self) -> Result<Option<Vec<Keypair>>, Error> {
        let mut key_files = fs::read_dir(&self.key_dir)?.peekable();

        if key_files.peek().is_none() {
            return Ok(None);
        }

        let mut key_pairs: Vec<Keypair> = Vec::new();

        for key_filename in key_files {
            let mut key_file = File::open(key_filename?.path())?;

            let key: Keypair = bincode::deserialize_from(&mut key_file)
                .map_err(|e| Error::new(ErrorKind::InvalidData, e))?;

            key_pairs.push(key);
        }

        Ok(Some(key_pairs))
    }

    pub fn save_key(&self, key: &Keypair) -> Result<(), Error> {
        let key_path = self.key_dir.join(key.identifier() + ".key");
        let mut key_file = File::create(&key_path)?;
        bincode::serialize_into(&mut key_file, &key)
            .map_err(|e| Error::new(ErrorKind::InvalidData, e))?;
        Ok(())
    }
}
<commit_msg>Minor updates to Paul's comments.  - Bubbled up home_dir not found error  - Made comment show up in docs<commit_after>use bls::Keypair;
use std::fs;
use std::fs::File;
use std::io::{Error, ErrorKind};
use std::path::PathBuf;
use types::ChainSpec;

/// Stores the core configuration for this validator instance.
#[derive(Clone)]
pub struct ClientConfig {
    pub data_dir: PathBuf,
    pub key_dir: PathBuf,
    pub server: String,
    pub spec: ChainSpec,
}

const DEFAULT_LIGHTHOUSE_DIR: &str = ".lighthouse-validators";
const DEFAULT_KEYSTORE_SUBDIR: &str = "keystore";

impl ClientConfig {
    /// Build a new configuration from defaults.
    pub fn default() -> Result<Self, Error> {
        let data_dir = {
            let home = dirs::home_dir()
                .ok_or(Error::new(ErrorKind::NotFound, "Unable to determine home directory."))?;
            home.join(DEFAULT_LIGHTHOUSE_DIR)
        };
        fs::create_dir_all(&data_dir)?;

        let key_dir = data_dir.join(DEFAULT_KEYSTORE_SUBDIR);
        fs::create_dir_all(&key_dir)?;

        let server = "localhost:50051".to_string();
        let spec = ChainSpec::foundation();
        Ok(Self {
            data_dir,
            key_dir,
            server,
            spec,
        })
    }

    /// Try to load keys from key_dir, returning None if none are found or an error.
    pub fn fetch_keys(&self) -> Result<Option<Vec<Keypair>>, Error> {
        let mut key_files = fs::read_dir(&self.key_dir)?.peekable();

        if key_files.peek().is_none() {
            return Ok(None);
        }

        let mut key_pairs: Vec<Keypair> = Vec::new();

        for key_filename in key_files {
            let mut key_file = File::open(key_filename?.path())?;

            let key: Keypair = bincode::deserialize_from(&mut key_file)
                .map_err(|e| Error::new(ErrorKind::InvalidData, e))?;

            key_pairs.push(key);
        }

        Ok(Some(key_pairs))
    }

    pub fn save_key(&self, key: &Keypair) -> Result<(), Error> {
        let key_path = self.key_dir.join(key.identifier() + ".key");
        let mut key_file = File::create(&key_path)?;
        bincode::serialize_into(&mut key_file, &key)
            .map_err(|e| Error::new(ErrorKind::InvalidData, e))?;
        Ok(())
    }
}
<|endoftext|>


<commit_before>extern crate env_logger;
extern crate log;
extern crate log4rs;
extern crate log_panics;
#[cfg(target_os = "android")]
extern crate android_logger;

use settings;
use std::sync::{Once, ONCE_INIT};
use std::env;
#[allow(unused_imports)]
use self::log::{Level};
#[cfg(target_os = "android")]
use self::android_logger::Filter;

pub struct LoggerUtils {}

static LOGGER_INIT: Once = ONCE_INIT;

// From: https://www.tutorialspoint.com/log4j/log4j_logging_levels.htm
//
//DEBUG	Designates fine-grained informational events that are most useful to debug an application.
//ERROR	Designates error events that might still allow the application to continue running.
//FATAL	Designates very severe error events that will presumably lead the application to abort.
//INFO	Designates informational messages that highlight the progress of the application at coarse-grained level.
//OFF	The highest possible rank and is intended to turn off logging.
//TRACE	Designates finer-grained informational events than the DEBUG.
//WARN	Designates potentially harmful situations.

impl LoggerUtils {
    pub fn init_test_logging(level: &str) {
        // logger for testing purposes, sends to stdout (set env RUST_LOG to configure log level
        let level = match env::var("RUST_LOG") {
            Err(_) => level.to_string(),
            Ok(value) =>  value,
        };
        env::set_var("RUST_LOG", &level);
        LOGGER_INIT.call_once(|| {
            env_logger::init().unwrap();
        });
    }

    pub fn init() {

        match settings::get_config_value(settings::CONFIG_ENABLE_TEST_MODE) {
            Ok(_) => return LoggerUtils::init_test_logging("off"),
            Err(x) => (),
        };

        // turn libindy logging off if RUST_LOG is not specified

        match env::var("RUST_LOG") {
            Err(_) => {
                env::set_var("RUST_LOG", "off");
            },
            Ok(value) =>  (),
        };

        LOGGER_INIT.call_once(|| {
            // Logging of panics is essential for android. As android does not log to stdout for native code
            log_panics::init();
            if cfg!(target_os = "android") {
                // TODO: Set logging to off when deploying production android app.
                #[cfg(target_os = "android")]
                android_logger::init_once(
                    Filter::default().with_min_level(Level::Trace)
                );
                trace!("logging enabled for android");
            } else {
                match settings::get_config_value(settings::CONFIG_LOG_CONFIG) {
                    Err(_) => {/* NO-OP - no logging configured */},
                    Ok(x) => {
                        match log4rs::init_file(&x, Default::default()) {
                            Err(e) => println!("invalid log configuration: {}", e),
                            Ok(_) => {},
                        }
                    }
                }
            }
        });
    }
}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn test_logger() {
        LoggerUtils::init();
    }
}
<commit_msg>Now android logger reads environment variable to set the logging level<commit_after>extern crate env_logger;
extern crate log;
extern crate log4rs;
extern crate log_panics;
#[cfg(target_os = "android")]
extern crate android_logger;

use settings;
use std::sync::{Once, ONCE_INIT};
use std::env;
#[allow(unused_imports)]
use self::log::{Level};
#[cfg(target_os = "android")]
use self::android_logger::Filter;

pub struct LoggerUtils {}

static LOGGER_INIT: Once = ONCE_INIT;

// From: https://www.tutorialspoint.com/log4j/log4j_logging_levels.htm
//
//DEBUG	Designates fine-grained informational events that are most useful to debug an application.
//ERROR	Designates error events that might still allow the application to continue running.
//FATAL	Designates very severe error events that will presumably lead the application to abort.
//INFO	Designates informational messages that highlight the progress of the application at coarse-grained level.
//OFF	The highest possible rank and is intended to turn off logging.
//TRACE	Designates finer-grained informational events than the DEBUG.
//WARN	Designates potentially harmful situations.

impl LoggerUtils {
    pub fn init_test_logging(level: &str) {
        // logger for testing purposes, sends to stdout (set env RUST_LOG to configure log level
        let level = match env::var("RUST_LOG") {
            Err(_) => level.to_string(),
            Ok(value) =>  value,
        };
        env::set_var("RUST_LOG", &level);
        LOGGER_INIT.call_once(|| {
            env_logger::init().unwrap();
        });
    }

    pub fn init() {

        match settings::get_config_value(settings::CONFIG_ENABLE_TEST_MODE) {
            Ok(_) => return LoggerUtils::init_test_logging("off"),
            Err(x) => (),
        };

        // turn libindy logging off if RUST_LOG is not specified

        match env::var("RUST_LOG") {
            Err(_) => {
                env::set_var("RUST_LOG", "off");
            },
            Ok(value) =>  (),
        };

        LOGGER_INIT.call_once(|| {
            // Logging of panics is essential for android. As android does not log to stdout for native code
            log_panics::init();
            if cfg!(target_os = "android") {
                #[cfg(target_os = "android")]
                let log_filter = match env::var("RUST_LOG") {
                    Ok(val) => match val.to_lowercase().as_ref(){
                        "error" => Filter::default().with_min_level(log::Level::Error),
                        "warn" => Filter::default().with_min_level(log::Level::Warn),
                        "info" => Filter::default().with_min_level(log::Level::Info),
                        "debug" => Filter::default().with_min_level(log::Level::Debug),
                        "trace" => Filter::default().with_min_level(log::Level::Trace),
                        _ => Filter::default().with_min_level(log::Level::Error),
                    },
                    Err(..) => Filter::default().with_min_level(log::Level::Error)
                };

                #[cfg(target_os = "android")]
                android_logger::init_once(log_filter);
                info!("Logging for Android");
            } else {
                match settings::get_config_value(settings::CONFIG_LOG_CONFIG) {
                    Err(_) => {/* NO-OP - no logging configured */},
                    Ok(x) => {
                        match log4rs::init_file(&x, Default::default()) {
                            Err(e) => println!("invalid log configuration: {}", e),
                            Ok(_) => {},
                        }
                    }
                }
            }
        });
    }
}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn test_logger() {
        LoggerUtils::init();
    }
}
<|endoftext|>


<commit_before>use ndarray::*;
use numpy::*;

#[test]
fn to_pyarray_vec() {
    pyo3::Python::with_gil(|py| {
        let a = vec![1, 2, 3];
        let arr = a.to_pyarray(py).readonly();
        println!("arr.shape = {:?}", arr.shape());
        assert_eq!(arr.shape(), [3]);
        assert_eq!(arr.as_slice().unwrap(), &[1, 2, 3])
    })
}

#[test]
fn to_pyarray_array() {
    pyo3::Python::with_gil(|py| {
        let a = Array3::<f64>::zeros((3, 4, 2));
        let shape = a.shape().to_vec();
        let strides = a.strides().iter().map(|d| d * 8).collect::<Vec<_>>();
        println!("a.shape   = {:?}", a.shape());
        println!("a.strides = {:?}", a.strides());
        let pa = a.to_pyarray(py);
        println!("pa.shape   = {:?}", pa.shape());
        println!("pa.strides = {:?}", pa.strides());
        assert_eq!(pa.shape(), shape.as_slice());
        assert_eq!(pa.strides(), strides.as_slice());
    })
}

#[test]
fn iter_to_pyarray() {
    pyo3::Python::with_gil(|py| {
        let arr = PyArray::from_iter(py, (0..10).map(|x| x * x)).readonly();
        assert_eq!(
            arr.as_slice().unwrap(),
            &[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
        );
    })
}

#[test]
fn long_iter_to_pyarray() {
    pyo3::Python::with_gil(|py| {
        let arr = PyArray::from_iter(py, 0u32..512).readonly();
        let slice = arr.as_slice().unwrap();
        for (i, &elem) in slice.iter().enumerate() {
            assert_eq!(i as u32, elem);
        }
    })
}

macro_rules! small_array_test {
    ($($t: ident)+) => {
        #[test]
        fn from_small_array() {
            $({
                pyo3::Python::with_gil(|py| {
                    let array: [$t; 2] = [$t::min_value(), $t::max_value()];
                    let pyarray = array.to_pyarray(py).readonly();
                    assert_eq!(
                        pyarray.as_slice().unwrap(),
                        &[$t::min_value(), $t::max_value()]
                    );
                })
            })+
        }
    };
}

small_array_test!(i8 u8 i16 u16 i32 u32 i64 u64 usize);

#[test]
fn usize_dtype() {
    let a: Vec<usize> = vec![1, 2, 3];

    pyo3::Python::with_gil(|py| {
        let x = a.into_pyarray(py);

        if cfg!(target_pointer_width = "64") {
            pyo3::py_run!(py, x, "assert str(x.dtype) == 'uint64'")
        } else {
            pyo3::py_run!(py, x, "assert str(x.dtype) == 'uint32'")
        };
    })
}

#[test]
fn into_pyarray_vec() {
    let a = vec![1, 2, 3];
    pyo3::Python::with_gil(|py| {
        let arr = a.into_pyarray(py).readonly();
        assert_eq!(arr.as_slice().unwrap(), &[1, 2, 3])
    })
}

#[test]
fn into_pyarray_array() {
    let arr = Array3::<f64>::zeros((3, 4, 2));
    let shape = arr.shape().to_vec();
    let strides = arr.strides().iter().map(|d| d * 8).collect::<Vec<_>>();
    pyo3::Python::with_gil(|py| {
        let py_arr = arr.into_pyarray(py);
        assert_eq!(py_arr.shape(), shape.as_slice());
        assert_eq!(py_arr.strides(), strides.as_slice());
    })
}

#[test]
fn into_pyarray_cant_resize() {
    let a = vec![1, 2, 3];
    pyo3::Python::with_gil(|py| {
        let arr = a.into_pyarray(py);
        assert!(arr.resize(100).is_err())
    })
}

/// Check that into_pyarray works for ndarray of which the pointer of the first element is
/// not at the start. See https://github.com/PyO3/rust-numpy/issues/182 for more
#[test]
fn into_pyarray_collapsed() {
    let mut arr = Array2::<f64>::from_shape_fn([3, 4], |(i, j)| (i * 10 + j) as f64);
    arr.slice_collapse(s![1.., ..]);
    let copy = arr.clone();
    pyo3::Python::with_gil(|py| {
        let py_arr = arr.into_pyarray(py);
        assert_eq!(py_arr.readonly().as_array(), copy);
    })
}

#[test]
fn forder_to_pyarray() {
    pyo3::Python::with_gil(|py| {
        let matrix = Array2::from_shape_vec([4, 2], vec![0, 1, 2, 3, 4, 5, 6, 7]).unwrap();
        let fortran_matrix = matrix.reversed_axes();
        let fmat_py = fortran_matrix.to_pyarray(py);
        assert_eq!(
            fmat_py.readonly().as_array(),
            array![[0, 2, 4, 6], [1, 3, 5, 7]],
        );
        pyo3::py_run!(py, fmat_py, "assert fmat_py.flags['F_CONTIGUOUS']")
    })
}

#[test]
fn slice_to_pyarray() {
    pyo3::Python::with_gil(|py| {
        let matrix = Array2::from_shape_vec([4, 2], vec![0, 1, 2, 3, 4, 5, 6, 7]).unwrap();
        let slice = matrix.slice(s![1..4; -1, ..]);
        let slice_py = slice.to_pyarray(py);
        assert_eq!(
            slice_py.readonly().as_array(),
            array![[6, 7], [4, 5], [2, 3]],
        );
        pyo3::py_run!(py, slice_py, "assert slice_py.flags['C_CONTIGUOUS']")
    })
}

#[test]
fn forder_into_pyarray() {
    pyo3::Python::with_gil(|py| {
        let matrix = Array2::from_shape_vec([4, 2], vec![0, 1, 2, 3, 4, 5, 6, 7]).unwrap();
        let fortran_matrix = matrix.reversed_axes();
        let fmat_py = fortran_matrix.into_pyarray(py);
        assert_eq!(
            fmat_py.readonly().as_array(),
            array![[0, 2, 4, 6], [1, 3, 5, 7]],
        );
        pyo3::py_run!(py, fmat_py, "assert fmat_py.flags['F_CONTIGUOUS']")
    })
}

#[test]
fn to_pyarray_object_vec() {
    use pyo3::{
        types::{PyDict, PyString},
        ToPyObject,
    };
    use std::cmp::Ordering;

    pyo3::Python::with_gil(|py| {
        let dict = PyDict::new(py);
        let string = PyString::new(py, "Hello:)");
        let vec = vec![dict.to_object(py), string.to_object(py)];
        let arr = vec.to_pyarray(py).readonly();

        for (a, b) in vec.iter().zip(arr.as_slice().unwrap().iter()) {
            assert_eq!(
                a.as_ref(py).compare(b).map_err(|e| e.print(py)).unwrap(),
                Ordering::Equal
            );
        }
    })
}
<commit_msg>Add a test for the ToPyArray impl for ArrayBase.<commit_after>use ndarray::*;
use numpy::*;

#[test]
fn to_pyarray_vec() {
    pyo3::Python::with_gil(|py| {
        let a = vec![1, 2, 3];
        let arr = a.to_pyarray(py).readonly();
        println!("arr.shape = {:?}", arr.shape());
        assert_eq!(arr.shape(), [3]);
        assert_eq!(arr.as_slice().unwrap(), &[1, 2, 3])
    })
}

#[test]
fn to_pyarray_array() {
    pyo3::Python::with_gil(|py| {
        let a = Array3::<f64>::zeros((3, 4, 2));
        let shape = a.shape().to_vec();
        let strides = a.strides().iter().map(|d| d * 8).collect::<Vec<_>>();
        println!("a.shape   = {:?}", a.shape());
        println!("a.strides = {:?}", a.strides());
        let pa = a.to_pyarray(py);
        println!("pa.shape   = {:?}", pa.shape());
        println!("pa.strides = {:?}", pa.strides());
        assert_eq!(pa.shape(), shape.as_slice());
        assert_eq!(pa.strides(), strides.as_slice());
    })
}

#[test]
fn iter_to_pyarray() {
    pyo3::Python::with_gil(|py| {
        let arr = PyArray::from_iter(py, (0..10).map(|x| x * x)).readonly();
        assert_eq!(
            arr.as_slice().unwrap(),
            &[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
        );
    })
}

#[test]
fn long_iter_to_pyarray() {
    pyo3::Python::with_gil(|py| {
        let arr = PyArray::from_iter(py, 0u32..512).readonly();
        let slice = arr.as_slice().unwrap();
        for (i, &elem) in slice.iter().enumerate() {
            assert_eq!(i as u32, elem);
        }
    })
}

macro_rules! small_array_test {
    ($($t: ident)+) => {
        #[test]
        fn from_small_array() {
            $({
                pyo3::Python::with_gil(|py| {
                    let array: [$t; 2] = [$t::min_value(), $t::max_value()];
                    let pyarray = array.to_pyarray(py).readonly();
                    assert_eq!(
                        pyarray.as_slice().unwrap(),
                        &[$t::min_value(), $t::max_value()]
                    );
                })
            })+
        }
    };
}

small_array_test!(i8 u8 i16 u16 i32 u32 i64 u64 usize);

#[test]
fn usize_dtype() {
    let a: Vec<usize> = vec![1, 2, 3];

    pyo3::Python::with_gil(|py| {
        let x = a.into_pyarray(py);

        if cfg!(target_pointer_width = "64") {
            pyo3::py_run!(py, x, "assert str(x.dtype) == 'uint64'")
        } else {
            pyo3::py_run!(py, x, "assert str(x.dtype) == 'uint32'")
        };
    })
}

#[test]
fn into_pyarray_vec() {
    let a = vec![1, 2, 3];
    pyo3::Python::with_gil(|py| {
        let arr = a.into_pyarray(py).readonly();
        assert_eq!(arr.as_slice().unwrap(), &[1, 2, 3])
    })
}

#[test]
fn into_pyarray_array() {
    let arr = Array3::<f64>::zeros((3, 4, 2));
    let shape = arr.shape().to_vec();
    let strides = arr.strides().iter().map(|d| d * 8).collect::<Vec<_>>();
    pyo3::Python::with_gil(|py| {
        let py_arr = arr.into_pyarray(py);
        assert_eq!(py_arr.shape(), shape.as_slice());
        assert_eq!(py_arr.strides(), strides.as_slice());
    })
}

#[test]
fn into_pyarray_cant_resize() {
    let a = vec![1, 2, 3];
    pyo3::Python::with_gil(|py| {
        let arr = a.into_pyarray(py);
        assert!(arr.resize(100).is_err())
    })
}

/// Check that into_pyarray works for ndarray of which the pointer of the first element is
/// not at the start. See https://github.com/PyO3/rust-numpy/issues/182 for more
#[test]
fn into_pyarray_collapsed() {
    let mut arr = Array2::<f64>::from_shape_fn([3, 4], |(i, j)| (i * 10 + j) as f64);
    arr.slice_collapse(s![1.., ..]);
    let copy = arr.clone();
    pyo3::Python::with_gil(|py| {
        let py_arr = arr.into_pyarray(py);
        assert_eq!(py_arr.readonly().as_array(), copy);
    })
}

#[test]
fn forder_to_pyarray() {
    pyo3::Python::with_gil(|py| {
        let matrix = Array2::from_shape_vec([4, 2], vec![0, 1, 2, 3, 4, 5, 6, 7]).unwrap();
        let fortran_matrix = matrix.reversed_axes();
        let fmat_py = fortran_matrix.to_pyarray(py);
        assert_eq!(
            fmat_py.readonly().as_array(),
            array![[0, 2, 4, 6], [1, 3, 5, 7]],
        );
        pyo3::py_run!(py, fmat_py, "assert fmat_py.flags['F_CONTIGUOUS']")
    })
}

#[test]
fn slice_to_pyarray() {
    pyo3::Python::with_gil(|py| {
        let matrix = Array2::from_shape_vec([4, 2], vec![0, 1, 2, 3, 4, 5, 6, 7]).unwrap();
        let slice = matrix.slice(s![1..4; -1, ..]);
        let slice_py = slice.to_pyarray(py);
        assert_eq!(
            slice_py.readonly().as_array(),
            array![[6, 7], [4, 5], [2, 3]],
        );
        pyo3::py_run!(py, slice_py, "assert slice_py.flags['C_CONTIGUOUS']")
    })
}

#[test]
fn forder_into_pyarray() {
    pyo3::Python::with_gil(|py| {
        let matrix = Array2::from_shape_vec([4, 2], vec![0, 1, 2, 3, 4, 5, 6, 7]).unwrap();
        let fortran_matrix = matrix.reversed_axes();
        let fmat_py = fortran_matrix.into_pyarray(py);
        assert_eq!(
            fmat_py.readonly().as_array(),
            array![[0, 2, 4, 6], [1, 3, 5, 7]],
        );
        pyo3::py_run!(py, fmat_py, "assert fmat_py.flags['F_CONTIGUOUS']")
    })
}

#[test]
fn to_pyarray_object_vec() {
    use pyo3::{
        types::{PyDict, PyString},
        ToPyObject,
    };
    use std::cmp::Ordering;

    pyo3::Python::with_gil(|py| {
        let dict = PyDict::new(py);
        let string = PyString::new(py, "Hello:)");
        let vec = vec![dict.to_object(py), string.to_object(py)];
        let arr = vec.to_pyarray(py).readonly();

        for (a, b) in vec.iter().zip(arr.as_slice().unwrap().iter()) {
            assert_eq!(
                a.as_ref(py).compare(b).map_err(|e| e.print(py)).unwrap(),
                Ordering::Equal
            );
        }
    })
}

#[test]
fn to_pyarray_object_array() {
    use ndarray::Array2;
    use pyo3::{
        types::{PyDict, PyString},
        ToPyObject,
    };
    use std::cmp::Ordering;

    pyo3::Python::with_gil(|py| {
        let mut nd_arr = Array2::from_shape_fn((2, 3), |(_, _)| py.None());
        nd_arr[(0, 2)] = PyDict::new(py).to_object(py);
        nd_arr[(1, 0)] = PyString::new(py, "Hello:)").to_object(py);

        let py_arr = nd_arr.to_pyarray(py).readonly();

        for (a, b) in nd_arr
            .as_slice()
            .unwrap()
            .iter()
            .zip(py_arr.as_slice().unwrap().iter())
        {
            assert_eq!(
                a.as_ref(py).compare(b).map_err(|e| e.print(py)).unwrap(),
                Ordering::Equal
            );
        }
    })
}
<|endoftext|>


<commit_before>use crate::gen::out::{Content, OutFile};
use crate::syntax::{self, IncludeKind};
use std::ops::{Deref, DerefMut};

/// The complete contents of the "rust/cxx.h" header.
pub static HEADER: &str = include_str!("include/cxx.h");

/// A header to #include.
///
/// The cxxbridge tool does not parse or even require the given paths to exist;
/// they simply go into the generated C++ code as #include lines.
#[derive(Clone, PartialEq, Debug)]
pub struct Include {
    /// The header's path, not including the enclosing quotation marks or angle
    /// brackets.
    pub path: String,
    /// Whether to emit `#include "path"` or `#include <path>`.
    pub kind: IncludeKind,
}

#[derive(Default, PartialEq)]
pub struct Includes<'a> {
    pub custom: Vec<Include>,
    pub array: bool,
    pub cstddef: bool,
    pub cstdint: bool,
    pub cstring: bool,
    pub exception: bool,
    pub iterator: bool,
    pub memory: bool,
    pub new: bool,
    pub string: bool,
    pub type_traits: bool,
    pub utility: bool,
    pub vector: bool,
    pub basetsd: bool,
    pub content: Content<'a>,
}

impl<'a> Includes<'a> {
    pub fn new() -> Self {
        Includes::default()
    }

    pub fn insert(&mut self, include: impl Into<Include>) {
        self.custom.push(include.into());
    }
}

pub(super) fn write(out: &mut OutFile) {
    let header = out.header;
    let include = &mut out.include;
    let out = &mut include.content;

    if header {
        writeln!(out, "#pragma once");
    }

    for include in &include.custom {
        match include.kind {
            IncludeKind::Quoted => {
                writeln!(out, "#include \"{}\"", include.path.escape_default());
            }
            IncludeKind::Bracketed => {
                writeln!(out, "#include <{}>", include.path);
            }
        }
    }

    if include.array {
        writeln!(out, "#include <array>");
    }
    if include.cstddef {
        writeln!(out, "#include <cstddef>");
    }
    if include.cstdint {
        writeln!(out, "#include <cstdint>");
    }
    if include.cstring {
        writeln!(out, "#include <cstring>");
    }
    if include.exception {
        writeln!(out, "#include <exception>");
    }
    if include.iterator {
        writeln!(out, "#include <iterator>");
    }
    if include.memory {
        writeln!(out, "#include <memory>");
    }
    if include.new {
        writeln!(out, "#include <new>");
    }
    if include.string {
        writeln!(out, "#include <string>");
    }
    if include.type_traits {
        writeln!(out, "#include <type_traits>");
    }
    if include.utility {
        writeln!(out, "#include <utility>");
    }
    if include.vector {
        writeln!(out, "#include <vector>");
    }
    if include.basetsd {
        writeln!(out, "#if defined(_WIN32)");
        writeln!(out, "#include <basetsd.h>");
        writeln!(out, "#endif");
    }
}

impl<'i, 'a> Extend<&'i Include> for Includes<'a> {
    fn extend<I: IntoIterator<Item = &'i Include>>(&mut self, iter: I) {
        self.custom.extend(iter.into_iter().cloned());
    }
}

impl<'i> From<&'i syntax::Include> for Include {
    fn from(include: &syntax::Include) -> Self {
        Include {
            path: include.path.clone(),
            kind: include.kind,
        }
    }
}

impl<'a> Deref for Includes<'a> {
    type Target = Content<'a>;

    fn deref(&self) -> &Self::Target {
        &self.content
    }
}

impl<'a> DerefMut for Includes<'a> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.content
    }
}
<commit_msg>Exhaustive match to ensure no missing prints for includes<commit_after>use crate::gen::out::{Content, OutFile};
use crate::syntax::{self, IncludeKind};
use std::ops::{Deref, DerefMut};

/// The complete contents of the "rust/cxx.h" header.
pub static HEADER: &str = include_str!("include/cxx.h");

/// A header to #include.
///
/// The cxxbridge tool does not parse or even require the given paths to exist;
/// they simply go into the generated C++ code as #include lines.
#[derive(Clone, PartialEq, Debug)]
pub struct Include {
    /// The header's path, not including the enclosing quotation marks or angle
    /// brackets.
    pub path: String,
    /// Whether to emit `#include "path"` or `#include <path>`.
    pub kind: IncludeKind,
}

#[derive(Default, PartialEq)]
pub struct Includes<'a> {
    pub custom: Vec<Include>,
    pub array: bool,
    pub cstddef: bool,
    pub cstdint: bool,
    pub cstring: bool,
    pub exception: bool,
    pub iterator: bool,
    pub memory: bool,
    pub new: bool,
    pub string: bool,
    pub type_traits: bool,
    pub utility: bool,
    pub vector: bool,
    pub basetsd: bool,
    pub content: Content<'a>,
}

impl<'a> Includes<'a> {
    pub fn new() -> Self {
        Includes::default()
    }

    pub fn insert(&mut self, include: impl Into<Include>) {
        self.custom.push(include.into());
    }
}

pub(super) fn write(out: &mut OutFile) {
    let header = out.header;
    let include = &mut out.include;
    let out = &mut include.content;

    if header {
        writeln!(out, "#pragma once");
    }

    for include in &include.custom {
        match include.kind {
            IncludeKind::Quoted => {
                writeln!(out, "#include \"{}\"", include.path.escape_default());
            }
            IncludeKind::Bracketed => {
                writeln!(out, "#include <{}>", include.path);
            }
        }
    }

    let Includes {
        custom: _,
        array,
        cstddef,
        cstdint,
        cstring,
        exception,
        iterator,
        memory,
        new,
        string,
        type_traits,
        utility,
        vector,
        basetsd,
        content: _,
    } = *include;

    if array {
        writeln!(out, "#include <array>");
    }
    if cstddef {
        writeln!(out, "#include <cstddef>");
    }
    if cstdint {
        writeln!(out, "#include <cstdint>");
    }
    if cstring {
        writeln!(out, "#include <cstring>");
    }
    if exception {
        writeln!(out, "#include <exception>");
    }
    if iterator {
        writeln!(out, "#include <iterator>");
    }
    if memory {
        writeln!(out, "#include <memory>");
    }
    if new {
        writeln!(out, "#include <new>");
    }
    if string {
        writeln!(out, "#include <string>");
    }
    if type_traits {
        writeln!(out, "#include <type_traits>");
    }
    if utility {
        writeln!(out, "#include <utility>");
    }
    if vector {
        writeln!(out, "#include <vector>");
    }
    if basetsd {
        writeln!(out, "#if defined(_WIN32)");
        writeln!(out, "#include <basetsd.h>");
        writeln!(out, "#endif");
    }
}

impl<'i, 'a> Extend<&'i Include> for Includes<'a> {
    fn extend<I: IntoIterator<Item = &'i Include>>(&mut self, iter: I) {
        self.custom.extend(iter.into_iter().cloned());
    }
}

impl<'i> From<&'i syntax::Include> for Include {
    fn from(include: &syntax::Include) -> Self {
        Include {
            path: include.path.clone(),
            kind: include.kind,
        }
    }
}

impl<'a> Deref for Includes<'a> {
    type Target = Content<'a>;

    fn deref(&self) -> &Self::Target {
        &self.content
    }
}

impl<'a> DerefMut for Includes<'a> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.content
    }
}
<|endoftext|>


<commit_before>use std::error;
use std::io;
use std::fmt;

use Connection;

#[doc(inline)]
pub use postgres_shared::error::*;

#[derive(Debug)]
pub enum Error {
    Io(io::Error),
    Db(Box<DbError>, Connection),
    Conversion(Box<error::Error + Sync + Send>, Connection),
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.write_str(error::Error::description(self))?;
        match *self {
            Error::Db(ref err, _) => write!(fmt, ": {}", err),
            Error::Io(ref err) => write!(fmt, ": {}", err),
            Error::Conversion(ref err, _) => write!(fmt, ": {}", err),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Db(_, _) => "Error reported by Postgres",
            Error::Io(_) => "Error communicating with the server",
            Error::Conversion(_, _) => "Error converting between Postgres and Rust types",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Db(ref err, _) => Some(&**err),
            Error::Io(ref err) => Some(err),
            Error::Conversion(ref err, _) => Some(&**err),
        }
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}
<commit_msg>Use try not ?<commit_after>use std::error;
use std::io;
use std::fmt;

use Connection;

#[doc(inline)]
pub use postgres_shared::error::*;

#[derive(Debug)]
pub enum Error {
    Io(io::Error),
    Db(Box<DbError>, Connection),
    Conversion(Box<error::Error + Sync + Send>, Connection),
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!(fmt.write_str(error::Error::description(self)));
        match *self {
            Error::Db(ref err, _) => write!(fmt, ": {}", err),
            Error::Io(ref err) => write!(fmt, ": {}", err),
            Error::Conversion(ref err, _) => write!(fmt, ": {}", err),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Db(_, _) => "Error reported by Postgres",
            Error::Io(_) => "Error communicating with the server",
            Error::Conversion(_, _) => "Error converting between Postgres and Rust types",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Db(ref err, _) => Some(&**err),
            Error::Io(ref err) => Some(err),
            Error::Conversion(ref err, _) => Some(&**err),
        }
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}
<|endoftext|>