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

pub mod mersenne_utils {
    extern crate num_bigint;
    extern crate num_traits;

    use num_traits::{Pow,Num};
    use num_bigint::{BigInt,ToBigInt};

    pub fn mersennes_discovery_dates(n:usize) -> String {
        let mersennes_discovery_dates:Vec<Vec<&str>> = vec![
            //TODO: Complete this list all the way upto 50
            //TODO: We could include download links etc
            vec![""],//faux zero entry to make things easier when reading this vector
            vec!["500BC"],
            vec!["500BC"],
            vec!["275BC"],
            vec!["275BC"],
            vec!["1456"],
            vec!["1588"],
            vec!["1588"],
            vec!["1772"],
            vec!["1883"],
            vec!["1911"],
            vec!["1914"],
            vec!["1876"],
            vec!["30-Jan-1952"],
            vec!["30-Jan-1952"],
            vec!["26-Jun-1952"],
            vec!["7-Oct-1952"],
            vec!["9-Oct-1952"],
            vec!["8-Sep-1957"],
            vec!["3-Nov-1961"],
            vec!["3-Nov-1961"],
        ];

        mersennes_discovery_dates[n][0].to_owned()
    }

    pub fn mersennes() -> Vec<Vec<usize>> {
        vec![
            //TODO: Complete this list all the way upto 50
            //vec![p,digits]
            vec![0,      0],//faux zero entry to make things easier when reading this vector
            vec![2,     1],
            vec![3,     1],
            vec![5,     2],
            vec![7,     3],
            vec![13,    4],
            vec![17,    6],
            vec![19,    6],
            vec![31,   10],
            vec![61,   19],
            vec![89,   27],
            vec![107,  33],
            vec![127,  39],
            vec![521,  157],
            vec![607,  183],
            vec![1279, 386],
            vec![2203, 664],
            vec![2281, 687],
            vec![3217, 969],
            vec![4253,1281],
            vec![4423,1332],
        ]
    }

    pub fn nth_mersenne_prime (candidate:&str) -> u64 {
        let big_candidate:BigInt = num_bigint::BigInt::from_str_radix(&candidate, 10).unwrap();
        let mersennes:Vec<Vec<usize>> = mersennes();

        let mut answer:u64 = 0;
        let big_two:BigInt = 2.to_bigint().unwrap();
        for n in 1..mersennes.len() {
            let mprime:BigInt = big_two.pow(mersennes[n][0]) - 1;
            if big_candidate == mprime {
                answer = n as u64;
                break
            } else if big_candidate < mprime {
                break
            }
        }

        answer
    }
}

pub fn render() -> seed::dom_types::Node<Msg> {
    let mut html = vec![];

    let mersennes = mersenne_utils::mersennes();

    for n in 1..mersennes.len() {
        let download_txt:String = vec!["https://static.bigprimes.net/archive/mersenne/M",&n.to_string(),".txt"].into_iter().collect();
        let download_zip:String = vec!["https://static.bigprimes.net/archive/mersenne/M",&n.to_string(),".zip"].into_iter().collect();
        html.push(
            tr![
                td![n.to_string()],
                td!["2",sup![mersennes[n][0].to_string()],"-1"],
                td![mersennes[n][1].to_string()],
                td![mersenne_utils::mersennes_discovery_dates(n)],
                if n >= 30 {a![attrs!{At::Href => download_zip},"ZIP"]} else {a![attrs!{At::Href => download_txt},"TXT"]}
            ]
        );
    }

    html.reverse();

    div![
        h1!["The Mersenne Numbers"],
        br![],
        br![],
        br![],
        table![
            attrs!{At::Class => "mersennetable text"},
            tbody![
                tr![
                    td![
                        b!["No."]
                    ],
                    td![
                        b!["Prime"]
                    ],
                    td![
                        b!["Digits"]
                    ],
                    td![
                        b!["Discovered"]
                    ],
                    td![
                        b!["Download"]
                    ]
                ],
                html
            ]
        ]
    ]

    /*div![

 50
 277232917-1
 23249425
 26-Dec-2017

 ZIP

 49
 274207281-1
 22338618
 07-Jan-2016

 ZIP

 48
 257885161-1
 17425170
 25-Jan-2013

 ZIP

 47
 243112609-1
 12978189
 12-Apr-2008

 ZIP

 46
 242643801-1
 12837064
 06-Sep-2009

 ZIP

 45
 237156667-1
 11185272
 23-Aug-2008

 ZIP

 44
 232582657-1
 9808358
 4-Sep-2006

 ZIP

 43
 230402457-1
 9152052
 15-Dec-2005

 ZIP

 42
 225964951-1
 7816230
 26-Feb-2005

 ZIP

 41
 224036583-1
 7235733
 28-May-2004

 ZIP

 40
 220996011-1
 6320430
 17-Nov-2003

 ZIP

 39
 213466917-1
 4053946
 14-Nov-2001

 ZIP

 38
 26972593-1
 2098960
 1-Jun-1999

 ZIP

 37
 23021377-1
 909526
 27-Jan-1998

 ZIP

 36
 22976221-1
 895832
 24-Aug-1997

 ZIP

 35
 21398269-1
 420921
 12-Nov-1996
 TXT

 ZIP

 34
 21257787-1
 378632
 3-Sep-1996
 TXT

 ZIP

 33
 2859433-1
 258716
 10-Jan-1994
 TXT

 ZIP

 32
 2756839-1
 227832
 19-Feb-1992
 TXT

 ZIP

 31
 2216091-1
 65050
 6-Sep-1985
 TXT

 ZIP

 30
 2132049-1
 39751
 20-Sep-1983
 TXT

 ZIP

 29
 2110503-1
 33265
 28-Jan-1988
 TXT

 28
 286243-1
 25962
 25-Sep-1982
 TXT

 27
 244497-1
 13395
 8-Apr-1979
 TXT

 26
 223209-1
 6987
 9-Feb-1979
 TXT

 25
 221701-1
 6533
 30-Oct-1978
 TXT

 24
 219937-1
 6002
 4-Mar-1971
 TXT

 23
 211213-1
 3376
 2-Jun-1963
 TXT

 22
 29941-1
 2993
 16-May-1963
 TXT

 21
 29689-1
 2917
 11-May-1963
 TXT

 20
 24423-1
 1332
 3-Nov-1961
 TXT

"),
    ]*/
}<commit_msg>Completed refactor for remaining 30 mersennes. Many less lines of code.<commit_after>use seed::prelude::*;
use crate::Msg;

pub mod mersenne_utils {
    extern crate num_bigint;
    extern crate num_traits;

    use num_traits::{Pow,Num};
    use num_bigint::{BigInt,ToBigInt};

    pub fn mersennes_discovery_dates(n:usize) -> String {
        let mersennes_discovery_dates:Vec<Vec<&str>> = vec![
            //TODO: Complete this list all the way upto 50
            //TODO: We could include download links etc
            vec![""],//faux zero entry to make things easier when reading this vector
            vec!["500BC"],
            vec!["500BC"],
            vec!["275BC"],
            vec!["275BC"],
            vec!["1456"],
            vec!["1588"],
            vec!["1588"],
            vec!["1772"],
            vec!["1883"],
            vec!["1911"],
            vec!["1914"],
            vec!["1876"],
            vec!["30-Jan-1952"],
            vec!["30-Jan-1952"],
            vec!["26-Jun-1952"],
            vec!["7-Oct-1952"],
            vec!["9-Oct-1952"],
            vec!["8-Sep-1957"],
            vec!["3-Nov-1961"],
            vec!["3-Nov-1961"],
            vec!["11-May-1963"],
            vec!["16-May-1963"],
            vec!["2-Jun-1963"],
            vec!["4-Mar-1971"],
            vec!["30-Oct-1978"],
            vec!["9-Feb-1979"],
            vec!["8-Apr-1979"],
            vec!["25-Sep-1982"],
            vec!["28-Jan-1988"],
            vec!["20-Sep-1983"],
            vec!["6-Sep-1985"],
            vec!["19-Feb-1992"],
            vec!["10-Jan-1994"],
            vec!["3-Sep-1996"],
            vec!["12-Nov-1996"],
            vec!["24-Aug-1997"],
            vec!["27-Jan-1998"],
            vec!["1-Jun-1999"],
            vec!["14-Nov-2001"],
            vec!["17-Nov-2003"],
            vec!["28-May-2004"],
            vec!["26-Feb-2005"],
            vec!["15-Dec-2005"],
            vec!["4-Sep-2006"],
            vec!["23-Aug-2008"],
            vec!["06-Sep-2009"],
            vec!["12-Apr-2008"],
            vec!["25-Jan-2013"],
            vec!["07-Jan-2016"],
            vec!["26-Dec-2017"],
        ];

        mersennes_discovery_dates[n][0].to_owned()
    }

    pub fn mersennes() -> Vec<Vec<usize>> {
        vec![
            //TODO: Complete this list all the way upto 50
            //vec![p,digits]
            vec![0,      0],//faux zero entry to make things easier when reading this vector
            vec![2,     1],
            vec![3,     1],
            vec![5,     2],
            vec![7,     3],
            vec![13,    4],
            vec![17,    6],
            vec![19,    6],
            vec![31,   10],
            vec![61,   19],
            vec![89,   27],
            vec![107,  33],
            vec![127,  39],
            vec![521,  157],
            vec![607,  183],
            vec![1279, 386],
            vec![2203, 664],
            vec![2281, 687],
            vec![3217, 969],
            vec![4253,1281],
            vec![4423,1332],
            vec![9689,2917],
            vec![9941,2993],
            vec![11213,3376],
            vec![19937,6002],
            vec![21701,6533],
            vec![23209,6987],
            vec![44497,13395],
            vec![86243,25962],
            vec![110503,33265],
            vec![132049,39751],
            vec![216091,65050],
            vec![756839,227832],
            vec![859433,258716],
            vec![1257787,378632],
            vec![1398269,420921],
            vec![2976221,895832],
            vec![3021377,909526],
            vec![6972593,2098960],
            vec![13466917,4053946],
            vec![20996011,6320430],
            vec![24036583,7235733],
            vec![25964951,7816230],
            vec![30402457,9152052],
            vec![32582657,9808358],
            vec![37156667,11185272],
            vec![42643801,12837064],
            vec![43112609,12978189],
            vec![57885161,17425170],
            vec![74207281,22338618],
            vec![77232917,23249425],
        ]
    }

    pub fn nth_mersenne_prime (candidate:&str) -> u64 {
        let big_candidate:BigInt = num_bigint::BigInt::from_str_radix(&candidate, 10).unwrap();
        let mersennes:Vec<Vec<usize>> = mersennes();

        let mut answer:u64 = 0;
        let big_two:BigInt = 2.to_bigint().unwrap();
        for n in 1..mersennes.len() {
            let mprime:BigInt = big_two.pow(mersennes[n][0]) - 1;
            if big_candidate == mprime {
                answer = n as u64;
                break
            } else if big_candidate < mprime {
                break
            }
        }

        answer
    }
}

pub fn render() -> seed::dom_types::Node<Msg> {
    let mut html = vec![];

    let mersennes = mersenne_utils::mersennes();

    for n in 1..mersennes.len() {
        let download_txt:String = vec!["https://static.bigprimes.net/archive/mersenne/M",&n.to_string(),".txt"].into_iter().collect();
        let download_zip:String = vec!["https://static.bigprimes.net/archive/mersenne/M",&n.to_string(),".zip"].into_iter().collect();
        html.push(
            tr![
                td![n.to_string()],
                td!["2",sup![mersennes[n][0].to_string()],"-1"],
                td![mersennes[n][1].to_string()],
                td![mersenne_utils::mersennes_discovery_dates(n)],
                if n >= 30 {a![attrs!{At::Href => download_zip},"ZIP"]} else {a![attrs!{At::Href => download_txt},"TXT"]}
            ]
        );
    }

    html.reverse();

    div![
        h1!["The Mersenne Numbers"],
        br![],
        br![],
        br![],
        table![
            attrs!{At::Class => "mersennetable text"},
            tbody![
                tr![
                    td![
                        b!["No."]
                    ],
                    td![
                        b!["Prime"]
                    ],
                    td![
                        b!["Digits"]
                    ],
                    td![
                        b!["Discovered"]
                    ],
                    td![
                        b!["Download"]
                    ]
                ],
                html
            ]
        ]
    ]
}<|endoftext|>


