<commit_before>//! [![ggez logo](https://raw.githubusercontent.com/ggez/ggez/master/docs/ggez-logo-maroon-full.svg)](http://ggez.rs/)
//!
//! # What is this?
//!
//! ![Build status](https://github.com/ggez/ggez/workflows/CI/badge.svg)
//! [![Docs Status](https://docs.rs/ggez/badge.svg)](https://docs.rs/ggez)
//! [![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/ggez/ggez/blob/master/LICENSE)
//! [![Crates.io](https://img.shields.io/crates/v/ggez.svg)](https://crates.io/crates/ggez)
//! [![Crates.io](https://img.shields.io/crates/d/ggez.svg)](https://crates.io/crates/ggez)
//!
//! ggez is a Rust library to create a Good Game Easily.
//!
//! More specifically, ggez is a lightweight cross-platform game framework
//! for making 2D games with minimum friction.  It aims to implement an
//! API based on (a Rustified version of) the [LÖVE](https://love2d.org/)
//! game framework.  This means it contains basic and portable 2D
//! drawing, sound, resource loading and event handling, but finer details
//! and performance characteristics may be different than LÖVE.
//!
//! ggez is not meant to be everything to everyone, but rather a good
//! base upon which to build.  Thus it takes a fairly
//! batteries-included approach without needing a million additions
//! and plugins for everything imaginable, but also does not dictate
//! higher-level functionality such as physics engine or entity
//! component system.  Instead the goal is to allow you to use
//! whichever libraries you want to provide these functions, or build
//! your own libraries atop ggez.
//!
//! ## Features
//!
//! * Filesystem abstraction that lets you load resources from folders or zip files
//! * Hardware-accelerated 2D rendering built on the `gfx-rs` graphics engine
//! * Loading and playing .ogg, .wav and .flac files via the `rodio` crate
//! * TTF font rendering with `rusttype` and `glyph_brush`.
//! * Interface for handling keyboard and mouse events easily through callbacks
//! * Config file for defining engine and game settings
//! * Easy timing and FPS measurement functions.
//! * Math library integration with `mint`.
//! * Some more advanced graphics options: shaders, sprite batches and render targets
//!
//! ### Supported platforms
//!
//!  * Fully supported: Windows, Linux
//!  * Not officially supported but might work anyway: Mac
//!
//! For details, see [docs/BuildingForEveryPlatform.md](docs/BuildingForEveryPlatform.md)
//!
//! If you want to run ggez on Android, iOS or the web using WebAssembly take a look at [good-web-game](https://github.com/ggez/good-web-game).
//!
//! ## Who's using ggez?
//!
//! Check out the [projects list!](docs/Projects.md)
//!
//! ## Usage
//!
//! ggez requires rustc >= 1.42 and is distributed on
//! crates.io. To include it in your project, just add the dependency
//! line to your `Cargo.toml` file:
//!
//! ```text
//! ggez = "0.6.1"
//! ```
//!
//! ggez consists of three main parts: A `Context` object which
//! contains all the state required to interface with the computer's
//! hardware, an `EventHandler` trait that the user implements to
//! register callbacks for events, and various sub-modules such as
//! `graphics` and `audio` that provide the functionality to actually
//! get stuff done.  The general pattern is to create a struct holding
//! your game's data which implements the `EventHandler` trait.
//! Create a new `Context` object with default objects from a `ContextBuilder`
//! or `Conf` object, and then call `event::run()` with
//! the `Context` and an instance of your `EventHandler` to run your game's
//! main loop.
//!
//! See the [API docs](https://docs.rs/ggez/) for full documentation, or the [examples](/examples) directory for a number of commented examples of varying complexity.  Most examples show off
//! a single feature of ggez, while `astroblasto` and `snake` are small but complete games.
//!
//! ## Getting started
//!
//! For a quick tutorial on ggez, see the [Hello ggez](https://github.com/ggez/ggez/blob/master/docs/guides/HelloGgez.md) guide in the `docs/` directory.
//!
//! ## Examples
//!
//! See the `examples/` directory in the source.  Most examples show off
//! a single feature of ggez, while `astroblasto` is a small  but
//! complete Asteroids-like game.
//!
//! To run the examples, just check out the source and execute `cargo run --example`
//! in the root directory:
//!
//! ```text
//! git clone https://github.com/ggez/ggez.git
//! cd ggez
//! cargo run --example 05_astroblasto
//! ```
//!
//! If this doesn't work, see the
//! [FAQ](https://github.com/ggez/ggez/blob/master/docs/FAQ.md) for solutions
//! to common problems.
//!
//! ### Basic Project Template
//!
//! ```rust,no_run
//! use ggez::{Context, ContextBuilder, GameResult};
//! use ggez::graphics::{self, Color};
//! use ggez::event::{self, EventHandler};
//!
//! fn main() {
//!     // Make a Context.
//!     let (mut ctx, event_loop) = ContextBuilder::new("my_game", "Cool Game Author")
//!         .build()
//!         .expect("aieee, could not create ggez context!");
//!
//!     // Create an instance of your event handler.
//!     // Usually, you should provide it with the Context object to
//!     // use when setting your game up.
//!     let my_game = MyGame::new(&mut ctx);
//!
//!     // Run!
//!     event::run(ctx, event_loop, my_game);
//! }
//!
//! struct MyGame {
//!     // Your state here...
//! }
//!
//! impl MyGame {
//!     pub fn new(_ctx: &mut Context) -> MyGame {
//!         // Load/create resources such as images here.
//!         MyGame {
//!             // ...
//!         }
//!     }
//! }
//!
//! impl EventHandler<ggez::GameError> for MyGame {
//!     fn update(&mut self, _ctx: &mut Context) -> GameResult<()> {
//!         // Update code here...
//!         Ok(())
//!     }
//!
//!     fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
//!         graphics::clear(ctx, Color::WHITE);
//!         // Draw code here...
//!         graphics::present(ctx)
//!     }
//! }
//! ```
//!
//! ## Implementation details
//!
//! ggez is built upon `winit` for windowing and events, `rodio` for
//! sound, and a 2D drawing engine implemented in `gfx` using the OpenGL
//! backend (which currently defaults to use OpenGL 3.2).  It is entirely
//! thread-safe (though platform constraints mean the event-handling loop
//! and drawing must be done in the main thread), and portable to Windows
//! and Linux.
//!
//! ggez is pure Rust™.
//!
//! ## Help!
//!
//! Sources of information:
//!
//!  * The [FAQ](https://github.com/ggez/ggez/blob/master/docs/FAQ.md) has answers to common questions and problems.
//!  * The [API docs](https://docs.rs/ggez/), a lot of design stuff is explained there.
//!  * Check out the [examples](https://github.com/ggez/ggez/tree/master/examples).
//!
//!  If you still have problems or questions, feel free to ask!  Easiest ways are:
//!
//!  * Open an issue on [the Github issue tracker](https://github.com/ggez/ggez/issues)
//!  * Say hi on the [unofficial Rust Discord server](http://bit.ly/rust-community) or the [Rust Gamedev server](https://discord.gg/yNtPTb2)

#![doc(html_logo_url = "https://raw.githubusercontent.com/ggez/ggez/master/docs/ggez-logo-maroon-logo-only.svg")]

#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![deny(unused_results)]
// This is not as strong a constraint as `#![forbid(unsafe_code)]` but is good enough.
// It means the only place we use unsafe is then in the modules noted as allowing it.
#![deny(unsafe_code)]
#![warn(bare_trait_objects)]
#![warn(missing_copy_implementations)]
#![allow(clippy::needless_doctest_main)]

#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate gfx;
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate smart_default;

pub extern crate mint;

pub mod audio;
pub mod conf;
mod context;
pub mod error;
pub mod event;
pub mod filesystem;
pub mod graphics;
pub mod input;
pub mod timer;
mod vfs;

#[cfg(test)]
pub mod tests;

pub use crate::context::{winit, Context, ContextBuilder};
pub use crate::error::*;
<commit_msg>rustfmt...<commit_after>//! [![ggez logo](https://raw.githubusercontent.com/ggez/ggez/master/docs/ggez-logo-maroon-full.svg)](http://ggez.rs/)
//!
//! # What is this?
//!
//! ![Build status](https://github.com/ggez/ggez/workflows/CI/badge.svg)
//! [![Docs Status](https://docs.rs/ggez/badge.svg)](https://docs.rs/ggez)
//! [![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/ggez/ggez/blob/master/LICENSE)
//! [![Crates.io](https://img.shields.io/crates/v/ggez.svg)](https://crates.io/crates/ggez)
//! [![Crates.io](https://img.shields.io/crates/d/ggez.svg)](https://crates.io/crates/ggez)
//!
//! ggez is a Rust library to create a Good Game Easily.
//!
//! More specifically, ggez is a lightweight cross-platform game framework
//! for making 2D games with minimum friction.  It aims to implement an
//! API based on (a Rustified version of) the [LÖVE](https://love2d.org/)
//! game framework.  This means it contains basic and portable 2D
//! drawing, sound, resource loading and event handling, but finer details
//! and performance characteristics may be different than LÖVE.
//!
//! ggez is not meant to be everything to everyone, but rather a good
//! base upon which to build.  Thus it takes a fairly
//! batteries-included approach without needing a million additions
//! and plugins for everything imaginable, but also does not dictate
//! higher-level functionality such as physics engine or entity
//! component system.  Instead the goal is to allow you to use
//! whichever libraries you want to provide these functions, or build
//! your own libraries atop ggez.
//!
//! ## Features
//!
//! * Filesystem abstraction that lets you load resources from folders or zip files
//! * Hardware-accelerated 2D rendering built on the `gfx-rs` graphics engine
//! * Loading and playing .ogg, .wav and .flac files via the `rodio` crate
//! * TTF font rendering with `rusttype` and `glyph_brush`.
//! * Interface for handling keyboard and mouse events easily through callbacks
//! * Config file for defining engine and game settings
//! * Easy timing and FPS measurement functions.
//! * Math library integration with `mint`.
//! * Some more advanced graphics options: shaders, sprite batches and render targets
//!
//! ### Supported platforms
//!
//!  * Fully supported: Windows, Linux
//!  * Not officially supported but might work anyway: Mac
//!
//! For details, see [docs/BuildingForEveryPlatform.md](docs/BuildingForEveryPlatform.md)
//!
//! If you want to run ggez on Android, iOS or the web using WebAssembly take a look at [good-web-game](https://github.com/ggez/good-web-game).
//!
//! ## Who's using ggez?
//!
//! Check out the [projects list!](docs/Projects.md)
//!
//! ## Usage
//!
//! ggez requires rustc >= 1.42 and is distributed on
//! crates.io. To include it in your project, just add the dependency
//! line to your `Cargo.toml` file:
//!
//! ```text
//! ggez = "0.6.1"
//! ```
//!
//! ggez consists of three main parts: A `Context` object which
//! contains all the state required to interface with the computer's
//! hardware, an `EventHandler` trait that the user implements to
//! register callbacks for events, and various sub-modules such as
//! `graphics` and `audio` that provide the functionality to actually
//! get stuff done.  The general pattern is to create a struct holding
//! your game's data which implements the `EventHandler` trait.
//! Create a new `Context` object with default objects from a `ContextBuilder`
//! or `Conf` object, and then call `event::run()` with
//! the `Context` and an instance of your `EventHandler` to run your game's
//! main loop.
//!
//! See the [API docs](https://docs.rs/ggez/) for full documentation, or the [examples](/examples) directory for a number of commented examples of varying complexity.  Most examples show off
//! a single feature of ggez, while `astroblasto` and `snake` are small but complete games.
//!
//! ## Getting started
//!
//! For a quick tutorial on ggez, see the [Hello ggez](https://github.com/ggez/ggez/blob/master/docs/guides/HelloGgez.md) guide in the `docs/` directory.
//!
//! ## Examples
//!
//! See the `examples/` directory in the source.  Most examples show off
//! a single feature of ggez, while `astroblasto` is a small  but
//! complete Asteroids-like game.
//!
//! To run the examples, just check out the source and execute `cargo run --example`
//! in the root directory:
//!
//! ```text
//! git clone https://github.com/ggez/ggez.git
//! cd ggez
//! cargo run --example 05_astroblasto
//! ```
//!
//! If this doesn't work, see the
//! [FAQ](https://github.com/ggez/ggez/blob/master/docs/FAQ.md) for solutions
//! to common problems.
//!
//! ### Basic Project Template
//!
//! ```rust,no_run
//! use ggez::{Context, ContextBuilder, GameResult};
//! use ggez::graphics::{self, Color};
//! use ggez::event::{self, EventHandler};
//!
//! fn main() {
//!     // Make a Context.
//!     let (mut ctx, event_loop) = ContextBuilder::new("my_game", "Cool Game Author")
//!         .build()
//!         .expect("aieee, could not create ggez context!");
//!
//!     // Create an instance of your event handler.
//!     // Usually, you should provide it with the Context object to
//!     // use when setting your game up.
//!     let my_game = MyGame::new(&mut ctx);
//!
//!     // Run!
//!     event::run(ctx, event_loop, my_game);
//! }
//!
//! struct MyGame {
//!     // Your state here...
//! }
//!
//! impl MyGame {
//!     pub fn new(_ctx: &mut Context) -> MyGame {
//!         // Load/create resources such as images here.
//!         MyGame {
//!             // ...
//!         }
//!     }
//! }
//!
//! impl EventHandler<ggez::GameError> for MyGame {
//!     fn update(&mut self, _ctx: &mut Context) -> GameResult<()> {
//!         // Update code here...
//!         Ok(())
//!     }
//!
//!     fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
//!         graphics::clear(ctx, Color::WHITE);
//!         // Draw code here...
//!         graphics::present(ctx)
//!     }
//! }
//! ```
//!
//! ## Implementation details
//!
//! ggez is built upon `winit` for windowing and events, `rodio` for
//! sound, and a 2D drawing engine implemented in `gfx` using the OpenGL
//! backend (which currently defaults to use OpenGL 3.2).  It is entirely
//! thread-safe (though platform constraints mean the event-handling loop
//! and drawing must be done in the main thread), and portable to Windows
//! and Linux.
//!
//! ggez is pure Rust™.
//!
//! ## Help!
//!
//! Sources of information:
//!
//!  * The [FAQ](https://github.com/ggez/ggez/blob/master/docs/FAQ.md) has answers to common questions and problems.
//!  * The [API docs](https://docs.rs/ggez/), a lot of design stuff is explained there.
//!  * Check out the [examples](https://github.com/ggez/ggez/tree/master/examples).
//!
//!  If you still have problems or questions, feel free to ask!  Easiest ways are:
//!
//!  * Open an issue on [the Github issue tracker](https://github.com/ggez/ggez/issues)
//!  * Say hi on the [unofficial Rust Discord server](http://bit.ly/rust-community) or the [Rust Gamedev server](https://discord.gg/yNtPTb2)

