<commit_before>
#![feature(globs)]

extern crate graphics;
extern crate piston;
extern crate sdl2_game_window;
extern crate gfx;
extern crate gfx_graphics;

use gfx::{Device, DeviceHelper};
use gfx_graphics::{
    Gfx2d,
    RenderContext,
    Texture,
};
use sdl2_game_window::WindowSDL2;
use graphics::*;
use piston::{
    AssetStore,
    EventIterator,
    EventSettings,
    WindowSettings,
    Render,
};

fn main() {
    let opengl = piston::shader_version::opengl::OpenGL_3_2;
    let mut window = WindowSDL2::new(
        opengl,
        WindowSettings {
            title: "Image".to_string(),
            size: [300, 300],
            fullscreen: false,
            exit_on_esc: true,
            samples: 0,
        }
    );

    let (mut device, frame) = window.gfx();
    let mut renderer = device.create_renderer();

    let asset_store = AssetStore::from_folder("../bin/assets");

    let image = asset_store.path("rust-logo.png").unwrap();
    let image = Texture::from_path(&mut device, &image).unwrap();
    let event_settings = EventSettings {
            updates_per_second: 120,
            max_frames_per_second: 60,
        };
    let mut gfx2d = Gfx2d::new(&mut device);
    for e in EventIterator::new(&mut window, &event_settings) {
        match e {
            Render(args) => {
                {
                    let ref mut g = RenderContext::new(&mut renderer, &frame, &mut gfx2d);
                    let c = Context::abs(args.width as f64, args.height as f64);
                    c.rgb(1.0, 1.0, 1.0).draw(g);
                    c.rect(0.0, 0.0, 100.0, 100.0).rgb(1.0, 0.0, 0.0).draw(g);
                    c.rect(50.0, 50.0, 100.0, 100.0).rgba(0.0, 1.0, 0.0, 0.3).draw(g);
                    c.trans(100.0, 100.0).image(&image).draw(g);
                }

                device.submit(renderer.as_buffer());
                renderer.reset();
            },
            _ => {},
        }
    }
}
<commit_msg>Upgraded example<commit_after>
#![feature(globs)]

extern crate graphics;
extern crate piston;
extern crate sdl2_game_window;
extern crate gfx;
extern crate gfx_graphics;
extern crate sdl2;

use gfx::{Device, DeviceHelper};
use gfx_graphics::{
    Gfx2d,
    RenderContext,
    Texture,
};
use sdl2_game_window::WindowSDL2;
use graphics::*;
use piston::{
    AssetStore,
    EventIterator,
    EventSettings,
    Window,
    WindowSettings,
    Render,
};

fn main() {
    let opengl = piston::shader_version::opengl::OpenGL_3_2;
    let mut window = WindowSDL2::new(
        opengl,
        WindowSettings {
            title: "Image".to_string(),
            size: [300, 300],
            fullscreen: false,
            exit_on_esc: true,
            samples: 0,
        }
    );

    let mut device = gfx::GlDevice::new(|s| unsafe {
        std::mem::transmute(sdl2::video::gl_get_proc_address(s))
    });
    let (w, h) = window.get_size();
    let frame = gfx::Frame::new(w as u16, h as u16);
    let mut renderer = device.create_renderer();

    let asset_store = AssetStore::from_folder("../bin/assets");

    let image = asset_store.path("rust-logo.png").unwrap();
    let image = Texture::from_path(&mut device, &image).unwrap();
    let event_settings = EventSettings {
            updates_per_second: 120,
            max_frames_per_second: 60,
        };
    let mut gfx2d = Gfx2d::new(&mut device);
    for e in EventIterator::new(&mut window, &event_settings) {
        match e {
            Render(args) => {
                {
                    let ref mut g = RenderContext::new(&mut renderer, &frame, &mut gfx2d);
                    let c = Context::abs(args.width as f64, args.height as f64);
                    c.rgb(1.0, 1.0, 1.0).draw(g);
                    c.rect(0.0, 0.0, 100.0, 100.0).rgb(1.0, 0.0, 0.0).draw(g);
                    c.rect(50.0, 50.0, 100.0, 100.0).rgba(0.0, 1.0, 0.0, 0.3).draw(g);
                    c.trans(100.0, 100.0).image(&image).draw(g);
                }

                device.submit(renderer.as_buffer());
                renderer.reset();
            },
            _ => {},
        }
    }
}
<|endoftext|>


<commit_before>use core::hashmap::linear::{ LinearMap };

use std::sort::{ quick_sort3 };

use common::calc::{ num_to_digits };
use common::problem::{ Problem };

pub static problem: Problem<'static> = Problem {
    id: 62,
    answer: "127035954683",
    solver: solve
};

fn solve() -> ~str {
    let mut map = LinearMap::new::<~[uint], ~[uint]>();
    let mut n = 0;
    loop {
        n += 1;
        let cube = n * n * n;
        let mut ds = num_to_digits(cube, 10);
        quick_sort3(ds);

        let v = match map.pop(&ds) {
            Some(nums) => nums + ~[ cube ],
            None       => ~[cube]
        };
        if v.len() == 5 {
            return v[0].to_str();
        }
        map.insert(ds, v);
    }
}

<commit_msg>Improve problem #62<commit_after>use core::hashmap::linear::{ LinearMap, LinearSet };

use std::sort::{ quick_sort3 };

use common::calc::{ num_to_digits };
use common::problem::{ Problem };

pub static problem: Problem<'static> = Problem {
    id: 62,
    answer: "127035954683",
    solver: solve
};

fn solve() -> ~str {
    let mut map = LinearMap::new::<~[uint], ~[uint]>();
    let mut set = LinearSet::new::<uint>();
    let mut n     = 0;
    let mut limit = 10;
    loop {
        n += 1;
        if n >= limit {
            if !set.is_empty() {
                break;
            }
            limit *= 10;
        }

        let cube = n * n * n;
        let mut ds = num_to_digits(cube, 10);
        quick_sort3(ds);

        let v = match map.pop(&ds) {
            Some(nums) => nums + ~[ cube ],
            None       => ~[cube]
        };
        if v.len() == 5 {
            set.insert(v[0]);
        }
        if v.len() == 6 {
            set.remove(&v[0]);
        }
        map.insert(ds, v);
    }

    let mut answer = uint::max_value;
    for set.each |&n| {
        if n < answer { answer = n; }
    }
    return answer.to_str();
}

<|endoftext|>


<commit_before>use std::os::raw::c_char;

use std::borrow::Cow;

use JNIEnv;

use objects::JString;

use errors::*;

use strings::JNIStr;

/// Reference to a string in the JVM. Holds a pointer to the array
/// returned by GetStringUTFChars. Calls ReleaseStringUTFChars on Drop.
/// Can be converted to a `&JNIStr` with the same cost as the `&CStr.from_ptr`
/// conversion.
pub struct JavaStr<'a> {
    internal: *const c_char,
    obj: JString<'a>,
    env: &'a JNIEnv<'a>,
}

impl<'a> JavaStr<'a> {
    /// Build a `JavaStr` from an object and a reference to the environment. You
    /// probably want to use `JNIEnv::get_string` instead.
    pub fn from_env(env: &'a JNIEnv<'a>, obj: JString<'a>) -> Result<Self> {
        let ptr = unsafe { env.get_string_utf_chars(obj)? };
        let java_str = JavaStr {
            internal: ptr,
            env: env,
            obj: obj,
        };
        Ok(java_str)
    }
}

impl<'a> ::std::ops::Deref for JavaStr<'a> {
    type Target = JNIStr;
    fn deref(&self) -> &Self::Target {
        self.into()
    }
}

impl<'a> From<&'a JavaStr<'a>> for &'a JNIStr {
    fn from(other: &'a JavaStr) -> &'a JNIStr {
        unsafe { JNIStr::from_ptr(other.internal) }
    }
}

impl<'a> From<&'a JavaStr<'a>> for Cow<'a, str> {
    fn from(other: &'a JavaStr) -> Cow<'a, str> {
        let jni_str: &JNIStr = &*other;
        jni_str.into()
    }
}

impl<'a> From<JavaStr<'a>> for String {
    fn from(other: JavaStr) -> String {
        let cow: Cow<str> = (&other).into();
        cow.into_owned()
    }
}

impl<'a> Drop for JavaStr<'a> {
    fn drop(&mut self) {
        match unsafe {
            self.env.release_string_utf_chars(self.obj, self.internal)
        } {
            Ok(()) => {}
            Err(e) => warn!("error dropping java str: {}", e),
        }
    }
}
<commit_msg>Add get_raw to JavaStr<commit_after>use std::os::raw::c_char;

use std::borrow::Cow;

use JNIEnv;

use objects::JString;

use errors::*;

use strings::JNIStr;

/// Reference to a string in the JVM. Holds a pointer to the array
/// returned by GetStringUTFChars. Calls ReleaseStringUTFChars on Drop.
/// Can be converted to a `&JNIStr` with the same cost as the `&CStr.from_ptr`
/// conversion.
pub struct JavaStr<'a> {
    internal: *const c_char,
    obj: JString<'a>,
    env: &'a JNIEnv<'a>,
}

impl<'a> JavaStr<'a> {
    /// Build a `JavaStr` from an object and a reference to the environment. You
    /// probably want to use `JNIEnv::get_string` instead.
    pub fn from_env(env: &'a JNIEnv<'a>, obj: JString<'a>) -> Result<Self> {
        let ptr = unsafe { env.get_string_utf_chars(obj)? };
        let java_str = JavaStr {
            internal: ptr,
            env: env,
            obj: obj,
        };
        Ok(java_str)
    }

    /// Extract the raw C string pointer from the JavaStr. This will be
    /// encoded using the JVM internal `CESU-8`-style.
    pub fn get_raw(&self) -> *const c_char {
        self.internal
    }
}

impl<'a> ::std::ops::Deref for JavaStr<'a> {
    type Target = JNIStr;
    fn deref(&self) -> &Self::Target {
        self.into()
    }
}

impl<'a> From<&'a JavaStr<'a>> for &'a JNIStr {
    fn from(other: &'a JavaStr) -> &'a JNIStr {
        unsafe { JNIStr::from_ptr(other.internal) }
    }
}

impl<'a> From<&'a JavaStr<'a>> for Cow<'a, str> {
    fn from(other: &'a JavaStr) -> Cow<'a, str> {
        let jni_str: &JNIStr = &*other;
        jni_str.into()
    }
}

impl<'a> From<JavaStr<'a>> for String {
    fn from(other: JavaStr) -> String {
        let cow: Cow<str> = (&other).into();
        cow.into_owned()
    }
}

impl<'a> Drop for JavaStr<'a> {
    fn drop(&mut self) {
        match unsafe { self.env.release_string_utf_chars(self.obj, self.internal) } {
            Ok(()) => {}
            Err(e) => warn!("error dropping java str: {}", e),
        }
    }
}

<|endoftext|>


<commit_before>// Copyright 2018 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate colored;
extern crate dirs;
extern crate evcxr;
extern crate regex;
extern crate rustyline;

use colored::*;
use evcxr::{CommandContext, CompilationError, Error};
use rustyline::{error::ReadlineError, Editor};
use std::fs;
use std::io;
use std::sync::mpsc;

const PROMPT: &str = "# ";

struct Repl {
    command_context: CommandContext,
}

fn send_output<T: io::Write + Send + 'static>(channel: mpsc::Receiver<String>, mut output: T) {
    std::thread::spawn(move || {
        while let Ok(line) = channel.recv() {
            if writeln!(output, "{}", line).is_err() {
                break;
            }
        }
    });
}

impl Repl {
    fn new() -> Result<Repl, Error> {
        let (command_context, outputs) = CommandContext::new()?;
        send_output(outputs.stdout, io::stdout());
        send_output(outputs.stderr, io::stderr());
        Ok(Repl { command_context })
    }

