<commit_before>use std::{
    cell::{Ref, RefCell},
    rc::Rc,
};

use glium::{
    self,
    index::PrimitiveType,
    texture::{MipmapsOption, Texture2d, UncompressedFloatFormat},
    Frame, GlObject, Surface,
};
use slog::Logger;

#[cfg(feature = "egl")]
use smithay::backend::egl::display::EGLBufferReader;
use smithay::{
    backend::{
        egl::{BufferAccessError, EGLImages, Format},
        graphics::{gl::GLGraphicsBackend, glium::GliumGraphicsBackend},
    },
    reexports::wayland_server::protocol::{wl_buffer, wl_surface},
    wayland::{
        compositor::{roles::Role, SubsurfaceRole, TraversalAction},
        data_device::DnDIconRole,
        seat::CursorImageRole,
        shm::with_buffer_contents as shm_buffer_contents,
    },
};

use crate::shaders;
use crate::shell::{MyCompositorToken, MyWindowMap, SurfaceData};

#[derive(Copy, Clone)]
struct Vertex {
    position: [f32; 2],
    tex_coords: [f32; 2],
}

implement_vertex!(Vertex, position, tex_coords);

pub struct GliumDrawer<F: GLGraphicsBackend + 'static> {
    display: GliumGraphicsBackend<F>,
    vertex_buffer: glium::VertexBuffer<Vertex>,
    index_buffer: glium::IndexBuffer<u16>,
    programs: [glium::Program; shaders::FRAGMENT_COUNT],
    #[cfg(feature = "egl")]
    egl_buffer_reader: Rc<RefCell<Option<EGLBufferReader>>>,
    log: Logger,
}

impl<F: GLGraphicsBackend + 'static> GliumDrawer<F> {
    pub fn borrow(&self) -> Ref<'_, F> {
        self.display.borrow()
    }
}

impl<T: Into<GliumGraphicsBackend<T>> + GLGraphicsBackend + 'static> GliumDrawer<T> {
    #[cfg(feature = "egl")]
    pub fn init(
        backend: T,
        egl_buffer_reader: Rc<RefCell<Option<EGLBufferReader>>>,
        log: Logger,
    ) -> GliumDrawer<T> {
        let display = backend.into();

        // building the vertex buffer, which contains all the vertices that we will draw
        let vertex_buffer = glium::VertexBuffer::new(
            &display,
            &[
                Vertex {
                    position: [0.0, 0.0],
                    tex_coords: [0.0, 0.0],
                },
                Vertex {
                    position: [0.0, 1.0],
                    tex_coords: [0.0, 1.0],
                },
                Vertex {
                    position: [1.0, 1.0],
                    tex_coords: [1.0, 1.0],
                },
                Vertex {
                    position: [1.0, 0.0],
                    tex_coords: [1.0, 0.0],
                },
            ],
        )
        .unwrap();

        // building the index buffer
        let index_buffer =
            glium::IndexBuffer::new(&display, PrimitiveType::TriangleStrip, &[1 as u16, 2, 0, 3]).unwrap();

        let programs = opengl_programs!(&display);

        GliumDrawer {
            display,
            vertex_buffer,
            index_buffer,
            programs,
            egl_buffer_reader,
            log,
        }
    }

    #[cfg(not(feature = "egl"))]
    pub fn init(backend: T, log: Logger) -> GliumDrawer<T> {
        let display = backend.into();

        // building the vertex buffer, which contains all the vertices that we will draw
        let vertex_buffer = glium::VertexBuffer::new(
            &display,
            &[
                Vertex {
                    position: [0.0, 0.0],
                    tex_coords: [0.0, 0.0],
                },
                Vertex {
                    position: [0.0, 1.0],
                    tex_coords: [0.0, 1.0],
                },
                Vertex {
                    position: [1.0, 1.0],
                    tex_coords: [1.0, 1.0],
                },
                Vertex {
                    position: [1.0, 0.0],
                    tex_coords: [1.0, 0.0],
                },
            ],
        )
        .unwrap();

        // building the index buffer
        let index_buffer =
            glium::IndexBuffer::new(&display, PrimitiveType::TriangleStrip, &[1 as u16, 2, 0, 3]).unwrap();

        let programs = opengl_programs!(&display);

        GliumDrawer {
            display,
            vertex_buffer,
            index_buffer,
            programs,
            log,
        }
    }
}

impl<F: GLGraphicsBackend + 'static> GliumDrawer<F> {
    #[cfg(feature = "egl")]
    pub fn texture_from_buffer(&self, buffer: wl_buffer::WlBuffer) -> Result<TextureMetadata, ()> {
        // try to retrieve the egl contents of this buffer
        let images = if let Some(display) = &self.egl_buffer_reader.borrow().as_ref() {
            display.egl_buffer_contents(buffer)
        } else {
            Err(BufferAccessError::NotManaged(buffer))
        };
        match images {
            Ok(images) => {
                // we have an EGL buffer
                let format = match images.format {
                    Format::RGB => UncompressedFloatFormat::U8U8U8,
                    Format::RGBA => UncompressedFloatFormat::U8U8U8U8,
                    _ => {
                        warn!(self.log, "Unsupported EGL buffer format"; "format" => format!("{:?}", images.format));
                        return Err(());
                    }
                };
                let opengl_texture = Texture2d::empty_with_format(
                    &self.display,
                    format,
                    MipmapsOption::NoMipmap,
                    images.width,
                    images.height,
                )
                .unwrap();
                unsafe {
                    images
                        .bind_to_texture(0, opengl_texture.get_id(), &*self.display.borrow())
                        .expect("Failed to bind to texture");
                }
                Ok(TextureMetadata {
                    texture: opengl_texture,
                    fragment: crate::shaders::BUFFER_RGBA,
                    y_inverted: images.y_inverted,
                    dimensions: (images.width, images.height),
                    images: Some(images), // I guess we need to keep this alive ?
                })
            }
            Err(BufferAccessError::NotManaged(buffer)) => {
                // this is not an EGL buffer, try SHM
                self.texture_from_shm_buffer(buffer)
            }
            Err(err) => {
                error!(self.log, "EGL error"; "err" => format!("{:?}", err));
                Err(())
            }
        }
    }

    #[cfg(not(feature = "egl"))]
    pub fn texture_from_buffer(&self, buffer: wl_buffer::WlBuffer) -> Result<TextureMetadata, ()> {
        self.texture_from_shm_buffer(buffer)
    }

    fn texture_from_shm_buffer(&self, buffer: wl_buffer::WlBuffer) -> Result<TextureMetadata, ()> {
        match shm_buffer_contents(&buffer, |slice, data| {
            crate::shm_load::load_shm_buffer(data, slice)
                .map(|(image, kind)| (Texture2d::new(&self.display, image).unwrap(), kind, data))
        }) {
            Ok(Ok((texture, kind, data))) => Ok(TextureMetadata {
                texture,
                fragment: kind,
                y_inverted: false,
                dimensions: (data.width as u32, data.height as u32),
                #[cfg(feature = "egl")]
                images: None,
            }),
            Ok(Err(format)) => {
                warn!(self.log, "Unsupported SHM buffer format"; "format" => format!("{:?}", format));
                Err(())
            }
            Err(err) => {
                warn!(self.log, "Unable to load buffer contents"; "err" => format!("{:?}", err));
                Err(())
            }
        }
    }

    pub fn render_texture(
        &self,
        target: &mut glium::Frame,
        texture: &Texture2d,
        texture_kind: usize,
        y_inverted: bool,
        surface_dimensions: (u32, u32),
        surface_location: (i32, i32),
        screen_size: (u32, u32),
        blending: glium::Blend,
    ) {
        let xscale = 2.0 * (surface_dimensions.0 as f32) / (screen_size.0 as f32);
        let mut yscale = -2.0 * (surface_dimensions.1 as f32) / (screen_size.1 as f32);

        let x = 2.0 * (surface_location.0 as f32) / (screen_size.0 as f32) - 1.0;
        let mut y = 1.0 - 2.0 * (surface_location.1 as f32) / (screen_size.1 as f32);

        if y_inverted {
            yscale = -yscale;
            y -= surface_dimensions.1 as f32;
        }

        let uniforms = uniform! {
            matrix: [
                [xscale,   0.0  , 0.0, 0.0],
                [  0.0 , yscale , 0.0, 0.0],
                [  0.0 ,   0.0  , 1.0, 0.0],
                [   x  ,    y   , 0.0, 1.0]
            ],
            tex: texture,
        };

        target
            .draw(
                &self.vertex_buffer,
                &self.index_buffer,
                &self.programs[texture_kind],
                &uniforms,
                &glium::DrawParameters {
                    blend: blending,
                    ..Default::default()
                },
            )
            .unwrap();
    }

    #[inline]
    pub fn draw(&self) -> Frame {
        self.display.draw()
    }
}

pub struct TextureMetadata {
    pub texture: Texture2d,
    pub fragment: usize,
    pub y_inverted: bool,
    pub dimensions: (u32, u32),
    #[cfg(feature = "egl")]
    images: Option<EGLImages>,
}