#![doc(
    html_logo_url = "https://raw.githubusercontent.com/ggez/ggez/master/docs/ggez-logo-maroon-logo-only.svg"
)]
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![deny(unused_results)]
// This is not as strong a constraint as `#![forbid(unsafe_code)]` but is good enough.
// It means the only place we use unsafe is then in the modules noted as allowing it.
#![deny(unsafe_code)]
#![warn(bare_trait_objects)]
#![warn(missing_copy_implementations)]
#![allow(clippy::needless_doctest_main)]

#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate gfx;
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate smart_default;

pub extern crate mint;

pub mod audio;
pub mod conf;
mod context;
pub mod error;
pub mod event;
pub mod filesystem;
pub mod graphics;
pub mod input;
pub mod timer;
mod vfs;

#[cfg(test)]
pub mod tests;

pub use crate::context::{winit, Context, ContextBuilder};
pub use crate::error::*;
<|endoftext|>


<commit_before>#![allow(non_camel_case_types)]

extern crate libc;

use libc::{c_char};
use std::ffi::{CString, CStr};
use std::ptr;

pub mod taglib_sys;

use taglib_sys as ll;

fn c_str_to_str(c_str: *const c_char) -> String {
  if c_str.is_null() {
    String::new()
  }
  else {
    let bytes = unsafe { CStr::from_ptr(c_str).to_bytes() };
    String::from_utf8_lossy(bytes).to_string()
  }
}

/// The abstract meta-data container for audio files
///
/// Each `Tag` instance can only be created by the `taglib::File::tag()`
/// method.
pub struct Tag {
  raw: *mut ll::TagLib_Tag,
}

impl Drop for Tag {
  fn drop(&mut self) {
    unsafe { ll::taglib_tag_free_strings() }
  }
}

impl Tag {
  /// Returns the track name, or an empty string if no track name is present.
  pub fn title(&self) -> String {
    let res = unsafe { ll::taglib_tag_title(self.raw) };
    c_str_to_str(res)
  }

  /// Sets the track name.
  pub fn set_title(&mut self, title: &str) {
    let s = CString::new(title).unwrap().as_ptr();
    unsafe { ll::taglib_tag_set_title(self.raw, s); }
  }

  /// Returns the artist name, or an empty string if no artist name is present.
  pub fn artist(&self) -> String {
    let res = unsafe { ll::taglib_tag_artist(self.raw) };
    c_str_to_str(res)
  }

  /// Sets the artist name.
  pub fn set_artist(&mut self, artist: &str) {
    let s = CString::new(artist).unwrap().as_ptr();
    unsafe { ll::taglib_tag_set_artist(self.raw, s); }
  }

  /// Returns the album name, or an empty string if no album name is present.
  pub fn album(&self) -> String {
    let res = unsafe { ll::taglib_tag_album(self.raw) };
    c_str_to_str(res)
  }

  /// Sets the album name.
  pub fn set_album(&mut self, album: &str) {
    let s = CString::new(album).unwrap().as_ptr();
    unsafe { ll::taglib_tag_set_album(self.raw, s); }
  }

  /// Returns the track comment, or an empty string if no track comment is
  /// present.
  pub fn comment(&self) -> String {
    let res = unsafe { ll::taglib_tag_comment(self.raw) };
    c_str_to_str(res)
  }

  /// Sets the track comment.
  pub fn set_comment(&mut self, comment: &str) {
    let s = CString::new(comment).unwrap().as_ptr();
    unsafe { ll::taglib_tag_set_comment(self.raw, s); }
  }

  /// Returns the genre name, or an empty string if no genre name is present.
  pub fn genre(&self) -> String {
    let res = unsafe { ll::taglib_tag_genre(self.raw) };
    c_str_to_str(res)
  }

  /// Sets the genre name.
  pub fn set_genre(&mut self, genre: &str) {
    let s = CString::new(genre).unwrap().as_ptr();
    unsafe { ll::taglib_tag_set_genre(self.raw, s); }
  }

  /// Returns the year, or 0 if no year is present.
  pub fn year(&self) -> u32 {
    unsafe { ll::taglib_tag_year(self.raw) as u32 }
  }

  /// Sets the year.
  pub fn set_year(&mut self, year: u32) {
    unsafe { ll::taglib_tag_set_year(self.raw, year); }
  }

  /// Returns the track number, or 0 if no track number is present.
  pub fn track(&self) -> u32 {
    unsafe { ll::taglib_tag_track(self.raw) as u32 }
  }

  /// Sets the track number.
  pub fn set_track(&mut self, track: u32) {
    unsafe { ll::taglib_tag_set_track(self.raw, track); }
  }
}

/// Common audio file properties.
///
/// Instances of `AudioProperties` can only be created through the
/// `taglib::File::audioproperties()` method.
pub struct AudioProperties {
  raw: *const ll::TagLib_AudioProperties,
}

impl AudioProperties {
  /// Returns the length, in seconds, of the track.
  pub fn length(&self) -> u32 {
    unsafe { ll::taglib_audioproperties_length(self.raw) as u32 }
  }

  /// Returns the most appropriate bit rate for the track, in kB/s.
  /// For constant bit rate formats, the returned value is the bit
  /// rate of the file; for variable bit rate formats this is either
  /// the average or the nominal bit rate.
  pub fn bitrate(&self) -> u32 {
    unsafe { ll::taglib_audioproperties_bitrate(self.raw) as u32 }
  }

  /// Returns the sample rate, in Hz.
  pub fn samplerate(&self) -> u32 {
    unsafe { ll::taglib_audioproperties_samplerate(self.raw) as u32 }
  }

  /// Returns the number of audio channels.
  pub fn channels(&self) -> u32 {
    unsafe { ll::taglib_audioproperties_channels(self.raw) as u32 }
  }
}

#[derive(Copy, Clone, PartialEq)]
pub enum FileType {
  /// MPEG file
  MPEG = ll::TAGLIB_FILE_MPEG as isize,
  /// Ogg/Vorbis file
  OggVorbis = ll::TAGLIB_FILE_OGG_VORBIS as isize,
  /// FLAC file
  FLAC = ll::TAGLIB_FILE_FLAC as isize,
  /// MPC file
  MPC = ll::TAGLIB_FILE_MPC as isize,
  /// Ogg/FLAC file
  OggFlac = ll::TAGLIB_FILE_OGG_FLAC as isize,
  /// WavPack file
  WavPack = ll::TAGLIB_FILE_WAV_PACK as isize,
  /// Ogg/Speex file
  Speex = ll::TAGLIB_FILE_SPEEX as isize,
  /// TrueAudio file
  TrueAudio = ll::TAGLIB_FILE_TRUE_AUDIO as isize,
  /// MP4 file
  MP4 = ll::TAGLIB_FILE_MP4 as isize,
  /// ASF file
  ASF = ll::TAGLIB_FILE_ASF as isize
}

#[derive(Debug)]
pub enum FileError {
  /// The file is an invalid or an unrecognized audio container
  InvalidFile,
  /// The file name is invalid
  InvalidFileName,
  /// No meta-data is available
  NoAvailableTag,
  /// No audio properties are available
  NoAvailableAudioProperties
}

/// A representation of an audio file, with meta-data and properties.
pub struct File {
  raw: *mut ll::TagLib_File,
}

impl Drop for File {
  fn drop(&mut self) {
    unsafe { ll::taglib_file_free(self.raw); }
  }
}

impl File {
  /// Creates a new `taglib::File` for the given `filename`.
  pub fn new(filename: &str) -> Result<File, FileError> {
    let filename_c =
      match CString::new(filename) {
        Ok(s) => s.as_ptr(),
        _ => return Err(FileError::InvalidFileName)
      };

    let f = unsafe { ll::taglib_file_new(filename_c) };
    if f.is_null() {
      return Err(FileError::InvalidFile);
    }

    Ok(File { raw: f })
  }

  /// Returns the `taglib::Tag` instance for the given file.
  pub fn tag(&self) -> Result<Tag, FileError> {
    let res = unsafe { ll::taglib_file_tag(self.raw) };

    if res.is_null() {
      Err(FileError::NoAvailableTag)
    }
    else {
      Ok(Tag { raw: res })
    }
  }

  /// Returns whether the file is valid.
  pub fn is_valid(&self) -> bool {
    unsafe { ll::taglib_file_is_valid(self.raw) != 0 }
  }

  /// Returns the `taglib::AudioProperties` instance for the given file.
  pub fn audioproperties(&self) -> Result<AudioProperties, FileError> {
    let res = unsafe { ll::taglib_file_audioproperties(self.raw) };

    if res.is_null() {
      Err(FileError::NoAvailableAudioProperties)
    }
    else {
      Ok(AudioProperties { raw: res })
    }
  }

  /// Updates the meta-data of the file.
  pub fn save(&self) -> bool {
    unsafe { ll::taglib_file_save(self.raw) != 0 }
  }
}

/// Enables or disables the Unicode string management.
pub fn set_strings_unicode(value: bool) {
  unsafe { ll::taglib_set_strings_unicode(value as ll::TagLib_Bool); }
}
<commit_msg>Remove unnecessary import<commit_after>#![allow(non_camel_case_types)]

extern crate libc;

use libc::{c_char};
use std::ffi::{CString, CStr};

pub mod taglib_sys;

use taglib_sys as ll;

fn c_str_to_str(c_str: *const c_char) -> String {
  if c_str.is_null() {
    String::new()
  }
  else {
    let bytes = unsafe { CStr::from_ptr(c_str).to_bytes() };
    String::from_utf8_lossy(bytes).to_string()
  }
}

/// The abstract meta-data container for audio files
///
/// Each `Tag` instance can only be created by the `taglib::File::tag()`
/// method.
pub struct Tag {
  raw: *mut ll::TagLib_Tag,
}

impl Drop for Tag {
  fn drop(&mut self) {
    unsafe { ll::taglib_tag_free_strings() }
  }
}

impl Tag {
  /// Returns the track name, or an empty string if no track name is present.
  pub fn title(&self) -> String {
    let res = unsafe { ll::taglib_tag_title(self.raw) };
    c_str_to_str(res)
  }

  /// Sets the track name.
  pub fn set_title(&mut self, title: &str) {
    let s = CString::new(title).unwrap().as_ptr();
    unsafe { ll::taglib_tag_set_title(self.raw, s); }
  }

