<commit_before>/// Internal namespace.
mod internal
{

  ///
  /// Constructor without arguments.
  ///

  pub trait Make0
  where
    Self : Sized,
  {
    /// Constructor without arguments.
    fn make() -> Self
    {
      Self::make_0()
    }
    /// Constructor without arguments.
    fn make_0() -> Self;
  }

  ///
  /// Constructor with single argument.
  ///

  pub trait Make1< Arg >
  where
    Self : Sized,
  {
    /// Constructor without arguments.
    fn make( arg : Arg ) -> Self
    {
      Self::make_1( arg )
    }
    /// Constructor without arguments.
    fn make_1( arg : Arg ) -> Self;
  }

  ///
  /// Constructor with two arguments.
  ///

  pub trait Make2< Arg1, Arg2 >
  where
    Self : Sized,
  {
    /// Constructor with two arguments.
    fn make( arg1 : Arg1, arg2 : Arg2 ) -> Self
    {
      Self::make_2( arg1, arg2 )
    }
    /// Constructor with two arguments.
    fn make_2( arg1 : Arg1, arg2 : Arg2 ) -> Self;
  }

  ///
  /// Constructor with three arguments.
  ///

  pub trait Make3< Arg1, Arg2, Arg3 >
  where
    Self : Sized,
  {
    /// Constructor with three arguments.
    fn make( arg1 : Arg1, arg2 : Arg2, arg3 : Arg3 ) -> Self
    {
      Self::make_3( arg1, arg2, arg3 )
    }
    /// Constructor with three arguments.
    fn make_3( arg1 : Arg1, arg2 : Arg2, arg3 : Arg3 ) -> Self;
  }

  ///
  /// Variadic constructor.
  ///
  /// Unified interface of arbitrary-length constructor.
  ///
  /// ### Sample :: make - variadic constructor
  ///
  /// Implement traits [Make0], [Make1] up to MakeN to provide interface to construct your structure with different set of arguments.
  /// In this example structure Struct1 could be constructed either without arguments, with single argument or with two arguments.
  /// - Constructor without arguments fills fields with zero.
  /// - Constructor with single argument sets both fields to value of the argument.
  /// - Constructor with 2 arguments set individual values of each field.
  ///
  /// ```rust
  /// use type_constructor::prelude::*;
  ///
  /// #[ derive( Debug, PartialEq ) ]
  /// struct Struct1
  /// {
  ///   a : i32,
  ///   b : i32,
  /// }
  ///
  /// impl Make0 for Struct1
  /// {
  ///   fn make_0() -> Self
  ///   {
  ///     Self { a : 0, b : 0 }
  ///   }
  /// }
  ///
  /// impl Make1< i32 > for Struct1
  /// {
  ///   fn make_1( val : i32 ) -> Self
  ///   {
  ///     Self { a : val, b : val }
  ///   }
  /// }
  ///
  /// impl Make2< i32, i32 > for Struct1
  /// {
  ///   fn make_2( val1 : i32, val2 : i32 ) -> Self
  ///   {
  ///     Self { a : val1, b : val2 }
  ///   }
  /// }
  ///
  /// let got : Struct1 = make!();
  /// let exp = Struct1{ a : 0, b : 0 };
  /// assert_eq!( got, exp );
  ///
  /// let got : Struct1 = make!( 13 );
  /// let exp = Struct1{ a : 13, b : 13 };
  /// assert_eq!( got, exp );
  ///
  /// let got : Struct1 = make!( 1, 3 );
  /// let exp = Struct1{ a : 1, b : 3 };
  /// assert_eq!( got, exp );
  /// ```
  ///

  #[ macro_export ]
  macro_rules! make
  {

    (
      $(,)?
    )
    =>
    {
      $crate::Make0::make_0();
    };

    (
      $Arg1 : expr $(,)?
    )
    =>
    {
      $crate::Make1::make_1( $Arg1 );
    };

    (
      $Arg1 : expr, $Arg2 : expr $(,)?
    )
    =>
    {
      $crate::Make2::make_2( $Arg1, $Arg2 );
    };

    (
      $Arg1 : expr, $Arg2 : expr, $Arg3 : expr $(,)?
    )
    =>
    {
      $crate::Make3::make_3( $Arg1, $Arg2, $Arg3 );
    };

    (
      $( $Rest : tt )+
    )
    =>
    {
      compile_error!
      (
        concat!
        (
          "Variadic constructor supports up to 3 arguments.\n",
          "Open an issue if you need more.\n",
          "You passed:\n",
          stringify!
          (
            make!( $( $Rest )+ )
          )
        )
      );
    };

  }

  pub use make;
}

/// Protected namespace of the module.
pub mod protected
{
  pub use super::orphan::*;
}

pub use protected::*;

/// Orphan namespace of the module.
pub mod orphan
{
  pub use super::exposed::*;
}

/// Exposed namespace of the module.
pub mod exposed
{
  pub use super::prelude::*;
}

pub use exposed::*;

/// Prelude to use: `use wtools::prelude::*`.
pub mod prelude
{
  pub use super::internal::
  {

    Make0,
    Make1,
    Make2,
    Make3,

    make,

  };
}
<commit_msg>!build<commit_after>/// Internal namespace.
mod internal
{

  ///
  /// Constructor without arguments.
  ///

  pub trait Make0
  where
    Self : Sized,
  {
    /// Constructor without arguments.
    fn make() -> Self
    {
      Self::make_0()
    }
    /// Constructor without arguments.
    fn make_0() -> Self;
  }

  ///
  /// Constructor with single argument.
  ///

  pub trait Make1< Arg >
  where
    Self : Sized,
  {
    /// Constructor without arguments.
    fn make( arg : Arg ) -> Self
    {
      Self::make_1( arg )
    }
    /// Constructor without arguments.
    fn make_1( arg : Arg ) -> Self;
  }

  ///
  /// Constructor with two arguments.
  ///

  pub trait Make2< Arg1, Arg2 >
  where
    Self : Sized,
  {
    /// Constructor with two arguments.
    fn make( arg1 : Arg1, arg2 : Arg2 ) -> Self
    {
      Self::make_2( arg1, arg2 )
    }
    /// Constructor with two arguments.
    fn make_2( arg1 : Arg1, arg2 : Arg2 ) -> Self;
  }

  ///
  /// Constructor with three arguments.
  ///

  pub trait Make3< Arg1, Arg2, Arg3 >
  where
    Self : Sized,
  {
    /// Constructor with three arguments.
    fn make( arg1 : Arg1, arg2 : Arg2, arg3 : Arg3 ) -> Self
    {
      Self::make_3( arg1, arg2, arg3 )
    }
    /// Constructor with three arguments.
    fn make_3( arg1 : Arg1, arg2 : Arg2, arg3 : Arg3 ) -> Self;
  }

  ///
  /// Variadic constructor.
  ///
  /// Unified interface of arbitrary-length constructor.
  ///
  /// ### Sample :: make - variadic constructor
  ///
  /// Implement traits [Make0], [Make1] up to MakeN to provide interface to construct your structure with different set of arguments.
  /// In this example structure Struct1 could be constructed either without arguments, with single argument or with two arguments.
  /// - Constructor without arguments fills fields with zero.
  /// - Constructor with single argument sets both fields to value of the argument.
  /// - Constructor with 2 arguments set individual values of each field.
  ///
  /// ```rust
  /// use type_constructor::prelude::*;
  ///
  /// #[ derive( Debug, PartialEq ) ]
  /// struct Struct1
  /// {
  ///   a : i32,
  ///   b : i32,
  /// }
  ///
  /// impl Make0 for Struct1
  /// {
  ///   fn make_0() -> Self
  ///   {
  ///     Self { a : 0, b : 0 }
  ///   }
  /// }
  ///
  /// impl Make1< i32 > for Struct1
  /// {
  ///   fn make_1( val : i32 ) -> Self
  ///   {
  ///     Self { a : val, b : val }
  ///   }
  /// }
  ///
  /// impl Make2< i32, i32 > for Struct1
  /// {
  ///   fn make_2( val1 : i32, val2 : i32 ) -> Self
  ///   {
  ///     Self { a : val1, b : val2 }
  ///   }
  /// }
  ///
  /// let got : Struct1 = make!();
  /// let exp = Struct1{ a : 0, b : 0 };
  /// assert_eq!( got, exp );
  ///
  /// let got : Struct1 = make!( 13 );
  /// let exp = Struct1{ a : 13, b : 13 };
  /// assert_eq!( got, exp );
  ///
  /// let got : Struct1 = make!( 1, 3 );
  /// let exp = Struct1{ a : 1, b : 3 };
  /// assert_eq!( got, exp );
  /// ```
  ///

  #[ macro_export ]
  macro_rules! make
  {

    (
      $(,)?
    )
    =>
    {
      $crate::Make0::make_0();
    };

    (
      $Arg1 : expr $(,)?
    )
    =>
    {
      $crate::Make1::make_1( $Arg1 );
    };

    (
      $Arg1 : expr, $Arg2 : expr $(,)?
    )
    =>
    {
      $crate::Make2::make_2( $Arg1, $Arg2 );
    };

    (
      $Arg1 : expr, $Arg2 : expr, $Arg3 : expr $(,)?
    )
    =>
    {
      $crate::Make3::make_3( $Arg1, $Arg2, $Arg3 );
    };

    (
      $( $Rest : tt )+
    )
    =>
    {
      compile_error!
      (
        concat!
        (
          "Variadic constructor supports up to 3 arguments.\n",
          "Open an issue if you need more.\n",
          "You passed:\n",
          stringify!
          (
            make!( $( $Rest )+ )
          )
        )
      );
    };

  }

  pub use make;
}

/// Protected namespace of the module.
pub mod protected
{
  pub use super::orphan::*;
}

pub use protected::*;

/// Orphan namespace of the module.
pub mod orphan
{
  pub use super::exposed::*;
}

/// Exposed namespace of the module.
pub mod exposed
{
  pub use super::prelude::*;
}

pub use exposed::*;

/// Prelude to use: `use wtools::prelude::*`.
pub mod prelude
{
  pub use super::internal::
  {

    Make0,
    Make1,
    Make2,
    Make3,

    make,

  };
}
<|endoftext|>


<commit_before>//! A really dumb PPU benchmark

#![feature(test)]

extern crate breeze_core;
extern crate breeze_frontends;
extern crate test;

use breeze_core::snes::Snes;
use breeze_core::rom::Rom;
use breeze_frontends::RENDERER_MAP;

use test::Bencher;
use std::iter;

fn build_rom() -> Vec<u8> {
    let code = [
        0xA9, 0x00,         // lda #0
        0xA2, 0x00,         // ldx #0
        0xA0, 0x00,         // ldy #0
        0x9A,               // txs

        // Let the PPU do some work
        // Disable forced blank and set brightness to max
        0xA9, 0x0F,         // lda #$0F
        0x8D, 0x00, 0x21,   // sta $2100
        // Enable all layers on the main screen
        0xA9, 0x1F,         // lda #$1F
        0x8D, 0x2C, 0x21,   // sta $212C

        // Enter endless loop
        0xA9, 0x00,         // lda #0
        0xF0, 0xFE,         // beq -2 (self)
    ];

    // Build the header
    let mut header = Vec::with_capacity(32);

    // First 21 Bytes: Title (ASCII)
    let name = "BENCHROM";
    header.extend(name.chars()
                      .map(|c| c as u8)
                      .chain(iter::repeat(' ' as u8))
                      .take(21));

    header.push(0);     // ROM makeup Byte - LoROM, no FastROM
    header.push(0);     // Chipset (none/don't care)
    header.push(6);     // ROM size - $400<<6 = 64K bytes
    header.push(0);     // Cart. RAM size - $400 bytes
    header.push(0);     // Vendor code
    header.push(0);
    header.push(0);     // Version
    header.push(0x55);  // Checksum (invalid)
    header.push(0x55);
    header.push(0xAA);  // Checksum complement
    header.push(0xAA);
    // Extended header (ignored)

    assert_eq!(header.len(), 32);
    assert!(code.len() < 0x8000 - 64, "code size too high");

    // Now we can put the image together
    // The header is located (for LoROM) at `0x8000 - 64`, preceded by code that will be mapped to
    // 0x8000+, followed by the extended header, the interrupt vectors, and the data section(s)
    // (in our case)
    let mut rom = code.iter()
                      .cloned()
                      .chain(iter::repeat(0))
                      .take(0x8000 - 64)
                      .chain(header.into_iter())
                      .chain(iter::repeat(0))
                      .take(0x8000 * 2)
                      .collect::<Vec<_>>();

    // Set the correct vectors (emulation mode)
    // RESET @ 0x8000
    rom[0x7ffc] = 0x00;
    rom[0x7ffd] = 0x80;
    // This should now be a valid, runnable 64K ROM image (minus the checksum)

    rom
}