impl<F: GLGraphicsBackend + 'static> GliumDrawer<F> {
    fn draw_surface_tree(
        &self,
        frame: &mut Frame,
        root: &wl_surface::WlSurface,
        location: (i32, i32),
        compositor_token: MyCompositorToken,
        screen_dimensions: (u32, u32),
    ) {
        compositor_token.with_surface_tree_upward(
            root,
            location,
            |_surface, attributes, role, &(mut x, mut y)| {
                // Pull a new buffer if available
                if let Some(data) = attributes.user_data.get::<RefCell<SurfaceData>>() {
                    let mut data = data.borrow_mut();
                    if data.texture.is_none() {
                        if let Some(buffer) = data.buffer.take() {
                            if let Ok(m) = self.texture_from_buffer(buffer.clone()) {
                                // release the buffer if it was an SHM buffer
                                #[cfg(feature = "egl")]
                                {
                                    if m.images.is_none() {
                                        buffer.release();
                                    }
                                }
                                #[cfg(not(feature = "egl"))]
                                {
                                    buffer.release();
                                }

                                data.texture = Some(m);
                            } else {
                                // there was an error reading the buffer, release it, we
                                // already logged the error
                                buffer.release();
                            }
                        }
                    }
                    // Now, should we be drawn ?
                    if data.texture.is_some() {
                        // if yes, also process the children
                        if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
                            x += subdata.location.0;
                            y += subdata.location.1;
                        }
                        TraversalAction::DoChildren((x, y))
                    } else {
                        // we are not displayed, so our children are neither
                        TraversalAction::SkipChildren
                    }
                } else {
                    // we are not displayed, so our children are neither
                    TraversalAction::SkipChildren
                }
            },
            |_surface, attributes, role, &(mut x, mut y)| {
                if let Some(ref data) = attributes.user_data.get::<RefCell<SurfaceData>>() {
                    if let Some(ref metadata) = data.borrow().texture {
                        // we need to re-extract the subsurface offset, as the previous closure
                        // only passes it to our children
                        if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
                            x += subdata.location.0;
                            y += subdata.location.1;
                        }
                        self.render_texture(
                            frame,
                            &metadata.texture,
                            metadata.fragment,
                            metadata.y_inverted,
                            metadata.dimensions,
                            (x, y),
                            screen_dimensions,
                            ::glium::Blend {
                                color: ::glium::BlendingFunction::Addition {
                                    source: ::glium::LinearBlendingFactor::One,
                                    destination: ::glium::LinearBlendingFactor::OneMinusSourceAlpha,
                                },
                                alpha: ::glium::BlendingFunction::Addition {
                                    source: ::glium::LinearBlendingFactor::One,
                                    destination: ::glium::LinearBlendingFactor::OneMinusSourceAlpha,
                                },
                                ..Default::default()
                            },
                        );
                    }
                }
            },
            |_, _, _, _| true,
        );
    }

    pub fn draw_windows(
        &self,
        frame: &mut Frame,
        window_map: &MyWindowMap,
        compositor_token: MyCompositorToken,
    ) {
        // redraw the frame, in a simple but inneficient way
        {
            let screen_dimensions = self.borrow().get_framebuffer_dimensions();
            window_map.with_windows_from_bottom_to_top(|toplevel_surface, initial_place| {
                if let Some(wl_surface) = toplevel_surface.get_surface() {
                    // this surface is a root of a subsurface tree that needs to be drawn
                    self.draw_surface_tree(
                        frame,
                        &wl_surface,
                        initial_place,
                        compositor_token,
                        screen_dimensions,
                    );
                }
            });
        }
    }

    pub fn draw_cursor(
        &self,
        frame: &mut Frame,
        surface: &wl_surface::WlSurface,
        (x, y): (i32, i32),
        token: MyCompositorToken,
    ) {
        let (dx, dy) = match token.with_role_data::<CursorImageRole, _, _>(surface, |data| data.hotspot) {
            Ok(h) => h,
            Err(_) => {
                warn!(
                    self.log,
                    "Trying to display as a cursor a surface that does not have the CursorImage role."
                );
                (0, 0)
            }
        };
        let screen_dimensions = self.borrow().get_framebuffer_dimensions();
        self.draw_surface_tree(frame, surface, (x - dx, y - dy), token, screen_dimensions);
    }

    pub fn draw_dnd_icon(
        &self,
        frame: &mut Frame,
        surface: &wl_surface::WlSurface,
        (x, y): (i32, i32),
        token: MyCompositorToken,
    ) {
        if !token.has_role::<DnDIconRole>(surface) {
            warn!(
                self.log,
                "Trying to display as a dnd icon a surface that does not have the DndIcon role."
            );
        }
        let screen_dimensions = self.borrow().get_framebuffer_dimensions();
        self.draw_surface_tree(frame, surface, (x, y), token, screen_dimensions);
    }
}
<commit_msg>anvil: disable clippy lint for glium macros<commit_after>use std::{
    cell::{Ref, RefCell},
    rc::Rc,
};

use glium::{
    self,
    index::PrimitiveType,
    texture::{MipmapsOption, Texture2d, UncompressedFloatFormat},
    Frame, GlObject, Surface,
};
use slog::Logger;

#[cfg(feature = "egl")]
use smithay::backend::egl::display::EGLBufferReader;
use smithay::{
    backend::{
        egl::{BufferAccessError, EGLImages, Format},
        graphics::{gl::GLGraphicsBackend, glium::GliumGraphicsBackend},
    },
    reexports::wayland_server::protocol::{wl_buffer, wl_surface},
    wayland::{
        compositor::{roles::Role, SubsurfaceRole, TraversalAction},
        data_device::DnDIconRole,
        seat::CursorImageRole,
        shm::with_buffer_contents as shm_buffer_contents,
    },
};

use crate::shaders;
use crate::shell::{MyCompositorToken, MyWindowMap, SurfaceData};

#[derive(Copy, Clone)]
struct Vertex {
    position: [f32; 2],
    tex_coords: [f32; 2],
}

mod implement_vertex {
    #![allow(clippy::unneeded_field_pattern)]
    // Module to scope the clippy lint disabling
    use super::Vertex;
    implement_vertex!(Vertex, position, tex_coords);
}

pub struct GliumDrawer<F: GLGraphicsBackend + 'static> {
    display: GliumGraphicsBackend<F>,
    vertex_buffer: glium::VertexBuffer<Vertex>,
    index_buffer: glium::IndexBuffer<u16>,
    programs: [glium::Program; shaders::FRAGMENT_COUNT],
    #[cfg(feature = "egl")]
    egl_buffer_reader: Rc<RefCell<Option<EGLBufferReader>>>,
    log: Logger,
}

impl<F: GLGraphicsBackend + 'static> GliumDrawer<F> {
    pub fn borrow(&self) -> Ref<'_, F> {
        self.display.borrow()
    }
}

impl<T: Into<GliumGraphicsBackend<T>> + GLGraphicsBackend + 'static> GliumDrawer<T> {
    #[cfg(feature = "egl")]
    pub fn init(
        backend: T,
        egl_buffer_reader: Rc<RefCell<Option<EGLBufferReader>>>,
        log: Logger,
    ) -> GliumDrawer<T> {
        let display = backend.into();

        // building the vertex buffer, which contains all the vertices that we will draw
        let vertex_buffer = glium::VertexBuffer::new(
            &display,
            &[
                Vertex {
                    position: [0.0, 0.0],
                    tex_coords: [0.0, 0.0],
                },
                Vertex {
                    position: [0.0, 1.0],
                    tex_coords: [0.0, 1.0],
                },
                Vertex {
                    position: [1.0, 1.0],
                    tex_coords: [1.0, 1.0],
                },
                Vertex {
                    position: [1.0, 0.0],
                    tex_coords: [1.0, 0.0],
                },
            ],
        )
        .unwrap();

        // building the index buffer
        let index_buffer =
            glium::IndexBuffer::new(&display, PrimitiveType::TriangleStrip, &[1 as u16, 2, 0, 3]).unwrap();

        let programs = opengl_programs!(&display);

        GliumDrawer {
            display,
            vertex_buffer,
            index_buffer,
            programs,
            egl_buffer_reader,
            log,
        }
    }

    #[cfg(not(feature = "egl"))]
    pub fn init(backend: T, log: Logger) -> GliumDrawer<T> {
        let display = backend.into();

        // building the vertex buffer, which contains all the vertices that we will draw
        let vertex_buffer = glium::VertexBuffer::new(
            &display,
            &[
                Vertex {
                    position: [0.0, 0.0],
                    tex_coords: [0.0, 0.0],
                },
                Vertex {
                    position: [0.0, 1.0],
                    tex_coords: [0.0, 1.0],
                },
                Vertex {
                    position: [1.0, 1.0],
                    tex_coords: [1.0, 1.0],
                },
                Vertex {
                    position: [1.0, 0.0],
                    tex_coords: [1.0, 0.0],
                },
            ],
        )
        .unwrap();

        // building the index buffer
        let index_buffer =
            glium::IndexBuffer::new(&display, PrimitiveType::TriangleStrip, &[1 as u16, 2, 0, 3]).unwrap();

        let programs = opengl_programs!(&display);

        GliumDrawer {
            display,
            vertex_buffer,
            index_buffer,
            programs,
            log,
        }
    }
}

impl<F: GLGraphicsBackend + 'static> GliumDrawer<F> {
    #[cfg(feature = "egl")]
    pub fn texture_from_buffer(&self, buffer: wl_buffer::WlBuffer) -> Result<TextureMetadata, ()> {
        // try to retrieve the egl contents of this buffer
        let images = if let Some(display) = &self.egl_buffer_reader.borrow().as_ref() {
            display.egl_buffer_contents(buffer)
        } else {
            Err(BufferAccessError::NotManaged(buffer))
        };
        match images {
            Ok(images) => {
                // we have an EGL buffer
                let format = match images.format {
                    Format::RGB => UncompressedFloatFormat::U8U8U8,
                    Format::RGBA => UncompressedFloatFormat::U8U8U8U8,
                    _ => {
                        warn!(self.log, "Unsupported EGL buffer format"; "format" => format!("{:?}", images.format));
                        return Err(());
                    }
                };
                let opengl_texture = Texture2d::empty_with_format(
                    &self.display,
                    format,
                    MipmapsOption::NoMipmap,
                    images.width,
                    images.height,
                )
                .unwrap();
                unsafe {
                    images
                        .bind_to_texture(0, opengl_texture.get_id(), &*self.display.borrow())
                        .expect("Failed to bind to texture");
                }
                Ok(TextureMetadata {
                    texture: opengl_texture,
                    fragment: crate::shaders::BUFFER_RGBA,
                    y_inverted: images.y_inverted,
                    dimensions: (images.width, images.height),
                    images: Some(images), // I guess we need to keep this alive ?
                })
            }
            Err(BufferAccessError::NotManaged(buffer)) => {
                // this is not an EGL buffer, try SHM
                self.texture_from_shm_buffer(buffer)
            }
            Err(err) => {
                error!(self.log, "EGL error"; "err" => format!("{:?}", err));
                Err(())
            }
        }
    }

    #[cfg(not(feature = "egl"))]
    pub fn texture_from_buffer(&self, buffer: wl_buffer::WlBuffer) -> Result<TextureMetadata, ()> {
        self.texture_from_shm_buffer(buffer)
    }

    fn texture_from_shm_buffer(&self, buffer: wl_buffer::WlBuffer) -> Result<TextureMetadata, ()> {
        match shm_buffer_contents(&buffer, |slice, data| {
            crate::shm_load::load_shm_buffer(data, slice)
                .map(|(image, kind)| (Texture2d::new(&self.display, image).unwrap(), kind, data))
        }) {
            Ok(Ok((texture, kind, data))) => Ok(TextureMetadata {
                texture,
                fragment: kind,
                y_inverted: false,
                dimensions: (data.width as u32, data.height as u32),
                #[cfg(feature = "egl")]
                images: None,
            }),
            Ok(Err(format)) => {
                warn!(self.log, "Unsupported SHM buffer format"; "format" => format!("{:?}", format));
                Err(())
            }
            Err(err) => {
                warn!(self.log, "Unable to load buffer contents"; "err" => format!("{:?}", err));
                Err(())
            }
        }
    }

    pub fn render_texture(
        &self,
        target: &mut glium::Frame,
        texture: &Texture2d,
        texture_kind: usize,
        y_inverted: bool,
        surface_dimensions: (u32, u32),
        surface_location: (i32, i32),
        screen_size: (u32, u32),
        blending: glium::Blend,
    ) {
        let xscale = 2.0 * (surface_dimensions.0 as f32) / (screen_size.0 as f32);
        let mut yscale = -2.0 * (surface_dimensions.1 as f32) / (screen_size.1 as f32);

        let x = 2.0 * (surface_location.0 as f32) / (screen_size.0 as f32) - 1.0;
        let mut y = 1.0 - 2.0 * (surface_location.1 as f32) / (screen_size.1 as f32);

        if y_inverted {
            yscale = -yscale;
            y -= surface_dimensions.1 as f32;
        }

        let uniforms = uniform! {
            matrix: [
                [xscale,   0.0  , 0.0, 0.0],
                [  0.0 , yscale , 0.0, 0.0],
                [  0.0 ,   0.0  , 1.0, 0.0],
                [   x  ,    y   , 0.0, 1.0]
            ],
            tex: texture,
        };

        target
            .draw(
                &self.vertex_buffer,
                &self.index_buffer,
                &self.programs[texture_kind],
                &uniforms,
                &glium::DrawParameters {
                    blend: blending,
                    ..Default::default()
                },
            )
            .unwrap();
    }

    #[inline]
    pub fn draw(&self) -> Frame {
        self.display.draw()
    }
}