  /// Returns the artist name, or an empty string if no artist name is present.
  pub fn artist(&self) -> String {
    let res = unsafe { ll::taglib_tag_artist(self.raw) };
    c_str_to_str(res)
  }

  /// Sets the artist name.
  pub fn set_artist(&mut self, artist: &str) {
    let s = CString::new(artist).unwrap().as_ptr();
    unsafe { ll::taglib_tag_set_artist(self.raw, s); }
  }

  /// Returns the album name, or an empty string if no album name is present.
  pub fn album(&self) -> String {
    let res = unsafe { ll::taglib_tag_album(self.raw) };
    c_str_to_str(res)
  }

  /// Sets the album name.
  pub fn set_album(&mut self, album: &str) {
    let s = CString::new(album).unwrap().as_ptr();
    unsafe { ll::taglib_tag_set_album(self.raw, s); }
  }

  /// Returns the track comment, or an empty string if no track comment is
  /// present.
  pub fn comment(&self) -> String {
    let res = unsafe { ll::taglib_tag_comment(self.raw) };
    c_str_to_str(res)
  }

  /// Sets the track comment.
  pub fn set_comment(&mut self, comment: &str) {
    let s = CString::new(comment).unwrap().as_ptr();
    unsafe { ll::taglib_tag_set_comment(self.raw, s); }
  }

  /// Returns the genre name, or an empty string if no genre name is present.
  pub fn genre(&self) -> String {
    let res = unsafe { ll::taglib_tag_genre(self.raw) };
    c_str_to_str(res)
  }

  /// Sets the genre name.
  pub fn set_genre(&mut self, genre: &str) {
    let s = CString::new(genre).unwrap().as_ptr();
    unsafe { ll::taglib_tag_set_genre(self.raw, s); }
  }

  /// Returns the year, or 0 if no year is present.
  pub fn year(&self) -> u32 {
    unsafe { ll::taglib_tag_year(self.raw) as u32 }
  }

  /// Sets the year.
  pub fn set_year(&mut self, year: u32) {
    unsafe { ll::taglib_tag_set_year(self.raw, year); }
  }

  /// Returns the track number, or 0 if no track number is present.
  pub fn track(&self) -> u32 {
    unsafe { ll::taglib_tag_track(self.raw) as u32 }
  }

  /// Sets the track number.
  pub fn set_track(&mut self, track: u32) {
    unsafe { ll::taglib_tag_set_track(self.raw, track); }
  }
}

/// Common audio file properties.
///
/// Instances of `AudioProperties` can only be created through the
/// `taglib::File::audioproperties()` method.
pub struct AudioProperties {
  raw: *const ll::TagLib_AudioProperties,
}

impl AudioProperties {
  /// Returns the length, in seconds, of the track.
  pub fn length(&self) -> u32 {
    unsafe { ll::taglib_audioproperties_length(self.raw) as u32 }
  }

  /// Returns the most appropriate bit rate for the track, in kB/s.
  /// For constant bit rate formats, the returned value is the bit
  /// rate of the file; for variable bit rate formats this is either
  /// the average or the nominal bit rate.
  pub fn bitrate(&self) -> u32 {
    unsafe { ll::taglib_audioproperties_bitrate(self.raw) as u32 }
  }

  /// Returns the sample rate, in Hz.
  pub fn samplerate(&self) -> u32 {
    unsafe { ll::taglib_audioproperties_samplerate(self.raw) as u32 }
  }

  /// Returns the number of audio channels.
  pub fn channels(&self) -> u32 {
    unsafe { ll::taglib_audioproperties_channels(self.raw) as u32 }
  }
}

#[derive(Copy, Clone, PartialEq)]
pub enum FileType {
  /// MPEG file
  MPEG = ll::TAGLIB_FILE_MPEG as isize,
  /// Ogg/Vorbis file
  OggVorbis = ll::TAGLIB_FILE_OGG_VORBIS as isize,
  /// FLAC file
  FLAC = ll::TAGLIB_FILE_FLAC as isize,
  /// MPC file
  MPC = ll::TAGLIB_FILE_MPC as isize,
  /// Ogg/FLAC file
  OggFlac = ll::TAGLIB_FILE_OGG_FLAC as isize,
  /// WavPack file
  WavPack = ll::TAGLIB_FILE_WAV_PACK as isize,
  /// Ogg/Speex file
  Speex = ll::TAGLIB_FILE_SPEEX as isize,
  /// TrueAudio file
  TrueAudio = ll::TAGLIB_FILE_TRUE_AUDIO as isize,
  /// MP4 file
  MP4 = ll::TAGLIB_FILE_MP4 as isize,
  /// ASF file
  ASF = ll::TAGLIB_FILE_ASF as isize
}

#[derive(Debug)]
pub enum FileError {
  /// The file is an invalid or an unrecognized audio container
  InvalidFile,
  /// The file name is invalid
  InvalidFileName,
  /// No meta-data is available
  NoAvailableTag,
  /// No audio properties are available
  NoAvailableAudioProperties
}

/// A representation of an audio file, with meta-data and properties.
pub struct File {
  raw: *mut ll::TagLib_File,
}

impl Drop for File {
  fn drop(&mut self) {
    unsafe { ll::taglib_file_free(self.raw); }
  }
}

impl File {
  /// Creates a new `taglib::File` for the given `filename`.
  pub fn new(filename: &str) -> Result<File, FileError> {
    let filename_c =
      match CString::new(filename) {
        Ok(s) => s.as_ptr(),
        _ => return Err(FileError::InvalidFileName)
      };

    let f = unsafe { ll::taglib_file_new(filename_c) };
    if f.is_null() {
      return Err(FileError::InvalidFile);
    }

    Ok(File { raw: f })
  }

  /// Returns the `taglib::Tag` instance for the given file.
  pub fn tag(&self) -> Result<Tag, FileError> {
    let res = unsafe { ll::taglib_file_tag(self.raw) };

    if res.is_null() {
      Err(FileError::NoAvailableTag)
    }
    else {
      Ok(Tag { raw: res })
    }
  }

  /// Returns whether the file is valid.
  pub fn is_valid(&self) -> bool {
    unsafe { ll::taglib_file_is_valid(self.raw) != 0 }
  }

  /// Returns the `taglib::AudioProperties` instance for the given file.
  pub fn audioproperties(&self) -> Result<AudioProperties, FileError> {
    let res = unsafe { ll::taglib_file_audioproperties(self.raw) };

    if res.is_null() {
      Err(FileError::NoAvailableAudioProperties)
    }
    else {
      Ok(AudioProperties { raw: res })
    }
  }

  /// Updates the meta-data of the file.
  pub fn save(&self) -> bool {
    unsafe { ll::taglib_file_save(self.raw) != 0 }
  }
}

/// Enables or disables the Unicode string management.
pub fn set_strings_unicode(value: bool) {
  unsafe { ll::taglib_set_strings_unicode(value as ll::TagLib_Bool); }
}
<|endoftext|>


<commit_before>use std::os;

/// Probe the system for the directory in which CA certificates should likely be
/// found.
///
/// This will only search known system locations.
pub fn find_certs_dir() -> Option<Path> {
    // see http://gagravarr.org/writing/openssl-certs/others.shtml
    [
        "/var/ssl",
        "/usr/share/ssl",
        "/usr/local/ssl",
        "/usr/local/openssl",
        "/usr/lib/ssl",
        "/usr/ssl",
        "/etc/openssl",
        "/etc/pki/tls",
        "/etc/ssl",
    ].iter().map(|s| Path::new(*s)).find(|p| {
        p.exists()
    })
}

pub fn init_ssl_cert_env_vars() {
    let certs_dir = match find_certs_dir() {
        Some(path) => path,
        None => return,
    };

    if certs_dir.join("cert.pem").exists() {
        match os::getenv("SSL_CERT_FILE") {
            // Someone else has already got this, they probably know what
            // they're doing more than we do
            Some(..) => {}

            None => os::setenv("SSL_CERT_FILE", certs_dir.join("cert.pem")),
        }
    }

    if certs_dir.join("certs").exists() {
        match os::getenv("SSL_CERT_DIR") {
            Some(..) => {}
            None => os::setenv("SSL_CERT_DIR", certs_dir.join("certs")),
        }
    }
}
<commit_msg>Update to master<commit_after>use std::os;
use std::io::fs::PathExtensions;

/// Probe the system for the directory in which CA certificates should likely be
/// found.
///
/// This will only search known system locations.
pub fn find_certs_dir() -> Option<Path> {
    // see http://gagravarr.org/writing/openssl-certs/others.shtml
    [
        "/var/ssl",
        "/usr/share/ssl",
        "/usr/local/ssl",
        "/usr/local/openssl",
        "/usr/lib/ssl",
        "/usr/ssl",
        "/etc/openssl",
        "/etc/pki/tls",
        "/etc/ssl",
    ].iter().map(|s| Path::new(*s)).find(|p| {
        p.exists()
    })
}

pub fn init_ssl_cert_env_vars() {
    let certs_dir = match find_certs_dir() {
        Some(path) => path,
        None => return,
    };

    if certs_dir.join("cert.pem").exists() {
        match os::getenv("SSL_CERT_FILE") {
            // Someone else has already got this, they probably know what
            // they're doing more than we do
            Some(..) => {}

            None => os::setenv("SSL_CERT_FILE", certs_dir.join("cert.pem")),
        }
    }

    if certs_dir.join("certs").exists() {
        match os::getenv("SSL_CERT_DIR") {
            Some(..) => {}
            None => os::setenv("SSL_CERT_DIR", certs_dir.join("certs")),
        }
    }
}
<|endoftext|>


<commit_before>#![feature(fn_traits, get_type_id, unboxed_closures)]

