<commit_before>use super::*;

pub trait Notification {
    type Params;
    const METHOD: &'static str;
}

#[macro_export]
macro_rules! lsp_notification {
    ("$/cancelRequest") => {
        $crate::notification::Cancel
    };
    ("initialized") => {
        $crate::notification::Initialized
    };
    ("exit") => {
        $crate::notification::Exit
    };

    ("window/showMessage") => {
        $crate::notification::ShowMessage
    };
    ("window/logMessage") => {
        $crate::notification::LogMessage
    };

    ("telemetry/event") => {
        $crate::notification::TelemetryEvent
    };

    ("textDocument/didOpen") => {
        $crate::notification::DidOpenTextDocument
    };
    ("textDocument/didChange") => {
        $crate::notification::DidChangeTextDocument
    };
    ("textDocument/willSave") => {
        $crate::notification::WillSaveTextDocument
    };
    ("textDocument/willSaveWaitUntil") => {
        $crate::notification::WillSaveWaitUntil
    };
    ("textDocument/didSave") => {
        $crate::notification::DidSaveTextDocument
    };
    ("textDocument/didClose") => {
        $crate::notification::DidCloseTextDocument
    };
    ("textDocument/publishDiagnostics") => {
        $crate::notification::PublishDiagnostics
    };

    ("workspace/didChangeConfiguration") => {
        $crate::notification::DidChangeConfiguration
    };
    ("workspace/didChangeWatchedFiles") => {
        $crate::notification::DidChangeWatchedFiles
    };
    ("workspace/didChangeWorkspaceFolders") => {
        $crate::notification::DidChangeWorkspaceFolders
    };

    // Requires #[cfg(feature = "proposed")]
    ("$/progress") => {
        $crate::notification::Progress
    };

    // Requires #[cfg(feature = "proposed")]
    ("window/workDoneProgress/cancel") => {
        $crate::notification::WorkDoneProgressCancel
    };
}

/// The base protocol now offers support for request cancellation. To cancel a request,
/// a notification message with the following properties is sent:
///
/// A request that got canceled still needs to return from the server and send a response back.
/// It can not be left open / hanging. This is in line with the JSON RPC protocol that requires
/// that every request sends a response back. In addition it allows for returning partial results on cancel.
#[derive(Debug)]
pub enum Cancel {}

impl Notification for Cancel {
    type Params = CancelParams;
    const METHOD: &'static str = "$/cancelRequest";
}

/// The initialized notification is sent from the client to the server after the client received
/// the result of the initialize request but before the client is sending any other request or
/// notification to the server. The server can use the initialized notification for example to
/// dynamically register capabilities.
#[derive(Debug)]
pub enum Initialized {}

impl Notification for Initialized {
    type Params = InitializedParams;
    const METHOD: &'static str = "initialized";
}

/**
 * A notification to ask the server to exit its process.
 * The server should exit with success code 0 if the shutdown request has been received before;
 * otherwise with error code 1.
 */
#[derive(Debug)]
pub enum Exit {}

impl Notification for Exit {
    type Params = ();
    const METHOD: &'static str = "exit";
}

/**
 * The show message notification is sent from a server to a client to ask the client to display a particular message
 * in the user interface.
 */
#[derive(Debug)]
pub enum ShowMessage {}

impl Notification for ShowMessage {
    type Params = ShowMessageParams;
    const METHOD: &'static str = "window/showMessage";
}

/**
 * The log message notification is sent from the server to the client to ask the client to log a particular message.
 */
#[derive(Debug)]
pub enum LogMessage {}

impl Notification for LogMessage {
    type Params = LogMessageParams;
    const METHOD: &'static str = "window/logMessage";
}

/**
 * The telemetry notification is sent from the server to the client to ask the client to log a telemetry event.
 */
#[derive(Debug)]
pub enum TelemetryEvent {}

impl Notification for TelemetryEvent {
    type Params = serde_json::Value;
    const METHOD: &'static str = "telemetry/event";
}

/**
 * A notification sent from the client to the server to signal the change of configuration settings.
 */
#[derive(Debug)]
pub enum DidChangeConfiguration {}

impl Notification for DidChangeConfiguration {
    type Params = DidChangeConfigurationParams;
    const METHOD: &'static str = "workspace/didChangeConfiguration";
}

/**
 * The document open notification is sent from the client to the server to signal newly opened text documents.
 * The document's truth is now managed by the client and the server must not try to read the document's truth
 * using the document's uri.
 */
#[derive(Debug)]
pub enum DidOpenTextDocument {}

impl Notification for DidOpenTextDocument {
    type Params = DidOpenTextDocumentParams;
    const METHOD: &'static str = "textDocument/didOpen";
}

/**
 * The document change notification is sent from the client to the server to signal changes to a text document.
 * In 2.0 the shape of the params has changed to include proper version numbers and language ids.
 */
#[derive(Debug)]
pub enum DidChangeTextDocument {}

impl Notification for DidChangeTextDocument {
    type Params = DidChangeTextDocumentParams;
    const METHOD: &'static str = "textDocument/didChange";
}

/// The document will save notification is sent from the client to the server before the document
/// is actually saved.
#[derive(Debug)]
pub enum WillSaveTextDocument {}

impl Notification for WillSaveTextDocument {
    type Params = WillSaveTextDocumentParams;
    const METHOD: &'static str = "textDocument/willSave";
}

/// The document will save request is sent from the client to the server before the document is
/// actually saved. The request can return an array of TextEdits which will be applied to the text
/// document before it is saved. Please note that clients might drop results if computing the text
/// edits took too long or if a server constantly fails on this request. This is done to keep the
/// save fast and reliable.
#[derive(Debug)]
pub enum WillSaveWaitUntil {}

impl Notification for WillSaveWaitUntil {
    type Params = WillSaveTextDocumentParams;
    const METHOD: &'static str = "textDocument/willSaveWaitUntil";
}

/**
 * The document close notification is sent from the client to the server when the document got closed in the client.
 * The document's truth now exists where the document's uri points to (e.g. if the document's uri is a file uri
 * the truth now exists on disk).
 */
#[derive(Debug)]
pub enum DidCloseTextDocument {}

impl Notification for DidCloseTextDocument {
    type Params = DidCloseTextDocumentParams;
    const METHOD: &'static str = "textDocument/didClose";
}

/**
 * The document save notification is sent from the client to the server when the document was saved in the client.
 */
#[derive(Debug)]
pub enum DidSaveTextDocument {}

impl Notification for DidSaveTextDocument {
    type Params = DidSaveTextDocumentParams;
    const METHOD: &'static str = "textDocument/didSave";
}

/**
 * The watched files notification is sent from the client to the server when the client detects changes to files
 * watched by the language client.
 */
#[derive(Debug)]
pub enum DidChangeWatchedFiles {}

impl Notification for DidChangeWatchedFiles {
    type Params = DidChangeWatchedFilesParams;
    const METHOD: &'static str = "workspace/didChangeWatchedFiles";
}

/**
 * The workspace/didChangeWorkspaceFolders notification is sent from the client to the server to inform the server
 * about workspace folder configuration changes
 */
#[derive(Debug)]
pub enum DidChangeWorkspaceFolders {}

impl Notification for DidChangeWorkspaceFolders {
    type Params = DidChangeWorkspaceFoldersParams;
    const METHOD: &'static str = "workspace/didChangeWorkspaceFolders";
}

/**
 * Diagnostics notification are sent from the server to the client to signal results of validation runs.
 */
#[derive(Debug)]
pub enum PublishDiagnostics {}

impl Notification for PublishDiagnostics {
    type Params = PublishDiagnosticsParams;
    const METHOD: &'static str = "textDocument/publishDiagnostics";
}

#[cfg(feature = "proposed")]
/// The progress notification is sent from the server to the client to ask
/// the client to indicate progress.
#[derive(Debug)]
pub enum Progress {}

#[cfg(feature = "proposed")]
impl Notification for Progress {
    type Params = ProgressParams;
    const METHOD: &'static str = "$/progress";
}

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

    fn fake_call<N>()
    where
        N: Notification,
        N::Params: serde::Serialize,
    {
    }

    macro_rules! check_macro {
        ($name:tt) => {
            // check whether the macro name matches the method
            assert_eq!(<lsp_notification!($name) as Notification>::METHOD, $name);
            // test whether type checking passes for each component
            fake_call::<lsp_notification!($name)>();
        };
    }

    #[test]
    fn check_macro_definitions() {
        check_macro!("$/cancelRequest");
        check_macro!("initialized");
        check_macro!("exit");
        check_macro!("window/showMessage");
        check_macro!("window/logMessage");
        check_macro!("telemetry/event");
        check_macro!("textDocument/didOpen");
        check_macro!("textDocument/didChange");
        check_macro!("textDocument/willSave");
        check_macro!("textDocument/willSaveWaitUntil");
        check_macro!("textDocument/didSave");
        check_macro!("textDocument/didClose");
        check_macro!("textDocument/publishDiagnostics");
        check_macro!("workspace/didChangeConfiguration");
        check_macro!("workspace/didChangeWatchedFiles");
        check_macro!("workspace/didChangeWorkspaceFolders");
    }

    #[test]
    #[cfg(feature = "proposed")]
    fn check_proposed_macro_definitions() {
        check_macro!("$/progress");
        check_macro!("window/workDoneProgress/cancel");
    }
}
<commit_msg>Fix test<commit_after>use super::*;

pub trait Notification {
    type Params;
    const METHOD: &'static str;
}

#[macro_export]
macro_rules! lsp_notification {
    ("$/cancelRequest") => {
        $crate::notification::Cancel
    };
    ("initialized") => {
        $crate::notification::Initialized
    };
    ("exit") => {
        $crate::notification::Exit
    };

    ("window/showMessage") => {
        $crate::notification::ShowMessage
    };
    ("window/logMessage") => {
        $crate::notification::LogMessage
    };

    ("telemetry/event") => {
        $crate::notification::TelemetryEvent
    };

    ("textDocument/didOpen") => {
        $crate::notification::DidOpenTextDocument
    };
    ("textDocument/didChange") => {
        $crate::notification::DidChangeTextDocument
    };
    ("textDocument/willSave") => {
        $crate::notification::WillSaveTextDocument
    };
    ("textDocument/willSaveWaitUntil") => {
        $crate::notification::WillSaveWaitUntil
    };
    ("textDocument/didSave") => {
        $crate::notification::DidSaveTextDocument
    };
    ("textDocument/didClose") => {
        $crate::notification::DidCloseTextDocument
    };
    ("textDocument/publishDiagnostics") => {
        $crate::notification::PublishDiagnostics
    };

    ("workspace/didChangeConfiguration") => {
        $crate::notification::DidChangeConfiguration
    };
    ("workspace/didChangeWatchedFiles") => {
        $crate::notification::DidChangeWatchedFiles
    };
    ("workspace/didChangeWorkspaceFolders") => {
        $crate::notification::DidChangeWorkspaceFolders
    };

    // Requires #[cfg(feature = "proposed")]
    ("$/progress") => {
        $crate::notification::Progress
    };
}

/// The base protocol now offers support for request cancellation. To cancel a request,
/// a notification message with the following properties is sent:
///
/// A request that got canceled still needs to return from the server and send a response back.
/// It can not be left open / hanging. This is in line with the JSON RPC protocol that requires
/// that every request sends a response back. In addition it allows for returning partial results on cancel.
#[derive(Debug)]
pub enum Cancel {}

impl Notification for Cancel {
    type Params = CancelParams;
    const METHOD: &'static str = "$/cancelRequest";
}

/// The initialized notification is sent from the client to the server after the client received
/// the result of the initialize request but before the client is sending any other request or
/// notification to the server. The server can use the initialized notification for example to
/// dynamically register capabilities.
#[derive(Debug)]
pub enum Initialized {}

impl Notification for Initialized {
    type Params = InitializedParams;
    const METHOD: &'static str = "initialized";
}

/**
 * A notification to ask the server to exit its process.
 * The server should exit with success code 0 if the shutdown request has been received before;
 * otherwise with error code 1.
 */
#[derive(Debug)]
pub enum Exit {}

impl Notification for Exit {
    type Params = ();
    const METHOD: &'static str = "exit";
}

/**
 * The show message notification is sent from a server to a client to ask the client to display a particular message
 * in the user interface.
 */
#[derive(Debug)]
pub enum ShowMessage {}

impl Notification for ShowMessage {
    type Params = ShowMessageParams;
    const METHOD: &'static str = "window/showMessage";
}

/**
 * The log message notification is sent from the server to the client to ask the client to log a particular message.
 */
#[derive(Debug)]
pub enum LogMessage {}