<commit_before>// Copyright 2013 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.

//! Implementation of cross-process surfaces for Linux. This uses X pixmaps.

#![allow(non_snake_case)]

use texturegl::Texture;

use geom::size::Size2D;
use libc::{c_char, c_int, c_uint, c_void};
use glx;
use gleam::gl;
use skia::{SkiaSkNativeSharedGLContextRef, SkiaSkNativeSharedGLContextStealSurface};
use std::ascii::OwnedAsciiExt;
use std::ffi::{CString, CStr};
use std::mem;
use std::ptr;
use std::str;
use x11::xlib::{Display, Pixmap, XCreateGC, XCreateImage, XCreatePixmap, XDefaultScreen};
use x11::xlib::{XDisplayString, XFree, XFreePixmap, XGetGeometry, XOpenDisplay, XPutImage};
use x11::xlib::{XRootWindow, XVisualInfo, ZPixmap};

/// The display and visual info. This is needed in order to upload on the painting side. This
/// holds a weak reference to the display and will not close it when done.
///
/// FIXME(pcwalton): Mark nonsendable.
#[allow(missing_copy_implementations)]
pub struct NativePaintingGraphicsContext {
    pub display: *mut Display,
    visual_info: *mut XVisualInfo,
}

impl NativePaintingGraphicsContext {
    pub fn from_metadata(metadata: &NativeGraphicsMetadata) -> NativePaintingGraphicsContext {
        // FIXME(pcwalton): It would be more robust to actually have the compositor pass the
        // visual.
        let (compositor_visual_info, _) =
            NativeCompositingGraphicsContext::compositor_visual_info(metadata.display);

        NativePaintingGraphicsContext {
            display: metadata.display,
            visual_info: compositor_visual_info,
        }
    }
}

/// The display, visual info, and framebuffer configuration. This is needed in order to bind to a
/// texture on the compositor side. This holds only a *weak* reference to the display and does not
/// close it.
///
/// FIXME(pcwalton): Unchecked weak references are bad and can violate memory safety. This is hard
/// to fix because the Display is given to us by the native windowing system, but we should fix it
/// someday.
///
/// FIXME(pcwalton): Mark nonsendable.
#[derive(Copy, Clone)]
pub struct NativeCompositingGraphicsContext {
    display: *mut Display,
    framebuffer_configuration: Option<glx::types::GLXFBConfig>,
}

impl NativeCompositingGraphicsContext {
    /// Chooses the compositor visual info using the same algorithm that the compositor uses.
    ///
    /// FIXME(pcwalton): It would be more robust to actually have the compositor pass the visual.
    fn compositor_visual_info(display: *mut Display) -> (*mut XVisualInfo, Option<glx::types::GLXFBConfig>) {
        // If display is null, we'll assume we are going to be rendering
        // in headless mode without X running.
        if display == ptr::null_mut() {
            return (ptr::null_mut(), None);
        }

        unsafe {
            let fbconfig_attributes = [
                glx::DOUBLEBUFFER as i32, 0,
                glx::DRAWABLE_TYPE as i32, glx::PIXMAP_BIT as i32 | glx::WINDOW_BIT as i32,
                glx::BIND_TO_TEXTURE_RGBA_EXT as i32, 1,
                glx::RENDER_TYPE as i32, glx::RGBA_BIT as i32,
                glx::ALPHA_SIZE as i32, 8,
                0
            ];

            let screen = XDefaultScreen(display);
            let mut number_of_configs = 0;
            let configs = glx::ChooseFBConfig(mem::transmute(display),
                                              screen,
                                              fbconfig_attributes.as_ptr(),
                                              &mut number_of_configs);
            NativeCompositingGraphicsContext::get_compatible_configuration(display,
                                                                           configs,
                                                                           number_of_configs)
        }
    }

    fn get_compatible_configuration(display: *mut Display,
                                    configs: *mut glx::types::GLXFBConfig,
                                    number_of_configs: i32)
                                    -> (*mut XVisualInfo, Option<glx::types::GLXFBConfig>) {
        unsafe {
            if number_of_configs == 0 {
                panic!("glx::ChooseFBConfig returned no configurations.");
            }

            if !NativeCompositingGraphicsContext::need_to_find_32_bit_depth_visual(display) {
                let config = *configs.offset(0);
                let visual = glx::GetVisualFromFBConfig(mem::transmute(display), config);
                return (mem::transmute(visual), Some(config));
            }

            // NVidia (and AMD/ATI) drivers have RGBA configurations that use 24-bit
            // XVisual, not capable of representing an alpha-channel in Pixmap form,
            // so we look for the configuration with a full set of 32 bits.
            for i in 0..number_of_configs as isize {
                let config = *configs.offset(i);
                let visual: *mut XVisualInfo =
                    mem::transmute(glx::GetVisualFromFBConfig(mem::transmute(display), config));
                if (*visual).depth == 32 {
                    return (mem::transmute(visual), Some(config));
                }
                XFree(mem::transmute(visual));
            }

            panic!("Could not find 32-bit visual.");
        }
    }

    fn need_to_find_32_bit_depth_visual(display: *mut Display) -> bool {
        unsafe {
            let glXGetClientString: extern "C" fn(*mut Display, c_int) -> *const c_char =
                mem::transmute(glx::GetProcAddress(mem::transmute(&"glXGetClientString\x00".as_bytes()[0])));
            assert!(glXGetClientString as *mut c_void != ptr::null_mut());

            let glx_vendor = glx::GetClientString(mem::transmute(display), glx::VENDOR as i32);
            if glx_vendor == ptr::null() {
                panic!("Could not determine GLX vendor.");
            }
            let glx_vendor =
                str::from_utf8(CStr::from_ptr(glx_vendor).to_bytes())
                    .ok()
                    .expect("GLX client vendor string not in UTF-8 format.");
            let glx_vendor = String::from_str(glx_vendor).into_ascii_lowercase();
            glx_vendor.contains("nvidia") || glx_vendor.contains("ati")
        }
    }

    /// Creates a native graphics context from the given X display connection. This uses GLX. Only
    /// the compositor is allowed to call this.
    pub fn from_display(display: *mut Display) -> NativeCompositingGraphicsContext {
        let (_, fbconfig) = NativeCompositingGraphicsContext::compositor_visual_info(display);

        NativeCompositingGraphicsContext {
            display: display,
            framebuffer_configuration: fbconfig,
        }
    }
}

/// The X display.
#[derive(Clone, Copy)]
pub struct NativeGraphicsMetadata {
    pub display: *mut Display,
}
unsafe impl Send for NativeGraphicsMetadata {}

impl NativeGraphicsMetadata {
    /// Creates graphics metadata from a metadata descriptor.
    pub fn from_descriptor(descriptor: &NativeGraphicsMetadataDescriptor)
                           -> NativeGraphicsMetadata {
        // WARNING: We currently rely on the X display connection being the
        // same in both the Painting and Compositing contexts, as otherwise
        // the X Pixmap will not be sharable across them. Using this
        // method breaks that assumption.
        unsafe {
            let c_str = CString::new(descriptor.display.as_bytes()).unwrap();
            let display = XOpenDisplay(c_str.as_ptr() as *mut _);
            if display.is_null() {
                panic!("XOpenDisplay() failed!");
            }
            NativeGraphicsMetadata {
                display: display,
            }
        }
    }
}

/// A sendable form of the X display string.
#[derive(Clone, RustcDecodable, RustcEncodable)]
pub struct NativeGraphicsMetadataDescriptor {
    display: String,
}

impl NativeGraphicsMetadataDescriptor {
    /// Creates a metadata descriptor from metadata.
    pub fn from_metadata(metadata: NativeGraphicsMetadata) -> NativeGraphicsMetadataDescriptor {
        unsafe {
            let c_str = XDisplayString(metadata.display) as *const _;
            let bytes = CStr::from_ptr(c_str).to_bytes();
            NativeGraphicsMetadataDescriptor {
                display: str::from_utf8(bytes).unwrap().to_string(),
            }
        }
    }
}

#[derive(RustcDecodable, RustcEncodable)]
pub struct PixmapNativeSurface {
    /// The pixmap.
    pixmap: Pixmap,

    /// Whether this pixmap will leak if the destructor runs. This is for debugging purposes.
    will_leak: bool,
}

impl Drop for PixmapNativeSurface {
    fn drop(&mut self) {
        if self.will_leak {
            panic!("You should have disposed of the pixmap properly with destroy()! This pixmap \
                   will leak!");
        }
    }
}

impl PixmapNativeSurface {
    fn from_pixmap(pixmap: Pixmap) -> PixmapNativeSurface {
        PixmapNativeSurface {
            pixmap: pixmap,
            will_leak: true,
        }
    }

    pub fn from_skia_shared_gl_context(context: SkiaSkNativeSharedGLContextRef)
                                       -> PixmapNativeSurface {
        unsafe {
            let surface = SkiaSkNativeSharedGLContextStealSurface(context);
            PixmapNativeSurface::from_pixmap(mem::transmute(surface))
        }
    }

    pub fn new(native_context: &NativePaintingGraphicsContext, size: Size2D<i32>, _stride: i32)
           -> PixmapNativeSurface {
        unsafe {
            // Create the pixmap.
            let screen = XDefaultScreen(native_context.display);
            let window = XRootWindow(native_context.display, screen);
            // The X server we use for testing on build machines always returns
            // visuals that report 24 bit depth. But creating a 32 bit pixmap does work, so
            // hard code the depth here.
            let pixmap = XCreatePixmap(native_context.display,
                                       window,
                                       size.width as c_uint,
                                       size.height as c_uint,
                                       32);
            PixmapNativeSurface::from_pixmap(pixmap)
        }
    }

    /// This may only be called on the compositor side.
    pub fn bind_to_texture(&self,
                           native_context: &NativeCompositingGraphicsContext,
                           texture: &Texture,
                           _: Size2D<isize>) {
        // Create the GLX pixmap.
        //
        // FIXME(pcwalton): RAII for exception safety?
        unsafe {
            let pixmap_attributes = [
                glx::TEXTURE_TARGET_EXT as i32, glx::TEXTURE_2D_EXT as i32,
                glx::TEXTURE_FORMAT_EXT as i32, glx::TEXTURE_FORMAT_RGBA_EXT as i32,
                0
            ];

            let glx_display = mem::transmute(native_context.display);

            let glx_pixmap = glx::CreatePixmap(glx_display,
                                             native_context.framebuffer_configuration.expect(
                                                 "GLX 1.3 should have a framebuffer_configuration"),
                                             self.pixmap,
                                             pixmap_attributes.as_ptr());

            let glXBindTexImageEXT: extern "C" fn(*mut Display, glx::types::GLXDrawable, c_int, *mut c_int) =
                mem::transmute(glx::GetProcAddress(mem::transmute(&"glXBindTexImageEXT\x00".as_bytes()[0])));
            assert!(glXBindTexImageEXT as *mut c_void != ptr::null_mut());
            let _bound = texture.bind();
            glXBindTexImageEXT(native_context.display,
                               mem::transmute(glx_pixmap),
                               glx::FRONT_EXT  as i32,
                               ptr::null_mut());

            // FIXME(pcwalton): Recycle these for speed?
            glx::DestroyPixmap(glx_display, glx_pixmap);
        }
    }