pub struct TextureMetadata {
    pub texture: Texture2d,
    pub fragment: usize,
    pub y_inverted: bool,
    pub dimensions: (u32, u32),
    #[cfg(feature = "egl")]
    images: Option<EGLImages>,
}

impl<F: GLGraphicsBackend + 'static> GliumDrawer<F> {
    fn draw_surface_tree(
        &self,
        frame: &mut Frame,
        root: &wl_surface::WlSurface,
        location: (i32, i32),
        compositor_token: MyCompositorToken,
        screen_dimensions: (u32, u32),
    ) {
        compositor_token.with_surface_tree_upward(
            root,
            location,
            |_surface, attributes, role, &(mut x, mut y)| {
                // Pull a new buffer if available
                if let Some(data) = attributes.user_data.get::<RefCell<SurfaceData>>() {
                    let mut data = data.borrow_mut();
                    if data.texture.is_none() {
                        if let Some(buffer) = data.buffer.take() {
                            if let Ok(m) = self.texture_from_buffer(buffer.clone()) {
                                // release the buffer if it was an SHM buffer
                                #[cfg(feature = "egl")]
                                {
                                    if m.images.is_none() {
                                        buffer.release();
                                    }
                                }
                                #[cfg(not(feature = "egl"))]
                                {
                                    buffer.release();
                                }

                                data.texture = Some(m);
                            } else {
                                // there was an error reading the buffer, release it, we
                                // already logged the error
                                buffer.release();
                            }
                        }
                    }
                    // Now, should we be drawn ?
                    if data.texture.is_some() {
                        // if yes, also process the children
                        if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
                            x += subdata.location.0;
                            y += subdata.location.1;
                        }
                        TraversalAction::DoChildren((x, y))
                    } else {
                        // we are not displayed, so our children are neither
                        TraversalAction::SkipChildren
                    }
                } else {
                    // we are not displayed, so our children are neither
                    TraversalAction::SkipChildren
                }
            },
            |_surface, attributes, role, &(mut x, mut y)| {
                if let Some(ref data) = attributes.user_data.get::<RefCell<SurfaceData>>() {
                    if let Some(ref metadata) = data.borrow().texture {
                        // we need to re-extract the subsurface offset, as the previous closure
                        // only passes it to our children
                        if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
                            x += subdata.location.0;
                            y += subdata.location.1;
                        }
                        self.render_texture(
                            frame,
                            &metadata.texture,
                            metadata.fragment,
                            metadata.y_inverted,
                            metadata.dimensions,
                            (x, y),
                            screen_dimensions,
                            ::glium::Blend {
                                color: ::glium::BlendingFunction::Addition {
                                    source: ::glium::LinearBlendingFactor::One,
                                    destination: ::glium::LinearBlendingFactor::OneMinusSourceAlpha,
                                },
                                alpha: ::glium::BlendingFunction::Addition {
                                    source: ::glium::LinearBlendingFactor::One,
                                    destination: ::glium::LinearBlendingFactor::OneMinusSourceAlpha,
                                },
                                ..Default::default()
                            },
                        );
                    }
                }
            },
            |_, _, _, _| true,
        );
    }

    pub fn draw_windows(
        &self,
        frame: &mut Frame,
        window_map: &MyWindowMap,
        compositor_token: MyCompositorToken,
    ) {
        // redraw the frame, in a simple but inneficient way
        {
            let screen_dimensions = self.borrow().get_framebuffer_dimensions();
            window_map.with_windows_from_bottom_to_top(|toplevel_surface, initial_place| {
                if let Some(wl_surface) = toplevel_surface.get_surface() {
                    // this surface is a root of a subsurface tree that needs to be drawn
                    self.draw_surface_tree(
                        frame,
                        &wl_surface,
                        initial_place,
                        compositor_token,
                        screen_dimensions,
                    );
                }
            });
        }
    }

    pub fn draw_cursor(
        &self,
        frame: &mut Frame,
        surface: &wl_surface::WlSurface,
        (x, y): (i32, i32),
        token: MyCompositorToken,
    ) {
        let (dx, dy) = match token.with_role_data::<CursorImageRole, _, _>(surface, |data| data.hotspot) {
            Ok(h) => h,
            Err(_) => {
                warn!(
                    self.log,
                    "Trying to display as a cursor a surface that does not have the CursorImage role."
                );
                (0, 0)
            }
        };
        let screen_dimensions = self.borrow().get_framebuffer_dimensions();
        self.draw_surface_tree(frame, surface, (x - dx, y - dy), token, screen_dimensions);
    }

    pub fn draw_dnd_icon(
        &self,
        frame: &mut Frame,
        surface: &wl_surface::WlSurface,
        (x, y): (i32, i32),
        token: MyCompositorToken,
    ) {
        if !token.has_role::<DnDIconRole>(surface) {
            warn!(
                self.log,
                "Trying to display as a dnd icon a surface that does not have the DndIcon role."
            );
        }
        let screen_dimensions = self.borrow().get_framebuffer_dimensions();
        self.draw_surface_tree(frame, surface, (x, y), token, screen_dimensions);
    }
}
<|endoftext|>


<commit_before>use std::thread;
use std::sync::mpsc;
use std::time::Duration;

fn main() {
    let (tx, rx) = mpsc::channel();

    thread::spawn(move || {
        let vals = vec![
            String::from("Hello there"),
            String::from("Hello there 2"),
            String::from("Hello there 3"),
            String::from("Hello there 4")
        ];
        for val in vals {
            tx.send(val).unwrap();
            thread::sleep(Duration::from_secs(1));
        }
    });

    for received in rx {
        println!("Got: {}", received);
    }
}
<commit_msg>Add second thread sending messages<commit_after>use std::thread;
use std::sync::mpsc;
use std::time::Duration;

fn main() {
    let (tx, rx) = mpsc::channel();

    let cloned_tx = tx.clone();

    thread::spawn(move || {
        let vals = vec![
            String::from("Hello there"),
            String::from("Hello there 2"),
            String::from("Hello there 3"),
            String::from("Hello there 4")
        ];
        for val in vals {
            tx.send(val).unwrap();
            thread::sleep(Duration::from_secs(1));
        }
    });

    thread::spawn(move || {
        let vals = vec![
            String::from("Hello there from second_thread"),
            String::from("Hello there from second_thread 2"),
            String::from("Hello there from second_thread 3"),
            String::from("Hello there from second_thread 4")
        ];
        for val in vals {
            cloned_tx.send(val).unwrap();
            thread::sleep(Duration::from_secs(2));
        }
    });

    for received in rx {
        println!("Got: {}", received);
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)] // TODO: don't forget to remove

use crate::arc_or_static::ArcOrStatic;
use crate::descriptor::FileDescriptorProto;
use crate::reflect::MessageDescriptor;
use crate::reflect::{EnumDescriptor, GeneratedEnumDescriptorData, GeneratedMessageDescriptorData};

/// Reflection for objects defined in `.proto` file (messages, enums, etc).
pub struct FileDescriptor {
    file_descriptor_proto: ArcOrStatic<FileDescriptorProto>,
    dependencies: Vec<ArcOrStatic<FileDescriptor>>,
    messages: Vec<&'static MessageDescriptor>,
    enums: Vec<&'static EnumDescriptor>,
}

impl FileDescriptor {
    /// This function is to be called from generated code.
    pub fn new_generated(
        file_descriptor_proto: &'static FileDescriptorProto,
        dependencies: Vec<&'static FileDescriptor>,
        messages: Vec<GeneratedMessageDescriptorData>,
        enums: Vec<GeneratedEnumDescriptorData>,
    ) -> FileDescriptor {
        FileDescriptor {
            file_descriptor_proto: ArcOrStatic::Static(file_descriptor_proto),
            dependencies: dependencies.into_iter().map(ArcOrStatic::Static).collect(),
            messages: Vec::new(),
            enums: Vec::new(),
        }
    }

    /// Dynamic message (created from [`FileDescriptorProto`] without generated files.
    pub fn new_dynamic(
        file_descriptor_proto: ArcOrStatic<FileDescriptorProto>,
        dependencies: Vec<ArcOrStatic<FileDescriptor>>,
    ) -> FileDescriptor {
        FileDescriptor {
            file_descriptor_proto,
            dependencies,
            messages: Vec::new(), // TODO
            enums: Vec::new(),    // TODO
        }
    }
}
<commit_msg>Working on migration to new descriptors<commit_after>#![allow(dead_code)] // TODO: don't forget to remove

use crate::arc_or_static::ArcOrStatic;
use crate::descriptor::FileDescriptorProto;
use crate::reflect::EnumDescriptor;
use crate::reflect::GeneratedEnumDescriptorData;
use crate::reflect::GeneratedMessageDescriptorData;
use crate::reflect::MessageDescriptor;

/// Reflection for objects defined in `.proto` file (messages, enums, etc).
pub struct FileDescriptor {
    file_descriptor_proto: ArcOrStatic<FileDescriptorProto>,
    dependencies: Vec<ArcOrStatic<FileDescriptor>>,
    messages: Vec<GeneratedMessageDescriptorData>,
    enums: Vec<GeneratedEnumDescriptorData>,
}

impl FileDescriptor {
    /// This function is to be called from generated code.
    pub fn new_generated(
        file_descriptor_proto: &'static FileDescriptorProto,
        dependencies: Vec<&'static FileDescriptor>,
        messages: Vec<GeneratedMessageDescriptorData>,
        enums: Vec<GeneratedEnumDescriptorData>,
    ) -> FileDescriptor {
        FileDescriptor {
            file_descriptor_proto: ArcOrStatic::Static(file_descriptor_proto),
            dependencies: dependencies.into_iter().map(ArcOrStatic::Static).collect(),
            messages,
            enums,
        }
    }

    /// Dynamic message (created from [`FileDescriptorProto`] without generated files.
    pub fn new_dynamic(
        file_descriptor_proto: ArcOrStatic<FileDescriptorProto>,
        dependencies: Vec<ArcOrStatic<FileDescriptor>>,
    ) -> FileDescriptor {
        FileDescriptor {
            file_descriptor_proto,
            dependencies,
            messages: Vec::new(), // TODO
            enums: Vec::new(),    // TODO
        }
    }
}
<|endoftext|>


<commit_before>#![no_std]
#![no_main]
#![feature(asm, const_fn, lang_items, compiler_builtins_lib, const_cell_new)]

extern crate capsules;
extern crate compiler_builtins;
extern crate hotel;
#[macro_use(static_init)]
extern crate kernel;

#[macro_use]
pub mod io;
//pub mod rng;

//pub mod digest;
//pub mod aes;

use kernel::{Chip, Platform};
use kernel::mpu::MPU;