//! Mocking framework for Rust (currently only nightly)
//!
//! ```
//! #[mockable]
//! mod hello_world {
//!     pub fn world() -> &'static str {
//!         "world"
//!     }
//!
//!     pub fn hello_world() -> String {
//!         format!("Hello {}!", world())
//!     }
//! }
//!
//! #[test]
//! fn mock_test() {
//!     hello_world::world.mock_safe(|| MockResult::Return("mocking"));
//!
//!     assert_eq!("Hello mocking!", hello_world::hello_world());
//! }
//! ```
//! # Introduction
//! This is a user guide showing Rust project set up for testing with mocks.
//!
//! It is highly recommended to **use mocks ONLY for test runs and NEVER in release builds!**
//! Mocktopus is not designed for high performance and will slow down code execution.
//!
//! Note: this guide shows set up of mocking for test builds only.
//! # Prerequisites
//! Add Mocktopus dev-dependency to project's `Cargo.toml`:
//!
//! ```
//! [dev-dependencies]
//! mocktopus = "0.1.0"
//! ```
//! Enable procedural macros in crate root:
//!
//! ```
//! #![cfg_attr(test, feature(proc_macro_mod))]
//! ```
//! Import Mocktopus:
//!
//! ```
//! #[cfg(test)]
//! extern crate mocktopus;
//! ```
//! # Making functions mockable
//! To make functions mockable they must be annotated with provided procedural macros.
//! See [documentation](https://docs.rs/mocktopus_macros) for all their possibilities and rules.
//!
//! To use these macros import them into namespace:
//!
//! ```
//! #[cfg(test)]
//! use mocktopus::macros::*;
//! ```
//! It is possible to annotate modules, which makes all their potentially mockable content mockable.
//! To make every function in project mockable annotate each module in its root:
//!
//! ```
//! #[cfg_attr(test, mockable)]
//! mod my_module;
//! ```
//! # Mocking
//! Import tools for mocking in test module:
//!
//! ```
//! #[cfg(test)]
//! mod tests {
//!     use mocktopus::mocking::*;
//! ```
//! Among others this imports trait `Mockable`.
//! It is implemented for all functions and provides an interface for setting up mocks:
//!
//! ```
//! #[test]
//! fn my_test() {
//!     my_function.mock_safe(|| MockResult::Return(1));
//!
//!     assert_eq!(1, my_function());
//! }
//! ```
//! It is also possible to mock struct methods, either from own impls, traits or trait defaults:
//!
//! ```
//! // Mocking method
//! MyStruct::my_method.mock_safe(|| MockResult::Return(1));
//! // Mocking trait method
//! MyStruct::my_trait_method.mock_safe(|| MockResult::Return(2));
//! // Mocking default trait method
//! MyStruct::my_trait_default_method.mock_safe(|| MockResult::Return(3));
//! ```
//! Mocking with `mock_safe` is simplest, but the `Mockable` trait has more,
//! see [documantation](mocking/trait.Mockable.html).
//!
//! ## Mocking range
//! Every mock works only in thread, in which it was set.
//! All Rust test runs are executed in independent threads, so mocks do not leak between them:
//!
//! ```
//! #[cfg_attr(test, mockable)]
//! fn common_fn() -> u32 {
//!     0
//! }
//!
//! #[test]
//! fn common_fn_test_1() {
//!     assert_eq!(0, common_fn());
//!
//!     common_fn.mock_safe(|| MockResult::Return(1));
//!
//!     assert_eq!(1, common_fn());
//! }
//!
//! #[test]
//! fn common_fn_test_2() {
//!     assert_eq!(0, common_fn());
//!
//!     common_fn.mock_safe(|| MockResult::Return(2));
//!
//!     assert_eq!(2, common_fn());
//! }
//! ```
//!
//! ## Mock closure
//! `mock_safe` has single argument: a closure, which takes same input as mocked function and returns a `MockResult`.
//! Whenever the mocked function is called, its inputs are passed to the closure:
//!
//! ```
//! #[cfg_attr(test, mockable)]
//! fn my_function_1(_: u32) {
//!     return
//! }
//!
//! #[test]
//! fn my_function_1_test() {
//!     my_function_1.mock_safe(|x| {
//!         assert_eq!(2, x);
//!         MockResult::Return(())
//!     });
//!
//!     my_function_1(2); // Passes
//!     my_function_1(3); // Panics
//! }
//! ```
//! If the closure returns `MockResult::Return`, the mocked function does not run.
//! It immediately returns with a value, which is passed inside `MockResult::Return`:
//!
//! ```
//! #[cfg_attr(test, mockable)]
//! fn my_function_2() -> u32 {
//!     unreachable!()
//! }
//!
//! #[test]
//! fn my_function_2_test() {
//!     my_function_2.mock_safe(|| MockResult::Return(3));
//!
//!     assert_eq!(3, my_function_2());
//! }
//! ```
//! If the closure returns `MockResult::Continue`, the mocked function runs normally, but with changed arguments.
//! The new arguments are returned from closure in tuple inside `MockResult::Continue`:
//!
//! ```
//! #[cfg_attr(test, mockable)]
//! fn my_function_3(x: u32, y: u32) -> u32 {
//!     x + y
//! }
//!
//! #[test]
//! fn my_function_3_test() {
//!     my_function_3.mock_safe(|x, y| MockResult::Continue((x, y + 1)));
//!
//!     assert_eq!(3, my_function_3(1, 1));
//! }
//! ```
//!
//! ##Mocking generics
//! When mocking generic functions, all its generics must be defined and only this variant will be affected:
//!
//! ```
//! #[cfg_attr(test, mockable)]
//! fn generic_fn<T: Display>(t: T) -> String {
//!     t.to_string()
//! }
//!
//! #[test]
//! fn generic_fn_test() {
//!     generic_fn::<u32>.mock_safe(|_| MockResult::Return("mocked".to_string()));
//!
//!     assert_eq!("1", generic_fn(1i32));
//!     assert_eq!("mocked", generic_fn(1u32));
//! }
//! ```
//! The only exception are lifetimes, they are ignored:
//!
//! ```
//! #[cfg_attr(test, mockable)]
//! fn lifetime_generic_fn<'a>(string: &'a String) -> &'a str {
//!     string.as_ref()
//! }
//!
//! #[test]
//! fn lifetime_generic_fn_test() {
//!     lifetime_generic_fn.mock_safe(|_| MockResult::Return("mocked"));
//!
//!     assert_eq!("mocked", lifetime_generic_fn(&"not mocked".to_string()));
//! }
//! ```
//! Same rules apply to methods and structures:
//!
//! ```
//! struct GenericStruct<'a, T: Display + 'a>(&'a T);
//!
//! #[cfg_attr(test, mockable)]
//! impl<'a, T: Display + 'a> GenericStruct<'a, T> {
//!     fn to_string(&self) -> String {
//!         self.0.to_string()
//!     }
//! }
//!
//! static VALUE: u32 = 1;
//!
//! #[test]
//! fn lifetime_generic_fn_test() {
//!     GenericStruct::<u32>::to_string.mock_safe(|_| MockResult::Return("mocked".to_string()));
//!
//!     assert_eq!("mocked", GenericStruct(&VALUE).to_string());
//!     assert_eq!("mocked", GenericStruct(&2u32).to_string());
//!     assert_eq!("2", GenericStruct(&2i32).to_string());
//! }
//! ```
#![doc(html_logo_url = "https://raw.githubusercontent.com/CodeSandwich/mocktopus/master/logo.png",
    html_favicon_url = "https://raw.githubusercontent.com/CodeSandwich/mocktopus/master/logo.png")]

extern crate mocktopus_macros;

/// For use in testing code: mocking tools
pub mod mocking;

/// For use in testing code: helper tools for writing tests using mocking
pub mod mocking_utils;

/// For use in tested code: tools making items mockable
pub mod macros {
    pub use mocktopus_macros::*;
}

<commit_msg>lib: Update documentation example for proc_macro_mod inclusion?<commit_after>#![feature(fn_traits, get_type_id, unboxed_closures)]

//! Mocking framework for Rust (currently only nightly)
//!
//! ```
//! #[mockable]
//! mod hello_world {
//!     pub fn world() -> &'static str {
//!         "world"
//!     }
//!
//!     pub fn hello_world() -> String {
//!         format!("Hello {}!", world())
//!     }
//! }
//!
//! #[test]
//! fn mock_test() {
//!     hello_world::world.mock_safe(|| MockResult::Return("mocking"));
//!
//!     assert_eq!("Hello mocking!", hello_world::hello_world());
//! }
//! ```
//! # Introduction
//! This is a user guide showing Rust project set up for testing with mocks.
//!
//! It is highly recommended to **use mocks ONLY for test runs and NEVER in release builds!**
//! Mocktopus is not designed for high performance and will slow down code execution.
//!
//! Note: this guide shows set up of mocking for test builds only.
//! # Prerequisites
//! Add Mocktopus dev-dependency to project's `Cargo.toml`:
//!
//! ```
//! [dev-dependencies]
//! mocktopus = "0.1.0"
//! ```
//! Enable procedural macros in crate root:
//!
//! ```
//! #![cfg_attr(test, feature(proc_macro_hygiene))]
//! ```
//! Import Mocktopus:
//!
//! ```
//! #[cfg(test)]
//! extern crate mocktopus;
//! ```
//! # Making functions mockable
//! To make functions mockable they must be annotated with provided procedural macros.
//! See [documentation](https://docs.rs/mocktopus_macros) for all their possibilities and rules.
//!
//! To use these macros import them into namespace:
//!
//! ```
//! #[cfg(test)]
//! use mocktopus::macros::*;
//! ```
//! It is possible to annotate modules, which makes all their potentially mockable content mockable.
//! To make every function in project mockable annotate each module in its root:
//!
//! ```
//! #[cfg_attr(test, mockable)]
//! mod my_module;
//! ```
//! # Mocking
//! Import tools for mocking in test module:
//!
//! ```
//! #[cfg(test)]
//! mod tests {
//!     use mocktopus::mocking::*;
//! ```
//! Among others this imports trait `Mockable`.
//! It is implemented for all functions and provides an interface for setting up mocks:
//!
//! ```
//! #[test]
//! fn my_test() {
//!     my_function.mock_safe(|| MockResult::Return(1));
//!
//!     assert_eq!(1, my_function());
//! }
//! ```
//! It is also possible to mock struct methods, either from own impls, traits or trait defaults:
//!
//! ```
//! // Mocking method
//! MyStruct::my_method.mock_safe(|| MockResult::Return(1));
//! // Mocking trait method
//! MyStruct::my_trait_method.mock_safe(|| MockResult::Return(2));
//! // Mocking default trait method
//! MyStruct::my_trait_default_method.mock_safe(|| MockResult::Return(3));
//! ```
//! Mocking with `mock_safe` is simplest, but the `Mockable` trait has more,
//! see [documantation](mocking/trait.Mockable.html).
//!
//! ## Mocking range
//! Every mock works only in thread, in which it was set.
//! All Rust test runs are executed in independent threads, so mocks do not leak between them:
//!
//! ```
//! #[cfg_attr(test, mockable)]
//! fn common_fn() -> u32 {
//!     0
//! }
//!
//! #[test]
//! fn common_fn_test_1() {
//!     assert_eq!(0, common_fn());
//!
//!     common_fn.mock_safe(|| MockResult::Return(1));
//!
//!     assert_eq!(1, common_fn());
//! }
//!
//! #[test]
//! fn common_fn_test_2() {
//!     assert_eq!(0, common_fn());
//!
//!     common_fn.mock_safe(|| MockResult::Return(2));
//!
//!     assert_eq!(2, common_fn());
//! }
//! ```
//!
//! ## Mock closure
//! `mock_safe` has single argument: a closure, which takes same input as mocked function and returns a `MockResult`.
//! Whenever the mocked function is called, its inputs are passed to the closure:
//!
//! ```
//! #[cfg_attr(test, mockable)]
//! fn my_function_1(_: u32) {
//!     return
//! }
//!
//! #[test]
//! fn my_function_1_test() {
//!     my_function_1.mock_safe(|x| {
//!         assert_eq!(2, x);
//!         MockResult::Return(())
//!     });
//!
//!     my_function_1(2); // Passes
//!     my_function_1(3); // Panics
//! }
//! ```
//! If the closure returns `MockResult::Return`, the mocked function does not run.
//! It immediately returns with a value, which is passed inside `MockResult::Return`:
//!
//! ```
//! #[cfg_attr(test, mockable)]
//! fn my_function_2() -> u32 {
//!     unreachable!()
//! }
//!
//! #[test]
//! fn my_function_2_test() {
//!     my_function_2.mock_safe(|| MockResult::Return(3));
//!
//!     assert_eq!(3, my_function_2());
//! }
//! ```
//! If the closure returns `MockResult::Continue`, the mocked function runs normally, but with changed arguments.
//! The new arguments are returned from closure in tuple inside `MockResult::Continue`:
//!
//! ```
//! #[cfg_attr(test, mockable)]
//! fn my_function_3(x: u32, y: u32) -> u32 {
//!     x + y
//! }
//!
//! #[test]
//! fn my_function_3_test() {
//!     my_function_3.mock_safe(|x, y| MockResult::Continue((x, y + 1)));
//!
//!     assert_eq!(3, my_function_3(1, 1));
//! }
//! ```
//!
//! ##Mocking generics
//! When mocking generic functions, all its generics must be defined and only this variant will be affected:
//!
//! ```
//! #[cfg_attr(test, mockable)]
//! fn generic_fn<T: Display>(t: T) -> String {
//!     t.to_string()
//! }
//!
//! #[test]
//! fn generic_fn_test() {
//!     generic_fn::<u32>.mock_safe(|_| MockResult::Return("mocked".to_string()));
//!
//!     assert_eq!("1", generic_fn(1i32));
//!     assert_eq!("mocked", generic_fn(1u32));
//! }
//! ```
//! The only exception are lifetimes, they are ignored:
//!
//! ```
//! #[cfg_attr(test, mockable)]
//! fn lifetime_generic_fn<'a>(string: &'a String) -> &'a str {
//!     string.as_ref()
//! }
//!
//! #[test]
//! fn lifetime_generic_fn_test() {
//!     lifetime_generic_fn.mock_safe(|_| MockResult::Return("mocked"));
//!
//!     assert_eq!("mocked", lifetime_generic_fn(&"not mocked".to_string()));
//! }
//! ```
//! Same rules apply to methods and structures:
//!
//! ```
//! struct GenericStruct<'a, T: Display + 'a>(&'a T);
//!
//! #[cfg_attr(test, mockable)]
//! impl<'a, T: Display + 'a> GenericStruct<'a, T> {
//!     fn to_string(&self) -> String {
//!         self.0.to_string()
//!     }
//! }
//!
//! static VALUE: u32 = 1;
//!
//! #[test]
//! fn lifetime_generic_fn_test() {
//!     GenericStruct::<u32>::to_string.mock_safe(|_| MockResult::Return("mocked".to_string()));
//!
//!     assert_eq!("mocked", GenericStruct(&VALUE).to_string());
//!     assert_eq!("mocked", GenericStruct(&2u32).to_string());
//!     assert_eq!("2", GenericStruct(&2i32).to_string());
//! }
//! ```
#![doc(html_logo_url = "https://raw.githubusercontent.com/CodeSandwich/mocktopus/master/logo.png",
    html_favicon_url = "https://raw.githubusercontent.com/CodeSandwich/mocktopus/master/logo.png")]

extern crate mocktopus_macros;

/// For use in testing code: mocking tools
pub mod mocking;

/// For use in testing code: helper tools for writing tests using mocking
pub mod mocking_utils;