    fn execute(&mut self, to_run: &str) {
        match self.command_context.execute(to_run) {
            Ok(output) => {
                if let Some(text) = output.get("text/plain") {
                    println!("{}", text);
                }
            }
            Err(evcxr::Error::CompilationErrors(errors)) => {
                self.display_errors(errors);
            }
            Err(evcxr::Error::ChildProcessTerminated(err))
            | Err(evcxr::Error::JustMessage(err)) => eprintln!("{}", err.bright_red()),
        }
    }

    fn display_errors(&mut self, errors: Vec<CompilationError>) {
        for error in errors {
            if error.is_from_user_code() {
                for spanned_message in error.spanned_messages() {
                    if let Some(span) = &spanned_message.span {
                        for _ in 1..span.start_column + PROMPT.len() {
                            print!(" ");
                        }
                        let mut carrots = String::new();
                        for _ in span.start_column..span.end_column {
                            carrots.push('^');
                        }
                        print!("{}", carrots.bright_red());
                        println!(" {}", spanned_message.label.bright_blue());
                    } else {
                        // Our error originates from both user-code and generated
                        // code.
                        println!("{}", spanned_message.label.bright_blue());
                    }
                }
                println!("{}", error.message().bright_red());
                for help in error.help() {
                    println!("{} {}", "help:".bold(), help);
                }
                if let Some(extra_hint) = error.evcxr_extra_hint() {
                    println!("{}", extra_hint);
                }
            } else {
                println!(
                    "A compilation error was found in code we generated.\n\
                     Ideally this should't happen. Type :last_error_json to see details.\n{}",
                    error.rendered()
                );
            }
        }
    }
}

fn main() {
    evcxr::runtime_hook();
    println!("Welcome to evcxr. For help, type .help");
    let mut repl = match Repl::new() {
        Ok(c) => c,
        Err(error) => {
            eprintln!("{}", error);
            return;
        }
    };

    let mut editor = Editor::<()>::new();
    let mut opt_history_file = None;
    let config_dir = dirs::config_dir().map(|h| h.join("evcxr"));
    if let Some(config_dir) = &config_dir {
        fs::create_dir_all(config_dir).ok();
        let history_file = config_dir.join("history.txt");
        editor.load_history(&history_file).ok();
        opt_history_file = Some(history_file);
    }
    loop {
        let readline = editor.readline(&PROMPT.yellow());
        match readline {
            Ok(line) => {
                editor.add_history_entry(&line);
                repl.execute(&line);
            }
            Err(ReadlineError::Interrupted) | Err(ReadlineError::Eof) => break,
            Err(err) => {
                eprintln!("Error: {:?}", err);
                break;
            }
        }
    }
    if let Some(history_file) = &opt_history_file {
        editor.save_history(&history_file).ok();
    }
}
<commit_msg>Fix welcome message: .help -> :help<commit_after>// Copyright 2018 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate colored;
extern crate dirs;
extern crate evcxr;
extern crate regex;
extern crate rustyline;

use colored::*;
use evcxr::{CommandContext, CompilationError, Error};
use rustyline::{error::ReadlineError, Editor};
use std::fs;
use std::io;
use std::sync::mpsc;

const PROMPT: &str = "# ";

struct Repl {
    command_context: CommandContext,
}

fn send_output<T: io::Write + Send + 'static>(channel: mpsc::Receiver<String>, mut output: T) {
    std::thread::spawn(move || {
        while let Ok(line) = channel.recv() {
            if writeln!(output, "{}", line).is_err() {
                break;
            }
        }
    });
}

impl Repl {
    fn new() -> Result<Repl, Error> {
        let (command_context, outputs) = CommandContext::new()?;
        send_output(outputs.stdout, io::stdout());
        send_output(outputs.stderr, io::stderr());
        Ok(Repl { command_context })
    }

    fn execute(&mut self, to_run: &str) {
        match self.command_context.execute(to_run) {
            Ok(output) => {
                if let Some(text) = output.get("text/plain") {
                    println!("{}", text);
                }
            }
            Err(evcxr::Error::CompilationErrors(errors)) => {
                self.display_errors(errors);
            }
            Err(evcxr::Error::ChildProcessTerminated(err))
            | Err(evcxr::Error::JustMessage(err)) => eprintln!("{}", err.bright_red()),
        }
    }

    fn display_errors(&mut self, errors: Vec<CompilationError>) {
        for error in errors {
            if error.is_from_user_code() {
                for spanned_message in error.spanned_messages() {
                    if let Some(span) = &spanned_message.span {
                        for _ in 1..span.start_column + PROMPT.len() {
                            print!(" ");
                        }
                        let mut carrots = String::new();
                        for _ in span.start_column..span.end_column {
                            carrots.push('^');
                        }
                        print!("{}", carrots.bright_red());
                        println!(" {}", spanned_message.label.bright_blue());
                    } else {
                        // Our error originates from both user-code and generated
                        // code.
                        println!("{}", spanned_message.label.bright_blue());
                    }
                }
                println!("{}", error.message().bright_red());
                for help in error.help() {
                    println!("{} {}", "help:".bold(), help);
                }
                if let Some(extra_hint) = error.evcxr_extra_hint() {
                    println!("{}", extra_hint);
                }
            } else {
                println!(
                    "A compilation error was found in code we generated.\n\
                     Ideally this should't happen. Type :last_error_json to see details.\n{}",
                    error.rendered()
                );
            }
        }
    }
}

fn main() {
    evcxr::runtime_hook();
    println!("Welcome to evcxr. For help, type :help");
    let mut repl = match Repl::new() {
        Ok(c) => c,
        Err(error) => {
            eprintln!("{}", error);
            return;
        }
    };

    let mut editor = Editor::<()>::new();
    let mut opt_history_file = None;
    let config_dir = dirs::config_dir().map(|h| h.join("evcxr"));
    if let Some(config_dir) = &config_dir {
        fs::create_dir_all(config_dir).ok();
        let history_file = config_dir.join("history.txt");
        editor.load_history(&history_file).ok();
        opt_history_file = Some(history_file);
    }
    loop {
        let readline = editor.readline(&PROMPT.yellow());
        match readline {
            Ok(line) => {
                editor.add_history_entry(&line);
                repl.execute(&line);
            }
            Err(ReadlineError::Interrupted) | Err(ReadlineError::Eof) => break,
            Err(err) => {
                eprintln!("Error: {:?}", err);
                break;
            }
        }
    }
    if let Some(history_file) = &opt_history_file {
        editor.save_history(&history_file).ok();
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#![cfg_attr(windows, allow(unused))]

//! Emulates virtual and hardware devices.

mod bus;
mod cmos;
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
mod debugcon;
#[cfg(feature = "direct")]
pub mod direct_io;
#[cfg(feature = "direct")]
pub mod direct_irq;
mod i8042;
mod irq_event;
pub mod irqchip;
mod pci;
pub mod pl030;
#[cfg(feature = "usb")]
#[macro_use]
mod register_space;
mod serial;
pub mod serial_device;
#[cfg(feature = "tpm")]
mod software_tpm;
mod sys;
pub mod virtio;
#[cfg(all(feature = "tpm", feature = "chromeos", target_arch = "x86_64"))]
mod vtpm_proxy;

cfg_if::cfg_if! {
    if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
        mod pit;
        pub use self::pit::{Pit, PitError};
        pub mod tsc;
    }
}

pub use self::bus::Error as BusError;
pub use self::bus::{
    Bus, BusAccessInfo, BusDevice, BusDeviceObj, BusDeviceSync, BusRange, BusResumeDevice, BusType,
    HostHotPlugKey, HotPlugBus,
};
pub use self::cmos::Cmos;
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub use self::debugcon::Debugcon;
#[cfg(feature = "direct")]
pub use self::direct_io::{DirectIo, DirectMmio};
#[cfg(feature = "direct")]
pub use self::direct_irq::{DirectIrq, DirectIrqError};
pub use self::i8042::I8042Device;
pub use self::irq_event::{IrqEdgeEvent, IrqLevelEvent};
pub use self::irqchip::*;
pub use self::pci::CrosvmDeviceId;
pub use self::pci::{
    BarRange, PciAddress, PciAddressError, PciBus, PciClassCode, PciConfigIo, PciConfigMmio,
    PciDevice, PciDeviceError, PciInterruptPin, PciRoot, PciVirtualConfigMmio, StubPciDevice,
    StubPciParameters,
};
pub use self::pl030::Pl030;
pub use self::serial::Serial;
pub use self::serial_device::{
    Error as SerialError, SerialDevice, SerialHardware, SerialParameters, SerialType,
};
#[cfg(feature = "tpm")]
pub use self::software_tpm::SoftwareTpm;
#[cfg(all(feature = "tpm", feature = "chromeos", target_arch = "x86_64"))]
pub use self::vtpm_proxy::VtpmProxy;

cfg_if::cfg_if! {
    if #[cfg(unix)] {
        mod platform;
        mod proxy;
        pub mod acpi;
        pub mod bat;
        #[cfg(feature = "usb")]
        pub mod usb;
        #[cfg(feature = "usb")]
        mod utils;
        pub mod vfio;

        pub use self::acpi::ACPIPMResource;
        pub use self::bat::{BatteryError, GoldfishBattery};
        #[cfg(feature = "audio")]
        pub use self::pci::{Ac97Backend, Ac97Dev, Ac97Parameters};
        pub use self::pci::{
            CoIommuDev, CoIommuParameters, CoIommuUnpinPolicy,
            PvPanicCode, PcieRootPort, PcieHostPort,
            PvPanicPciDevice, VfioPciDevice, PciBridge,
        };
        pub use self::platform::VfioPlatformDevice;
        pub use self::proxy::Error as ProxyError;
        pub use self::proxy::ProxyDevice;
        #[cfg(feature = "usb")]
        pub use self::usb::host_backend::host_backend_device_provider::HostBackendDeviceProvider;
        #[cfg(feature = "usb")]
        pub use self::usb::xhci::xhci_controller::XhciController;
        pub use self::vfio::{VfioContainer, VfioDevice};
        pub use self::virtio::{vfio_wrapper, VirtioPciDevice};

        /// Request CoIOMMU to unpin a specific range.
        use serde::{Deserialize, Serialize};
        #[derive(Serialize, Deserialize, Debug)]
        pub struct UnpinRequest {
            /// The ranges presents (start gfn, count).
            ranges: Vec<(u64, u64)>,
        }

        #[derive(Serialize, Deserialize, Debug)]
        pub enum UnpinResponse {
            Success,
            Failed,
        }

        #[derive(Debug)]
        pub enum ParseIommuDevTypeResult {
            NoSuchType,
        }

        #[derive(Copy, Clone, Eq, PartialEq)]
        pub enum IommuDevType {
            NoIommu,
            VirtioIommu,
            CoIommu,
        }

        use std::str::FromStr;
        impl FromStr for IommuDevType {
            type Err = ParseIommuDevTypeResult;

            fn from_str(s: &str) -> Result<Self, Self::Err> {
                match s {
                    "off" => Ok(IommuDevType::NoIommu),
                    "viommu" => Ok(IommuDevType::VirtioIommu),
                    "coiommu" => Ok(IommuDevType::CoIommu),
                    _ => Err(ParseIommuDevTypeResult::NoSuchType),
                }
            }
        }
    } else if #[cfg(windows)] {
        // We define Minijail as an empty struct on Windows because the concept
        // of jailing is baked into a bunch of places where it isn't easy
        // to compile it out. In the long term, this should go away.
        #[cfg(windows)]
        pub struct Minijail {}
    } else {
        compile_error!("Unsupported platform");
    }
}
<commit_msg>devices: move lib.rs common functions<commit_after>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#![cfg_attr(windows, allow(unused))]