unsafe fn load_processes_old() -> &'static mut [Option<kernel::process::Process<'static>>] {
    extern "C" {
        /// Beginning of the ROM region containing app images.
        static _sapps: u8;
    }

    const NUM_PROCS: usize = 2;

    #[link_section = ".app_memory"]
    static mut MEMORIES: [[u8; 8192]; NUM_PROCS] = [[0; 8192]; NUM_PROCS];

    static mut PROCESSES: [Option<kernel::process::Process<'static>>; NUM_PROCS] = [None, None];

    let mut addr = &_sapps as *const u8;
    for i in 0..NUM_PROCS {
        // The first member of the LoadInfo header contains the total size of each process image. A
        // sentinel value of 0 (invalid because it's smaller than the header itself) is used to
        // mark the end of the list of processes.
        let total_size = *(addr as *const usize);
        if total_size == 0 {
            break;
        }

        let process = &mut PROCESSES[i];
        let memory = &mut MEMORIES[i];
        //*process = Some(kernel::process::Process::create(addr, total_size, memory));
        // TODO: panic if loading failed?

        addr = addr.offset(total_size as isize);
    }

    if *(addr as *const usize) != 0 {
        panic!("Exceeded maximum NUM_PROCS.");
    }

    &mut PROCESSES
}

pub struct Golf {
//    console: &'static capsules::console::Console<'static, hotel::uart::UART>,
    gpio: &'static capsules::gpio::GPIO<'static, hotel::gpio::GPIOPin>,
    timer: &'static capsules::alarm::AlarmDriver<'static, hotel::timels::Timels<'static>>,
    ipc: kernel::ipc::IPC,
//    digest: &'static digest::DigestDriver<'static, hotel::crypto::sha::ShaEngine>,
//    aes: &'static aes::AesDriver<'static>,
//    rng: &'static rng::RngDriver<'static, hotel::trng::TRNG>,
}

#[no_mangle]
pub unsafe fn reset_handler() {
    hotel::init();

    let timerhs = {
        use hotel::pmu::*;
        use hotel::timeus::Timeus;
        Clock::new(PeripheralClock::Bank1(PeripheralClock1::TimeUs0Timer)).enable();
        Clock::new(PeripheralClock::Bank1(PeripheralClock1::TimeLs0)).enable();
        let timer = Timeus::new(0);
        timer
    };

    timerhs.start();
    let start = timerhs.now();

    {
        use hotel::pmu::*;
        Clock::new(PeripheralClock::Bank0(PeripheralClock0::Gpio0)).enable();
        let pinmux = &mut *hotel::pinmux::PINMUX;
        // LED_0
        pinmux.dioa11.select.set(hotel::pinmux::Function::Gpio0Gpio0);

        // SW1
        pinmux.gpio0_gpio1.select.set(hotel::pinmux::SelectablePin::Diom2);
        pinmux.diom2.select.set(hotel::pinmux::Function::Gpio0Gpio1);
        pinmux.diom2.control.set(1 << 2 | 1 << 4);

        pinmux.diob1.select.set(hotel::pinmux::Function::Uart0Tx);
        pinmux.diob6.control.set(1 << 2 | 1 << 4);
        pinmux.uart0_rx.select.set(hotel::pinmux::SelectablePin::Diob6);
    }

/*    let console = static_init!(
        capsules::console::Console<'static, hotel::uart::UART>,
        capsules::console::Console::new(&hotel::uart::UART0,
                                       &mut capsules::console::WRITE_BUF,
                                       kernel::container::Container::create()),
        24);
    hotel::uart::UART0.set_client(console);
    console.initialize();
*/
    let gpio_pins = static_init!(
        [&'static hotel::gpio::GPIOPin; 2],
        [&hotel::gpio::PORT0.pins[0], &hotel::gpio::PORT0.pins[1]],
        8);

    let gpio = static_init!(
        capsules::gpio::GPIO<'static, hotel::gpio::GPIOPin>,
        capsules::gpio::GPIO::new(gpio_pins),
        20);
    for pin in gpio_pins.iter() {
        pin.set_client(gpio)
    }

    let timer = static_init!(
        capsules::alarm::AlarmDriver<'static, hotel::timels::Timels<'static>>,
        capsules::alarm::AlarmDriver::new(
            &hotel::timels::Timels0, kernel::Grant::create()),
        12);
    hotel::timels::Timels0.set_client(timer);
/*
    let digest = static_init!(
        digest::DigestDriver<'static, hotel::crypto::sha::ShaEngine>,
        digest::DigestDriver::new(
                &mut hotel::crypto::sha::KEYMGR0_SHA,
                kernel::Container::create()),
        16);

    let aes = static_init!(
        aes::AesDriver,
        aes::AesDriver::new(&mut hotel::crypto::aes::KEYMGR0_AES, kernel::Container::create()),
        16);
    hotel::crypto::aes::KEYMGR0_AES.set_client(aes);

    hotel::trng::TRNG0.init();
    let rng = static_init!(
        rng::RngDriver<'static, hotel::trng::TRNG>,
        rng::RngDriver::new(&mut hotel::trng::TRNG0, kernel::Container::create()),
        8);
    hotel::trng::TRNG0.set_client(rng);
*/
    let golf2 = static_init!(Golf, Golf {
//        console: console,
        gpio: gpio,
        timer: timer,
        ipc: kernel::ipc::IPC::new(),
//        digest: digest,
//        aes: aes,
//        rng: rng,
    }, 8);
/*
    hotel::usb::USB0.init(&mut hotel::usb::OUT_DESCRIPTORS,
                          &mut hotel::usb::OUT_BUFFERS,
                          &mut hotel::usb::IN_DESCRIPTORS,
                          &mut hotel::usb::IN_BUFFERS,
                          hotel::usb::PHY::A,
                          None,
                          Some(0x0011),
                          Some(0x7788));
*/

    let end = timerhs.now();

    println!("Hello from Rust! Initialization took {} tics.",
             end.wrapping_sub(start));

    let mut chip = hotel::chip::Hotel::new();
    chip.mpu().enable_mpu();

    kernel::main(golf2, &mut chip, load_processes_old(), &golf2.ipc);
}

impl Platform for Golf {
    fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
        where F: FnOnce(Option<&kernel::Driver>) -> R
    {
        match driver_num {
//            casules::console::DRIVER_NUM => f(Some(self.console)),
            capsules::gpio::DRIVER_NUM => f(Some(self.gpio)),
//            2 => f(Some(self.digest)),
            capsules::alarm::DRIVER_NUM => f(Some(self.timer)),
//            4 => f(Some(self.aes)),
            //            5 => f(Some(self.rng)),
            kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
            _ => f(None),
        }
    }
}
<commit_msg>Tock 1.0 is booting correctly, can twiddle GPIO. This commit doesn't fully boot, it just enters an infinite loop at the end of the kernel boot (before loading processes) that twiddles LED0.<commit_after>#![no_std]
#![no_main]
#![feature(asm, const_fn, lang_items, compiler_builtins_lib, const_cell_new)]

extern crate capsules;
extern crate compiler_builtins;
extern crate hotel;
#[macro_use(static_init)]
extern crate kernel;

#[macro_use]
pub mod io;
//pub mod rng;

//pub mod digest;
//pub mod aes;

use kernel::{Chip, Platform};
use kernel::mpu::MPU;
use kernel::hil::gpio::Pin;

unsafe fn load_processes_old() -> &'static mut [Option<kernel::process::Process<'static>>] {
    extern "C" {
        /// Beginning of the ROM region containing app images.
        static _sapps: u8;
    }

    const NUM_PROCS: usize = 2;

    #[link_section = ".app_memory"]
    static mut MEMORIES: [[u8; 8192]; NUM_PROCS] = [[0; 8192]; NUM_PROCS];

    static mut PROCESSES: [Option<kernel::process::Process<'static>>; NUM_PROCS] = [None, None];

    let mut addr = &_sapps as *const u8;
    for i in 0..NUM_PROCS {
        // The first member of the LoadInfo header contains the total size of each process image. A
        // sentinel value of 0 (invalid because it's smaller than the header itself) is used to
        // mark the end of the list of processes.
        let total_size = *(addr as *const usize);
        if total_size == 0 {
            break;
        }

        let process = &mut PROCESSES[i];
        let memory = &mut MEMORIES[i];
        //*process = Some(kernel::process::Process::create(addr, total_size, memory));
        // TODO: panic if loading failed?

        addr = addr.offset(total_size as isize);
    }

    if *(addr as *const usize) != 0 {
        panic!("Exceeded maximum NUM_PROCS.");
    }

    &mut PROCESSES
}

pub struct Golf {
//    console: &'static capsules::console::Console<'static, hotel::uart::UART>,
    gpio: &'static capsules::gpio::GPIO<'static, hotel::gpio::GPIOPin>,
    timer: &'static capsules::alarm::AlarmDriver<'static, hotel::timels::Timels<'static>>,
    ipc: kernel::ipc::IPC,
//    digest: &'static digest::DigestDriver<'static, hotel::crypto::sha::ShaEngine>,
//    aes: &'static aes::AesDriver<'static>,
//    rng: &'static rng::RngDriver<'static, hotel::trng::TRNG>,
}

#[no_mangle]
pub unsafe fn reset_handler() {
    hotel::init();

    let timerhs = {
        use hotel::pmu::*;
        use hotel::timeus::Timeus;
        Clock::new(PeripheralClock::Bank1(PeripheralClock1::TimeUs0Timer)).enable();
        Clock::new(PeripheralClock::Bank1(PeripheralClock1::TimeLs0)).enable();
        let timer = Timeus::new(0);
        timer
    };

    timerhs.start();
    let start = timerhs.now();

    {
        use hotel::pmu::*;
        Clock::new(PeripheralClock::Bank0(PeripheralClock0::Gpio0)).enable();
        let pinmux = &mut *hotel::pinmux::PINMUX;
        // LED_0
        pinmux.dioa11.select.set(hotel::pinmux::Function::Gpio0Gpio0);

        // SW1
        pinmux.gpio0_gpio1.select.set(hotel::pinmux::SelectablePin::Diom2);
        pinmux.diom2.select.set(hotel::pinmux::Function::Gpio0Gpio1);
        pinmux.diom2.control.set(1 << 2 | 1 << 4);

        pinmux.diob1.select.set(hotel::pinmux::Function::Uart0Tx);
        pinmux.diob6.control.set(1 << 2 | 1 << 4);
        pinmux.uart0_rx.select.set(hotel::pinmux::SelectablePin::Diob6);
    }

/*    let console = static_init!(
        capsules::console::Console<'static, hotel::uart::UART>,
        capsules::console::Console::new(&hotel::uart::UART0,
                                       &mut capsules::console::WRITE_BUF,
                                       kernel::container::Container::create()),
        24);
    hotel::uart::UART0.set_client(console);
    console.initialize();
*/
    let gpio_pins = static_init!(
        [&'static hotel::gpio::GPIOPin; 2],
        [&hotel::gpio::PORT0.pins[0], &hotel::gpio::PORT0.pins[1]],
        8);

    let gpio = static_init!(
        capsules::gpio::GPIO<'static, hotel::gpio::GPIOPin>,
        capsules::gpio::GPIO::new(gpio_pins),
        20);
    for pin in gpio_pins.iter() {
        pin.set_client(gpio)
    }

    let timer = static_init!(
        capsules::alarm::AlarmDriver<'static, hotel::timels::Timels<'static>>,
        capsules::alarm::AlarmDriver::new(
            &hotel::timels::Timels0, kernel::Grant::create()),
        12);
    hotel::timels::Timels0.set_client(timer);
/*
    let digest = static_init!(
        digest::DigestDriver<'static, hotel::crypto::sha::ShaEngine>,
        digest::DigestDriver::new(
                &mut hotel::crypto::sha::KEYMGR0_SHA,
                kernel::Container::create()),
        16);

    let aes = static_init!(
        aes::AesDriver,
        aes::AesDriver::new(&mut hotel::crypto::aes::KEYMGR0_AES, kernel::Container::create()),
        16);
    hotel::crypto::aes::KEYMGR0_AES.set_client(aes);

    hotel::trng::TRNG0.init();
    let rng = static_init!(
        rng::RngDriver<'static, hotel::trng::TRNG>,
        rng::RngDriver::new(&mut hotel::trng::TRNG0, kernel::Container::create()),
        8);
    hotel::trng::TRNG0.set_client(rng);
*/
    let golf2 = static_init!(Golf, Golf {
//        console: console,
        gpio: gpio,
        timer: timer,
        ipc: kernel::ipc::IPC::new(),
//        digest: digest,
//        aes: aes,
//        rng: rng,
    }, 8);
/*
    hotel::usb::USB0.init(&mut hotel::usb::OUT_DESCRIPTORS,
                          &mut hotel::usb::OUT_BUFFERS,
                          &mut hotel::usb::IN_DESCRIPTORS,
                          &mut hotel::usb::IN_BUFFERS,
                          hotel::usb::PHY::A,
                          None,
                          Some(0x0011),
                          Some(0x7788));
*/

    let end = timerhs.now();

    println!("Hello from Rust! Initialization took {} tics.",
             end.wrapping_sub(start));

    let mut chip = hotel::chip::Hotel::new();
    chip.mpu().enable_mpu();

    // Simple test loop to show system is booting and can twiddle
    // GPIO
    hotel::gpio::PORT0.pins[0].make_output();
    loop {
        let mut x = 5;
        for i in 0..1000000 {
            if x < 500000 {
                hotel::gpio::PORT0.pins[0].clear();
            } else {
                hotel::gpio::PORT0.pins[0].set();
            }
            x = x + 1;
        }
    }

    kernel::main(golf2, &mut chip, load_processes_old(), &golf2.ipc);
}

impl Platform for Golf {
    fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
        where F: FnOnce(Option<&kernel::Driver>) -> R
    {
        match driver_num {
//            casules::console::DRIVER_NUM => f(Some(self.console)),
            capsules::gpio::DRIVER_NUM => f(Some(self.gpio)),
//            2 => f(Some(self.digest)),
            capsules::alarm::DRIVER_NUM => f(Some(self.timer)),
//            4 => f(Some(self.aes)),
            //            5 => f(Some(self.rng)),
            kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
            _ => f(None),
        }
    }
}
<|endoftext|>


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

use std::collections::HashMap;
use std::sync::Mutex;
use std::sync::mpsc::{self, Receiver, Sender};
use std::thread;

use ipc::{self, IpcReceiver, IpcReceiverSet, IpcSelectionResult, IpcSender, OpaqueIpcMessage};
use ipc::{OpaqueIpcReceiver};
use serde::{Deserialize, Serialize};

lazy_static! {
    pub static ref ROUTER: RouterProxy = RouterProxy::new();
}

pub struct RouterProxy {
    comm: Mutex<RouterProxyComm>,
}

impl RouterProxy {
    pub fn new() -> RouterProxy {
        let (msg_sender, msg_receiver) = mpsc::channel();
        let (wakeup_sender, wakeup_receiver) = ipc::channel().unwrap();
        thread::spawn(move || Router::new(msg_receiver, wakeup_receiver).run());
        RouterProxy {
            comm: Mutex::new(RouterProxyComm {
                msg_sender: msg_sender,
                wakeup_sender: wakeup_sender,
            }),
        }
    }

    pub fn add_route(&self, receiver: OpaqueIpcReceiver, callback: RouterHandler) {
        let comm = self.comm.lock().unwrap();
        comm.msg_sender.send(RouterMsg::AddRoute(receiver, callback)).unwrap();
        comm.wakeup_sender.send(()).unwrap();
    }

    /// A convenience function to route an `IpcReceiver<T>` to an existing `Sender<T>`.
    pub fn route_ipc_receiver_to_mpsc_sender<T>(&self,
                                                ipc_receiver: IpcReceiver<T>,
                                                mpsc_sender: Sender<T>)
                                                where T: Deserialize +
                                                         Serialize +
                                                         Send +
                                                         'static {
        self.add_route(ipc_receiver.to_opaque(), Box::new(move |message| {
            drop(mpsc_sender.send(message.to::<T>().unwrap()))
        }))
    }

    /// A convenience function to route an `IpcReceiver<T>` to a `Receiver<T>`: the most common
    /// use of a `Router`.
    pub fn route_ipc_receiver_to_new_mpsc_receiver<T>(&self, ipc_receiver: IpcReceiver<T>)
                                                  -> Receiver<T>
                                                  where T: Deserialize +
                                                           Serialize +
                                                           Send +
                                                           'static {
        let (mpsc_sender, mpsc_receiver) = mpsc::channel();
        self.route_ipc_receiver_to_mpsc_sender(ipc_receiver, mpsc_sender);
        mpsc_receiver
    }
}

struct RouterProxyComm {
    msg_sender: Sender<RouterMsg>,
    wakeup_sender: IpcSender<()>,
}

struct Router {
    msg_receiver: Receiver<RouterMsg>,
    msg_wakeup_id: i64,
    ipc_receiver_set: IpcReceiverSet,
    handlers: HashMap<i64,RouterHandler>,
}

impl Router {
    fn new(msg_receiver: Receiver<RouterMsg>, wakeup_receiver: IpcReceiver<()>) -> Router {
        let mut ipc_receiver_set = IpcReceiverSet::new().unwrap();
        let msg_wakeup_id = ipc_receiver_set.add(wakeup_receiver).unwrap();
        Router {
            msg_receiver: msg_receiver,
            msg_wakeup_id: msg_wakeup_id,
            ipc_receiver_set: ipc_receiver_set,
            handlers: HashMap::new(),
        }
    }

    fn run(&mut self) {
        loop {
            let results = match self.ipc_receiver_set.select() {
                Ok(results) => results,
                Err(_) => break,
            };
            for result in results.into_iter() {
                match result {
                    IpcSelectionResult::MessageReceived(id, _) if id == self.msg_wakeup_id => {
                        match self.msg_receiver.recv().unwrap() {
                            RouterMsg::AddRoute(receiver, handler) => {
                                let new_receiver_id = self.ipc_receiver_set
                                                          .add_opaque(receiver)
                                                          .unwrap();
                                self.handlers.insert(new_receiver_id, handler);
                            }
                        }
                    }
                    IpcSelectionResult::MessageReceived(id, message) => {
                        self.handlers.get(&id).unwrap()(message)
                    }
                    IpcSelectionResult::ChannelClosed(id) => {
                        self.handlers.remove(&id).unwrap();
                    }
                }
            }
        }
    }
}

enum RouterMsg {
    AddRoute(OpaqueIpcReceiver, RouterHandler),
}

pub type RouterHandler = Box<Fn(OpaqueIpcMessage) + Send>;

<commit_msg>Auto merge of #12 - eefriedman:router-handler, r=pcwalton<commit_after>// Copyright 2015 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::collections::HashMap;
use std::sync::Mutex;
use std::sync::mpsc::{self, Receiver, Sender};
use std::thread;

use ipc::{self, IpcReceiver, IpcReceiverSet, IpcSelectionResult, IpcSender, OpaqueIpcMessage};
use ipc::{OpaqueIpcReceiver};
use serde::{Deserialize, Serialize};

lazy_static! {
    pub static ref ROUTER: RouterProxy = RouterProxy::new();
}

pub struct RouterProxy {
    comm: Mutex<RouterProxyComm>,
}

impl RouterProxy {
    pub fn new() -> RouterProxy {
        let (msg_sender, msg_receiver) = mpsc::channel();
        let (wakeup_sender, wakeup_receiver) = ipc::channel().unwrap();
        thread::spawn(move || Router::new(msg_receiver, wakeup_receiver).run());
        RouterProxy {
            comm: Mutex::new(RouterProxyComm {
                msg_sender: msg_sender,
                wakeup_sender: wakeup_sender,
            }),
        }
    }

    pub fn add_route(&self, receiver: OpaqueIpcReceiver, callback: RouterHandler) {
        let comm = self.comm.lock().unwrap();
        comm.msg_sender.send(RouterMsg::AddRoute(receiver, callback)).unwrap();
        comm.wakeup_sender.send(()).unwrap();
    }

    /// A convenience function to route an `IpcReceiver<T>` to an existing `Sender<T>`.
    pub fn route_ipc_receiver_to_mpsc_sender<T>(&self,
                                                ipc_receiver: IpcReceiver<T>,
                                                mpsc_sender: Sender<T>)
                                                where T: Deserialize +
                                                         Serialize +
                                                         Send +
                                                         'static {
        self.add_route(ipc_receiver.to_opaque(), Box::new(move |message| {
            drop(mpsc_sender.send(message.to::<T>().unwrap()))
        }))
    }

    /// A convenience function to route an `IpcReceiver<T>` to a `Receiver<T>`: the most common
    /// use of a `Router`.
    pub fn route_ipc_receiver_to_new_mpsc_receiver<T>(&self, ipc_receiver: IpcReceiver<T>)
                                                  -> Receiver<T>
                                                  where T: Deserialize +
                                                           Serialize +
                                                           Send +
                                                           'static {
        let (mpsc_sender, mpsc_receiver) = mpsc::channel();
        self.route_ipc_receiver_to_mpsc_sender(ipc_receiver, mpsc_sender);
        mpsc_receiver
    }
}