/// For use in tested code: tools making items mockable
pub mod macros {
    pub use mocktopus_macros::*;
}

<|endoftext|>


<commit_before>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not
// distributed with this file, You can
// obtain one at
// http://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible
// With Secondary Licenses", as defined by
// the Mozilla Public License, v. 2.0.

extern crate libc;
extern crate errno;

use std::result::Result;
use std::os::unix::io::RawFd;

use errno::errno;
use libc::c_int;
use libc::consts::os::posix88;

use util::*;
mod util;

/// Represents the result of calling epoll_create1
pub type CreateResult = Result<RawFd, CreateError>;

/// Represents the result of calling epoll_ctrl
pub type CtlResult = Result<(), CtlError>;

/// Represents the result of calling epoll_wait
pub type WaitResult = Result<u32, WaitError>;

#[cfg(target_arch = "x86_64")]
#[repr(C, packed)]
pub struct EpollEvent {
    events: u32,
    data: u64
}

#[cfg(not(target_arch = "x86_64"))]
#[repr(C)]
pub struct EpollEvent {
    events: u32,
    data: u64
}

extern "C" {
    fn epoll_create1(flags: c_int) -> c_int;
    fn epoll_ctl(epfd: c_int, op: c_int, fd: c_int,
        event: *const EpollEvent) -> c_int;
    fn epoll_wait(epfd: c_int, event: *mut EpollEvent,
        maxevents: c_int, timeout: c_int) -> c_int;
}

/// Attempts to create a new epoll instance
#[inline]
pub fn create1(flags: u32) -> CreateResult {
    let mut epoll_fd;
    unsafe {
        epoll_fd = epoll_create1(flags as c_int);
    }

    if epoll_fd == -1 {
        let errno = errno().0 as i32;
        return match errno {
            posix88::EINVAL     => Err(CreateError::EINVAL),
            posix88::EMFILE     => Err(CreateError::EMFILE),
            posix88::ENFILE     => Err(CreateError::ENFILE),
            posix88::ENOMEM     => Err(CreateError::ENOMEM),
            _ => panic!("Unexpected errno: {}", errno)
        }
    }

    Ok(epoll_fd)
}

/// Calls epoll_ctl(2) with supplied params
#[inline]
pub fn ctl(epoll_fd: RawFd, op: CtlOp,
           socket_fd: RawFd, event: Box<EpollEvent>) -> CtlResult {
    let mut x;
    unsafe {
        x = epoll_ctl(epoll_fd as c_int,
            op as c_int,
            socket_fd as c_int,
            &*event);
    }

    if x == -1 {
        let errno = errno().0 as i32;
        return match errno {
            posix88::EBADF      => Err(CtlError::EBADF),
            posix88::EEXIST     => Err(CtlError::EEXIST),
            posix88::EINVAL     => Err(CtlError::EINVAL),
            posix88::ENOENT     => Err(CtlError::ENOENT),
            posix88::ENOSPC     => Err(CtlError::ENOSPC),
            posix88::EPERM      => Err(CtlError::EPERM),
            _ => panic!("Unexpected errno: {}", errno)
        }
    }

    Ok(())
}

/// Calls epoll_wait(1) with supplied params
#[inline]
pub fn wait(epoll_fd: RawFd, events: &mut [EpollEvent],
    timeout: u32) -> WaitResult {

    let mut num_fds_ready;
    unsafe {
        num_fds_ready = epoll_wait(epoll_fd as c_int,
            events.as_mut_ptr(),
            events.len() as c_int,
            timeout as c_int);
    }

    if num_fds_ready == -1 {
        let errno = errno().0 as i32;
        return match errno {
            posix88::EBADF  => Err(WaitError::EBADF),
            posix88::EFAULT => Err(WaitError::EFAULT),
            posix88::EINTR  => Err(WaitError::EINTR),
            posix88::EINVAL => Err(WaitError::EINVAL),
            _ => panic!("Unexpected errno: {}", errno)
        }
    }

    Ok(num_fds_ready as u32)
}
<commit_msg>Debugging<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v.
// 2.0. If a copy of the MPL was not
// distributed with this file, You can
// obtain one at
// http://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible
// With Secondary Licenses", as defined by
// the Mozilla Public License, v. 2.0.

extern crate libc;
extern crate errno;

use std::result::Result;
use std::os::unix::io::RawFd;

use errno::errno;
use libc::c_int;
use libc::consts::os::posix88;

use util::*;
mod util;

/// Represents the result of calling epoll_create1
pub type CreateResult = Result<RawFd, CreateError>;

/// Represents the result of calling epoll_ctrl
pub type CtlResult = Result<(), CtlError>;

/// Represents the result of calling epoll_wait
pub type WaitResult = Result<u32, WaitError>;

#[cfg(target_arch = "x86_64")]
#[repr(C, packed)]
pub struct EpollEvent {
    events: u32,
    data: u64
}

#[cfg(not(target_arch = "x86_64"))]
#[repr(C)]
pub struct EpollEvent {
    events: u32,
    data: u64
}

extern "C" {
    fn epoll_create1(flags: c_int) -> c_int;
    fn epoll_ctl(epfd: c_int, op: c_int, fd: c_int,
        event: *const EpollEvent) -> c_int;
    fn epoll_wait(epfd: c_int, event: *mut EpollEvent,
        maxevents: c_int, timeout: c_int) -> c_int;
}

/// Attempts to create a new epoll instance
#[inline]
pub fn create1(flags: u32) -> CreateResult {
    let mut epoll_fd;
    unsafe {
        epoll_fd = epoll_create1(flags as c_int);
    }

    if epoll_fd == -1 {
        let errno = errno().0 as i32;
        return match errno {
            posix88::EINVAL     => Err(CreateError::EINVAL),
            posix88::EMFILE     => Err(CreateError::EMFILE),
            posix88::ENFILE     => Err(CreateError::ENFILE),
            posix88::ENOMEM     => Err(CreateError::ENOMEM),
            _ => panic!("Unexpected errno: {}", errno)
        }
    }

    Ok(epoll_fd)
}

/// Calls epoll_ctl(2) with supplied params
#[inline]
pub fn ctl(epoll_fd: RawFd, op: CtlOp,
           socket_fd: RawFd, event: Box<EpollEvent>) -> CtlResult {
    let mut x;
    unsafe {
        x = epoll_ctl(epoll_fd as c_int,
            op as c_int,
            socket_fd as c_int,
            &*event);
    }

    if x == -1 {
        let errno = errno().0 as i32;
        return match errno {
            posix88::EBADF      => Err(CtlError::EBADF),
            posix88::EEXIST     => Err(CtlError::EEXIST),
            posix88::EINVAL     => Err(CtlError::EINVAL),
            posix88::ENOENT     => Err(CtlError::ENOENT),
            posix88::ENOSPC     => Err(CtlError::ENOSPC),
            posix88::EPERM      => Err(CtlError::EPERM),
            _ => panic!("Unexpected errno: {}", errno)
        }
    }

    Ok(())
}

/// Calls epoll_wait(1) with supplied params
#[inline]
pub fn wait(epoll_fd: RawFd, events: &mut [EpollEvent],
    timeout: u32) -> WaitResult {

    println!("events.len(): {}", events.len());

    let mut num_fds_ready;
    unsafe {
        num_fds_ready = epoll_wait(epoll_fd as c_int,
            events.as_mut_ptr(),
            events.len() as c_int,
            timeout as c_int);
    }

    if num_fds_ready == -1 {
        let errno = errno().0 as i32;
        return match errno {
            posix88::EBADF  => Err(WaitError::EBADF),
            posix88::EFAULT => Err(WaitError::EFAULT),
            posix88::EINTR  => Err(WaitError::EINTR),
            posix88::EINVAL => Err(WaitError::EINVAL),
            _ => panic!("Unexpected errno: {}", errno)
        }
    }

    Ok(num_fds_ready as u32)
}
<|endoftext|>


<commit_before>#![feature(rustc_private, never_type, decl_macro)]
#![allow(intra_doc_link_resolution_failure)]

extern crate flate2;
extern crate tempfile;
extern crate rustc;
extern crate rustc_codegen_ssa;
extern crate rustc_codegen_utils;
extern crate rustc_data_structures;
extern crate rustc_driver;
extern crate rustc_fs_util;
extern crate rustc_incremental;
extern crate rustc_mir;
extern crate rustc_target;
extern crate syntax;

use std::any::Any;
use std::sync::mpsc;

use rustc::dep_graph::DepGraph;
use rustc::middle::cstore::{EncodedMetadata, MetadataLoader};
use rustc::session::config::OutputFilenames;
use rustc::ty::query::Providers;
use rustc::util::common::ErrorReported;
use rustc_codegen_utils::codegen_backend::CodegenBackend;

use cranelift::codegen::settings;

use crate::constant::ConstantCx;
use crate::prelude::*;

mod abi;
mod allocator;
mod analyze;
mod archive;
mod base;
mod cast;
mod codegen_i128;
mod common;
mod constant;
mod debuginfo;
mod discriminant;
mod driver;
mod intrinsics;
mod linkage;
mod llvm_intrinsics;
mod main_shim;
mod metadata;
mod num;
mod pretty_clif;
mod target_features_whitelist;
mod trap;
mod unimpl;
mod unsize;
mod value_and_place;
mod vtable;

mod prelude {
    pub use std::any::Any;
    pub use std::collections::{HashMap, HashSet};
    pub use std::convert::{TryFrom, TryInto};

    pub use syntax::ast::{FloatTy, IntTy, UintTy};
    pub use syntax::source_map::{Pos, Span, DUMMY_SP};

    pub use rustc::bug;
    pub use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
    pub use rustc::mir::{self, interpret::AllocId, mono::MonoItem, *};
    pub use rustc::session::{
        config::{CrateType, Lto},
        Session,
    };
    pub use rustc::ty::layout::{self, Abi, LayoutOf, Scalar, Size, TyLayout, VariantIdx};
    pub use rustc::ty::{
        self, FnSig, Instance, InstanceDef, ParamEnv, PolyFnSig, Ty, TyCtxt, TypeAndMut,
        TypeFoldable,
    };
    pub use rustc_data_structures::{
        fx::{FxHashMap, FxHashSet},
        indexed_vec::Idx,
        sync::Lrc,
    };
    pub use rustc_mir::monomorphize::collector;

    pub use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
    pub use rustc_codegen_ssa::traits::*;
    pub use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleKind};

    pub use cranelift::codegen::ir::{
        condcodes::IntCC, function::Function, ExternalName, FuncRef, Inst, SourceLoc, StackSlot,
    };
    pub use cranelift::codegen::isa::CallConv;
    pub use cranelift::codegen::Context;
    pub use cranelift::prelude::*;
    pub use cranelift_module::{
        self, Backend, DataContext, DataId, FuncId, FuncOrDataId, Linkage, Module,
    };

    pub use crate::abi::*;
    pub use crate::base::{trans_operand, trans_place};
    pub use crate::cast::*;
    pub use crate::common::*;
    pub use crate::debuginfo::{DebugContext, FunctionDebugContext};
    pub use crate::trap::*;
    pub use crate::unimpl::{unimpl, with_unimpl_span};
    pub use crate::value_and_place::{CPlace, CPlaceInner, CValue};
    pub use crate::{Caches, CodegenCx};

    pub struct PrintOnPanic<F: Fn() -> String>(pub F);
    impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
        fn drop(&mut self) {
            if ::std::thread::panicking() {
                println!("{}", (self.0)());
            }
        }
    }
}

pub struct Caches<'tcx> {
    pub context: Context,
    pub vtables: HashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), DataId>,
}

impl Default for Caches<'_> {
    fn default() -> Self {
        Caches {
            context: Context::new(),
            vtables: HashMap::new(),
        }
    }
}

pub struct CodegenCx<'clif, 'tcx, B: Backend + 'static> {
    tcx: TyCtxt<'tcx>,
    module: &'clif mut Module<B>,
    constants_cx: ConstantCx,
    caches: Caches<'tcx>,
    debug_context: Option<&'clif mut DebugContext<'tcx>>,
}

impl<'clif, 'tcx, B: Backend + 'static> CodegenCx<'clif, 'tcx, B> {
    fn new(
        tcx: TyCtxt<'tcx>,
        module: &'clif mut Module<B>,
        debug_context: Option<&'clif mut DebugContext<'tcx>>,
    ) -> Self {
        CodegenCx {
            tcx,
            module,
            constants_cx: ConstantCx::default(),
            caches: Caches::default(),
            debug_context,
        }
    }

    fn finalize(self) {
        self.constants_cx.finalize(self.tcx, self.module);
    }
}

struct CraneliftCodegenBackend;