//! Emulates virtual and hardware devices.

mod bus;
mod cmos;
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
mod debugcon;
#[cfg(feature = "direct")]
pub mod direct_io;
#[cfg(feature = "direct")]
pub mod direct_irq;
mod i8042;
mod irq_event;
pub mod irqchip;
mod pci;
pub mod pl030;
#[cfg(feature = "usb")]
#[macro_use]
mod register_space;
mod serial;
pub mod serial_device;
#[cfg(feature = "tpm")]
mod software_tpm;
mod sys;
pub mod virtio;
#[cfg(all(feature = "tpm", feature = "chromeos", target_arch = "x86_64"))]
mod vtpm_proxy;

cfg_if::cfg_if! {
    if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
        mod pit;
        pub use self::pit::{Pit, PitError};
        pub mod tsc;
    }
}

pub use self::bus::Error as BusError;
pub use self::bus::{
    Bus, BusAccessInfo, BusDevice, BusDeviceObj, BusDeviceSync, BusRange, BusResumeDevice, BusType,
    HostHotPlugKey, HotPlugBus,
};
pub use self::cmos::Cmos;
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub use self::debugcon::Debugcon;
#[cfg(feature = "direct")]
pub use self::direct_io::{DirectIo, DirectMmio};
#[cfg(feature = "direct")]
pub use self::direct_irq::{DirectIrq, DirectIrqError};
pub use self::i8042::I8042Device;
pub use self::irq_event::{IrqEdgeEvent, IrqLevelEvent};
pub use self::irqchip::*;
pub use self::pci::CrosvmDeviceId;
pub use self::pci::{
    BarRange, PciAddress, PciAddressError, PciBus, PciClassCode, PciConfigIo, PciConfigMmio,
    PciDevice, PciDeviceError, PciInterruptPin, PciRoot, PciVirtualConfigMmio, StubPciDevice,
    StubPciParameters,
};
pub use self::pl030::Pl030;
pub use self::serial::Serial;
pub use self::serial_device::{
    Error as SerialError, SerialDevice, SerialHardware, SerialParameters, SerialType,
};
#[cfg(feature = "tpm")]
pub use self::software_tpm::SoftwareTpm;
#[cfg(all(feature = "tpm", feature = "chromeos", target_arch = "x86_64"))]
pub use self::vtpm_proxy::VtpmProxy;

cfg_if::cfg_if! {
    if #[cfg(unix)] {
        mod platform;
        mod proxy;
        pub mod acpi;
        pub mod bat;
        #[cfg(feature = "usb")]
        pub mod usb;
        #[cfg(feature = "usb")]
        mod utils;
        pub mod vfio;

        pub use self::acpi::ACPIPMResource;
        pub use self::bat::{BatteryError, GoldfishBattery};
        #[cfg(feature = "audio")]
        pub use self::pci::{Ac97Backend, Ac97Dev, Ac97Parameters};
        pub use self::pci::{
            CoIommuDev, CoIommuParameters, CoIommuUnpinPolicy,
            PvPanicCode, PcieRootPort, PcieHostPort,
            PvPanicPciDevice, VfioPciDevice, PciBridge,
        };
        pub use self::platform::VfioPlatformDevice;
        pub use self::proxy::Error as ProxyError;
        pub use self::proxy::ProxyDevice;
        #[cfg(feature = "usb")]
        pub use self::usb::host_backend::host_backend_device_provider::HostBackendDeviceProvider;
        #[cfg(feature = "usb")]
        pub use self::usb::xhci::xhci_controller::XhciController;
        pub use self::vfio::{VfioContainer, VfioDevice};
        pub use self::virtio::{vfio_wrapper, VirtioPciDevice};

    } else if #[cfg(windows)] {
        // We define Minijail as an empty struct on Windows because the concept
        // of jailing is baked into a bunch of places where it isn't easy
        // to compile it out. In the long term, this should go away.
        #[cfg(windows)]
        pub struct Minijail {}
    } else {
        compile_error!("Unsupported platform");
    }
}

/// Request CoIOMMU to unpin a specific range.
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
pub struct UnpinRequest {
    /// The ranges presents (start gfn, count).
    ranges: Vec<(u64, u64)>,
}

#[derive(Serialize, Deserialize, Debug)]
pub enum UnpinResponse {
    Success,
    Failed,
}

#[derive(Debug)]
pub enum ParseIommuDevTypeResult {
    NoSuchType,
}

#[derive(Copy, Clone, Eq, PartialEq)]
pub enum IommuDevType {
    NoIommu,
    VirtioIommu,
    CoIommu,
}

use std::str::FromStr;
impl FromStr for IommuDevType {
    type Err = ParseIommuDevTypeResult;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "off" => Ok(IommuDevType::NoIommu),
            "viommu" => Ok(IommuDevType::VirtioIommu),
            "coiommu" => Ok(IommuDevType::CoIommu),
            _ => Err(ParseIommuDevTypeResult::NoSuchType),
        }
    }
}
<|endoftext|>


<commit_before>#![feature(test, plugin)]
#![plugin(jit_macros)]
#[no_link] #[macro_use]
extern crate jit_macros;
extern crate jit;
extern crate test;
use test::Bencher;
use jit::*;

#[bench]
fn bench_gcd(b: &mut Bencher) {
    let mut ctx = Context::<()>::new();
    jit_func!(ctx, func, gcd(x: usize, y:usize) -> usize, {
        func.insn_if(func.insn_eq(x, y), || func.insn_return(x));
        func.insn_if(func.insn_lt(x, y), || {
            let mut args = [x, y - x];
            let v = func.insn_call(Some("gcd"), func, None, args.as_mut_slice(), flags::CallFlags::NO_THROW);
            func.insn_return(v);
        });
        let mut args = [x - y, y];
        let temp4 = func.insn_call(Some("gcd"), func, None, args.as_mut_slice(), flags::CallFlags::NO_THROW);
        func.insn_return(temp4);
    }, |gcd| {
        b.iter(|| {
            assert_eq!(gcd((90, 50)), 10)
        })
    });
}
#[bench]
fn bench_raw_gcd(b: &mut Bencher) {
    fn gcd(x: usize, y: usize) -> usize {
        if x == y {
            x
        } else if x < y {
            gcd(x, y - x)
        } else {
            gcd(x - y, y)
        }
    }
    b.iter(|| {
        assert_eq!(gcd(90, 50), 10)
    })
}
<commit_msg>Replace `as_mut_slice` with `&mut`<commit_after>#![feature(test, plugin)]
#![plugin(jit_macros)]
#[no_link] #[macro_use]
extern crate jit_macros;
extern crate jit;
extern crate test;
use test::Bencher;
use jit::*;

#[bench]
fn bench_gcd(b: &mut Bencher) {
    let mut ctx = Context::<()>::new();
    jit_func!(ctx, func, gcd(x: usize, y:usize) -> usize, {
        func.insn_if(func.insn_eq(x, y), || func.insn_return(x));
        func.insn_if(func.insn_lt(x, y), || {
            let mut args = [x, y - x];
            let v = func.insn_call(Some("gcd"), func, None, &mut args, flags::CallFlags::NO_THROW);
            func.insn_return(v);
        });
        let mut args = [x - y, y];
        let temp4 = func.insn_call(Some("gcd"), func, None, &mut args, flags::CallFlags::NO_THROW);
        func.insn_return(temp4);
    }, |gcd| {
        b.iter(|| {
            assert_eq!(gcd((90, 50)), 10)
        })
    });
}
#[bench]
fn bench_raw_gcd(b: &mut Bencher) {
    fn gcd(x: usize, y: usize) -> usize {
        if x == y {
            x
        } else if x < y {
            gcd(x, y - x)
        } else {
            gcd(x - y, y)
        }
    }
    b.iter(|| {
        assert_eq!(gcd(90, 50), 10)
    })
}
<|endoftext|>


<commit_before>#![cfg(feature = "mp4")]
#[macro_use]
extern crate bencher;

extern crate byteorder;
extern crate combine;

use bencher::{black_box, Bencher};

use std::str::from_utf8;
use std::fs::File;
use std::io::Read;

use byteorder::{BigEndian, ByteOrder};

use combine::*;
use combine::range::{range, take};

#[derive(Clone, PartialEq, Eq, Debug)]
struct FileType<'a> {
    major_brand: &'a str,
    major_brand_version: &'a [u8],
    compatible_brands: Vec<&'a str>,
}

#[derive(Clone, Debug)]
enum MP4Box<'a> {
    Ftyp(FileType<'a>),
    Moov,
    Mdat,
    Free,
    Skip,
    Wide,
    Unknown,
}

fn parse_mp4(data: &[u8]) -> Result<(Vec<MP4Box>, &[u8]), StreamError<&[u8]>> {
    let brand_name = || take(4).and_then(from_utf8);
    let filetype_box = (
        range(&b"ftyp"[..]),
        brand_name(),
        take(4),
        many(brand_name()),
    ).map(|(_, m, v, c)| {
        MP4Box::Ftyp(FileType {
            major_brand: m,
            major_brand_version: v,
            compatible_brands: c,
        })
    });

    let mp4_box = take(4)
        .map(BigEndian::read_u32)
        .then(|offset| take(offset as usize - 4));
    let mut box_parser = choice((
        filetype_box,
        range(&b"moov"[..]).map(|_| MP4Box::Moov),
        range(&b"mdat"[..]).map(|_| MP4Box::Mdat),
        range(&b"free"[..]).map(|_| MP4Box::Free),
        range(&b"skip"[..]).map(|_| MP4Box::Skip),
        range(&b"wide"[..]).map(|_| MP4Box::Wide),
        value(MP4Box::Unknown),
    ));
    let data_interpreter =
        mp4_box.flat_map(|box_data| box_parser.easy_parse(box_data).map(|t| t.0));

    many(data_interpreter).easy_parse(data)
}