struct RouterProxyComm {
    msg_sender: Sender<RouterMsg>,
    wakeup_sender: IpcSender<()>,
}

struct Router {
    msg_receiver: Receiver<RouterMsg>,
    msg_wakeup_id: i64,
    ipc_receiver_set: IpcReceiverSet,
    handlers: HashMap<i64,RouterHandler>,
}

impl Router {
    fn new(msg_receiver: Receiver<RouterMsg>, wakeup_receiver: IpcReceiver<()>) -> Router {
        let mut ipc_receiver_set = IpcReceiverSet::new().unwrap();
        let msg_wakeup_id = ipc_receiver_set.add(wakeup_receiver).unwrap();
        Router {
            msg_receiver: msg_receiver,
            msg_wakeup_id: msg_wakeup_id,
            ipc_receiver_set: ipc_receiver_set,
            handlers: HashMap::new(),
        }
    }

    fn run(&mut self) {
        loop {
            let results = match self.ipc_receiver_set.select() {
                Ok(results) => results,
                Err(_) => break,
            };
            for result in results.into_iter() {
                match result {
                    IpcSelectionResult::MessageReceived(id, _) if id == self.msg_wakeup_id => {
                        match self.msg_receiver.recv().unwrap() {
                            RouterMsg::AddRoute(receiver, handler) => {
                                let new_receiver_id = self.ipc_receiver_set
                                                          .add_opaque(receiver)
                                                          .unwrap();
                                self.handlers.insert(new_receiver_id, handler);
                            }
                        }
                    }
                    IpcSelectionResult::MessageReceived(id, message) => {
                        self.handlers.get_mut(&id).unwrap()(message)
                    }
                    IpcSelectionResult::ChannelClosed(id) => {
                        self.handlers.remove(&id).unwrap();
                    }
                }
            }
        }
    }
}

enum RouterMsg {
    AddRoute(OpaqueIpcReceiver, RouterHandler),
}

pub type RouterHandler = Box<FnMut(OpaqueIpcMessage) + Send>;

<|endoftext|>


<commit_before>#![no_std]
#![no_main]
#![feature(lang_items)]

#[cfg(not(test))]
pub mod panic;