impl Notification for LogMessage {
    type Params = LogMessageParams;
    const METHOD: &'static str = "window/logMessage";
}

/**
 * The telemetry notification is sent from the server to the client to ask the client to log a telemetry event.
 */
#[derive(Debug)]
pub enum TelemetryEvent {}

impl Notification for TelemetryEvent {
    type Params = serde_json::Value;
    const METHOD: &'static str = "telemetry/event";
}

/**
 * A notification sent from the client to the server to signal the change of configuration settings.
 */
#[derive(Debug)]
pub enum DidChangeConfiguration {}

impl Notification for DidChangeConfiguration {
    type Params = DidChangeConfigurationParams;
    const METHOD: &'static str = "workspace/didChangeConfiguration";
}

/**
 * The document open notification is sent from the client to the server to signal newly opened text documents.
 * The document's truth is now managed by the client and the server must not try to read the document's truth
 * using the document's uri.
 */
#[derive(Debug)]
pub enum DidOpenTextDocument {}

impl Notification for DidOpenTextDocument {
    type Params = DidOpenTextDocumentParams;
    const METHOD: &'static str = "textDocument/didOpen";
}

/**
 * The document change notification is sent from the client to the server to signal changes to a text document.
 * In 2.0 the shape of the params has changed to include proper version numbers and language ids.
 */
#[derive(Debug)]
pub enum DidChangeTextDocument {}

impl Notification for DidChangeTextDocument {
    type Params = DidChangeTextDocumentParams;
    const METHOD: &'static str = "textDocument/didChange";
}

/// The document will save notification is sent from the client to the server before the document
/// is actually saved.
#[derive(Debug)]
pub enum WillSaveTextDocument {}

impl Notification for WillSaveTextDocument {
    type Params = WillSaveTextDocumentParams;
    const METHOD: &'static str = "textDocument/willSave";
}

/// The document will save request is sent from the client to the server before the document is
/// actually saved. The request can return an array of TextEdits which will be applied to the text
/// document before it is saved. Please note that clients might drop results if computing the text
/// edits took too long or if a server constantly fails on this request. This is done to keep the
/// save fast and reliable.
#[derive(Debug)]
pub enum WillSaveWaitUntil {}

impl Notification for WillSaveWaitUntil {
    type Params = WillSaveTextDocumentParams;
    const METHOD: &'static str = "textDocument/willSaveWaitUntil";
}

/**
 * The document close notification is sent from the client to the server when the document got closed in the client.
 * The document's truth now exists where the document's uri points to (e.g. if the document's uri is a file uri
 * the truth now exists on disk).
 */
#[derive(Debug)]
pub enum DidCloseTextDocument {}

impl Notification for DidCloseTextDocument {
    type Params = DidCloseTextDocumentParams;
    const METHOD: &'static str = "textDocument/didClose";
}

/**
 * The document save notification is sent from the client to the server when the document was saved in the client.
 */
#[derive(Debug)]
pub enum DidSaveTextDocument {}

impl Notification for DidSaveTextDocument {
    type Params = DidSaveTextDocumentParams;
    const METHOD: &'static str = "textDocument/didSave";
}

/**
 * The watched files notification is sent from the client to the server when the client detects changes to files
 * watched by the language client.
 */
#[derive(Debug)]
pub enum DidChangeWatchedFiles {}

impl Notification for DidChangeWatchedFiles {
    type Params = DidChangeWatchedFilesParams;
    const METHOD: &'static str = "workspace/didChangeWatchedFiles";
}

/**
 * The workspace/didChangeWorkspaceFolders notification is sent from the client to the server to inform the server
 * about workspace folder configuration changes
 */
#[derive(Debug)]
pub enum DidChangeWorkspaceFolders {}

impl Notification for DidChangeWorkspaceFolders {
    type Params = DidChangeWorkspaceFoldersParams;
    const METHOD: &'static str = "workspace/didChangeWorkspaceFolders";
}

/**
 * Diagnostics notification are sent from the server to the client to signal results of validation runs.
 */
#[derive(Debug)]
pub enum PublishDiagnostics {}

impl Notification for PublishDiagnostics {
    type Params = PublishDiagnosticsParams;
    const METHOD: &'static str = "textDocument/publishDiagnostics";
}

#[cfg(feature = "proposed")]
/// The progress notification is sent from the server to the client to ask
/// the client to indicate progress.
#[derive(Debug)]
pub enum Progress {}

#[cfg(feature = "proposed")]
impl Notification for Progress {
    type Params = ProgressParams;
    const METHOD: &'static str = "$/progress";
}

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

    fn fake_call<N>()
    where
        N: Notification,
        N::Params: serde::Serialize,
    {
    }

    macro_rules! check_macro {
        ($name:tt) => {
            // check whether the macro name matches the method
            assert_eq!(<lsp_notification!($name) as Notification>::METHOD, $name);
            // test whether type checking passes for each component
            fake_call::<lsp_notification!($name)>();
        };
    }

    #[test]
    fn check_macro_definitions() {
        check_macro!("$/cancelRequest");
        check_macro!("initialized");
        check_macro!("exit");
        check_macro!("window/showMessage");
        check_macro!("window/logMessage");
        check_macro!("telemetry/event");
        check_macro!("textDocument/didOpen");
        check_macro!("textDocument/didChange");
        check_macro!("textDocument/willSave");
        check_macro!("textDocument/willSaveWaitUntil");
        check_macro!("textDocument/didSave");
        check_macro!("textDocument/didClose");
        check_macro!("textDocument/publishDiagnostics");
        check_macro!("workspace/didChangeConfiguration");
        check_macro!("workspace/didChangeWatchedFiles");
        check_macro!("workspace/didChangeWorkspaceFolders");
    }

    #[test]
    #[cfg(feature = "proposed")]
    fn check_proposed_macro_definitions() {
        check_macro!("$/progress");
    }
}
<|endoftext|>


<commit_before>use rusqlite::Connection;
use std::env;
use std::fs::create_dir_all;

pub fn db_exists() -> bool {
    let tmp = env::home_dir();
    let mut path_buf = tmp.unwrap();
    path_buf.push("Film-O-Mat");
    path_buf.push("database");
    path_buf.set_extension("db");
    path_buf.as_path().exists()
}

fn get_connection() -> Connection {
    let tmp = env::home_dir();
    let mut path_buf = tmp.unwrap();
    path_buf.push("Film-O-Mat");
    path_buf.push("database");
    path_buf.set_extension("db");

    let conn = Connection::open(path_buf).unwrap();
    conn
}

pub fn create_database() {
    let conn = get_connection();

    conn.execute("CREATE TABLE IF NOT EXISTS movies (
                  id              INTEGER PRIMARY KEY,
                  name            TEXT NOT NULL,
                  year            TEXT NOT NULL,
                  genre           TEXT,
                  director        TEXT
                  )",
                 &[])
        .unwrap();

    conn.execute("CREATE TABLE IF NOT EXISTS actors (
                  id              INTEGER PRIMARY KEY,
                  name            TEXT NOT NULL
                  )",
                 &[])
        .unwrap();

    conn.execute("CREATE TABLE IF NOT EXISTS rankings (
                  id              INTEGER PRIMARY KEY,
                  movie_id        INTEGER,
                  score           TEXT NOT NULL,
                  number          INTEGER NOT NULL,
                  FOREIGN KEY(movie_id) REFERENCES movies(id)
                  )",
                 &[])
        .unwrap();

    conn.execute("CREATE TABLE IF NOT EXISTS crew (
                  actor_id        INTEGER,
                  movie_id        INTEGER,
                  FOREIGN KEY(movie_id) REFERENCES movies(id),
                  FOREIGN KEY(actor_id) REFERENCES actors(id)
                  )",
                 &[])
        .unwrap();
}

pub fn import_movie(title: &str, year: &str) {
    let conn = get_connection();

    conn.execute(&format!("INSERT INTO movies (name, year) VALUES ('{}', '{}')",
                          title,
                          year),
                 &[])
        .unwrap();
}
<commit_msg>implemented add_rating and add_genres<commit_after>use rusqlite::Connection;
use std::env;
use std::fs::create_dir_all;

pub fn db_exists() -> bool {
    let tmp = env::home_dir();
    let mut path_buf = tmp.unwrap();
    path_buf.push("Film-O-Mat");
    path_buf.push("database");
    path_buf.set_extension("db");
    path_buf.as_path().exists()
}

fn get_connection() -> Connection {
    let tmp = env::home_dir();
    let mut path_buf = tmp.unwrap();
    path_buf.push("Film-O-Mat");
    path_buf.push("database");
    path_buf.set_extension("db");

    let conn = Connection::open(path_buf).unwrap();
    conn
}

pub fn create_database() {
    let conn = get_connection();

    conn.execute("CREATE TABLE IF NOT EXISTS movies (
                  id              INTEGER PRIMARY KEY,
                  title            TEXT NOT NULL,
                  year            TEXT NOT NULL,
                  genre           TEXT,
                  director        TEXT
                  )",
                 &[])
        .unwrap();

    conn.execute("CREATE TABLE IF NOT EXISTS actors (
                  id              INTEGER PRIMARY KEY,
                  name            TEXT NOT NULL
                  )",
                 &[])
        .unwrap();

    conn.execute("CREATE TABLE IF NOT EXISTS rankings (
                  id              INTEGER PRIMARY KEY,
                  movie_id        INTEGER,
                  score           TEXT NOT NULL,
                  number          INTEGER NOT NULL,
                  FOREIGN KEY(movie_id) REFERENCES movies(id)
                  )",
                 &[])
        .unwrap();

    conn.execute("CREATE TABLE IF NOT EXISTS crew (
                  actor_id        INTEGER,
                  movie_id        INTEGER,
                  FOREIGN KEY(movie_id) REFERENCES movies(id),
                  FOREIGN KEY(actor_id) REFERENCES actors(id)
                  )",
                 &[])
        .unwrap();
}

pub fn import_movie(title: &str, year: &str) {
    let conn = get_connection();

    conn.execute(&format!("INSERT INTO movies (title, year) VALUES ('{}', '{}')",
                          title,
                          year),
                 &[])
        .unwrap();
}

pub fn add_genres(title: &str, year: &str, genre: &str) {
    let conn = get_connection();

    conn.execute(&format!("UPDATE movies SET genre = '{}' WHERE title = '{}' AND year = '{}'",
                          genre,
                          title,
                          year),
                 &[])
        .unwrap();
}

pub fn add_rating(title: &str, year: &str, rank: &str, votes: u64) {
    let conn = get_connection();

    conn.execute(&format!("INSERT INTO rankings (movie_id, score, number) VALUES ((SELECT id \
                           FROM movies WHERE title = '{}' AND year = '{}'), '{}', {})",
                          title,
                          year,
                          rank,
                          votes),
                 &[])
        .unwrap();
}
<|endoftext|>


<commit_before>use decoders::*;
use decoders::basics::*;
  use std::f32::NAN;

pub fn is_x3f(buf: &[u8]) -> bool {
  buf[0..4] == b"FOVb"[..]
}

#[derive(Debug, Clone)]
struct X3fFile {
  dirs: Vec<X3fDirectory>,
}

#[derive(Debug, Clone)]
struct X3fDirectory {
  offset: usize,
  len: usize,
  id: String,
}

impl X3fFile {
  fn new(buf: &Buffer) -> Result<X3fFile, String> {
    let offset = LEu32(&buf.buf, buf.size-4) as usize;
    let data = &buf.buf[offset..];
    let version = LEu32(data, 4);
    if version < 0x00020000 {
      return Err(format!("X3F: Directory version too old {}", version).to_string())
    }
    let entries = LEu32(data, 8) as usize;
    let mut dirs = Vec::new();
    for i in 0..entries {
      let dir = try!(X3fDirectory::new(data, 12+i*12));
      dirs.push(dir);
    }

    Ok(X3fFile{
      dirs: dirs,
    })
  }
}

impl X3fDirectory {
  fn new(buf: &[u8], offset: usize) -> Result<X3fDirectory, String> {
    let data = &buf[offset..];
    let off = LEu32(data, 0) as usize;
    let len = LEu32(data, 4) as usize;
    let name = String::from_utf8_lossy(&data[8..12]).to_string();

    Ok(X3fDirectory {
      offset: off,
      len: len,
      id: name,
    })
  }
}

#[derive(Debug, Clone)]
pub struct X3fDecoder<'a> {
  buffer: &'a [u8],
  rawloader: &'a RawLoader,
  dir: X3fFile,
}

