<commit_before>//! Render to a window created by Glutin, using Glium's OpenGL functions

use ppu::{SCREEN_WIDTH, SCREEN_HEIGHT};

use glium::{DisplayBuild, Surface};
use glium::backend::glutin_backend::GlutinFacade;
use glium::index::{NoIndices, PrimitiveType};
use glium::glutin::WindowBuilder;
use glium::vertex::VertexBuffer;

use std::process;

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

impl Vertex {
    fn new(x: f32, y: f32) -> Self { Vertex { pos: [x, y] } }
}

implement_vertex!(Vertex, pos);

pub struct GliumRenderer {
    display: GlutinFacade,
    vbuf: VertexBuffer<Vertex>,
    index: NoIndices,
}

impl Default for GliumRenderer {
    fn default() -> Self {
        let display = WindowBuilder::new()
            .with_dimensions(SCREEN_WIDTH as u32 * 3, SCREEN_HEIGHT as u32 * 3)
            .with_title("sneeze".to_owned())
            .build_glium().unwrap();
        let shape = [
            Vertex::new(-1.0, 1.0),
            Vertex::new(1.0, 1.0),
            Vertex::new(1.0, -1.0),
            Vertex::new(-1.0, -1.0),
        ];
        let vbuf = VertexBuffer::new(&display, &shape).unwrap();
        let index = NoIndices(PrimitiveType::TriangleStrip);

        GliumRenderer {
            display: display,
            vbuf: vbuf,
            index: index,
        }
    }
}

impl GliumRenderer {
    fn handle_events(&mut self) {
        use glium::glutin::Event::*;

        for ev in self.display.poll_events() {
            match ev {
                Closed => {
                    info!("quit event -> exiting");
                    process::exit(0);
                }
                _ => ()
            }
        }
    }
}

impl super::Renderer for GliumRenderer {
    fn render(&mut self, frame_data: &[u8]) {
        let mut target = self.display.draw();
        target.finish().unwrap();

        self.handle_events();
    }
}
<commit_msg>Glium is now red. Great success.<commit_after>//! Render to a window created by Glutin, using Glium's OpenGL functions

use ppu::{SCREEN_WIDTH, SCREEN_HEIGHT};

use glium::{DisplayBuild, Surface};
use glium::backend::glutin_backend::GlutinFacade;
use glium::index::{NoIndices, PrimitiveType};
use glium::glutin::WindowBuilder;
use glium::program::Program;
use glium::uniforms;
use glium::vertex::VertexBuffer;

use std::process;

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

impl Vertex {
    fn new(x: f32, y: f32) -> Self { Vertex { position: [x, y] } }
}

implement_vertex!(Vertex, position);

const VERTEX_SHADER_SRC: &'static str = r#"
    #version 140

    in vec2 position;

    void main() {
        gl_Position = vec4(position, 0.0, 1.0);
    }
"#;

const FRAGMENT_SHADER_SRC: &'static str = r#"
    #version 140

    out vec4 color;

    void main() {
        color = vec4(1.0, 0.0, 0.0, 1.0);
    }
"#;

pub struct GliumRenderer {
    display: GlutinFacade,
    vbuf: VertexBuffer<Vertex>,
    indices: NoIndices,
    program: Program,
}

impl Default for GliumRenderer {
    fn default() -> Self {
        let display = WindowBuilder::new()
            .with_dimensions(SCREEN_WIDTH as u32 * 3, SCREEN_HEIGHT as u32 * 3)
            .with_title("sneeze".to_owned())
            .build_glium().unwrap();
        let shape = [
            Vertex::new(-1.0, 1.0),
            Vertex::new(1.0, 1.0),
            Vertex::new(-1.0, -1.0),
            Vertex::new(1.0, -1.0),
        ];
        let program = Program::from_source(
            &display,
            VERTEX_SHADER_SRC,
            FRAGMENT_SHADER_SRC,
            None).unwrap();

        GliumRenderer {
            vbuf: VertexBuffer::new(&display, &shape).unwrap(),
            indices: NoIndices(PrimitiveType::TriangleStrip),
            display: display,
            program: program,
        }
    }
}

impl GliumRenderer {
    fn handle_events(&mut self) {
        use glium::glutin::Event::*;

        for ev in self.display.poll_events() {
            match ev {
                Closed => {
                    info!("quit event -> exiting");
                    process::exit(0);
                }
                _ => ()
            }
        }
    }
}

impl super::Renderer for GliumRenderer {
    fn render(&mut self, frame_data: &[u8]) {
        let mut target = self.display.draw();
        target.draw(&self.vbuf, &self.indices, &self.program, &uniforms::EmptyUniforms,
            &Default::default()).unwrap();
        target.finish().unwrap();

        self.handle_events();
    }
}
<|endoftext|>


<commit_before>#[macro_use] extern crate libeuler;
extern crate num;

use num::traits::Zero;
use num::traits::One;
use num::bigint::BigUint;
use std::mem::replace;

/// The Fibonacci sequence is defined by the recurrence relation:
///
///    Fn = Fn−1 + Fn−2, where F1 = 1 and F2 = 1.
///
/// Hence the first 12 terms will be:
///
///    F1 = 1
///    F2 = 1
///    F3 = 2
///    F4 = 3
///    F5 = 5
///    F6 = 8
///    F7 = 13
///    F8 = 21
///    F9 = 34
///    F10 = 55
///    F11 = 89
///    F12 = 144
///
/// The 12th term, F12, is the first term to contain three digits.
///
/// What is the first term in the Fibonacci sequence to contain 1000 digits?
fn main() {
    solutions! {
        inputs: (digits: usize = 1000)

        sol naive {
            let min_bits = digits as f32 * 2.5f32;
            let mut current = BigUint::zero();
            let mut previous = BigUint::one();
            let mut i = 0;

            println!("Minimum bits needed to represent {} digits is {}", digits, min_bits);

            loop {
                let new = current + &previous;
                current = replace(&mut previous, new);

                i += 1;

                if current.bits() as f32 >= min_bits {
                    if format!("{}", current).len() >= digits {
                        break;
                    }
                }
            }

            i
        }
    }
}

<commit_msg>Speed up 25.. Still needs work<commit_after>#[macro_use] extern crate libeuler;
extern crate num;

use num::traits::Zero;
use num::traits::One;
use num::bigint::BigUint;
use std::mem::replace;

/// The Fibonacci sequence is defined by the recurrence relation:
///
///    Fn = Fn−1 + Fn−2, where F1 = 1 and F2 = 1.
///
/// Hence the first 12 terms will be:
///
///    F1 = 1
///    F2 = 1
///    F3 = 2
///    F4 = 3
///    F5 = 5
///    F6 = 8
///    F7 = 13
///    F8 = 21
///    F9 = 34
///    F10 = 55
///    F11 = 89
///    F12 = 144
///
/// The 12th term, F12, is the first term to contain three digits.
///
/// What is the first term in the Fibonacci sequence to contain 1000 digits?
fn main() {
    solutions! {
        inputs: (digits: usize = 1000)

        sol naive {
            let min_bits = digits as f32 * 3.319f32;
            let mut current = BigUint::zero();
            let mut previous = BigUint::one();
            let mut i = 0;

            println!("Minimum bits needed to represent {} digits is {}", digits, min_bits);

            loop {
                let new = current + &previous;
                current = replace(&mut previous, new);

                i += 1;

                if current.bits() as f32 >= min_bits {
                    if format!("{}", current).len() >= digits {
                        break;
                    }
                }
            }

            i
        }
    }
}

<|endoftext|>


<commit_before>use shared::protocol::*;
use shared::protocol::connection::*;
use std::io::Cursor;

#[test]
fn test_protocol() {
    let msg = IdentificationSuccessMessage {
        has_rights: Flag(true),
        was_already_connected: Flag(false),
        login: "salut".to_string(),
        nickname: "yo".to_string(),
        account_id: 54,
        community_id: 1,
        secret_question: "hello".to_string(),
        account_creation: 64.,
        subscription_elapsed_duration: 74.,
        subscription_end_date: 84.,
    };

    let mut buf = Vec::new();
    msg.serialize(&mut buf).unwrap();
    let mut buf = Cursor::new(buf);
    let msg = IdentificationSuccessMessage::deserialize(&mut buf).unwrap();

    assert!(msg.has_rights.0 && !msg.was_already_connected.0);
    assert_eq!("yo", &msg.nickname);
    assert_eq!(1, msg.community_id);
    assert_eq!(74., msg.subscription_elapsed_duration);
}
<commit_msg>updated test_protocol.rs<commit_after>use shared::protocol::*;
use shared::protocol::messages::connection::*;
use std::io::Cursor;

#[test]
fn test_protocol() {
    let msg = IdentificationSuccessMessage {
        has_rights: Flag(true),
        was_already_connected: Flag(false),
        login: "salut".to_string(),
        nickname: "yo".to_string(),
        account_id: 54,
        community_id: 1,
        secret_question: "hello".to_string(),
        account_creation: 64.,
        subscription_elapsed_duration: 74.,
        subscription_end_date: 84.,
    };

    let mut buf = Vec::new();
    msg.serialize(&mut buf).unwrap();
    let mut buf = Cursor::new(buf);
    let msg = IdentificationSuccessMessage::deserialize(&mut buf).unwrap();

    assert!(msg.has_rights.0 && !msg.was_already_connected.0);
    assert_eq!("yo", &msg.nickname);
    assert_eq!(1, msg.community_id);
    assert_eq!(74., msg.subscription_elapsed_duration);
}
<|endoftext|>


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

use LinkerFlavor;
use target::{LinkArgs, TargetOptions};
use std::default::Default;