#[bench]
fn dumb(b: &mut Bencher) {
    let rom = build_rom();
    let rom = Rom::from_bytes(&rom).unwrap();

    // FIXME: Just use DummyRenderer directly
    let mut renderer = RENDERER_MAP.get("dummy").unwrap().unwrap()();
    let mut snes = Snes::new(rom, &mut *renderer);
    b.iter(|| {
        snes.render_frame();
    });
}
<commit_msg>Fix the benchmark<commit_after>//! A really dumb PPU benchmark

#![feature(test)]

extern crate breeze_core;
extern crate breeze_frontends;
extern crate test;

use breeze_core::snes::Snes;
use breeze_core::rom::Rom;
use breeze_frontends::RENDERER_MAP;
use breeze_frontends::frontend::dummy::DummySink;

use test::Bencher;
use std::iter;

fn build_rom() -> Vec<u8> {
    let code = [
        0xA9, 0x00,         // lda #0
        0xA2, 0x00,         // ldx #0
        0xA0, 0x00,         // ldy #0
        0x9A,               // txs

        // Let the PPU do some work
        // Disable forced blank and set brightness to max
        0xA9, 0x0F,         // lda #$0F
        0x8D, 0x00, 0x21,   // sta $2100
        // Enable all layers on the main screen
        0xA9, 0x1F,         // lda #$1F
        0x8D, 0x2C, 0x21,   // sta $212C

        // Enter endless loop
        0xA9, 0x00,         // lda #0
        0xF0, 0xFE,         // beq -2 (self)
    ];

    // Build the header
    let mut header = Vec::with_capacity(32);

    // First 21 Bytes: Title (ASCII)
    let name = "BENCHROM";
    header.extend(name.chars()
                      .map(|c| c as u8)
                      .chain(iter::repeat(' ' as u8))
                      .take(21));

    header.push(0);     // ROM makeup Byte - LoROM, no FastROM
    header.push(0);     // Chipset (none/don't care)
    header.push(6);     // ROM size - $400<<6 = 64K bytes
    header.push(0);     // Cart. RAM size - $400 bytes
    header.push(0);     // Vendor code
    header.push(0);
    header.push(0);     // Version
    header.push(0x55);  // Checksum (invalid)
    header.push(0x55);
    header.push(0xAA);  // Checksum complement
    header.push(0xAA);
    // Extended header (ignored)

    assert_eq!(header.len(), 32);
    assert!(code.len() < 0x8000 - 64, "code size too high");

    // Now we can put the image together
    // The header is located (for LoROM) at `0x8000 - 64`, preceded by code that will be mapped to
    // 0x8000+, followed by the extended header, the interrupt vectors, and the data section(s)
    // (in our case)
    let mut rom = code.iter()
                      .cloned()
                      .chain(iter::repeat(0))
                      .take(0x8000 - 64)
                      .chain(header.into_iter())
                      .chain(iter::repeat(0))
                      .take(0x8000 * 2)
                      .collect::<Vec<_>>();

    // Set the correct vectors (emulation mode)
    // RESET @ 0x8000
    rom[0x7ffc] = 0x00;
    rom[0x7ffd] = 0x80;
    // This should now be a valid, runnable 64K ROM image (minus the checksum)

    rom
}

#[bench]
fn dumb(b: &mut Bencher) {
    let rom = build_rom();
    let rom = Rom::from_bytes(&rom).unwrap();

    // FIXME: Just use DummyRenderer directly
    let mut renderer = RENDERER_MAP.get("dummy").unwrap().unwrap()();
    let mut snes = Snes::new(rom, &mut *renderer, Box::new(DummySink));
    b.iter(|| {
        snes.render_frame();
    });
}
<|endoftext|>


<commit_before>//! Provides sourcemap validation functionality.
use std::fs;
use std::collections::HashMap;
use std::path::{Path, PathBuf};

use url::Url;
use sourcemap;

use CliResult;

fn join_url(base_url: &str, url: &str) -> CliResult<String> {
    if base_url.starts_with("~/") {
        match Url::parse(&format!("http://{}", base_url))?.join(url) {
            Ok(url) => {
                let rv = url.to_string();
                if rv.starts_with("http://~/") {
                    Ok(format!("~/{}", &rv[9..]))
                } else {
                    Ok(rv)
                }
            },
            Err(x) => fail!(x)
        }
    } else {
        Ok(Url::parse(base_url)?.join(url)?.to_string())
    }
}

#[derive(PartialEq)]
enum SourceType {
    Script,
    SourceMap,
}

#[derive(PartialEq, Debug)]
enum LogLevel {
    Info,
    Warning,
    Error,
}

impl LogLevel {
    fn is_insignificant(&self) -> bool {
        *self == LogLevel::Info
    }
}

struct Source {
    url: String,
    file_path: PathBuf,
    ty: SourceType,
}

/// Validates sourcemaps.
pub struct SourceMapValidator {
    sources: HashMap<String, Source>,
    verbose: bool,
}

struct Log {
    pub failed: bool,
    last_source: Option<String>,
    verbose: bool,
}

impl Log {
    pub fn new(verbose: bool) -> Log {
        Log {
            failed: false,
            last_source: None,
            verbose: verbose,
        }
    }

    pub fn log(&mut self, source: &Source, level: LogLevel, message: String) {
        if self.last_source.as_ref() != Some(&source.url) {
            self.last_source = Some(source.url.clone());
            println!("  {}", source.url);
        }
        if level.is_insignificant() && !self.verbose {
            return;
        }
        println!("    {:?}: {}", level, &message);
        if level == LogLevel::Error {
            self.failed = true;
        }
    }

    pub fn error(&mut self, source: &Source, message: String) {
        self.log(source, LogLevel::Error, message);
    }

    pub fn warn(&mut self, source: &Source, message: String) {
        self.log(source, LogLevel::Warning, message);
    }

    pub fn info(&mut self, source: &Source, message: String) {
        self.log(source, LogLevel::Info, message);
    }
}

impl SourceMapValidator {
    /// Creates a new sourcemap validator.  If it's set to verbose
    /// it prints the progress to stdout.
    pub fn new(verbose: bool) -> SourceMapValidator {
        SourceMapValidator {
            sources: HashMap::new(),
            verbose: verbose,
        }
    }

    /// Adds a file for consideration.
    pub fn consider_file(&mut self, path: &Path, url: &str) -> bool {
        let ty = match path.extension().and_then(|x| x.to_str()) {
            Some("js") => SourceType::Script,
            Some("map") => SourceType::SourceMap,
            _ => { return false; }
        };
        self.sources.insert(url.to_owned(), Source {
            url: url.to_owned(),
            file_path: path.to_path_buf(),
            ty: ty,
        });
        true
    }

    fn validate_script(&self, log: &mut Log, source: &Source) -> CliResult<()> {
        let f = fs::File::open(&source.file_path)?;
        let reference = sourcemap::locate_sourcemap_reference(&f)?;
        if let sourcemap::SourceMapRef::LegacyRef(_) = reference {
            log.warn(source, "encountered a legacy reference".into());
        }
        if let Some(url) = reference.get_url() {
            let full_url = join_url(&source.url, url)?;
            log.info(source, format!("sourcemap at {}", full_url));
        } else if source.url.ends_with(".min.js") {
            log.error(source, "missing sourcemap!".into());
        } else {
            log.warn(source, "no sourcemap reference".into());
        }
        Ok(())
    }

    fn validate_sourcemap(&self, log: &mut Log, source: &Source) -> CliResult<()> {
        let f = fs::File::open(&source.file_path)?;
        match sourcemap::decode(&f)? {
            sourcemap::DecodedMap::Regular(sm) => {
                for idx in 0..sm.get_source_count() {
                    let source_url = sm.get_source(idx).unwrap_or("??");
                    if sm.get_source_contents(idx).is_some() ||
                       self.sources.get(source_url).is_some() {
                        log.info(source, format!("found source ({})", source_url));
                    } else {
                        log.warn(source, format!("missing sourcecode ({})", source_url));
                    }
                }
            },
            sourcemap::DecodedMap::Index(_) => {
                log.warn(source, "encountered indexed sourcemap. We
                         cannot validate those.".into());
            }
        }
        Ok(())
    }

    /// Validates all sources within.
    pub fn validate_sources(&self) -> CliResult<()> {
        let mut log = Log::new(self.verbose);
        let mut sources : Vec<_> = self.sources.iter().map(|x| x.1).collect();
        sources.sort_by_key(|x| &x.url);

        for source in sources.iter() {
            match source.ty {
                SourceType::Script => {
                    if let Err(err) = self.validate_script(&mut log, &source) {
                        log.error(&source, format!("failed to process: {}", err));
                    }
                },
                SourceType::SourceMap => {
                    if let Err(err) = self.validate_sourcemap(&mut log, &source) {
                        log.error(&source, format!("failed to process: {}", err));
                    }
                }
            }
        }
        if log.failed {
            fail!("Encountered problems when validating sourcemaps.");
        }
        println!("All Good!");
        Ok(())
    }
}
<commit_msg>Make things a bit more colorful :)<commit_after>//! Provides sourcemap validation functionality.
use std::fs;
use std::collections::HashMap;
use std::path::{Path, PathBuf};

use term;
use url::Url;
use sourcemap;

use CliResult;

fn join_url(base_url: &str, url: &str) -> CliResult<String> {
    if base_url.starts_with("~/") {
        match Url::parse(&format!("http://{}", base_url))?.join(url) {
            Ok(url) => {
                let rv = url.to_string();
                if rv.starts_with("http://~/") {
                    Ok(format!("~/{}", &rv[9..]))
                } else {
                    Ok(rv)
                }
            },
            Err(x) => fail!(x)
        }
    } else {
        Ok(Url::parse(base_url)?.join(url)?.to_string())
    }
}

#[derive(PartialEq)]
enum SourceType {
    Script,
    SourceMap,
}

#[derive(PartialEq, Debug)]
enum LogLevel {
    Info,
    Warning,
    Error,
}

impl LogLevel {
    fn is_insignificant(&self) -> bool {
        *self == LogLevel::Info
    }
}

struct Source {
    url: String,
    file_path: PathBuf,
    ty: SourceType,
}

/// Validates sourcemaps.
pub struct SourceMapValidator {
    sources: HashMap<String, Source>,
    verbose: bool,
}

struct Log {
    pub failed: bool,
    last_source: Option<String>,
    verbose: bool,
}

impl Log {
    pub fn new(verbose: bool) -> Log {
        Log {
            failed: false,
            last_source: None,
            verbose: verbose,
        }
    }