fn run_test(b: &mut Bencher, data: &[u8]) {
    b.iter(|| match parse_mp4(data) {
        Ok(x) => black_box(x),
        Err(err) => panic!("{}", err.map_range(|bytes| format!("{:?}", bytes))),
    });
}

fn mp4_small_test(b: &mut Bencher) {
    let mut mp4_small = Vec::new();
    File::open("benches/small.mp4")
        .and_then(|mut f| f.read_to_end(&mut mp4_small))
        .expect("Unable to read benches/small.mp4");
    run_test(b, &mp4_small)
}

benchmark_group!(mp4, mp4_small_test);
benchmark_main!(mp4);
<commit_msg>Fix the mp4 benchmark<commit_after>#![cfg(feature = "mp4")]
#[macro_use]
extern crate bencher;

extern crate byteorder;
extern crate combine;

use bencher::{black_box, Bencher};

use std::str::from_utf8;
use std::fs::File;
use std::io::Read;

use byteorder::{BigEndian, ByteOrder};

use combine::*;
use combine::range::{range, take};
use combine::easy::StreamErrors;

#[derive(Clone, PartialEq, Eq, Debug)]
struct FileType<'a> {
    major_brand: &'a str,
    major_brand_version: &'a [u8],
    compatible_brands: Vec<&'a str>,
}

#[derive(Clone, Debug)]
enum MP4Box<'a> {
    Ftyp(FileType<'a>),
    Moov,
    Mdat,
    Free,
    Skip,
    Wide,
    Unknown,
}

fn parse_mp4(data: &[u8]) -> Result<(Vec<MP4Box>, &[u8]), StreamErrors<&[u8]>> {
    let brand_name = || take(4).and_then(from_utf8);
    let filetype_box = (
        range(&b"ftyp"[..]),
        brand_name(),
        take(4),
        many(brand_name()),
    ).map(|(_, m, v, c)| {
        MP4Box::Ftyp(FileType {
            major_brand: m,
            major_brand_version: v,
            compatible_brands: c,
        })
    });

    let mp4_box = take(4)
        .map(BigEndian::read_u32)
        .then(|offset| take(offset as usize - 4));
    let mut box_parser = choice((
        filetype_box,
        range(&b"moov"[..]).map(|_| MP4Box::Moov),
        range(&b"mdat"[..]).map(|_| MP4Box::Mdat),
        range(&b"free"[..]).map(|_| MP4Box::Free),
        range(&b"skip"[..]).map(|_| MP4Box::Skip),
        range(&b"wide"[..]).map(|_| MP4Box::Wide),
        value(MP4Box::Unknown),
    ));
    let data_interpreter =
        mp4_box.flat_map(|box_data| box_parser.easy_parse(box_data).map(|t| t.0));

    many(data_interpreter).easy_parse(data)
}

fn run_test(b: &mut Bencher, data: &[u8]) {
    b.iter(|| match parse_mp4(data) {
        Ok(x) => black_box(x),
        Err(err) => panic!("{}", err.map_range(|bytes| format!("{:?}", bytes))),
    });
}

fn mp4_small_test(b: &mut Bencher) {
    let mut mp4_small = Vec::new();
    File::open("benches/small.mp4")
        .and_then(|mut f| f.read_to_end(&mut mp4_small))
        .expect("Unable to read benches/small.mp4");
    run_test(b, &mp4_small)
}

benchmark_group!(mp4, mp4_small_test);
benchmark_main!(mp4);
<|endoftext|>


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

use dom::bindings::codegen::Bindings::HTMLMainElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLMainElementDerived;
use dom::bindings::js::{JSRef, Temporary};
use dom::document::Document;
use dom::element::HTMLMainElementTypeId;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::node::{Node, ElementNodeTypeId};
use servo_util::str::DOMString;

#[deriving(Encodable)]
pub struct HTMLMainElement {
    pub htmlelement: HTMLElement
}

impl HTMLMainElementDerived for EventTarget {
    fn is_htmlmainelement(&self) -> bool {
        self.type_id == NodeTargetTypeId(ElementNodeTypeId(HTMLMainElementTypeId))
    }
}

impl HTMLMainElement {
    pub fn new_inherited(localName: DOMString, document: &JSRef<Document>) -> HTMLMainElement {
        HTMLMainElement {
            htmlelement: HTMLElement::new_inherited(HTMLMainElementTypeId, localName, document)
        }
    }

    pub fn new(localName: DOMString, document: &JSRef<Document>) -> Temporary<HTMLMainElement> {
        let element = HTMLMainElement::new_inherited(localName, document);
        Node::reflect_node(box element, document, HTMLMainElementBinding::Wrap)
    }
}

pub trait HTMLMainElementMethods {
}
<commit_msg>auto merge of #2597 : Ms2ger/servo/main, r=jdm<commit_after><|endoftext|>


<commit_before>use super::*;

impl Editor {
    /// Get pos of next char
    pub fn next_pos(&mut self) -> (usize, usize) {
        // TODO: Add numerals
        if self.x() == self.text[self.y()].len() {
            if self.y() < self.text.len() - 1 {
                (0, self.y() + 1)
            } else {
                (self.x(), self.y())
            }
        } else {
            (self.x() + 1, self.y())
        }
    }

    /// Get pos of previous char
    pub fn previous_pos(&mut self) -> (usize, usize) {
        if self.x() == 0 {
            if self.y() > 0 {
                (self.text[self.y()].len(), self.y() - 1)
            } else {
                (self.x(), self.y())
            }
        } else {
            (self.x() - 1, self.y())
        }
    }

    pub fn next(&mut self) {
        let (x, y) = self.next_pos();
        self.cursor_mut().x = x;
        self.cursor_mut().y = y;
    }
    pub fn previous(&mut self) {
        let (x, y) = self.previous_pos();
        self.cursor_mut().x = x;
        self.cursor_mut().y = y;
    }

    /// Go right
    pub fn right(&mut self, n: usize) {
        let x = self.x() + n;
        let y = self.y();

        let text = self.text.clone();
        let curs = self.cursor_mut();

        curs.x += n;

        if x > text[y].len() {
            curs.x = text[y].len();
        }
    }

    /// Go left
    pub fn left(&mut self, n: usize) {
        let x = self.x();
        let y = self.y();

        let text = self.text.clone();
        let curs = self.cursor_mut();

        if n <= x {
            curs.x = x - n;
        } else {
            curs.x = 0;
        }

    }

    /// Go up
    pub fn up(&mut self, n: usize) {
        let y = self.y();
        let curs = self.cursor_mut();
        if n <= y {
            curs.y -= n;
        } else {
            curs.y = 0;
        }
    }

    /// Go down
    pub fn down(&mut self, n: usize) {
        let x = self.x();
        let y = self.y() + n;

        let text = self.text.clone();
        let curs = self.cursor_mut();

        curs.y += n;

        if y >= text.len() {
            curs.y = text.len() - 1;
        }
    }
}
<commit_msg>Remove unused mut<commit_after>use super::*;

impl Editor {
    /// Get pos of next char
    pub fn next_pos(&self) -> (usize, usize) {
        // TODO: Add numerals
        if self.x() == self.text[self.y()].len() {
            if self.y() < self.text.len() - 1 {
                (0, self.y() + 1)
            } else {
                (self.x(), self.y())
            }
        } else {
            (self.x() + 1, self.y())
        }
    }

    /// Get pos of previous char
    pub fn previous_pos(&self) -> (usize, usize) {
        if self.x() == 0 {
            if self.y() > 0 {
                (self.text[self.y()].len(), self.y() - 1)
            } else {
                (self.x(), self.y())
            }
        } else {
            (self.x() - 1, self.y())
        }
    }

    pub fn next(&mut self) {
        let (x, y) = self.next_pos();
        self.cursor_mut().x = x;
        self.cursor_mut().y = y;
    }
    pub fn previous(&mut self) {
        let (x, y) = self.previous_pos();
        self.cursor_mut().x = x;
        self.cursor_mut().y = y;
    }

    /// Go right
    pub fn right(&mut self, n: usize) {
        let x = self.x() + n;
        let y = self.y();

        let text = self.text.clone();
        let curs = self.cursor_mut();

        curs.x += n;

        if x > text[y].len() {
            curs.x = text[y].len();
        }
    }

    /// Go left
    pub fn left(&mut self, n: usize) {
        let x = self.x();
        let y = self.y();

        let text = self.text.clone();
        let curs = self.cursor_mut();

        if n <= x {
            curs.x = x - n;
        } else {
            curs.x = 0;
        }

    }

    /// Go up
    pub fn up(&mut self, n: usize) {
        let y = self.y();
        let curs = self.cursor_mut();
        if n <= y {
            curs.y -= n;
        } else {
            curs.y = 0;
        }
    }

    /// Go down
    pub fn down(&mut self, n: usize) {
        let x = self.x();
        let y = self.y() + n;

        let text = self.text.clone();
        let curs = self.cursor_mut();

        curs.y += n;

        if y >= text.len() {
            curs.y = text.len() - 1;
        }
    }
}
<|endoftext|>


<commit_before>use std::cmp::Eq;
use std::fmt::Display;
use std::iter::FromIterator;

trait Parser<T: Display + Eq, E>: Sized {
    fn preview(&self) -> Option<&T>;
    fn consume(&mut self) -> Option<T>;
    fn current_pos(&self) -> (i32, i32);
    fn error<S: Into<String>>(&self, message: S) -> E;

    fn export(&self) -> Self;
    fn import(&mut self, backup: Self);

    fn next(&mut self) -> Result<T, E> {
        self.consume().ok_or(self.error("unexpected eof"))
    }

    fn predicate<F>(&mut self, pred: F) -> Result<T, E>
        where F: Fn(&T) -> bool
    {
        let x = try!(self.next());
        if pred(&x) {
            Ok(x)
        } else {
            Err(self.error(format!("unexpected token {}", x)))
        }
    }

    fn atom(&mut self, expected: T) -> Result<T, E> {
        let x = try!(self.next());
        if x == expected {
            Ok(x)
        } else {
            Err(self.error(format!("unexpected token {}, expected {}", x, expected)))
        }
    }

    fn string<S, O>(&mut self, s: S) -> Result<O, E>
        where S: IntoIterator<Item = T>,
              O: FromIterator<T>
    {
        let mut res: Vec<T> = Vec::new();
        for c in s {
            match self.atom(c) {
                Ok(x) => res.push(x),
                Err(err) => return Err(err),
            }
        }
        Ok(O::from_iter(res))
    }