impl<'a> X3fDecoder<'a> {
  pub fn new(buf: &'a Buffer, rawloader: &'a RawLoader) -> X3fDecoder<'a> {
    let dir = X3fFile::new(buf).unwrap();

    X3fDecoder {
      buffer: &buf.buf,
      rawloader: rawloader,
      dir: dir,
    }
  }
}

impl<'a> Decoder for X3fDecoder<'a> {
  fn image(&self) -> Result<RawImage,String> {
    Err("X3F not finished yet".to_string())
  }
}

impl<'a> X3fDecoder<'a> {
  fn get_wb(&self) -> Result<[f32;4], String> {
    Ok([NAN,NAN,NAN,NAN])
  }
}
<commit_msg>X3F: implement the basic decoding skeleton<commit_after>use decoders::*;
use decoders::tiff::*;
use decoders::basics::*;
use std::f32::NAN;

pub fn is_x3f(buf: &[u8]) -> bool {
  buf[0..4] == b"FOVb"[..]
}

#[derive(Debug, Clone)]
struct X3fFile {
  dirs: Vec<X3fDirectory>,
  images: Vec<X3fImage>,
}

#[derive(Debug, Clone)]
struct X3fDirectory {
  offset: usize,
  len: usize,
  id: String,
}

#[derive(Debug, Clone)]
struct X3fImage {
  typ: usize,
  format: usize,
  width: usize,
  height: usize,
  pitch: usize,
  doffset: usize,
}

impl X3fFile {
  fn new(buf: &Buffer) -> Result<X3fFile, String> {
    let offset = LEu32(&buf.buf, buf.size-4) as usize;
    let data = &buf.buf[offset..];
    let version = LEu32(data, 4);
    if version < 0x00020000 {
      return Err(format!("X3F: Directory version too old {}", version).to_string())
    }
    let entries = LEu32(data, 8) as usize;
    let mut dirs = Vec::new();
    let mut images = Vec::new();
    for i in 0..entries {
      let dir = try!(X3fDirectory::new(data, 12+i*12));
      if dir.id == "IMA2" {
        let img = try!(X3fImage::new(&buf.buf, dir.offset));
        println!("Found image with offset {}", img.doffset);
        images.push(img);
      }
      dirs.push(dir);
    }

    Ok(X3fFile{
      dirs: dirs,
      images: images,
    })
  }
}

impl X3fDirectory {
  fn new(buf: &[u8], offset: usize) -> Result<X3fDirectory, String> {
    let data = &buf[offset..];
    let off = LEu32(data, 0) as usize;
    let len = LEu32(data, 4) as usize;
    let name = String::from_utf8_lossy(&data[8..12]).to_string();

    Ok(X3fDirectory {
      offset: off,
      len: len,
      id: name,
    })
  }
}

impl X3fImage {
  fn new(buf: &[u8], offset: usize) -> Result<X3fImage, String> {
    let data = &buf[offset..];
    println!("Decoding image at offset {}", offset);

    Ok(X3fImage {
      typ:     LEu32(data,  8) as usize,
      format:  LEu32(data, 12) as usize,
      width:   LEu32(data, 16) as usize,
      height:  LEu32(data, 20) as usize,
      pitch:   LEu32(data, 24) as usize,
      doffset: offset+28,
    })
  }
}

#[derive(Debug, Clone)]
pub struct X3fDecoder<'a> {
  buffer: &'a [u8],
  rawloader: &'a RawLoader,
  dir: X3fFile,
}

impl<'a> X3fDecoder<'a> {
  pub fn new(buf: &'a Buffer, rawloader: &'a RawLoader) -> X3fDecoder<'a> {
    let dir = X3fFile::new(buf).unwrap();

    X3fDecoder {
      buffer: &buf.buf,
      rawloader: rawloader,
      dir: dir,
    }
  }
}

impl<'a> Decoder for X3fDecoder<'a> {
  fn image(&self) -> Result<RawImage,String> {
    let caminfo = try!(
      self.dir.images.iter().find(|i| i.typ == 2 && i.format == 0x12)
        .ok_or("X3F: Couldn't find camera info".to_string())
    );
    let data = &self.buffer[caminfo.doffset+6..];
    if data[0..4] != b"Exif"[..] {
      return Err("X3F: Couldn't find EXIF info".to_string())
    }
    let tiff = try!(TiffIFD::new_root(self.buffer, caminfo.doffset+12));
    let camera = try!(self.rawloader.check_supported(&tiff));

    let imginfo = try!(
      self.dir.images.iter().find(|i| i.typ == 1 || i.typ == 3)
        .ok_or("X3F: Couldn't find image".to_string())
    );
    let width = imginfo.width;
    let height = imginfo.height;
    let offset = imginfo.doffset;
    let src = &self.buffer[offset..];

    let image = decode_12be(src, width, height);
    ok_image(camera, width, height, try!(self.get_wb()), image)
  }
}

impl<'a> X3fDecoder<'a> {
  fn get_wb(&self) -> Result<[f32;4], String> {
    Ok([NAN,NAN,NAN,NAN])
  }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Gfx-rs Developers.
//
// 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
//
//     http://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.

//! Shader parameter handling.

use std::cell::Cell;
use device::{back, shade};
use device::shade::UniformValue;
use device::{RawBufferHandle, TextureHandle, SamplerHandle};

pub use device::shade::{Stage, CreateShaderError};

/// Helper trait to transform base types into their corresponding uniforms
pub trait ToUniform {
    /// Create a `UniformValue` representing this value.
    fn to_uniform(&self) -> shade::UniformValue;
}

macro_rules! impl_ToUniform(
    ($srcty:ty, $dstty:expr) => (
        impl ToUniform for $srcty {
            fn to_uniform(&self) -> shade::UniformValue {
                $dstty(*self)
            }
        }
    );
);

impl_ToUniform!(i32, UniformValue::I32);
impl_ToUniform!(f32, UniformValue::F32);

impl_ToUniform!([i32; 2], UniformValue::I32Vector2);
impl_ToUniform!([i32; 3], UniformValue::I32Vector3);
impl_ToUniform!([i32; 4], UniformValue::I32Vector4);

impl_ToUniform!([f32; 2], UniformValue::F32Vector2);
impl_ToUniform!([f32; 3], UniformValue::F32Vector3);
impl_ToUniform!([f32; 4], UniformValue::F32Vector4);

impl_ToUniform!([[f32; 2]; 2], UniformValue::F32Matrix2);
impl_ToUniform!([[f32; 3]; 3], UniformValue::F32Matrix3);
impl_ToUniform!([[f32; 4]; 4], UniformValue::F32Matrix4);

/// Variable index of a uniform.
pub type VarUniform = u16;

/// Variable index of a uniform block.
pub type VarBlock = u8;

/// Variable index of a texture.
pub type VarTexture = u8;

/// A texture parameter: consists of a texture handle with an optional sampler.
pub type TextureParam = (TextureHandle<back::GlResources>, Option<SamplerHandle<back::GlResources>>);

/// A borrowed mutable storage for shader parameter values.
// Not sure if it's the best data structure to represent it.
pub struct ParamValues<'a> {
    /// uniform values to be provided
    pub uniforms: &'a mut Vec<UniformValue>,
    /// uniform buffers to be provided
    pub blocks  : &'a mut Vec<RawBufferHandle<back::GlResources>>,
    /// textures to be provided
    pub textures: &'a mut Vec<TextureParam>,
}

/// An error type on either the parameter storage or the program side
#[derive(Clone, PartialEq, Debug)]
pub enum ParameterError {
    /// Internal error
    ParameterGeneralMismatch,
    /// Shader requested a uniform that the parameters do not have
    MissingUniform(String),
    /// Shader requested a block that the parameters do not have
    MissingBlock(String),
    /// Shader requested a texture that the parameters do not have
    MissingTexture(String),
}

/// Abstracts the shader parameter structure, generated by the `shader_param` attribute
pub trait ShaderParam {
    /// A helper structure to contain variable indices inside the shader
    type Link;
    /// Create a new link to be used with a given program
    fn create_link(Option<&Self>, &shade::ProgramInfo) -> Result<Self::Link, ParameterError>;
    /// Get all the contained parameter values, using a given link
    fn fill_params(&self, &Self::Link, ParamValues);
}

impl ShaderParam for () {
    type Link = ();

    fn create_link(_: Option<&()>, info: &shade::ProgramInfo) -> Result<(), ParameterError> {
        match info.uniforms[..].first() {
            Some(u) => return Err(ParameterError::MissingUniform(u.name.clone())),
            None => (),
        }
        match info.blocks[..].first() {
            Some(b) => return Err(ParameterError::MissingBlock(b.name.clone())),
            None => (),
        }
        match info.textures[..].first() {
            Some(t) => return Err(ParameterError::MissingTexture(t.name.clone())),
            None => (),
        }
        Ok(())
    }

    fn fill_params(&self, _: &(), _: ParamValues) {
        //empty
    }
}

/// A named cell containing arbitrary value
pub struct NamedCell<T> {
    /// Name
    pub name: String,
    /// Value
    pub value: Cell<T>,
}

/// A dictionary of parameters, meant to be shared between different programs
pub struct ParamDictionary {
    /// Uniform dictionary
    pub uniforms: Vec<NamedCell<shade::UniformValue>>,
    /// Block dictionary
    pub blocks: Vec<NamedCell<RawBufferHandle<back::GlResources>>>,
    /// Texture dictionary
    pub textures: Vec<NamedCell<TextureParam>>,
}

/// Redirects program input to the relevant ParamDictionary cell
pub struct ParamDictionaryLink {
    uniforms: Vec<usize>,
    blocks: Vec<usize>,
    textures: Vec<usize>,
}

impl ShaderParam for ParamDictionary {
    type Link = ParamDictionaryLink;

    fn create_link(this: Option<&ParamDictionary>, info: &shade::ProgramInfo)
                   -> Result<ParamDictionaryLink, ParameterError> {
        let this = match this {
            Some(d) => d,
            None => return Err(ParameterError::ParameterGeneralMismatch),
        };
        //TODO: proper error checks
        Ok(ParamDictionaryLink {
            uniforms: info.uniforms.iter().map(|var|
                this.uniforms.iter().position(|c| c.name == var.name).unwrap()
            ).collect(),
            blocks: info.blocks.iter().map(|var|
                this.blocks  .iter().position(|c| c.name == var.name).unwrap()
            ).collect(),
            textures: info.textures.iter().map(|var|
                this.textures.iter().position(|c| c.name == var.name).unwrap()
            ).collect(),
        })
    }

    fn fill_params(&self, link: &ParamDictionaryLink, params: ParamValues) {
        for &id in link.uniforms.iter() {
            params.uniforms.push(self.uniforms[id].value.get());
        }
        for &id in link.blocks.iter() {
            params.blocks.push(self.blocks[id].value.get());
        }
        for &id in link.textures.iter() {
            params.textures.push(self.textures[id].value.get());
        }
    }
}
<commit_msg>Add Resources parameter to ParamDictionary<commit_after>// Copyright 2014 The Gfx-rs Developers.
//
// 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
//
//     http://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.

//! Shader parameter handling.

use std::cell::Cell;
use device::{back, shade};
use device::shade::UniformValue;
use device::{Resources, RawBufferHandle, TextureHandle, SamplerHandle};

pub use device::shade::{Stage, CreateShaderError};

/// Helper trait to transform base types into their corresponding uniforms
pub trait ToUniform {
    /// Create a `UniformValue` representing this value.
    fn to_uniform(&self) -> shade::UniformValue;
}

macro_rules! impl_ToUniform(
    ($srcty:ty, $dstty:expr) => (
        impl ToUniform for $srcty {
            fn to_uniform(&self) -> shade::UniformValue {
                $dstty(*self)
            }
        }
    );
);

impl_ToUniform!(i32, UniformValue::I32);
impl_ToUniform!(f32, UniformValue::F32);

impl_ToUniform!([i32; 2], UniformValue::I32Vector2);
impl_ToUniform!([i32; 3], UniformValue::I32Vector3);
impl_ToUniform!([i32; 4], UniformValue::I32Vector4);

impl_ToUniform!([f32; 2], UniformValue::F32Vector2);
impl_ToUniform!([f32; 3], UniformValue::F32Vector3);
impl_ToUniform!([f32; 4], UniformValue::F32Vector4);

impl_ToUniform!([[f32; 2]; 2], UniformValue::F32Matrix2);
impl_ToUniform!([[f32; 3]; 3], UniformValue::F32Matrix3);
impl_ToUniform!([[f32; 4]; 4], UniformValue::F32Matrix4);

/// Variable index of a uniform.
pub type VarUniform = u16;

/// Variable index of a uniform block.
pub type VarBlock = u8;