    /// This may only be called on the painting side.
    pub fn upload(&mut self, graphics_context: &NativePaintingGraphicsContext, data: &[u8]) {
        unsafe {
            // Ensure that we're running on the render task. Take the display.
            let pixmap = self.pixmap;

            // Figure out the width, height, and depth of the pixmap.
            let mut root_window = 0;
            let mut x = 0;
            let mut y = 0;
            let mut width = 0;
            let mut height = 0;
            let mut border_width = 0;
            let mut depth = 0;
            let _ = XGetGeometry(graphics_context.display,
                                 mem::transmute(pixmap),
                                 &mut root_window,
                                 &mut x,
                                 &mut y,
                                 &mut width,
                                 &mut height,
                                 &mut border_width,
                                 &mut depth);

            // Create the image.
            let image = XCreateImage(graphics_context.display,
                                     (*graphics_context.visual_info).visual,
                                     depth,
                                     ZPixmap,
                                     0,
                                     mem::transmute(&data[0]),
                                     width as c_uint,
                                     height as c_uint,
                                     32,
                                     0);

            // Create the X graphics context.
            let gc = XCreateGC(graphics_context.display, pixmap, 0, ptr::null_mut());

            // Draw the image.
            let _ = XPutImage(graphics_context.display,
                              pixmap,
                              gc,
                              image,
                              0,
                              0,
                              0,
                              0,
                              width,
                              height);
        }
    }

    pub fn get_id(&self) -> isize {
        self.pixmap as isize
    }

    pub fn destroy(&mut self, graphics_context: &NativePaintingGraphicsContext) {
        unsafe {
            assert!(self.pixmap != 0);
            XFreePixmap(graphics_context.display, self.pixmap);
            self.mark_wont_leak()
        }
    }

    pub fn mark_will_leak(&mut self) {
        self.will_leak = true;
    }

    pub fn mark_wont_leak(&mut self) {
        self.will_leak = false;
    }
}
<commit_msg>Prevent memory leak in X11 code<commit_after>// Copyright 2013 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.

//! Implementation of cross-process surfaces for Linux. This uses X pixmaps.

#![allow(non_snake_case)]

use texturegl::Texture;

use geom::size::Size2D;
use libc::{c_char, c_int, c_uint, c_void};
use glx;
use gleam::gl;
use skia::{SkiaSkNativeSharedGLContextRef, SkiaSkNativeSharedGLContextStealSurface};
use std::ascii::OwnedAsciiExt;
use std::ffi::{CString, CStr};
use std::mem;
use std::ptr;
use std::str;
use x11::xlib::{Display, Pixmap, XCreateGC, XCreateImage, XCreatePixmap, XDefaultScreen};
use x11::xlib::{XDisplayString, XFree, XFreePixmap, XGetGeometry, XOpenDisplay, XPutImage};
use x11::xlib::{XRootWindow, XVisualInfo, ZPixmap};

/// The display and visual info. This is needed in order to upload on the painting side. This
/// holds a weak reference to the display and will not close it when done.
///
/// FIXME(pcwalton): Mark nonsendable.
#[allow(missing_copy_implementations)]
pub struct NativePaintingGraphicsContext {
    pub display: *mut Display,
    visual_info: *mut XVisualInfo,
}

impl NativePaintingGraphicsContext {
    pub fn from_metadata(metadata: &NativeGraphicsMetadata) -> NativePaintingGraphicsContext {
        // FIXME(pcwalton): It would be more robust to actually have the compositor pass the
        // visual.
        let (compositor_visual_info, _) =
            NativeCompositingGraphicsContext::compositor_visual_info(metadata.display);

        NativePaintingGraphicsContext {
            display: metadata.display,
            visual_info: compositor_visual_info,
        }
    }
}

/// The display, visual info, and framebuffer configuration. This is needed in order to bind to a
/// texture on the compositor side. This holds only a *weak* reference to the display and does not
/// close it.
///
/// FIXME(pcwalton): Unchecked weak references are bad and can violate memory safety. This is hard
/// to fix because the Display is given to us by the native windowing system, but we should fix it
/// someday.
///
/// FIXME(pcwalton): Mark nonsendable.
#[derive(Copy, Clone)]
pub struct NativeCompositingGraphicsContext {
    display: *mut Display,
    framebuffer_configuration: Option<glx::types::GLXFBConfig>,
}

impl NativeCompositingGraphicsContext {
    /// Chooses the compositor visual info using the same algorithm that the compositor uses.
    ///
    /// FIXME(pcwalton): It would be more robust to actually have the compositor pass the visual.
    fn compositor_visual_info(display: *mut Display) -> (*mut XVisualInfo, Option<glx::types::GLXFBConfig>) {
        // If display is null, we'll assume we are going to be rendering
        // in headless mode without X running.
        if display == ptr::null_mut() {
            return (ptr::null_mut(), None);
        }

        unsafe {
            let fbconfig_attributes = [
                glx::DOUBLEBUFFER as i32, 0,
                glx::DRAWABLE_TYPE as i32, glx::PIXMAP_BIT as i32 | glx::WINDOW_BIT as i32,
                glx::BIND_TO_TEXTURE_RGBA_EXT as i32, 1,
                glx::RENDER_TYPE as i32, glx::RGBA_BIT as i32,
                glx::ALPHA_SIZE as i32, 8,
                0
            ];

            let screen = XDefaultScreen(display);
            let mut number_of_configs = 0;
            let configs = glx::ChooseFBConfig(mem::transmute(display),
                                              screen,
                                              fbconfig_attributes.as_ptr(),
                                              &mut number_of_configs);
            NativeCompositingGraphicsContext::get_compatible_configuration(display,
                                                                           configs,
                                                                           number_of_configs)
        }
    }

    fn get_compatible_configuration(display: *mut Display,
                                    configs: *mut glx::types::GLXFBConfig,
                                    number_of_configs: i32)
                                    -> (*mut XVisualInfo, Option<glx::types::GLXFBConfig>) {
        unsafe {
            if number_of_configs == 0 {
                panic!("glx::ChooseFBConfig returned no configurations.");
            }

            if !NativeCompositingGraphicsContext::need_to_find_32_bit_depth_visual(display) {
                let config = *configs.offset(0);
                let visual = glx::GetVisualFromFBConfig(mem::transmute(display), config);

                XFree(configs as *mut c_void);
                return (mem::transmute(visual), Some(config));
            }

            // NVidia (and AMD/ATI) drivers have RGBA configurations that use 24-bit
            // XVisual, not capable of representing an alpha-channel in Pixmap form,
            // so we look for the configuration with a full set of 32 bits.
            for i in 0..number_of_configs as isize {
                let config = *configs.offset(i);
                let visual: *mut XVisualInfo =
                    mem::transmute(glx::GetVisualFromFBConfig(mem::transmute(display), config));
                if (*visual).depth == 32 {
                    XFree(configs as *mut c_void);
                    return (visual, Some(config));
                }
                XFree(visual as *mut c_void);
            }

            XFree(configs as *mut c_void);
            panic!("Could not find 32-bit visual.");
        }
    }

    fn need_to_find_32_bit_depth_visual(display: *mut Display) -> bool {
        unsafe {
            let glXGetClientString: extern "C" fn(*mut Display, c_int) -> *const c_char =
                mem::transmute(glx::GetProcAddress(mem::transmute(&"glXGetClientString\x00".as_bytes()[0])));
            assert!(glXGetClientString as *mut c_void != ptr::null_mut());

            let glx_vendor = glx::GetClientString(mem::transmute(display), glx::VENDOR as i32);
            if glx_vendor == ptr::null() {
                panic!("Could not determine GLX vendor.");
            }
            let glx_vendor =
                str::from_utf8(CStr::from_ptr(glx_vendor).to_bytes())
                    .ok()
                    .expect("GLX client vendor string not in UTF-8 format.");
            let glx_vendor = String::from_str(glx_vendor).into_ascii_lowercase();
            glx_vendor.contains("nvidia") || glx_vendor.contains("ati")
        }
    }

    /// Creates a native graphics context from the given X display connection. This uses GLX. Only
    /// the compositor is allowed to call this.
    pub fn from_display(display: *mut Display) -> NativeCompositingGraphicsContext {
        let (_, fbconfig) = NativeCompositingGraphicsContext::compositor_visual_info(display);

        NativeCompositingGraphicsContext {
            display: display,
            framebuffer_configuration: fbconfig,
        }
    }
}

/// The X display.
#[derive(Clone, Copy)]
pub struct NativeGraphicsMetadata {
    pub display: *mut Display,
}
unsafe impl Send for NativeGraphicsMetadata {}

impl NativeGraphicsMetadata {
    /// Creates graphics metadata from a metadata descriptor.
    pub fn from_descriptor(descriptor: &NativeGraphicsMetadataDescriptor)
                           -> NativeGraphicsMetadata {
        // WARNING: We currently rely on the X display connection being the
        // same in both the Painting and Compositing contexts, as otherwise
        // the X Pixmap will not be sharable across them. Using this
        // method breaks that assumption.
        unsafe {
            let c_str = CString::new(descriptor.display.as_bytes()).unwrap();
            let display = XOpenDisplay(c_str.as_ptr() as *mut _);
            if display.is_null() {
                panic!("XOpenDisplay() failed!");
            }
            NativeGraphicsMetadata {
                display: display,
            }
        }
    }
}

/// A sendable form of the X display string.
#[derive(Clone, RustcDecodable, RustcEncodable)]
pub struct NativeGraphicsMetadataDescriptor {
    display: String,
}

impl NativeGraphicsMetadataDescriptor {
    /// Creates a metadata descriptor from metadata.
    pub fn from_metadata(metadata: NativeGraphicsMetadata) -> NativeGraphicsMetadataDescriptor {
        unsafe {
            let c_str = XDisplayString(metadata.display) as *const _;
            let bytes = CStr::from_ptr(c_str).to_bytes();
            NativeGraphicsMetadataDescriptor {
                display: str::from_utf8(bytes).unwrap().to_string(),
            }
        }
    }
}

#[derive(RustcDecodable, RustcEncodable)]
pub struct PixmapNativeSurface {
    /// The pixmap.
    pixmap: Pixmap,

    /// Whether this pixmap will leak if the destructor runs. This is for debugging purposes.
    will_leak: bool,
}

impl Drop for PixmapNativeSurface {
    fn drop(&mut self) {
        if self.will_leak {
            panic!("You should have disposed of the pixmap properly with destroy()! This pixmap \
                   will leak!");
        }
    }
}

impl PixmapNativeSurface {
    fn from_pixmap(pixmap: Pixmap) -> PixmapNativeSurface {
        PixmapNativeSurface {
            pixmap: pixmap,
            will_leak: true,
        }
    }

    pub fn from_skia_shared_gl_context(context: SkiaSkNativeSharedGLContextRef)
                                       -> PixmapNativeSurface {
        unsafe {
            let surface = SkiaSkNativeSharedGLContextStealSurface(context);
            PixmapNativeSurface::from_pixmap(mem::transmute(surface))
        }
    }

    pub fn new(native_context: &NativePaintingGraphicsContext, size: Size2D<i32>, _stride: i32)
           -> PixmapNativeSurface {
        unsafe {
            // Create the pixmap.
            let screen = XDefaultScreen(native_context.display);
            let window = XRootWindow(native_context.display, screen);
            // The X server we use for testing on build machines always returns
            // visuals that report 24 bit depth. But creating a 32 bit pixmap does work, so
            // hard code the depth here.
            let pixmap = XCreatePixmap(native_context.display,
                                       window,
                                       size.width as c_uint,
                                       size.height as c_uint,
                                       32);
            PixmapNativeSurface::from_pixmap(pixmap)
        }
    }

    /// This may only be called on the compositor side.
    pub fn bind_to_texture(&self,
                           native_context: &NativeCompositingGraphicsContext,
                           texture: &Texture,
                           _: Size2D<isize>) {
        // Create the GLX pixmap.
        //
        // FIXME(pcwalton): RAII for exception safety?
        unsafe {
            let pixmap_attributes = [
                glx::TEXTURE_TARGET_EXT as i32, glx::TEXTURE_2D_EXT as i32,
                glx::TEXTURE_FORMAT_EXT as i32, glx::TEXTURE_FORMAT_RGBA_EXT as i32,
                0
            ];

            let glx_display = mem::transmute(native_context.display);

            let glx_pixmap = glx::CreatePixmap(glx_display,
                                             native_context.framebuffer_configuration.expect(
                                                 "GLX 1.3 should have a framebuffer_configuration"),
                                             self.pixmap,
                                             pixmap_attributes.as_ptr());

            let glXBindTexImageEXT: extern "C" fn(*mut Display, glx::types::GLXDrawable, c_int, *mut c_int) =
                mem::transmute(glx::GetProcAddress(mem::transmute(&"glXBindTexImageEXT\x00".as_bytes()[0])));
            assert!(glXBindTexImageEXT as *mut c_void != ptr::null_mut());
            let _bound = texture.bind();
            glXBindTexImageEXT(native_context.display,
                               mem::transmute(glx_pixmap),
                               glx::FRONT_EXT  as i32,
                               ptr::null_mut());

            // FIXME(pcwalton): Recycle these for speed?
            glx::DestroyPixmap(glx_display, glx_pixmap);
        }
    }