impl CodegenBackend for CraneliftCodegenBackend {
    fn init(&self, _sess: &Session) {}

    fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync> {
        Box::new(crate::metadata::CraneliftMetadataLoader)
    }

    fn provide(&self, providers: &mut Providers) {
        rustc_codegen_utils::symbol_names::provide(providers);
        rustc_codegen_ssa::back::symbol_export::provide(providers);

        providers.target_features_whitelist = |tcx, cnum| {
            assert_eq!(cnum, LOCAL_CRATE);
            if tcx.sess.opts.actually_rustdoc {
                // rustdoc needs to be able to document functions that use all the features, so
                // whitelist them all
                tcx.arena.alloc(
                    target_features_whitelist::all_known_features()
                        .map(|(a, b)| (a.to_string(), b))
                        .collect(),
                )
            } else {
                tcx.arena.alloc(
                    target_features_whitelist::target_feature_whitelist(tcx.sess)
                        .iter()
                        .map(|&(a, b)| (a.to_string(), b))
                        .collect(),
                )
            }
        };
    }
    fn provide_extern(&self, providers: &mut Providers) {
        rustc_codegen_ssa::back::symbol_export::provide_extern(providers);
    }

    fn codegen_crate<'tcx>(
        &self,
        tcx: TyCtxt<'tcx>,
        metadata: EncodedMetadata,
        need_metadata_module: bool,
        _rx: mpsc::Receiver<Box<dyn Any + Send>>,
    ) -> Box<dyn Any> {
        rustc_codegen_utils::check_for_rustc_errors_attr(tcx);

        let res = driver::codegen_crate(tcx, metadata, need_metadata_module);

        rustc_incremental::assert_module_sources::assert_module_sources(tcx);
        rustc_codegen_utils::symbol_names_test::report_symbol_names(tcx);

        res
    }

    fn join_codegen_and_link(
        &self,
        res: Box<dyn Any>,
        sess: &Session,
        _dep_graph: &DepGraph,
        outputs: &OutputFilenames,
    ) -> Result<(), ErrorReported> {
        use rustc_codegen_ssa::back::link::link_binary;

        let codegen_results = *res
            .downcast::<CodegenResults>()
            .expect("Expected CraneliftCodegenBackend's CodegenResult, found Box<Any>");

        let target_cpu = target_triple(sess).to_string();
        link_binary::<crate::archive::ArArchiveBuilder<'_>>(
            sess,
            &codegen_results,
            outputs,
            &codegen_results.crate_name.as_str(),
            &target_cpu,
        );

        Ok(())
    }
}

fn target_triple(sess: &Session) -> target_lexicon::Triple {
    sess.target.target.llvm_target.parse().unwrap()
}

fn build_isa(sess: &Session, enable_pic: bool) -> Box<dyn isa::TargetIsa + 'static> {
    let mut flags_builder = settings::builder();
    if enable_pic {
        flags_builder.enable("is_pic").unwrap();
    } else {
        flags_builder.set("is_pic", "false").unwrap();
    }
    flags_builder.set("probestack_enabled", "false").unwrap(); // __cranelift_probestack is not provided
    flags_builder
        .set(
            "enable_verifier",
            if cfg!(debug_assertions) {
                "true"
            } else {
                "false"
            },
        )
        .unwrap();

    // FIXME(CraneStation/cranelift#732) fix LICM in presence of jump tables
    /*
    use rustc::session::config::OptLevel;
    match sess.opts.optimize {
        OptLevel::No => {
            flags_builder.set("opt_level", "fastest").unwrap();
        }
        OptLevel::Less | OptLevel::Default => {}
        OptLevel::Aggressive => {
            flags_builder.set("opt_level", "best").unwrap();
        }
        OptLevel::Size | OptLevel::SizeMin => {
            sess.warn("Optimizing for size is not supported. Just ignoring the request");
        }
    }*/

    let target_triple = target_triple(sess);
    let flags = settings::Flags::new(flags_builder);
    cranelift::codegen::isa::lookup(target_triple)
        .unwrap()
        .finish(flags)
}

/// This is the entrypoint for a hot plugged rustc_codegen_cranelift
#[no_mangle]
pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
    Box::new(CraneliftCodegenBackend)
}
<commit_msg>Wrap linker invocation in time()<commit_after>#![feature(rustc_private, never_type, decl_macro)]
#![allow(intra_doc_link_resolution_failure)]

extern crate flate2;
extern crate tempfile;
extern crate rustc;
extern crate rustc_codegen_ssa;
extern crate rustc_codegen_utils;
extern crate rustc_data_structures;
extern crate rustc_driver;
extern crate rustc_fs_util;
extern crate rustc_incremental;
extern crate rustc_mir;
extern crate rustc_target;
extern crate syntax;

use std::any::Any;
use std::sync::mpsc;

use rustc::dep_graph::DepGraph;
use rustc::middle::cstore::{EncodedMetadata, MetadataLoader};
use rustc::session::config::OutputFilenames;
use rustc::ty::query::Providers;
use rustc::util::common::ErrorReported;
use rustc_codegen_utils::codegen_backend::CodegenBackend;

use cranelift::codegen::settings;

use crate::constant::ConstantCx;
use crate::prelude::*;

mod abi;
mod allocator;
mod analyze;
mod archive;
mod base;
mod cast;
mod codegen_i128;
mod common;
mod constant;
mod debuginfo;
mod discriminant;
mod driver;
mod intrinsics;
mod linkage;
mod llvm_intrinsics;
mod main_shim;
mod metadata;
mod num;
mod pretty_clif;
mod target_features_whitelist;
mod trap;
mod unimpl;
mod unsize;
mod value_and_place;
mod vtable;

mod prelude {
    pub use std::any::Any;
    pub use std::collections::{HashMap, HashSet};
    pub use std::convert::{TryFrom, TryInto};

    pub use syntax::ast::{FloatTy, IntTy, UintTy};
    pub use syntax::source_map::{Pos, Span, DUMMY_SP};

    pub use rustc::bug;
    pub use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
    pub use rustc::mir::{self, interpret::AllocId, mono::MonoItem, *};
    pub use rustc::session::{
        config::{CrateType, Lto},
        Session,
    };
    pub use rustc::ty::layout::{self, Abi, LayoutOf, Scalar, Size, TyLayout, VariantIdx};
    pub use rustc::ty::{
        self, FnSig, Instance, InstanceDef, ParamEnv, PolyFnSig, Ty, TyCtxt, TypeAndMut,
        TypeFoldable,
    };
    pub use rustc_data_structures::{
        fx::{FxHashMap, FxHashSet},
        indexed_vec::Idx,
        sync::Lrc,
    };
    pub use rustc_mir::monomorphize::collector;

    pub use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
    pub use rustc_codegen_ssa::traits::*;
    pub use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleKind};

    pub use cranelift::codegen::ir::{
        condcodes::IntCC, function::Function, ExternalName, FuncRef, Inst, SourceLoc, StackSlot,
    };
    pub use cranelift::codegen::isa::CallConv;
    pub use cranelift::codegen::Context;
    pub use cranelift::prelude::*;
    pub use cranelift_module::{
        self, Backend, DataContext, DataId, FuncId, FuncOrDataId, Linkage, Module,
    };

    pub use crate::abi::*;
    pub use crate::base::{trans_operand, trans_place};
    pub use crate::cast::*;
    pub use crate::common::*;
    pub use crate::debuginfo::{DebugContext, FunctionDebugContext};
    pub use crate::trap::*;
    pub use crate::unimpl::{unimpl, with_unimpl_span};
    pub use crate::value_and_place::{CPlace, CPlaceInner, CValue};
    pub use crate::{Caches, CodegenCx};

    pub struct PrintOnPanic<F: Fn() -> String>(pub F);
    impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
        fn drop(&mut self) {
            if ::std::thread::panicking() {
                println!("{}", (self.0)());
            }
        }
    }
}

pub struct Caches<'tcx> {
    pub context: Context,
    pub vtables: HashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), DataId>,
}

impl Default for Caches<'_> {
    fn default() -> Self {
        Caches {
            context: Context::new(),
            vtables: HashMap::new(),
        }
    }
}

pub struct CodegenCx<'clif, 'tcx, B: Backend + 'static> {
    tcx: TyCtxt<'tcx>,
    module: &'clif mut Module<B>,
    constants_cx: ConstantCx,
    caches: Caches<'tcx>,
    debug_context: Option<&'clif mut DebugContext<'tcx>>,
}

impl<'clif, 'tcx, B: Backend + 'static> CodegenCx<'clif, 'tcx, B> {
    fn new(
        tcx: TyCtxt<'tcx>,
        module: &'clif mut Module<B>,
        debug_context: Option<&'clif mut DebugContext<'tcx>>,
    ) -> Self {
        CodegenCx {
            tcx,
            module,
            constants_cx: ConstantCx::default(),
            caches: Caches::default(),
            debug_context,
        }
    }

    fn finalize(self) {
        self.constants_cx.finalize(self.tcx, self.module);
    }
}

struct CraneliftCodegenBackend;

impl CodegenBackend for CraneliftCodegenBackend {
    fn init(&self, _sess: &Session) {}

    fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync> {
        Box::new(crate::metadata::CraneliftMetadataLoader)
    }

    fn provide(&self, providers: &mut Providers) {
        rustc_codegen_utils::symbol_names::provide(providers);
        rustc_codegen_ssa::back::symbol_export::provide(providers);

        providers.target_features_whitelist = |tcx, cnum| {
            assert_eq!(cnum, LOCAL_CRATE);
            if tcx.sess.opts.actually_rustdoc {
                // rustdoc needs to be able to document functions that use all the features, so
                // whitelist them all
                tcx.arena.alloc(
                    target_features_whitelist::all_known_features()
                        .map(|(a, b)| (a.to_string(), b))
                        .collect(),
                )
            } else {
                tcx.arena.alloc(
                    target_features_whitelist::target_feature_whitelist(tcx.sess)
                        .iter()
                        .map(|&(a, b)| (a.to_string(), b))
                        .collect(),
                )
            }
        };
    }
    fn provide_extern(&self, providers: &mut Providers) {
        rustc_codegen_ssa::back::symbol_export::provide_extern(providers);
    }

    fn codegen_crate<'tcx>(
        &self,
        tcx: TyCtxt<'tcx>,
        metadata: EncodedMetadata,
        need_metadata_module: bool,
        _rx: mpsc::Receiver<Box<dyn Any + Send>>,
    ) -> Box<dyn Any> {
        rustc_codegen_utils::check_for_rustc_errors_attr(tcx);

        let res = driver::codegen_crate(tcx, metadata, need_metadata_module);

        rustc_incremental::assert_module_sources::assert_module_sources(tcx);
        rustc_codegen_utils::symbol_names_test::report_symbol_names(tcx);

        res
    }

    fn join_codegen_and_link(
        &self,
        res: Box<dyn Any>,
        sess: &Session,
        _dep_graph: &DepGraph,
        outputs: &OutputFilenames,
    ) -> Result<(), ErrorReported> {
        use rustc_codegen_ssa::back::link::link_binary;

        let codegen_results = *res
            .downcast::<CodegenResults>()
            .expect("Expected CraneliftCodegenBackend's CodegenResult, found Box<Any>");

        sess.profiler(|p| p.start_activity("link_crate"));
        rustc::util::common::time(sess, "linking", || {
            let target_cpu = target_triple(sess).to_string();
            link_binary::<crate::archive::ArArchiveBuilder<'_>>(
                sess,
                &codegen_results,
                outputs,
                &codegen_results.crate_name.as_str(),
                &target_cpu,
            );
        });
        sess.profiler(|p| p.end_activity("link_crate"));

        Ok(())
    }
}

fn target_triple(sess: &Session) -> target_lexicon::Triple {
    sess.target.target.llvm_target.parse().unwrap()
}

fn build_isa(sess: &Session, enable_pic: bool) -> Box<dyn isa::TargetIsa + 'static> {
    let mut flags_builder = settings::builder();
    if enable_pic {
        flags_builder.enable("is_pic").unwrap();
    } else {
        flags_builder.set("is_pic", "false").unwrap();
    }
    flags_builder.set("probestack_enabled", "false").unwrap(); // __cranelift_probestack is not provided
    flags_builder
        .set(
            "enable_verifier",
            if cfg!(debug_assertions) {
                "true"
            } else {
                "false"
            },
        )
        .unwrap();

    // FIXME(CraneStation/cranelift#732) fix LICM in presence of jump tables
    /*
    use rustc::session::config::OptLevel;
    match sess.opts.optimize {
        OptLevel::No => {
            flags_builder.set("opt_level", "fastest").unwrap();
        }
        OptLevel::Less | OptLevel::Default => {}
        OptLevel::Aggressive => {
            flags_builder.set("opt_level", "best").unwrap();
        }
        OptLevel::Size | OptLevel::SizeMin => {
            sess.warn("Optimizing for size is not supported. Just ignoring the request");
        }
    }*/

    let target_triple = target_triple(sess);
    let flags = settings::Flags::new(flags_builder);
    cranelift::codegen::isa::lookup(target_triple)
        .unwrap()
        .finish(flags)
}