pub fn opts() -> TargetOptions {
    let mut pre_link_args = LinkArgs::new();
    pre_link_args.insert(LinkerFlavor::Gcc, vec![
            // And here, we see obscure linker flags #45. On windows, it has been
            // found to be necessary to have this flag to compile liblibc.
            //
            // First a bit of background. On Windows, the file format is not ELF,
            // but COFF (at least according to LLVM). COFF doesn't officially allow
            // for section names over 8 characters, apparently. Our metadata
            // section, ".note.rustc", you'll note is over 8 characters.
            //
            // On more recent versions of gcc on mingw, apparently the section name
            // is *not* truncated, but rather stored elsewhere in a separate lookup
            // table. On older versions of gcc, they apparently always truncated th
            // section names (at least in some cases). Truncating the section name
            // actually creates "invalid" objects [1] [2], but only for some
            // introspection tools, not in terms of whether it can be loaded.
            //
            // Long story short, passing this flag forces the linker to *not*
            // truncate section names (so we can find the metadata section after
            // it's compiled). The real kicker is that rust compiled just fine on
            // windows for quite a long time *without* this flag, so I have no idea
            // why it suddenly started failing for liblibc. Regardless, we
            // definitely don't want section name truncation, so we're keeping this
            // flag for windows.
            //
            // [1] - https://sourceware.org/bugzilla/show_bug.cgi?id=13130
            // [2] - https://code.google.com/p/go/issues/detail?id=2139
            "-Wl,--enable-long-section-names".to_string(),

            // Tell GCC to avoid linker plugins, because we are not bundling
            // them with Windows installer, and Rust does its own LTO anyways.
            "-fno-use-linker-plugin".to_string(),

            // Always enable DEP (NX bit) when it is available
            "-Wl,--nxcompat".to_string(),

            // Do not use the standard system startup files or libraries when linking
            "-nostdlib".to_string(),
        ]);

    let mut late_link_args = LinkArgs::new();
    late_link_args.insert(LinkerFlavor::Gcc, vec![
        "-lmingwex".to_string(),
        "-lmingw32".to_string(),
        "-lgcc".to_string(), // alas, mingw* libraries above depend on libgcc
        "-lmsvcrt".to_string(),
        "-luser32".to_string(),
        "-lkernel32".to_string(),
    ]);

    TargetOptions {
        function_sections: true,
        linker: "gcc".to_string(),
        dynamic_linking: true,
        executables: true,
        dll_prefix: "".to_string(),
        dll_suffix: ".dll".to_string(),
        exe_suffix: ".exe".to_string(),
        staticlib_prefix: "".to_string(),
        staticlib_suffix: ".lib".to_string(),
        no_default_libraries: true,
        target_family: Some("windows".to_string()),
        is_like_windows: true,
        allows_weak_linkage: false,
        pre_link_args,
        pre_link_objects_exe: vec![
            "crt2.o".to_string(),    // mingw C runtime initialization for executables
            "rsbegin.o".to_string(), // Rust compiler runtime initialization, see rsbegin.rs
        ],
        pre_link_objects_dll: vec![
            "dllcrt2.o".to_string(), // mingw C runtime initialization for dlls
            "rsbegin.o".to_string(),
        ],
        late_link_args,
        post_link_objects: vec![
            "rsend.o".to_string()
        ],
        custom_unwind_resume: true,

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

use LinkerFlavor;
use target::{LinkArgs, TargetOptions};
use std::default::Default;

pub fn opts() -> TargetOptions {
    let mut pre_link_args = LinkArgs::new();
    pre_link_args.insert(LinkerFlavor::Gcc, vec![
            // And here, we see obscure linker flags #45. On windows, it has been
            // found to be necessary to have this flag to compile liblibc.
            //
            // First a bit of background. On Windows, the file format is not ELF,
            // but COFF (at least according to LLVM). COFF doesn't officially allow
            // for section names over 8 characters, apparently. Our metadata
            // section, ".note.rustc", you'll note is over 8 characters.
            //
            // On more recent versions of gcc on mingw, apparently the section name
            // is *not* truncated, but rather stored elsewhere in a separate lookup
            // table. On older versions of gcc, they apparently always truncated th
            // section names (at least in some cases). Truncating the section name
            // actually creates "invalid" objects [1] [2], but only for some
            // introspection tools, not in terms of whether it can be loaded.
            //
            // Long story short, passing this flag forces the linker to *not*
            // truncate section names (so we can find the metadata section after
            // it's compiled). The real kicker is that rust compiled just fine on
            // windows for quite a long time *without* this flag, so I have no idea
            // why it suddenly started failing for liblibc. Regardless, we
            // definitely don't want section name truncation, so we're keeping this
            // flag for windows.
            //
            // [1] - https://sourceware.org/bugzilla/show_bug.cgi?id=13130
            // [2] - https://code.google.com/p/go/issues/detail?id=2139
            "-Wl,--enable-long-section-names".to_string(),

            // Tell GCC to avoid linker plugins, because we are not bundling
            // them with Windows installer, and Rust does its own LTO anyways.
            "-fno-use-linker-plugin".to_string(),

            // Always enable DEP (NX bit) when it is available
            "-Wl,--nxcompat".to_string(),

            // Do not use the standard system startup files or libraries when linking
            "-nostdlib".to_string(),
        ]);

    let mut late_link_args = LinkArgs::new();
    late_link_args.insert(LinkerFlavor::Gcc, vec![
        "-lmingwex".to_string(),
        "-lmingw32".to_string(),
        "-lgcc".to_string(), // alas, mingw* libraries above depend on libgcc
        "-lmsvcrt".to_string(),
        "-luser32".to_string(),
        "-lkernel32".to_string(),
    ]);

    TargetOptions {
        // FIXME(#13846) this should be enabled for windows
        function_sections: false,
        linker: "gcc".to_string(),
        dynamic_linking: true,
        executables: true,
        dll_prefix: "".to_string(),
        dll_suffix: ".dll".to_string(),
        exe_suffix: ".exe".to_string(),
        staticlib_prefix: "".to_string(),
        staticlib_suffix: ".lib".to_string(),
        no_default_libraries: true,
        target_family: Some("windows".to_string()),
        is_like_windows: true,
        allows_weak_linkage: false,
        pre_link_args,
        pre_link_objects_exe: vec![
            "crt2.o".to_string(),    // mingw C runtime initialization for executables
            "rsbegin.o".to_string(), // Rust compiler runtime initialization, see rsbegin.rs
        ],
        pre_link_objects_dll: vec![
            "dllcrt2.o".to_string(), // mingw C runtime initialization for dlls
            "rsbegin.o".to_string(),
        ],
        late_link_args,
        post_link_objects: vec![
            "rsend.o".to_string()
        ],
        custom_unwind_resume: true,

        .. Default::default()
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 Serde Developers
//
// 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 serde::{ser, Serialize};

use error::Error;
use token::Token;

/// A `Serializer` that ensures that a value serializes to a given list of tokens.
#[derive(Debug)]
pub struct Serializer<'a> {
    tokens: &'a [Token],
}

impl<'a> Serializer<'a> {
    /// Creates the serializer.
    pub fn new(tokens: &'a [Token]) -> Self {
        Serializer { tokens: tokens }
    }

    /// Pulls the next token off of the serializer, ignoring it.
    fn next_token(&mut self) -> Option<Token> {
        if let Some((&first, rest)) = self.tokens.split_first() {
            self.tokens = rest;
            Some(first)
        } else {
            None
        }
    }

    pub fn remaining(&self) -> usize {
        self.tokens.len()
    }
}

macro_rules! assert_next_token {
    ($ser:expr, $expected:ident) => {
        assert_next_token!($ser, $expected, Token::$expected, true);
    };
    ($ser:expr, $expected:ident($v:expr)) => {
        assert_next_token!($ser, $expected, Token::$expected(v), v == $v);
    };
    ($ser:expr, $expected:ident { $($k:ident),* }) => {
        let compare = ($($k,)*);
        assert_next_token!($ser, $expected, Token::$expected { $($k),* }, ($($k,)*) == compare);
    };
    ($ser:expr, $expected:ident, $pat:pat, $guard:expr) => {
        match $ser.next_token() {
            Some($pat) if $guard => {}
            Some(other) => {
                panic!("expected Token::{} but serialized as {}",
                       stringify!($expected), other);
            }
            None => {
                panic!("expected Token::{} after end of serialized tokens",
                       stringify!($expected));
            }
        }
    };
}

impl<'s, 'a> ser::Serializer for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    type SerializeSeq = Self;
    type SerializeTuple = Self;
    type SerializeTupleStruct = Self;
    type SerializeTupleVariant = Variant<'s, 'a>;
    type SerializeMap = Self;
    type SerializeStruct = Self;
    type SerializeStructVariant = Variant<'s, 'a>;

    fn serialize_bool(self, v: bool) -> Result<(), Error> {
        assert_next_token!(self, Bool(v));
        Ok(())
    }

    fn serialize_i8(self, v: i8) -> Result<(), Error> {
        assert_next_token!(self, I8(v));
        Ok(())
    }

    fn serialize_i16(self, v: i16) -> Result<(), Error> {
        assert_next_token!(self, I16(v));
        Ok(())
    }

    fn serialize_i32(self, v: i32) -> Result<(), Error> {
        assert_next_token!(self, I32(v));
        Ok(())
    }

    fn serialize_i64(self, v: i64) -> Result<(), Error> {
        assert_next_token!(self, I64(v));
        Ok(())
    }

    fn serialize_u8(self, v: u8) -> Result<(), Error> {
        assert_next_token!(self, U8(v));
        Ok(())
    }

    fn serialize_u16(self, v: u16) -> Result<(), Error> {
        assert_next_token!(self, U16(v));
        Ok(())
    }

    fn serialize_u32(self, v: u32) -> Result<(), Error> {
        assert_next_token!(self, U32(v));
        Ok(())
    }

    fn serialize_u64(self, v: u64) -> Result<(), Error> {
        assert_next_token!(self, U64(v));
        Ok(())
    }

    fn serialize_f32(self, v: f32) -> Result<(), Error> {
        assert_next_token!(self, F32(v));
        Ok(())
    }

    fn serialize_f64(self, v: f64) -> Result<(), Error> {
        assert_next_token!(self, F64(v));
        Ok(())
    }

    fn serialize_char(self, v: char) -> Result<(), Error> {
        assert_next_token!(self, Char(v));
        Ok(())
    }

    fn serialize_str(self, v: &str) -> Result<(), Error> {
        match self.tokens.first() {
            Some(&Token::BorrowedStr(_)) => assert_next_token!(self, BorrowedStr(v)),
            Some(&Token::String(_)) => assert_next_token!(self, String(v)),
            _ => assert_next_token!(self, Str(v)),
        }
        Ok(())
    }

    fn serialize_bytes(self, v: &[u8]) -> Result<(), Self::Error> {
        match self.tokens.first() {
            Some(&Token::BorrowedBytes(_)) => assert_next_token!(self, BorrowedBytes(v)),
            Some(&Token::ByteBuf(_)) => assert_next_token!(self, ByteBuf(v)),
            _ => assert_next_token!(self, Bytes(v)),
        }
        Ok(())
    }

    fn serialize_unit(self) -> Result<(), Error> {
        assert_next_token!(self, Unit);
        Ok(())
    }

    fn serialize_unit_struct(self, name: &'static str) -> Result<(), Error> {
        assert_next_token!(self, UnitStruct { name });
        Ok(())
    }

    fn serialize_unit_variant(
        self,
        name: &'static str,
        _variant_index: u32,
        variant: &'static str,
    ) -> Result<(), Error> {
        if self.tokens.first() == Some(&Token::Enum { name }) {
            self.next_token();
            assert_next_token!(self, Str(variant));
            assert_next_token!(self, Unit);
        } else {
            assert_next_token!(self, UnitVariant { name, variant });
        }
        Ok(())
    }

    fn serialize_newtype_struct<T: ?Sized>(self, name: &'static str, value: &T) -> Result<(), Error>
    where
        T: Serialize,
    {
        assert_next_token!(self, NewtypeStruct { name });
        value.serialize(self)
    }

    fn serialize_newtype_variant<T: ?Sized>(
        self,
        name: &'static str,
        _variant_index: u32,
        variant: &'static str,
        value: &T,
    ) -> Result<(), Error>
    where
        T: Serialize,
    {
        if self.tokens.first() == Some(&Token::Enum { name }) {
            self.next_token();
            assert_next_token!(self, Str(variant));
        } else {
            assert_next_token!(self, NewtypeVariant { name, variant });
        }
        value.serialize(self)
    }

    fn serialize_none(self) -> Result<(), Error> {
        assert_next_token!(self, None);
        Ok(())
    }

    fn serialize_some<T: ?Sized>(self, value: &T) -> Result<(), Error>
    where
        T: Serialize,
    {
        assert_next_token!(self, Some);
        value.serialize(self)
    }

    fn serialize_seq(self, len: Option<usize>) -> Result<Self, Error> {
        assert_next_token!(self, Seq { len });
        Ok(self)
    }

    fn serialize_tuple(self, len: usize) -> Result<Self, Error> {
        assert_next_token!(self, Tuple { len });
        Ok(self)
    }

    fn serialize_tuple_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
        assert_next_token!(self, TupleStruct { name, len });
        Ok(self)
    }

    fn serialize_tuple_variant(
        self,
        name: &'static str,
        _variant_index: u32,
        variant: &'static str,
        len: usize,
    ) -> Result<Self::SerializeTupleVariant, Error> {
        if self.tokens.first() == Some(&Token::Enum { name }) {
            self.next_token();
            assert_next_token!(self, Str(variant));
            let len = Some(len);
            assert_next_token!(self, Seq { len });
            Ok(Variant { ser: self, end: Token::SeqEnd })
        } else {
            assert_next_token!(self, TupleVariant { name, variant, len });
            Ok(Variant { ser: self, end: Token::TupleVariantEnd })
        }
    }

    fn serialize_map(self, len: Option<usize>) -> Result<Self, Error> {
        assert_next_token!(self, Map { len });
        Ok(self)
    }

    fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
        assert_next_token!(self, Struct { name, len });
        Ok(self)
    }

    fn serialize_struct_variant(
        self,
        name: &'static str,
        _variant_index: u32,
        variant: &'static str,
        len: usize,
    ) -> Result<Self::SerializeStructVariant, Error> {
        if self.tokens.first() == Some(&Token::Enum { name }) {
            self.next_token();
            assert_next_token!(self, Str(variant));
            let len = Some(len);
            assert_next_token!(self, Map { len });
            Ok(Variant { ser: self, end: Token::MapEnd })
        } else {
            assert_next_token!(self, StructVariant { name, variant, len });
            Ok(Variant { ser: self, end: Token::StructVariantEnd })
        }
    }
}

pub struct Variant<'s, 'a: 's> {
    ser: &'s mut Serializer<'a>,
    end: Token,
}