    pub fn log(&mut self, source: &Source, level: LogLevel, message: String) {
        let mut term = term::stderr().unwrap();
        match level {
            LogLevel::Error => { term.fg(term::color::RED).ok(); }
            LogLevel::Warning => { term.fg(term::color::YELLOW).ok(); }
            LogLevel::Info => {}
        }
        if self.last_source.as_ref() != Some(&source.url) {
            self.last_source = Some(source.url.clone());
            writeln!(term, "  {}", source.url).ok();
        }
        if level.is_insignificant() && !self.verbose {
            return;
        }
        writeln!(term, "    {:?}: {}", level, &message).ok();
        if level == LogLevel::Error {
            self.failed = true;
        }
        term.reset().ok();
    }

    pub fn error(&mut self, source: &Source, message: String) {
        self.log(source, LogLevel::Error, message);
    }

    pub fn warn(&mut self, source: &Source, message: String) {
        self.log(source, LogLevel::Warning, message);
    }

    pub fn info(&mut self, source: &Source, message: String) {
        self.log(source, LogLevel::Info, message);
    }
}

impl SourceMapValidator {
    /// Creates a new sourcemap validator.  If it's set to verbose
    /// it prints the progress to stdout.
    pub fn new(verbose: bool) -> SourceMapValidator {
        SourceMapValidator {
            sources: HashMap::new(),
            verbose: verbose,
        }
    }

    /// Adds a file for consideration.
    pub fn consider_file(&mut self, path: &Path, url: &str) -> bool {
        let ty = match path.extension().and_then(|x| x.to_str()) {
            Some("js") => SourceType::Script,
            Some("map") => SourceType::SourceMap,
            _ => { return false; }
        };
        self.sources.insert(url.to_owned(), Source {
            url: url.to_owned(),
            file_path: path.to_path_buf(),
            ty: ty,
        });
        true
    }

    fn validate_script(&self, log: &mut Log, source: &Source) -> CliResult<()> {
        let f = fs::File::open(&source.file_path)?;
        let reference = sourcemap::locate_sourcemap_reference(&f)?;
        if let sourcemap::SourceMapRef::LegacyRef(_) = reference {
            log.warn(source, "encountered a legacy reference".into());
        }
        if let Some(url) = reference.get_url() {
            let full_url = join_url(&source.url, url)?;
            log.info(source, format!("sourcemap at {}", full_url));
        } else if source.url.ends_with(".min.js") {
            log.error(source, "missing sourcemap!".into());
        } else {
            log.warn(source, "no sourcemap reference".into());
        }
        Ok(())
    }