/// Variable index of a texture.
pub type VarTexture = u8;

/// A texture parameter: consists of a texture handle with an optional sampler.
pub type TextureParam = (TextureHandle<back::GlResources>, Option<SamplerHandle<back::GlResources>>);

/// A borrowed mutable storage for shader parameter values.
// Not sure if it's the best data structure to represent it.
pub struct ParamValues<'a> {
    /// uniform values to be provided
    pub uniforms: &'a mut Vec<UniformValue>,
    /// uniform buffers to be provided
    pub blocks  : &'a mut Vec<RawBufferHandle<back::GlResources>>,
    /// textures to be provided
    pub textures: &'a mut Vec<TextureParam>,
}

/// An error type on either the parameter storage or the program side
#[derive(Clone, PartialEq, Debug)]
pub enum ParameterError {
    /// Internal error
    ParameterGeneralMismatch,
    /// Shader requested a uniform that the parameters do not have
    MissingUniform(String),
    /// Shader requested a block that the parameters do not have
    MissingBlock(String),
    /// Shader requested a texture that the parameters do not have
    MissingTexture(String),
}

/// Abstracts the shader parameter structure, generated by the `shader_param` attribute
pub trait ShaderParam {
    /// A helper structure to contain variable indices inside the shader
    type Link;
    /// Create a new link to be used with a given program
    fn create_link(Option<&Self>, &shade::ProgramInfo) -> Result<Self::Link, ParameterError>;
    /// Get all the contained parameter values, using a given link
    fn fill_params(&self, &Self::Link, ParamValues);
}

impl ShaderParam for () {
    type Link = ();

    fn create_link(_: Option<&()>, info: &shade::ProgramInfo) -> Result<(), ParameterError> {
        match info.uniforms[..].first() {
            Some(u) => return Err(ParameterError::MissingUniform(u.name.clone())),
            None => (),
        }
        match info.blocks[..].first() {
            Some(b) => return Err(ParameterError::MissingBlock(b.name.clone())),
            None => (),
        }
        match info.textures[..].first() {
            Some(t) => return Err(ParameterError::MissingTexture(t.name.clone())),
            None => (),
        }
        Ok(())
    }

    fn fill_params(&self, _: &(), _: ParamValues) {
        //empty
    }
}

/// A named cell containing arbitrary value
pub struct NamedCell<T> {
    /// Name
    pub name: String,
    /// Value
    pub value: Cell<T>,
}

/// A dictionary of parameters, meant to be shared between different programs
pub struct ParamDictionary<R: Resources> {
    /// Uniform dictionary
    pub uniforms: Vec<NamedCell<shade::UniformValue>>,
    /// Block dictionary
    pub blocks: Vec<NamedCell<RawBufferHandle<R>>>,
    /// Texture dictionary
    pub textures: Vec<NamedCell<TextureParam>>,
}

/// Redirects program input to the relevant ParamDictionary cell
pub struct ParamDictionaryLink {
    uniforms: Vec<usize>,
    blocks: Vec<usize>,
    textures: Vec<usize>,
}

impl ShaderParam for ParamDictionary<back::GlResources> {
    type Link = ParamDictionaryLink;

    fn create_link(this: Option<&ParamDictionary<back::GlResources>>, info: &shade::ProgramInfo)
                   -> Result<ParamDictionaryLink, ParameterError> {
        let this = match this {
            Some(d) => d,
            None => return Err(ParameterError::ParameterGeneralMismatch),
        };
        //TODO: proper error checks
        Ok(ParamDictionaryLink {
            uniforms: info.uniforms.iter().map(|var|
                this.uniforms.iter().position(|c| c.name == var.name).unwrap()
            ).collect(),
            blocks: info.blocks.iter().map(|var|
                this.blocks  .iter().position(|c| c.name == var.name).unwrap()
            ).collect(),
            textures: info.textures.iter().map(|var|
                this.textures.iter().position(|c| c.name == var.name).unwrap()
            ).collect(),
        })
    }

    fn fill_params(&self, link: &ParamDictionaryLink, params: ParamValues) {
        for &id in link.uniforms.iter() {
            params.uniforms.push(self.uniforms[id].value.get());
        }
        for &id in link.blocks.iter() {
            params.blocks.push(self.blocks[id].value.get());
        }
        for &id in link.textures.iter() {
            params.textures.push(self.textures[id].value.get());
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 Pierre Talbot (IRCAM)

// 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

//     http://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.

#![crate_name = "testpeg"]
#![experimental]
#![crate_type = "bin"]

#![feature(phase,globs)]

#[phase(plugin, link)]
extern crate peg;
extern crate term;

use std::os;
use std::io::File;
use std::io::fs;
use std::io;

use peg::Parser;

use term::*;

pub mod ntcc;

enum ExpectedResult {
  Match,
  Error
}

struct TestDisplay
{
  terminal: Box<Terminal<WriterWrapper>>,
  code_snippet_len: uint
}

impl TestDisplay
{
  pub fn new(code_snippet_len: uint) -> TestDisplay
  {
    TestDisplay{
      terminal: term::stdout().unwrap(),
      code_snippet_len: code_snippet_len
    }
  }

  pub fn info(&mut self, msg: &String)
  {
    self.write_line(term::color::CYAN, "\n[ info ] ", msg);
  }

  pub fn error(&mut self, msg: &String)
  {
    self.write_line(term::color::RED, "  [ error ] ", msg);
  }

  pub fn path(&mut self, path: &Path)
  {
    self.write_line(term::color::CYAN, "  [ path ] ",
      &format!("{}", path.display()));
  }

  pub fn failure<'a>(&mut self, path: &Path, expectation: ExpectedResult,
    result: &Result<Option<&'a str>, String>)
  {
    let test_name = self.filestem(path);
    self.write_line(term::color::RED, "[ failed ] ", &test_name);
    self.path(path);
    self.expected(expectation);
    self.wrong_result(result);
  }

  fn expected(&mut self, expectation: ExpectedResult)
  {
    let msg = match expectation {
      Match => "Fully match",
      Error => "Error"
    };
    self.write_line(term::color::CYAN, "  [ expected ] ", &format!("{}", msg))
  }

  fn wrong_result<'a>(&mut self, result: &Result<Option<&'a str>, String>)
  {
    let msg = match result {
      &Ok(Some(input)) => format!("Partial match, stopped at `{}`.", self.code_snippet(input)),
      &Ok(None) => format!("Fully matched."),
      &Err(ref msg) => msg.clone()
    };
    self.error(&msg)
  }

  fn code_snippet<'a>(&self, code: &'a str) -> &'a str
  {
    code.slice_to(std::cmp::min(code.len()-1, self.code_snippet_len))
  }

  pub fn success(&mut self, path: &Path)
  {
    let test_name = self.filestem(path);
    self.write_line(term::color::GREEN, "[ passed ] ", &test_name);
  }

  fn filestem(&self, path: &Path) -> String
  {
    format!("{}", path.filestem_str().unwrap())
  }

  pub fn warn(&mut self, msg: &String)
  {
    self.write_line(term::color::MAGENTA, "  [ warning ] ", msg);
  }

  pub fn fs_error(&mut self, msg: &str, path: &Path, io_err: &io::IoError)
  {
    self.system_error(&format!("{}", msg));
    self.path(path);
    self.error(&format!("{}", io_err));
  }

  pub fn system_error(&mut self, msg: &String)
  {
    self.write_line(term::color::RED, "[ system error ] ", msg);
  }

  fn write_line(&mut self, color: color::Color, header: &str, msg: &String)
  {
    self.write_header(color, header);
    self.write_msg(msg.as_slice());
    self.write_msg("\n");
  }

  fn write_header(&mut self, color: color::Color, header: &str)
  {
    self.terminal.fg(color).unwrap();
    self.write_msg(header);
    self.terminal.reset().unwrap();
  }

  fn write_msg(&mut self, msg: &str)
  {
    (write!(self.terminal, "{}", msg)).unwrap();
  }
}

struct GrammarInfo
{
  name: String,
  parser: Box<Parser>
}

struct Test<'a>
{
  info: &'a GrammarInfo,
  display: &'a mut TestDisplay,
}

impl<'a> Test<'a>
{
  fn test_directory(&mut self, start_msg: &String, directory: &Path, expectation: ExpectedResult)
  {
    self.display.info(start_msg);

    match fs::readdir(directory) {
      Ok(dir_entries) => {
        for entry in dir_entries.iter() {
          if entry.is_file() {
            self.test_file(entry, expectation);
          } else {
            self.display.warn(&format!("Entry ignored because it's not a file."));
            self.display.path(entry);
          }
        }
      }
      Err(ref io_err) => {
        self.display.fs_error("Can't read directory.", directory, io_err);
      }
    }
  }

  fn test_file(&mut self, filepath: &Path, expectation: ExpectedResult)
  {
    let mut file = File::open(filepath);
    match file {
      Ok(ref mut file) => {
        let contents = file.read_to_end();
        match contents {
          Ok(contents) => {
            let utf8_contents = std::str::from_utf8(contents.as_slice());
            self.test_input(utf8_contents.unwrap(), expectation, filepath);
          },
          Err(ref io_err) => {
            self.display.fs_error("Can't read file.", filepath, io_err);
          }
        }
      },
      Err(ref io_err) => {
        self.display.fs_error("Can't open file.", filepath, io_err);
      }
    }
  }

  fn test_input(&mut self, input: &str, expectation: ExpectedResult, test_path: &Path)
  {
    match (expectation, self.info.parser.parse(input)) {
      (Match, Ok(None))
    | (Error, Ok(Some(_)))
    | (Error, Err(_)) => self.display.success(test_path),
      (_, ref res) => {
        self.display.failure(test_path, expectation, res);
      }
    }
  }
}

struct TestEngine
{
  test_path : Path,
  grammars : Vec<GrammarInfo>,
  display : TestDisplay
}

impl TestEngine
{
  fn new(test_path: Path) -> TestEngine
  {
    if !test_path.is_dir() {
      fail!(format!("`{}` is not a valid grammar directory.", test_path.display()));
    }
    TestEngine{
      test_path: test_path.clone(),
      grammars : Vec::new(),
      display : TestDisplay::new(20)
    }
  }

  fn register(&mut self, name: &str, parser: Box<Parser>)
  {
    self.grammars.push(GrammarInfo{name: String::from_str(name), parser: parser});
  }

  fn run(&mut self)
  {
    self.display.info(&format!("Start PEG library tests suite."));
    for grammar in self.grammars.iter() {
      let grammar_path = self.test_path.join(Path::new(grammar.name.clone()));
      self.display.info(&format!("Start tests of grammar `{}`", grammar.name));
      self.display.path(&grammar_path);
      let mut test = Test{
        info: grammar,
        display: &mut self.display
      };
      test.test_directory(&format!("Run and Pass tests of `{}`", grammar.name),
        &grammar_path.join(Path::new("run-pass")), Match);
      test.test_directory(&format!("Run and Fail tests of `{}`", grammar.name),
        &grammar_path.join(Path::new("run-fail")), Error);
    }
  }
}

fn main()
{
  let args = os::args();
  if args.len() != 2 {
    fail!(format!("usage: {} <data-dir>", args.as_slice()[0]));
  }
  let data_path = Path::new(args.as_slice()[1].clone());
  if !data_path.is_dir() {
    fail!(format!("`{}` is not a valid data directory.", data_path.display()));
  }
  let mut test_path = data_path.clone();
  test_path.push("test");
  let mut test_engine = TestEngine::new(test_path);
  test_engine.register("ntcc", box ntcc::ntcc::Parser::new());
  test_engine.run();
}
<commit_msg>[Tests] Add statistics and change title layout.<commit_after>// Copyright 2014 Pierre Talbot (IRCAM)

// 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

//     http://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.

#![crate_name = "testpeg"]
#![experimental]
#![crate_type = "bin"]

#![feature(phase,globs)]

#[phase(plugin, link)]
extern crate peg;
extern crate term;

use std::os;
use std::io::File;
use std::io::fs;
use std::io;

use peg::Parser;

use term::*;

pub mod ntcc;

enum ExpectedResult {
  Match,
  Error
}

struct TestDisplay
{
  terminal: Box<Terminal<WriterWrapper>>,
  code_snippet_len: uint,
  num_success: uint,
  num_failure: uint,
  num_system_failure: uint
}

impl TestDisplay
{
  pub fn new(code_snippet_len: uint) -> TestDisplay
  {
    TestDisplay{
      terminal: term::stdout().unwrap(),
      code_snippet_len: code_snippet_len,
      num_success: 0,
      num_failure: 0,
      num_system_failure: 0
    }
  }