impl<'s, 'a> ser::SerializeSeq for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
    where
        T: Serialize,
    {
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Error> {
        assert_next_token!(self, SeqEnd);
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeTuple for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
    where
        T: Serialize,
    {
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Error> {
        assert_next_token!(self, TupleEnd);
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeTupleStruct for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
    where
        T: Serialize,
    {
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Error> {
        assert_next_token!(self, TupleStructEnd);
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeTupleVariant for Variant<'s, 'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
    where
        T: Serialize,
    {
        value.serialize(&mut *self.ser)
    }

    fn end(self) -> Result<(), Error> {
        match self.end {
            Token::TupleVariantEnd => assert_next_token!(self.ser, TupleVariantEnd),
            Token::SeqEnd => assert_next_token!(self.ser, SeqEnd),
            _ => unreachable!(),
        }
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeMap for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
    where
        T: Serialize,
    {
        key.serialize(&mut **self)
    }

    fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
    where
        T: Serialize,
    {
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Self::Error> {
        assert_next_token!(self, MapEnd);
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeStruct for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T: ?Sized>(
        &mut self,
        key: &'static str,
        value: &T,
    ) -> Result<(), Self::Error>
    where
        T: Serialize,
    {
        try!(key.serialize(&mut **self));
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Self::Error> {
        assert_next_token!(self, StructEnd);
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeStructVariant for Variant<'s, 'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T: ?Sized>(
        &mut self,
        key: &'static str,
        value: &T,
    ) -> Result<(), Self::Error>
    where
        T: Serialize,
    {
        try!(key.serialize(&mut *self.ser));
        value.serialize(&mut *self.ser)
    }

    fn end(self) -> Result<(), Self::Error> {
        match self.end {
            Token::StructVariantEnd => assert_next_token!(self.ser, StructVariantEnd),
            Token::MapEnd => assert_next_token!(self.ser, MapEnd),
            _ => unreachable!(),
        }
        Ok(())
    }
}
<commit_msg>Support old rustc<commit_after>// Copyright 2017 Serde Developers
//
// 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 serde::{ser, Serialize};

use error::Error;
use token::Token;

/// A `Serializer` that ensures that a value serializes to a given list of tokens.
#[derive(Debug)]
pub struct Serializer<'a> {
    tokens: &'a [Token],
}

impl<'a> Serializer<'a> {
    /// Creates the serializer.
    pub fn new(tokens: &'a [Token]) -> Self {
        Serializer { tokens: tokens }
    }

    /// Pulls the next token off of the serializer, ignoring it.
    fn next_token(&mut self) -> Option<Token> {
        if let Some((&first, rest)) = self.tokens.split_first() {
            self.tokens = rest;
            Some(first)
        } else {
            None
        }
    }

    pub fn remaining(&self) -> usize {
        self.tokens.len()
    }
}

macro_rules! assert_next_token {
    ($ser:expr, $expected:ident) => {
        assert_next_token!($ser, $expected, Token::$expected, true);
    };
    ($ser:expr, $expected:ident($v:expr)) => {
        assert_next_token!($ser, $expected, Token::$expected(v), v == $v);
    };
    ($ser:expr, $expected:ident { $($k:ident),* }) => {
        let compare = ($($k,)*);
        assert_next_token!($ser, $expected, Token::$expected { $($k),* }, ($($k,)*) == compare);
    };
    ($ser:expr, $expected:ident, $pat:pat, $guard:expr) => {
        match $ser.next_token() {
            Some($pat) if $guard => {}
            Some(other) => {
                panic!("expected Token::{} but serialized as {}",
                       stringify!($expected), other);
            }
            None => {
                panic!("expected Token::{} after end of serialized tokens",
                       stringify!($expected));
            }
        }
    };
}

impl<'s, 'a> ser::Serializer for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    type SerializeSeq = Self;
    type SerializeTuple = Self;
    type SerializeTupleStruct = Self;
    type SerializeTupleVariant = Variant<'s, 'a>;
    type SerializeMap = Self;
    type SerializeStruct = Self;
    type SerializeStructVariant = Variant<'s, 'a>;

    fn serialize_bool(self, v: bool) -> Result<(), Error> {
        assert_next_token!(self, Bool(v));
        Ok(())
    }

    fn serialize_i8(self, v: i8) -> Result<(), Error> {
        assert_next_token!(self, I8(v));
        Ok(())
    }

    fn serialize_i16(self, v: i16) -> Result<(), Error> {
        assert_next_token!(self, I16(v));
        Ok(())
    }

    fn serialize_i32(self, v: i32) -> Result<(), Error> {
        assert_next_token!(self, I32(v));
        Ok(())
    }

    fn serialize_i64(self, v: i64) -> Result<(), Error> {
        assert_next_token!(self, I64(v));
        Ok(())
    }

    fn serialize_u8(self, v: u8) -> Result<(), Error> {
        assert_next_token!(self, U8(v));
        Ok(())
    }

    fn serialize_u16(self, v: u16) -> Result<(), Error> {
        assert_next_token!(self, U16(v));
        Ok(())
    }

    fn serialize_u32(self, v: u32) -> Result<(), Error> {
        assert_next_token!(self, U32(v));
        Ok(())
    }

    fn serialize_u64(self, v: u64) -> Result<(), Error> {
        assert_next_token!(self, U64(v));
        Ok(())
    }

    fn serialize_f32(self, v: f32) -> Result<(), Error> {
        assert_next_token!(self, F32(v));
        Ok(())
    }

    fn serialize_f64(self, v: f64) -> Result<(), Error> {
        assert_next_token!(self, F64(v));
        Ok(())
    }

    fn serialize_char(self, v: char) -> Result<(), Error> {
        assert_next_token!(self, Char(v));
        Ok(())
    }

    fn serialize_str(self, v: &str) -> Result<(), Error> {
        match self.tokens.first() {
            Some(&Token::BorrowedStr(_)) => assert_next_token!(self, BorrowedStr(v)),
            Some(&Token::String(_)) => assert_next_token!(self, String(v)),
            _ => assert_next_token!(self, Str(v)),
        }
        Ok(())
    }

    fn serialize_bytes(self, v: &[u8]) -> Result<(), Self::Error> {
        match self.tokens.first() {
            Some(&Token::BorrowedBytes(_)) => assert_next_token!(self, BorrowedBytes(v)),
            Some(&Token::ByteBuf(_)) => assert_next_token!(self, ByteBuf(v)),
            _ => assert_next_token!(self, Bytes(v)),
        }
        Ok(())
    }

    fn serialize_unit(self) -> Result<(), Error> {
        assert_next_token!(self, Unit);
        Ok(())
    }

    fn serialize_unit_struct(self, name: &'static str) -> Result<(), Error> {
        assert_next_token!(self, UnitStruct { name });
        Ok(())
    }

    fn serialize_unit_variant(
        self,
        name: &'static str,
        _variant_index: u32,
        variant: &'static str,
    ) -> Result<(), Error> {
        if self.tokens.first() == Some(&Token::Enum { name: name }) {
            self.next_token();
            assert_next_token!(self, Str(variant));
            assert_next_token!(self, Unit);
        } else {
            assert_next_token!(self, UnitVariant { name, variant });
        }
        Ok(())
    }

    fn serialize_newtype_struct<T: ?Sized>(self, name: &'static str, value: &T) -> Result<(), Error>
    where
        T: Serialize,
    {
        assert_next_token!(self, NewtypeStruct { name });
        value.serialize(self)
    }

    fn serialize_newtype_variant<T: ?Sized>(
        self,
        name: &'static str,
        _variant_index: u32,
        variant: &'static str,
        value: &T,
    ) -> Result<(), Error>
    where
        T: Serialize,
    {
        if self.tokens.first() == Some(&Token::Enum { name: name }) {
            self.next_token();
            assert_next_token!(self, Str(variant));
        } else {
            assert_next_token!(self, NewtypeVariant { name, variant });
        }
        value.serialize(self)
    }

    fn serialize_none(self) -> Result<(), Error> {
        assert_next_token!(self, None);
        Ok(())
    }

    fn serialize_some<T: ?Sized>(self, value: &T) -> Result<(), Error>
    where
        T: Serialize,
    {
        assert_next_token!(self, Some);
        value.serialize(self)
    }

    fn serialize_seq(self, len: Option<usize>) -> Result<Self, Error> {
        assert_next_token!(self, Seq { len });
        Ok(self)
    }

    fn serialize_tuple(self, len: usize) -> Result<Self, Error> {
        assert_next_token!(self, Tuple { len });
        Ok(self)
    }

    fn serialize_tuple_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
        assert_next_token!(self, TupleStruct { name, len });
        Ok(self)
    }

    fn serialize_tuple_variant(
        self,
        name: &'static str,
        _variant_index: u32,
        variant: &'static str,
        len: usize,
    ) -> Result<Self::SerializeTupleVariant, Error> {
        if self.tokens.first() == Some(&Token::Enum { name: name }) {
            self.next_token();
            assert_next_token!(self, Str(variant));
            let len = Some(len);
            assert_next_token!(self, Seq { len });
            Ok(Variant { ser: self, end: Token::SeqEnd })
        } else {
            assert_next_token!(self, TupleVariant { name, variant, len });
            Ok(Variant { ser: self, end: Token::TupleVariantEnd })
        }
    }

    fn serialize_map(self, len: Option<usize>) -> Result<Self, Error> {
        assert_next_token!(self, Map { len });
        Ok(self)
    }

    fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self, Error> {
        assert_next_token!(self, Struct { name, len });
        Ok(self)
    }

    fn serialize_struct_variant(
        self,
        name: &'static str,
        _variant_index: u32,
        variant: &'static str,
        len: usize,
    ) -> Result<Self::SerializeStructVariant, Error> {
        if self.tokens.first() == Some(&Token::Enum { name: name }) {
            self.next_token();
            assert_next_token!(self, Str(variant));
            let len = Some(len);
            assert_next_token!(self, Map { len });
            Ok(Variant { ser: self, end: Token::MapEnd })
        } else {
            assert_next_token!(self, StructVariant { name, variant, len });
            Ok(Variant { ser: self, end: Token::StructVariantEnd })
        }
    }
}

pub struct Variant<'s, 'a: 's> {
    ser: &'s mut Serializer<'a>,
    end: Token,
}

impl<'s, 'a> ser::SerializeSeq for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
    where
        T: Serialize,
    {
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Error> {
        assert_next_token!(self, SeqEnd);
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeTuple for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
    where
        T: Serialize,
    {
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Error> {
        assert_next_token!(self, TupleEnd);
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeTupleStruct for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
    where
        T: Serialize,
    {
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Error> {
        assert_next_token!(self, TupleStructEnd);
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeTupleVariant for Variant<'s, 'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
    where
        T: Serialize,
    {
        value.serialize(&mut *self.ser)
    }

    fn end(self) -> Result<(), Error> {
        match self.end {
            Token::TupleVariantEnd => assert_next_token!(self.ser, TupleVariantEnd),
            Token::SeqEnd => assert_next_token!(self.ser, SeqEnd),
            _ => unreachable!(),
        }
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeMap for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error>
    where
        T: Serialize,
    {
        key.serialize(&mut **self)
    }

    fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error>
    where
        T: Serialize,
    {
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Self::Error> {
        assert_next_token!(self, MapEnd);
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeStruct for &'s mut Serializer<'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T: ?Sized>(
        &mut self,
        key: &'static str,
        value: &T,
    ) -> Result<(), Self::Error>
    where
        T: Serialize,
    {
        try!(key.serialize(&mut **self));
        value.serialize(&mut **self)
    }

    fn end(self) -> Result<(), Self::Error> {
        assert_next_token!(self, StructEnd);
        Ok(())
    }
}

impl<'s, 'a> ser::SerializeStructVariant for Variant<'s, 'a> {
    type Ok = ();
    type Error = Error;

    fn serialize_field<T: ?Sized>(
        &mut self,
        key: &'static str,
        value: &T,
    ) -> Result<(), Self::Error>
    where
        T: Serialize,
    {
        try!(key.serialize(&mut *self.ser));
        value.serialize(&mut *self.ser)
    }

    fn end(self) -> Result<(), Self::Error> {
        match self.end {
            Token::StructVariantEnd => assert_next_token!(self.ser, StructVariantEnd),
            Token::MapEnd => assert_next_token!(self.ser, MapEnd),
            _ => unreachable!(),
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>use rustc::traits::Reveal;
use rustc::ty::{self, TyCtxt, Ty, Instance, layout};
use rustc::mir;

use syntax::ast::Mutability;
use syntax::codemap::Span;

use super::{
    EvalResult, EvalError, EvalErrorKind,
    GlobalId, Lvalue, Value,
    PrimVal,
    EvalContext, StackPopCleanup, PtrAndAlign,
    Kind,
};

use rustc_const_math::ConstInt;

use std::fmt;
use std::error::Error;

pub fn eval_body_as_primval<'a, 'tcx>(
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
    instance: Instance<'tcx>,
) -> EvalResult<'tcx, (PrimVal, Ty<'tcx>)> {
    let limits = super::ResourceLimits::default();
    let mut ecx = EvalContext::<CompileTimeFunctionEvaluator>::new(tcx, limits, (), ());
    let cid = GlobalId { instance, promoted: None };
    if ecx.tcx.has_attr(instance.def_id(), "linkage") {
        return Err(ConstEvalError::NotConst("extern global".to_string()).into());
    }

    let mir = ecx.load_mir(instance.def)?;
    if !ecx.globals.contains_key(&cid) {
        let size = ecx.type_size_with_substs(mir.return_ty, instance.substs)?.expect("unsized global");
        let align = ecx.type_align_with_substs(mir.return_ty, instance.substs)?;
        let ptr = ecx.memory.allocate(size, align, Kind::UninitializedStatic)?;
        let aligned = !ecx.is_packed(mir.return_ty)?;
        ecx.globals.insert(cid, PtrAndAlign { ptr: ptr.into(), aligned });
        let mutable = !mir.return_ty.is_freeze(
                ecx.tcx,
                ty::ParamEnv::empty(Reveal::All),
                mir.span);
        let mutability = if mutable {
            Mutability::Mutable
        } else {
            Mutability::Immutable
        };
        let cleanup = StackPopCleanup::MarkStatic(mutability);
        let name = ty::tls::with(|tcx| tcx.item_path_str(instance.def_id()));
        trace!("pushing stack frame for global: {}", name);
        ecx.push_stack_frame(
            instance,
            mir.span,
            mir,
            Lvalue::from_ptr(ptr),
            cleanup,
        )?;

        while ecx.step()? {}
    }
    let value = Value::ByRef(*ecx.globals.get(&cid).expect("global not cached"));
    Ok((ecx.value_to_primval(value, mir.return_ty)?, mir.return_ty))
}

pub fn eval_body_as_integer<'a, 'tcx>(
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
    instance: Instance<'tcx>,
) -> EvalResult<'tcx, ConstInt> {
    let (prim, ty) = eval_body_as_primval(tcx, instance)?;
    let prim = prim.to_bytes()?;
    use syntax::ast::{IntTy, UintTy};
    use rustc::ty::TypeVariants::*;
    use rustc_const_math::{ConstIsize, ConstUsize};
    Ok(match ty.sty {
        TyInt(IntTy::I8) => ConstInt::I8(prim as i128 as i8),
        TyInt(IntTy::I16) => ConstInt::I16(prim as i128 as i16),
        TyInt(IntTy::I32) => ConstInt::I32(prim as i128 as i32),
        TyInt(IntTy::I64) => ConstInt::I64(prim as i128 as i64),
        TyInt(IntTy::I128) => ConstInt::I128(prim as i128),
        TyInt(IntTy::Is) => ConstInt::Isize(ConstIsize::new(prim as i128 as i64, tcx.sess.target.int_type).expect("miri should already have errored")),
        TyUint(UintTy::U8) => ConstInt::U8(prim as u8),
        TyUint(UintTy::U16) => ConstInt::U16(prim as u16),
        TyUint(UintTy::U32) => ConstInt::U32(prim as u32),
        TyUint(UintTy::U64) => ConstInt::U64(prim as u64),
        TyUint(UintTy::U128) => ConstInt::U128(prim),
        TyUint(UintTy::Us) => ConstInt::Usize(ConstUsize::new(prim as u64, tcx.sess.target.uint_type).expect("miri should already have errored")),
        _ => return Err(ConstEvalError::NeedsRfc("evaluating anything other than isize/usize during typeck".to_string()).into()),
    })
}

struct CompileTimeFunctionEvaluator;

impl<'tcx> Into<EvalError<'tcx>> for ConstEvalError {
    fn into(self) -> EvalError<'tcx> {
        EvalErrorKind::MachineError(Box::new(self)).into()
    }
}

#[derive(Clone, Debug)]
enum ConstEvalError {
    NeedsRfc(String),
    NotConst(String),
}

impl fmt::Display for ConstEvalError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::ConstEvalError::*;
        match *self {
            NeedsRfc(ref msg) =>
                write!(f, "\"{}\" needs an rfc before being allowed inside constants", msg),
            NotConst(ref msg) =>
                write!(f, "Cannot evaluate within constants: \"{}\"", msg),
        }
    }
}

impl Error for ConstEvalError {
    fn description(&self) -> &str {
        use self::ConstEvalError::*;
        match *self {
            NeedsRfc(_) =>
                "this feature needs an rfc before being allowed inside constants",
            NotConst(_) =>
                "this feature is not compatible with constant evaluation",
        }
    }

    fn cause(&self) -> Option<&Error> {
        None
    }
}

impl<'tcx> super::Machine<'tcx> for CompileTimeFunctionEvaluator {
    type Data = ();
    type MemoryData = ();
    type MemoryKinds = !;
    fn eval_fn_call<'a>(
        ecx: &mut EvalContext<'a, 'tcx, Self>,
        instance: ty::Instance<'tcx>,
        destination: Option<(Lvalue, mir::BasicBlock)>,
        _arg_operands: &[mir::Operand<'tcx>],
        span: Span,
        _sig: ty::FnSig<'tcx>,
    ) -> EvalResult<'tcx, bool> {
        if !ecx.tcx.is_const_fn(instance.def_id()) {
            return Err(ConstEvalError::NotConst(format!("calling non-const fn `{}`", instance)).into());
        }
        let mir = match ecx.load_mir(instance.def) {
            Ok(mir) => mir,
            Err(EvalError{ kind: EvalErrorKind::NoMirFor(path), ..} ) => {
                // some simple things like `malloc` might get accepted in the future
                return Err(ConstEvalError::NeedsRfc(format!("calling extern function `{}`", path)).into());
            },
            Err(other) => return Err(other),
        };
        let (return_lvalue, return_to_block) = match destination {
            Some((lvalue, block)) => (lvalue, StackPopCleanup::Goto(block)),
            None => (Lvalue::undef(), StackPopCleanup::None),
        };

        ecx.push_stack_frame(
            instance,
            span,
            mir,
            return_lvalue,
            return_to_block,
        )?;

        Ok(false)
    }

    fn call_intrinsic<'a>(
        _ecx: &mut EvalContext<'a, 'tcx, Self>,
        _instance: ty::Instance<'tcx>,
        _args: &[mir::Operand<'tcx>],
        _dest: Lvalue,
        _dest_ty: Ty<'tcx>,
        _dest_layout: &'tcx layout::Layout,
        _target: mir::BasicBlock,
    ) -> EvalResult<'tcx> {
        Err(ConstEvalError::NeedsRfc("calling intrinsics".to_string()).into())
    }

    fn try_ptr_op<'a>(
        _ecx: &EvalContext<'a, 'tcx, Self>,
        _bin_op: mir::BinOp,
        left: PrimVal,
        _left_ty: Ty<'tcx>,
        right: PrimVal,
        _right_ty: Ty<'tcx>,
    ) -> EvalResult<'tcx, Option<(PrimVal, bool)>> {
        if left.is_bytes() && right.is_bytes() {
            Ok(None)
        } else {
            Err(ConstEvalError::NeedsRfc("Pointer arithmetic or comparison".to_string()).into())
        }
    }

    fn mark_static_initialized(m: !) -> EvalResult<'tcx> {
        m
    }

    fn box_alloc<'a>(
        _ecx: &mut EvalContext<'a, 'tcx, Self>,
        _ty: ty::Ty<'tcx>,
    ) -> EvalResult<'tcx, PrimVal> {
        Err(ConstEvalError::NeedsRfc("Heap allocations via `box` keyword".to_string()).into())
    }
}
<commit_msg>clarify which function is pushing a global<commit_after>use rustc::traits::Reveal;
use rustc::ty::{self, TyCtxt, Ty, Instance, layout};
use rustc::mir;

use syntax::ast::Mutability;
use syntax::codemap::Span;

use super::{
    EvalResult, EvalError, EvalErrorKind,
    GlobalId, Lvalue, Value,
    PrimVal,
    EvalContext, StackPopCleanup, PtrAndAlign,
    Kind,
};

use rustc_const_math::ConstInt;

use std::fmt;
use std::error::Error;

pub fn eval_body_as_primval<'a, 'tcx>(
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
    instance: Instance<'tcx>,
) -> EvalResult<'tcx, (PrimVal, Ty<'tcx>)> {
    let limits = super::ResourceLimits::default();
    let mut ecx = EvalContext::<CompileTimeFunctionEvaluator>::new(tcx, limits, (), ());
    let cid = GlobalId { instance, promoted: None };
    if ecx.tcx.has_attr(instance.def_id(), "linkage") {
        return Err(ConstEvalError::NotConst("extern global".to_string()).into());
    }

    let mir = ecx.load_mir(instance.def)?;
    if !ecx.globals.contains_key(&cid) {
        let size = ecx.type_size_with_substs(mir.return_ty, instance.substs)?.expect("unsized global");
        let align = ecx.type_align_with_substs(mir.return_ty, instance.substs)?;
        let ptr = ecx.memory.allocate(size, align, Kind::UninitializedStatic)?;
        let aligned = !ecx.is_packed(mir.return_ty)?;
        ecx.globals.insert(cid, PtrAndAlign { ptr: ptr.into(), aligned });
        let mutable = !mir.return_ty.is_freeze(
                ecx.tcx,
                ty::ParamEnv::empty(Reveal::All),
                mir.span);
        let mutability = if mutable {
            Mutability::Mutable
        } else {
            Mutability::Immutable
        };
        let cleanup = StackPopCleanup::MarkStatic(mutability);
        let name = ty::tls::with(|tcx| tcx.item_path_str(instance.def_id()));
        trace!("const_eval: pushing stack frame for global: {}", name);
        ecx.push_stack_frame(
            instance,
            mir.span,
            mir,
            Lvalue::from_ptr(ptr),
            cleanup,
        )?;

        while ecx.step()? {}
    }
    let value = Value::ByRef(*ecx.globals.get(&cid).expect("global not cached"));
    Ok((ecx.value_to_primval(value, mir.return_ty)?, mir.return_ty))
}

pub fn eval_body_as_integer<'a, 'tcx>(
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
    instance: Instance<'tcx>,
) -> EvalResult<'tcx, ConstInt> {
    let (prim, ty) = eval_body_as_primval(tcx, instance)?;
    let prim = prim.to_bytes()?;
    use syntax::ast::{IntTy, UintTy};
    use rustc::ty::TypeVariants::*;
    use rustc_const_math::{ConstIsize, ConstUsize};
    Ok(match ty.sty {
        TyInt(IntTy::I8) => ConstInt::I8(prim as i128 as i8),
        TyInt(IntTy::I16) => ConstInt::I16(prim as i128 as i16),
        TyInt(IntTy::I32) => ConstInt::I32(prim as i128 as i32),
        TyInt(IntTy::I64) => ConstInt::I64(prim as i128 as i64),
        TyInt(IntTy::I128) => ConstInt::I128(prim as i128),
        TyInt(IntTy::Is) => ConstInt::Isize(ConstIsize::new(prim as i128 as i64, tcx.sess.target.int_type).expect("miri should already have errored")),
        TyUint(UintTy::U8) => ConstInt::U8(prim as u8),
        TyUint(UintTy::U16) => ConstInt::U16(prim as u16),
        TyUint(UintTy::U32) => ConstInt::U32(prim as u32),
        TyUint(UintTy::U64) => ConstInt::U64(prim as u64),
        TyUint(UintTy::U128) => ConstInt::U128(prim),
        TyUint(UintTy::Us) => ConstInt::Usize(ConstUsize::new(prim as u64, tcx.sess.target.uint_type).expect("miri should already have errored")),
        _ => return Err(ConstEvalError::NeedsRfc("evaluating anything other than isize/usize during typeck".to_string()).into()),
    })
}

struct CompileTimeFunctionEvaluator;

impl<'tcx> Into<EvalError<'tcx>> for ConstEvalError {
    fn into(self) -> EvalError<'tcx> {
        EvalErrorKind::MachineError(Box::new(self)).into()
    }
}

#[derive(Clone, Debug)]
enum ConstEvalError {
    NeedsRfc(String),
    NotConst(String),
}

impl fmt::Display for ConstEvalError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::ConstEvalError::*;
        match *self {
            NeedsRfc(ref msg) =>
                write!(f, "\"{}\" needs an rfc before being allowed inside constants", msg),
            NotConst(ref msg) =>
                write!(f, "Cannot evaluate within constants: \"{}\"", msg),
        }
    }
}

impl Error for ConstEvalError {
    fn description(&self) -> &str {
        use self::ConstEvalError::*;
        match *self {
            NeedsRfc(_) =>
                "this feature needs an rfc before being allowed inside constants",
            NotConst(_) =>
                "this feature is not compatible with constant evaluation",
        }
    }

    fn cause(&self) -> Option<&Error> {
        None
    }
}

impl<'tcx> super::Machine<'tcx> for CompileTimeFunctionEvaluator {
    type Data = ();
    type MemoryData = ();
    type MemoryKinds = !;
    fn eval_fn_call<'a>(
        ecx: &mut EvalContext<'a, 'tcx, Self>,
        instance: ty::Instance<'tcx>,
        destination: Option<(Lvalue, mir::BasicBlock)>,
        _arg_operands: &[mir::Operand<'tcx>],
        span: Span,
        _sig: ty::FnSig<'tcx>,
    ) -> EvalResult<'tcx, bool> {
        if !ecx.tcx.is_const_fn(instance.def_id()) {
            return Err(ConstEvalError::NotConst(format!("calling non-const fn `{}`", instance)).into());
        }
        let mir = match ecx.load_mir(instance.def) {
            Ok(mir) => mir,
            Err(EvalError{ kind: EvalErrorKind::NoMirFor(path), ..} ) => {
                // some simple things like `malloc` might get accepted in the future
                return Err(ConstEvalError::NeedsRfc(format!("calling extern function `{}`", path)).into());
            },
            Err(other) => return Err(other),
        };
        let (return_lvalue, return_to_block) = match destination {
            Some((lvalue, block)) => (lvalue, StackPopCleanup::Goto(block)),
            None => (Lvalue::undef(), StackPopCleanup::None),
        };

        ecx.push_stack_frame(
            instance,
            span,
            mir,
            return_lvalue,
            return_to_block,
        )?;

        Ok(false)
    }

    fn call_intrinsic<'a>(
        _ecx: &mut EvalContext<'a, 'tcx, Self>,
        _instance: ty::Instance<'tcx>,
        _args: &[mir::Operand<'tcx>],
        _dest: Lvalue,
        _dest_ty: Ty<'tcx>,
        _dest_layout: &'tcx layout::Layout,
        _target: mir::BasicBlock,
    ) -> EvalResult<'tcx> {
        Err(ConstEvalError::NeedsRfc("calling intrinsics".to_string()).into())
    }

    fn try_ptr_op<'a>(
        _ecx: &EvalContext<'a, 'tcx, Self>,
        _bin_op: mir::BinOp,
        left: PrimVal,
        _left_ty: Ty<'tcx>,
        right: PrimVal,
        _right_ty: Ty<'tcx>,
    ) -> EvalResult<'tcx, Option<(PrimVal, bool)>> {
        if left.is_bytes() && right.is_bytes() {
            Ok(None)
        } else {
            Err(ConstEvalError::NeedsRfc("Pointer arithmetic or comparison".to_string()).into())
        }
    }

    fn mark_static_initialized(m: !) -> EvalResult<'tcx> {
        m
    }

    fn box_alloc<'a>(
        _ecx: &mut EvalContext<'a, 'tcx, Self>,
        _ty: ty::Ty<'tcx>,
    ) -> EvalResult<'tcx, PrimVal> {
        Err(ConstEvalError::NeedsRfc("Heap allocations via `box` keyword".to_string()).into())
    }
}
<|endoftext|>