    fn validate_sourcemap(&self, log: &mut Log, source: &Source) -> CliResult<()> {
        let f = fs::File::open(&source.file_path)?;
        match sourcemap::decode(&f)? {
            sourcemap::DecodedMap::Regular(sm) => {
                for idx in 0..sm.get_source_count() {
                    let source_url = sm.get_source(idx).unwrap_or("??");
                    if sm.get_source_contents(idx).is_some() ||
                       self.sources.get(source_url).is_some() {
                        log.info(source, format!("found source ({})", source_url));
                    } else {
                        log.warn(source, format!("missing sourcecode ({})", source_url));
                    }
                }
            },
            sourcemap::DecodedMap::Index(_) => {
                log.warn(source, "encountered indexed sourcemap. We
                         cannot validate those.".into());
            }
        }
        Ok(())
    }

    /// Validates all sources within.
    pub fn validate_sources(&self) -> CliResult<()> {
        let mut log = Log::new(self.verbose);
        let mut sources : Vec<_> = self.sources.iter().map(|x| x.1).collect();
        sources.sort_by_key(|x| &x.url);

        for source in sources.iter() {
            match source.ty {
                SourceType::Script => {
                    if let Err(err) = self.validate_script(&mut log, &source) {
                        log.error(&source, format!("failed to process: {}", err));
                    }
                },
                SourceType::SourceMap => {
                    if let Err(err) = self.validate_sourcemap(&mut log, &source) {
                        log.error(&source, format!("failed to process: {}", err));
                    }
                }
            }
        }
        if log.failed {
            fail!("Encountered problems when validating sourcemaps.");
        }
        println!("All Good!");
        Ok(())
    }
}
<|endoftext|>


<commit_before>
use std::str::CharIndices;
use std::iter::Peekable;

#[derive(PartialEq, Debug)]
pub enum Token<'a> {
  Eof,
  Punctuator(Punctuator, usize, usize),
  Name(&'a str, usize, usize),
  IntValue(&'a str, usize, usize),
  FloatValue(&'a str, usize, usize),
  StringValue(&'a str, usize, usize),
}

#[derive(PartialEq, Debug)]
pub enum Punctuator {
  Bang,
  Dollar,
  LeftParen,
  RightParen,
  Spread,
  Colon,
  Equals,
  At,
  LeftBracket,
  RightBracket,
  LeftBrace,
  RightBrace,
  Pipe,
}

macro_rules! take {
  ($lexer: ident, $($p: pat)|*) => ({
    let mut is_taken = false;
    if let Some(&(p, c)) = $lexer.iter.peek() {
      match c {
        $(
          $p => {
            $lexer.iter.next();
            $lexer.hi = p;
            is_taken = true;
          }
        )*
        _ => {}
      }
    }
    is_taken
  });
}

macro_rules! take_while {
  ($lexer: ident, $($p: pat)|*) => ({
    let mut is_taken = false;
    while let Some(&(p, c)) = $lexer.iter.peek() {
      match c {
        $(
          $p => {
            $lexer.iter.next();
            is_taken = true;
          }
        )*
        _ => {
          $lexer.hi = p;
          break;
        }
      }
    }
    is_taken
  });
}

macro_rules! take_while_not {
  ($lexer: ident, $($p: pat)|*) => ({
    let mut is_taken = false;
    while let Some(&(p, c)) = $lexer.iter.peek() {
      match c {
        $(
          $p => {
            $lexer.hi = p;
            break;
          }
        )*
        _ => {
            $lexer.iter.next();
            is_taken = true;
        }
      }
    }
    is_taken
  });
}

macro_rules! peek {
  ($lexer: ident, $($p: pat)|*) => ({
    let mut is_match = false;
    if let Some(&(_, c)) = $lexer.iter.peek() {
      match c {
        $(
          $p => {
            is_match = true;
          }
        )*
        _ => {}
      }
    }
    is_match
  });
}

macro_rules! take_eof {
  ($lexer: ident) => ({
    if $lexer.iter.peek().is_none() {
      $lexer.hi = $lexer.input_len;
      true
    } else {
      false
    }
  });
}

pub struct Lexer<'a> {
  input: &'a str,
  input_len: usize,
  iter: Peekable<CharIndices<'a>>,
  is_eof: bool,
  lo: usize,
  hi: usize,
}

impl<'a> Lexer<'a> {
  pub fn new(input: &'a str) -> Lexer<'a> {
    Lexer {
      input: input,
      input_len: input.len(),
      iter: input.char_indices().peekable(),
      is_eof: false,
      lo: 0,
      hi: 0,
    }
  }
}

fn skip_ignored_token(lexer: &mut Lexer) {
  loop {
    if take!(lexer, '#') {
      take_while_not!(lexer, '\r' | '\n');
    }
    if !take_while!(lexer, '\u{feff}' | ' ' | '\t' | '\r' | '\n' | ',') {
      break;
    }
  }
}

fn scan_spread(lexer: &mut Lexer) -> bool {
  if take!(lexer, '.') {
    if take!(lexer, '.') {
      if take!(lexer, '.') {
        return true;
      }
    }
  }
  return false;
}

fn scan_name(lexer: &mut Lexer) {
  take_while!(lexer, '_' | 'a'...'z' | 'A'...'Z' | '0'...'9');
  take_eof!(lexer);
}

// Return the raw string without unescape character
fn scan_string(lexer: &mut Lexer) -> (bool, bool) {
  let mut is_bad_escape = false;
  let mut is_terminated = false;
  if take!(lexer, '"') {
    lexer.lo = lexer.lo + 1;
  }
  loop {
    if take!(lexer, '\\') {
      if !take!(lexer, '\\' | '"' | 'b' | 'f' | 'n' | 'r' | 't' | '/' | 'u') {
        is_bad_escape = true;
        break;
      }
    }
    take_while_not!(lexer, '"' | '\\');
    if take!(lexer, '"') {
      is_terminated = true;
      break;
    }
  }
  (is_terminated, is_bad_escape)
}

// IntValue:   (+|-)?(0|[1-9][0-9]*)
// FloatValue: (+|-)?(0|[1-9][0-9]*)(\.[0-9]+)?((E|e)(+|-)?[0-9]+)?
fn scan_number(lexer: &mut Lexer) -> (bool, bool) {
  let mut is_float = false;
  take!(lexer, '+' | '-');
  // Integer part
  if take!(lexer, '1'...'9') {
    take_while!(lexer, '0'...'9');
    if take!(lexer, ' ' | '\t' | '\r' | '\n' | ',') || take_eof!(lexer) {
      return (true, is_float);
    }
  } else if take!(lexer, '0') {
    if take!(lexer, ' ' | '\t' | '\r' | '\n' | ',') || take_eof!(lexer) {
      return (true, is_float);
    }
  }
  // Fractional part
  if take!(lexer, '.') {
    if !take_while!(lexer, '0'...'9') {
      return (false, is_float);
    }
    is_float = true;
  }
  // Exponent part
  if !is_float && peek!(lexer, 'E' | 'e') {
    return (false, is_float);
  }
  if take!(lexer, 'E' | 'e') {
    if take!(lexer, '+' | '-') {
      if !take_while!(lexer, '0'...'9') {
        return (false, is_float);
      }
    } else {
      take_while!(lexer, '0'...'9');
    }
  }

  if take!(lexer, ' ' | '\t' | '\r' | '\n' | ',') || take_eof!(lexer) {
    return (true, is_float);
  }
  return (false, is_float);
}

impl<'a> Iterator for Lexer<'a> {
  type Item = Result<Token<'a>, &'a str>;
  fn next(&mut self) -> Option<Result<Token<'a>, &'a str>> {
    use self::Token::*;
    use self::Punctuator::*;

    if !self.is_eof && take_eof!(self) {
      self.is_eof = true;
      return Some(Ok(Token::Eof));
    }
    if self.is_eof {
      return None;
    }
    skip_ignored_token(self);

    let mut item = None;
    if let Some(&(p, c)) = self.iter.peek() {
      self.lo = p;
      self.hi = p + 1;
      item = match c {
        '!' => {
          self.iter.next();
          Some(Ok(Punctuator(Bang, self.lo, self.hi)))
        }
        '$' => {
          self.iter.next();
          Some(Ok(Punctuator(Dollar, self.lo, self.hi)))
        }
        '(' => {
          self.iter.next();
          Some(Ok(Punctuator(LeftParen, self.lo, self.hi)))
        }
        ')' => {
          self.iter.next();
          Some(Ok(Punctuator(RightParen, self.lo, self.hi)))
        }
        ':' => {
          self.iter.next();
          Some(Ok(Punctuator(Colon, self.lo, self.hi)))
        }
        '=' => {
          self.iter.next();
          Some(Ok(Punctuator(Equals, self.lo, self.hi)))
        }
        '@' => {
          self.iter.next();
          Some(Ok(Punctuator(At, self.lo, self.hi)))
        }
        '[' => {
          self.iter.next();
          Some(Ok(Punctuator(LeftBracket, self.lo, self.hi)))
        }
        ']' => {
          self.iter.next();
          Some(Ok(Punctuator(RightBracket, self.lo, self.hi)))
        }
        '{' => {
          self.iter.next();
          Some(Ok(Punctuator(LeftBrace, self.lo, self.hi)))
        }
        '}' => {
          self.iter.next();
          Some(Ok(Punctuator(RightBrace, self.lo, self.hi)))
        }
        '|' => {
          self.iter.next();
          Some(Ok(Punctuator(Pipe, self.lo, self.hi)))
        }
        '.' => {
          if scan_spread(self) {
            Some(Ok(Punctuator(Spread, self.lo, self.hi + 1)))
          } else {
            Some(Err("Unexpected character."))
          }
        }
        '_' | 'a'...'z' | 'A'...'Z' => {
          scan_name(self);
          Some(Ok(Name(&self.input[self.lo..self.hi], self.lo, self.hi)))
        }
        '-' | '0'...'9' => {
          match scan_number(self) {
            (false, false) => Some(Err("Invalid integer number.")),
            (false, true) => Some(Err("Invalid float number.")),
            (true, false) => Some(Ok(IntValue(&self.input[self.lo..self.hi], self.lo, self.hi))),
            (true, true) => Some(Ok(FloatValue(&self.input[self.lo..self.hi], self.lo, self.hi))),
          }
        }
        '"' => {
          match scan_string(self) {
            (false, _) => Some(Err("Unterminated string.")),
            (_, true) => Some(Err("Bad character escape sequence.")),
            _ => Some(Ok(StringValue(&self.input[self.lo..self.hi], self.lo, self.hi))),
          }
        }
        _ => Some(Err("Unexpected character.")),
      }
    }
    item
  }
}

#[cfg(test)]
mod tests {
  use super::Punctuator::*;
  use super::Token::*;
  use super::{Lexer, Token};

  fn test_next_token(lexer: &mut Lexer, expected: Token) {
    let next = lexer.next();
    assert_eq!(Some(Ok(expected)), next);
  }

  fn test_with_lex(input: &str, expeced: Token) {
    let mut lexer = Lexer::new(&input);
    test_next_token(&mut lexer, expeced);
  }

  fn test_str(input: &str, expeced: &str) {
    let len = expeced.len();
    test_with_lex(input, StringValue(expeced, 1, len + 1))
  }

  #[test]
  fn test_string() {
    test_str(r#""simple""#, r#"simple"#);
    test_str(r#"" white space ""#, r#" white space "#);
    test_str(r#""quote \"""#, r#"quote \""#);
    test_str(r#""slashes \\ \/""#, r#"slashes \\ \/"#);
    test_str(r#""unicode \u1234\u5678\u90AB\uCDEF""#,
             r#"unicode \u1234\u5678\u90AB\uCDEF"#);
  }

  #[test]
  fn test_name() {
    let mut lexer = Lexer::new("     name1    name2   \"simple\" \"  white space   \" other_name");
    test_next_token(&mut lexer, Name("name1", 5, 10));
    test_next_token(&mut lexer, Name("name2", 14, 19));
    test_next_token(&mut lexer, StringValue("simple", 23, 29));
    test_next_token(&mut lexer, StringValue("  white space   ", 32, 48));
    test_next_token(&mut lexer, Name("other_name", 50, 60));
    test_next_token(&mut lexer, Eof);
    assert_eq!(None, lexer.next());
  }

  #[test]
  fn test_number() {
    let mut lexer = Lexer::new("-9 0 9 -0 -9 1234 -1234 0.0 -0.0 1.0 -1.012 -0.101 1.0e2 -1.0E2 \
                                0.00e-002 -0.00E+002 9.1E+0");
    test_next_token(&mut lexer, IntValue("-9", 0, 2));
    test_next_token(&mut lexer, IntValue("0", 3, 4));
    test_next_token(&mut lexer, IntValue("9", 5, 6));
    test_next_token(&mut lexer, IntValue("-0", 7, 9));
    test_next_token(&mut lexer, IntValue("-9", 10, 12));
    test_next_token(&mut lexer, IntValue("1234", 13, 17));
    test_next_token(&mut lexer, IntValue("-1234", 18, 23));
    test_next_token(&mut lexer, FloatValue("0.0", 24, 27));
    test_next_token(&mut lexer, FloatValue("-0.0", 28, 32));
    test_next_token(&mut lexer, FloatValue("1.0", 33, 36));
    test_next_token(&mut lexer, FloatValue("-1.012", 37, 43));
    test_next_token(&mut lexer, FloatValue("-0.101", 44, 50));
    test_next_token(&mut lexer, FloatValue("1.0e2", 51, 56));
    test_next_token(&mut lexer, FloatValue("-1.0E2", 57, 63));
    test_next_token(&mut lexer, FloatValue("0.00e-002", 64, 73));
    test_next_token(&mut lexer, FloatValue("-0.00E+002", 74, 84));
    test_next_token(&mut lexer, FloatValue("9.1E+0", 85, 91));
    test_next_token(&mut lexer, Eof);
    assert_eq!(None, lexer.next());
  }

  #[test]
  fn test_symbol() {
    let mut lexer = Lexer::new("@ !  :$ =    [  {   (|] } )      ...");
    test_next_token(&mut lexer, Punctuator(At, 0, 1));
    test_next_token(&mut lexer, Punctuator(Bang, 2, 3));
    test_next_token(&mut lexer, Punctuator(Colon, 5, 6));
    test_next_token(&mut lexer, Punctuator(Dollar, 6, 7));
    test_next_token(&mut lexer, Punctuator(Equals, 8, 9));
    test_next_token(&mut lexer, Punctuator(LeftBracket, 13, 14));
    test_next_token(&mut lexer, Punctuator(LeftBrace, 16, 17));
    test_next_token(&mut lexer, Punctuator(LeftParen, 20, 21));
    test_next_token(&mut lexer, Punctuator(Pipe, 21, 22));
    test_next_token(&mut lexer, Punctuator(RightBracket, 22, 23));
    test_next_token(&mut lexer, Punctuator(RightBrace, 24, 25));
    test_next_token(&mut lexer, Punctuator(RightParen, 26, 27));
    test_next_token(&mut lexer, Punctuator(Spread, 33, 36));
    test_next_token(&mut lexer, Eof);
    assert_eq!(None, lexer.next());
  }
}
<commit_msg>add commit so that github recognizes the previous one<commit_after>
use std::str::CharIndices;
use std::iter::Peekable;

#[derive(PartialEq, Debug)]
pub enum Token<'a> {
  Eof,
  Punctuator(Punctuator, usize, usize),
  Name(&'a str, usize, usize),
  IntValue(&'a str, usize, usize),
  FloatValue(&'a str, usize, usize),
  StringValue(&'a str, usize, usize),
}

#[derive(PartialEq, Debug)]
pub enum Punctuator {
  Bang,
  Dollar,
  LeftParen,
  RightParen,
  Spread,
  Colon,
  Equals,
  At,
  LeftBracket,
  RightBracket,
  LeftBrace,
  RightBrace,
  Pipe,
}

macro_rules! take {
  ($lexer: ident, $($p: pat)|*) => ({
    let mut is_taken = false;
    if let Some(&(p, c)) = $lexer.iter.peek() {
      match c {
        $(
          $p => {
            $lexer.iter.next();
            $lexer.hi = p;
            is_taken = true;
          }
        )*
        _ => {}
      }
    }
    is_taken
  });
}

macro_rules! take_while {
  ($lexer: ident, $($p: pat)|*) => ({
    let mut is_taken = false;
    while let Some(&(p, c)) = $lexer.iter.peek() {
      match c {
        $(
          $p => {
            $lexer.iter.next();
            is_taken = true;
          }
        )*
        _ => {
          $lexer.hi = p;
          break;
        }
      }
    }
    is_taken
  });
}

macro_rules! take_while_not {
  ($lexer: ident, $($p: pat)|*) => ({
    let mut is_taken = false;
    while let Some(&(p, c)) = $lexer.iter.peek() {
      match c {
        $(
          $p => {
            $lexer.hi = p;
            break;
          }
        )*
        _ => {
            $lexer.iter.next();
            is_taken = true;
        }
      }
    }
    is_taken
  });
}

macro_rules! peek {
  ($lexer: ident, $($p: pat)|*) => ({
    let mut is_match = false;
    if let Some(&(_, c)) = $lexer.iter.peek() {
      match c {
        $(
          $p => {
            is_match = true;
          }
        )*
        _ => {}
      }
    }
    is_match
  });
}

macro_rules! take_eof {
  ($lexer: ident) => ({
    if $lexer.iter.peek().is_none() {
      $lexer.hi = $lexer.input_len;
      true
    } else {
      false
    }
  });
}

pub struct Lexer<'a> {
  input: &'a str,
  input_len: usize,
  iter: Peekable<CharIndices<'a>>,
  is_eof: bool,
  lo: usize,
  hi: usize,
}

impl<'a> Lexer<'a> {
  pub fn new(input: &'a str) -> Lexer<'a> {
    Lexer {
      input: input,
      input_len: input.len(),
      iter: input.char_indices().peekable(),
      is_eof: false,
      lo: 0,
      hi: 0,
    }
  }
}

fn skip_ignored_token(lexer: &mut Lexer) {
  loop {
    if take!(lexer, '#') {
      take_while_not!(lexer, '\r' | '\n');
    }
    if !take_while!(lexer, '\u{feff}' | ' ' | '\t' | '\r' | '\n' | ',') {
      break;
    }
  }
}

fn scan_spread(lexer: &mut Lexer) -> bool {
  if take!(lexer, '.') {
    if take!(lexer, '.') {
      if take!(lexer, '.') {
        lexer.hi += 1;
        return true;
      }
    }
  }
  return false;
}

fn scan_name(lexer: &mut Lexer) {
  take_while!(lexer, '_' | 'a'...'z' | 'A'...'Z' | '0'...'9');
  take_eof!(lexer);
}

// Return the raw string without unescape character
fn scan_string(lexer: &mut Lexer) -> (bool, bool) {
  let mut is_bad_escape = false;
  let mut is_terminated = false;
  if take!(lexer, '"') {
    lexer.lo += 1;
  }
  loop {
    if take!(lexer, '\\') {
      if !take!(lexer, '\\' | '"' | 'b' | 'f' | 'n' | 'r' | 't' | '/' | 'u') {
        is_bad_escape = true;
        break;
      }
    }
    take_while_not!(lexer, '"' | '\\');
    if take!(lexer, '"') {
      is_terminated = true;
      break;
    }
  }
  (is_terminated, is_bad_escape)
}

// IntValue:   (+|-)?(0|[1-9][0-9]*)
// FloatValue: (+|-)?(0|[1-9][0-9]*)(\.[0-9]+)?((E|e)(+|-)?[0-9]+)?
fn scan_number(lexer: &mut Lexer) -> (bool, bool) {
  let mut is_float = false;
  take!(lexer, '+' | '-');
  // Integer part
  if take!(lexer, '1'...'9') {
    take_while!(lexer, '0'...'9');
    if take!(lexer, ' ' | '\t' | '\r' | '\n' | ',') || take_eof!(lexer) {
      return (true, is_float);
    }
  } else if take!(lexer, '0') {
    if take!(lexer, ' ' | '\t' | '\r' | '\n' | ',') || take_eof!(lexer) {
      return (true, is_float);
    }
  }
  // Fractional part
  if take!(lexer, '.') {
    if !take_while!(lexer, '0'...'9') {
      return (false, is_float);
    }
    is_float = true;
  }
  // Exponent part
  if !is_float && peek!(lexer, 'E' | 'e') {
    return (false, is_float);
  }
  if take!(lexer, 'E' | 'e') {
    if take!(lexer, '+' | '-') {
      if !take_while!(lexer, '0'...'9') {
        return (false, is_float);
      }
    } else {
      take_while!(lexer, '0'...'9');
    }
  }

  if take!(lexer, ' ' | '\t' | '\r' | '\n' | ',') || take_eof!(lexer) {
    return (true, is_float);
  }
  return (false, is_float);
}

impl<'a> Iterator for Lexer<'a> {
  type Item = Result<Token<'a>, &'a str>;
  fn next(&mut self) -> Option<Result<Token<'a>, &'a str>> {
    use self::Token::*;
    use self::Punctuator::*;

    if !self.is_eof && take_eof!(self) {
      self.is_eof = true;
      return Some(Ok(Token::Eof));
    }
    if self.is_eof {
      return None;
    }
    skip_ignored_token(self);

    let mut item = None;
    if let Some(&(p, c)) = self.iter.peek() {
      self.lo = p;
      self.hi = p + 1;
      item = match c {
        '!' => {
          self.iter.next();
          Some(Ok(Punctuator(Bang, self.lo, self.hi)))
        }
        '$' => {
          self.iter.next();
          Some(Ok(Punctuator(Dollar, self.lo, self.hi)))
        }
        '(' => {
          self.iter.next();
          Some(Ok(Punctuator(LeftParen, self.lo, self.hi)))
        }
        ')' => {
          self.iter.next();
          Some(Ok(Punctuator(RightParen, self.lo, self.hi)))
        }
        ':' => {
          self.iter.next();
          Some(Ok(Punctuator(Colon, self.lo, self.hi)))
        }
        '=' => {
          self.iter.next();
          Some(Ok(Punctuator(Equals, self.lo, self.hi)))
        }
        '@' => {
          self.iter.next();
          Some(Ok(Punctuator(At, self.lo, self.hi)))
        }
        '[' => {
          self.iter.next();
          Some(Ok(Punctuator(LeftBracket, self.lo, self.hi)))
        }
        ']' => {
          self.iter.next();
          Some(Ok(Punctuator(RightBracket, self.lo, self.hi)))
        }
        '{' => {
          self.iter.next();
          Some(Ok(Punctuator(LeftBrace, self.lo, self.hi)))
        }
        '}' => {
          self.iter.next();
          Some(Ok(Punctuator(RightBrace, self.lo, self.hi)))
        }
        '|' => {
          self.iter.next();
          Some(Ok(Punctuator(Pipe, self.lo, self.hi)))
        }
        '.' => {
          if scan_spread(self) {
            Some(Ok(Punctuator(Spread, self.lo, self.hi)))
          } else {
            Some(Err("Unexpected character."))
          }
        }
        '_' | 'a'...'z' | 'A'...'Z' => {
          scan_name(self);
          Some(Ok(Name(&self.input[self.lo..self.hi], self.lo, self.hi)))
        }
        '-' | '0'...'9' => {
          match scan_number(self) {
            (false, false) => Some(Err("Invalid integer number.")),
            (false, true) => Some(Err("Invalid float number.")),
            (true, false) => Some(Ok(IntValue(&self.input[self.lo..self.hi], self.lo, self.hi))),
            (true, true) => Some(Ok(FloatValue(&self.input[self.lo..self.hi], self.lo, self.hi))),
          }
        }
        '"' => {
          match scan_string(self) {
            (false, _) => Some(Err("Unterminated string.")),
            (_, true) => Some(Err("Bad character escape sequence.")),
            _ => Some(Ok(StringValue(&self.input[self.lo..self.hi], self.lo, self.hi))),
          }
        }
        _ => Some(Err("Unexpected character.")),
      }
    }
    item
  }
}

#[cfg(test)]
mod tests {
  use super::Punctuator::*;
  use super::Token::*;
  use super::{Lexer, Token};

  fn test_next_token(lexer: &mut Lexer, expected: Token) {
    let next = lexer.next();
    assert_eq!(Some(Ok(expected)), next);
  }

  fn test_with_lex(input: &str, expeced: Token) {
    let mut lexer = Lexer::new(&input);
    test_next_token(&mut lexer, expeced);
  }

  fn test_str(input: &str, expeced: &str) {
    let len = expeced.len();
    test_with_lex(input, StringValue(expeced, 1, len + 1))
  }

  #[test]
  fn test_string() {
    test_str(r#""simple""#, r#"simple"#);
    test_str(r#"" white space ""#, r#" white space "#);
    test_str(r#""quote \"""#, r#"quote \""#);
    test_str(r#""slashes \\ \/""#, r#"slashes \\ \/"#);
    test_str(r#""unicode \u1234\u5678\u90AB\uCDEF""#,
             r#"unicode \u1234\u5678\u90AB\uCDEF"#);
  }

  #[test]
  fn test_name() {
    let mut lexer = Lexer::new("     name1    name2   \"simple\" \"  white space   \" other_name");
    test_next_token(&mut lexer, Name("name1", 5, 10));
    test_next_token(&mut lexer, Name("name2", 14, 19));
    test_next_token(&mut lexer, StringValue("simple", 23, 29));
    test_next_token(&mut lexer, StringValue("  white space   ", 32, 48));
    test_next_token(&mut lexer, Name("other_name", 50, 60));
    test_next_token(&mut lexer, Eof);
    assert_eq!(None, lexer.next());
  }

  #[test]
  fn test_number() {
    let mut lexer = Lexer::new("-9 0 9 -0 -9 1234 -1234 0.0 -0.0 1.0 -1.012 -0.101 1.0e2 -1.0E2 \
                                0.00e-002 -0.00E+002 9.1E+0");
    test_next_token(&mut lexer, IntValue("-9", 0, 2));
    test_next_token(&mut lexer, IntValue("0", 3, 4));
    test_next_token(&mut lexer, IntValue("9", 5, 6));
    test_next_token(&mut lexer, IntValue("-0", 7, 9));
    test_next_token(&mut lexer, IntValue("-9", 10, 12));
    test_next_token(&mut lexer, IntValue("1234", 13, 17));
    test_next_token(&mut lexer, IntValue("-1234", 18, 23));
    test_next_token(&mut lexer, FloatValue("0.0", 24, 27));
    test_next_token(&mut lexer, FloatValue("-0.0", 28, 32));
    test_next_token(&mut lexer, FloatValue("1.0", 33, 36));
    test_next_token(&mut lexer, FloatValue("-1.012", 37, 43));
    test_next_token(&mut lexer, FloatValue("-0.101", 44, 50));
    test_next_token(&mut lexer, FloatValue("1.0e2", 51, 56));
    test_next_token(&mut lexer, FloatValue("-1.0E2", 57, 63));
    test_next_token(&mut lexer, FloatValue("0.00e-002", 64, 73));
    test_next_token(&mut lexer, FloatValue("-0.00E+002", 74, 84));
    test_next_token(&mut lexer, FloatValue("9.1E+0", 85, 91));
    test_next_token(&mut lexer, Eof);
    assert_eq!(None, lexer.next());
  }

  #[test]
  fn test_symbol() {
    let mut lexer = Lexer::new("@ !  :$ =    [  {   (|] } )      ...");
    test_next_token(&mut lexer, Punctuator(At, 0, 1));
    test_next_token(&mut lexer, Punctuator(Bang, 2, 3));
    test_next_token(&mut lexer, Punctuator(Colon, 5, 6));
    test_next_token(&mut lexer, Punctuator(Dollar, 6, 7));
    test_next_token(&mut lexer, Punctuator(Equals, 8, 9));
    test_next_token(&mut lexer, Punctuator(LeftBracket, 13, 14));
    test_next_token(&mut lexer, Punctuator(LeftBrace, 16, 17));
    test_next_token(&mut lexer, Punctuator(LeftParen, 20, 21));
    test_next_token(&mut lexer, Punctuator(Pipe, 21, 22));
    test_next_token(&mut lexer, Punctuator(RightBracket, 22, 23));
    test_next_token(&mut lexer, Punctuator(RightBrace, 24, 25));
    test_next_token(&mut lexer, Punctuator(RightParen, 26, 27));
    test_next_token(&mut lexer, Punctuator(Spread, 33, 36));
    test_next_token(&mut lexer, Eof);
    assert_eq!(None, lexer.next());
  }
}
<|endoftext|>


<commit_before>extern crate ggez;
extern crate clap;
use clap::{Arg, App};
use ggez::*;
use ggez::graphics::{DrawMode, Point2, Drawable};
use ggez::event::{Keycode, Mod};
use std::time::Duration;

enum WindowToggle {
    NONE,
    FORWARD,
    REVERSE
}

struct WindowSettings {
    window_size_toggle: WindowToggle,
    toggle_fullscreen: bool,
    is_fullscreen: usize,
    num_of_resolutions: usize,
    resolution_index: usize,
}

struct MainState {
    pos_x: f32,
    angle: f32, // in radians
    window_settings: WindowSettings,
}

impl MainState {
    fn new(_ctx: &mut Context) -> GameResult<MainState> {
        let mut s = MainState {
            pos_x: 0.0,
            angle: 0.0,
            window_settings: WindowSettings {
                toggle_fullscreen: false,
                window_size_toggle: WindowToggle::NONE,
                is_fullscreen: 0,
                resolution_index: 0,
                num_of_resolutions: 0,
            }
        };

        let resolutions = ggez::graphics::get_fullscreen_modes(_ctx, 0)?;
        s.window_settings.num_of_resolutions = resolutions.len();

        Ok(s)
    }
}

impl event::EventHandler for MainState {
    fn update(&mut self, ctx: &mut Context, _dt: Duration) -> GameResult<()> {
        self.pos_x = self.pos_x % 800.0 + 1.0;
        self.angle = self.angle + 0.01;

        if self.window_settings.toggle_fullscreen {
            ggez::graphics::set_fullscreen(ctx, self.window_settings.is_fullscreen != 0)?;
            self.window_settings.toggle_fullscreen = false;
        }

        match self.window_settings.window_size_toggle {
            WindowToggle::FORWARD | WindowToggle::REVERSE => {
                let resolutions = ggez::graphics::get_fullscreen_modes(ctx, 0)?;
                let (width, height) = resolutions[self.window_settings.resolution_index];

                ggez::graphics::set_resolution(ctx, width, height)?;

                self.window_settings.window_size_toggle = WindowToggle::NONE;
            }
            _ => {},
        }

        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
        graphics::clear(ctx);

        let rot_circle = graphics::Mesh::new_circle(ctx, DrawMode::Line(3.0), Point2::new(0.0, 0.0), 100.0, 4.0)?;
        rot_circle.draw(ctx, Point2::new(400.0, 300.0), self.angle)?;

        graphics::present(ctx);
        Ok(())
    }

    fn key_up_event(&mut self, keycode: Keycode, _keymod: Mod, repeat: bool) {

        if !repeat {
            match keycode {
                Keycode::F => {
                    self.window_settings.toggle_fullscreen = true;
                    self.window_settings.is_fullscreen ^= 1;
                }
                Keycode::H => {
                    self.window_settings.window_size_toggle = WindowToggle::FORWARD;
                    self.window_settings.resolution_index += 1;
                    self.window_settings.resolution_index %= self.window_settings.num_of_resolutions;
                }
                Keycode::G => {
                    if self.window_settings.resolution_index > 0 {
                        self.window_settings.window_size_toggle = WindowToggle::REVERSE;
                        self.window_settings.resolution_index -= 1;
                        self.window_settings.resolution_index %= self.window_settings.num_of_resolutions;
                    }
                }
                _ => {},
            }
        }
    }
}

pub fn main() {
    let matches = App::new("graphics settings example")
        .arg(Arg::with_name("msaa")
            .short("m")
            .value_name("N")
            .help("Number of MSAA samples to do (powers of 2 from 1 to 16)")
            .takes_value(true))
        .get_matches();

    let msaa: u32 = matches.value_of("msaa")
        .unwrap_or("1")
        .parse()
        .expect("Option msaa needs to be a number!");
    let mut c = conf::Conf::new();
    c.window_mode.samples = conf::NumSamples::from_u32(msaa)
        .expect("Option msaa needs to be 1, 2, 4, 8 or 16!");
    let ctx = &mut Context::load_from_conf("super_simple", "ggez", c).unwrap();
    let state = &mut MainState::new(ctx).unwrap();
    event::run(ctx, state).unwrap();
}
<commit_msg>Updated to match mainline update<commit_after>extern crate ggez;
extern crate clap;
use clap::{Arg, App};
use ggez::*;
use ggez::graphics::{DrawMode, Point2, Drawable};
use ggez::event::{Keycode, Mod};
use std::time::Duration;

enum WindowToggle {
    NONE,
    FORWARD,
    REVERSE
}

struct WindowSettings {
    window_size_toggle: WindowToggle,
    toggle_fullscreen: bool,
    is_fullscreen: usize,
    num_of_resolutions: usize,
    resolution_index: usize,
}

struct MainState {
    pos_x: f32,
    angle: f32, // in radians
    window_settings: WindowSettings,
}

impl MainState {
    fn new(_ctx: &mut Context) -> GameResult<MainState> {
        let mut s = MainState {
            pos_x: 0.0,
            angle: 0.0,
            window_settings: WindowSettings {
                toggle_fullscreen: false,
                window_size_toggle: WindowToggle::NONE,
                is_fullscreen: 0,
                resolution_index: 0,
                num_of_resolutions: 0,
            }
        };

        let resolutions = ggez::graphics::get_fullscreen_modes(_ctx, 0)?;
        s.window_settings.num_of_resolutions = resolutions.len();

        Ok(s)
    }
}

impl event::EventHandler for MainState {
    fn update(&mut self, ctx: &mut Context) -> GameResult<()> {
        self.pos_x = self.pos_x % 800.0 + 1.0;
        self.angle = self.angle + 0.01;

        if self.window_settings.toggle_fullscreen {
            ggez::graphics::set_fullscreen(ctx, self.window_settings.is_fullscreen != 0)?;
            self.window_settings.toggle_fullscreen = false;
        }

        match self.window_settings.window_size_toggle {
            WindowToggle::FORWARD | WindowToggle::REVERSE => {
                let resolutions = ggez::graphics::get_fullscreen_modes(ctx, 0)?;
                let (width, height) = resolutions[self.window_settings.resolution_index];

                ggez::graphics::set_resolution(ctx, width, height)?;

                self.window_settings.window_size_toggle = WindowToggle::NONE;
            }
            _ => {},
        }

        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
        graphics::clear(ctx);

        let rot_circle = graphics::Mesh::new_circle(ctx, DrawMode::Line(3.0), Point2::new(0.0, 0.0), 100.0, 4.0)?;
        rot_circle.draw(ctx, Point2::new(400.0, 300.0), self.angle)?;

        graphics::present(ctx);
        Ok(())
    }

    fn key_up_event(&mut self, ctx: &mut Context, keycode: Keycode, _keymod: Mod, repeat: bool) {

        if !repeat {
            match keycode {
                Keycode::F => {
                    self.window_settings.toggle_fullscreen = true;
                    self.window_settings.is_fullscreen ^= 1;
                }
                Keycode::H => {
                    self.window_settings.window_size_toggle = WindowToggle::FORWARD;
                    self.window_settings.resolution_index += 1;
                    self.window_settings.resolution_index %= self.window_settings.num_of_resolutions;
                }
                Keycode::G => {
                    if self.window_settings.resolution_index > 0 {
                        self.window_settings.window_size_toggle = WindowToggle::REVERSE;
                        self.window_settings.resolution_index -= 1;
                        self.window_settings.resolution_index %= self.window_settings.num_of_resolutions;
                    }
                }
                _ => {},
            }
        }
    }
}

pub fn main() {
    let matches = App::new("graphics settings example")
        .arg(Arg::with_name("msaa")
            .short("m")
            .value_name("N")
            .help("Number of MSAA samples to do (powers of 2 from 1 to 16)")
            .takes_value(true))
        .get_matches();

    let msaa: u32 = matches.value_of("msaa")
        .unwrap_or("1")
        .parse()
        .expect("Option msaa needs to be a number!");
    let mut c = conf::Conf::new();
    c.window_mode.samples = conf::NumSamples::from_u32(msaa)
        .expect("Option msaa needs to be 1, 2, 4, 8 or 16!");
    let ctx = &mut Context::load_from_conf("super_simple", "ggez", c).unwrap();
    let state = &mut MainState::new(ctx).unwrap();
    event::run(ctx, state).unwrap();
}
<|endoftext|>


<commit_before>extern crate ndarray;
#[macro_use]
extern crate ndarray_linalg;
extern crate num_traits;

use ndarray::*;
use ndarray_linalg::*;
use num_traits::Zero;

fn det_3x3<A, S>(a: ArrayBase<S, Ix2>) -> A
where
    A: Scalar,
    S: Data<Elem = A>,
{
    a[(0, 0)] * a[(1, 1)] * a[(2, 2)] + a[(0, 1)] * a[(1, 2)] * a[(2, 0)] + a[(0, 2)] * a[(1, 0)] * a[(2, 1)] -
        a[(0, 2)] * a[(1, 1)] * a[(2, 0)] - a[(0, 1)] * a[(1, 0)] * a[(2, 2)] - a[(0, 0)] * a[(1, 2)] * a[(2, 1)]
}

#[test]
fn det_zero() {
    macro_rules! det_zero {
        ($elem:ty) => {
            let a: Array2<$elem> = array![[Zero::zero()]];
            assert_eq!(a.det().unwrap(), Zero::zero());
            assert_eq!(a.det_into().unwrap(), Zero::zero());
        }
    }
    det_zero!(f64);
    det_zero!(f32);
    det_zero!(c64);
    det_zero!(c32);
}

#[test]
fn det_zero_nonsquare() {
    macro_rules! det_zero_nonsquare {
        ($elem:ty, $shape:expr) => {
            let a: Array2<$elem> = Array2::zeros($shape);
            assert!(a.det().is_err());
            assert!(a.det_into().is_err());
        }
    }
    for &shape in &[(1, 2).into_shape(), (1, 2).f()] {
        det_zero_nonsquare!(f64, shape);
        det_zero_nonsquare!(f32, shape);
        det_zero_nonsquare!(c64, shape);
        det_zero_nonsquare!(c32, shape);
    }
}

#[test]
fn det() {
    macro_rules! det {
        ($elem:ty, $shape:expr, $rtol:expr) => {
            let a: Array2<$elem> = random($shape);
            println!("a = \n{:?}", a);
            let det = det_3x3(a.view());
            assert_rclose!(a.factorize().unwrap().det().unwrap(), det, $rtol);
            assert_rclose!(a.factorize().unwrap().det_into().unwrap(), det, $rtol);
            assert_rclose!(a.det().unwrap(), det, $rtol);
            assert_rclose!(a.det_into().unwrap(), det, $rtol);
        }
    }
    for &shape in &[(3, 3).into_shape(), (3, 3).f()] {
        det!(f64, shape, 1e-9);
        det!(f32, shape, 1e-4);
        det!(c64, shape, 1e-9);
        det!(c32, shape, 1e-4);
    }
}

#[test]
fn det_nonsquare() {
    macro_rules! det_nonsquare {
        ($elem:ty, $shape:expr) => {
            let a: Array2<$elem> = random($shape);
            assert!(a.factorize().unwrap().det().is_err());
            assert!(a.factorize().unwrap().det_into().is_err());
            assert!(a.det().is_err());
            assert!(a.det_into().is_err());
        }
    }
    for &shape in &[(1, 2).into_shape(), (1, 2).f(), (2, 1).into_shape(), (2, 1).f()] {
        det_nonsquare!(f64, shape);
        det_nonsquare!(f32, shape);
        det_nonsquare!(c64, shape);
        det_nonsquare!(c32, shape);
    }
}
<commit_msg>Add more tests for determinant methods<commit_after>extern crate ndarray;
#[macro_use]
extern crate ndarray_linalg;
extern crate num_traits;

use ndarray::*;
use ndarray_linalg::*;
use num_traits::{One, Zero};

/// Returns the matrix with the specified `row` and `col` removed.
fn matrix_minor<A, S>(a: ArrayBase<S, Ix2>, (row, col): (usize, usize)) -> Array2<A>
where
    A: Scalar,
    S: Data<Elem = A>,
{
    let mut select_rows = (0..a.rows()).collect::<Vec<_>>();
    select_rows.remove(row);
    let mut select_cols = (0..a.cols()).collect::<Vec<_>>();
    select_cols.remove(col);
    a.select(Axis(0), &select_rows).select(
        Axis(1),
        &select_cols,
    )
}

/// Computes the determinant of matrix `a`.
///
/// Note: This implementation is written to be clearly correct so that it's
/// useful for verification, but it's very inefficient.
fn det_naive<A, S>(a: ArrayBase<S, Ix2>) -> A
where
    A: Scalar,
    S: Data<Elem = A>,
{
    assert_eq!(a.rows(), a.cols());
    match a.cols() {
        0 => A::one(),
        1 => a[(0, 0)],
        cols => {
            (0..cols)
                .map(|col| {
                    let sign = if col % 2 == 0 { A::one() } else { -A::one() };
                    sign * a[(0, col)] * det_naive(matrix_minor(a.view(), (0, col)))
                })
                .fold(A::zero(), |sum, subdet| sum + subdet)
        }
    }
}

#[test]
fn det_empty() {
    macro_rules! det_empty {
        ($elem:ty) => {
            let a: Array2<$elem> = Array2::zeros((0, 0));
            assert_eq!(a.factorize().unwrap().det().unwrap(), One::one());
            assert_eq!(a.factorize().unwrap().det_into().unwrap(), One::one());
            assert_eq!(a.det().unwrap(), One::one());
            assert_eq!(a.det_into().unwrap(), One::one());
        }
    }
    det_empty!(f64);
    det_empty!(f32);
    det_empty!(c64);
    det_empty!(c32);
}

#[test]
fn det_zero() {
    macro_rules! det_zero {
        ($elem:ty) => {
            let a: Array2<$elem> = Array2::zeros((1, 1));
            assert_eq!(a.det().unwrap(), Zero::zero());
            assert_eq!(a.det_into().unwrap(), Zero::zero());
        }
    }
    det_zero!(f64);
    det_zero!(f32);
    det_zero!(c64);
    det_zero!(c32);
}

#[test]
fn det_zero_nonsquare() {
    macro_rules! det_zero_nonsquare {
        ($elem:ty, $shape:expr) => {
            let a: Array2<$elem> = Array2::zeros($shape);
            assert!(a.det().is_err());
            assert!(a.det_into().is_err());
        }
    }
    for &shape in &[(1, 2).into_shape(), (1, 2).f()] {
        det_zero_nonsquare!(f64, shape);
        det_zero_nonsquare!(f32, shape);
        det_zero_nonsquare!(c64, shape);
        det_zero_nonsquare!(c32, shape);
    }
}

#[test]
fn det() {
    macro_rules! det {
        ($elem:ty, $shape:expr, $rtol:expr) => {
            let a: Array2<$elem> = random($shape);
            println!("a = \n{:?}", a);
            let det = det_naive(a.view());
            assert_rclose!(a.factorize().unwrap().det().unwrap(), det, $rtol);
            assert_rclose!(a.factorize().unwrap().det_into().unwrap(), det, $rtol);
            assert_rclose!(a.det().unwrap(), det, $rtol);
            assert_rclose!(a.det_into().unwrap(), det, $rtol);
        }
    }
    for rows in 1..5 {
        for &shape in &[(rows, rows).into_shape(), (rows, rows).f()] {
            det!(f64, shape, 1e-9);
            det!(f32, shape, 1e-4);
            det!(c64, shape, 1e-9);
            det!(c32, shape, 1e-4);
        }
    }
}

#[test]
fn det_nonsquare() {
    macro_rules! det_nonsquare {
        ($elem:ty, $shape:expr) => {
            let a: Array2<$elem> = random($shape);
            assert!(a.factorize().unwrap().det().is_err());
            assert!(a.factorize().unwrap().det_into().is_err());
            assert!(a.det().is_err());
            assert!(a.det_into().is_err());
        }
    }
    for &dims in &[(1, 0), (1, 2), (2, 1), (2, 3)] {
        // Work around bug in ndarray: https://github.com/bluss/rust-ndarray/issues/361
        let shapes = if dims == (1, 0) {
            vec![dims.clone().into_shape()]
        } else {
            vec![dims.clone().into_shape(), dims.clone().f()]
        };
        for &shape in &shapes {
            det_nonsquare!(f64, shape);
            det_nonsquare!(f32, shape);
            det_nonsquare!(c64, shape);
            det_nonsquare!(c32, shape);
        }
    }
}
<|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

mod cont;
mod day;
mod month;
mod start;
mod stop;
mod track;
mod ui;
mod week;
mod year;

use cont::cont;
use day::day;
use month::month;
use start::start;
use stop::stop;
use track::track;
use ui::build_ui;
use week::week;
use year::year;

use libimagrt::setup::generate_runtime_setup;

fn main() {
    let rt = generate_runtime_setup("imag-timetrack",
                                    &version!()[..],
                                    "Time tracking module",
                                    build_ui);

    let command = rt.cli().subcommand_name();
    let retval  = if let Some(command) = command {
        debug!("Call: {}", command);
        match command {
            "continue" => cont(&rt),
            "day"      => day(&rt),
            "month"    => month(&rt),
            "start"    => start(&rt),
            "stop"     => stop(&rt),
            "track"    => track(&rt),
            "week"     => week(&rt),
            "year"     => year(&rt),
            _ => {
                error!("Unknown command");
                1
            },
        }
    } else {
        error!("No command");
        1
    };

    ::std::process::exit(retval);
}
<commit_msg>Add missing extern crates<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

#[macro_use]
extern crate log;

#[macro_use]
extern crate version;

extern crate clap;
extern crate semver;
extern crate toml;
extern crate chrono;

extern crate libimagerror;
extern crate libimagstore;
extern crate libimagrt;
extern crate libimagentrytimetrack;
extern crate libimagutil;

mod cont;
mod day;
mod month;
mod start;
mod stop;
mod track;
mod ui;
mod week;
mod year;

use cont::cont;
use day::day;
use month::month;
use start::start;
use stop::stop;
use track::track;
use ui::build_ui;
use week::week;
use year::year;

use libimagrt::setup::generate_runtime_setup;

fn main() {
    let rt = generate_runtime_setup("imag-timetrack",
                                    &version!()[..],
                                    "Time tracking module",
                                    build_ui);

    let command = rt.cli().subcommand_name();
    let retval  = if let Some(command) = command {
        debug!("Call: {}", command);
        match command {
            "continue" => cont(&rt),
            "day"      => day(&rt),
            "month"    => month(&rt),
            "start"    => start(&rt),
            "stop"     => stop(&rt),
            "track"    => track(&rt),
            "week"     => week(&rt),
            "year"     => year(&rt),
            _ => {
                error!("Unknown command");
                1
            },
        }
    } else {
        error!("No command");
        1
    };

    ::std::process::exit(retval);
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2016-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Initial 32-bit bootloader for x86_64
#![crate_name = "boot"]
#![feature(asm)]
#![feature(lang_items)]
#![feature(naked_functions)]
#![feature(static_recursion)]
#![feature(linkage)]
#![feature(struct_field_attributes)]
#![feature(stmt_expr_attributes)]
#![no_std]

const TABLE_LENGTH: usize = 512;

type Table = [u64; TABLE_LENGTH];

use core::convert;

macro_rules! set_flags {
    (%$register:ident $( |= $body:expr);+ ) => {
        let mut $register: usize;
        asm!( concat!("mov $0, ", stringify!($register))
            : "=r"($register)
            ::: "intel");
        $($register |= $body;)+
        asm!( concat!("mov ", stringify!($register), ", $0")
            :: "r"($register)
            :: "intel");
    }
}

#[repr(C, packed)]
pub struct Gdt { _null: u64
               , code: u64
               }

#[repr(C, packed)]
pub struct GdtPointer { /// the length of the GDT
                        pub limit: u16
                      , /// pointer to the GDT
                        pub base: &'static Gdt
                      }

impl GdtPointer {
    #[cold] #[inline(always)]
    unsafe fn load (&self) {
        asm!("lgdt ($0)" :: "r"(self) : "memory");
    }
}

impl convert::From<&'static Gdt> for GdtPointer {
    #[cold] #[inline(always)]
    fn from(gdt: &'static Gdt) -> Self {
        use core::mem::size_of_val;
        GdtPointer { limit: size_of_val(gdt) as u16 - 1
                   , base: gdt }
    }
}

#[link_name = ".gdt64"]
#[link_section = ".gdt"]
#[no_mangle]
pub static GDT: Gdt
    = Gdt { _null: 0
          , code: (1<<44) | (1<<47) | (1<<41) | (1<<43) | (1<<53)
        //   , data: (1 << 44) | (1 << 47) | (1 << 41)
          };

#[cfg(feature = "log")]
#[inline(always)]
#[naked]
fn boot_write(s: &[u8]) {
	use core::ptr;
    let mut offset = 0;
    unsafe {
        let vga_buf: *mut u16 = 0xb8000 as *mut u16;
    	for c in s {
    		ptr::write_volatile( vga_buf.offset(offset)
                               , 0x0200 + *c as u16);
    		offset += 1;
    	}

    }

}

#[cfg(not(feature = "log"))]
fn boot_write(_s: &[u8]) { }

extern "C" {
    static mut pml4_table: Table;
    static mut pdp_table: Table;
    static mut pd_table: Table;
}

#[cold]
#[inline(always)]
#[naked]
unsafe fn create_page_tables() {
    // 3. if everything is okay, create the page tables and start long mode
    const HUGE_PAGE_SIZE: u64 = 2 * 1024 * 1024; // 2 MiB

    //-- map the PML4 and PDP tables -----------------------------------------
    // recursive map last PML4 entry
    pml4_table[511] = (&pml4_table as *const _ as u64) | 0b11;
    // map first PML4 entry to PDP table
    pml4_table[0] = (&pdp_table as *const _ as u64) | 0b11;
    // map first PDPT entry to PD table
    pdp_table[0] = (&pd_table as *const _ as u64) | 0b11;

    boot_write(b"3.1");

    //-- map the PD table ----------------------------------------------------
    for (number, entry) in pd_table.iter_mut().enumerate() {
        // set each PD entry equal to the start address of the page (the page
        // number times the page's size)
        let addr = number as u64 * HUGE_PAGE_SIZE;
        // with the appropriate flags (present + writable + huge)
        // TODO: do we want to do this using bitflags, or is that too
        //       heavyweight for the boot module?
        //          - eliza, 1/23/2017
        *entry = addr | 0b10000011;
    }

    boot_write(b"3.2");
}
#[cold]
#[inline(always)]
#[naked]
unsafe fn set_long_mode() {
    // load PML4 addr to cr3
    asm!("mov cr3, $0" :: "r"(&pml4_table) :: "intel");
    boot_write(b"3.3");

    // // enable PAE flag in cr4
    set_flags!(%cr4 |= 1 << 5 );
    boot_write(b"3.4");

    // set the long mode bit in EFER MSR (model specific register)
    asm!( "mov   ecx, 0xC0000080
           rdmsr
           or    eax, 1 << 8
           wrmsr"
        :::: "intel");
    boot_write(b"3.5");

    // enable paging in cr0
    set_flags!(%cr0 |= 1 << 31;
                    |= 1 << 16 );
}

#[cold]
#[no_mangle]
#[naked]
pub unsafe extern "C" fn _start() {
    boot_write(b"0");
    asm!("cli");

    // 1. Move Multiboot info pointer to edi
    asm!("mov edi, ebx" :::: "intel");
    boot_write(b"1");

    // 2. make sure the system supports SOS
    // TODO: port this from boot.asm
    boot_write(b"2");

    create_page_tables();
    set_long_mode();

    // 4. load the 64-bit GDT
    GdtPointer::from(&GDT).load();
    boot_write(b"4");

    // 6. jump to the 64-bit boot subroutine.
    asm!("ljmpl $$8, $$long_mode_init");

}
<commit_msg>[boot] make boot writing to VGA buffer prettier<commit_after>//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2016-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Initial 32-bit bootloader for x86_64
#![crate_name = "boot"]
#![feature(asm)]
#![feature(lang_items)]
#![feature(naked_functions)]
#![feature(static_recursion)]
#![feature(linkage)]
#![feature(struct_field_attributes)]
#![feature(stmt_expr_attributes)]
#![no_std]

const TABLE_LENGTH: usize = 512;

type Table = [u64; TABLE_LENGTH];

use core::convert;

macro_rules! set_flags {
    (%$register:ident $( |= $body:expr);+ ) => {
        let mut $register: usize;
        asm!( concat!("mov $0, ", stringify!($register))
            : "=r"($register)
            ::: "intel");
        $($register |= $body;)+
        asm!( concat!("mov ", stringify!($register), ", $0")
            :: "r"($register)
            :: "intel");
    }
}

#[repr(C, packed)]
pub struct Gdt { _null: u64
               , code: u64
               }

#[repr(C, packed)]
pub struct GdtPointer { /// the length of the GDT
                        pub limit: u16
                      , /// pointer to the GDT
                        pub base: &'static Gdt
                      }

impl GdtPointer {
    #[cold] #[inline(always)]
    unsafe fn load (&self) {
        asm!("lgdt ($0)" :: "r"(self) : "memory");
    }
}

impl convert::From<&'static Gdt> for GdtPointer {
    #[cold] #[inline(always)]
    fn from(gdt: &'static Gdt) -> Self {
        use core::mem::size_of_val;
        GdtPointer { limit: size_of_val(gdt) as u16 - 1
                   , base: gdt }
    }
}

#[link_name = ".gdt64"]
#[link_section = ".gdt"]
#[no_mangle]
pub static GDT: Gdt
    = Gdt { _null: 0
          , code: (1<<44) | (1<<47) | (1<<41) | (1<<43) | (1<<53)
        //   , data: (1 << 44) | (1 << 47) | (1 << 41)
          };

#[inline(always)]
fn boot_write(s: &[u8]) {
    unsafe {
        use core::ptr::write_volatile;
        let vga_buf = 0xb8000 as *mut u16;
    	for (n, c) in s.iter().enumerate() {
    		write_volatile(vga_buf.offset(n as isize), 0x0200 + *c as u16);
    	}

    }

}

extern "C" {
    static mut pml4_table: Table;
    static mut pdp_table: Table;
    static mut pd_table: Table;
}

#[cold]
#[inline(always)]
#[naked]
unsafe fn create_page_tables() {
    // 3. if everything is okay, create the page tables and start long mode
    const HUGE_PAGE_SIZE: u64 = 2 * 1024 * 1024; // 2 MiB

    //-- map the PML4 and PDP tables -----------------------------------------
    // recursive map last PML4 entry
    pml4_table[511] = (&pml4_table as *const _ as u64) | 0b11;
    // map first PML4 entry to PDP table
    pml4_table[0] = (&pdp_table as *const _ as u64) | 0b11;
    // map first PDPT entry to PD table
    pdp_table[0] = (&pd_table as *const _ as u64) | 0b11;

    boot_write(b"3.1");

    //-- map the PD table ----------------------------------------------------
    for (number, entry) in pd_table.iter_mut().enumerate() {
        // set each PD entry equal to the start address of the page (the page
        // number times the page's size)
        let addr = number as u64 * HUGE_PAGE_SIZE;
        // with the appropriate flags (present + writable + huge)
        // TODO: do we want to do this using bitflags, or is that too
        //       heavyweight for the boot module?
        //          - eliza, 1/23/2017
        *entry = addr | 0b10000011;
    }

    boot_write(b"3.2");
}
#[cold]
#[inline(always)]
#[naked]
unsafe fn set_long_mode() {
    // load PML4 addr to cr3
    asm!("mov cr3, $0" :: "r"(&pml4_table) :: "intel");
    boot_write(b"3.3");

    // // enable PAE flag in cr4
    set_flags!(%cr4 |= 1 << 5 );
    boot_write(b"3.4");

    // set the long mode bit in EFER MSR (model specific register)
    asm!( "mov   ecx, 0xC0000080
           rdmsr
           or    eax, 1 << 8
           wrmsr"
        :::: "intel");
    boot_write(b"3.5");

    // enable paging in cr0
    set_flags!(%cr0 |= 1 << 31;
                    |= 1 << 16 );
}

#[cold]
#[no_mangle]
#[naked]
pub unsafe extern "C" fn _start() {
    boot_write(b"0");
    asm!("cli");

    // 1. Move Multiboot info pointer to edi
    asm!("mov edi, ebx" :::: "intel");
    boot_write(b"1");

    // 2. make sure the system supports SOS
    // TODO: port this from boot.asm
    boot_write(b"2");

    create_page_tables();
    set_long_mode();

    // 4. load the 64-bit GDT
    GdtPointer::from(&GDT).load();
    boot_write(b"4");

    // 6. jump to the 64-bit boot subroutine.
    asm!("ljmpl $$8, $$long_mode_init");

}
<|endoftext|>


<commit_before>//! Custom formatting traits used when outputting Graphviz diagrams with the results of a dataflow
//! analysis.

use rustc_index::bit_set::{BitSet, HybridBitSet};
use rustc_index::vec::Idx;
use std::fmt;

/// An extension to `fmt::Debug` for data that can be better printed with some auxiliary data `C`.
pub trait DebugWithContext<C>: Eq + fmt::Debug {
    fn fmt_with(&self, _ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Debug::fmt(self, f)
    }

    /// Print the difference between `self` and `old`.
    ///
    /// This should print nothing if `self == old`.
    ///
    /// `+` and `-` are typically used to indicate differences. However, these characters are
    /// fairly common and may be needed to print a types representation. If using them to indicate
    /// a diff, prefix them with the "Unit Separator"  control character (␟  U+001F).
    fn fmt_diff_with(&self, old: &Self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        if self == old {
            return Ok(());
        }

        write!(f, "\u{001f}+")?;
        self.fmt_with(ctxt, f)?;

        if f.alternate() {
            write!(f, "\n")?;
        } else {
            write!(f, "\t")?;
        }

        write!(f, "\u{001f}-")?;
        self.fmt_with(ctxt, f)
    }
}

/// Implements `fmt::Debug` by deferring to `<T as DebugWithContext<C>>::fmt_with`.
pub struct DebugWithAdapter<'a, T, C> {
    pub this: T,
    pub ctxt: &'a C,
}

impl<T, C> fmt::Debug for DebugWithAdapter<'_, T, C>
where
    T: DebugWithContext<C>,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.this.fmt_with(self.ctxt, f)
    }
}

/// Implements `fmt::Debug` by deferring to `<T as DebugWithContext<C>>::fmt_diff_with`.
pub struct DebugDiffWithAdapter<'a, T, C> {
    pub new: T,
    pub old: T,
    pub ctxt: &'a C,
}

impl<T, C> fmt::Debug for DebugDiffWithAdapter<'_, T, C>
where
    T: DebugWithContext<C>,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.new.fmt_diff_with(&self.old, self.ctxt, f)
    }
}

// Impls

impl<T, C> DebugWithContext<C> for BitSet<T>
where
    T: Idx + DebugWithContext<C>,
{
    fn fmt_with(&self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_set().entries(self.iter().map(|i| DebugWithAdapter { this: i, ctxt })).finish()
    }

    fn fmt_diff_with(&self, old: &Self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let size = self.domain_size();
        assert_eq!(size, old.domain_size());

        let mut set_in_self = HybridBitSet::new_empty(size);
        let mut cleared_in_self = HybridBitSet::new_empty(size);

        for i in (0..size).map(T::new) {
            match (self.contains(i), old.contains(i)) {
                (true, false) => set_in_self.insert(i),
                (false, true) => cleared_in_self.insert(i),
                _ => continue,
            };
        }

        let mut first = true;
        for idx in set_in_self.iter() {
            let delim = if first {
                "\u{001f}+"
            } else if f.alternate() {
                "\n\u{001f}+"
            } else {
                ", "
            };

            write!(f, "{}", delim)?;
            idx.fmt_with(ctxt, f)?;
            first = false;
        }

        if !f.alternate() {
            first = true;
            if !set_in_self.is_empty() && !cleared_in_self.is_empty() {
                write!(f, "\t")?;
            }
        }

        for idx in cleared_in_self.iter() {
            let delim = if first {
                "\u{001f}-"
            } else if f.alternate() {
                "\n\u{001f}-"
            } else {
                ", "
            };

            write!(f, "{}", delim)?;
            idx.fmt_with(ctxt, f)?;
            first = false;
        }

        Ok(())
    }
}

impl<T, C> DebugWithContext<C> for &'_ T
where
    T: DebugWithContext<C>,
{
    fn fmt_with(&self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        (*self).fmt_with(ctxt, f)
    }

    fn fmt_diff_with(&self, old: &Self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        (*self).fmt_diff_with(*old, ctxt, f)
    }
}

impl<C> DebugWithContext<C> for rustc_middle::mir::Local {}
impl<C> DebugWithContext<C> for crate::dataflow::move_paths::InitIndex {}

impl<'tcx, C> DebugWithContext<C> for crate::dataflow::move_paths::MovePathIndex
where
    C: crate::dataflow::move_paths::HasMoveData<'tcx>,
{
    fn fmt_with(&self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", ctxt.move_data().move_paths[*self])
    }
}

impl<T, C> DebugWithContext<C> for crate::dataflow::lattice::Dual<T>
where
    T: DebugWithContext<C>,
{
    fn fmt_with(&self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        (self.0).fmt_with(ctxt, f)
    }

    fn fmt_diff_with(&self, old: &Self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        (self.0).fmt_diff_with(&old.0, ctxt, f)
    }
}
<commit_msg>Fix bug in fmt_diff_with<commit_after>//! Custom formatting traits used when outputting Graphviz diagrams with the results of a dataflow
//! analysis.

use rustc_index::bit_set::{BitSet, HybridBitSet};
use rustc_index::vec::Idx;
use std::fmt;

/// An extension to `fmt::Debug` for data that can be better printed with some auxiliary data `C`.
pub trait DebugWithContext<C>: Eq + fmt::Debug {
    fn fmt_with(&self, _ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Debug::fmt(self, f)
    }

    /// Print the difference between `self` and `old`.
    ///
    /// This should print nothing if `self == old`.
    ///
    /// `+` and `-` are typically used to indicate differences. However, these characters are
    /// fairly common and may be needed to print a types representation. If using them to indicate
    /// a diff, prefix them with the "Unit Separator"  control character (␟  U+001F).
    fn fmt_diff_with(&self, old: &Self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        if self == old {
            return Ok(());
        }

        write!(f, "\u{001f}+")?;
        self.fmt_with(ctxt, f)?;

        if f.alternate() {
            write!(f, "\n")?;
        } else {
            write!(f, "\t")?;
        }

        write!(f, "\u{001f}-")?;
        old.fmt_with(ctxt, f)
    }
}

/// Implements `fmt::Debug` by deferring to `<T as DebugWithContext<C>>::fmt_with`.
pub struct DebugWithAdapter<'a, T, C> {
    pub this: T,
    pub ctxt: &'a C,
}

impl<T, C> fmt::Debug for DebugWithAdapter<'_, T, C>
where
    T: DebugWithContext<C>,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.this.fmt_with(self.ctxt, f)
    }
}

/// Implements `fmt::Debug` by deferring to `<T as DebugWithContext<C>>::fmt_diff_with`.
pub struct DebugDiffWithAdapter<'a, T, C> {
    pub new: T,
    pub old: T,
    pub ctxt: &'a C,
}

impl<T, C> fmt::Debug for DebugDiffWithAdapter<'_, T, C>
where
    T: DebugWithContext<C>,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.new.fmt_diff_with(&self.old, self.ctxt, f)
    }
}

// Impls

impl<T, C> DebugWithContext<C> for BitSet<T>
where
    T: Idx + DebugWithContext<C>,
{
    fn fmt_with(&self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_set().entries(self.iter().map(|i| DebugWithAdapter { this: i, ctxt })).finish()
    }

    fn fmt_diff_with(&self, old: &Self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let size = self.domain_size();
        assert_eq!(size, old.domain_size());

        let mut set_in_self = HybridBitSet::new_empty(size);
        let mut cleared_in_self = HybridBitSet::new_empty(size);

        for i in (0..size).map(T::new) {
            match (self.contains(i), old.contains(i)) {
                (true, false) => set_in_self.insert(i),
                (false, true) => cleared_in_self.insert(i),
                _ => continue,
            };
        }

        let mut first = true;
        for idx in set_in_self.iter() {
            let delim = if first {
                "\u{001f}+"
            } else if f.alternate() {
                "\n\u{001f}+"
            } else {
                ", "
            };

            write!(f, "{}", delim)?;
            idx.fmt_with(ctxt, f)?;
            first = false;
        }

        if !f.alternate() {
            first = true;
            if !set_in_self.is_empty() && !cleared_in_self.is_empty() {
                write!(f, "\t")?;
            }
        }

        for idx in cleared_in_self.iter() {
            let delim = if first {
                "\u{001f}-"
            } else if f.alternate() {
                "\n\u{001f}-"
            } else {
                ", "
            };

            write!(f, "{}", delim)?;
            idx.fmt_with(ctxt, f)?;
            first = false;
        }

        Ok(())
    }
}

impl<T, C> DebugWithContext<C> for &'_ T
where
    T: DebugWithContext<C>,
{
    fn fmt_with(&self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        (*self).fmt_with(ctxt, f)
    }

    fn fmt_diff_with(&self, old: &Self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        (*self).fmt_diff_with(*old, ctxt, f)
    }
}

impl<C> DebugWithContext<C> for rustc_middle::mir::Local {}
impl<C> DebugWithContext<C> for crate::dataflow::move_paths::InitIndex {}

impl<'tcx, C> DebugWithContext<C> for crate::dataflow::move_paths::MovePathIndex
where
    C: crate::dataflow::move_paths::HasMoveData<'tcx>,
{
    fn fmt_with(&self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", ctxt.move_data().move_paths[*self])
    }
}

impl<T, C> DebugWithContext<C> for crate::dataflow::lattice::Dual<T>
where
    T: DebugWithContext<C>,
{
    fn fmt_with(&self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        (self.0).fmt_with(ctxt, f)
    }

    fn fmt_diff_with(&self, old: &Self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        (self.0).fmt_diff_with(&old.0, ctxt, f)
    }
}
<|endoftext|>