  pub fn title(&mut self, msg: &str)
  {
    self.write_header(term::color::CYAN, msg);
    self.write_msg("\n\n");
  }

  pub fn info(&mut self, msg: &String)
  {
    self.write_line(term::color::CYAN, "\n[ info ] ", msg);
  }

  pub fn error(&mut self, msg: &String)
  {
    self.write_line(term::color::RED, "  [ error ] ", msg);
  }

  pub fn path(&mut self, path: &Path)
  {
    self.write_line(term::color::CYAN, "  [ path ] ",
      &format!("{}", path.display()));
  }

  pub fn stats(&mut self)
  {
    let system_failure_plural = if self.num_system_failure > 1 { "s" } else { "" };
    let msg = format!("{} passed, {} failed, {} system failure{}.",
        self.num_success, self.num_failure, self.num_system_failure,
        system_failure_plural);
    self.write_line(term::color::BLUE, "\n\n[ stats ] ", &msg);
  }

  pub fn failure<'a>(&mut self, path: &Path, expectation: ExpectedResult,
    result: &Result<Option<&'a str>, String>)
  {
    self.num_failure += 1;
    let test_name = self.filestem(path);
    self.write_line(term::color::RED, "[ failed ] ", &test_name);
    self.path(path);
    self.expected(expectation);
    self.wrong_result(result);
  }

  fn expected(&mut self, expectation: ExpectedResult)
  {
    let msg = match expectation {
      Match => "Fully match",
      Error => "Error"
    };
    self.write_line(term::color::CYAN, "  [ expected ] ", &format!("{}", msg))
  }

  fn wrong_result<'a>(&mut self, result: &Result<Option<&'a str>, String>)
  {
    let msg = match result {
      &Ok(Some(input)) => format!("Partial match, stopped at `{}`.", self.code_snippet(input)),
      &Ok(None) => format!("Fully matched."),
      &Err(ref msg) => msg.clone()
    };
    self.error(&msg)
  }

  fn code_snippet<'a>(&self, code: &'a str) -> &'a str
  {
    code.slice_to(std::cmp::min(code.len()-1, self.code_snippet_len))
  }

  pub fn success(&mut self, path: &Path)
  {
    self.num_success += 1;
    let test_name = self.filestem(path);
    self.write_line(term::color::GREEN, "[ passed ] ", &test_name);
  }

  fn filestem(&self, path: &Path) -> String
  {
    format!("{}", path.filestem_str().unwrap())
  }

  pub fn warn(&mut self, msg: &String)
  {
    self.write_line(term::color::YELLOW, "  [ warning ] ", msg);
  }

  pub fn fs_error(&mut self, msg: &str, path: &Path, io_err: &io::IoError)
  {
    self.system_failure(&format!("{}", msg));
    self.path(path);
    self.error(&format!("{}", io_err));
  }

  pub fn system_failure(&mut self, msg: &String)
  {
    self.num_system_failure += 1;
    self.write_line(term::color::RED, "[ system error ] ", msg);
  }

  fn write_line(&mut self, color: color::Color, header: &str, msg: &String)
  {
    self.write_header(color, header);
    self.write_msg(msg.as_slice());
    self.write_msg("\n");
  }

  fn write_header(&mut self, color: color::Color, header: &str)
  {
    self.terminal.fg(color).unwrap();
    self.write_msg(header);
    self.terminal.reset().unwrap();
  }

  fn write_msg(&mut self, msg: &str)
  {
    (write!(self.terminal, "{}", msg)).unwrap();
  }
}

struct GrammarInfo
{
  name: String,
  parser: Box<Parser>
}

struct Test<'a>
{
  info: &'a GrammarInfo,
  display: &'a mut TestDisplay,
}

impl<'a> Test<'a>
{
  fn test_directory(&mut self, start_msg: &String, directory: &Path, expectation: ExpectedResult)
  {
    self.display.info(start_msg);

    match fs::readdir(directory) {
      Ok(dir_entries) => {
        for entry in dir_entries.iter() {
          if entry.is_file() {
            self.test_file(entry, expectation);
          } else {
            self.display.warn(&format!("Entry ignored because it's not a file."));
            self.display.path(entry);
          }
        }
      }
      Err(ref io_err) => {
        self.display.fs_error("Can't read directory.", directory, io_err);
      }
    }
  }

  fn test_file(&mut self, filepath: &Path, expectation: ExpectedResult)
  {
    let mut file = File::open(filepath);
    match file {
      Ok(ref mut file) => {
        let contents = file.read_to_end();
        match contents {
          Ok(contents) => {
            let utf8_contents = std::str::from_utf8(contents.as_slice());
            self.test_input(utf8_contents.unwrap(), expectation, filepath);
          },
          Err(ref io_err) => {
            self.display.fs_error("Can't read file.", filepath, io_err);
          }
        }
      },
      Err(ref io_err) => {
        self.display.fs_error("Can't open file.", filepath, io_err);
      }
    }
  }

  fn test_input(&mut self, input: &str, expectation: ExpectedResult, test_path: &Path)
  {
    match (expectation, self.info.parser.parse(input)) {
      (Match, Ok(None))
    | (Error, Ok(Some(_)))
    | (Error, Err(_)) => self.display.success(test_path),
      (_, ref res) => {
        self.display.failure(test_path, expectation, res);
      }
    }
  }
}

struct TestEngine
{
  test_path : Path,
  grammars : Vec<GrammarInfo>,
  display : TestDisplay
}

impl TestEngine
{
  fn new(test_path: Path) -> TestEngine
  {
    if !test_path.is_dir() {
      fail!(format!("`{}` is not a valid grammar directory.", test_path.display()));
    }
    TestEngine{
      test_path: test_path.clone(),
      grammars : Vec::new(),
      display : TestDisplay::new(20)
    }
  }

  fn register(&mut self, name: &str, parser: Box<Parser>)
  {
    self.grammars.push(GrammarInfo{name: String::from_str(name), parser: parser});
  }

  fn run(&mut self)
  {
    self.display.title("    PEG library tests suite");
    for grammar in self.grammars.iter() {
      let grammar_path = self.test_path.join(Path::new(grammar.name.clone()));
      self.display.info(&format!("Start tests of the grammar `{}`", grammar.name));
      self.display.path(&grammar_path);
      let mut test = Test{
        info: grammar,
        display: &mut self.display
      };
      test.test_directory(&format!("Run and Pass tests of `{}`", grammar.name),
        &grammar_path.join(Path::new("run-pass")), Match);
      test.test_directory(&format!("Run and Fail tests of `{}`", grammar.name),
        &grammar_path.join(Path::new("run-fail")), Error);
    }
    self.display.stats();
  }
}

fn main()
{
  let args = os::args();
  if args.len() != 2 {
    fail!(format!("usage: {} <data-dir>", args.as_slice()[0]));
  }
  let data_path = Path::new(args.as_slice()[1].clone());
  if !data_path.is_dir() {
    fail!(format!("`{}` is not a valid data directory.", data_path.display()));
  }
  let mut test_path = data_path.clone();
  test_path.push("test");
  let mut test_engine = TestEngine::new(test_path);
  test_engine.register("ntcc", box ntcc::ntcc::Parser::new());
  test_engine.run();
}
<|endoftext|>


<commit_before>//! Wrapper for wlr_cursor

use std::{mem, ptr, slice};
use std::cell::RefCell;
use std::rc::Rc;
use types::input_device::InputDevice;
use types::output::OutputLayout;
use utils::safe_as_cstring;

use wlroots_sys::{wlr_cursor, wlr_cursor_attach_output_layout, wlr_cursor_create,
                  wlr_cursor_destroy, wlr_cursor_move, wlr_cursor_set_image, wlr_cursor_warp,
                  wlr_xcursor, wlr_xcursor_image, wlr_xcursor_theme, wlr_xcursor_theme_get_cursor,
                  wlr_xcursor_theme_load};

#[derive(Debug)]
pub struct Cursor {
    cursor: *mut wlr_cursor,
    xcursor: Option<XCursor>,
    layout: Option<Rc<RefCell<OutputLayout>>>
}

#[derive(Debug)]
pub struct XCursorTheme {
    theme: *mut wlr_xcursor_theme
}

#[derive(Debug)]
pub struct XCursor {
    xcursor: *mut wlr_xcursor
}

impl Cursor {
    pub fn new() -> Option<Cursor> {
        unsafe {
            let cursor = wlr_cursor_create();
            if cursor.is_null() {
                None
            } else {
                Some(Cursor { cursor: cursor,
                              xcursor: None,
                              layout: None })
            }
        }
    }

    pub fn coords(&self) -> (f64, f64) {
        unsafe { ((*self.cursor).x, (*self.cursor).y) }
    }

    pub fn warp(&mut self, dev: Option<InputDevice>, x: f64, y: f64) -> bool {
        unsafe {
            let dev_ptr = dev.map(|dev| dev.to_ptr()).unwrap_or(ptr::null_mut());
            wlr_cursor_warp(self.cursor, dev_ptr, x, y)
        }
    }

    pub fn xcursor(&self) -> Option<&XCursor> {
        self.xcursor.as_ref()
    }

    /// Attaches an output layout to the cursor.
    /// The layout specifies the boundaries of the cursor, i.e where it can go.
    pub fn attach_output_layout(&mut self, layout: Rc<RefCell<OutputLayout>>) {
        unsafe {
            // NOTE Rationale for why the pointer isn't leaked from the refcell:
            // * A pointer is not stored to the layout, the internal state is just updated.
            wlr_cursor_attach_output_layout(self.cursor, layout.borrow_mut().to_ptr());
            self.layout = Some(layout);
        }
    }

    pub fn move_to(&mut self, dev: &InputDevice, delta_x: f64, delta_y: f64) {
        unsafe { wlr_cursor_move(self.cursor, dev.to_ptr(), delta_x, delta_y) }
    }

    pub fn output_layout(&self) -> &Option<Rc<RefCell<OutputLayout>>> {
        &self.layout
    }

    /// Sets the image of the cursor to the image from the XCursor.
    pub fn set_cursor_image(&mut self, image: &XCursorImage) {
        unsafe {
            let scale = 0.0;
            // NOTE Rationale for why lifetime isn't attached:
            //
            // wlr_cursor_set_image uses gl calls internally, which copies
            // the buffer and so it doesn't matter what happens to the
            // xcursor image after this call.
            wlr_cursor_set_image(self.cursor,
                                 image.buffer.as_ptr(),
                                 image.width as i32,
                                 image.width,
                                 image.height,
                                 image.hotspot_x as i32,
                                 image.hotspot_y as i32,
                                 scale)
        }
    }
}

impl Drop for Cursor {
    fn drop(&mut self) {
        unsafe { wlr_cursor_destroy(self.cursor) }
    }
}

impl XCursorTheme {
    /// If no name is given, defaults to "default".
    pub fn load_theme(name: Option<String>, size: i32) -> Option<Self> {
        unsafe {
            let name_str = name.map(safe_as_cstring);
            let name_ptr = name_str.map(|s| s.as_ptr()).unwrap_or(ptr::null_mut());
            let theme = wlr_xcursor_theme_load(name_ptr, size);
            if theme.is_null() {
                None
            } else {
                Some(XCursorTheme { theme })
            }
        }
    }

    pub fn get_cursor(&self, name: String) -> Option<XCursor> {
        let name_str = safe_as_cstring(name);
        let xcursor =
            unsafe { wlr_xcursor_theme_get_cursor(self.theme, name_str.as_ptr()) };
        if xcursor.is_null() {
            None
        } else {
            Some(XCursor { xcursor })
        }
    }

    pub fn into_raw(self) -> *mut wlr_xcursor_theme {
        self.theme
    }
}

impl XCursor {
    pub unsafe fn as_raw(&mut self) -> *mut wlr_xcursor {
        self.xcursor
    }

    pub fn images<'cursor>(&'cursor self) -> Vec<XCursorImage<'cursor>> {
        unsafe {
            let image_ptr = (*self.xcursor).images as *const *const wlr_xcursor_image;
            let length = (*self.xcursor).image_count;
            let cursors_slice: &'cursor [*const wlr_xcursor_image] =
                slice::from_raw_parts::<'cursor, *const wlr_xcursor_image>(image_ptr,
                                                                           length as usize);
            let mut result = Vec::with_capacity(cursors_slice.len());
            for cursor in cursors_slice {
                result.push(XCursorImage {
                    width: (**cursor).width,
                    height: (**cursor).height,
                    hotspot_x: (**cursor).hotspot_x,
                    hotspot_y: (**cursor).hotspot_y,
                    delay: (**cursor).delay,
                    buffer: slice::from_raw_parts::<'cursor, u8>(
                        (**cursor).buffer as *const u8,
                        (**cursor).width as usize * (**cursor).height as usize
                            * mem::size_of::<u32>()
                    )
                })
            }
            result
        }
    }
}