    fn try<O, F>(&mut self, parser: F) -> Result<O, E>
        where F: Fn(&mut Self) -> Result<O, E>
    {
        let backup = self.export();
        parser(self).map_err(|x| {
                                 self.import(backup);
                                 x
                             })
    }

    fn choose<O>(&mut self, parsers: &[&Fn(&mut Self) -> Result<O, E>]) -> Result<O, E> {
        for parser in parsers {
            match self.try(parser) {
                Ok(x) => return Ok(x),
                Err(_) => continue,
            }
        }

        Err(self.error(match self.preview() {
                           Some(x) => format!("unexpected token {}", x),
                           None => String::from("unexpected eof"),
                       }))
    }

    fn many<X, F, O>(&mut self, parser: F) -> Result<O, E>
        where F: Fn(&mut Self) -> Result<X, E>,
              O: FromIterator<X>
    {
        let mut res: Vec<X> = Vec::new();
        loop {
            match self.try(&parser) {
                Ok(x) => res.push(x),
                Err(_) => break,
            }
        }
        Ok(O::from_iter(res))
    }

    fn many1<X, F, O>(&mut self, parser: F) -> Result<O, E>
        where F: Fn(&mut Self) -> Result<X, E>,
              O: FromIterator<X>
    {
        let mut res: Vec<X> = Vec::new();
        res.push(try!(parser(self)));
        loop {
            match self.try(&parser) {
                Ok(x) => res.push(x),
                Err(_) => break,
            }
        }
        Ok(O::from_iter(res))
    }

    fn optional<X, F>(&mut self, parser: F)
        where F: Fn(&mut Self) -> Result<X, E>
    {
        unimplemented!()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::collections::vec_deque::VecDeque;

    struct TP {
        input: VecDeque<i32>,
    }

    impl TP {
        fn new(input: &[i32]) -> TP {
            TP { input: VecDeque::from(input.to_vec()) }
        }
    }

    impl Parser<i32, String> for TP {
        fn consume(&mut self) -> Option<i32> {
            self.input.pop_front()
        }

        fn preview(&self) -> Option<&i32> {
            self.input.front()
        }

        fn current_pos(&self) -> (i32, i32) {
            (0, 0)
        }

        fn error<S: Into<String>>(&self, message: S) -> String {
            message.into()
        }

        fn export(&self) -> Self {
            TP { input: self.input.clone() }
        }

        fn import(&mut self, backup: Self) {
            self.input = backup.input;
        }
    }

    type TPR = Result<Vec<i32>, String>;

    fn err<T>(m: &str) -> Result<T, String> {
        Err(String::from(m))
    }

    #[test]
    fn next_success() {
        let mut p = TP::new(&[1, 2, 3]);
        assert_eq!(p.next(), Ok(1));
        assert_eq!(p.next(), Ok(2));
        assert_eq!(p.next(), Ok(3));
    }

    #[test]
    fn next_fail_empty() {
        let mut p = TP::new(&[]);
        assert_eq!(p.next(), err("unexpected eof"));
    }

    #[test]
    fn predicate_success() {
        let mut p = TP::new(&[2, 4, 6]);
        assert_eq!(p.predicate(|x| x % 2 == 0), Ok(2));
        assert_eq!(p.predicate(|x| x % 2 == 0), Ok(4));
        assert_eq!(p.predicate(|x| x % 2 == 0), Ok(6));
    }

    #[test]
    fn predicate_fail_empty() {
        let mut p = TP::new(&[]);
        assert_eq!(p.predicate(|x| x % 2 == 0), err("unexpected eof"));
    }

    #[test]
    fn predicate_fail_not_satisfy() {
        let mut p = TP::new(&[3, 5, 7]);
        assert_eq!(p.predicate(|x| x % 2 == 0), err("unexpected token 3"));
    }

    #[test]
    fn atom_success() {
        let mut p = TP::new(&[2, 4, 6]);
        assert_eq!(p.atom(2), Ok(2));
        assert_eq!(p.atom(4), Ok(4));
        assert_eq!(p.atom(6), Ok(6));
    }

    #[test]
    fn atom_fail_empty() {
        let mut p = TP::new(&[]);
        assert_eq!(p.atom(2), err("unexpected eof"));
    }

    #[test]
    fn atom_fail_not_expected() {
        let mut p = TP::new(&[3, 5, 7]);
        assert_eq!(p.atom(3), Ok(3));
        assert_eq!(p.atom(4), err("unexpected token 5, expected 4"));
    }

    #[test]
    fn string_success() {
        let mut p = TP::new(&[2, 4, 6]);
        assert_eq!(p.string(vec![2, 4, 6]), Ok(vec![2, 4, 6]));
    }

    #[test]
    fn string_fail_empty() {
        let mut p = TP::new(&[]);
        assert_eq!(p.string(vec![2, 4, 6]) as TPR, err("unexpected eof"));
    }

    #[test]
    fn string_fail_not_expected() {
        let mut p = TP::new(&[2, 5, 6]);
        assert_eq!(p.string(vec![2, 4, 6]) as TPR,
                   err("unexpected token 5, expected 4"));
    }

    #[test]
    fn try_success() {
        let mut p = TP::new(&[2, 4, 6]);
        assert_eq!(p.try(|p| p.string(vec![2, 4, 6])), Ok(vec![2, 4, 6]));
    }

    #[test]
    fn try_fail_recover() {
        let mut p = TP::new(&[2, 4, 6]);
        assert_eq!(p.try(|p| p.string(vec![2, 4, 7])) as TPR,
                   err("unexpected token 6, expected 7"));
        assert_eq!(p.try(|p| p.string(vec![2, 4, 6])), Ok(vec![2, 4, 6]));
    }

    #[test]
    fn choose_success() {
        let mut p = TP::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
        assert_eq!(p.choose(&[&|p| p.string(vec![1, 2, 3]),
                              &|p| p.string(vec![4, 5, 6, 7]),
                              &|p| p.string(vec![4, 5, 6])]),
                   Ok(vec![1, 2, 3]));
    }

    #[test]
    fn choose_success_with_recover() {
        let mut p = TP::new(&[4, 5, 6, 7, 8, 9, 10]);
        assert_eq!(p.choose(&[&|p| p.string(vec![1, 2, 3]),
                              &|p| p.string(vec![4, 5, 6, 8]),
                              &|p| p.string(vec![4, 5, 6])]),
                   Ok(vec![4, 5, 6]));
    }

    #[test]
    fn choose_fail_no_match() {
        let mut p = TP::new(&[5, 6, 7, 8, 9, 10]);
        assert_eq!(p.choose(&[&|p| p.string(vec![1, 2, 3]),
                              &|p| p.string(vec![4, 5, 6, 8]),
                              &|p| p.string(vec![4, 5, 6])]) as TPR,
                   err("unexpected token 5"));
    }

    #[test]
    fn choose_fail_empty() {
        let mut p = TP::new(&[]);
        assert_eq!(p.choose(&[&|p| p.string(vec![1, 2, 3]),
                              &|p| p.string(vec![4, 5, 6, 8]),
                              &|p| p.string(vec![4, 5, 6])]) as TPR,
                   err("unexpected eof"));
    }

    #[test]
    fn many_success() {
        let lt5 = |p: &mut TP| -> Result<i32, String> { p.predicate(|x| *x < 5) };

        assert_eq!(TP::new(&[1, 2, 3, 4]).many(&lt5), Ok(vec![1, 2, 3, 4]));
        assert_eq!(TP::new(&[1, 2, 3, 4, 5, 6, 7, 8]).many(&lt5),
                   Ok(vec![1, 2, 3, 4]));
        assert_eq!(TP::new(&[4, 5, 6, 7, 8]).many(&lt5), Ok(vec![4]));
        assert_eq!(TP::new(&[5, 6, 7, 8]).many(&lt5), Ok(vec![]));
    }

    #[test]
    fn many1_success() {
        let lt5 = |p: &mut TP| -> Result<i32, String> { p.predicate(|x| *x < 5) };

        assert_eq!(TP::new(&[1, 2, 3, 4]).many1(&lt5), Ok(vec![1, 2, 3, 4]));
        assert_eq!(TP::new(&[1, 2, 3, 4, 5, 6, 7, 8]).many1(&lt5),
                   Ok(vec![1, 2, 3, 4]));
        assert_eq!(TP::new(&[4, 5, 6, 7, 8]).many1(&lt5), Ok(vec![4]));
    }

    #[test]
    fn many1_fail() {
        let lt5 = |p: &mut TP| -> Result<i32, String> { p.predicate(|x| *x < 5) };

        assert_eq!(TP::new(&[5, 6, 7, 8]).many1(&lt5) as TPR,
                   err("unexpected token 5"));
    }

    #[test]
    fn optional_success() {
        let mut p = TP::new(&[1, 2, 3, 4, 5]);
        p.optional(|p| p.atom(1));
        assert_eq!(p.string(vec![2, 3, 4]), Ok(vec![2, 3, 4]));
    }

    #[test]
    fn optional_success_without_matching() {
        let mut p = TP::new(&[1, 2, 3, 4, 5]);
        p.optional(|p| p.atom(2));
        assert_eq!(p.string(vec![1, 2, 3]), Ok(vec![1, 2, 3]));
    }
}
<commit_msg>Implement optional combinator<commit_after>use std::cmp::Eq;
use std::fmt::Display;
use std::iter::FromIterator;

trait Parser<T: Display + Eq, E>: Sized {
    fn preview(&self) -> Option<&T>;
    fn consume(&mut self) -> Option<T>;
    fn current_pos(&self) -> (i32, i32);
    fn error<S: Into<String>>(&self, message: S) -> E;

    fn export(&self) -> Self;
    fn import(&mut self, backup: Self);

    fn next(&mut self) -> Result<T, E> {
        self.consume().ok_or(self.error("unexpected eof"))
    }

    fn predicate<F>(&mut self, pred: F) -> Result<T, E>
        where F: Fn(&T) -> bool
    {
        let x = try!(self.next());
        if pred(&x) {
            Ok(x)
        } else {
            Err(self.error(format!("unexpected token {}", x)))
        }
    }

    fn atom(&mut self, expected: T) -> Result<T, E> {
        let x = try!(self.next());
        if x == expected {
            Ok(x)
        } else {
            Err(self.error(format!("unexpected token {}, expected {}", x, expected)))
        }
    }

    fn string<S, O>(&mut self, s: S) -> Result<O, E>
        where S: IntoIterator<Item = T>,
              O: FromIterator<T>
    {
        let mut res: Vec<T> = Vec::new();
        for c in s {
            match self.atom(c) {
                Ok(x) => res.push(x),
                Err(err) => return Err(err),
            }
        }
        Ok(O::from_iter(res))
    }

    fn try<O, F>(&mut self, parser: F) -> Result<O, E>
        where F: Fn(&mut Self) -> Result<O, E>
    {
        let backup = self.export();
        parser(self).map_err(|x| {
                                 self.import(backup);
                                 x
                             })
    }