    /// This may only be called on the painting side.
    pub fn upload(&mut self, graphics_context: &NativePaintingGraphicsContext, data: &[u8]) {
        unsafe {
            // Ensure that we're running on the render task. Take the display.
            let pixmap = self.pixmap;

            // Figure out the width, height, and depth of the pixmap.
            let mut root_window = 0;
            let mut x = 0;
            let mut y = 0;
            let mut width = 0;
            let mut height = 0;
            let mut border_width = 0;
            let mut depth = 0;
            let _ = XGetGeometry(graphics_context.display,
                                 mem::transmute(pixmap),
                                 &mut root_window,
                                 &mut x,
                                 &mut y,
                                 &mut width,
                                 &mut height,
                                 &mut border_width,
                                 &mut depth);

            // Create the image.
            let image = XCreateImage(graphics_context.display,
                                     (*graphics_context.visual_info).visual,
                                     depth,
                                     ZPixmap,
                                     0,
                                     mem::transmute(&data[0]),
                                     width as c_uint,
                                     height as c_uint,
                                     32,
                                     0);

            // Create the X graphics context.
            let gc = XCreateGC(graphics_context.display, pixmap, 0, ptr::null_mut());

            // Draw the image.
            let _ = XPutImage(graphics_context.display,
                              pixmap,
                              gc,
                              image,
                              0,
                              0,
                              0,
                              0,
                              width,
                              height);
        }
    }

    pub fn get_id(&self) -> isize {
        self.pixmap as isize
    }

    pub fn destroy(&mut self, graphics_context: &NativePaintingGraphicsContext) {
        unsafe {
            assert!(self.pixmap != 0);
            XFreePixmap(graphics_context.display, self.pixmap);
            self.mark_wont_leak()
        }
    }

    pub fn mark_will_leak(&mut self) {
        self.will_leak = true;
    }

    pub fn mark_wont_leak(&mut self) {
        self.will_leak = false;
    }
}
<|endoftext|>


<commit_before>use int::Int;

macro_rules! div {
    ($intrinsic:ident: $ty:ty, $uty:ty) => {
        div!($intrinsic: $ty, $uty, $ty, |i| {i});
    };
    ($intrinsic:ident: $ty:ty, $uty:ty, $tyret:ty, $conv:expr) => {
        /// Returns `a / b`
        #[cfg_attr(not(test), no_mangle)]
        pub extern "C" fn $intrinsic(a: $ty, b: $ty) -> $tyret {
            let s_a = a >> (<$ty>::bits() - 1);
            let s_b = b >> (<$ty>::bits() - 1);
            let a = (a ^ s_a) - s_a;
            let b = (b ^ s_b) - s_b;
            let s = s_a ^ s_b;

            let r = udiv!(a as $uty, b as $uty);
            ($conv)((r as $ty ^ s) - s)
        }
    }
}

macro_rules! mod_ {
    ($intrinsic:ident: $ty:ty, $uty:ty) => {
        mod_!($intrinsic: $ty, $uty, $ty, |i| {i});
    };
    ($intrinsic:ident: $ty:ty, $uty:ty, $tyret:ty, $conv:expr) => {
        /// Returns `a % b`
        #[cfg_attr(not(test), no_mangle)]
        pub extern "C" fn $intrinsic(a: $ty, b: $ty) -> $tyret {
            let s = b >> (<$ty>::bits() - 1);
            let b = (b ^ s) - s;
            let s = a >> (<$ty>::bits() - 1);
            let a = (a ^ s) - s;

            let r = urem!(a as $uty, b as $uty);
            ($conv)((r as $ty ^ s) - s)
        }
    }
}

macro_rules! divmod {
    ($abi:tt, $intrinsic:ident, $div:ident: $ty:ty) => {
        /// Returns `a / b` and sets `*rem = n % d`
        #[cfg_attr(not(test), no_mangle)]
        pub extern $abi fn $intrinsic(a: $ty, b: $ty, rem: &mut $ty) -> $ty {
            #[cfg(all(feature = "c", any(target_arch = "x86")))]
            extern {
                fn $div(a: $ty, b: $ty) -> $ty;
            }

            let r = match () {
                #[cfg(not(all(feature = "c", any(target_arch = "x86"))))]
                () => $div(a, b),
                #[cfg(all(feature = "c", any(target_arch = "x86")))]
                () => unsafe { $div(a, b) },
            };
            *rem = a - (r * b);
            r
        }
    }
}

#[cfg(not(all(feature = "c", target_arch = "arm", not(target_os = "ios"), not(thumbv6m))))]
div!(__divsi3: i32, u32);

#[cfg(not(all(feature = "c", target_arch = "x86")))]
div!(__divdi3: i64, u64);

#[cfg(not(all(windows, target_pointer_width="64")))]
div!(__divti3: i128, u128);

#[cfg(all(windows, target_pointer_width="64"))]
div!(__divti3: i128, u128, ::U64x2, ::sconv);

#[cfg(not(all(feature = "c", target_arch = "arm", not(target_os = "ios"))))]
mod_!(__modsi3: i32, u32);

#[cfg(not(all(feature = "c", target_arch = "x86")))]
mod_!(__moddi3: i64, u64);

#[cfg(not(all(windows, target_pointer_width="64")))]
mod_!(__modti3: i128, u128);

#[cfg(all(windows, target_pointer_width="64"))]
mod_!(__modti3: i128, u128, ::U64x2, ::sconv);

#[cfg(not(all(feature = "c", target_arch = "arm", not(target_os = "ios"))))]
divmod!("C", __divmodsi4, __divsi3: i32);

#[cfg(target_arch = "arm")]
divmod!("aapcs", __divmoddi4, __divdi3: i64);

#[cfg(not(target_arch = "arm"))]
divmod!("C", __divmoddi4, __divdi3: i64);

#[cfg(test)]
mod tests {
    use qc::{U32, U64};

    check! {
        fn __divdi3(f: extern "C" fn(i64, i64) -> i64, n: U64, d: U64) -> Option<i64> {
            let (n, d) = (n.0 as i64, d.0 as i64);
            if d == 0 {
                None
            } else {
                Some(f(n, d))
            }
        }

        fn __moddi3(f: extern "C" fn(i64, i64) -> i64, n: U64, d: U64) -> Option<i64> {
            let (n, d) = (n.0 as i64, d.0 as i64);
            if d == 0 {
                None
            } else {
                Some(f(n, d))
            }
        }

        #[cfg(target_arch = "arm")]
        fn __divmoddi4(f: extern "aapcs" fn(i64, i64, &mut i64) -> i64,
                       n: U64,
                       d: U64) -> Option<(i64, i64)> {
            let (n, d) = (n.0 as i64, d.0 as i64);
            if d == 0 {
                None
            } else {
                let mut r = 0;
                let q = f(n, d, &mut r);
                Some((q, r))
            }
        }

        #[cfg(not(target_arch = "arm"))]
        fn __divmoddi4(f: extern "C" fn(i64, i64, &mut i64) -> i64,
                       n: U64,
                       d: U64) -> Option<(i64, i64)> {
            let (n, d) = (n.0 as i64, d.0 as i64);
            if d == 0 {
                None
            } else {
                let mut r = 0;
                let q = f(n, d, &mut r);
                Some((q, r))
            }
        }

        fn __divsi3(f: extern "C" fn(i32, i32) -> i32,
                    n: U32,
                    d: U32) -> Option<i32> {
            let (n, d) = (n.0 as i32, d.0 as i32);
            if d == 0 {
                None
            } else {
                Some(f(n, d))
            }
        }

        fn __modsi3(f: extern "C" fn(i32, i32) -> i32,
                    n: U32,
                    d: U32) -> Option<i32> {
            let (n, d) = (n.0 as i32, d.0 as i32);
            if d == 0 {
                None
            } else {
                Some(f(n, d))
            }
        }

        fn __divmodsi4(f: extern "C" fn(i32, i32, &mut i32) -> i32,
                       n: U32,
                       d: U32) -> Option<(i32, i32)> {
            let (n, d) = (n.0 as i32, d.0 as i32);
            if d == 0 {
                None
            } else {
                let mut r = 0;
                let q = f(n, d, &mut r);
                Some((q, r))
            }
        }
    }
}

#[cfg(test)]
#[cfg(all(not(windows),
          not(target_arch = "mips64"),
          not(target_arch = "mips64el"),
          target_pointer_width="64"))]
mod tests_i128 {
    use qc::U128;
    check! {

        fn __divti3(f: extern "C" fn(i128, i128) -> i128, n: U128, d: U128) -> Option<i128> {
            let (n, d) = (n.0 as i128, d.0 as i128);
            if d == 0 {
                None
            } else {
                Some(f(n, d))
            }
        }

        fn __modti3(f: extern "C" fn(i128, i128) -> i128, n: U128, d: U128) -> Option<i128> {
            let (n, d) = (n.0 as i128, d.0 as i128);
            if d == 0 {
                None
            } else {
                Some(f(n, d))
            }
        }
    }
}
<commit_msg>fix debug assertion in divdi3<commit_after>use int::Int;

macro_rules! div {
    ($intrinsic:ident: $ty:ty, $uty:ty) => {
        div!($intrinsic: $ty, $uty, $ty, |i| {i});
    };
    ($intrinsic:ident: $ty:ty, $uty:ty, $tyret:ty, $conv:expr) => {
        /// Returns `a / b`
        #[cfg_attr(not(test), no_mangle)]
        pub extern "C" fn $intrinsic(a: $ty, b: $ty) -> $tyret {
            let s_a = a >> (<$ty>::bits() - 1);
            let s_b = b >> (<$ty>::bits() - 1);
            // NOTE it's OK to overflow here because of the `as $uty` cast below
            // This whole operation is computing the absolute value of the inputs
            // So some overflow will happen when dealing with e.g. `i64::MIN`
            // where the absolute value is `(-i64::MIN) as u64`
            let a = (a ^ s_a).wrapping_sub(s_a);
            let b = (b ^ s_b).wrapping_sub(s_b);
            let s = s_a ^ s_b;

            let r = udiv!(a as $uty, b as $uty);
            ($conv)((r as $ty ^ s) - s)
        }
    }
}

macro_rules! mod_ {
    ($intrinsic:ident: $ty:ty, $uty:ty) => {
        mod_!($intrinsic: $ty, $uty, $ty, |i| {i});
    };
    ($intrinsic:ident: $ty:ty, $uty:ty, $tyret:ty, $conv:expr) => {
        /// Returns `a % b`
        #[cfg_attr(not(test), no_mangle)]
        pub extern "C" fn $intrinsic(a: $ty, b: $ty) -> $tyret {
            let s = b >> (<$ty>::bits() - 1);
            let b = (b ^ s) - s;
            let s = a >> (<$ty>::bits() - 1);
            let a = (a ^ s) - s;

            let r = urem!(a as $uty, b as $uty);
            ($conv)((r as $ty ^ s) - s)
        }
    }
}

macro_rules! divmod {
    ($abi:tt, $intrinsic:ident, $div:ident: $ty:ty) => {
        /// Returns `a / b` and sets `*rem = n % d`
        #[cfg_attr(not(test), no_mangle)]
        pub extern $abi fn $intrinsic(a: $ty, b: $ty, rem: &mut $ty) -> $ty {
            #[cfg(all(feature = "c", any(target_arch = "x86")))]
            extern {
                fn $div(a: $ty, b: $ty) -> $ty;
            }

            let r = match () {
                #[cfg(not(all(feature = "c", any(target_arch = "x86"))))]
                () => $div(a, b),
                #[cfg(all(feature = "c", any(target_arch = "x86")))]
                () => unsafe { $div(a, b) },
            };
            *rem = a - (r * b);
            r
        }
    }
}