#[derive(Debug)]
pub struct XCursorImage<'cursor> {
    pub width: u32,
    pub height: u32,
    pub hotspot_x: u32,
    pub hotspot_y: u32,
    pub delay: u32,
    pub buffer: &'cursor [u8]
}
<commit_msg>Remove optional xcursor in cursor<commit_after>//! Wrapper for wlr_cursor

use std::{mem, ptr, slice};
use std::cell::RefCell;
use std::rc::Rc;
use types::input_device::InputDevice;
use types::output::OutputLayout;
use utils::safe_as_cstring;

use wlroots_sys::{wlr_cursor, wlr_cursor_attach_output_layout, wlr_cursor_create,
                  wlr_cursor_destroy, wlr_cursor_move, wlr_cursor_set_image, wlr_cursor_warp,
                  wlr_xcursor, wlr_xcursor_image, wlr_xcursor_theme, wlr_xcursor_theme_get_cursor,
                  wlr_xcursor_theme_load};

#[derive(Debug)]
pub struct Cursor {
    cursor: *mut wlr_cursor,
    layout: Option<Rc<RefCell<OutputLayout>>>
}

#[derive(Debug)]
pub struct XCursorTheme {
    theme: *mut wlr_xcursor_theme
}

#[derive(Debug)]
pub struct XCursor {
    xcursor: *mut wlr_xcursor
}

impl Cursor {
    pub fn new() -> Option<Cursor> {
        unsafe {
            let cursor = wlr_cursor_create();
            if cursor.is_null() {
                None
            } else {
                Some(Cursor { cursor: cursor,
                              layout: None })
            }
        }
    }

    pub fn coords(&self) -> (f64, f64) {
        unsafe { ((*self.cursor).x, (*self.cursor).y) }
    }

    pub fn warp(&mut self, dev: Option<InputDevice>, x: f64, y: f64) -> bool {
        unsafe {
            let dev_ptr = dev.map(|dev| dev.to_ptr()).unwrap_or(ptr::null_mut());
            wlr_cursor_warp(self.cursor, dev_ptr, x, y)
        }
    }

    /// Attaches an output layout to the cursor.
    /// The layout specifies the boundaries of the cursor, i.e where it can go.
    pub fn attach_output_layout(&mut self, layout: Rc<RefCell<OutputLayout>>) {
        unsafe {
            // NOTE Rationale for why the pointer isn't leaked from the refcell:
            // * A pointer is not stored to the layout, the internal state is just updated.
            wlr_cursor_attach_output_layout(self.cursor, layout.borrow_mut().to_ptr());
            self.layout = Some(layout);
        }
    }

    pub fn move_to(&mut self, dev: &InputDevice, delta_x: f64, delta_y: f64) {
        unsafe { wlr_cursor_move(self.cursor, dev.to_ptr(), delta_x, delta_y) }
    }

    pub fn output_layout(&self) -> &Option<Rc<RefCell<OutputLayout>>> {
        &self.layout
    }

    /// Sets the image of the cursor to the image from the XCursor.
    pub fn set_cursor_image(&mut self, image: &XCursorImage) {
        unsafe {
            let scale = 0.0;
            // NOTE Rationale for why lifetime isn't attached:
            //
            // wlr_cursor_set_image uses gl calls internally, which copies
            // the buffer and so it doesn't matter what happens to the
            // xcursor image after this call.
            wlr_cursor_set_image(self.cursor,
                                 image.buffer.as_ptr(),
                                 image.width as i32,
                                 image.width,
                                 image.height,
                                 image.hotspot_x as i32,
                                 image.hotspot_y as i32,
                                 scale)
        }
    }
}

impl Drop for Cursor {
    fn drop(&mut self) {
        unsafe { wlr_cursor_destroy(self.cursor) }
    }
}

impl XCursorTheme {
    /// If no name is given, defaults to "default".
    pub fn load_theme(name: Option<String>, size: i32) -> Option<Self> {
        unsafe {
            let name_str = name.map(safe_as_cstring);
            let name_ptr = name_str.map(|s| s.as_ptr()).unwrap_or(ptr::null_mut());
            let theme = wlr_xcursor_theme_load(name_ptr, size);
            if theme.is_null() {
                None
            } else {
                Some(XCursorTheme { theme })
            }
        }
    }

    pub fn get_cursor(&self, name: String) -> Option<XCursor> {
        let name_str = safe_as_cstring(name);
        let xcursor =
            unsafe { wlr_xcursor_theme_get_cursor(self.theme, name_str.as_ptr()) };
        if xcursor.is_null() {
            None
        } else {
            Some(XCursor { xcursor })
        }
    }

    pub fn into_raw(self) -> *mut wlr_xcursor_theme {
        self.theme
    }
}

impl XCursor {
    pub unsafe fn as_raw(&mut self) -> *mut wlr_xcursor {
        self.xcursor
    }

    pub fn images<'cursor>(&'cursor self) -> Vec<XCursorImage<'cursor>> {
        unsafe {
            let image_ptr = (*self.xcursor).images as *const *const wlr_xcursor_image;
            let length = (*self.xcursor).image_count;
            let cursors_slice: &'cursor [*const wlr_xcursor_image] =
                slice::from_raw_parts::<'cursor, *const wlr_xcursor_image>(image_ptr,
                                                                           length as usize);
            let mut result = Vec::with_capacity(cursors_slice.len());
            for cursor in cursors_slice {
                result.push(XCursorImage {
                    width: (**cursor).width,
                    height: (**cursor).height,
                    hotspot_x: (**cursor).hotspot_x,
                    hotspot_y: (**cursor).hotspot_y,
                    delay: (**cursor).delay,
                    buffer: slice::from_raw_parts::<'cursor, u8>(
                        (**cursor).buffer as *const u8,
                        (**cursor).width as usize * (**cursor).height as usize
                            * mem::size_of::<u32>()
                    )
                })
            }
            result
        }
    }
}

#[derive(Debug)]
pub struct XCursorImage<'cursor> {
    pub width: u32,
    pub height: u32,
    pub hotspot_x: u32,
    pub hotspot_y: u32,
    pub delay: u32,
    pub buffer: &'cursor [u8]
}
<|endoftext|>


<commit_before>use std::collections::hash_map::HashMap;
use std::collections::hash_set::HashSet;
use std::fmt::{Display, Formatter, Error};
use std::string::String;
use std::vec::Vec;

use alloc_box::AllocBox;
use super::binding::UniqueBinding;
use super::js_var::{JsVar, JsKey, JsType, JsPtrEnum};

#[derive(Clone, Debug)]
pub struct JsObjStruct {
    pub proto: JsProto,
    pub name: String,
    pub dict: HashMap<JsKey, JsVar>,
}

impl JsObjStruct {
    #[allow(unused_variables)]
    pub fn new(proto: JsProto, name: &str, kv_tuples: Vec<(JsKey, JsVar, Option<JsPtrEnum>)>,
               allocator: &mut AllocBox) -> JsObjStruct {
        JsObjStruct {
            proto: None,
            name: String::from(name),
            dict: kv_tuples.into_iter().map(|(k, v, ptr)| {
                if let Some(ptr) = ptr {
                    allocator.alloc(v.unique.clone(), ptr).expect("Unable to allocate!"); // TODO better error handling
                }
                (k, v)
            }).collect()
        }
    }

    pub fn add_key(&mut self, k: JsKey, v: JsVar, ptr: Option<JsPtrEnum>, allocator: &mut AllocBox) {
        println!("{:#?}", self);
        // If the key already exists, potentially condemn its pointer, which is being overwritten.
        if let Some(var) = self.dict.get(&k) {
            println!("VAR");
            match var.t {
                JsType::JsPtr(_) => { println!("CONDEMN"); allocator.condemn(var.unique.clone()).expect("Unable to whiten!") },
                _ => {}
            }
        }
        // Then, allocate the new pointer if necessary...
        if let Some(ptr) = ptr {
            println!("POINTER");
            allocator.alloc(v.unique.clone(), ptr).expect("Unable to allocate!"); // TODO better error handling
        }
        // ...and insert the key & value into the dictionary blindly.
        self.dict.insert(k, v);
        println!("DONE");
        println!("{:#?}", self);
    }

    pub fn get_children(&self) -> HashSet<UniqueBinding> {
        let mut bindings = HashSet::new();
        for v in self.dict.values() {
            match v.t {
                JsType::JsPtr(_) => { bindings.insert(v.unique.clone()); },
                _ => (),
            }
        }
        bindings
    }
}

impl Display for JsObjStruct {
    fn fmt(&self, mut fmt: &mut Formatter) -> Result<(), Error> {
        try!(write!(fmt, "{{ "));

        for (i, (ref key, ref val)) in self.dict.iter().enumerate() {
            if i != 0 {
                try!(write!(fmt, ", "));
            }

            try!(write!(fmt, "{}: {}", key, val));
        }

        write!(fmt, " }}")
    }
}

pub type JsProto = Option<Box<JsObjStruct>>;

// TODO nice JS object creation macro
//macro_rules! js_obj {
//    ( $kt:ty : $ke:expr => $vt:ty : $ve:expr ),* {
//        {
//
//        }
//    };
//}
<commit_msg>Add pointer typechecking to JsObjStruct creation<commit_after>use std::collections::hash_map::HashMap;
use std::collections::hash_set::HashSet;
use std::fmt::{Display, Formatter, Error};
use std::string::String;
use std::vec::Vec;

use alloc_box::AllocBox;
use super::binding::UniqueBinding;
use super::js_var::{JsVar, JsKey, JsType, JsPtrEnum};

macro_rules! ptr_type_mismatch {
    ($tag:expr, $ptr:expr) => {
        panic!("Pointer type mismatch: expected {:?} but received {:?}", $tag, $ptr);
    }
}

#[derive(Clone, Debug)]
pub struct JsObjStruct {
    pub proto: JsProto,
    pub name: String,
    pub dict: HashMap<JsKey, JsVar>,
}

impl JsObjStruct {
    #[allow(unused_variables)]
    pub fn new(proto: JsProto, name: &str, kv_tuples: Vec<(JsKey, JsVar, Option<JsPtrEnum>)>,
               allocator: &mut AllocBox) -> JsObjStruct {
        JsObjStruct {
            proto: None,
            name: String::from(name),
            dict: kv_tuples.into_iter().map(|(k, v, ptr)| {
                match v.t {
                    JsType::JsPtr(ref tag) => match ptr {
                        Some(ptr) => {
                            if tag.eq_ptr_type(&ptr) {
                                allocator.alloc(v.unique.clone(), ptr).expect("Unable to allocate!"); // TODO better error handling
                            } else {
                                ptr_type_mismatch!(tag, ptr);
                            }
                        },
                        None => ptr_type_mismatch!(tag, None::<JsPtrEnum>),
                    },
                    _ => match ptr {
                        Some(ptr) => ptr_type_mismatch!(None::<JsPtrEnum>, ptr),
                        None => {},
                    },
                }
                (k, v)
            }).collect()
        }
    }

    pub fn add_key(&mut self, k: JsKey, v: JsVar, ptr: Option<JsPtrEnum>, allocator: &mut AllocBox) {
        println!("{:#?}", self);
        // If the key already exists, potentially condemn its pointer, which is being overwritten.
        if let Some(var) = self.dict.get(&k) {
            println!("VAR");
            match var.t {
                JsType::JsPtr(_) => { println!("CONDEMN"); allocator.condemn(var.unique.clone()).expect("Unable to whiten!") },
                _ => {}
            }
        }
        // Then, allocate the new pointer if necessary...
        if let Some(ptr) = ptr {
            println!("POINTER");
            allocator.alloc(v.unique.clone(), ptr).expect("Unable to allocate!"); // TODO better error handling
        }
        // ...and insert the key & value into the dictionary blindly.
        self.dict.insert(k, v);
        println!("DONE");
        println!("{:#?}", self);
    }

    pub fn get_children(&self) -> HashSet<UniqueBinding> {
        let mut bindings = HashSet::new();
        for v in self.dict.values() {
            match v.t {
                JsType::JsPtr(_) => { bindings.insert(v.unique.clone()); },
                _ => (),
            }
        }
        bindings
    }
}