<commit_before>enum Group<T> {
    One(T),
    Many(uint, T)
}

fn decode<T: Clone>(list: &[Group<T>]) -> ~[T] {
    list.flat_map(|e|
                match *e {
                    One(ref a)     => {
                        let l = ~[a.clone()];
                        l
                    }
                    Many(n, ref a) => {
                        let mut l = ~[];
                        for _ in range(0, n) { l.push(a.clone()) }
                        l
                    }
                })
}

fn main() {
    let list =
~[Many(4, 'a'), One('b'), Many(2, 'c'), Many(2, 'a'), One('d'), Many(4, 'e')];

    println!("{:?}", decode(list));
}
<commit_msg>Cleanup Problem 12<commit_after>// The author of this work hereby waives all claim of copyright (economic and
// moral) in this work and immediately places it in the public domain; it may
// be used, distorted or destroyed in any manner whatsoever without further
// attribution or notice to the creator.

//! Problem 12: Vectors: decode
//!
//! Given a run-length encoded vector generated by the function of the
//! previous problem, construct his uncompressed version.
//!
//! Your function could have this signature:
//! `fn decode<T: Clone>(vec: ~[Node<T>]) -> ~[T]`

enum Node<T> {
    One(T),
    Many(uint, T)
}

fn decode<T: Clone>(list: ~[Node<T>]) -> ~[T] {
    list.move_iter().flat_map(|e|
                match e {
                    One(a)     => {
                        Vec::from_elem(1, a).move_iter()
                    }
                    Many(n, a) => {
                        Vec::from_elem(n, a).move_iter()
                    }
                }).collect()
}