#[cfg(not(all(feature = "c", target_arch = "arm", not(target_os = "ios"), not(thumbv6m))))]
div!(__divsi3: i32, u32);

#[cfg(not(all(feature = "c", target_arch = "x86")))]
div!(__divdi3: i64, u64);

#[cfg(not(all(windows, target_pointer_width="64")))]
div!(__divti3: i128, u128);

#[cfg(all(windows, target_pointer_width="64"))]
div!(__divti3: i128, u128, ::U64x2, ::sconv);

#[cfg(not(all(feature = "c", target_arch = "arm", not(target_os = "ios"))))]
mod_!(__modsi3: i32, u32);

#[cfg(not(all(feature = "c", target_arch = "x86")))]
mod_!(__moddi3: i64, u64);

#[cfg(not(all(windows, target_pointer_width="64")))]
mod_!(__modti3: i128, u128);

#[cfg(all(windows, target_pointer_width="64"))]
mod_!(__modti3: i128, u128, ::U64x2, ::sconv);

#[cfg(not(all(feature = "c", target_arch = "arm", not(target_os = "ios"))))]
divmod!("C", __divmodsi4, __divsi3: i32);

#[cfg(target_arch = "arm")]
divmod!("aapcs", __divmoddi4, __divdi3: i64);

#[cfg(not(target_arch = "arm"))]
divmod!("C", __divmoddi4, __divdi3: i64);

#[cfg(test)]
mod tests {
    use qc::{U32, U64};

    check! {
        fn __divdi3(f: extern "C" fn(i64, i64) -> i64, n: U64, d: U64) -> Option<i64> {
            let (n, d) = (n.0 as i64, d.0 as i64);
            if d == 0 {
                None
            } else {
                Some(f(n, d))
            }
        }

        fn __moddi3(f: extern "C" fn(i64, i64) -> i64, n: U64, d: U64) -> Option<i64> {
            let (n, d) = (n.0 as i64, d.0 as i64);
            if d == 0 {
                None
            } else {
                Some(f(n, d))
            }
        }

        #[cfg(target_arch = "arm")]
        fn __divmoddi4(f: extern "aapcs" fn(i64, i64, &mut i64) -> i64,
                       n: U64,
                       d: U64) -> Option<(i64, i64)> {
            let (n, d) = (n.0 as i64, d.0 as i64);
            if d == 0 {
                None
            } else {
                let mut r = 0;
                let q = f(n, d, &mut r);
                Some((q, r))
            }
        }

        #[cfg(not(target_arch = "arm"))]
        fn __divmoddi4(f: extern "C" fn(i64, i64, &mut i64) -> i64,
                       n: U64,
                       d: U64) -> Option<(i64, i64)> {
            let (n, d) = (n.0 as i64, d.0 as i64);
            if d == 0 {
                None
            } else {
                let mut r = 0;
                let q = f(n, d, &mut r);
                Some((q, r))
            }
        }

        fn __divsi3(f: extern "C" fn(i32, i32) -> i32,
                    n: U32,
                    d: U32) -> Option<i32> {
            let (n, d) = (n.0 as i32, d.0 as i32);
            if d == 0 {
                None
            } else {
                Some(f(n, d))
            }
        }

        fn __modsi3(f: extern "C" fn(i32, i32) -> i32,
                    n: U32,
                    d: U32) -> Option<i32> {
            let (n, d) = (n.0 as i32, d.0 as i32);
            if d == 0 {
                None
            } else {
                Some(f(n, d))
            }
        }

        fn __divmodsi4(f: extern "C" fn(i32, i32, &mut i32) -> i32,
                       n: U32,
                       d: U32) -> Option<(i32, i32)> {
            let (n, d) = (n.0 as i32, d.0 as i32);
            if d == 0 {
                None
            } else {
                let mut r = 0;
                let q = f(n, d, &mut r);
                Some((q, r))
            }
        }
    }
}

#[cfg(test)]
#[cfg(all(not(windows),
          not(target_arch = "mips64"),
          not(target_arch = "mips64el"),
          target_pointer_width="64"))]
mod tests_i128 {
    use qc::U128;
    check! {

        fn __divti3(f: extern "C" fn(i128, i128) -> i128, n: U128, d: U128) -> Option<i128> {
            let (n, d) = (n.0 as i128, d.0 as i128);
            if d == 0 {
                None
            } else {
                Some(f(n, d))
            }
        }

        fn __modti3(f: extern "C" fn(i128, i128) -> i128, n: U128, d: U128) -> Option<i128> {
            let (n, d) = (n.0 as i128, d.0 as i128);
            if d == 0 {
                None
            } else {
                Some(f(n, d))
            }
        }
    }
}
<|endoftext|>


<commit_before>//! Basic types to build the parsers

use self::Needed::*;
use crate::error::{self, ErrorKind};
use core::num::NonZeroUsize;

/// Holds the result of parsing functions
///
/// It depends on the input type `I`, the output type `O`, and the error type `E`
/// (by default `(I, nom::ErrorKind)`)
///
/// The `Ok` side is a pair containing the remainder of the input (the part of the data that
/// was not parsed) and the produced value. The `Err` side contains an instance of `nom::Err`.
///
/// Outside of the parsing code, you can use the [Finish::finish] method to convert
/// it to a more common result type
pub type IResult<I, O, E = error::Error<I>> = Result<(I, O), Err<E>>;

/// Helper trait to convert a parser's result to a more manageable type
pub trait Finish<I, O, E> {
  /// converts the parser's result to a type that is more consumable by error
  /// management libraries. It keeps the same `Ok` branch, and merges `Err::Error`
  /// and `Err::Failure` into the `Err` side.
  ///
  /// *warning*: if the result is `Err(Err::Incomplete(_))`, this method will panic.
  /// - "complete" parsers: It will not be an issue, `Incomplete` is never used
  /// - "streaming" parsers: `Incomplete` will be returned if there's not enough data
  /// for the parser to decide, and you should gather more data before parsing again.
  /// Once the parser returns either `Ok(_)`, `Err(Err::Error(_))` or `Err(Err::Failure(_))`,
  /// you can get out of the parsing loop and call `finish()` on the parser's result
  fn finish(self) -> Result<(I, O), E>;
}

impl<I, O, E> Finish<I, O, E> for IResult<I, O, E> {
  fn finish(self) -> Result<(I, O), E> {
    match self {
            Ok(res) => Ok(res),
            Err(Err::Error(e)) | Err(Err::Failure(e)) => Err(e),
            Err(Err::Incomplete(_)) => {
                panic!("Cannot call `finish()` on `Err(Err::Incomplete(_))`: this result means that the parser does not have enough data to decide, you should gather more data and try to reapply  the parser instead")
            }
        }
  }
}

/// Contains information on needed data if a parser returned `Incomplete`
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Needed {
  /// Needs more data, but we do not know how much
  Unknown,
  /// Contains the required data size in bytes
  Size(NonZeroUsize),
}

impl Needed {
  /// Creates `Needed` instance, returns `Needed::Unknown` if the argument is zero
  pub fn new(s: usize) -> Self {
    match NonZeroUsize::new(s) {
      Some(sz) => Needed::Size(sz),
      None => Needed::Unknown,
    }
  }

  /// Indicates if we know how many bytes we need
  pub fn is_known(&self) -> bool {
    *self != Unknown
  }

  /// Maps a `Needed` to `Needed` by applying a function to a contained `Size` value.
  #[inline]
  pub fn map<F: Fn(NonZeroUsize) -> usize>(self, f: F) -> Needed {
    match self {
      Unknown => Unknown,
      Size(n) => Needed::new(f(n)),
    }
  }
}

/// The `Err` enum indicates the parser was not successful
///
/// It has three cases:
///
/// * `Incomplete` indicates that more data is needed to decide. The `Needed` enum
/// can contain how many additional bytes are necessary. If you are sure your parser
/// is working on full data, you can wrap your parser with the `complete` combinator
/// to transform that case in `Error`
/// * `Error` means some parser did not succeed, but another one might (as an example,
/// when testing different branches of an `alt` combinator)
/// * `Failure` indicates an unrecoverable error. As an example, if you recognize a prefix
/// to decide on the next parser to apply, and that parser fails, you know there's no need
/// to try other parsers, you were already in the right branch, so the data is invalid
///
#[derive(Debug, Clone, PartialEq)]
pub enum Err<E> {
  /// There was not enough data
  Incomplete(Needed),
  /// The parser had an error (recoverable)
  Error(E),
  /// The parser had an unrecoverable error: we got to the right
  /// branch and we know other branches won't work, so backtrack
  /// as fast as possible
  Failure(E),
}

impl<E> Err<E> {
  /// Tests if the result is Incomplete
  pub fn is_incomplete(&self) -> bool {
    if let Err::Incomplete(_) = self {
      true
    } else {
      false
    }
  }

  /// Applies the given function to the inner error
  pub fn map<E2, F>(self, f: F) -> Err<E2>
  where
    F: FnOnce(E) -> E2,
  {
    match self {
      Err::Incomplete(n) => Err::Incomplete(n),
      Err::Failure(t) => Err::Failure(f(t)),
      Err::Error(t) => Err::Error(f(t)),
    }
  }

  /// Automatically converts between errors if the underlying type supports it
  pub fn convert<F>(e: Err<F>) -> Self
  where
    E: From<F>,
  {
    e.map(Into::into)
  }
}

impl<T> Err<(T, ErrorKind)> {
  /// Maps `Err<(T, ErrorKind)>` to `Err<(U, ErrorKind)>` with the given `F: T -> U`
  pub fn map_input<U, F>(self, f: F) -> Err<(U, ErrorKind)>
  where
    F: FnOnce(T) -> U,
  {
    match self {
      Err::Incomplete(n) => Err::Incomplete(n),
      Err::Failure((input, k)) => Err::Failure((f(input), k)),
      Err::Error((input, k)) => Err::Error((f(input), k)),
    }
  }
}

#[cfg(feature = "alloc")]
use crate::lib::std::{borrow::ToOwned, string::String, vec::Vec};
#[cfg(feature = "alloc")]
impl Err<(&[u8], ErrorKind)> {
  /// Obtaining ownership
  #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
  pub fn to_owned(self) -> Err<(Vec<u8>, ErrorKind)> {
    self.map_input(ToOwned::to_owned)
  }
}

#[cfg(feature = "alloc")]
impl Err<(&str, ErrorKind)> {
  /// Automatically converts between errors if the underlying type supports it
  #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
  pub fn to_owned(self) -> Err<(String, ErrorKind)> {
    self.map_input(ToOwned::to_owned)
  }
}

impl<E: Eq> Eq for Err<E> {}

#[cfg(feature = "std")]
use std::fmt;

#[cfg(feature = "std")]
impl<E> fmt::Display for Err<E>
where
  E: fmt::Debug,
{
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    match self {
      Err::Incomplete(Needed::Size(u)) => write!(f, "Parsing requires {} bytes/chars", u),
      Err::Incomplete(Needed::Unknown) => write!(f, "Parsing requires more data"),
      Err::Failure(c) => write!(f, "Parsing Failure: {:?}", c),
      Err::Error(c) => write!(f, "Parsing Error: {:?}", c),
    }
  }
}

#[cfg(feature = "std")]
use std::error::Error;

#[cfg(feature = "std")]
impl<E> Error for Err<E>
where
  E: fmt::Debug,
{
  fn source(&self) -> Option<&(dyn Error + 'static)> {
    None // no underlying error
  }
}

/// All nom parsers implement this trait
pub trait Parser<I, O, E> {
  /// A parser takes in input type, and returns a `Result` containing
  /// either the remaining input and the output value, or an error
  fn parse(&mut self, input: I) -> IResult<I, O, E>;