impl Display for JsObjStruct {
    fn fmt(&self, mut fmt: &mut Formatter) -> Result<(), Error> {
        try!(write!(fmt, "{{ "));

        for (i, (ref key, ref val)) in self.dict.iter().enumerate() {
            if i != 0 {
                try!(write!(fmt, ", "));
            }

            try!(write!(fmt, "{}: {}", key, val));
        }

        write!(fmt, " }}")
    }
}

pub type JsProto = Option<Box<JsObjStruct>>;

// TODO nice JS object creation macro
//macro_rules! js_obj {
//    ( $kt:ty : $ke:expr => $vt:ty : $ve:expr ),* {
//        {
//
//        }
//    };
//}
<|endoftext|>


<commit_before>
use eventprocessor::EventProcessor;
use paddedatomics::Padded64;
use std::cmp::{min, max};

pub trait WaitStrategy {
	fn new(ring_size: uint) -> Self;
	fn get_ring_size(&self) -> uint;
	fn wait_for(&self, sequence: int, ep: &Vec<&Padded64>) -> uint;
	fn can_read(&self, sequence: int, deps: &Vec<&Padded64>) -> Option<int>;

	fn until(&self, sequence: int, deps: &Vec<&Padded64>) -> int {
		let mut next: Option<int> = None;

		debug!("deps: {}", deps);
		for v in deps.iter() {
			let pos: int = v.load();

			debug!("Dep: {}, Sequence: {}", pos, sequence);
			if pos != -1 {
				let adjusted = match pos < sequence {
					true => pos + self.get_ring_size() as int,
					false => pos
				};

				next = match next {
					None => Some(adjusted),
					Some(p) => {
						Some(min(p, adjusted))
					}
				}
			}
		}

		let final = match next {
			None => -1,
			Some(p) => p
		};

		debug!("WaitStrategy::until:  {}", final);
		final
	}

}

pub struct BusyWait {
	ring_size: uint,
  ring_mask: uint
}

impl WaitStrategy for BusyWait {
	fn new(ring_size: uint) -> BusyWait {
		BusyWait {
			ring_size: ring_size,
			ring_mask: ring_size -1
		}
	}

	fn get_ring_size(&self) -> uint {
		self.ring_size
	}

	fn wait_for(&self, sequence: int, deps: &Vec<&Padded64>) -> uint {
		let mut available = 0;
		loop {
			match self.can_read(sequence, deps) {
				Some(v) => {
					available = v;
					break
				},
				None => {}
			}
		}
		debug!("					Wait done, returning {}", available);
		available as uint
	}

	fn can_read(&self, sequence: int, deps: &Vec<&Padded64>) -> Option<int> {
		let mut min_cursor = (self.ring_size * 2) as int + 1;

		for v in deps.iter() {
			let cursor = v.load();
			debug!("					dep cursor: {}, ring_size: {}, sequence: {}, calculation: {}", cursor, self.ring_size as int, sequence, sequence == (cursor ^ self.ring_size as int));

			if sequence == cursor {
				return None;	// at same position as a dependency. we can't move
			}
			min_cursor = min(min_cursor, cursor);
			debug!("					dep cursor: {}, ring_size: {}, sequence: {}, calculation: {}", cursor, self.ring_size as int, sequence, sequence == (cursor ^ self.ring_size as int));
			debug!("					min_cursor: {}", min_cursor);

			//if sequence == (cursor ^ self.ring_size as int) {
			//	return false;	// full ring buffer, same position but flipped parity bits
			//}
		}
		Some(min_cursor)
	}
}
<commit_msg>remove unused debug<commit_after>
use eventprocessor::EventProcessor;
use paddedatomics::Padded64;
use std::cmp::{min, max};

pub trait WaitStrategy {
	fn new(ring_size: uint) -> Self;
	fn get_ring_size(&self) -> uint;
	fn wait_for(&self, sequence: int, ep: &Vec<&Padded64>) -> uint;
	fn can_read(&self, sequence: int, deps: &Vec<&Padded64>) -> Option<int>;

	fn until(&self, sequence: int, deps: &Vec<&Padded64>) -> int {
		let mut next: Option<int> = None;

		for v in deps.iter() {
			let pos: int = v.load();

			debug!("Dep: {}, Sequence: {}", pos, sequence);
			if pos != -1 {
				let adjusted = match pos < sequence {
					true => pos + self.get_ring_size() as int,
					false => pos
				};

				next = match next {
					None => Some(adjusted),
					Some(p) => {
						Some(min(p, adjusted))
					}
				}
			}
		}

		let final = match next {
			None => -1,
			Some(p) => p
		};

		debug!("WaitStrategy::until:  {}", final);
		final
	}

}

pub struct BusyWait {
	ring_size: uint,
  ring_mask: uint
}

impl WaitStrategy for BusyWait {
	fn new(ring_size: uint) -> BusyWait {
		BusyWait {
			ring_size: ring_size,
			ring_mask: ring_size -1
		}
	}

	fn get_ring_size(&self) -> uint {
		self.ring_size
	}

	fn wait_for(&self, sequence: int, deps: &Vec<&Padded64>) -> uint {
		let mut available = 0;
		loop {
			match self.can_read(sequence, deps) {
				Some(v) => {
					available = v;
					break
				},
				None => {}
			}
		}
		debug!("					Wait done, returning {}", available);
		available as uint
	}

	fn can_read(&self, sequence: int, deps: &Vec<&Padded64>) -> Option<int> {
		let mut min_cursor = (self.ring_size * 2) as int + 1;

		for v in deps.iter() {
			let cursor = v.load();
			debug!("					dep cursor: {}, ring_size: {}, sequence: {}, calculation: {}", cursor, self.ring_size as int, sequence, sequence == (cursor ^ self.ring_size as int));

			if sequence == cursor {
				return None;	// at same position as a dependency. we can't move
			}
			min_cursor = min(min_cursor, cursor);
			debug!("					dep cursor: {}, ring_size: {}, sequence: {}, calculation: {}", cursor, self.ring_size as int, sequence, sequence == (cursor ^ self.ring_size as int));
			debug!("					min_cursor: {}", min_cursor);

			//if sequence == (cursor ^ self.ring_size as int) {
			//	return false;	// full ring buffer, same position but flipped parity bits
			//}
		}
		Some(min_cursor)
	}
}
<|endoftext|>


<commit_before>use byteorder::{LittleEndian, ReadBytesExt};
use std::default::Default;
use std::io;
use std::io::{Cursor, Read};

use image;
use image::ImageDecoder;
use image::ImageResult;

use color;

use super::vp8::Frame;
use super::vp8::VP8Decoder;

/// A Representation of a Webp Image format decoder.
pub struct WebpDecoder<R> {
    r: R,
    frame: Frame,
    have_frame: bool,
}

impl<R: Read> WebpDecoder<R> {
    /// Create a new WebpDecoder from the Reader ```r```.
    /// This function takes ownership of the Reader.
    pub fn new(r: R) -> ImageResult<WebpDecoder<R>> {
        let f: Frame = Default::default();

        let mut decoder = WebpDecoder {
            r,
            have_frame: false,
            frame: f,
        };
        decoder.read_metadata()?;
        Ok(decoder)
    }

    fn read_riff_header(&mut self) -> ImageResult<u32> {
        let mut riff = Vec::with_capacity(4);
        try!(self.r.by_ref().take(4).read_to_end(&mut riff));
        let size = try!(self.r.read_u32::<LittleEndian>());
        let mut webp = Vec::with_capacity(4);
        try!(self.r.by_ref().take(4).read_to_end(&mut webp));

        if &*riff != b"RIFF" {
            return Err(image::ImageError::FormatError(
                "Invalid RIFF signature.".to_string(),
            ));
        }

        if &*webp != b"WEBP" {
            return Err(image::ImageError::FormatError(
                "Invalid WEBP signature.".to_string(),
            ));
        }

        Ok(size)
    }

    fn read_vp8_header(&mut self) -> ImageResult<()> {
        let mut vp8 = Vec::with_capacity(4);
        try!(self.r.by_ref().take(4).read_to_end(&mut vp8));

        if &*vp8 != b"VP8 " {
            return Err(image::ImageError::FormatError(
                "Invalid VP8 signature.".to_string(),
            ));
        }

        let _len = try!(self.r.read_u32::<LittleEndian>());

        Ok(())
    }

    fn read_frame(&mut self) -> ImageResult<()> {
        let mut framedata = Vec::new();
        try!(self.r.read_to_end(&mut framedata));
        let m = io::Cursor::new(framedata);

        let mut v = VP8Decoder::new(m);
        let frame = try!(v.decode_frame());

        self.frame = frame.clone();

        Ok(())
    }

    fn read_metadata(&mut self) -> ImageResult<()> {
        if !self.have_frame {
            try!(self.read_riff_header());
            try!(self.read_vp8_header());
            try!(self.read_frame());

            self.have_frame = true;
        }

        Ok(())
    }
}

impl<R: Read> ImageDecoder for WebpDecoder<R> {
    type Reader = Cursor<Vec<u8>>;

    fn dimensions(&self) -> (u64, u64) {
        (self.frame.width as u64, self.frame.height as u64)
    }

    fn colortype(&self) -> color::ColorType {
        color::ColorType::Gray(8)
    }

    fn into_reader(self) -> ImageResult<Self::Reader> {
        Ok(Cursor::new(self.frame.ybuf))
    }

    fn read_image(self) -> ImageResult<Vec<u8>> {
        Ok(self.frame.ybuf)
    }
}
<commit_msg>Clarify that webp decoder can only decode luma channel<commit_after>use byteorder::{LittleEndian, ReadBytesExt};
use std::default::Default;
use std::io;
use std::io::{Cursor, Read};

use image;
use image::ImageDecoder;
use image::ImageResult;

use color;

use super::vp8::Frame;
use super::vp8::VP8Decoder;

/// Webp Image format decoder. Currently only supportes the luma channel (meaning that decoded
/// images will be grayscale).
pub struct WebpDecoder<R> {
    r: R,
    frame: Frame,
    have_frame: bool,
}

impl<R: Read> WebpDecoder<R> {
    /// Create a new WebpDecoder from the Reader ```r```.
    /// This function takes ownership of the Reader.
    pub fn new(r: R) -> ImageResult<WebpDecoder<R>> {
        let f: Frame = Default::default();

        let mut decoder = WebpDecoder {
            r,
            have_frame: false,
            frame: f,
        };
        decoder.read_metadata()?;
        Ok(decoder)
    }

    fn read_riff_header(&mut self) -> ImageResult<u32> {
        let mut riff = Vec::with_capacity(4);
        try!(self.r.by_ref().take(4).read_to_end(&mut riff));
        let size = try!(self.r.read_u32::<LittleEndian>());
        let mut webp = Vec::with_capacity(4);
        try!(self.r.by_ref().take(4).read_to_end(&mut webp));

        if &*riff != b"RIFF" {
            return Err(image::ImageError::FormatError(
                "Invalid RIFF signature.".to_string(),
            ));
        }

        if &*webp != b"WEBP" {
            return Err(image::ImageError::FormatError(
                "Invalid WEBP signature.".to_string(),
            ));
        }

        Ok(size)
    }

    fn read_vp8_header(&mut self) -> ImageResult<()> {
        let mut vp8 = Vec::with_capacity(4);
        try!(self.r.by_ref().take(4).read_to_end(&mut vp8));

        if &*vp8 != b"VP8 " {
            return Err(image::ImageError::FormatError(
                "Invalid VP8 signature.".to_string(),
            ));
        }

        let _len = try!(self.r.read_u32::<LittleEndian>());

        Ok(())
    }

    fn read_frame(&mut self) -> ImageResult<()> {
        let mut framedata = Vec::new();
        try!(self.r.read_to_end(&mut framedata));
        let m = io::Cursor::new(framedata);

        let mut v = VP8Decoder::new(m);
        let frame = try!(v.decode_frame());

        self.frame = frame.clone();

        Ok(())
    }

    fn read_metadata(&mut self) -> ImageResult<()> {
        if !self.have_frame {
            try!(self.read_riff_header());
            try!(self.read_vp8_header());
            try!(self.read_frame());

            self.have_frame = true;
        }

        Ok(())
    }
}

impl<R: Read> ImageDecoder for WebpDecoder<R> {
    type Reader = Cursor<Vec<u8>>;

    fn dimensions(&self) -> (u64, u64) {
        (self.frame.width as u64, self.frame.height as u64)
    }

    fn colortype(&self) -> color::ColorType {
        color::ColorType::Gray(8)
    }

    fn into_reader(self) -> ImageResult<Self::Reader> {
        Ok(Cursor::new(self.frame.ybuf))
    }

    fn read_image(self) -> ImageResult<Vec<u8>> {
        Ok(self.frame.ybuf)
    }
}
<|endoftext|>