#[test]
fn decode_test() {
    let vec = ~[Many(4, 'a'),
                One('b'),
                Many(2, 'c'),
                Many(2, 'a'),
                One('d'),
                Many(4, 'e')];
    assert_eq!(decode(vec), ~[  'a', 'a', 'a', 'a',
                                'b',
                                'c', 'c',
                                'a', 'a',
                                'd',
                                'e', 'e', 'e', 'e']);
}
<|endoftext|>


<commit_before>// Copyright 2018 Syn Developers
//
// 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.

extern crate proc_macro2;
extern crate syn;
extern crate syntax;
extern crate syntax_pos;

use self::syntax::ast;
use self::syntax::codemap::FilePathMapping;
use self::syntax::parse::{self, ParseSess};
use self::syntax::ptr::P;
use self::syntax_pos::FileName;

use std::panic;

use self::syn::buffer::TokenBuffer;
use self::syn::synom::Synom;

pub fn libsyntax_expr(input: &str) -> Option<P<ast::Expr>> {
    match panic::catch_unwind(|| {
        let sess = ParseSess::new(FilePathMapping::empty());
        sess.span_diagnostic.set_continue_after_error(false);
        let e = parse::new_parser_from_source_str(
            &sess,
            FileName::Custom("test_precedence".to_string()),
            input.to_string(),
        ).parse_expr();
        Some(match e {
            Ok(expr) => expr,
            Err(mut diagnostic) => {
                diagnostic.emit();;
                return None;
            }
        })
    }) {
        Ok(Some(e)) => Some(e),
        Ok(None) => None,
        Err(_) => {
            errorf!("libsyntax panicked\n");
            None
        }
    }
}