  /// Maps a function over the result of a parser
  fn map<G, O2>(self, g: G) -> Map<Self, G, O>
  where
    G: Fn(O) -> O2,
    Self: core::marker::Sized,
  {
    Map {
      f: self,
      g,
      phantom: core::marker::PhantomData,
    }
  }

  /// Creates a second parser from the output of the first one, then apply over the rest of the input
  fn flat_map<G, H, O2>(self, g: G) -> FlatMap<Self, G, O>
  where
    G: Fn(O) -> H,
    H: Parser<I, O2, E>,
    Self: core::marker::Sized,
  {
    FlatMap {
      f: self,
      g,
      phantom: core::marker::PhantomData,
    }
  }

  /// Applies a second parser over the output of the first one
  fn and_then<G, O2>(self, g: G) -> AndThen<Self, G, O>
  where
    G: Parser<O, O2, E>,
    Self: core::marker::Sized,
  {
    AndThen {
      f: self,
      g,
      phantom: core::marker::PhantomData,
    }
  }

  /// Applies a second parser after the first one, return their results as a tuple
  fn and<G, O2>(self, g: G) -> And<Self, G>
  where
    G: Parser<I, O2, E>,
    Self: core::marker::Sized,
  {
    And { f: self, g }
  }

  /// Applies a second parser over the input if the first one failed
  fn or<G>(self, g: G) -> Or<Self, G>
  where
    G: Parser<I, O, E>,
    Self: core::marker::Sized,
  {
    Or { f: self, g }
  }
}

impl<'a, I, O, E, F> Parser<I, O, E> for F
where
  F: FnMut(I) -> IResult<I, O, E> + 'a,
{
  fn parse(&mut self, i: I) -> IResult<I, O, E> {
    self(i)
  }
}

/// Implementation of `Parser:::map`
pub struct Map<F, G, O1> {
  f: F,
  g: G,
  phantom: core::marker::PhantomData<O1>,
}

impl<'a, I, O1, O2, E, F: Parser<I, O1, E>, G: Fn(O1) -> O2> Parser<I, O2, E> for Map<F, G, O1> {
  fn parse(&mut self, i: I) -> IResult<I, O2, E> {
    match self.f.parse(i) {
      Err(e) => Err(e),
      Ok((i, o)) => Ok((i, (self.g)(o))),
    }
  }
}

/// Implementation of `Parser::flat_map`
pub struct FlatMap<F, G, O1> {
  f: F,
  g: G,
  phantom: core::marker::PhantomData<O1>,
}

impl<'a, I, O1, O2, E, F: Parser<I, O1, E>, G: Fn(O1) -> H, H: Parser<I, O2, E>> Parser<I, O2, E>
  for FlatMap<F, G, O1>
{
  fn parse(&mut self, i: I) -> IResult<I, O2, E> {
    let (i, o1) = self.f.parse(i)?;
    (self.g)(o1).parse(i)
  }
}

/// Implementation of `Parser::and_then`
pub struct AndThen<F, G, O1> {
  f: F,
  g: G,
  phantom: core::marker::PhantomData<O1>,
}

impl<'a, I, O1, O2, E, F: Parser<I, O1, E>, G: Parser<O1, O2, E>> Parser<I, O2, E>
  for AndThen<F, G, O1>
{
  fn parse(&mut self, i: I) -> IResult<I, O2, E> {
    let (i, o1) = self.f.parse(i)?;
    let (_, o2) = self.g.parse(o1)?;
    Ok((i, o2))
  }
}

/// Implementation of `Parser::and`
pub struct And<F, G> {
  f: F,
  g: G,
}

impl<'a, I, O1, O2, E, F: Parser<I, O1, E>, G: Parser<I, O2, E>> Parser<I, (O1, O2), E>
  for And<F, G>
{
  fn parse(&mut self, i: I) -> IResult<I, (O1, O2), E> {
    let (i, o1) = self.f.parse(i)?;
    let (i, o2) = self.g.parse(i)?;
    Ok((i, (o1, o2)))
  }
}

/// Implementation of `Parser::or`
pub struct Or<F, G> {
  f: F,
  g: G,
}

impl<'a, I: Clone, O, E: crate::error::ParseError<I>, F: Parser<I, O, E>, G: Parser<I, O, E>>
  Parser<I, O, E> for Or<F, G>
{
  fn parse(&mut self, i: I) -> IResult<I, O, E> {
    match self.f.parse(i.clone()) {
      Err(Err::Error(e1)) => match self.g.parse(i) {
        Err(Err::Error(e2)) => Err(Err::Error(e1.or(e2))),
        res => res,
      },
      res => res,
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use crate::error::ErrorKind;

  #[doc(hidden)]
  #[macro_export]
  macro_rules! assert_size (
    ($t:ty, $sz:expr) => (
      assert_eq!(crate::lib::std::mem::size_of::<$t>(), $sz);
    );
  );

  #[test]
  #[cfg(target_pointer_width = "64")]
  fn size_test() {
    assert_size!(IResult<&[u8], &[u8], (&[u8], u32)>, 40);
    assert_size!(IResult<&str, &str, u32>, 40);
    assert_size!(Needed, 8);
    assert_size!(Err<u32>, 16);
    assert_size!(ErrorKind, 1);
  }

  #[test]
  fn err_map_test() {
    let e = Err::Error(1);
    assert_eq!(e.map(|v| v + 1), Err::Error(2));
  }
}
<commit_msg>Enable Display impl of Err on no-std configuration<commit_after>//! Basic types to build the parsers

use self::Needed::*;
use crate::error::{self, ErrorKind};
use crate::lib::std::fmt;
use core::num::NonZeroUsize;

/// Holds the result of parsing functions
///
/// It depends on the input type `I`, the output type `O`, and the error type `E`
/// (by default `(I, nom::ErrorKind)`)
///
/// The `Ok` side is a pair containing the remainder of the input (the part of the data that
/// was not parsed) and the produced value. The `Err` side contains an instance of `nom::Err`.
///
/// Outside of the parsing code, you can use the [Finish::finish] method to convert
/// it to a more common result type
pub type IResult<I, O, E = error::Error<I>> = Result<(I, O), Err<E>>;

/// Helper trait to convert a parser's result to a more manageable type
pub trait Finish<I, O, E> {
  /// converts the parser's result to a type that is more consumable by error
  /// management libraries. It keeps the same `Ok` branch, and merges `Err::Error`
  /// and `Err::Failure` into the `Err` side.
  ///
  /// *warning*: if the result is `Err(Err::Incomplete(_))`, this method will panic.
  /// - "complete" parsers: It will not be an issue, `Incomplete` is never used
  /// - "streaming" parsers: `Incomplete` will be returned if there's not enough data
  /// for the parser to decide, and you should gather more data before parsing again.
  /// Once the parser returns either `Ok(_)`, `Err(Err::Error(_))` or `Err(Err::Failure(_))`,
  /// you can get out of the parsing loop and call `finish()` on the parser's result
  fn finish(self) -> Result<(I, O), E>;
}

impl<I, O, E> Finish<I, O, E> for IResult<I, O, E> {
  fn finish(self) -> Result<(I, O), E> {
    match self {
            Ok(res) => Ok(res),
            Err(Err::Error(e)) | Err(Err::Failure(e)) => Err(e),
            Err(Err::Incomplete(_)) => {
                panic!("Cannot call `finish()` on `Err(Err::Incomplete(_))`: this result means that the parser does not have enough data to decide, you should gather more data and try to reapply  the parser instead")
            }
        }
  }
}

/// Contains information on needed data if a parser returned `Incomplete`
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Needed {
  /// Needs more data, but we do not know how much
  Unknown,
  /// Contains the required data size in bytes
  Size(NonZeroUsize),
}

impl Needed {
  /// Creates `Needed` instance, returns `Needed::Unknown` if the argument is zero
  pub fn new(s: usize) -> Self {
    match NonZeroUsize::new(s) {
      Some(sz) => Needed::Size(sz),
      None => Needed::Unknown,
    }
  }

  /// Indicates if we know how many bytes we need
  pub fn is_known(&self) -> bool {
    *self != Unknown
  }

  /// Maps a `Needed` to `Needed` by applying a function to a contained `Size` value.
  #[inline]
  pub fn map<F: Fn(NonZeroUsize) -> usize>(self, f: F) -> Needed {
    match self {
      Unknown => Unknown,
      Size(n) => Needed::new(f(n)),
    }
  }
}

/// The `Err` enum indicates the parser was not successful
///
/// It has three cases:
///
/// * `Incomplete` indicates that more data is needed to decide. The `Needed` enum
/// can contain how many additional bytes are necessary. If you are sure your parser
/// is working on full data, you can wrap your parser with the `complete` combinator
/// to transform that case in `Error`
/// * `Error` means some parser did not succeed, but another one might (as an example,
/// when testing different branches of an `alt` combinator)
/// * `Failure` indicates an unrecoverable error. As an example, if you recognize a prefix
/// to decide on the next parser to apply, and that parser fails, you know there's no need
/// to try other parsers, you were already in the right branch, so the data is invalid
///
#[derive(Debug, Clone, PartialEq)]
pub enum Err<E> {
  /// There was not enough data
  Incomplete(Needed),
  /// The parser had an error (recoverable)
  Error(E),
  /// The parser had an unrecoverable error: we got to the right
  /// branch and we know other branches won't work, so backtrack
  /// as fast as possible
  Failure(E),
}

impl<E> Err<E> {
  /// Tests if the result is Incomplete
  pub fn is_incomplete(&self) -> bool {
    if let Err::Incomplete(_) = self {
      true
    } else {
      false
    }
  }

  /// Applies the given function to the inner error
  pub fn map<E2, F>(self, f: F) -> Err<E2>
  where
    F: FnOnce(E) -> E2,
  {
    match self {
      Err::Incomplete(n) => Err::Incomplete(n),
      Err::Failure(t) => Err::Failure(f(t)),
      Err::Error(t) => Err::Error(f(t)),
    }
  }

  /// Automatically converts between errors if the underlying type supports it
  pub fn convert<F>(e: Err<F>) -> Self
  where
    E: From<F>,
  {
    e.map(Into::into)
  }
}

impl<T> Err<(T, ErrorKind)> {
  /// Maps `Err<(T, ErrorKind)>` to `Err<(U, ErrorKind)>` with the given `F: T -> U`
  pub fn map_input<U, F>(self, f: F) -> Err<(U, ErrorKind)>
  where
    F: FnOnce(T) -> U,
  {
    match self {
      Err::Incomplete(n) => Err::Incomplete(n),
      Err::Failure((input, k)) => Err::Failure((f(input), k)),
      Err::Error((input, k)) => Err::Error((f(input), k)),
    }
  }
}

#[cfg(feature = "alloc")]
use crate::lib::std::{borrow::ToOwned, string::String, vec::Vec};
#[cfg(feature = "alloc")]
impl Err<(&[u8], ErrorKind)> {
  /// Obtaining ownership
  #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
  pub fn to_owned(self) -> Err<(Vec<u8>, ErrorKind)> {
    self.map_input(ToOwned::to_owned)
  }
}

#[cfg(feature = "alloc")]
impl Err<(&str, ErrorKind)> {
  /// Automatically converts between errors if the underlying type supports it
  #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
  pub fn to_owned(self) -> Err<(String, ErrorKind)> {
    self.map_input(ToOwned::to_owned)
  }
}

impl<E: Eq> Eq for Err<E> {}

impl<E> fmt::Display for Err<E>
where
  E: fmt::Debug,
{
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    match self {
      Err::Incomplete(Needed::Size(u)) => write!(f, "Parsing requires {} bytes/chars", u),
      Err::Incomplete(Needed::Unknown) => write!(f, "Parsing requires more data"),
      Err::Failure(c) => write!(f, "Parsing Failure: {:?}", c),
      Err::Error(c) => write!(f, "Parsing Error: {:?}", c),
    }
  }
}

#[cfg(feature = "std")]
use std::error::Error;

#[cfg(feature = "std")]
impl<E> Error for Err<E>
where
  E: fmt::Debug,
{
  fn source(&self) -> Option<&(dyn Error + 'static)> {
    None // no underlying error
  }
}

/// All nom parsers implement this trait
pub trait Parser<I, O, E> {
  /// A parser takes in input type, and returns a `Result` containing
  /// either the remaining input and the output value, or an error
  fn parse(&mut self, input: I) -> IResult<I, O, E>;

  /// Maps a function over the result of a parser
  fn map<G, O2>(self, g: G) -> Map<Self, G, O>
  where
    G: Fn(O) -> O2,
    Self: core::marker::Sized,
  {
    Map {
      f: self,
      g,
      phantom: core::marker::PhantomData,
    }
  }

  /// Creates a second parser from the output of the first one, then apply over the rest of the input
  fn flat_map<G, H, O2>(self, g: G) -> FlatMap<Self, G, O>
  where
    G: Fn(O) -> H,
    H: Parser<I, O2, E>,
    Self: core::marker::Sized,
  {
    FlatMap {
      f: self,
      g,
      phantom: core::marker::PhantomData,
    }
  }

  /// Applies a second parser over the output of the first one
  fn and_then<G, O2>(self, g: G) -> AndThen<Self, G, O>
  where
    G: Parser<O, O2, E>,
    Self: core::marker::Sized,
  {
    AndThen {
      f: self,
      g,
      phantom: core::marker::PhantomData,
    }
  }

  /// Applies a second parser after the first one, return their results as a tuple
  fn and<G, O2>(self, g: G) -> And<Self, G>
  where
    G: Parser<I, O2, E>,
    Self: core::marker::Sized,
  {
    And { f: self, g }
  }

  /// Applies a second parser over the input if the first one failed
  fn or<G>(self, g: G) -> Or<Self, G>
  where
    G: Parser<I, O, E>,
    Self: core::marker::Sized,
  {
    Or { f: self, g }
  }
}

impl<'a, I, O, E, F> Parser<I, O, E> for F
where
  F: FnMut(I) -> IResult<I, O, E> + 'a,
{
  fn parse(&mut self, i: I) -> IResult<I, O, E> {
    self(i)
  }
}

/// Implementation of `Parser:::map`
pub struct Map<F, G, O1> {
  f: F,
  g: G,
  phantom: core::marker::PhantomData<O1>,
}

impl<'a, I, O1, O2, E, F: Parser<I, O1, E>, G: Fn(O1) -> O2> Parser<I, O2, E> for Map<F, G, O1> {
  fn parse(&mut self, i: I) -> IResult<I, O2, E> {
    match self.f.parse(i) {
      Err(e) => Err(e),
      Ok((i, o)) => Ok((i, (self.g)(o))),
    }
  }
}