<commit_before>extern crate native;
extern crate kiss3d;
extern crate nalgebra;
extern crate genmesh;

use std::rc::Rc;
use std::cell::RefCell;
use nalgebra::na::Vec3;
use nalgebra::na;
use kiss3d::window::Window;
use kiss3d::resource::Mesh;
use kiss3d::light;

use genmesh::{MapToVertices, Triangulate};
use genmesh::{LruIndexer, Indexer};
use genmesh::generators::Cube;

#[start]
fn start(argc: int, argv: *const *const u8) -> int {
    native::start(argc, argv, main)
}

fn main() {
    let mut window = Window::new("Kiss3d: custom_mesh");

    let mut cube_v = Vec::new();
    let cube_i: Vec<Vec3<u32>> = {
        let mut indexer = LruIndexer::new(8, |_, v| cube_v.push(v));
        Cube::new()
            .vertex(|(a, b, c)| {
                Vec3::new(a, b, c)
            })
            .vertex(|v| indexer.index(v) as u32)
            .triangulate()
            .map(|p| Vec3::new(p.x, p.y, p.z) )
            .collect()
    };

    let mesh  = Rc::new(RefCell::new(Mesh::new(cube_v, cube_i, None, None, false)));
    let mut c = window.add_mesh(mesh, na::one());

    c.set_color(1.0, 0.0, 0.0);
    c.enable_backface_culling(false);
    c.set_local_scale(0.1, 0.1, 0.1);
    c.set_local_translation(Vec3::new(0f32, 0., 0.));

    window.set_light(light::StickToCamera);

    while window.render() {
        c.prepend_to_local_rotation(&Vec3::new(0.0f32, 0.014, 0.01));
    }
}
<commit_msg>added plane to example<commit_after>extern crate native;
extern crate kiss3d;
extern crate nalgebra;
extern crate genmesh;

use std::rc::Rc;
use std::cell::RefCell;
use nalgebra::na::Vec3;
use nalgebra::na;
use kiss3d::window::Window;
use kiss3d::resource::Mesh;
use kiss3d::light;

use genmesh::{MapToVertices, Triangulate};
use genmesh::{LruIndexer, Indexer};
use genmesh::generators::{Plane, Cube};

#[start]
fn start(argc: int, argv: *const *const u8) -> int {
    native::start(argc, argv, main)
}

fn main() {
    let mut window = Window::new("Kiss3d: custom_mesh");

    let mut cube_v = Vec::new();
    let cube_i: Vec<Vec3<u32>> = {
        let mut indexer = LruIndexer::new(8, |_, v| cube_v.push(v));
        Cube::new()
            .vertex(|(a, b, c)| {
                Vec3::new(a, b, c)
            })
            .vertex(|v| indexer.index(v) as u32)
            .triangulate()
            .map(|p| Vec3::new(p.x, p.y, p.z) )
            .collect()
    };
    let cube_mesh = Rc::new(RefCell::new(Mesh::new(cube_v, cube_i, None, None, false)));
    let mut cube = window.add_mesh(cube_mesh, na::one());

    cube.set_color(1.0, 0.0, 0.0);
    cube.set_local_scale(0.1, 0.1, 0.1);
    cube.prepend_to_local_rotation(&Vec3::new(-0.5f32, 0., 0.));

    let mut plane_v = Vec::new();
    let plane_i: Vec<Vec3<u32>> = {
        let mut indexer = LruIndexer::new(8, |_, v| plane_v.push(v));
        Plane::subdivide(8, 8)
            .triangulate()
            .vertex(|(a, b)| {
                Vec3::new(a, b, 0.)
            })
            .vertex(|v| indexer.index(v) as u32)
            .map(|p| Vec3::new(p.x, p.y, p.z) )
            .collect()
    };
    let plane_mesh = Rc::new(RefCell::new(Mesh::new(plane_v, plane_i, None, None, false)));
    let mut plane = window.add_mesh(plane_mesh, na::one());

    plane.set_color(0.0, 1.0, 0.0);
    plane.set_local_scale(0.1, 0.1, 0.1);
    plane.set_local_translation(Vec3::new(0.25f32, 0.0, 0.0));
    plane.prepend_to_local_rotation(&Vec3::new(-0.5f32, 0., 0.));

    window.set_light(light::StickToCamera);

    while window.render() {
        cube.prepend_to_local_rotation(&Vec3::new(0.0f32, 0.014, 0.0));
        plane.prepend_to_local_rotation(&Vec3::new(0.0f32, 0.014, 0.0));
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 fd developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0>
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::process::Command;
use std::sync::{Arc, Mutex};
use std::io;

/// Executes a command.
#[cfg(not(unix))]
pub fn execute_command(mut cmd: Command, out_perm: Arc<Mutex<()>>) {
    use std::process::Stdio;
    use std::io::Write;

    // Spawn the supplied command.
    let output = cmd.stdout(Stdio::piped()).stderr(Stdio::piped()).output();

    // Then wait for the command to exit, if it was spawned.
    match output {
        Ok(output) => {
            // While this lock is active, this thread will be the only thread allowed
            // to write it's outputs.
            let _lock = out_perm.lock().unwrap();

            let stdout = io::stdout();
            let stderr = io::stderr();

            let _ = stdout.lock().write_all(&output.stdout);
            let _ = stderr.lock().write_all(&output.stderr);
        }
        Err(why) => eprintln!("fd: exec error: {}", why),
    }
}

/// Executes a command.
#[cfg(all(unix))]
pub fn execute_command(mut cmd: Command, out_perm: Arc<Mutex<()>>) {
    use libc::{close, dup2, pipe, STDERR_FILENO, STDOUT_FILENO};
    use std::fs::File;
    use std::os::unix::process::CommandExt;
    use std::os::unix::io::FromRawFd;

    // Initial a pair of pipes that will be used to
    // pipe the std{out,err} of the spawned process.
    let mut stdout_fds = [0; 2];
    let mut stderr_fds = [0; 2];

    unsafe {
        pipe(stdout_fds.as_mut_ptr());
        pipe(stderr_fds.as_mut_ptr());
    }

    // Configure the pipes accordingly in the child.
    let child = cmd.before_exec(move || unsafe {
        // Redirect the child's std{out,err} to the write ends of our pipe.
        dup2(stdout_fds[1], STDOUT_FILENO);
        dup2(stderr_fds[1], STDERR_FILENO);

        // Close all the fds we created here, so EOF will be sent when the program exits.
        close(stdout_fds[0]);
        close(stdout_fds[1]);
        close(stderr_fds[0]);
        close(stderr_fds[1]);
        Ok(())
    }).spawn();

    // Open the read end of the pipes as `File`s.
    let (mut pout, mut perr) = unsafe {
        // Close the write ends of the pipes in the parent
        close(stdout_fds[1]);
        close(stderr_fds[1]);
        (
            // But create files from the read ends.
            File::from_raw_fd(stdout_fds[0]),
            File::from_raw_fd(stderr_fds[0]),
        )
    };

    match child {
        Ok(mut child) => {
            let _ = child.wait();

            // Create a lock to ensure that this thread has exclusive access to writing.
            let _lock = self.out_perm.lock().unwrap();

            // And then write the outputs of the process until EOF is sent to each file.
            let stdout = io::stdout();
            let stderr = io::stderr();
            let _ = io::copy(&mut pout, &mut stdout.lock());
            let _ = io::copy(&mut perr, &mut stderr.lock());
        }
        Err(why) => eprintln!("fd: exec error: {}", why),
    }
}
<commit_msg>Fix execute_command on Unix<commit_after>// Copyright (c) 2017 fd developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0>
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::process::Command;
use std::sync::{Arc, Mutex};
use std::io;

/// Executes a command.
#[cfg(not(unix))]
pub fn execute_command(mut cmd: Command, out_perm: Arc<Mutex<()>>) {
    use std::process::Stdio;
    use std::io::Write;

    // Spawn the supplied command.
    let output = cmd.stdout(Stdio::piped()).stderr(Stdio::piped()).output();

    // Then wait for the command to exit, if it was spawned.
    match output {
        Ok(output) => {
            // While this lock is active, this thread will be the only thread allowed
            // to write it's outputs.
            let _lock = out_perm.lock().unwrap();

            let stdout = io::stdout();
            let stderr = io::stderr();

            let _ = stdout.lock().write_all(&output.stdout);
            let _ = stderr.lock().write_all(&output.stderr);
        }
        Err(why) => eprintln!("fd: exec error: {}", why),
    }
}

/// Executes a command.
#[cfg(all(unix))]
pub fn execute_command(mut cmd: Command, out_perm: Arc<Mutex<()>>) {
    use libc::{close, dup2, pipe, STDERR_FILENO, STDOUT_FILENO};
    use std::fs::File;
    use std::os::unix::process::CommandExt;
    use std::os::unix::io::FromRawFd;

    // Initial a pair of pipes that will be used to
    // pipe the std{out,err} of the spawned process.
    let mut stdout_fds = [0; 2];
    let mut stderr_fds = [0; 2];

    unsafe {
        pipe(stdout_fds.as_mut_ptr());
        pipe(stderr_fds.as_mut_ptr());
    }

    // Configure the pipes accordingly in the child.
    let child = cmd.before_exec(move || unsafe {
        // Redirect the child's std{out,err} to the write ends of our pipe.
        dup2(stdout_fds[1], STDOUT_FILENO);
        dup2(stderr_fds[1], STDERR_FILENO);

        // Close all the fds we created here, so EOF will be sent when the program exits.
        close(stdout_fds[0]);
        close(stdout_fds[1]);
        close(stderr_fds[0]);
        close(stderr_fds[1]);
        Ok(())
    }).spawn();

    // Open the read end of the pipes as `File`s.
    let (mut pout, mut perr) = unsafe {
        // Close the write ends of the pipes in the parent
        close(stdout_fds[1]);
        close(stderr_fds[1]);
        (
            // But create files from the read ends.
            File::from_raw_fd(stdout_fds[0]),
            File::from_raw_fd(stderr_fds[0]),
        )
    };

    match child {
        Ok(mut child) => {
            let _ = child.wait();

            // Create a lock to ensure that this thread has exclusive access to writing.
            let _lock = out_perm.lock().unwrap();

            // And then write the outputs of the process until EOF is sent to each file.
            let stdout = io::stdout();
            let stderr = io::stderr();
            let _ = io::copy(&mut pout, &mut stdout.lock());
            let _ = io::copy(&mut perr, &mut stderr.lock());
        }
        Err(why) => eprintln!("fd: exec error: {}", why),
    }
}
<|endoftext|>


<commit_before>use syntax;
use syntax::codemap::DUMMY_SP;
use syntax::ext::base::ExtCtxt;
use syntax::feature_gate::GatedCfg;

/// Create a fake ExtCtxt to perform macro quasiquotes outside of rustc plugins
pub fn with_fake_extctxt<T, F: Fn(&ExtCtxt) -> T>(f: F) -> T {
  let ps = syntax::parse::ParseSess::new();
  let mut fg_cfg = Vec::<GatedCfg>::new();

  let mut cx = syntax::ext::base::ExtCtxt::new(&ps, Vec::new(),
    syntax::ext::expand::ExpansionConfig::default("rust-peg".to_string()),
    &mut fg_cfg
  );

  cx.bt_push(syntax::codemap::ExpnInfo{
    call_site: DUMMY_SP,
    callee: syntax::codemap::NameAndSpan {
      format: syntax::codemap::MacroBang(syntax::parse::token::intern("")),
      span: None,
      allow_internal_unstable: false,
    }
  });

  f(&cx)
}
<commit_msg>rust: GatedCfg renamed<commit_after>use syntax;
use syntax::codemap::DUMMY_SP;
use syntax::ext::base::ExtCtxt;

/// Create a fake ExtCtxt to perform macro quasiquotes outside of rustc plugins
pub fn with_fake_extctxt<T, F: Fn(&ExtCtxt) -> T>(f: F) -> T {
  let ps = syntax::parse::ParseSess::new();
  let mut fg_cfg = Vec::new();

  let mut cx = syntax::ext::base::ExtCtxt::new(&ps, Vec::new(),
    syntax::ext::expand::ExpansionConfig::default("rust-peg".to_string()),
    &mut fg_cfg
  );

  cx.bt_push(syntax::codemap::ExpnInfo{
    call_site: DUMMY_SP,
    callee: syntax::codemap::NameAndSpan {
      format: syntax::codemap::MacroBang(syntax::parse::token::intern("")),
      span: None,
      allow_internal_unstable: false,
    }
  });

  f(&cx)
}
<|endoftext|>