#[no_mangle]
pub extern "C" fn kmain() -> ! {
    unsafe {
        let rust = 0xb8180 as *mut u64;
        *rust = 0x0254025302550252;

        let belt = 0xb8360 as *mut u64;
        *belt = 0x0254024c02450242;

        let wow = 0xb8298 as *mut u64;
        *wow = 0x0577056f0577;

        let rust2 = 0xb8680 as *mut u64;
        *rust2 = 0x0254025302550252;

        let such = 0xb8750 as *mut u64;
        *such = 0x0568056305750573;

        let os = 0xb8760 as *mut u64;
        *os = 0x0573056f;

        let exes = 0xb8880 as *mut u64;
        *exes = 0x0221022102210221;

        let amaz = 0xb8988 as *mut u64;
        *amaz = 0x057a0561056d0561;

        let e = 0xb8992 as *mut u64;
        *e = 0x0565;
    };

    loop { }
}
<commit_msg>hello hello con<commit_after>#![no_std]
#![no_main]
#![feature(lang_items)]

#[cfg(not(test))]
pub mod panic;

#[no_mangle]
pub extern "C" fn kmain() -> ! {
    unsafe {
        let hell = 0xb8180 as *mut u64;
        *hell = 0x026c026c02650268;

        let o = 0xb8188 as *mut u64;
        *o = 0x026f;

        let wow = 0xb8298 as *mut u64;
        *wow = 0x0577056f0577;

        let hell2 = 0xb8360 as *mut u64;
        *hell2 = 0x024c024c02450248;

        let o2 = 0xb8368 as *mut u64;
        *o2 = 0x024f;

        let con = 0xb8680 as *mut u64;
        *con = 0x024e024f0243;

        let such = 0xb8750 as *mut u64;
        *such = 0x0568056305750573;

        let os = 0xb8760 as *mut u64;
        *os = 0x0573056f;

        let exes = 0xb8880 as *mut u64;
        *exes = 0x0221022102210221;

        let amaz = 0xb8988 as *mut u64;
        *amaz = 0x057a0561056d0561;

        let e = 0xb8992 as *mut u64;
        *e = 0x0565;
    };

    loop { }
}
<|endoftext|>


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

use crate::descriptor::DescriptorProto;
use crate::descriptor::FileDescriptorProto;
use crate::message_dyn::MessageDyn;
use crate::message_full::MessageFull;
use crate::reflect::dynamic::DynamicMessage;
use crate::reflect::field::FieldDescriptorImpl;
use crate::reflect::file::index::MessageIndex;
use crate::reflect::file::FileDescriptorImpl;
use crate::reflect::message::generated::GeneratedMessageDescriptor;
use crate::reflect::reflect_eq::ReflectEq;
use crate::reflect::reflect_eq::ReflectEqMode;
use crate::reflect::EnumDescriptor;
use crate::reflect::FieldDescriptor;
use crate::reflect::FileDescriptor;
use crate::reflect::OneofDescriptor;
use crate::CodedInputStream;

pub(crate) mod generated;
pub(crate) mod message_ref;
pub(crate) mod path;

/// Dynamic representation of message type.
///
/// Used for reflection.
#[derive(Clone, Eq, PartialEq, Hash)]
pub struct MessageDescriptor {
    pub(crate) file_descriptor: FileDescriptor,
    pub(crate) index: usize,
}

impl fmt::Display for MessageDescriptor {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.full_name())
    }
}

impl fmt::Debug for MessageDescriptor {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("MessageDescriptor").finish_non_exhaustive()
    }
}

impl MessageDescriptor {
    pub(crate) fn new(file_descriptor: FileDescriptor, index: usize) -> MessageDescriptor {
        MessageDescriptor {
            file_descriptor,
            index,
        }
    }

    /// Get internal index.
    ///
    /// Only needed for codegen.
    #[doc(hidden)]
    pub fn index_in_file_for_codegen(&self) -> usize {
        self.index
    }

    /// Get underlying `DescriptorProto` object.
    pub fn proto(&self) -> &DescriptorProto {
        self.file_descriptor.message_proto(self.index)
    }

    /// Message name as specified in `.proto` file.
    pub fn name(&self) -> &str {
        &self.index().name
    }

    fn index_entry(&self) -> &MessageIndex {
        self.file_descriptor.message_index_entry(self.index)
    }

    /// Get a message descriptor for given message type
    pub fn for_type<M: MessageFull>() -> MessageDescriptor {
        M::descriptor()
    }

    #[doc(hidden)]
    pub fn new_generated_2(file_descriptor: FileDescriptor, index: usize) -> MessageDescriptor {
        MessageDescriptor::new(file_descriptor, index)
    }

    /// Messages declared in this messages.
    pub fn nested_messages(&self) -> impl Iterator<Item = MessageDescriptor> + '_ {
        self.index_entry()
            .nested_messages
            .iter()
            .map(|i| MessageDescriptor::new(self.file_descriptor.clone(), *i))
    }

    /// Get enums declared in this message.
    pub fn nested_enums(&self) -> impl Iterator<Item = EnumDescriptor> + '_ {
        let index_entry = self.index_entry();
        (index_entry.first_enum_index..(index_entry.first_enum_index + index_entry.enum_count))
            .map(|i| EnumDescriptor::new(self.file_descriptor.clone(), i))
    }

    /// Get a message containing this message, or `None` if this message is declared at file level.
    pub fn enclosing_message(&self) -> Option<MessageDescriptor> {
        self.index_entry()
            .enclosing_message
            .map(|i| MessageDescriptor::new(self.file_descriptor.clone(), i))
    }

    pub(crate) fn get_impl(&self) -> MessageDescriptorImplRef {
        match &self.file_descriptor.imp {
            FileDescriptorImpl::Generated(g) => {
                MessageDescriptorImplRef::Generated(&g.messages[self.index])
            }
            FileDescriptorImpl::Dynamic(..) => MessageDescriptorImplRef::Dynamic,
        }
    }

    /// [`FileDescriptor`] containing this message.
    pub fn file_descriptor(&self) -> &FileDescriptor {
        &self.file_descriptor
    }

    /// `FileDescriptorProto` containg this message type
    pub fn file_descriptor_proto(&self) -> &FileDescriptorProto {
        self.file_descriptor().proto()
    }

    /// This message descriptor is a map entry.
    pub fn is_map_entry(&self) -> bool {
        self.proto().options.get_or_default().map_entry()
    }

    fn assert_not_map_entry(&self) {
        assert!(
            !self.is_map_entry(),
            "message is map entry: {}",
            self.full_name()
        );
    }

    /// New empty message.
    ///
    /// # Panics
    ///
    /// If this message is a map entry message.
    pub fn new_instance(&self) -> Box<dyn MessageDyn> {
        self.assert_not_map_entry();
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => g.non_map().factory.new_instance(),
            MessageDescriptorImplRef::Dynamic => Box::new(DynamicMessage::new(self.clone())),
        }
    }

    /// Shared immutable empty message.
    ///
    /// Returns `None` for dynamic message.
    ///
    /// # Panics
    ///
    /// If this message is a map entry message.
    pub fn default_instance(&self) -> Option<&'static dyn MessageDyn> {
        self.assert_not_map_entry();
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => Some(g.non_map().factory.default_instance()),
            MessageDescriptorImplRef::Dynamic => None,
        }
    }

    /// Clone a message
    pub(crate) fn clone_message(&self, message: &dyn MessageDyn) -> Box<dyn MessageDyn> {
        assert!(&message.descriptor_dyn() == self);
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => g.non_map().factory.clone(message),
            MessageDescriptorImplRef::Dynamic => {
                let message: &DynamicMessage = DynamicMessage::downcast_ref(message);
                Box::new(message.clone())
            }
        }
    }

    /// Check if two messages equal.
    ///
    /// # Panics
    ///
    /// Is any message has different type than this descriptor.
    pub fn eq(&self, a: &dyn MessageDyn, b: &dyn MessageDyn) -> bool {
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => g.non_map().factory.eq(a, b),
            MessageDescriptorImplRef::Dynamic => unimplemented!(),
        }
    }

    /// Similar to `eq`, but considers `NaN` values equal.
    ///
    /// # Panics
    ///
    /// Is any message has different type than this descriptor.
    pub(crate) fn reflect_eq(
        &self,
        a: &dyn MessageDyn,
        b: &dyn MessageDyn,
        mode: &ReflectEqMode,
    ) -> bool {
        // Explicitly force panic even if field list is empty
        assert_eq!(self, &a.descriptor_dyn());
        assert_eq!(self, &b.descriptor_dyn());

        for field in self.fields() {
            let af = field.get_reflect(a);
            let bf = field.get_reflect(b);
            if !af.reflect_eq(&bf, mode) {
                return false;
            }
        }
        true
    }

    pub(crate) fn reflect_eq_maybe_unrelated(
        a: &dyn MessageDyn,
        b: &dyn MessageDyn,
        mode: &ReflectEqMode,
    ) -> bool {
        let ad = a.descriptor_dyn();
        let bd = b.descriptor_dyn();
        ad == bd && ad.reflect_eq(a, b, mode)
    }

    /// Fully qualified protobuf message name
    pub fn full_name(&self) -> &str {
        &self.index_entry().full_name
    }

    /// Name relative to the package where the message is declared.
    pub fn name_to_package(&self) -> &str {
        &self.index_entry().name_to_package
    }

    /// Nested oneofs including synthetic.
    pub fn all_oneofs<'a>(&'a self) -> impl Iterator<Item = OneofDescriptor> + 'a {
        let index_entry = self.index_entry();
        (index_entry.first_oneof_index..index_entry.first_oneof_index + index_entry.oneof_count)
            .map(move |i| OneofDescriptor {
                file_descriptor: self.file_descriptor.clone(),
                index: i,
            })
    }

    /// Non-synthetic oneofs.
    pub fn oneofs<'a>(&'a self) -> impl Iterator<Item = OneofDescriptor> + 'a {
        self.all_oneofs().filter(|oneof| !oneof.is_synthetic())
    }

    /// Get message oneof by name (**not implemented**).
    pub fn oneof_by_name(&self, name: &str) -> Option<OneofDescriptor> {
        self.all_oneofs().find(|oneof| oneof.name() == name)
    }

    /// Message field descriptors.
    pub fn fields<'a>(&'a self) -> impl Iterator<Item = FieldDescriptor> + 'a {
        (0..self.index().message_index.fields.len()).map(move |index| FieldDescriptor {
            imp: FieldDescriptorImpl::Field(self.clone(), index),
        })
    }

    /// Extension fields.
    pub fn extensions(&self) -> impl Iterator<Item = FieldDescriptor> + '_ {
        (0..self.index().message_index.extensions.len()).map(move |index| FieldDescriptor {
            imp: FieldDescriptorImpl::ExtensionInMessage(self.clone(), index),
        })
    }

    pub(crate) fn index(&self) -> &MessageIndex {
        &self.file_descriptor.common().messages[self.index]
    }

    pub(crate) fn generated_index(&self) -> &'static MessageIndex {
        &self.file_descriptor.generated_index().messages[self.index]
    }

    /// Find message field by protobuf field name
    ///
    /// Note: protobuf field name might be different for Rust field name.
    // TODO: return value, not pointer, pointer is not compatible with dynamic message
    pub fn field_by_name(&self, name: &str) -> Option<FieldDescriptor> {
        let &index = self.index().message_index.field_index_by_name.get(name)?;
        Some(FieldDescriptor {
            imp: FieldDescriptorImpl::Field(self.clone(), index),
        })
    }

    /// Find message field by field name or field JSON name
    pub fn field_by_name_or_json_name<'a>(&'a self, name: &str) -> Option<FieldDescriptor> {
        let &index = self
            .index()
            .message_index
            .field_index_by_name_or_json_name
            .get(name)?;
        Some(FieldDescriptor {
            imp: FieldDescriptorImpl::Field(self.clone(), index),
        })
    }

    /// Find message field by field name
    pub fn field_by_number(&self, number: u32) -> Option<FieldDescriptor> {
        let &index = self
            .index()
            .message_index
            .field_index_by_number
            .get(&number)?;
        Some(FieldDescriptor {
            imp: FieldDescriptorImpl::Field(self.clone(), index),
        })
    }

    /// Parse message from stream.
    pub fn parse_from(&self, is: &mut CodedInputStream) -> crate::Result<Box<dyn MessageDyn>> {
        let mut r = self.new_instance();
        r.merge_from_dyn(is)?;
        r.check_initialized_dyn()?;
        Ok(r)
    }

    /// Parse message from reader.
    /// Parse stops on EOF or when error encountered.
    pub fn parse_from_reader(&self, reader: &mut dyn Read) -> crate::Result<Box<dyn MessageDyn>> {
        let mut is = CodedInputStream::new(reader);
        let r = self.parse_from(&mut is)?;
        is.check_eof()?;
        Ok(r)
    }

    /// Parse message from byte array.
    pub fn parse_from_bytes(&self, bytes: &[u8]) -> crate::Result<Box<dyn MessageDyn>> {
        let mut is = CodedInputStream::from_bytes(bytes);
        let r = self.parse_from(&mut is)?;
        is.check_eof()?;
        Ok(r)
    }
}