/// Implementation of `Parser::flat_map`
pub struct FlatMap<F, G, O1> {
  f: F,
  g: G,
  phantom: core::marker::PhantomData<O1>,
}

impl<'a, I, O1, O2, E, F: Parser<I, O1, E>, G: Fn(O1) -> H, H: Parser<I, O2, E>> Parser<I, O2, E>
  for FlatMap<F, G, O1>
{
  fn parse(&mut self, i: I) -> IResult<I, O2, E> {
    let (i, o1) = self.f.parse(i)?;
    (self.g)(o1).parse(i)
  }
}

/// Implementation of `Parser::and_then`
pub struct AndThen<F, G, O1> {
  f: F,
  g: G,
  phantom: core::marker::PhantomData<O1>,
}

impl<'a, I, O1, O2, E, F: Parser<I, O1, E>, G: Parser<O1, O2, E>> Parser<I, O2, E>
  for AndThen<F, G, O1>
{
  fn parse(&mut self, i: I) -> IResult<I, O2, E> {
    let (i, o1) = self.f.parse(i)?;
    let (_, o2) = self.g.parse(o1)?;
    Ok((i, o2))
  }
}

/// Implementation of `Parser::and`
pub struct And<F, G> {
  f: F,
  g: G,
}

impl<'a, I, O1, O2, E, F: Parser<I, O1, E>, G: Parser<I, O2, E>> Parser<I, (O1, O2), E>
  for And<F, G>
{
  fn parse(&mut self, i: I) -> IResult<I, (O1, O2), E> {
    let (i, o1) = self.f.parse(i)?;
    let (i, o2) = self.g.parse(i)?;
    Ok((i, (o1, o2)))
  }
}

/// Implementation of `Parser::or`
pub struct Or<F, G> {
  f: F,
  g: G,
}