pub fn syn_expr(input: &str) -> Option<syn::Expr> {
    match syn::parse_str(input) {
        Ok(e) => Some(e),
        Err(msg) => {
            errorf!("syn failed to parse\n{:?}\n", msg);
            None
        }
    }
}

pub fn syn<T: Synom>(tokens: proc_macro2::TokenStream) -> T {
    let buf = TokenBuffer::new2(tokens);
    let result = T::parse(buf.begin());
    match result {
        Ok((t, rest)) => {
            if rest.eof() {
                t
            } else if rest == buf.begin() {
                panic!("failed to parse anything")
            } else {
                panic!("failed to parse all tokens")
            }
        }
        Err(err) => panic!("failed to parse: {}", err),
    }
}
<commit_msg>Configure libsyntax to 2018 edition<commit_after>// Copyright 2018 Syn Developers
//
// 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.

extern crate proc_macro2;
extern crate syn;
extern crate syntax;
extern crate syntax_pos;

use self::syntax::ast;
use self::syntax::codemap::FilePathMapping;
use self::syntax::parse::{self, ParseSess};
use self::syntax::ptr::P;
use self::syntax_pos::{hygiene, FileName};
use self::syntax_pos::edition::Edition;

use std::panic;

use self::syn::buffer::TokenBuffer;
use self::syn::synom::Synom;

pub fn libsyntax_expr(input: &str) -> Option<P<ast::Expr>> {
    match panic::catch_unwind(|| {
        hygiene::set_default_edition(Edition::Edition2018);
        let sess = ParseSess::new(FilePathMapping::empty());
        sess.span_diagnostic.set_continue_after_error(false);
        let e = parse::new_parser_from_source_str(
            &sess,
            FileName::Custom("test_precedence".to_string()),
            input.to_string(),
        ).parse_expr();
        Some(match e {
            Ok(expr) => expr,
            Err(mut diagnostic) => {
                diagnostic.emit();;
                return None;
            }
        })
    }) {
        Ok(Some(e)) => Some(e),
        Ok(None) => None,
        Err(_) => {
            errorf!("libsyntax panicked\n");
            None
        }
    }
}

pub fn syn_expr(input: &str) -> Option<syn::Expr> {
    match syn::parse_str(input) {
        Ok(e) => Some(e),
        Err(msg) => {
            errorf!("syn failed to parse\n{:?}\n", msg);
            None
        }
    }
}

pub fn syn<T: Synom>(tokens: proc_macro2::TokenStream) -> T {
    let buf = TokenBuffer::new2(tokens);
    let result = T::parse(buf.begin());
    match result {
        Ok((t, rest)) => {
            if rest.eof() {
                t
            } else if rest == buf.begin() {
                panic!("failed to parse anything")
            } else {
                panic!("failed to parse all tokens")
            }
        }
        Err(err) => panic!("failed to parse: {}", err),
    }
}
<|endoftext|>


<commit_before>use metric::{Measured, Line, Grapheme, Metric};
use super::{NodeLink, LeafRepr };

use self::Value::*;

use std::cell::Cell;
use std::convert;
use std::default::Default;
use std::fmt;
use std::ops;

/// A lazily-evaluated field
#[derive(Clone)]
struct Lazy<T: Copy>(Cell<Option<T>>);

impl<T> Lazy<T>
where T: Copy {

    /// Get the value of the field if it has been computed
    ///
    /// # Returns
    /// - `Some(T)` if the value of this field has been computed
    /// - `None` if the field has yet to be computed
    #[inline]
    pub fn get(&self) -> Option<T> { self.0.get() }

    /// Get the value of the field, or compute it
    ///
    /// # Arguments
    /// - `f`: a function returning type `T` to use to calculate the value of
    ///        the field if it has not already been calculated
    ///
    /// # Returns
    /// - If the field has already been evaluated, the value of the field.
    /// - If the field has not been evaluated, the value of `f`
    #[inline]
    pub fn get_or_else<F>(&self, f: F) -> T
    where F: FnOnce() -> T {
        if let Some(value) = self.0.get() {
            value
        } else {
            let value = f();
            self.0.set(Some(value));
            value
        }
    }

    #[inline]
    pub fn new() -> Self {
        Lazy(Cell::new(None))
    }

}

impl<T> Default for Lazy<T>
where T: Copy {
    fn default() -> Self {
        Self::new()
    }
}

impl<T> fmt::Debug for Lazy<T>
where T: fmt::Debug
    , T: Copy {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.0.get() { Some(value) => value.fmt(f)
                           , None => write!(f, "?")

        }
    }
}

macro_rules! lazy_field {
    ($method: ident, $field: ident, $ty:ty) => {
        #[inline] fn $method(&self) -> $ty {
            self.$field.get_or_else(|| { self.value.$method() })
        }

    }
}

/// A `Node`.
#[derive(Clone, Default)]
pub struct Node { len: Lazy<usize>
                , weight: Lazy<usize>
                , line_count: Lazy<Line>
                , line_weight: Lazy<Line>
                , grapheme_count: Lazy<Grapheme>
                , grapheme_weight: Lazy<Grapheme>
                , pub value: Value
                }

impl Node {
    pub fn new(value: Value) -> Self {
        Node { value: value, ..Default::default() }
    }

    pub fn spanning(&self, i: usize, span_len: usize) -> (&Node, usize)
    where Node: Measured<usize> {
        assert!(self.len() >= span_len);
        match **self {
            Branch { ref right, ref left } if < Node as Measured<usize>>::measure_weight(self) < i => {
                // if this node is a branch, and the weight is less than the
                // index, where the span begins, then the first index of the
                // span is on the right side
                let span_i = or_zero!(i, left.len());
                assert!(or_zero!(right.len(), span_i) >= span_len);
                right.spanning(span_i, span_len)
            }
          , Branch { ref left, .. }
            // if the left child is long enough to contain the entire span,
            // walk to the left child
            if or_zero!(left.len(), i) >= span_len => left.spanning(i, span_len)
         ,  Leaf(_) | Branch {..} =>
            // if this function has walked as far as a leaf node,
            // then that leaf must be the spanning node. return it;
            //
            // otherwise, if the node is a branch node and the span is longer
            // than the left child, then this node must be the minimum
            // spanning node
            (self, i)
        }
    }
}

impl fmt::Display for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.strings()
            .fold(Ok(()), |r, string| r.and_then(|_| write!(f, "{}", string)))
    }
}

impl fmt::Debug for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!( f, "Node {{{}{}{}{:#?} }}"
              , self.len.get().map(|l| format!("{} chars, ", l))
                    .unwrap_or_else(|| { String::new() })
            //   , self.weight.get().map(|w| format!("weight: {:?}, ", w))
            //         .unwrap_or_else(|| { String::new() })
              , self.grapheme_count.get()
                    .map(|w| format!("{} graphemes, ", w.0))
                    .unwrap_or_else(|| { String::new() })
            //   , self.grapheme_weight.get().map(|w| format!("weight: {:?}, ", w))
            //         .unwrap_or_else(|| { String::new() })
              , self.line_count.get()
                  .map(|w| format!("{} lines, ", w.0))
                  .unwrap_or_else(|| { String::new() })
            //   , self.line_weight.get().map(|w| format!(", weight: {:?}", w))
            //         .unwrap_or_else(|| { String::new() })
              , self.value
              )
    }
}

impl convert::Into<NodeLink> for Node {
    #[inline] fn into(self) -> NodeLink {
        NodeLink::new(self)
    }
}

impl ops::Deref for Node {
    type Target = Value;
    fn deref(&self) -> &Value { &self.value }
}

impl Measured<usize> for Node {

        #[inline] fn to_byte_index(&self, index: usize) -> Option<usize>  {
             Some(index)
        }

        lazy_field!(measure, len, usize);
        lazy_field!(measure_weight, weight, usize);

}

impl Measured<Grapheme> for Node {

        #[inline] fn to_byte_index(&self, index: Grapheme) -> Option<usize>  {
            self.value.to_byte_index(index)
        }

        lazy_field!(measure, grapheme_count, Grapheme);
        lazy_field!(measure_weight, grapheme_weight, Grapheme);

}

impl Measured<Line> for Node {

        #[inline] fn to_byte_index(&self, index: Line) -> Option<usize>  {
            self.value.to_byte_index(index)
        }

        lazy_field!(measure, line_count, Line);
        lazy_field!(measure_weight, line_weight, Line);

}

impl<M> ops::Index<M> for Node
where M: Metric
    , Node: Measured<M>
    , LeafRepr: Measured<M>
    {
    type Output = str;

    fn index(&self, i: M) -> &str {
        let len = self.measure();
        assert!( i < len
               , "Node::index: index {:?} out of bounds (length {:?})", i, len);
        match **self {
            Leaf(ref string) => {
                let idx = string.to_byte_index(i)
                                .expect("index out of bounds!");
                &string[idx..idx+1]
            }
          , Branch { ref right, .. } if len < i =>
                &right[i - len]
          , Branch { ref left, .. } => &left[i]
        }
    }
}

/// A `Node` in the `Rope`'s tree.
///
/// A `Node` is either a `Leaf` holding a `String`, or a
/// a `Branch` concatenating together two `Node`s.
#[derive(Clone)]
pub enum Value {
    /// A leaf node
    Leaf(LeafRepr)
  , /// A branch concatenating together `l`eft and `r`ight nodes.
    Branch { /// The left branch node
             left: NodeLink
           , /// The right branch node
             right: NodeLink }
}