    fn choose<O>(&mut self, parsers: &[&Fn(&mut Self) -> Result<O, E>]) -> Result<O, E> {
        for parser in parsers {
            match self.try(parser) {
                Ok(x) => return Ok(x),
                Err(_) => continue,
            }
        }

        Err(self.error(match self.preview() {
                           Some(x) => format!("unexpected token {}", x),
                           None => String::from("unexpected eof"),
                       }))
    }

    fn many<X, F, O>(&mut self, parser: F) -> Result<O, E>
        where F: Fn(&mut Self) -> Result<X, E>,
              O: FromIterator<X>
    {
        let mut res: Vec<X> = Vec::new();
        loop {
            match self.try(&parser) {
                Ok(x) => res.push(x),
                Err(_) => break,
            }
        }
        Ok(O::from_iter(res))
    }

    fn many1<X, F, O>(&mut self, parser: F) -> Result<O, E>
        where F: Fn(&mut Self) -> Result<X, E>,
              O: FromIterator<X>
    {
        let mut res: Vec<X> = Vec::new();
        res.push(try!(parser(self)));
        loop {
            match self.try(&parser) {
                Ok(x) => res.push(x),
                Err(_) => break,
            }
        }
        Ok(O::from_iter(res))
    }

    fn optional<X, F>(&mut self, parser: F)
        where F: Fn(&mut Self) -> Result<X, E>
    {
        self.try(parser);
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::collections::vec_deque::VecDeque;

    struct TP {
        input: VecDeque<i32>,
    }

    impl TP {
        fn new(input: &[i32]) -> TP {
            TP { input: VecDeque::from(input.to_vec()) }
        }
    }

    impl Parser<i32, String> for TP {
        fn consume(&mut self) -> Option<i32> {
            self.input.pop_front()
        }

        fn preview(&self) -> Option<&i32> {
            self.input.front()
        }

        fn current_pos(&self) -> (i32, i32) {
            (0, 0)
        }

        fn error<S: Into<String>>(&self, message: S) -> String {
            message.into()
        }

        fn export(&self) -> Self {
            TP { input: self.input.clone() }
        }

        fn import(&mut self, backup: Self) {
            self.input = backup.input;
        }
    }

    type TPR = Result<Vec<i32>, String>;

    fn err<T>(m: &str) -> Result<T, String> {
        Err(String::from(m))
    }

    #[test]
    fn next_success() {
        let mut p = TP::new(&[1, 2, 3]);
        assert_eq!(p.next(), Ok(1));
        assert_eq!(p.next(), Ok(2));
        assert_eq!(p.next(), Ok(3));
    }

    #[test]
    fn next_fail_empty() {
        let mut p = TP::new(&[]);
        assert_eq!(p.next(), err("unexpected eof"));
    }

    #[test]
    fn predicate_success() {
        let mut p = TP::new(&[2, 4, 6]);
        assert_eq!(p.predicate(|x| x % 2 == 0), Ok(2));
        assert_eq!(p.predicate(|x| x % 2 == 0), Ok(4));
        assert_eq!(p.predicate(|x| x % 2 == 0), Ok(6));
    }

    #[test]
    fn predicate_fail_empty() {
        let mut p = TP::new(&[]);
        assert_eq!(p.predicate(|x| x % 2 == 0), err("unexpected eof"));
    }

    #[test]
    fn predicate_fail_not_satisfy() {
        let mut p = TP::new(&[3, 5, 7]);
        assert_eq!(p.predicate(|x| x % 2 == 0), err("unexpected token 3"));
    }

    #[test]
    fn atom_success() {
        let mut p = TP::new(&[2, 4, 6]);
        assert_eq!(p.atom(2), Ok(2));
        assert_eq!(p.atom(4), Ok(4));
        assert_eq!(p.atom(6), Ok(6));
    }

    #[test]
    fn atom_fail_empty() {
        let mut p = TP::new(&[]);
        assert_eq!(p.atom(2), err("unexpected eof"));
    }

    #[test]
    fn atom_fail_not_expected() {
        let mut p = TP::new(&[3, 5, 7]);
        assert_eq!(p.atom(3), Ok(3));
        assert_eq!(p.atom(4), err("unexpected token 5, expected 4"));
    }

    #[test]
    fn string_success() {
        let mut p = TP::new(&[2, 4, 6]);
        assert_eq!(p.string(vec![2, 4, 6]), Ok(vec![2, 4, 6]));
    }

    #[test]
    fn string_fail_empty() {
        let mut p = TP::new(&[]);
        assert_eq!(p.string(vec![2, 4, 6]) as TPR, err("unexpected eof"));
    }

    #[test]
    fn string_fail_not_expected() {
        let mut p = TP::new(&[2, 5, 6]);
        assert_eq!(p.string(vec![2, 4, 6]) as TPR,
                   err("unexpected token 5, expected 4"));
    }

    #[test]
    fn try_success() {
        let mut p = TP::new(&[2, 4, 6]);
        assert_eq!(p.try(|p| p.string(vec![2, 4, 6])), Ok(vec![2, 4, 6]));
    }

    #[test]
    fn try_fail_recover() {
        let mut p = TP::new(&[2, 4, 6]);
        assert_eq!(p.try(|p| p.string(vec![2, 4, 7])) as TPR,
                   err("unexpected token 6, expected 7"));
        assert_eq!(p.try(|p| p.string(vec![2, 4, 6])), Ok(vec![2, 4, 6]));
    }

    #[test]
    fn choose_success() {
        let mut p = TP::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
        assert_eq!(p.choose(&[&|p| p.string(vec![1, 2, 3]),
                              &|p| p.string(vec![4, 5, 6, 7]),
                              &|p| p.string(vec![4, 5, 6])]),
                   Ok(vec![1, 2, 3]));
    }

    #[test]
    fn choose_success_with_recover() {
        let mut p = TP::new(&[4, 5, 6, 7, 8, 9, 10]);
        assert_eq!(p.choose(&[&|p| p.string(vec![1, 2, 3]),
                              &|p| p.string(vec![4, 5, 6, 8]),
                              &|p| p.string(vec![4, 5, 6])]),
                   Ok(vec![4, 5, 6]));
    }

    #[test]
    fn choose_fail_no_match() {
        let mut p = TP::new(&[5, 6, 7, 8, 9, 10]);
        assert_eq!(p.choose(&[&|p| p.string(vec![1, 2, 3]),
                              &|p| p.string(vec![4, 5, 6, 8]),
                              &|p| p.string(vec![4, 5, 6])]) as TPR,
                   err("unexpected token 5"));
    }

    #[test]
    fn choose_fail_empty() {
        let mut p = TP::new(&[]);
        assert_eq!(p.choose(&[&|p| p.string(vec![1, 2, 3]),
                              &|p| p.string(vec![4, 5, 6, 8]),
                              &|p| p.string(vec![4, 5, 6])]) as TPR,
                   err("unexpected eof"));
    }

    #[test]
    fn many_success() {
        let lt5 = |p: &mut TP| -> Result<i32, String> { p.predicate(|x| *x < 5) };

        assert_eq!(TP::new(&[1, 2, 3, 4]).many(&lt5), Ok(vec![1, 2, 3, 4]));
        assert_eq!(TP::new(&[1, 2, 3, 4, 5, 6, 7, 8]).many(&lt5),
                   Ok(vec![1, 2, 3, 4]));
        assert_eq!(TP::new(&[4, 5, 6, 7, 8]).many(&lt5), Ok(vec![4]));
        assert_eq!(TP::new(&[5, 6, 7, 8]).many(&lt5), Ok(vec![]));
    }

    #[test]
    fn many1_success() {
        let lt5 = |p: &mut TP| -> Result<i32, String> { p.predicate(|x| *x < 5) };

        assert_eq!(TP::new(&[1, 2, 3, 4]).many1(&lt5), Ok(vec![1, 2, 3, 4]));
        assert_eq!(TP::new(&[1, 2, 3, 4, 5, 6, 7, 8]).many1(&lt5),
                   Ok(vec![1, 2, 3, 4]));
        assert_eq!(TP::new(&[4, 5, 6, 7, 8]).many1(&lt5), Ok(vec![4]));
    }

    #[test]
    fn many1_fail() {
        let lt5 = |p: &mut TP| -> Result<i32, String> { p.predicate(|x| *x < 5) };

        assert_eq!(TP::new(&[5, 6, 7, 8]).many1(&lt5) as TPR,
                   err("unexpected token 5"));
    }

    #[test]
    fn optional_success() {
        let mut p = TP::new(&[1, 2, 3, 4, 5]);
        p.optional(|p| p.atom(1));
        assert_eq!(p.string(vec![2, 3, 4]), Ok(vec![2, 3, 4]));
    }

    #[test]
    fn optional_success_without_matching() {
        let mut p = TP::new(&[1, 2, 3, 4, 5]);
        p.optional(|p| p.atom(2));
        assert_eq!(p.string(vec![1, 2, 3]), Ok(vec![1, 2, 3]));
    }
}
<|endoftext|>


<commit_before>use cgmath::EuclideanSpace;
use gilrs::{Axis, Button, Gilrs};
use std::{f64::consts::PI, path::PathBuf};
use structopt::StructOpt;
use winit::{
    event,
    event_loop::{ControlFlow, EventLoop},
};

#[derive(Debug, StructOpt)]
struct Opt {
    #[structopt(short, long, default_value = "8FH495PF+29")]
    plus: String,
    #[structopt(short, long, default_value = "0")]
    heading: f64,
    #[structopt(short, long, default_value = "200000")]
    elevation: f64,
    #[structopt(long)]
    generate: Option<PathBuf>,
}

fn compute_projection_matrix(width: f32, height: f32) -> cgmath::Matrix4<f32> {
    let aspect = width / height;
    let f = 1.0 / (45.0f32.to_radians() / aspect).tan();
    let near = 0.1;

    #[cfg_attr(rustfmt, rustfmt_skip)]
    cgmath::Matrix4::new(
        f/aspect,  0.0,  0.0,   0.0,
        0.0,       f,    0.0,   0.0,
        0.0,       0.0,  0.0,  -1.0,
        0.0,       0.0,  near,  0.0)
}

fn make_depth_buffer(device: &wgpu::Device, width: u32, height: u32) -> wgpu::TextureView {
    device
        .create_texture(&wgpu::TextureDescriptor {
            size: wgpu::Extent3d { width, height, depth_or_array_layers: 1 },
            mip_level_count: 1,
            sample_count: 1,
            dimension: wgpu::TextureDimension::D2,
            format: wgpu::TextureFormat::Depth32Float,
            usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
            label: None,
        })
        .create_view(&Default::default())
}

fn main() {
    env_logger::init();

    let runtime = tokio::runtime::Runtime::new().unwrap();

    let trace_path: Option<&std::path::Path> = if cfg!(feature = "trace") {
        std::fs::create_dir_all("trace").unwrap();
        Some(std::path::Path::new("trace"))
    } else {
        None
    };

    let event_loop = EventLoop::new();
    let monitor = event_loop
        .available_monitors()
        .find(|monitor| monitor.video_modes().any(|mode| mode.size().width == 1920));
    let window = winit::window::WindowBuilder::new()
        .with_visible(false)
        .with_fullscreen(Some(winit::window::Fullscreen::Borderless(monitor)))
        .build(&event_loop)
        .unwrap();

    let instance = wgpu::Instance::new(wgpu::Backends::PRIMARY);
    let surface = unsafe { instance.create_surface(&window) };
    let adapter = runtime
        .block_on(instance.request_adapter(&wgpu::RequestAdapterOptions {
            power_preference: wgpu::PowerPreference::HighPerformance,
            compatible_surface: Some(&surface),
            force_fallback_adapter: false,
        }))
        .expect("Unable to create compatible wgpu adapter");
    let swapchain_format =
        surface.get_preferred_format(&adapter).expect("No compatible swapchain formats");

    // Terra requires support for BC texture compression.
    assert!(adapter.features().contains(wgpu::Features::TEXTURE_COMPRESSION_BC));
    let features = if !adapter.features().contains(wgpu::Features::SHADER_FLOAT64)
        || cfg!(feature = "soft-float64")
    {
        wgpu::Features::TEXTURE_COMPRESSION_BC
    } else {
        wgpu::Features::TEXTURE_COMPRESSION_BC | wgpu::Features::SHADER_FLOAT64
    };
    let features = features | adapter.features() & wgpu::Features::MULTI_DRAW_INDIRECT;

    let (device, queue) = runtime
        .block_on(adapter.request_device(
            &wgpu::DeviceDescriptor {
                features,
                limits: wgpu::Limits {
                    max_texture_array_layers: 1024,
                    max_compute_invocations_per_workgroup: 512,
                    ..wgpu::Limits::default()
                },
                label: None,
            },
            trace_path,
        ))
        .expect("Unable to create compatible wgpu device");

    let mut size = window.inner_size();
    let mut depth_buffer = make_depth_buffer(&device, size.width, size.height);

    #[cfg(feature = "smaa")]
    let mut smaa_target = smaa::SmaaTarget::new(
        &device,
        &queue,
        size.width,
        size.height,
        swapchain_format,
        smaa::SmaaMode::Smaa1X,
    );

    let mut gilrs = Gilrs::new().unwrap();
    let mut current_gamepad = None;
    for (_id, gamepad) in gilrs.gamepads() {
        current_gamepad = Some(gamepad.id());
    }

    let opt = Opt::from_args();
    let plus_center =
        open_location_code::decode(&opt.plus).expect("Failed to parse plus code").center;

    let planet_radius = 6371000.0;
    let mut angle = opt.heading.to_radians();
    let mut lat = plus_center.y().to_radians();
    let mut long = plus_center.x().to_radians();
    let mut altitude = opt.elevation;

    let mut terrain = match opt.generate {
        Some(dataset_directory) => {
            let pb = indicatif::ProgressBar::new(100);
            pb.set_style(
                indicatif::ProgressStyle::default_bar()
                    .template("{msg} {pos}/{len} [{wide_bar}] {percent}% {per_sec} {eta}")
                    .progress_chars("=> "),
            );
            let mut last_message = None;
            let progress_callback = |l: &str, i: usize, total: usize| {
                if last_message.is_none() || l != last_message.as_ref().unwrap() {
                    pb.set_message(l);
                    pb.reset_eta();
                    last_message = Some(l.to_string());
                }
                pb.set_length(total as u64);
                pb.set_position(i as u64);
            };

            runtime
                .block_on(terra::Terrain::generate_and_new(
                    &device,
                    &queue,
                    dataset_directory,
                    progress_callback,
                ))
                .unwrap()
        }
        None => terra::Terrain::new(&device, &queue).unwrap(),
    };

    {
        let r = altitude + planet_radius;
        let eye = cgmath::Point3::new(
            r * lat.cos() * long.cos(),
            r * lat.cos() * long.sin(),
            r * lat.sin(),
        );
        while terrain.poll_loading_status(&device, &queue, eye.into()) {
            std::thread::sleep(std::time::Duration::from_millis(10));
        }
    }
    window.set_visible(true);
    event_loop.run(move |event, _, control_flow| {
        *control_flow = ControlFlow::Poll;
        match event {
            event::Event::WindowEvent { event, .. } => match event {
                event::WindowEvent::CloseRequested => {
                    *control_flow = ControlFlow::Exit;
                }
                event::WindowEvent::KeyboardInput {
                    input:
                        event::KeyboardInput {
                            virtual_keycode: Some(keycode),
                            state: event::ElementState::Pressed,
                            ..
                        },
                    ..
                } => match keycode {
                    event::VirtualKeyCode::Escape => *control_flow = ControlFlow::Exit,
                    event::VirtualKeyCode::Space => altitude += 0.1 * altitude,
                    event::VirtualKeyCode::Z | event::VirtualKeyCode::Semicolon => {
                        altitude -= 0.1 * altitude
                    }
                    event::VirtualKeyCode::Left => {
                        lat += -angle.sin() * -(0.0000001 * altitude).min(0.01);
                        long += angle.cos() * -(0.0000001 * altitude).min(0.01);
                    }
                    event::VirtualKeyCode::Right => {
                        lat += -angle.sin() * (0.0000001 * altitude).min(0.01);
                        long += angle.cos() * (0.0000001 * altitude).min(0.01);
                    }
                    event::VirtualKeyCode::Up => {
                        lat += angle.cos() * (0.0000001 * altitude).min(0.01);
                        long += -angle.sin() * (0.0000001 * altitude).min(0.01);
                    }
                    event::VirtualKeyCode::Down => {
                        lat += angle.cos() * -(0.0000001 * altitude).min(0.01);
                        long += -angle.sin() * -(0.0000001 * altitude).min(0.01);
                    }
                    _ => {}
                },
                event::WindowEvent::Resized(new_size) => {
                    size = new_size;

                    #[cfg(feature = "smaa")]
                    smaa_target.resize(&device, new_size.width, new_size.height);

                    surface.configure(
                        &device,
                        &wgpu::SurfaceConfiguration {
                            usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
                            format: swapchain_format,
                            width: size.width,
                            height: size.height,
                            present_mode: wgpu::PresentMode::Fifo, // disable vsync by switching to Mailbox,
                        },
                    );
                    depth_buffer = make_depth_buffer(&device, size.width, size.height);
                }
                _ => {}
            },
            event::Event::MainEventsCleared => {
                window.request_redraw();
            }
            event::Event::RedrawRequested(_) => {
                let frame_texture = surface.get_current_texture();
                let frame_texture = match frame_texture {
                    Ok(f) => f,
                    Err(_) => return,
                };
                let frame_texture_view = frame_texture.texture.create_view(&Default::default());

                #[cfg(not(feature = "smaa"))]
                let frame = &frame_texture_view;

                #[cfg(feature = "smaa")]
                let frame = smaa_target.start_frame(&device, &queue, &frame_texture_view);

                while let Some(gilrs::Event { id, event: _event, time: _ }) = gilrs.next_event() {
                    current_gamepad = Some(id);
                }
                if let Some(gamepad) = current_gamepad.map(|id| gilrs.gamepad(id)) {
                    lat += angle.cos()
                        * gamepad.value(Axis::LeftStickY) as f64
                        * (0.0000001 * altitude).min(0.01)
                        - angle.sin()
                            * gamepad.value(Axis::LeftStickX) as f64
                            * (0.0000001 * altitude).min(0.01);

                    long += -angle.sin()
                        * gamepad.value(Axis::LeftStickY) as f64
                        * (0.0000001 * altitude).min(0.01)
                        + angle.cos()
                            * gamepad.value(Axis::LeftStickX) as f64
                            * (0.0000001 * altitude).min(0.01);

                    angle -= gamepad.value(Axis::RightZ) as f64 * 0.01;

                    if gamepad.is_pressed(Button::DPadUp) {
                        altitude += 0.01 * altitude;
                    }
                    if gamepad.is_pressed(Button::DPadDown) {
                        altitude -= 0.01 * altitude;
                    }
                }

                lat = lat.max(-PI).min(PI);
                if long < -PI {
                    long += PI * 2.0;
                }
                if long > PI {
                    long -= PI * 2.0;
                }

                let surface_height = terrain.get_height(lat, long) as f64;
                let r = altitude + planet_radius + surface_height + 2.0;
                let eye = cgmath::Point3::new(
                    r * lat.cos() * long.cos(),
                    r * lat.cos() * long.sin(),
                    r * lat.sin(),
                );

                let dt = (planet_radius / (planet_radius + altitude)).acos() * 0.3;
                let latc = lat + angle.cos() * dt;
                let longc = long - angle.sin() * dt;

                let center = cgmath::Point3::new(
                    planet_radius * latc.cos() * longc.cos() - eye.x,
                    planet_radius * latc.cos() * longc.sin() - eye.y,
                    planet_radius * latc.sin() - eye.z,
                );
                let up = cgmath::Vector3::new(eye.x as f32, eye.y as f32, eye.z as f32);

                let view = cgmath::Matrix4::look_at_rh(
                    cgmath::Point3::origin(),
                    cgmath::Point3::new(center.x as f32, center.y as f32, center.z as f32),
                    up,
                );

                let proj = compute_projection_matrix(size.width as f32, size.height as f32);
                let view_proj = proj * view;
                let view_proj = mint::ColumnMatrix4 {
                    x: view_proj.x.into(),
                    y: view_proj.y.into(),
                    z: view_proj.z.into(),
                    w: view_proj.w.into(),
                };

                terrain.render(
                    &device,
                    &queue,
                    &frame,
                    &depth_buffer,
                    (size.width, size.height),
                    view_proj,
                    eye.into(),
                );

                drop(frame);
                frame_texture.present();
            }
            _ => (),
        }
    });
}
<commit_msg>Configure surface even if window is never resized<commit_after>use cgmath::EuclideanSpace;
use gilrs::{Axis, Button, Gilrs};
use std::{f64::consts::PI, path::PathBuf};
use structopt::StructOpt;
use winit::{
    event,
    event_loop::{ControlFlow, EventLoop},
};

#[derive(Debug, StructOpt)]
struct Opt {
    #[structopt(short, long, default_value = "8FH495PF+29")]
    plus: String,
    #[structopt(short, long, default_value = "0")]
    heading: f64,
    #[structopt(short, long, default_value = "200000")]
    elevation: f64,
    #[structopt(long)]
    generate: Option<PathBuf>,
}

fn compute_projection_matrix(width: f32, height: f32) -> cgmath::Matrix4<f32> {
    let aspect = width / height;
    let f = 1.0 / (45.0f32.to_radians() / aspect).tan();
    let near = 0.1;

    #[cfg_attr(rustfmt, rustfmt_skip)]
    cgmath::Matrix4::new(
        f/aspect,  0.0,  0.0,   0.0,
        0.0,       f,    0.0,   0.0,
        0.0,       0.0,  0.0,  -1.0,
        0.0,       0.0,  near,  0.0)
}

fn make_depth_buffer(device: &wgpu::Device, width: u32, height: u32) -> wgpu::TextureView {
    device
        .create_texture(&wgpu::TextureDescriptor {
            size: wgpu::Extent3d { width, height, depth_or_array_layers: 1 },
            mip_level_count: 1,
            sample_count: 1,
            dimension: wgpu::TextureDimension::D2,
            format: wgpu::TextureFormat::Depth32Float,
            usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
            label: None,
        })
        .create_view(&Default::default())
}

fn configure_surface(
    device: &wgpu::Device,
    surface: &wgpu::Surface,
    swapchain_format: wgpu::TextureFormat,
    size: winit::dpi::PhysicalSize<u32>,
) {
    surface.configure(
        &device,
        &wgpu::SurfaceConfiguration {
            usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
            format: swapchain_format,
            width: size.width,
            height: size.height,
            present_mode: wgpu::PresentMode::Fifo, // disable vsync by switching to Mailbox,
        },
    );
}

fn main() {
    env_logger::init();

    let runtime = tokio::runtime::Runtime::new().unwrap();

    let trace_path: Option<&std::path::Path> = if cfg!(feature = "trace") {
        std::fs::create_dir_all("trace").unwrap();
        Some(std::path::Path::new("trace"))
    } else {
        None
    };

    let event_loop = EventLoop::new();
    let monitor = event_loop
        .available_monitors()
        .find(|monitor| monitor.video_modes().any(|mode| mode.size().width == 1920));
    let window = winit::window::WindowBuilder::new()
        .with_visible(false)
//        .with_fullscreen(Some(winit::window::Fullscreen::Borderless(monitor)))
        .build(&event_loop)
        .unwrap();

    let instance = wgpu::Instance::new(wgpu::Backends::PRIMARY);
    let surface = unsafe { instance.create_surface(&window) };
    let adapter = runtime
        .block_on(instance.request_adapter(&wgpu::RequestAdapterOptions {
            power_preference: wgpu::PowerPreference::HighPerformance,
            compatible_surface: Some(&surface),
            force_fallback_adapter: false,
        }))
        .expect("Unable to create compatible wgpu adapter");
    let swapchain_format =
        surface.get_preferred_format(&adapter).expect("No compatible swapchain formats");

    // Terra requires support for BC texture compression.
    assert!(adapter.features().contains(wgpu::Features::TEXTURE_COMPRESSION_BC));
    let features = if !adapter.features().contains(wgpu::Features::SHADER_FLOAT64)
        || cfg!(feature = "soft-float64")
    {
        wgpu::Features::TEXTURE_COMPRESSION_BC
    } else {
        wgpu::Features::TEXTURE_COMPRESSION_BC | wgpu::Features::SHADER_FLOAT64
    };
    let features = features | adapter.features() & wgpu::Features::MULTI_DRAW_INDIRECT;

    let (device, queue) = runtime
        .block_on(adapter.request_device(
            &wgpu::DeviceDescriptor {
                features,
                limits: wgpu::Limits {
                    max_texture_array_layers: 1024,
                    max_compute_invocations_per_workgroup: 512,
                    ..wgpu::Limits::default()
                },
                label: None,
            },
            trace_path,
        ))
        .expect("Unable to create compatible wgpu device");

    let mut size = window.inner_size();
    let mut depth_buffer = make_depth_buffer(&device, size.width, size.height);

    configure_surface(&device, &surface, swapchain_format, size);

    #[cfg(feature = "smaa")]
    let mut smaa_target = smaa::SmaaTarget::new(
        &device,
        &queue,
        size.width,
        size.height,
        swapchain_format,
        smaa::SmaaMode::Smaa1X,
    );

    let mut gilrs = Gilrs::new().unwrap();
    let mut current_gamepad = None;
    for (_id, gamepad) in gilrs.gamepads() {
        current_gamepad = Some(gamepad.id());
    }

    let opt = Opt::from_args();
    let plus_center =
        open_location_code::decode(&opt.plus).expect("Failed to parse plus code").center;

    let planet_radius = 6371000.0;
    let mut angle = opt.heading.to_radians();
    let mut lat = plus_center.y().to_radians();
    let mut long = plus_center.x().to_radians();
    let mut altitude = opt.elevation;

    let mut terrain = match opt.generate {
        Some(dataset_directory) => {
            let pb = indicatif::ProgressBar::new(100);
            pb.set_style(
                indicatif::ProgressStyle::default_bar()
                    .template("{msg} {pos}/{len} [{wide_bar}] {percent}% {per_sec} {eta}")
                    .progress_chars("=> "),
            );
            let mut last_message = None;
            let progress_callback = |l: &str, i: usize, total: usize| {
                if last_message.is_none() || l != last_message.as_ref().unwrap() {
                    pb.set_message(l);
                    pb.reset_eta();
                    last_message = Some(l.to_string());
                }
                pb.set_length(total as u64);
                pb.set_position(i as u64);
            };

            runtime
                .block_on(terra::Terrain::generate_and_new(
                    &device,
                    &queue,
                    dataset_directory,
                    progress_callback,
                ))
                .unwrap()
        }
        None => terra::Terrain::new(&device, &queue).unwrap(),
    };

    {
        let r = altitude + planet_radius;
        let eye = cgmath::Point3::new(
            r * lat.cos() * long.cos(),
            r * lat.cos() * long.sin(),
            r * lat.sin(),
        );
        while terrain.poll_loading_status(&device, &queue, eye.into()) {
            std::thread::sleep(std::time::Duration::from_millis(10));
        }
    }
    window.set_visible(true);
    event_loop.run(move |event, _, control_flow| {
        *control_flow = ControlFlow::Poll;
        match event {
            event::Event::WindowEvent { event, .. } => match event {
                event::WindowEvent::CloseRequested => {
                    *control_flow = ControlFlow::Exit;
                }
                event::WindowEvent::KeyboardInput {
                    input:
                        event::KeyboardInput {
                            virtual_keycode: Some(keycode),
                            state: event::ElementState::Pressed,
                            ..
                        },
                    ..
                } => match keycode {
                    event::VirtualKeyCode::Escape => *control_flow = ControlFlow::Exit,
                    event::VirtualKeyCode::Space => altitude += 0.1 * altitude,
                    event::VirtualKeyCode::Z | event::VirtualKeyCode::Semicolon => {
                        altitude -= 0.1 * altitude
                    }
                    event::VirtualKeyCode::Left => {
                        lat += -angle.sin() * -(0.0000001 * altitude).min(0.01);
                        long += angle.cos() * -(0.0000001 * altitude).min(0.01);
                    }
                    event::VirtualKeyCode::Right => {
                        lat += -angle.sin() * (0.0000001 * altitude).min(0.01);
                        long += angle.cos() * (0.0000001 * altitude).min(0.01);
                    }
                    event::VirtualKeyCode::Up => {
                        lat += angle.cos() * (0.0000001 * altitude).min(0.01);
                        long += -angle.sin() * (0.0000001 * altitude).min(0.01);
                    }
                    event::VirtualKeyCode::Down => {
                        lat += angle.cos() * -(0.0000001 * altitude).min(0.01);
                        long += -angle.sin() * -(0.0000001 * altitude).min(0.01);
                    }
                    _ => {}
                },
                event::WindowEvent::Resized(new_size) => {
                    size = new_size;

                    #[cfg(feature = "smaa")]
                    smaa_target.resize(&device, new_size.width, new_size.height);

                    configure_surface(&device, &surface, swapchain_format, size);
                    depth_buffer = make_depth_buffer(&device, size.width, size.height);
                }
                _ => {}
            },
            event::Event::MainEventsCleared => {
                window.request_redraw();
            }
            event::Event::RedrawRequested(_) => {
                let frame_texture = surface.get_current_texture();
                let frame_texture = match frame_texture {
                    Ok(f) => f,
                    Err(_) => return,
                };
                let frame_texture_view = frame_texture.texture.create_view(&Default::default());

                #[cfg(not(feature = "smaa"))]
                let frame = &frame_texture_view;

                #[cfg(feature = "smaa")]
                let frame = smaa_target.start_frame(&device, &queue, &frame_texture_view);

                while let Some(gilrs::Event { id, event: _event, time: _ }) = gilrs.next_event() {
                    current_gamepad = Some(id);
                }
                if let Some(gamepad) = current_gamepad.map(|id| gilrs.gamepad(id)) {
                    lat += angle.cos()
                        * gamepad.value(Axis::LeftStickY) as f64
                        * (0.0000001 * altitude).min(0.01)
                        - angle.sin()
                            * gamepad.value(Axis::LeftStickX) as f64
                            * (0.0000001 * altitude).min(0.01);

                    long += -angle.sin()
                        * gamepad.value(Axis::LeftStickY) as f64
                        * (0.0000001 * altitude).min(0.01)
                        + angle.cos()
                            * gamepad.value(Axis::LeftStickX) as f64
                            * (0.0000001 * altitude).min(0.01);

                    angle -= gamepad.value(Axis::RightZ) as f64 * 0.01;

                    if gamepad.is_pressed(Button::DPadUp) {
                        altitude += 0.01 * altitude;
                    }
                    if gamepad.is_pressed(Button::DPadDown) {
                        altitude -= 0.01 * altitude;
                    }
                }

                lat = lat.max(-PI).min(PI);
                if long < -PI {
                    long += PI * 2.0;
                }
                if long > PI {
                    long -= PI * 2.0;
                }

                let surface_height = terrain.get_height(lat, long) as f64;
                let r = altitude + planet_radius + surface_height + 2.0;
                let eye = cgmath::Point3::new(
                    r * lat.cos() * long.cos(),
                    r * lat.cos() * long.sin(),
                    r * lat.sin(),
                );

                let dt = (planet_radius / (planet_radius + altitude)).acos() * 0.3;
                let latc = lat + angle.cos() * dt;
                let longc = long - angle.sin() * dt;

                let center = cgmath::Point3::new(
                    planet_radius * latc.cos() * longc.cos() - eye.x,
                    planet_radius * latc.cos() * longc.sin() - eye.y,
                    planet_radius * latc.sin() - eye.z,
                );
                let up = cgmath::Vector3::new(eye.x as f32, eye.y as f32, eye.z as f32);

                let view = cgmath::Matrix4::look_at_rh(
                    cgmath::Point3::origin(),
                    cgmath::Point3::new(center.x as f32, center.y as f32, center.z as f32),
                    up,
                );

                let proj = compute_projection_matrix(size.width as f32, size.height as f32);
                let view_proj = proj * view;
                let view_proj = mint::ColumnMatrix4 {
                    x: view_proj.x.into(),
                    y: view_proj.y.into(),
                    z: view_proj.z.into(),
                    w: view_proj.w.into(),
                };

                terrain.render(
                    &device,
                    &queue,
                    &frame,
                    &depth_buffer,
                    (size.width, size.height),
                    view_proj,
                    eye.into(),
                );

                drop(frame);
                frame_texture.present();
            }
            _ => (),
        }
    });
}
<|endoftext|>