pub(crate) enum MessageDescriptorImplRef {
    Generated(&'static GeneratedMessageDescriptor),
    Dynamic,
}

#[cfg(test)]
mod test {
    use crate::descriptor::descriptor_proto::ExtensionRange;
    use crate::descriptor::field_descriptor_proto::Type;
    use crate::descriptor::DescriptorProto;
    use crate::descriptor::FieldDescriptorProto;
    use crate::EnumFull;
    use crate::MessageFull;

    #[test]
    #[cfg_attr(miri, ignore)] // Too slow on Miri.
    fn nested_messages() {
        assert!(DescriptorProto::descriptor()
            .nested_messages()
            .collect::<Vec<_>>()
            .contains(&ExtensionRange::descriptor()));
    }

    #[test]
    #[cfg_attr(miri, ignore)] // Too slow on Miri.
    fn nested_enums() {
        assert!(FieldDescriptorProto::descriptor()
            .nested_enums()
            .collect::<Vec<_>>()
            .contains(&Type::enum_descriptor()));
    }

    #[test]
    #[cfg_attr(miri, ignore)] // Too slow on Miri.
    fn enclosing_message() {
        assert_eq!(
            Some(DescriptorProto::descriptor()),
            ExtensionRange::descriptor().enclosing_message()
        );
        assert_eq!(None, DescriptorProto::descriptor().enclosing_message());
    }
}
<commit_msg>Remove some dead code<commit_after>use std::fmt;
use std::io::Read;

use crate::descriptor::DescriptorProto;
use crate::descriptor::FileDescriptorProto;
use crate::message_dyn::MessageDyn;
use crate::message_full::MessageFull;
use crate::reflect::dynamic::DynamicMessage;
use crate::reflect::field::FieldDescriptorImpl;
use crate::reflect::file::index::MessageIndex;
use crate::reflect::file::FileDescriptorImpl;
use crate::reflect::message::generated::GeneratedMessageDescriptor;
use crate::reflect::reflect_eq::ReflectEq;
use crate::reflect::reflect_eq::ReflectEqMode;
use crate::reflect::EnumDescriptor;
use crate::reflect::FieldDescriptor;
use crate::reflect::FileDescriptor;
use crate::reflect::OneofDescriptor;
use crate::CodedInputStream;

pub(crate) mod generated;
pub(crate) mod message_ref;
pub(crate) mod path;

/// Dynamic representation of message type.
///
/// Used for reflection.
#[derive(Clone, Eq, PartialEq, Hash)]
pub struct MessageDescriptor {
    pub(crate) file_descriptor: FileDescriptor,
    pub(crate) index: usize,
}

impl fmt::Display for MessageDescriptor {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.full_name())
    }
}

impl fmt::Debug for MessageDescriptor {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("MessageDescriptor").finish_non_exhaustive()
    }
}

impl MessageDescriptor {
    pub(crate) fn new(file_descriptor: FileDescriptor, index: usize) -> MessageDescriptor {
        MessageDescriptor {
            file_descriptor,
            index,
        }
    }

    /// Get underlying `DescriptorProto` object.
    pub fn proto(&self) -> &DescriptorProto {
        self.file_descriptor.message_proto(self.index)
    }

    /// Message name as specified in `.proto` file.
    pub fn name(&self) -> &str {
        &self.index().name
    }

    fn index_entry(&self) -> &MessageIndex {
        self.file_descriptor.message_index_entry(self.index)
    }

    /// Get a message descriptor for given message type
    pub fn for_type<M: MessageFull>() -> MessageDescriptor {
        M::descriptor()
    }

    #[doc(hidden)]
    pub fn new_generated_2(file_descriptor: FileDescriptor, index: usize) -> MessageDescriptor {
        MessageDescriptor::new(file_descriptor, index)
    }

    /// Messages declared in this messages.
    pub fn nested_messages(&self) -> impl Iterator<Item = MessageDescriptor> + '_ {
        self.index_entry()
            .nested_messages
            .iter()
            .map(|i| MessageDescriptor::new(self.file_descriptor.clone(), *i))
    }

    /// Get enums declared in this message.
    pub fn nested_enums(&self) -> impl Iterator<Item = EnumDescriptor> + '_ {
        let index_entry = self.index_entry();
        (index_entry.first_enum_index..(index_entry.first_enum_index + index_entry.enum_count))
            .map(|i| EnumDescriptor::new(self.file_descriptor.clone(), i))
    }

    /// Get a message containing this message, or `None` if this message is declared at file level.
    pub fn enclosing_message(&self) -> Option<MessageDescriptor> {
        self.index_entry()
            .enclosing_message
            .map(|i| MessageDescriptor::new(self.file_descriptor.clone(), i))
    }

    pub(crate) fn get_impl(&self) -> MessageDescriptorImplRef {
        match &self.file_descriptor.imp {
            FileDescriptorImpl::Generated(g) => {
                MessageDescriptorImplRef::Generated(&g.messages[self.index])
            }
            FileDescriptorImpl::Dynamic(..) => MessageDescriptorImplRef::Dynamic,
        }
    }

    /// [`FileDescriptor`] containing this message.
    pub fn file_descriptor(&self) -> &FileDescriptor {
        &self.file_descriptor
    }

    /// `FileDescriptorProto` containg this message type
    pub fn file_descriptor_proto(&self) -> &FileDescriptorProto {
        self.file_descriptor().proto()
    }

    /// This message descriptor is a map entry.
    pub fn is_map_entry(&self) -> bool {
        self.proto().options.get_or_default().map_entry()
    }

    fn assert_not_map_entry(&self) {
        assert!(
            !self.is_map_entry(),
            "message is map entry: {}",
            self.full_name()
        );
    }

    /// New empty message.
    ///
    /// # Panics
    ///
    /// If this message is a map entry message.
    pub fn new_instance(&self) -> Box<dyn MessageDyn> {
        self.assert_not_map_entry();
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => g.non_map().factory.new_instance(),
            MessageDescriptorImplRef::Dynamic => Box::new(DynamicMessage::new(self.clone())),
        }
    }

    /// Shared immutable empty message.
    ///
    /// Returns `None` for dynamic message.
    ///
    /// # Panics
    ///
    /// If this message is a map entry message.
    pub fn default_instance(&self) -> Option<&'static dyn MessageDyn> {
        self.assert_not_map_entry();
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => Some(g.non_map().factory.default_instance()),
            MessageDescriptorImplRef::Dynamic => None,
        }
    }

    /// Clone a message
    pub(crate) fn clone_message(&self, message: &dyn MessageDyn) -> Box<dyn MessageDyn> {
        assert!(&message.descriptor_dyn() == self);
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => g.non_map().factory.clone(message),
            MessageDescriptorImplRef::Dynamic => {
                let message: &DynamicMessage = DynamicMessage::downcast_ref(message);
                Box::new(message.clone())
            }
        }
    }

    /// Check if two messages equal.
    ///
    /// # Panics
    ///
    /// Is any message has different type than this descriptor.
    pub fn eq(&self, a: &dyn MessageDyn, b: &dyn MessageDyn) -> bool {
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => g.non_map().factory.eq(a, b),
            MessageDescriptorImplRef::Dynamic => unimplemented!(),
        }
    }

    /// Similar to `eq`, but considers `NaN` values equal.
    ///
    /// # Panics
    ///
    /// Is any message has different type than this descriptor.
    pub(crate) fn reflect_eq(
        &self,
        a: &dyn MessageDyn,
        b: &dyn MessageDyn,
        mode: &ReflectEqMode,
    ) -> bool {
        // Explicitly force panic even if field list is empty
        assert_eq!(self, &a.descriptor_dyn());
        assert_eq!(self, &b.descriptor_dyn());

        for field in self.fields() {
            let af = field.get_reflect(a);
            let bf = field.get_reflect(b);
            if !af.reflect_eq(&bf, mode) {
                return false;
            }
        }
        true
    }

    pub(crate) fn reflect_eq_maybe_unrelated(
        a: &dyn MessageDyn,
        b: &dyn MessageDyn,
        mode: &ReflectEqMode,
    ) -> bool {
        let ad = a.descriptor_dyn();
        let bd = b.descriptor_dyn();
        ad == bd && ad.reflect_eq(a, b, mode)
    }

    /// Fully qualified protobuf message name
    pub fn full_name(&self) -> &str {
        &self.index_entry().full_name
    }

    /// Name relative to the package where the message is declared.
    pub fn name_to_package(&self) -> &str {
        &self.index_entry().name_to_package
    }

    /// Nested oneofs including synthetic.
    pub fn all_oneofs<'a>(&'a self) -> impl Iterator<Item = OneofDescriptor> + 'a {
        let index_entry = self.index_entry();
        (index_entry.first_oneof_index..index_entry.first_oneof_index + index_entry.oneof_count)
            .map(move |i| OneofDescriptor {
                file_descriptor: self.file_descriptor.clone(),
                index: i,
            })
    }

    /// Non-synthetic oneofs.
    pub fn oneofs<'a>(&'a self) -> impl Iterator<Item = OneofDescriptor> + 'a {
        self.all_oneofs().filter(|oneof| !oneof.is_synthetic())
    }

    /// Get message oneof by name (**not implemented**).
    pub fn oneof_by_name(&self, name: &str) -> Option<OneofDescriptor> {
        self.all_oneofs().find(|oneof| oneof.name() == name)
    }

    /// Message field descriptors.
    pub fn fields<'a>(&'a self) -> impl Iterator<Item = FieldDescriptor> + 'a {
        (0..self.index().message_index.fields.len()).map(move |index| FieldDescriptor {
            imp: FieldDescriptorImpl::Field(self.clone(), index),
        })
    }

    /// Extension fields.
    pub fn extensions(&self) -> impl Iterator<Item = FieldDescriptor> + '_ {
        (0..self.index().message_index.extensions.len()).map(move |index| FieldDescriptor {
            imp: FieldDescriptorImpl::ExtensionInMessage(self.clone(), index),
        })
    }

    pub(crate) fn index(&self) -> &MessageIndex {
        &self.file_descriptor.common().messages[self.index]
    }

    pub(crate) fn generated_index(&self) -> &'static MessageIndex {
        &self.file_descriptor.generated_index().messages[self.index]
    }

    /// Find message field by protobuf field name
    ///
    /// Note: protobuf field name might be different for Rust field name.
    // TODO: return value, not pointer, pointer is not compatible with dynamic message
    pub fn field_by_name(&self, name: &str) -> Option<FieldDescriptor> {
        let &index = self.index().message_index.field_index_by_name.get(name)?;
        Some(FieldDescriptor {
            imp: FieldDescriptorImpl::Field(self.clone(), index),
        })
    }

    /// Find message field by field name or field JSON name
    pub fn field_by_name_or_json_name<'a>(&'a self, name: &str) -> Option<FieldDescriptor> {
        let &index = self
            .index()
            .message_index
            .field_index_by_name_or_json_name
            .get(name)?;
        Some(FieldDescriptor {
            imp: FieldDescriptorImpl::Field(self.clone(), index),
        })
    }

    /// Find message field by field name
    pub fn field_by_number(&self, number: u32) -> Option<FieldDescriptor> {
        let &index = self
            .index()
            .message_index
            .field_index_by_number
            .get(&number)?;
        Some(FieldDescriptor {
            imp: FieldDescriptorImpl::Field(self.clone(), index),
        })
    }

    /// Parse message from stream.
    pub fn parse_from(&self, is: &mut CodedInputStream) -> crate::Result<Box<dyn MessageDyn>> {
        let mut r = self.new_instance();
        r.merge_from_dyn(is)?;
        r.check_initialized_dyn()?;
        Ok(r)
    }

    /// Parse message from reader.
    /// Parse stops on EOF or when error encountered.
    pub fn parse_from_reader(&self, reader: &mut dyn Read) -> crate::Result<Box<dyn MessageDyn>> {
        let mut is = CodedInputStream::new(reader);
        let r = self.parse_from(&mut is)?;
        is.check_eof()?;
        Ok(r)
    }

    /// Parse message from byte array.
    pub fn parse_from_bytes(&self, bytes: &[u8]) -> crate::Result<Box<dyn MessageDyn>> {
        let mut is = CodedInputStream::from_bytes(bytes);
        let r = self.parse_from(&mut is)?;
        is.check_eof()?;
        Ok(r)
    }
}