impl Value {
    #[inline]
    pub fn new_branch(left: NodeLink, right: NodeLink) -> Self {
        Branch { left: left, right: right }
    }
}

impl<M> Measured<M> for Value
where M: Metric
    , LeafRepr: Measured<M>
    , Node: Measured<M>
{
    fn to_byte_index(&self, index: M) -> Option<usize> {
        unimplemented!()
    }

    fn measure(&self) -> M {
        match *self {
            Leaf(ref r) => r.measure()
          , Branch { ref left, ref right } =>
                left.measure() + right.measure()
        }
    }

    fn measure_weight(&self) -> M {
        match *self {
            Leaf(ref r) => r.measure_weight()
          , Branch { ref left, .. } => left.measure()
        }
    }

}

impl convert::Into<Node> for Value {
    #[inline] fn into(self) -> Node {
        Node::new(self)
    }
}

impl Default for Value {
    fn default() -> Self {
        Leaf(LeafRepr::default())
    }
}

impl fmt::Debug for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Leaf(ref r) => write!(f, "Leaf({:?})", r)
          , Branch { ref left, ref right } => write!( f, "Branch({:?}, {:?})"
                                                    , left
                                                    , right)
        }
    }
}
<commit_msg>fix(rope internals): re-enable missing to_byte_index fn<commit_after>use metric::{Measured, Line, Grapheme, Metric};
use super::{NodeLink, LeafRepr };

use self::Value::*;

use std::cell::Cell;
use std::convert;
use std::default::Default;
use std::fmt;
use std::ops;

/// A lazily-evaluated field
#[derive(Clone)]
struct Lazy<T: Copy>(Cell<Option<T>>);

impl<T> Lazy<T>
where T: Copy {

    /// Get the value of the field if it has been computed
    ///
    /// # Returns
    /// - `Some(T)` if the value of this field has been computed
    /// - `None` if the field has yet to be computed
    #[inline]
    pub fn get(&self) -> Option<T> { self.0.get() }

    /// Get the value of the field, or compute it
    ///
    /// # Arguments
    /// - `f`: a function returning type `T` to use to calculate the value of
    ///        the field if it has not already been calculated
    ///
    /// # Returns
    /// - If the field has already been evaluated, the value of the field.
    /// - If the field has not been evaluated, the value of `f`
    #[inline]
    pub fn get_or_else<F>(&self, f: F) -> T
    where F: FnOnce() -> T {
        if let Some(value) = self.0.get() {
            value
        } else {
            let value = f();
            self.0.set(Some(value));
            value
        }
    }

    #[inline]
    pub fn new() -> Self {
        Lazy(Cell::new(None))
    }

}

impl<T> Default for Lazy<T>
where T: Copy {
    fn default() -> Self {
        Self::new()
    }
}

impl<T> fmt::Debug for Lazy<T>
where T: fmt::Debug
    , T: Copy {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.0.get() { Some(value) => value.fmt(f)
                           , None => write!(f, "?")

        }
    }
}

macro_rules! lazy_field {
    ($method: ident, $field: ident, $ty:ty) => {
        #[inline] fn $method(&self) -> $ty {
            self.$field.get_or_else(|| { self.value.$method() })
        }

    }
}

/// A `Node`.
#[derive(Clone, Default)]
pub struct Node { len: Lazy<usize>
                , weight: Lazy<usize>
                , line_count: Lazy<Line>
                , line_weight: Lazy<Line>
                , grapheme_count: Lazy<Grapheme>
                , grapheme_weight: Lazy<Grapheme>
                , pub value: Value
                }

impl Node {
    pub fn new(value: Value) -> Self {
        Node { value: value, ..Default::default() }
    }

    pub fn spanning(&self, i: usize, span_len: usize) -> (&Node, usize)
    where Node: Measured<usize> {
        assert!(self.len() >= span_len);
        match **self {
            Branch { ref right, ref left } if < Node as Measured<usize>>::measure_weight(self) < i => {
                // if this node is a branch, and the weight is less than the
                // index, where the span begins, then the first index of the
                // span is on the right side
                let span_i = or_zero!(i, left.len());
                assert!(or_zero!(right.len(), span_i) >= span_len);
                right.spanning(span_i, span_len)
            }
          , Branch { ref left, .. }
            // if the left child is long enough to contain the entire span,
            // walk to the left child
            if or_zero!(left.len(), i) >= span_len => left.spanning(i, span_len)
         ,  Leaf(_) | Branch {..} =>
            // if this function has walked as far as a leaf node,
            // then that leaf must be the spanning node. return it;
            //
            // otherwise, if the node is a branch node and the span is longer
            // than the left child, then this node must be the minimum
            // spanning node
            (self, i)
        }
    }
}

impl fmt::Display for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.strings()
            .fold(Ok(()), |r, string| r.and_then(|_| write!(f, "{}", string)))
    }
}

impl fmt::Debug for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!( f, "Node {{{}{}{}{:#?} }}"
              , self.len.get().map(|l| format!("{} chars, ", l))
                    .unwrap_or_else(|| { String::new() })
            //   , self.weight.get().map(|w| format!("weight: {:?}, ", w))
            //         .unwrap_or_else(|| { String::new() })
              , self.grapheme_count.get()
                    .map(|w| format!("{} graphemes, ", w.0))
                    .unwrap_or_else(|| { String::new() })
            //   , self.grapheme_weight.get().map(|w| format!("weight: {:?}, ", w))
            //         .unwrap_or_else(|| { String::new() })
              , self.line_count.get()
                  .map(|w| format!("{} lines, ", w.0))
                  .unwrap_or_else(|| { String::new() })
            //   , self.line_weight.get().map(|w| format!(", weight: {:?}", w))
            //         .unwrap_or_else(|| { String::new() })
              , self.value
              )
    }
}

impl convert::Into<NodeLink> for Node {
    #[inline] fn into(self) -> NodeLink {
        NodeLink::new(self)
    }
}

impl ops::Deref for Node {
    type Target = Value;
    fn deref(&self) -> &Value { &self.value }
}

impl Measured<usize> for Node {

        #[inline] fn to_byte_index(&self, index: usize) -> Option<usize>  {
             Some(index)
        }

        lazy_field!(measure, len, usize);
        lazy_field!(measure_weight, weight, usize);

}

impl Measured<Grapheme> for Node {

        #[inline] fn to_byte_index(&self, index: Grapheme) -> Option<usize>  {
            self.value.to_byte_index(index)
        }

        lazy_field!(measure, grapheme_count, Grapheme);
        lazy_field!(measure_weight, grapheme_weight, Grapheme);

}

impl Measured<Line> for Node {

        #[inline] fn to_byte_index(&self, index: Line) -> Option<usize>  {
            self.value.to_byte_index(index)
        }

        lazy_field!(measure, line_count, Line);
        lazy_field!(measure_weight, line_weight, Line);

}

impl<M> ops::Index<M> for Node
where M: Metric
    , Node: Measured<M>
    , LeafRepr: Measured<M>
    {
    type Output = str;

    fn index(&self, i: M) -> &str {
        let len = self.measure();
        assert!( i < len
               , "Node::index: index {:?} out of bounds (length {:?})", i, len);
        match **self {
            Leaf(ref string) => {
                let idx = string.to_byte_index(i)
                                .expect("index out of bounds!");
                &string[idx..idx+1]
            }
          , Branch { ref right, .. } if len < i =>
                &right[i - len]
          , Branch { ref left, .. } => &left[i]
        }
    }
}

/// A `Node` in the `Rope`'s tree.
///
/// A `Node` is either a `Leaf` holding a `String`, or a
/// a `Branch` concatenating together two `Node`s.
#[derive(Clone)]
pub enum Value {
    /// A leaf node
    Leaf(LeafRepr)
  , /// A branch concatenating together `l`eft and `r`ight nodes.
    Branch { /// The left branch node
             left: NodeLink
           , /// The right branch node
             right: NodeLink }
}

impl Value {
    #[inline]
    pub fn new_branch(left: NodeLink, right: NodeLink) -> Self {
        Branch { left: left, right: right }
    }
}

impl<M> Measured<M> for Value
where M: Metric
    , LeafRepr: Measured<M>
    , Node: Measured<M>
{
    fn to_byte_index(&self, index: M) -> Option<usize> {
        match *self {
            Leaf(ref r) => r.to_byte_index(index)
          , Branch { ref left, ref right } =>
                left.to_byte_index(index)
                    .or_else(|| { right.to_byte_index(index)
                                       .map(|i| i + left.len() ) })
        }
    }

    fn measure(&self) -> M {
        match *self {
            Leaf(ref r) => r.measure()
          , Branch { ref left, ref right } =>
                left.measure() + right.measure()
        }
    }

    fn measure_weight(&self) -> M {
        match *self {
            Leaf(ref r) => r.measure_weight()
          , Branch { ref left, .. } => left.measure()
        }
    }

}

impl convert::Into<Node> for Value {
    #[inline] fn into(self) -> Node {
        Node::new(self)
    }
}

impl Default for Value {
    fn default() -> Self {
        Leaf(LeafRepr::default())
    }
}

impl fmt::Debug for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Leaf(ref r) => write!(f, "Leaf({:?})", r)
          , Branch { ref left, ref right } => write!( f, "Branch({:?}, {:?})"
                                                    , left
                                                    , right)
        }
    }
}
<|endoftext|>


<commit_before>//! # Exception handler system

mod idt;

/// This macro creates a wrapper for the handler in order to get the
/// exception stack frame to pass it to the actual exception handler.
macro_rules! handler {
    ($name: ident) => {{
        #[naked]
        extern "C" fn wrapper() -> ! {
            unsafe {
                asm!("mov rdi, rsp
                    sub rsp, 8 // align the stack pointer
                    call $0"
                    :: "i"($name as extern "C" fn(&ExceptionStackFrame) -> !)
                    : "rdi" : "intel");
                ::core::intrinsics::unreachable();
            }
        }
        wrapper
    }}
}

// The IDT is allocated statically to ensure that this stays in memory until the end of the kernel
// execution.
lazy_static! {
    #[derive(Debug)]
    static ref IDT: idt::Idt = {
        // create a new IDT structure
        let mut idt = idt::Idt::new();

        // set the handler for the zero division exception
        idt.set_handler(0, handler!(divide_by_zero_handler));
        idt.set_handler(6, handler!(invalid_opcode_handler));

        idt
    };
}

#[derive(Debug)]
#[repr(C)]
struct ExceptionStackFrame {
    instruction_pointer: u64,
    code_segment: u64,
    cpu_flags: u64,
    stack_pointer: u64,
    stack_segment: u64,
}

/// Initialize the IDT
pub fn init() {
    // load the IDT table into the CPU
    IDT.load();
}

/// Handler for the division by zero exception
extern "C" fn divide_by_zero_handler(stack_frame: &ExceptionStackFrame) -> ! {
    // print out the error message and the stack_frame
    println!("\nEXCEPTION: DIVIDE BY ZERO\n{:#?}", stack_frame);
    loop {}
}