/// This is the entrypoint for a hot plugged rustc_codegen_cranelift
#[no_mangle]
pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
    Box::new(CraneliftCodegenBackend)
}
<|endoftext|>


<commit_before>//! Solvent is a dependency resolver library written in rust.
//!
//! Solvent helps you to resolve dependency orderings by building up a dependency
//! graph and then resolving the dependences of some target node in an order such
//! that each output depends only upon the previous outputs.
//!
//! It is currently quite simple, but is still useful.
//!
//! #Example
//!
//! ```rust
//! extern crate solvent;
//!
//! use solvent::DepGraph;
//!
//! fn main() {
//!     // Create a new empty DepGraph.  Must be `mut` or else it cannot
//!     // be used by the rest of the library.
//!     let mut depgraph: DepGraph = DepGraph::new();
//!
//!     // You can register a dependency like this.  Solvent will
//!     // automatically create nodes for any term it has not seen before.
//!     // This means 'b' depends on 'd'
//!     depgraph.register_dependency("b","d");
//!
//!     // You can also register multiple dependencies at once
//!     depgraph.register_dependencies("a",&["b","c","d"]);
//!     depgraph.register_dependencies("c",&["e"]);
//!
//!     // You must set a target to resolve the dependencies of that target
//!     depgraph.set_target("a");
//!
//!     // Iterate through each dependency.  The dependencies will be returned
//!     // in an order such that each output only depends on the previous
//!     // outputs (or nothing).  The target itself will be output last.
//!     for node in depgraph.satisfying_iter() {
//!         print!("{} ", node);
//!     }
//! }
//! ```
//!
//! The above will output:  `d b e c a`
//!
//! You can also mark some elements as already satisfied, and the
//! iterator will take that into account:
//!
//! ```ignore
//! depgraph.mark_as_satisfied(["e","c"]);
//! ```
//!
//! The algorithm is not deterministic, and may give a different answer each
//! time it is run.  Beware.
//!
//! Dependency cycles are detected and will cause a panic!()

#![crate_name = "solvent"]
#![crate_type = "lib"]

// Required for log and rustdoc:
#![feature(phase)]
#[phase(plugin, link)]

extern crate log;

use std::collections::{HashMap,HashSet};
use std::collections::hash_map::{Occupied,Vacant};
use std::iter::{Iterator};
#[allow(unused_imports)]
use std::task;

/// This is the dependency graph.  It must be mutable, as the
/// library uses internal properties in the graph to do its
/// calculations.
#[deriving(Clone)]
pub struct DepGraph {
    /// List of dependencies.  Key is the element, values are the
    /// other elements that the key element depends upon.
    pub dependencies: HashMap<String,HashSet<String>>,

    // (private) target we are trying to satisfy
    target: Option<String>,

    // (private) elements already satisfied
    satisfied: HashSet<String>,
}

/// This iterates through the dependencies of the DepGraph's target
pub struct DepGraphIterator<'a> {
    depgraph: &'a mut DepGraph,

    // current path, for cycle detection
    curpath: HashSet<String>
}

/// This iterates through the dependencies of the DepGraph's target,
/// marking each element as satisfied as it is visited.
pub struct DepGraphSatisfyingIterator<'a> {
    depgraph: &'a mut DepGraph,

    // current path, for cycle detection
    curpath: HashSet<String>
}

impl DepGraph {

    /// Create an empty DepGraph.
    pub fn new() -> DepGraph
    {
        DepGraph {
            dependencies: HashMap::new(),
            target: None,
            satisfied: HashSet::new(),
        }
    }

    /// Add a dependency to a DepGraph.  The node does not need
    /// to pre-exist, nor do the dependency nodes.  But if the
    /// node does pre-exist, the depends_on will be added to its
    /// existing dependency list.
    pub fn register_dependency<'a>( &mut self,
                                node: &'a str,
                                depends_on: &'a str )
    {
        match self.dependencies.entry( String::from_str(node) ) {
            Vacant(entry) => {
                let mut deps = HashSet::with_capacity(1);
                deps.insert( String::from_str(depends_on) );
                entry.set( deps );
            },
            Occupied(mut entry) => {
                (*entry.get_mut()).insert(String::from_str(depends_on));
            },
        }
    }

    /// Add multiple dependencies of one node to a DepGraph.  The
    /// node does not need to pre-exist, nor do the dependency elements.
    /// But if the node does pre-exist, the depends_on will be added
    /// to its existing dependency list.
    pub fn register_dependencies<'a>( &mut self,
                                  node: &'a str,
                                  depends_on: &'a[&'a str] )
    {
        match self.dependencies.entry( String::from_str(node) ) {
            Vacant(entry) => {
                let mut deps = HashSet::with_capacity( depends_on.len() );
                for s in depends_on.iter() {
                    deps.insert( String::from_str(*s) );
                }
                entry.set( deps );
            },
            Occupied(mut entry) => {
                for s in depends_on.iter() {
                    (*entry.get_mut()).insert( String::from_str(*s) );
                }
            },
        }
    }

    /// This sets the target node.  Iteratators on the graph always
    /// get the dependencies of the target node.
    pub fn set_target<'a>( &mut self, target: &'a str )
    {
        self.target = Some(String::from_str(target));
    }

    /// This marks a node as satisfied.  Iterators will not output
    /// such nodes.
    pub fn mark_as_satisfied<'a>( &mut self,
                                   nodes: &'a[&'a str] )
    {
        for node in nodes.iter() {
            self.satisfied.insert(String::from_str(*node));
        }
    }

    fn get_next_dependency(&mut self, node: &String, curpath: &mut HashSet<String>) -> String
    {
        if curpath.contains(node) {
            panic!("Circular dependency graph at {}",node);
        }
        curpath.insert(node.clone());

        let deplist = match self.dependencies.get(node) {
            None => return node.clone(),
            Some(deplist) => deplist.clone() // ouch
        };

        for n in deplist.iter() {
            if self.satisfied.contains(n) {
                continue;
            }
            return self.get_next_dependency(n, curpath);
        }
        // nodes dependencies are satisfied
        node.clone()
    }

    /// Get an iterator to iterate through the dependencies of
    /// the target node.  This iter() will loop forever if you dont
    /// mark nodes satisfied as you go.  If you want the iterator
    /// to take care of that, use satisfying_iter()
    pub fn iter<'a>(&'a mut self) -> DepGraphIterator<'a>
    {
        DepGraphIterator {
            depgraph: self,
            curpath: HashSet::new(),
        }
    }

    /// Get an iterator to iterate through the dependencies of
    /// the target node, and also to mark those dependencies as
    /// satisfied as it goes.
    pub fn satisfying_iter<'a>(&'a mut self) -> DepGraphSatisfyingIterator<'a>
    {
        DepGraphSatisfyingIterator {
            depgraph: self,
            curpath: HashSet::new(),
        }
    }
}

impl<'a> Iterator<String> for DepGraphIterator<'a> {
    /// Get next dependency.  This may panic!() if a cycle is detected.
    fn next(&mut self) -> Option<String>
    {
        let node = match self.depgraph.target {
            None => return None,
            Some(ref node) => node.clone()
        };
        if self.depgraph.satisfied.contains(&node) {
            return None;
        }
        self.curpath.clear();
        Some(self.depgraph.get_next_dependency(&node, &mut self.curpath))
    }
}

impl<'a> Iterator<String> for DepGraphSatisfyingIterator<'a> {
    /// Get next dependency.  This may panic!() if a cycle is detected.
    fn next(&mut self) -> Option<String>
    {
        let node = match self.depgraph.target {
            None => return None,
            Some(ref node) => node.clone()
        };
        if self.depgraph.satisfied.contains(&node) {
            return None;
        }
        self.curpath.clear();
        let next = self.depgraph.get_next_dependency(&node, &mut self.curpath);
        self.depgraph.mark_as_satisfied(&[next.as_slice()]);
        Some(next)
    }
}

#[test]
fn solvent_test_branching() {
    let mut depgraph: DepGraph = DepGraph::new();

    depgraph.register_dependencies("a",&["b","c","d"]);
    depgraph.register_dependency("b","d");
    depgraph.register_dependencies("c",&["e","m","g"]);
    depgraph.register_dependency("e","f");
    depgraph.register_dependency("g","h");
    depgraph.register_dependency("h","i");
    depgraph.register_dependencies("i",&["j","k"]);
    depgraph.register_dependencies("k",&["l","m"]);
    depgraph.register_dependency("m","n");

    depgraph.set_target("a");

    let mut results: Vec<String> = Vec::new();

    loop {
        // detect infinite looping bugs
        assert!(results.len() < 30);

        let node = match depgraph.iter().next() {
            Some(x) => x,
            None => break,
        };
        depgraph.mark_as_satisfied(&[node.as_slice()]);

        // Check that all of that nodes dependencies have already been output
        let deps: Option<&HashSet<String>> = depgraph.dependencies.get(&node);
        if deps.is_some() {
            for dep in deps.unwrap().iter() {
                assert!( results.contains(dep) );
            }
        }

        results.push(node.clone());
    }
}

#[test]
fn solvent_test_updating_dependencies() {
    let mut depgraph: DepGraph = DepGraph::new();

    depgraph.register_dependencies("a",&["b","c"]);
    depgraph.register_dependency("a","d");
    assert!(depgraph.dependencies.get("a").unwrap().contains("b"));
    assert!(depgraph.dependencies.get("a").unwrap().contains("c"));
    assert!(depgraph.dependencies.get("a").unwrap().contains("d"));
}

#[test]
fn solvent_test_satisfying() {
    let mut depgraph: DepGraph = DepGraph::new();

    depgraph.register_dependencies("a",&["b","c","d"]);
    depgraph.register_dependency("b","d");
    depgraph.register_dependencies("c",&["e"]);

    depgraph.set_target("a");

    let mut results: Vec<String> = Vec::new();

    while let Some(node) = depgraph.satisfying_iter().next() {
        // detect infinite looping bugs
        assert!(results.len() < 30);

        // Check that all of that nodes dependencies have already been output
        let deps: Option<&HashSet<String>> = depgraph.dependencies.get(&node);
        if deps.is_some() {
            for dep in deps.unwrap().iter() {
                assert!( results.contains(dep) );
            }
        }

        results.push(node);
    }
}

#[test]
#[should_fail]
fn solvent_test_circular() {

    let mut depgraph: DepGraph = DepGraph::new();
    depgraph.register_dependency("a","b");
    depgraph.register_dependency("b","c");
    depgraph.register_dependency("c","a");
    depgraph.set_target("a");

    let mut results: Vec<String> = Vec::new();

    loop {
        // Detect infinite looping bugs
        // (Since this test should fail, we cause a success here)
        if results.len() >= 30 { break; }

        let node = match depgraph.iter().next() {
            Some(x) => x,
            None => break,
        };
        depgraph.mark_as_satisfied(&[node.as_slice()]);
        results.push(node);
    }
}

#[test]
fn solvent_test_satisfied_stoppage() {

    let mut depgraph: DepGraph = DepGraph::new();
    depgraph.register_dependencies("superconn", &[]);
    depgraph.register_dependencies("owneruser", &["superconn"]);
    depgraph.register_dependencies("appuser", &["superconn"]);
    depgraph.register_dependencies("database", &["owneruser"]);
    depgraph.register_dependencies("ownerconn", &["database","owneruser"]);
    depgraph.register_dependencies("adminconn", &["database"]);
    depgraph.register_dependencies("extensions", &["database","adminconn"]);
    depgraph.register_dependencies("schema_table", &["database","ownerconn"]);
    depgraph.register_dependencies("schemas", &["ownerconn","extensions","schema_table","appuser"]);
    depgraph.register_dependencies("appconn", &["database","appuser","schemas"]);

    depgraph.set_target("appconn");
    depgraph.mark_as_satisfied(&["owneruser","appuser"]);

    let mut results: Vec<String> = Vec::new();

    loop {
        assert!(results.len() < 30);

        let node = match depgraph.iter().next() {
            Some(x) => x,
            None => break,
        };
        depgraph.mark_as_satisfied(&[node.as_slice()]);
        results.push(node);
    }
    assert!( !results.contains(&String::from_str("superconn")) );
}