pub(crate) enum MessageDescriptorImplRef {
    Generated(&'static GeneratedMessageDescriptor),
    Dynamic,
}

#[cfg(test)]
mod test {
    use crate::descriptor::descriptor_proto::ExtensionRange;
    use crate::descriptor::field_descriptor_proto::Type;
    use crate::descriptor::DescriptorProto;
    use crate::descriptor::FieldDescriptorProto;
    use crate::EnumFull;
    use crate::MessageFull;

    #[test]
    #[cfg_attr(miri, ignore)] // Too slow on Miri.
    fn nested_messages() {
        assert!(DescriptorProto::descriptor()
            .nested_messages()
            .collect::<Vec<_>>()
            .contains(&ExtensionRange::descriptor()));
    }

    #[test]
    #[cfg_attr(miri, ignore)] // Too slow on Miri.
    fn nested_enums() {
        assert!(FieldDescriptorProto::descriptor()
            .nested_enums()
            .collect::<Vec<_>>()
            .contains(&Type::enum_descriptor()));
    }

    #[test]
    #[cfg_attr(miri, ignore)] // Too slow on Miri.
    fn enclosing_message() {
        assert_eq!(
            Some(DescriptorProto::descriptor()),
            ExtensionRange::descriptor().enclosing_message()
        );
        assert_eq!(None, DescriptorProto::descriptor().enclosing_message());
    }
}
<|endoftext|>


<commit_before>// This file is part of rgtk.
//
// rgtk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// rgtk is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with rgtk.  If not, see <http://www.gnu.org/licenses/>.

#![feature(slicing_syntax, env, path, io, collections)]

extern crate gcc;
extern crate "pkg-config" as pkg_config;

use std::old_io::process::Command;
use gcc::Config;
use std::env;

fn main() {
    env::set_var("PKG_CONFIG_ALLOW_CROSS", "1");

    // try to find gtk+-3.0 library
    match pkg_config::find_library("gtk+-3.0") {
        Ok(_) => {},
        Err(e) => panic!("{}", e)
    };

    // call native pkg-config, there is no way to do this with pkg-config for now
    let cmd = match Command::new("pkg-config").arg("--cflags").arg("gtk+-3.0").output() {
        Ok(r) => r,
        Err(e) => panic!("{}", e)
    };

    // make the vector of path to set to gcc::Config
    let output: String = unsafe { String::from_utf8_unchecked(cmd.output) };
    let res: Vec<&str> = output.split(' ').collect();
    let paths: Vec<Path> = res.iter().filter_map(|s| {
        if s.len() > 1 && s.char_at(1) == 'I' { Some(Path::new(&s[2..])) }
        else { None }
    }).collect();

    // build include path
    let mut gcc_conf = Config::new();
    for path in paths {
        gcc_conf.include(&path);
    }
    gcc_conf.file("src/gtk_glue.c");

    // build library
    gcc_conf.compile("librgtk_glue.a");
}
<commit_msg>Fix a recent rustc nightly warning.<commit_after>// This file is part of rgtk.
//
// rgtk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// rgtk is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with rgtk.  If not, see <http://www.gnu.org/licenses/>.

#![feature(env, path, io, collections)]

extern crate gcc;
extern crate "pkg-config" as pkg_config;

use std::old_io::process::Command;
use gcc::Config;
use std::env;

fn main() {
    env::set_var("PKG_CONFIG_ALLOW_CROSS", "1");

    // try to find gtk+-3.0 library
    match pkg_config::find_library("gtk+-3.0") {
        Ok(_) => {},
        Err(e) => panic!("{}", e)
    };

    // call native pkg-config, there is no way to do this with pkg-config for now
    let cmd = match Command::new("pkg-config").arg("--cflags").arg("gtk+-3.0").output() {
        Ok(r) => r,
        Err(e) => panic!("{}", e)
    };

    // make the vector of path to set to gcc::Config
    let output: String = unsafe { String::from_utf8_unchecked(cmd.output) };
    let res: Vec<&str> = output.split(' ').collect();
    let paths: Vec<Path> = res.iter().filter_map(|s| {
        if s.len() > 1 && s.char_at(1) == 'I' { Some(Path::new(&s[2..])) }
        else { None }
    }).collect();

    // build include path
    let mut gcc_conf = Config::new();
    for path in paths {
        gcc_conf.include(&path);
    }
    gcc_conf.file("src/gtk_glue.c");

    // build library
    gcc_conf.compile("librgtk_glue.a");
}
<|endoftext|>


<commit_before>// Regression test for issue #63263.
// Tests that we properly handle closures with an explicit return type
// that return an opaque type.

// run-pass

#![feature(type_alias_impl_trait)]

pub type Closure = impl FnOnce();

fn main() {
    || -> Closure { || () };
}
<commit_msg>Change test type to `check-pass`<commit_after>// Regression test for issue #63263.
// Tests that we properly handle closures with an explicit return type
// that return an opaque type.

// check-pass

#![feature(type_alias_impl_trait)]

pub type Closure = impl FnOnce();

fn main() {
    || -> Closure { || () };
}
<|endoftext|>


<commit_before>use super::{VirtualAddress, PhysicalAddress, Page, PAGE_SIZE, ENTRY_COUNT};
use super::table::P4;
use super::entry::{PRESENT, HUGE_PAGE};
use memory::Frame;

pub fn translate(virtual_address: VirtualAddress) -> Option<PhysicalAddress> {
    let offset = virtual_address % PAGE_SIZE;
    translate_page(Page::containing_address(virtual_address))
        .map(|frame| frame.number * PAGE_SIZE + offset)
}

fn translate_page(page: Page) -> Option<Frame> {
    let p4 = unsafe { &*P4 };

    let huge_page = || {
        p4.next_table(page.p4_index())
          .and_then(|p3| {
              // 1GiB page?
              if p3[page.p3_index()].flags().contains(HUGE_PAGE | PRESENT) {
                  let start_frame_number = p3[page.p3_index()].pointed_frame().unwrap().number;
                  // address must be 1GiB aligned
                  assert!(start_frame_number % (ENTRY_COUNT * ENTRY_COUNT) == 0);
                  return Some(start_frame_number + page.p2_index() * ENTRY_COUNT + page.p1_index());
              }
              if let Some(p2) = p3.next_table(page.p3_index()) {
                  // 2MiB page?
                  if p2[page.p2_index()].flags().contains(HUGE_PAGE | PRESENT) {
                      let start_frame_number = p2[page.p2_index()].pointed_frame().unwrap().number;
                      // address must be 2MiB aligned
                      assert!(start_frame_number % ENTRY_COUNT == 0);
                      return Some(start_frame_number + page.p1_index());
                  }
              }
              None
          })
          .map(|start_frame_number| Frame { number: start_frame_number })
    };

    p4.next_table(page.p4_index())
      .and_then(|p3| p3.next_table(page.p3_index()))
      .and_then(|p2| p2.next_table(page.p2_index()))
      .and_then(|p1| p1[page.p1_index()].pointed_frame())
      .or_else(huge_page)
}
<commit_msg>Improve huge_page closure<commit_after>use super::{VirtualAddress, PhysicalAddress, Page, PAGE_SIZE, ENTRY_COUNT};
use super::table::P4;
use super::entry::{PRESENT, HUGE_PAGE};
use memory::Frame;

pub fn translate(virtual_address: VirtualAddress) -> Option<PhysicalAddress> {
    let offset = virtual_address % PAGE_SIZE;
    translate_page(Page::containing_address(virtual_address))
        .map(|frame| frame.number * PAGE_SIZE + offset)
}

fn translate_page(page: Page) -> Option<Frame> {
    let p4 = unsafe { &*P4 };

    let huge_page = || {
        p4.next_table(page.p4_index())
          .and_then(|p3| {
              let p3_entry = &p3[page.p3_index()];
              // 1GiB page?
              if let Some(start_frame) = p3_entry.pointed_frame() {
                  if p3_entry.flags().contains(HUGE_PAGE) {
                      // address must be 1GiB aligned
                      assert!(start_frame.number % (ENTRY_COUNT * ENTRY_COUNT) == 0);
                      return Some(Frame {
                          number: start_frame.number + page.p2_index() * ENTRY_COUNT +
                                  page.p1_index(),
                      });
                  }
              }
              if let Some(p2) = p3.next_table(page.p3_index()) {
                  let p2_entry = &p2[page.p2_index()];
                  // 2MiB page?
                  if let Some(start_frame) = p2_entry.pointed_frame() {
                      if p2_entry.flags().contains(HUGE_PAGE) {
                          // address must be 2MiB aligned
                          assert!(start_frame.number % ENTRY_COUNT == 0);
                          return Some(Frame { number: start_frame.number + page.p1_index() });
                      }
                  }
              }
              None
          })
    };

    p4.next_table(page.p4_index())
      .and_then(|p3| p3.next_table(page.p3_index()))
      .and_then(|p2| p2.next_table(page.p2_index()))
      .and_then(|p1| p1[page.p1_index()].pointed_frame())
      .or_else(huge_page)
}
<|endoftext|>