/// Handler for a invalid opcode exception
extern "C" fn invalid_opcode_handler(stack_frame: &ExceptionStackFrame) -> ! {
    println!("\nEXCEPTION: INVALID OPCODE at {:#x}\n{:#?}\n",
        stack_frame.instruction_pointer, stack_frame);
    loop {}
}
<commit_msg>Add a handler to catch page faults<commit_after>//! # Exception handler system

mod idt;

/// This macro creates a wrapper for the handler in order to get the
/// exception stack frame to pass it to the actual exception handler.
macro_rules! handler {
    ($name: ident) => {{
        #[naked]
        extern "C" fn wrapper() -> ! {
            unsafe {
                asm!("mov rdi, rsp
                    sub rsp, 8 // align the stack pointer
                    call $0"
                    :: "i"($name as extern "C" fn(&ExceptionStackFrame) -> !)
                    : "rdi" : "intel");
                ::core::intrinsics::unreachable();
            }
        }
        wrapper
    }}
}

/// This macro creates a wrapper for the handler  to exception that support error codes, in order to
/// get the exception stack frame to pass it to the actual exception handler, and the error code.
macro_rules! handler_with_error_code {
    ($name: ident) => {{
        #[naked]
        extern "C" fn wrapper() -> ! {
            unsafe {
                asm!("pop rsi // pop error code into rsi
                    mov rdi, rsp
                    sub rsp, 8 // align the stack pointer
                    call $0"
                    :: "i"($name as extern "C" fn(&ExceptionStackFrame, u64) -> !)
                    : "rdi" : "intel");
                ::core::intrinsics::unreachable();
            }
        }
        wrapper
    }}
}

// The IDT is allocated statically to ensure that this stays in memory until the end of the kernel
// execution.
lazy_static! {
    #[derive(Debug)]
    static ref IDT: idt::Idt = {
        // create a new IDT structure
        let mut idt = idt::Idt::new();

        // set the handler for the zero division exception
        idt.set_handler(0, handler!(divide_by_zero_handler));
        idt.set_handler(6, handler!(invalid_opcode_handler));
        idt.set_handler(14, handler_with_error_code!(page_fault_exception));

        idt
    };
}

bitflags! {
    flags PageFaultErrorCode: u64 {
        const PROTECTION_VIOLATION = 1 << 0,
        const CAUSED_BY_WRITE = 1 << 1,
        const USER_MODE = 1 << 2,
        const MALFORMED_TABLE = 1 << 3,
        const INSTRUCTION_FETCH = 1 << 4,
    }
}

#[derive(Debug)]
#[repr(C)]
struct ExceptionStackFrame {
    instruction_pointer: u64,
    code_segment: u64,
    cpu_flags: u64,
    stack_pointer: u64,
    stack_segment: u64,
}

/// Initialize the IDT
pub fn init() {
    // load the IDT table into the CPU
    IDT.load();
}

/// Handler for the division by zero exception
extern "C" fn divide_by_zero_handler(stack_frame: &ExceptionStackFrame) -> ! {
    // print out the error message and the stack_frame
    println!("\nEXCEPTION: DIVIDE BY ZERO\n{:#?}", stack_frame);
    loop {}
}

/// Handler for a invalid opcode exception
extern "C" fn invalid_opcode_handler(stack_frame: &ExceptionStackFrame) -> ! {
    println!("\nEXCEPTION: INVALID OPCODE at {:#x}\n{:#?}\n",
        stack_frame.instruction_pointer, stack_frame);
    loop {}
}

extern "C" fn page_fault_exception(stack_frame: &ExceptionStackFrame, error_code: u64) -> ! {
    use x86::shared::control_regs;

    println!("\nEXCEPTION: PAGE FAULT while accessing {:#x}\
        \nerror code: {:?}\n{:#?}",
        unsafe { control_regs::cr2() },
        PageFaultErrorCode::from_bits(error_code).unwrap(),
        stack_frame);
    loop {}
}
<|endoftext|>


<commit_before>//! Tests!
extern crate fern;
extern crate log;
extern crate tempdir;

use std::io::prelude::*;
use std::{fs, io};

use log::Level::*;

mod support;

use support::manual_log;

#[test]
fn test_basic_logging_file_logging() {
    // Create a temporary directory to put a log file into for testing
    let temp_log_dir = tempdir::TempDir::new("fern").expect("Failed to set up temporary directory");
    let log_file = temp_log_dir.path().join("test.log");

    {
        // Create a basic logger configuration
        let (_max_level, logger) = fern::Dispatch::new()
        .format(|out, msg, record| {
            out.finish(format_args!("[{}] {}", record.level(), msg))
        })
        // Only log messages Info and above
        .level(log::LevelFilter::Info)
        // Output to stdout and the log file in the temporary directory we made above to test
        .chain(io::stdout())
        .chain(fern::log_file(log_file).expect("Failed to open log file"))
        .into_log();

        let l = &*logger;
        manual_log(l, Trace, "SHOULD NOT DISPLAY");
        manual_log(l, Debug, "SHOULD NOT DISPLAY");
        manual_log(l, Info, "Test information message");
        manual_log(l, Warn, "Test warning message");
        manual_log(l, Error, "Test error message");

        // ensure all File objects are dropped and OS buffers are flushed.
        log::logger().flush();

        {
            let result = {
                let mut log_read = fs::File::open(&temp_log_dir.path().join("test.log")).unwrap();
                let mut buf = String::new();
                log_read.read_to_string(&mut buf).unwrap();
                buf
            };
            assert!(
                !result.contains("SHOULD NOT DISPLAY"),
                "expected result not including \"SHOULD_NOT_DISPLAY\", found:\n```\n{}\n```\n",
                result
            );
            assert!(
                result.contains("[INFO] Test information message"),
                "expected result including \"[INFO] Test information message\", found:\n```\n{}\n```\n",
                result
            );
            assert!(
                result.contains("[WARN] Test warning message"),
                "expected result including \"[WARN] Test warning message\", found:\n```\n{}\n```\n",
                result
            );
            assert!(
                result.contains("[ERROR] Test error message"),
                "expected result to not include \"[ERROR] Test error message\", found:\n```\n{}\n```\n",
                result
            );
        }
    } // ensure logger is dropped before temp dir

    temp_log_dir
        .close()
        .expect("Failed to clean up temporary directory");
}

#[test]
fn test_custom_line_separators() {
    // Create a temporary directory to put a log file into for testing
    let temp_log_dir = tempdir::TempDir::new("fern").expect("Failed to set up temporary directory");
    let log_file = temp_log_dir.path().join("test_custom_line_sep.log");

    {
        // Create a basic logger configuration
        let (_max_level, logger) = fern::Dispatch::new()
        // default format is just the message if not specified
        // default log level is 'trace' if not specified (logs all messages)
        // output to the log file with the "\r\n" line separator.
        .chain(fern::Output::file(fern::log_file(&log_file).expect("Failed to open log file"), "\r\n"))
        .into_log();

        let l = &*logger;
        manual_log(l, Info, "message1");
        manual_log(l, Info, "message2");

        // ensure all File objects are dropped and OS buffers are flushed.
        logger.flush();

        {
            let result = {
                let mut log_read = fs::File::open(&temp_log_dir.path().join("test_custom_line_sep.log")).unwrap();
                let mut buf = String::new();
                log_read.read_to_string(&mut buf).unwrap();
                buf
            };
            assert_eq!(&result, "message1\r\nmessage2\r\n");
        }
    } // ensure logger is dropped before temp dir

    temp_log_dir
        .close()
        .expect("Failed to clean up temporary directory");
}
<commit_msg>Clean up formatting for file_logging test<commit_after>//! Tests!
extern crate fern;
extern crate log;
extern crate tempdir;

use std::io::prelude::*;
use std::{fs, io};

use log::Level::*;

mod support;

use support::manual_log;

#[test]
fn test_basic_logging_file_logging() {
    // Create a temporary directory to put a log file into for testing
    let temp_log_dir = tempdir::TempDir::new("fern").expect("Failed to set up temporary directory");
    let log_file = temp_log_dir.path().join("test.log");

    {
        // Create a basic logger configuration
        let (_max_level, logger) = fern::Dispatch::new()
            .format(|out, msg, record| out.finish(format_args!("[{}] {}", record.level(), msg)))
            .level(log::LevelFilter::Info)
            .chain(io::stdout())
            .chain(fern::log_file(log_file).expect("Failed to open log file"))
            .into_log();

        let l = &*logger;
        manual_log(l, Trace, "SHOULD NOT DISPLAY");
        manual_log(l, Debug, "SHOULD NOT DISPLAY");
        manual_log(l, Info, "Test information message");
        manual_log(l, Warn, "Test warning message");
        manual_log(l, Error, "Test error message");

        // ensure all File objects are dropped and OS buffers are flushed.
        log::logger().flush();

        {
            let result = {
                let mut log_read = fs::File::open(&temp_log_dir.path().join("test.log")).unwrap();
                let mut buf = String::new();
                log_read.read_to_string(&mut buf).unwrap();
                buf
            };
            assert!(
                !result.contains("SHOULD NOT DISPLAY"),
                "expected result not including \"SHOULD_NOT_DISPLAY\", found:\n```\n{}\n```\n",
                result
            );
            assert!(
                result.contains("[INFO] Test information message"),
                "expected result including \"[INFO] Test information message\", found:\n```\n{}\n```\n",
                result
            );
            assert!(
                result.contains("[WARN] Test warning message"),
                "expected result including \"[WARN] Test warning message\", found:\n```\n{}\n```\n",
                result
            );
            assert!(
                result.contains("[ERROR] Test error message"),
                "expected result to not include \"[ERROR] Test error message\", found:\n```\n{}\n```\n",
                result
            );
        }
    } // ensure logger is dropped before temp dir

    temp_log_dir
        .close()
        .expect("Failed to clean up temporary directory");
}

#[test]
fn test_custom_line_separators() {
    // Create a temporary directory to put a log file into for testing
    let temp_log_dir = tempdir::TempDir::new("fern").expect("Failed to set up temporary directory");
    let log_file = temp_log_dir.path().join("test_custom_line_sep.log");

    {
        // Create a basic logger configuration
        let (_max_level, logger) = fern::Dispatch::new()
            // default format is just the message if not specified
            // default log level is 'trace' if not specified (logs all messages)
            // output to the log file with the "\r\n" line separator.
            .chain(fern::Output::file(fern::log_file(&log_file).expect("Failed to open log file"), "\r\n"))
            .into_log();

        let l = &*logger;
        manual_log(l, Info, "message1");
        manual_log(l, Info, "message2");

        // ensure all File objects are dropped and OS buffers are flushed.
        logger.flush();

        {
            let result = {
                let mut log_read = fs::File::open(&temp_log_dir.path().join("test_custom_line_sep.log")).unwrap();
                let mut buf = String::new();
                log_read.read_to_string(&mut buf).unwrap();
                buf
            };
            assert_eq!(&result, "message1\r\nmessage2\r\n");
        }
    } // ensure logger is dropped before temp dir

    temp_log_dir
        .close()
        .expect("Failed to clean up temporary directory");
}
<|endoftext|>