impl<'a, I: Clone, O, E: crate::error::ParseError<I>, F: Parser<I, O, E>, G: Parser<I, O, E>>
  Parser<I, O, E> for Or<F, G>
{
  fn parse(&mut self, i: I) -> IResult<I, O, E> {
    match self.f.parse(i.clone()) {
      Err(Err::Error(e1)) => match self.g.parse(i) {
        Err(Err::Error(e2)) => Err(Err::Error(e1.or(e2))),
        res => res,
      },
      res => res,
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use crate::error::ErrorKind;

  #[doc(hidden)]
  #[macro_export]
  macro_rules! assert_size (
    ($t:ty, $sz:expr) => (
      assert_eq!(crate::lib::std::mem::size_of::<$t>(), $sz);
    );
  );

  #[test]
  #[cfg(target_pointer_width = "64")]
  fn size_test() {
    assert_size!(IResult<&[u8], &[u8], (&[u8], u32)>, 40);
    assert_size!(IResult<&str, &str, u32>, 40);
    assert_size!(Needed, 8);
    assert_size!(Err<u32>, 16);
    assert_size!(ErrorKind, 1);
  }

  #[test]
  fn err_map_test() {
    let e = Err::Error(1);
    assert_eq!(e.map(|v| v + 1), Err::Error(2));
  }
}
<|endoftext|>


<commit_before>use util::Point;

pub struct Actor {
    name: String,
    pos: Point,
    health: int,
    max_health: int,
    repr: char,
}

impl Actor {

    pub fn new(name: String, pos: Point, max_health: int, repr: char) -> Actor {
        Actor {
            name: name,
            pos: pos,
            health: max_health,
            max_health: max_health,
            repr: repr,
        }
    }

    pub fn pos(&self) -> &Point {
        &self.pos
    }

    pub fn hurt(&mut self, amount: int) {
        self.health -= amount;
    }

    pub fn heal(&mut self, amount: int) {
        self.health += amount;
    }

    pub fn kill(&mut self, amount: int) {
        self.health = 0;
    }

}
<commit_msg>Add is_dead() to Actor<commit_after>use util::Point;

pub struct Actor {
    name: String,
    pos: Point,
    health: int,
    max_health: int,
    repr: char,
}

impl Actor {

    pub fn new(name: String, pos: Point, max_health: int, repr: char) -> Actor {
        Actor {
            name: name,
            pos: pos,
            health: max_health,
            max_health: max_health,
            repr: repr,
        }
    }

    pub fn pos(&self) -> &Point {
        &self.pos
    }

    pub fn is_dead(&self) -> bool {
        self.health <= 0
    }

    pub fn hurt(&mut self, amount: int) {
        self.health -= amount;
    }

    pub fn heal(&mut self, amount: int) {
        self.health += amount;
    }

    pub fn kill(&mut self, amount: int) {
        self.health = 0;
    }

}
<|endoftext|>


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

use std::collections::HashSet;

use build::{Build, Compiler};

#[derive(Hash, Eq, PartialEq, Clone, Debug)]
pub struct Step<'a> {
    pub src: Source<'a>,
    pub target: &'a str,
}

macro_rules! targets {
    ($m:ident) => {
        $m! {
            (rustc, Rustc { stage: u32 }),
            (libstd, Libstd { stage: u32, compiler: Compiler<'a> }),
            (librustc, Librustc { stage: u32, compiler: Compiler<'a> }),
            (llvm, Llvm { _dummy: () }),
            (compiler_rt, CompilerRt { _dummy: () }),
        }
    }
}

macro_rules! item { ($a:item) => ($a) }

macro_rules! define_source {
    ($(($short:ident, $name:ident { $($args:tt)* }),)*) => {
        item! {
            #[derive(Hash, Eq, PartialEq, Clone, Debug)]
            pub enum Source<'a> {
                $($name { $($args)* }),*
            }
        }
    }
}

targets!(define_source);

pub fn all(build: &Build) -> Vec<Step> {
    let mut ret = Vec::new();
    let mut all = HashSet::new();
    for target in top_level(build) {
        fill(build, &target, &mut ret, &mut all);
    }
    return ret;

    fn fill<'a>(build: &'a Build,
                target: &Step<'a>,
                ret: &mut Vec<Step<'a>>,
                set: &mut HashSet<Step<'a>>) {
        if set.insert(target.clone()) {
            for dep in target.deps(build) {
                fill(build, &dep, ret, set);
            }
            ret.push(target.clone());
        }
    }
}

fn top_level(build: &Build) -> Vec<Step> {
    let mut targets = Vec::new();
    let stage = build.flags.stage.unwrap_or(2);

    let host = Step {
        src: Source::Llvm { _dummy: () },
        target: build.flags.host.iter().next()
                     .unwrap_or(&build.config.build),
    };
    let target = Step {
        src: Source::Llvm { _dummy: () },
        target: build.flags.target.iter().next().map(|x| &x[..])
                     .unwrap_or(host.target)
    };

    add_steps(build, stage, &host, &target, &mut targets);

    if targets.len() == 0 {
        let t = Step {
            src: Source::Llvm { _dummy: () },
            target: &build.config.build,
        };
        for host in build.config.host.iter() {
            if !build.flags.host.contains(host) {
                continue
            }
            let host = t.target(host);
            targets.push(host.librustc(stage, t.compiler(stage)));
            for target in build.config.target.iter() {
                if !build.flags.target.contains(target) {
                    continue
                }
                targets.push(host.target(target)
                                 .libstd(stage, t.compiler(stage)));
            }
        }
    }

    return targets

}

fn add_steps<'a>(build: &'a Build,
                 stage: u32,
                 host: &Step<'a>,
                 target: &Step<'a>,
                 targets: &mut Vec<Step<'a>>) {
    for step in build.flags.step.iter() {
        let compiler = host.compiler(stage);
        match &step[..] {
            "libstd" => targets.push(target.libstd(stage, compiler)),
            "librustc" => targets.push(target.librustc(stage, compiler)),
            "rustc" => targets.push(host.rustc(stage)),
            "llvm" => targets.push(target.llvm(())),
            "compiler-rt" => targets.push(target.compiler_rt(())),
            _ => panic!("unknown build target: `{}`", step),
        }
    }
}

macro_rules! constructors {
    ($(($short:ident, $name:ident { $($arg:ident: $t:ty),* }),)*) => {$(
        fn $short(&self, $($arg: $t),*) -> Step<'a> {
            Step {
                src: Source::$name { $($arg: $arg),* },
                target: self.target,
            }
        }
    )*}
}

impl<'a> Step<'a> {
    fn compiler(&self, stage: u32) -> Compiler<'a> {
        Compiler::new(stage, self.target)
    }

    fn target(&self, target: &'a str) -> Step<'a> {
        Step { target: target, src: self.src.clone() }
    }

    targets!(constructors);

    pub fn deps(&self, build: &'a Build) -> Vec<Step<'a>> {
        match self.src {
            Source::Rustc { stage: 0 } => {
                assert!(self.target == build.config.build);
                Vec::new()
            }
            Source::Rustc { stage } => {
                let compiler = Compiler::new(stage - 1, &build.config.build);
                vec![self.librustc(stage - 1, compiler)]
            }
            Source::Librustc { stage, compiler } => {
                vec![self.libstd(stage, compiler), self.llvm(())]
            }
            Source::Libstd { stage: _, compiler } => {
                vec![self.compiler_rt(()),
                     self.rustc(compiler.stage).target(compiler.host)]
            }
            Source::CompilerRt { _dummy } => {
                vec![self.llvm(()).target(&build.config.build)]
            }
            Source::Llvm { _dummy } => Vec::new(),
        }
    }
}
<commit_msg>rustbuild: Document what steps are<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::collections::HashSet;

use build::{Build, Compiler};

#[derive(Hash, Eq, PartialEq, Clone, Debug)]
pub struct Step<'a> {
    pub src: Source<'a>,
    pub target: &'a str,
}

macro_rules! targets {
    ($m:ident) => {
        $m! {
            // Step representing building the stageN compiler. This is just the
            // compiler executable itself, not any of the support libraries
            (rustc, Rustc { stage: u32 }),

            // Steps for the two main cargo builds, one for the standard library
            // and one for the compiler itself. These are parameterized over the
            // stage output they're going to be placed in along with the
            // compiler which is producing the copy of libstd or librustc
            (libstd, Libstd { stage: u32, compiler: Compiler<'a> }),
            (librustc, Librustc { stage: u32, compiler: Compiler<'a> }),

            // Steps for long-running native builds. Ideally these wouldn't
            // actually exist and would be part of build scripts, but for now
            // these are here.
            //
            // There aren't really any parameters to this, but empty structs
            // with braces are unstable so we just pick something that works.
            (llvm, Llvm { _dummy: () }),
            (compiler_rt, CompilerRt { _dummy: () }),
        }
    }
}

macro_rules! item { ($a:item) => ($a) }

macro_rules! define_source {
    ($(($short:ident, $name:ident { $($args:tt)* }),)*) => {
        item! {
            #[derive(Hash, Eq, PartialEq, Clone, Debug)]
            pub enum Source<'a> {
                $($name { $($args)* }),*
            }
        }
    }
}

targets!(define_source);

pub fn all(build: &Build) -> Vec<Step> {
    let mut ret = Vec::new();
    let mut all = HashSet::new();
    for target in top_level(build) {
        fill(build, &target, &mut ret, &mut all);
    }
    return ret;

    fn fill<'a>(build: &'a Build,
                target: &Step<'a>,
                ret: &mut Vec<Step<'a>>,
                set: &mut HashSet<Step<'a>>) {
        if set.insert(target.clone()) {
            for dep in target.deps(build) {
                fill(build, &dep, ret, set);
            }
            ret.push(target.clone());
        }
    }
}

fn top_level(build: &Build) -> Vec<Step> {
    let mut targets = Vec::new();
    let stage = build.flags.stage.unwrap_or(2);

    let host = Step {
        src: Source::Llvm { _dummy: () },
        target: build.flags.host.iter().next()
                     .unwrap_or(&build.config.build),
    };
    let target = Step {
        src: Source::Llvm { _dummy: () },
        target: build.flags.target.iter().next().map(|x| &x[..])
                     .unwrap_or(host.target)
    };

    add_steps(build, stage, &host, &target, &mut targets);

    if targets.len() == 0 {
        let t = Step {
            src: Source::Llvm { _dummy: () },
            target: &build.config.build,
        };
        for host in build.config.host.iter() {
            if !build.flags.host.contains(host) {
                continue
            }
            let host = t.target(host);
            targets.push(host.librustc(stage, t.compiler(stage)));
            for target in build.config.target.iter() {
                if !build.flags.target.contains(target) {
                    continue
                }
                targets.push(host.target(target)
                                 .libstd(stage, t.compiler(stage)));
            }
        }
    }

    return targets

}

fn add_steps<'a>(build: &'a Build,
                 stage: u32,
                 host: &Step<'a>,
                 target: &Step<'a>,
                 targets: &mut Vec<Step<'a>>) {
    for step in build.flags.step.iter() {
        let compiler = host.compiler(stage);
        match &step[..] {
            "libstd" => targets.push(target.libstd(stage, compiler)),
            "librustc" => targets.push(target.librustc(stage, compiler)),
            "rustc" => targets.push(host.rustc(stage)),
            "llvm" => targets.push(target.llvm(())),
            "compiler-rt" => targets.push(target.compiler_rt(())),
            _ => panic!("unknown build target: `{}`", step),
        }
    }
}

macro_rules! constructors {
    ($(($short:ident, $name:ident { $($arg:ident: $t:ty),* }),)*) => {$(
        fn $short(&self, $($arg: $t),*) -> Step<'a> {
            Step {
                src: Source::$name { $($arg: $arg),* },
                target: self.target,
            }
        }
    )*}
}

impl<'a> Step<'a> {
    fn compiler(&self, stage: u32) -> Compiler<'a> {
        Compiler::new(stage, self.target)
    }

    fn target(&self, target: &'a str) -> Step<'a> {
        Step { target: target, src: self.src.clone() }
    }

    targets!(constructors);

    pub fn deps(&self, build: &'a Build) -> Vec<Step<'a>> {
        match self.src {
            Source::Rustc { stage: 0 } => {
                assert!(self.target == build.config.build);
                Vec::new()
            }
            Source::Rustc { stage } => {
                let compiler = Compiler::new(stage - 1, &build.config.build);
                vec![self.librustc(stage - 1, compiler)]
            }
            Source::Librustc { stage, compiler } => {
                vec![self.libstd(stage, compiler), self.llvm(())]
            }
            Source::Libstd { stage: _, compiler } => {
                vec![self.compiler_rt(()),
                     self.rustc(compiler.stage).target(compiler.host)]
            }
            Source::CompilerRt { _dummy } => {
                vec![self.llvm(()).target(&build.config.build)]
            }
            Source::Llvm { _dummy } => Vec::new(),
        }
    }
}
<|endoftext|>


<commit_before>use crate::discord_client::{CommandHandler, DiscordClient};
use serenity::{
    client,
    model::{channel::Message, gateway::Ready},
    prelude::*,
};
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use std::thread;

pub struct SerenityDiscordClient {
    serenity_client: Arc<Mutex<Client>>,
    command_callbacks: Arc<Mutex<HashMap<String, Box<CommandHandler + Send>>>>,
}

struct SerenityDiscordHandler {
    command_callbacks: Arc<Mutex<HashMap<String, Box<CommandHandler + Send>>>>,
    command_prefix: &'static str,
}

impl DiscordClient for SerenityDiscordClient {
    fn new(token: &str) -> Self {
        println!("valid token: {}", client::validate_token(token).is_ok());

        let command_callbacks = Arc::new(Mutex::new(HashMap::new()));
        let serenity_handler = SerenityDiscordHandler {
            command_callbacks: command_callbacks.clone(),
            command_prefix: "!", //TODO: make this configurable in case of clashes with other bots
        };

        let serenity_client = Arc::new(Mutex::new(
            Client::new(token, serenity_handler).expect("Error creating serenity client"),
        ));
        println!("created client");

        let thread_serenity_client = serenity_client.clone();
        thread::spawn(move || {
            if let Err(why) = thread_serenity_client.lock().unwrap().start() {
                println!("An error occurred while running the client: {:?}", why);
            }
        });
        println!("started connection");

        SerenityDiscordClient {
            serenity_client: serenity_client.clone(),
            command_callbacks: command_callbacks.clone(),
        }
    }

    fn register_command<T>(
        &self,
        command: &str,
        command_handler: T,
    ) -> Result<(), Box<std::error::Error>>
    where
        T: CommandHandler + Send + 'static,
    {
        if self
            .command_callbacks
            .lock()
            .unwrap()
            .insert(command.to_string(), Box::new(command_handler))
            .is_some()
        {
            panic!("command was entered twice for {}", command);
        }
        Ok(())
    }
}

impl EventHandler for SerenityDiscordHandler {
    fn message(&self, ctx: Context, msg: Message) {
        //TODO: clean this up and split it out into more functions?
        if msg.content.starts_with(self.command_prefix) {
            if let Some(command) = msg.content.split_whitespace().nth(0) {
                if let Some(command) = command.chars().next().map(|c| &command[c.len_utf8()..]) {
                    if let Some(command_handler) =
                        self.command_callbacks.lock().unwrap().get(command)
                    {
                        if let Err(err) = command_handler.process_command(&msg.content, &|output| {
                            if let Err(err) = msg.channel_id.say(&ctx.http, output) {
                                println!("Error sending message: {:?}", err);
                            }
                        }) {
                            println!("Error processing command: {:?}", err);
                        }
                    };
                };
            };
        }
    }

    fn ready(&self, _: Context, ready: Ready) {
        println!("{} is connected!", ready.user.name);
    }
}
<commit_msg>Refactor discord client command parsing and add a unit test<commit_after>use crate::discord_client::{CommandHandler, DiscordClient};
use serenity::{
    client,
    model::{channel::Message, gateway::Ready},
    prelude::*,
};
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use std::thread;

pub struct SerenityDiscordClient {
    serenity_client: Arc<Mutex<Client>>,
    command_callbacks: Arc<Mutex<HashMap<String, Box<CommandHandler + Send>>>>,
}

struct SerenityDiscordHandler {
    command_callbacks: Arc<Mutex<HashMap<String, Box<CommandHandler + Send>>>>,
    command_prefix: &'static str,
}

impl DiscordClient for SerenityDiscordClient {
    fn new(token: &str) -> Self {
        println!("valid token: {}", client::validate_token(token).is_ok());

        let command_callbacks = Arc::new(Mutex::new(HashMap::new()));
        let serenity_handler = SerenityDiscordHandler {
            command_callbacks: command_callbacks.clone(),
            command_prefix: "!", //TODO: make this configurable in case of clashes with other bots
        };

        let serenity_client = Arc::new(Mutex::new(
            Client::new(token, serenity_handler).expect("Error creating serenity client"),
        ));
        println!("created client");

        let thread_serenity_client = serenity_client.clone();
        thread::spawn(move || {
            if let Err(why) = thread_serenity_client.lock().unwrap().start() {
                println!("An error occurred while running the client: {:?}", why);
            }
        });
        println!("started connection");

        SerenityDiscordClient {
            serenity_client: serenity_client.clone(),
            command_callbacks: command_callbacks.clone(),
        }
    }

    fn register_command<T>(
        &self,
        command: &str,
        command_handler: T,
    ) -> Result<(), Box<std::error::Error>>
    where
        T: CommandHandler + Send + 'static,
    {
        if self
            .command_callbacks
            .lock()
            .unwrap()
            .insert(command.to_string(), Box::new(command_handler))
            .is_some()
        {
            panic!("command was entered twice for {}", command);
        }
        Ok(())
    }
}

impl SerenityDiscordHandler {
    fn get_command_name(&self, full_command: &str) -> Option<String> {
        let mut result: Option<String> = None;

        if full_command.starts_with(self.command_prefix) {
            if let Some(command_with_prefix) = full_command.split_whitespace().nth(0) {
                if let Some(command) = command_with_prefix
                    .chars()
                    .next()
                    .map(|c| &command_with_prefix[c.len_utf8()..])
                {
                    result = Some(command.to_string());
                }
            }
        }

        result
    }
}

impl EventHandler for SerenityDiscordHandler {
    fn message(&self, ctx: Context, msg: Message) {
        if let Some(command) = self.get_command_name(&msg.content) {
            if let Some(command_handler) = self.command_callbacks.lock().unwrap().get(&command) {
                if let Err(err) = command_handler.process_command(&msg.content, &|output| {
                    if let Err(err) = msg.channel_id.say(&ctx.http, output) {
                        println!("Error sending message: {:?}", err);
                    }
                }) {
                    println!("Error processing command: {:?}", err);
                }
            };
        };
    }

    fn ready(&self, _: Context, ready: Ready) {
        println!("{} is connected!", ready.user.name);
    }
}

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

    #[test]
    fn test_get_command_name() {
        let command_callbacks = Arc::new(Mutex::new(HashMap::new()));

        let handler = SerenityDiscordHandler {
            command_callbacks: command_callbacks.clone(),
            command_prefix: "!",
        };

        assert_eq!(
            Some(String::from("ping")),
            handler.get_command_name("!ping")
        );
        assert_eq!(Some(String::from("pic")), handler.get_command_name("!pic"));
        assert_eq!(
            Some(String::from("pic")),
            handler.get_command_name("!pic tag1 tag2 tag3")
        );
        assert_eq!(
            Some(String::from("pic")),
            handler.get_command_name("!pic ももよ まじこい")
        );
        assert_eq!(
            Some(String::from("辞書")),
            handler.get_command_name("!辞書")
        );
        assert_eq!(
            Some(String::from("辞書")),
            handler.get_command_name("!辞書 勉強")
        );
    }
}
<|endoftext|>