<commit_msg>Moved get_next_dependency() into the interators<commit_after>//! Solvent is a dependency resolver library written in rust.
//!
//! Solvent helps you to resolve dependency orderings by building up a dependency
//! graph and then resolving the dependences of some target node in an order such
//! that each output depends only upon the previous outputs.
//!
//! It is currently quite simple, but is still useful.
//!
//! #Example
//!
//! ```rust
//! extern crate solvent;
//!
//! use solvent::DepGraph;
//!
//! fn main() {
//!     // Create a new empty DepGraph.  Must be `mut` or else it cannot
//!     // be used by the rest of the library.
//!     let mut depgraph: DepGraph = DepGraph::new();
//!
//!     // You can register a dependency like this.  Solvent will
//!     // automatically create nodes for any term it has not seen before.
//!     // This means 'b' depends on 'd'
//!     depgraph.register_dependency("b","d");
//!
//!     // You can also register multiple dependencies at once
//!     depgraph.register_dependencies("a",&["b","c","d"]);
//!     depgraph.register_dependencies("c",&["e"]);
//!
//!     // You must set a target to resolve the dependencies of that target
//!     depgraph.set_target("a");
//!
//!     // Iterate through each dependency.  The dependencies will be returned
//!     // in an order such that each output only depends on the previous
//!     // outputs (or nothing).  The target itself will be output last.
//!     for node in depgraph.satisfying_iter() {
//!         print!("{} ", node);
//!     }
//! }
//! ```
//!
//! The above will output:  `d b e c a`
//!
//! You can also mark some elements as already satisfied, and the
//! iterator will take that into account:
//!
//! ```ignore
//! depgraph.mark_as_satisfied(["e","c"]);
//! ```
//!
//! The algorithm is not deterministic, and may give a different answer each
//! time it is run.  Beware.
//!
//! Dependency cycles are detected and will cause a panic!()

#![crate_name = "solvent"]
#![crate_type = "lib"]

// Required for log and rustdoc:
#![feature(phase)]
#[phase(plugin, link)]

extern crate log;

use std::collections::{HashMap,HashSet};
use std::collections::hash_map::{Occupied,Vacant};
use std::iter::{Iterator};
#[allow(unused_imports)]
use std::task;

/// This is the dependency graph.  It must be mutable, as the
/// library uses internal properties in the graph to do its
/// calculations.
#[deriving(Clone)]
pub struct DepGraph {
    /// List of dependencies.  Key is the element, values are the
    /// other elements that the key element depends upon.
    pub dependencies: HashMap<String,HashSet<String>>,

    // (private) target we are trying to satisfy
    target: Option<String>,

    // (private) elements already satisfied
    satisfied: HashSet<String>,
}

/// This iterates through the dependencies of the DepGraph's target
pub struct DepGraphIterator<'a> {
    depgraph: &'a mut DepGraph,

    // current path, for cycle detection
    curpath: HashSet<String>
}

/// This iterates through the dependencies of the DepGraph's target,
/// marking each element as satisfied as it is visited.
pub struct DepGraphSatisfyingIterator<'a> {
    depgraph: &'a mut DepGraph,

    // current path, for cycle detection
    curpath: HashSet<String>
}

impl DepGraph {

    /// Create an empty DepGraph.
    pub fn new() -> DepGraph
    {
        DepGraph {
            dependencies: HashMap::new(),
            target: None,
            satisfied: HashSet::new(),
        }
    }

    /// Add a dependency to a DepGraph.  The node does not need
    /// to pre-exist, nor do the dependency nodes.  But if the
    /// node does pre-exist, the depends_on will be added to its
    /// existing dependency list.
    pub fn register_dependency<'a>( &mut self,
                                node: &'a str,
                                depends_on: &'a str )
    {
        match self.dependencies.entry( String::from_str(node) ) {
            Vacant(entry) => {
                let mut deps = HashSet::with_capacity(1);
                deps.insert( String::from_str(depends_on) );
                entry.set( deps );
            },
            Occupied(mut entry) => {
                (*entry.get_mut()).insert(String::from_str(depends_on));
            },
        }
    }

    /// Add multiple dependencies of one node to a DepGraph.  The
    /// node does not need to pre-exist, nor do the dependency elements.
    /// But if the node does pre-exist, the depends_on will be added
    /// to its existing dependency list.
    pub fn register_dependencies<'a>( &mut self,
                                  node: &'a str,
                                  depends_on: &'a[&'a str] )
    {
        match self.dependencies.entry( String::from_str(node) ) {
            Vacant(entry) => {
                let mut deps = HashSet::with_capacity( depends_on.len() );
                for s in depends_on.iter() {
                    deps.insert( String::from_str(*s) );
                }
                entry.set( deps );
            },
            Occupied(mut entry) => {
                for s in depends_on.iter() {
                    (*entry.get_mut()).insert( String::from_str(*s) );
                }
            },
        }
    }

    /// This sets the target node.  Iteratators on the graph always
    /// get the dependencies of the target node.
    pub fn set_target<'a>( &mut self, target: &'a str )
    {
        self.target = Some(String::from_str(target));
    }

    /// This marks a node as satisfied.  Iterators will not output
    /// such nodes.
    pub fn mark_as_satisfied<'a>( &mut self,
                                   nodes: &'a[&'a str] )
    {
        for node in nodes.iter() {
            self.satisfied.insert(String::from_str(*node));
        }
    }

    /// Get an iterator to iterate through the dependencies of
    /// the target node.  This iter() will loop forever if you dont
    /// mark nodes satisfied as you go.  If you want the iterator
    /// to take care of that, use satisfying_iter()
    pub fn iter<'a>(&'a mut self) -> DepGraphIterator<'a>
    {
        DepGraphIterator {
            depgraph: self,
            curpath: HashSet::new(),
        }
    }

    /// Get an iterator to iterate through the dependencies of
    /// the target node, and also to mark those dependencies as
    /// satisfied as it goes.
    pub fn satisfying_iter<'a>(&'a mut self) -> DepGraphSatisfyingIterator<'a>
    {
        DepGraphSatisfyingIterator {
            depgraph: self,
            curpath: HashSet::new(),
        }
    }
}

impl<'a> DepGraphIterator<'a> {
    fn get_next_dependency(&mut self, node: &String) -> String
    {
        if self.curpath.contains(node) {
            panic!("Circular dependency graph at {}",node);
        }
        self.curpath.insert(node.clone());

        let deplist = match self.depgraph.dependencies.get(node) {
            None => return node.clone(),
            Some(deplist) => deplist.clone() // ouch
        };

        for n in deplist.iter() {
            if self.depgraph.satisfied.contains(n) {
                continue;
            }
            return self.get_next_dependency(n);
        }
        // nodes dependencies are satisfied
        node.clone()
    }
}

impl<'a> DepGraphSatisfyingIterator<'a> {
    fn get_next_dependency(&mut self, node: &String) -> String
    {
        if self.curpath.contains(node) {
            panic!("Circular dependency graph at {}",node);
        }
        self.curpath.insert(node.clone());

        let deplist = match self.depgraph.dependencies.get(node) {
            None => return node.clone(),
            Some(deplist) => deplist.clone() // ouch
        };

        for n in deplist.iter() {
            if self.depgraph.satisfied.contains(n) {
                continue;
            }
            return self.get_next_dependency(n);
        }
        // nodes dependencies are satisfied
        node.clone()
    }
}

impl<'a> Iterator<String> for DepGraphIterator<'a> {
    /// Get next dependency.  This may panic!() if a cycle is detected.
    fn next(&mut self) -> Option<String>
    {
        let node = match self.depgraph.target {
            None => return None,
            Some(ref node) => node.clone()
        };
        if self.depgraph.satisfied.contains(&node) {
            return None;
        }
        self.curpath.clear();
        Some(self.get_next_dependency(&node))
    }
}

impl<'a> Iterator<String> for DepGraphSatisfyingIterator<'a> {
    /// Get next dependency.  This may panic!() if a cycle is detected.
    fn next(&mut self) -> Option<String>
    {
        let node = match self.depgraph.target {
            None => return None,
            Some(ref node) => node.clone()
        };
        if self.depgraph.satisfied.contains(&node) {
            return None;
        }
        self.curpath.clear();
        let next = self.get_next_dependency(&node);
        self.depgraph.mark_as_satisfied(&[next.as_slice()]);
        Some(next)
    }
}

#[test]
fn solvent_test_branching() {
    let mut depgraph: DepGraph = DepGraph::new();

    depgraph.register_dependencies("a",&["b","c","d"]);
    depgraph.register_dependency("b","d");
    depgraph.register_dependencies("c",&["e","m","g"]);
    depgraph.register_dependency("e","f");
    depgraph.register_dependency("g","h");
    depgraph.register_dependency("h","i");
    depgraph.register_dependencies("i",&["j","k"]);
    depgraph.register_dependencies("k",&["l","m"]);
    depgraph.register_dependency("m","n");

    depgraph.set_target("a");

    let mut results: Vec<String> = Vec::new();

    loop {
        // detect infinite looping bugs
        assert!(results.len() < 30);

        let node = match depgraph.iter().next() {
            Some(x) => x,
            None => break,
        };
        depgraph.mark_as_satisfied(&[node.as_slice()]);

        // Check that all of that nodes dependencies have already been output
        let deps: Option<&HashSet<String>> = depgraph.dependencies.get(&node);
        if deps.is_some() {
            for dep in deps.unwrap().iter() {
                assert!( results.contains(dep) );
            }
        }

        results.push(node.clone());
    }
}

#[test]
fn solvent_test_updating_dependencies() {
    let mut depgraph: DepGraph = DepGraph::new();

    depgraph.register_dependencies("a",&["b","c"]);
    depgraph.register_dependency("a","d");
    assert!(depgraph.dependencies.get("a").unwrap().contains("b"));
    assert!(depgraph.dependencies.get("a").unwrap().contains("c"));
    assert!(depgraph.dependencies.get("a").unwrap().contains("d"));
}

#[test]
fn solvent_test_satisfying() {
    let mut depgraph: DepGraph = DepGraph::new();

    depgraph.register_dependencies("a",&["b","c","d"]);
    depgraph.register_dependency("b","d");
    depgraph.register_dependencies("c",&["e"]);

    depgraph.set_target("a");

    let mut results: Vec<String> = Vec::new();

    while let Some(node) = depgraph.satisfying_iter().next() {
        // detect infinite looping bugs
        assert!(results.len() < 30);

        // Check that all of that nodes dependencies have already been output
        let deps: Option<&HashSet<String>> = depgraph.dependencies.get(&node);
        if deps.is_some() {
            for dep in deps.unwrap().iter() {
                assert!( results.contains(dep) );
            }
        }

        results.push(node);
    }
}

#[test]
#[should_fail]
fn solvent_test_circular() {

    let mut depgraph: DepGraph = DepGraph::new();
    depgraph.register_dependency("a","b");
    depgraph.register_dependency("b","c");
    depgraph.register_dependency("c","a");
    depgraph.set_target("a");

    let mut results: Vec<String> = Vec::new();

    loop {
        // Detect infinite looping bugs
        // (Since this test should fail, we cause a success here)
        if results.len() >= 30 { break; }

        let node = match depgraph.iter().next() {
            Some(x) => x,
            None => break,
        };
        depgraph.mark_as_satisfied(&[node.as_slice()]);
        results.push(node);
    }
}

#[test]
fn solvent_test_satisfied_stoppage() {

    let mut depgraph: DepGraph = DepGraph::new();
    depgraph.register_dependencies("superconn", &[]);
    depgraph.register_dependencies("owneruser", &["superconn"]);
    depgraph.register_dependencies("appuser", &["superconn"]);
    depgraph.register_dependencies("database", &["owneruser"]);
    depgraph.register_dependencies("ownerconn", &["database","owneruser"]);
    depgraph.register_dependencies("adminconn", &["database"]);
    depgraph.register_dependencies("extensions", &["database","adminconn"]);
    depgraph.register_dependencies("schema_table", &["database","ownerconn"]);
    depgraph.register_dependencies("schemas", &["ownerconn","extensions","schema_table","appuser"]);
    depgraph.register_dependencies("appconn", &["database","appuser","schemas"]);

    depgraph.set_target("appconn");
    depgraph.mark_as_satisfied(&["owneruser","appuser"]);

    let mut results: Vec<String> = Vec::new();

    loop {
        assert!(results.len() < 30);

        let node = match depgraph.iter().next() {
            Some(x) => x,
            None => break,
        };
        depgraph.mark_as_satisfied(&[node.as_slice()]);
        results.push(node);
    }
    assert!( !results.contains(&String::from_str("superconn")) );
}

<|endoftext|>