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

//! Local state for keys in the snapshot in progress (the "index").

use std::time::duration::{Duration};

use periodic_timer::{PeriodicTimer};
use process::{Process, MsgHandler};
use sqlite3::database::{Database};

use sqlite3::cursor::{Cursor};
use sqlite3::types::ResultCode::{SQLITE_ROW, SQLITE_DONE};
use sqlite3::{open};

use rustc_serialize::hex::{ToHex};

pub trait KeyEntry<KE> {
  fn id(&self) -> Option<u64>;
  fn parent_id(&self) -> Option<u64>;

  fn name(&self) -> Vec<u8>;
  fn size(&self) -> Option<u64>;

  fn created(&self) -> Option<u64>;
  fn modified(&self) -> Option<u64>;
  fn accessed(&self) -> Option<u64>;

  fn permissions(&self) -> Option<u64>;
  fn user_id(&self) -> Option<u64>;
  fn group_id(&self) -> Option<u64>;

  fn with_id(&self, u64) -> KE;
}

pub type KeyIndexProcess<KE> = Process<Msg<KE>, Reply>;

pub enum Msg<KeyEntryT> {

  /// Insert an entry in the key index.
  /// Returns `Id` with the new entry ID.
  Insert(KeyEntryT),

  /// Lookup an entry in the key index, to see if it exists.
  /// Returns either `Id` with the found entry ID or `Notfound`.
  LookupExact(KeyEntryT),

  /// Update the `payload` and `persistent_ref` of an entry.
  /// Returns `UpdateOK`.
  UpdateDataHash(KeyEntryT, Option<Vec<u8>>, Option<Vec<u8>>),

  /// List a directory (aka. `level`) in the index.
  /// Returns `ListResult` with all the entries under the given parent.
  ListDir(Option<u64>),

  /// Flush this key index.
  Flush,
}

pub enum Reply {
  Id(u64),
  NotFound,
  UpdateOK,
  ListResult(Vec<(u64, Vec<u8>, u64, u64, u64, Vec<u8>, Vec<u8>)>),
  FlushOK,
}

pub struct KeyIndex {
  path: String,
  dbh: Database,
  flush_timer: PeriodicTimer,
}

fn i64_to_u64_or_panic(x: i64) -> u64 {
  if x < 0 {
    panic!("expected u64, got {:?}", x);
  }
  return x as u64
}

impl KeyIndex {
  pub fn new(path: String) -> KeyIndex {
    let mut ki = match open(&path) {
      Ok(dbh) => {
        KeyIndex{path: path,
                 dbh: dbh,
                 flush_timer: PeriodicTimer::new(Duration::seconds(5))}
      },
      Err(err) => panic!("{:?}", err),
    };
    ki.exec_or_die("CREATE TABLE IF NOT EXISTS
                    key_index (rowid          INTEGER PRIMARY KEY,
                               parent         INTEGER,
                               name           BLOB,
                               created        UINT8,
                               modified       UINT8,
                               accessed       UINT8,
                               hash           BLOB,
                               persistent_ref BLOB
                            );");

    if cfg!(test) {
      ki.exec_or_die("CREATE UNIQUE INDEX IF NOT EXISTS
                      KeyIndex_UniqueParentName
                      ON key_index(parent, name)");
    }

    ki.exec_or_die("BEGIN");
    ki
  }

  #[cfg(test)]
  pub fn new_for_testing() -> KeyIndex {
    KeyIndex::new(":memory:".to_string())
  }

  fn exec_or_die(&mut self, sql: &str) {
    match self.dbh.exec(sql) {
      Ok(true) => (),
      Ok(false) => panic!("exec: {:?}, {}", self.dbh.get_errmsg(), sql),
      Err(msg) => panic!("exec: {:?}, {:?}, {}", msg, self.dbh.get_errmsg(), sql),
    }
  }

  fn prepare_or_die<'a>(&'a mut self, sql: &str) -> Cursor<'a> {
    match self.dbh.prepare(sql, &None) {
      Ok(s)  => s,
      Err(x) => panic!("sqlite error: {} ({:?})", self.dbh.get_errmsg(), x),
    }
  }

  pub fn maybe_flush(&mut self) {
    if self.flush_timer.did_fire() {
      self.flush();
    }
  }

  pub fn flush(&mut self) {
    self.exec_or_die("COMMIT; BEGIN");
  }
}

impl Clone for KeyIndex {
  fn clone(&self) -> KeyIndex {
    KeyIndex::new(self.path.clone())
  }
}

impl Drop for KeyIndex {
  fn drop(&mut self) {
    self.exec_or_die("COMMIT");
  }
}

impl <A: KeyEntry<A>> MsgHandler<Msg<A>, Reply> for KeyIndex {
  fn handle(&mut self, msg: Msg<A>, reply: Box<Fn(Reply)>) {
    match msg {

      Msg::Insert(entry) => {
        let parent = entry.parent_id().unwrap_or(0);

        self.exec_or_die(&format!(
          "INSERT OR REPLACE INTO key_index (parent, name, created, accessed)
           VALUES ({:?}, x'{}', {}, {})",
          parent, entry.name().to_hex(),
          entry.created().unwrap_or(0),
          entry.accessed().unwrap_or(0)));

        let id = self.dbh.get_last_insert_rowid();
        return reply(Reply::Id(i64_to_u64_or_panic(id)));
      },

      Msg::LookupExact(entry) => {
        let parent = entry.parent_id().unwrap_or(0);
        let mut cursor = self.prepare_or_die(&format!(
          "SELECT rowid FROM key_index
           WHERE parent={:?} AND name=x'{}'
           AND created={} AND modified={} AND accessed={}
           LIMIT 1",
          parent, entry.name().to_hex(),
          entry.created().unwrap_or(0),
          entry.modified().unwrap_or(0),
          entry.accessed().unwrap_or(0)));
        if cursor.step() == SQLITE_ROW {
          assert!(cursor.step() == SQLITE_DONE);
          return reply(Reply::Id((i64_to_u64_or_panic(cursor.get_i64(0)))));
        } else {
          return reply(Reply::NotFound);
        }
      },

      Msg::UpdateDataHash(entry, hash_opt, persistent_ref_opt) => {
        let parent = entry.parent_id().unwrap_or(0);

        assert!(hash_opt.is_some() == persistent_ref_opt.is_some());

        if hash_opt.is_some() && persistent_ref_opt.is_some() {
          match entry.modified() {
            Some(modified) => {
              self.exec_or_die(&format!(
                "UPDATE key_index SET hash=x'{}', persistent_ref=x'{}'
                                                  , modified={}
                  WHERE parent={:?} AND rowid={:?} AND IFNULL(modified,0)<={}",
                hash_opt.unwrap().to_hex(),
                persistent_ref_opt.unwrap().to_hex(),
                modified, parent, entry.id().expect("UpdateDataHash"),
                modified));
            },
            None => {
              self.exec_or_die(&format!(
                "UPDATE key_index SET hash=x'{}', persistent_ref=x'{}'
                 WHERE parent={:?} AND rowid={:?}",
                hash_opt.unwrap().to_hex(),
                persistent_ref_opt.unwrap().to_hex(),
                parent, entry.id().expect("UpdateDataHash, None")));
            }
          }
        } else {
          match entry.modified() {
            Some(modified) => {
              self.exec_or_die(&format!(
                "UPDATE key_index SET hash=NULL, persistent_ref=NULL
                                               , modified={}
                 WHERE parent={:?} AND rowid={:?} AND IFNULL(modified, 0)<={}",
                modified, parent, entry.id().expect("UpdateDataHash2"), modified));
            },
            None => {
              self.exec_or_die(&format!(
                "UPDATE key_index SET hash=NULL, persistent_ref=NULL
                 WHERE parent={:?} AND rowid={}",
                parent, entry.id().expect("UpdateDataHash2, None")));
            }
          }
        }

        self.maybe_flush();
        return reply(Reply::UpdateOK);
      },

      Msg::Flush => {
        self.flush();
        return reply(Reply::FlushOK);
      },

      Msg::ListDir(parent_opt) => {
        let mut listing = Vec::new();
        let parent = parent_opt.unwrap_or(0);

        let mut cursor = self.prepare_or_die(&format!(
           "SELECT rowid, name, created, modified, accessed, hash, persistent_ref
            FROM key_index
            WHERE parent={:?}", parent));

        // TODO(jos): replace get_int with something that understands usize64
        while cursor.step() == SQLITE_ROW {
          let id = i64_to_u64_or_panic(cursor.get_i64(0));
          let name = cursor.get_blob(1).expect("name").iter().map(|&x| x).collect();
          let created = cursor.get_int(2);
          let modified = cursor.get_int(3);
          let accessed = cursor.get_int(4);
          let hash = cursor.get_blob(5).unwrap_or(&[]).iter().map(|&x| x).collect();
          let persistent_ref = cursor.get_blob(6).unwrap_or(&[]).iter().map(|&x| x).collect();

          listing.push((id, name,
                        created as u64, modified as u64, accessed as u64,
                        hash, persistent_ref));
        }

        return reply(Reply::ListResult(listing));
      },
    }
  }
}

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

  struct TestEntry {
    id: Option<u64>,
    parent: Option<u64>,
    name: Vec<u8>,
  }
  impl KeyEntry<TestEntry> for TestEntry {
    fn id(&self) -> Option<u64> {
      None
    }
    fn parent_id(&self) -> Option<u64>{
      self.parent.clone()
    }
    fn name(&self) -> Vec<u8> {
      self.name.clone()
    }

    fn size(&self) -> Option<u64> {
      None
    }

    fn created(&self) -> Option<u64> {
      None
    }
    fn modified(&self) -> Option<u64> {
      None
    }
    fn accessed(&self) -> Option<u64> {
      None
    }

    fn permissions(&self) -> Option<u64> {
      None
    }
    fn user_id(&self) -> Option<u64> {
      None
    }
    fn group_id(&self) -> Option<u64> {
      None
    }
    fn with_id(&self, id: u64) -> TestEntry {
      TestEntry{id:Some(id),
                parent: self.parent_id(),
                name: self.name()}
    }
  }

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

//! Local state for keys in the snapshot in progress (the "index").

use std::time::duration::{Duration};

use periodic_timer::{PeriodicTimer};
use process::{Process, MsgHandler};
use sqlite3::database::{Database};

use sqlite3::cursor::{Cursor};
use sqlite3::types::ResultCode::{SQLITE_ROW, SQLITE_DONE};
use sqlite3::{open};

use rustc_serialize::hex::{ToHex};

pub trait KeyEntry<KE> {
  fn id(&self) -> Option<u64>;
  fn parent_id(&self) -> Option<u64>;

  fn name(&self) -> Vec<u8>;
  fn size(&self) -> Option<u64>;

  fn created(&self) -> Option<u64>;
  fn modified(&self) -> Option<u64>;
  fn accessed(&self) -> Option<u64>;

  fn permissions(&self) -> Option<u64>;
  fn user_id(&self) -> Option<u64>;
  fn group_id(&self) -> Option<u64>;

  fn with_id(&self, u64) -> KE;
}

pub type KeyIndexProcess<KE> = Process<Msg<KE>, Reply>;

pub enum Msg<KeyEntryT> {

  /// Insert an entry in the key index.
  /// Returns `Id` with the new entry ID.
  Insert(KeyEntryT),

  /// Lookup an entry in the key index, to see if it exists.
  /// Returns either `Id` with the found entry ID or `Notfound`.
  LookupExact(KeyEntryT),

  /// Update the `payload` and `persistent_ref` of an entry.
  /// Returns `UpdateOK`.
  UpdateDataHash(KeyEntryT, Option<Vec<u8>>, Option<Vec<u8>>),

  /// List a directory (aka. `level`) in the index.
  /// Returns `ListResult` with all the entries under the given parent.
  ListDir(Option<u64>),

  /// Flush this key index.
  Flush,
}

pub enum Reply {
  Id(u64),
  NotFound,
  UpdateOK,
  ListResult(Vec<(u64, Vec<u8>, u64, u64, u64, Vec<u8>, Vec<u8>)>),
  FlushOK,
}

pub struct KeyIndex {
  path: String,
  dbh: Database,
  flush_timer: PeriodicTimer,
}

fn i64_to_u64_or_panic(x: i64) -> u64 {
  if x < 0 {
    panic!("expected u64, got {:?}", x);
  }
  return x as u64
}

impl KeyIndex {
  pub fn new(path: String) -> KeyIndex {
    let mut ki = match open(&path) {
      Ok(dbh) => {
        KeyIndex{path: path,
                 dbh: dbh,
                 flush_timer: PeriodicTimer::new(Duration::seconds(5))}
      },
      Err(err) => panic!("{:?}", err),
    };
    ki.exec_or_die("CREATE TABLE IF NOT EXISTS
                    key_index (rowid          INTEGER PRIMARY KEY,
                               parent         INTEGER,
                               name           BLOB,
                               created        UINT8,
                               modified       UINT8,
                               accessed       UINT8,
                               hash           BLOB,
                               persistent_ref BLOB
                            );");

    if cfg!(test) {
      ki.exec_or_die("CREATE UNIQUE INDEX IF NOT EXISTS
                      KeyIndex_UniqueParentName
                      ON key_index(parent, name)");
    }

    ki.exec_or_die("BEGIN");
    ki
  }

  #[cfg(test)]
  pub fn new_for_testing() -> KeyIndex {
    KeyIndex::new(":memory:".to_string())
  }

  fn exec_or_die(&mut self, sql: &str) {
    match self.dbh.exec(sql) {
      Ok(true) => (),
      Ok(false) => panic!("exec: {:?}, {}", self.dbh.get_errmsg(), sql),
      Err(msg) => panic!("exec: {:?}, {:?}, {}", msg, self.dbh.get_errmsg(), sql),
    }
  }

  fn prepare_or_die<'a>(&'a mut self, sql: &str) -> Cursor<'a> {
    match self.dbh.prepare(sql, &None) {
      Ok(s)  => s,
      Err(x) => panic!("sqlite error: {} ({:?})", self.dbh.get_errmsg(), x),
    }
  }

  pub fn maybe_flush(&mut self) {
    if self.flush_timer.did_fire() {
      self.flush();
    }
  }

  pub fn flush(&mut self) {
    self.exec_or_die("COMMIT; BEGIN");
  }
}

impl Clone for KeyIndex {
  fn clone(&self) -> KeyIndex {
    KeyIndex::new(self.path.clone())
  }
}

impl Drop for KeyIndex {
  fn drop(&mut self) {
    self.exec_or_die("COMMIT");
  }
}

impl <A: KeyEntry<A>> MsgHandler<Msg<A>, Reply> for KeyIndex {
  fn handle(&mut self, msg: Msg<A>, reply: Box<Fn(Reply)>) {
    match msg {

      Msg::Insert(entry) => {
        let parent = entry.parent_id().unwrap_or(0);

        self.exec_or_die(&format!(
          "INSERT OR REPLACE INTO key_index (parent, name, created, modified, accessed)
           VALUES ({:?}, x'{}', {}, {}, {})",
          parent, entry.name().to_hex(),
          entry.created().unwrap_or(0),
          entry.modified().unwrap_or(0),
          entry.accessed().unwrap_or(0)));

        let id = self.dbh.get_last_insert_rowid();
        return reply(Reply::Id(i64_to_u64_or_panic(id)));
      },

      Msg::LookupExact(entry) => {
        let parent = entry.parent_id().unwrap_or(0);
        let mut cursor = self.prepare_or_die(&format!(
          "SELECT rowid FROM key_index
           WHERE parent={:?} AND name=x'{}'
           AND created={} AND modified={} AND accessed={}
           LIMIT 1",
          parent, entry.name().to_hex(),
          entry.created().unwrap_or(0),
          entry.modified().unwrap_or(0),
          entry.accessed().unwrap_or(0)));
        if cursor.step() == SQLITE_ROW {
          assert!(cursor.step() == SQLITE_DONE);
          return reply(Reply::Id((i64_to_u64_or_panic(cursor.get_i64(0)))));
        } else {
          return reply(Reply::NotFound);
        }
      },

      Msg::UpdateDataHash(entry, hash_opt, persistent_ref_opt) => {
        let parent = entry.parent_id().unwrap_or(0);

        assert!(hash_opt.is_some() == persistent_ref_opt.is_some());

        if hash_opt.is_some() && persistent_ref_opt.is_some() {
          match entry.modified() {
            Some(modified) => {
              self.exec_or_die(&format!(
                "UPDATE key_index SET hash=x'{}', persistent_ref=x'{}'
                                                  , modified={}
                  WHERE parent={:?} AND rowid={:?} AND IFNULL(modified,0)<={}",
                hash_opt.unwrap().to_hex(),
                persistent_ref_opt.unwrap().to_hex(),
                modified, parent, entry.id().expect("UpdateDataHash"),
                modified));
            },
            None => {
              self.exec_or_die(&format!(
                "UPDATE key_index SET hash=x'{}', persistent_ref=x'{}'
                 WHERE parent={:?} AND rowid={:?}",
                hash_opt.unwrap().to_hex(),
                persistent_ref_opt.unwrap().to_hex(),
                parent, entry.id().expect("UpdateDataHash, None")));
            }
          }
        } else {
          match entry.modified() {
            Some(modified) => {
              self.exec_or_die(&format!(
                "UPDATE key_index SET hash=NULL, persistent_ref=NULL
                                               , modified={}
                 WHERE parent={:?} AND rowid={:?} AND IFNULL(modified, 0)<={}",
                modified, parent, entry.id().expect("UpdateDataHash2"), modified));
            },
            None => {
              self.exec_or_die(&format!(
                "UPDATE key_index SET hash=NULL, persistent_ref=NULL
                 WHERE parent={:?} AND rowid={}",
                parent, entry.id().expect("UpdateDataHash2, None")));
            }
          }
        }

        self.maybe_flush();
        return reply(Reply::UpdateOK);
      },

      Msg::Flush => {
        self.flush();
        return reply(Reply::FlushOK);
      },

      Msg::ListDir(parent_opt) => {
        let mut listing = Vec::new();
        let parent = parent_opt.unwrap_or(0);

        let mut cursor = self.prepare_or_die(&format!(
           "SELECT rowid, name, created, modified, accessed, hash, persistent_ref
            FROM key_index
            WHERE parent={:?}", parent));

        // TODO(jos): replace get_int with something that understands usize64
        while cursor.step() == SQLITE_ROW {
          let id = i64_to_u64_or_panic(cursor.get_i64(0));
          let name = cursor.get_blob(1).expect("name").iter().map(|&x| x).collect();
          let created = cursor.get_int(2);
          let modified = cursor.get_int(3);
          let accessed = cursor.get_int(4);
          let hash = cursor.get_blob(5).unwrap_or(&[]).iter().map(|&x| x).collect();
          let persistent_ref = cursor.get_blob(6).unwrap_or(&[]).iter().map(|&x| x).collect();

          listing.push((id, name,
                        created as u64, modified as u64, accessed as u64,
                        hash, persistent_ref));
        }

        return reply(Reply::ListResult(listing));
      },
    }
  }
}

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

  struct TestEntry {
    id: Option<u64>,
    parent: Option<u64>,
    name: Vec<u8>,
  }
  impl KeyEntry<TestEntry> for TestEntry {
    fn id(&self) -> Option<u64> {
      None
    }
    fn parent_id(&self) -> Option<u64>{
      self.parent.clone()
    }
    fn name(&self) -> Vec<u8> {
      self.name.clone()
    }

    fn size(&self) -> Option<u64> {
      None
    }

    fn created(&self) -> Option<u64> {
      None
    }
    fn modified(&self) -> Option<u64> {
      None
    }
    fn accessed(&self) -> Option<u64> {
      None
    }

    fn permissions(&self) -> Option<u64> {
      None
    }
    fn user_id(&self) -> Option<u64> {
      None
    }
    fn group_id(&self) -> Option<u64> {
      None
    }
    fn with_id(&self, id: u64) -> TestEntry {
      TestEntry{id:Some(id),
                parent: self.parent_id(),
                name: self.name()}
    }
  }

}
<|endoftext|>


<commit_before>//! Tests for various types of file (video, image, compressed, etc).
//!
//! Currently this is dependent on the file’s name and extension, because
//! those are the only metadata that we have access to without reading the
//! file’s contents.

use ansi_term::Style;

use fs::File;
use output::file_name::FileColours;

#[derive(Debug, Default, PartialEq)]
pub struct FileExtensions;

impl FileExtensions {

    /// An “immediate” file is something that can be run or activated somehow
    /// in order to kick off the build of a project. It’s usually only present
    /// in directories full of source code.
    fn is_immediate(&self, file: &File) -> bool {
        file.name.starts_with("README") || file.name_is_one_of( &[
            "Makefile", "Cargo.toml", "SConstruct", "CMakeLists.txt",
            "build.gradle", "Rakefile", "Gruntfile.js",
            "Gruntfile.coffee",
        ])
    }

    fn is_image(&self, file: &File) -> bool {
        file.extension_is_one_of( &[
            "png", "jpeg", "jpg", "gif", "bmp", "tiff", "tif",
            "ppm", "pgm", "pbm", "pnm", "webp", "raw", "arw",
            "svg", "stl", "eps", "dvi", "ps", "cbr",
            "cbz", "xpm", "ico", "cr2", "orf", "nef",
        ])
    }

    fn is_video(&self, file: &File) -> bool {
        file.extension_is_one_of( &[
            "avi", "flv", "m2v", "mkv", "mov", "mp4", "mpeg",
            "mpg", "ogm", "ogv", "vob", "wmv", "webm", "m2ts",
            "ts",
        ])
    }

    fn is_music(&self, file: &File) -> bool {
        file.extension_is_one_of( &[
            "aac", "m4a", "mp3", "ogg", "wma", "mka", "opus",
        ])
    }

    // Lossless music, rather than any other kind of data...
    fn is_lossless(&self, file: &File) -> bool {
        file.extension_is_one_of( &[
            "alac", "ape", "flac", "wav",
        ])
    }

    fn is_crypto(&self, file: &File) -> bool {
        file.extension_is_one_of( &[
            "asc", "enc", "gpg", "pgp", "sig", "signature", "pfx", "p12",
        ])
    }

    fn is_document(&self, file: &File) -> bool {
        file.extension_is_one_of( &[
            "djvu", "doc", "docx", "dvi", "eml", "eps", "fotd",
            "odp", "odt", "pdf", "ppt", "pptx", "rtf",
            "xls", "xlsx",
        ])
    }

    fn is_compressed(&self, file: &File) -> bool {
        file.extension_is_one_of( &[
            "zip", "tar", "Z", "z", "gz", "bz2", "a", "ar", "7z",
            "iso", "dmg", "tc", "rar", "par", "tgz", "xz", "txz",
            "lzma", "deb", "rpm"
        ])
    }

    fn is_temp(&self, file: &File) -> bool {
        file.name.ends_with('~')
            || (file.name.starts_with('#') && file.name.ends_with('#'))
            || file.extension_is_one_of( &[ "tmp", "swp", "swo", "swn", "bak", "bk" ])
    }

    fn is_compiled(&self, file: &File) -> bool {
        if file.extension_is_one_of( &[ "class", "elc", "hi", "o", "pyc" ]) {
            true
        }
        else if let Some(dir) = file.parent_dir {
            file.get_source_files().iter().any(|path| dir.contains(path))
        }
        else {
            false
        }
    }
}

impl FileColours for FileExtensions {
    fn colour_file(&self, file: &File) -> Option<Style> {
        use ansi_term::Colour::*;

        Some(match file {
            f if self.is_immediate(f)   => Yellow.bold().underline(),
            f if self.is_image(f)       => Fixed(133).normal(),
            f if self.is_video(f)       => Fixed(135).normal(),
            f if self.is_music(f)       => Fixed(92).normal(),
            f if self.is_lossless(f)    => Fixed(93).normal(),
            f if self.is_crypto(f)      => Fixed(109).normal(),
            f if self.is_document(f)    => Fixed(105).normal(),
            f if self.is_compressed(f)  => Red.normal(),
            f if self.is_temp(f)        => Fixed(244).normal(),
            f if self.is_compiled(f)    => Fixed(137).normal(),
            _                           => return None,
        })
    }
}
<commit_msg>Update filetype.rs<commit_after>//! Tests for various types of file (video, image, compressed, etc).
//!
//! Currently this is dependent on the file’s name and extension, because
//! those are the only metadata that we have access to without reading the
//! file’s contents.

use ansi_term::Style;

use fs::File;
use output::file_name::FileColours;

#[derive(Debug, Default, PartialEq)]
pub struct FileExtensions;

impl FileExtensions {

    /// An “immediate” file is something that can be run or activated somehow
    /// in order to kick off the build of a project. It’s usually only present
    /// in directories full of source code.
    fn is_immediate(&self, file: &File) -> bool {
        file.name.starts_with("README") || file.name_is_one_of( &[
            "Makefile", "Cargo.toml", "SConstruct", "CMakeLists.txt",
            "build.gradle", "Rakefile", "Gruntfile.js",
            "Gruntfile.coffee",
        ])
    }

    fn is_image(&self, file: &File) -> bool {
        file.extension_is_one_of( &[
            "png", "jpeg", "jpg", "gif", "bmp", "tiff", "tif",
            "ppm", "pgm", "pbm", "pnm", "webp", "raw", "arw",
            "svg", "stl", "eps", "dvi", "ps", "cbr",
            "cbz", "xpm", "ico", "cr2", "orf", "nef",
        ])
    }

    fn is_video(&self, file: &File) -> bool {
        file.extension_is_one_of( &[
            "avi", "flv", "m2v", "mkv", "mov", "mp4", "mpeg",
            "mpg", "ogm", "ogv", "vob", "wmv", "webm", "m2ts",
            "ts",
        ])
    }

    fn is_music(&self, file: &File) -> bool {
        file.extension_is_one_of( &[
            "aac", "m4a", "mp3", "ogg", "wma", "mka", "opus",
        ])
    }

    // Lossless music, rather than any other kind of data...
    fn is_lossless(&self, file: &File) -> bool {
        file.extension_is_one_of( &[
            "alac", "ape", "flac", "wav",
        ])
    }

    fn is_crypto(&self, file: &File) -> bool {
        file.extension_is_one_of( &[
            "asc", "enc", "gpg", "pgp", "sig", "signature", "pfx", "p12",
        ])
    }

    fn is_document(&self, file: &File) -> bool {
        file.extension_is_one_of( &[
            "djvu", "doc", "docx", "dvi", "eml", "eps", "fotd",
            "odp", "odt", "pdf", "ppt", "pptx", "rtf",
            "xls", "xlsx",
        ])
    }

    fn is_compressed(&self, file: &File) -> bool {
        file.extension_is_one_of( &[
            "zip", "tar", "Z", "z", "gz", "bz2", "a", "ar", "7z",
            "iso", "dmg", "tc", "rar", "par", "tgz", "xz", "txz",
            "lzma", "deb", "rpm", "zst",
        ])
    }

    fn is_temp(&self, file: &File) -> bool {
        file.name.ends_with('~')
            || (file.name.starts_with('#') && file.name.ends_with('#'))
            || file.extension_is_one_of( &[ "tmp", "swp", "swo", "swn", "bak", "bk" ])
    }

    fn is_compiled(&self, file: &File) -> bool {
        if file.extension_is_one_of( &[ "class", "elc", "hi", "o", "pyc" ]) {
            true
        }
        else if let Some(dir) = file.parent_dir {
            file.get_source_files().iter().any(|path| dir.contains(path))
        }
        else {
            false
        }
    }
}

impl FileColours for FileExtensions {
    fn colour_file(&self, file: &File) -> Option<Style> {
        use ansi_term::Colour::*;

        Some(match file {
            f if self.is_immediate(f)   => Yellow.bold().underline(),
            f if self.is_image(f)       => Fixed(133).normal(),
            f if self.is_video(f)       => Fixed(135).normal(),
            f if self.is_music(f)       => Fixed(92).normal(),
            f if self.is_lossless(f)    => Fixed(93).normal(),
            f if self.is_crypto(f)      => Fixed(109).normal(),
            f if self.is_document(f)    => Fixed(105).normal(),
            f if self.is_compressed(f)  => Red.normal(),
            f if self.is_temp(f)        => Fixed(244).normal(),
            f if self.is_compiled(f)    => Fixed(137).normal(),
            _                           => return None,
        })
    }
}
<|endoftext|>


<commit_before>//! Internal traits and functions used to implement parallel
//! iteration. These should be considered highly unstable: users of
//! parallel iterators should not need to interact with them directly.
//! See `README.md` for a high-level overview.

use rayon_core::join;
use super::IndexedParallelIterator;

use std::cmp;
use std::usize;

pub trait ProducerCallback<T> {
    type Output;
    fn callback<P>(self, producer: P) -> Self::Output where P: Producer<Item = T>;
}

/// A producer which will produce a fixed number of items N. This is
/// not queryable through the API; the consumer is expected to track
/// it.
pub trait Producer: Send + Sized {
    // Rust issue https://github.com/rust-lang/rust/issues/20671
    // prevents us from declaring the DoubleEndedIterator and
    // ExactSizeIterator constraints on a required IntoIterator trait,
    // so we inline IntoIterator here until that issue is fixed.
    type Item;
    type IntoIter: Iterator<Item = Self::Item> + DoubleEndedIterator + ExactSizeIterator;

    fn into_iter(self) -> Self::IntoIter;

    fn min_len(&self) -> usize { 1 }
    fn max_len(&self) -> usize { usize::MAX }

    /// Split into two producers; one produces items `0..index`, the
    /// other `index..N`. Index must be less than or equal to `N`.
    fn split_at(self, index: usize) -> (Self, Self);

    /// Iterate the producer, feeding each element to `folder`, and
    /// stop when the folder is full (or all elements have been consumed).
    ///
    /// The provided implementation is sufficient for most iterables.
    fn fold_with<F>(self, folder: F) -> F
        where F: Folder<Self::Item>
    {
        folder.consume_iter(self.into_iter())
    }
}

/// A consumer which consumes items that are fed to it.
pub trait Consumer<Item>: Send + Sized {
    type Folder: Folder<Item, Result = Self::Result>;
    type Reducer: Reducer<Self::Result>;
    type Result: Send;

    /// Divide the consumer into two consumers, one processing items
    /// `0..index` and one processing items from `index..`. Also
    /// produces a reducer that can be used to reduce the results at
    /// the end.
    fn split_at(self, index: usize) -> (Self, Self, Self::Reducer);

    /// Convert the consumer into a folder that can consume items
    /// sequentially, eventually producing a final result.
    fn into_folder(self) -> Self::Folder;

    /// Hint whether this `Consumer` would like to stop processing
    /// further items, e.g. if a search has been completed.
    fn full(&self) -> bool {
        false
    }
}

pub trait Folder<Item>: Sized {
    type Result;

    /// Consume next item and return new sequential state.
    fn consume(self, item: Item) -> Self;

    /// Consume items from the iterator until full, and return new sequential state.
    fn consume_iter<I>(mut self, iter: I) -> Self
        where I: IntoIterator<Item = Item>
    {
        for item in iter {
            self = self.consume(item);
            if self.full() {
                break;
            }
        }
        self
    }

    /// Finish consuming items, produce final result.
    fn complete(self) -> Self::Result;

    /// Hint whether this `Folder` would like to stop processing
    /// further items, e.g. if a search has been completed.
    fn full(&self) -> bool {
        false
    }
}

pub trait Reducer<Result> {
    /// Reduce two final results into one; this is executed after a
    /// split.
    fn reduce(self, left: Result, right: Result) -> Result;
}

/// A stateless consumer can be freely copied.
pub trait UnindexedConsumer<I>: Consumer<I> {
    // The result of split_off_left should be used for the left side of the
    // data it consumes, and the remaining consumer for the right side
    // (this matters for methods like find_first).
    fn split_off_left(&self) -> Self;
    fn to_reducer(&self) -> Self::Reducer;
}

/// An unindexed producer that doesn't know its exact length.
/// (or can't represent its known length in a `usize`)
pub trait UnindexedProducer: Send + Sized {
    type Item;

    /// Split midway into a new producer if possible, otherwise return `None`.
    fn split(self) -> (Self, Option<Self>);

    /// Iterate the producer, feeding each element to `folder`, and
    /// stop when the folder is full (or all elements have been consumed).
    fn fold_with<F>(self, folder: F) -> F where F: Folder<Self::Item>;
}

/// A splitter controls the policy for splitting into smaller work items.
///
/// Thief-splitting is an adaptive policy that starts by splitting into
/// enough jobs for every worker thread, and then resets itself whenever a
/// job is actually stolen into a different thread.
#[derive(Clone, Copy)]
struct Splitter {
    origin: usize,
    splits: usize,
}

impl Splitter {
    #[inline]
    fn thief_id() -> usize {
        // The actual `ID` value is irrelevant.  We're just using its TLS
        // address as a unique thread key, faster than a real thread-id call.
        thread_local!{ static ID: bool = false }
        ID.with(|id| id as *const bool as usize)
    }

    #[inline]
    fn new() -> Splitter {
        Splitter {
            origin: Splitter::thief_id(),
            splits: ::current_num_threads(),
        }
    }

    #[inline]
    fn try(&mut self) -> bool {
        let Splitter { origin, splits } = *self;

        let id = Splitter::thief_id();
        if origin != id {
            self.origin = id;
            self.splits = cmp::max(::current_num_threads(), self.splits / 2);
            true
        } else if splits > 0 {
            self.splits /= 2;
            true
        } else {
            false
        }
    }
}

#[derive(Clone, Copy)]
struct LengthSplitter {
    inner: Splitter,
    min: usize,
}

impl LengthSplitter {
    #[inline]
    fn new(min: usize, max: usize, len: usize) -> LengthSplitter {
        let mut splitter = LengthSplitter {
            inner: Splitter::new(),
            min: cmp::max(min, 1),
        };

        let max_splits = len / cmp::max(max, 1);
        if max_splits > splitter.inner.splits {
            splitter.inner.splits = max_splits;
        }

        splitter
    }

    #[inline]
    fn try(&mut self, len: usize) -> bool {
        len / 2 >= self.min && self.inner.try()
    }
}

pub fn bridge<I, C>(mut par_iter: I, consumer: C) -> C::Result
    where I: IndexedParallelIterator,
          C: Consumer<I::Item>
{
    let len = par_iter.len();
    return par_iter.with_producer(Callback {
                                      len: len,
                                      consumer: consumer,
                                  });

    struct Callback<C> {
        len: usize,
        consumer: C,
    }

    impl<C, I> ProducerCallback<I> for Callback<C>
        where C: Consumer<I>
    {
        type Output = C::Result;
        fn callback<P>(self, producer: P) -> C::Result
            where P: Producer<Item = I>
        {
            bridge_producer_consumer(self.len, producer, self.consumer)
        }
    }
}

pub fn bridge_producer_consumer<P, C>(len: usize, producer: P, consumer: C) -> C::Result
    where P: Producer,
          C: Consumer<P::Item>
{
    let splitter = LengthSplitter::new(producer.min_len(), producer.max_len(), len);
    return helper(len, splitter, producer, consumer);

    fn helper<P, C>(len: usize, mut splitter: LengthSplitter, producer: P, consumer: C) -> C::Result
        where P: Producer,
              C: Consumer<P::Item>
    {
        if consumer.full() {
            consumer.into_folder().complete()
        } else if splitter.try(len) {
            let mid = len / 2;
            let (left_producer, right_producer) = producer.split_at(mid);
            let (left_consumer, right_consumer, reducer) = consumer.split_at(mid);
            let (left_result, right_result) =
                join(|| helper(mid, splitter, left_producer, left_consumer),
                     || helper(len - mid, splitter, right_producer, right_consumer));
            reducer.reduce(left_result, right_result)
        } else {
            producer.fold_with(consumer.into_folder()).complete()
        }
    }
}

pub fn bridge_unindexed<P, C>(producer: P, consumer: C) -> C::Result
    where P: UnindexedProducer,
          C: UnindexedConsumer<P::Item>
{
    let splitter = Splitter::new();
    bridge_unindexed_producer_consumer(splitter, producer, consumer)
}

fn bridge_unindexed_producer_consumer<P, C>(mut splitter: Splitter,
                                            producer: P,
                                            consumer: C)
                                            -> C::Result
    where P: UnindexedProducer,
          C: UnindexedConsumer<P::Item>
{
    if consumer.full() {
        consumer.into_folder().complete()
    } else if splitter.try() {
        match producer.split() {
            (left_producer, Some(right_producer)) => {
                let (reducer, left_consumer, right_consumer) =
                    (consumer.to_reducer(), consumer.split_off_left(), consumer);
                let bridge = bridge_unindexed_producer_consumer;
                let (left_result, right_result) =
                    join(|| bridge(splitter, left_producer, left_consumer),
                         || bridge(splitter, right_producer, right_consumer));
                reducer.reduce(left_result, right_result)
            }
            (producer, None) => producer.fold_with(consumer.into_folder()).complete(),
        }
    } else {
        producer.fold_with(consumer.into_folder()).complete()
    }
}

<commit_msg>Document the splitters, and rename to min_splits<commit_after>//! Internal traits and functions used to implement parallel
//! iteration. These should be considered highly unstable: users of
//! parallel iterators should not need to interact with them directly.
//! See `README.md` for a high-level overview.

use rayon_core::join;
use super::IndexedParallelIterator;

use std::cmp;
use std::usize;

pub trait ProducerCallback<T> {
    type Output;
    fn callback<P>(self, producer: P) -> Self::Output where P: Producer<Item = T>;
}

/// A producer which will produce a fixed number of items N. This is
/// not queryable through the API; the consumer is expected to track
/// it.
pub trait Producer: Send + Sized {
    // Rust issue https://github.com/rust-lang/rust/issues/20671
    // prevents us from declaring the DoubleEndedIterator and
    // ExactSizeIterator constraints on a required IntoIterator trait,
    // so we inline IntoIterator here until that issue is fixed.
    type Item;
    type IntoIter: Iterator<Item = Self::Item> + DoubleEndedIterator + ExactSizeIterator;

    fn into_iter(self) -> Self::IntoIter;

    fn min_len(&self) -> usize { 1 }
    fn max_len(&self) -> usize { usize::MAX }

    /// Split into two producers; one produces items `0..index`, the
    /// other `index..N`. Index must be less than or equal to `N`.
    fn split_at(self, index: usize) -> (Self, Self);

    /// Iterate the producer, feeding each element to `folder`, and
    /// stop when the folder is full (or all elements have been consumed).
    ///
    /// The provided implementation is sufficient for most iterables.
    fn fold_with<F>(self, folder: F) -> F
        where F: Folder<Self::Item>
    {
        folder.consume_iter(self.into_iter())
    }
}

/// A consumer which consumes items that are fed to it.
pub trait Consumer<Item>: Send + Sized {
    type Folder: Folder<Item, Result = Self::Result>;
    type Reducer: Reducer<Self::Result>;
    type Result: Send;

    /// Divide the consumer into two consumers, one processing items
    /// `0..index` and one processing items from `index..`. Also
    /// produces a reducer that can be used to reduce the results at
    /// the end.
    fn split_at(self, index: usize) -> (Self, Self, Self::Reducer);

    /// Convert the consumer into a folder that can consume items
    /// sequentially, eventually producing a final result.
    fn into_folder(self) -> Self::Folder;

    /// Hint whether this `Consumer` would like to stop processing
    /// further items, e.g. if a search has been completed.
    fn full(&self) -> bool {
        false
    }
}

pub trait Folder<Item>: Sized {
    type Result;

    /// Consume next item and return new sequential state.
    fn consume(self, item: Item) -> Self;

    /// Consume items from the iterator until full, and return new sequential state.
    fn consume_iter<I>(mut self, iter: I) -> Self
        where I: IntoIterator<Item = Item>
    {
        for item in iter {
            self = self.consume(item);
            if self.full() {
                break;
            }
        }
        self
    }

    /// Finish consuming items, produce final result.
    fn complete(self) -> Self::Result;

    /// Hint whether this `Folder` would like to stop processing
    /// further items, e.g. if a search has been completed.
    fn full(&self) -> bool {
        false
    }
}

pub trait Reducer<Result> {
    /// Reduce two final results into one; this is executed after a
    /// split.
    fn reduce(self, left: Result, right: Result) -> Result;
}

/// A stateless consumer can be freely copied.
pub trait UnindexedConsumer<I>: Consumer<I> {
    // The result of split_off_left should be used for the left side of the
    // data it consumes, and the remaining consumer for the right side
    // (this matters for methods like find_first).
    fn split_off_left(&self) -> Self;
    fn to_reducer(&self) -> Self::Reducer;
}

/// An unindexed producer that doesn't know its exact length.
/// (or can't represent its known length in a `usize`)
pub trait UnindexedProducer: Send + Sized {
    type Item;

    /// Split midway into a new producer if possible, otherwise return `None`.
    fn split(self) -> (Self, Option<Self>);

    /// Iterate the producer, feeding each element to `folder`, and
    /// stop when the folder is full (or all elements have been consumed).
    fn fold_with<F>(self, folder: F) -> F where F: Folder<Self::Item>;
}

/// A splitter controls the policy for splitting into smaller work items.
///
/// Thief-splitting is an adaptive policy that starts by splitting into
/// enough jobs for every worker thread, and then resets itself whenever a
/// job is actually stolen into a different thread.
#[derive(Clone, Copy)]
struct Splitter {

    /// The `origin` tracks the ID of the thread that started this job,
    /// so we can tell when we've been stolen to a new thread.
    origin: usize,

    /// The `splits` tell us approximately how many remaining times we'd
    /// like to split this job.  We always just divide it by two though, so
    /// the effective number of pieces will be `next_power_of_two()`.
    splits: usize,
}

impl Splitter {
    #[inline]
    fn thief_id() -> usize {
        // The actual `ID` value is irrelevant.  We're just using its TLS
        // address as a unique thread key, faster than a real thread-id call.
        thread_local!{ static ID: bool = false }
        ID.with(|id| id as *const bool as usize)
    }

    #[inline]
    fn new() -> Splitter {
        Splitter {
            origin: Splitter::thief_id(),
            splits: ::current_num_threads(),
        }
    }

    #[inline]
    fn try(&mut self) -> bool {
        let Splitter { origin, splits } = *self;

        let id = Splitter::thief_id();
        if origin != id {
            // This job was stolen!  Set a new origin and reset the number
            // of desired splits to the thread count, if that's more than
            // we had remaining anyway.
            self.origin = id;
            self.splits = cmp::max(::current_num_threads(), self.splits / 2);
            true
        } else if splits > 0 {
            // We have splits remaining, make it so.
            self.splits /= 2;
            true
        } else {
            // Not stolen, and no more splits -- we're done!
            false
        }
    }
}

/// The length splitter is built on thief-splitting, but additionally takes
/// into account the remaining length of the iterator.
#[derive(Clone, Copy)]
struct LengthSplitter {
    inner: Splitter,

    /// The smallest we're willing to divide into.  Usually this is just 1,
    /// but you can choose a larger working size with `set_min_len()`.
    min: usize,
}

impl LengthSplitter {
    /// Create a new splitter based on lengths.
    ///
    /// The `min` is a hard lower bound.  We'll never split below that, but
    /// of course an iterator might start out smaller already.
    ///
    /// The `max` is an upper bound on the working size, used to determine
    /// the minimum number of times we need to split to get under that limit.
    /// The adaptive algorithm may very well split even further, but never
    /// smaller than the `min`.
    #[inline]
    fn new(min: usize, max: usize, len: usize) -> LengthSplitter {
        let mut splitter = LengthSplitter {
            inner: Splitter::new(),
            min: cmp::max(min, 1),
        };

        // Divide the given length by the max working lenght to get the minimum
        // number of splits we need to get under that max.  This rounds down,
        // but the splitter actually gives `next_power_of_two()` pieces anyway.
        // e.g. len 12345 / max 100 = 123 min_splits -> 128 pieces.
        let min_splits = len / cmp::max(max, 1);

        // Only update the value if it's not splitting enough already.
        if min_splits > splitter.inner.splits {
            splitter.inner.splits = min_splits;
        }

        splitter
    }

    #[inline]
    fn try(&mut self, len: usize) -> bool {
        // If splitting wouldn't make us too small, try the inner splitter.
        len / 2 >= self.min && self.inner.try()
    }
}

pub fn bridge<I, C>(mut par_iter: I, consumer: C) -> C::Result
    where I: IndexedParallelIterator,
          C: Consumer<I::Item>
{
    let len = par_iter.len();
    return par_iter.with_producer(Callback {
                                      len: len,
                                      consumer: consumer,
                                  });

    struct Callback<C> {
        len: usize,
        consumer: C,
    }

    impl<C, I> ProducerCallback<I> for Callback<C>
        where C: Consumer<I>
    {
        type Output = C::Result;
        fn callback<P>(self, producer: P) -> C::Result
            where P: Producer<Item = I>
        {
            bridge_producer_consumer(self.len, producer, self.consumer)
        }
    }
}

pub fn bridge_producer_consumer<P, C>(len: usize, producer: P, consumer: C) -> C::Result
    where P: Producer,
          C: Consumer<P::Item>
{
    let splitter = LengthSplitter::new(producer.min_len(), producer.max_len(), len);
    return helper(len, splitter, producer, consumer);

    fn helper<P, C>(len: usize, mut splitter: LengthSplitter, producer: P, consumer: C) -> C::Result
        where P: Producer,
              C: Consumer<P::Item>
    {
        if consumer.full() {
            consumer.into_folder().complete()
        } else if splitter.try(len) {
            let mid = len / 2;
            let (left_producer, right_producer) = producer.split_at(mid);
            let (left_consumer, right_consumer, reducer) = consumer.split_at(mid);
            let (left_result, right_result) =
                join(|| helper(mid, splitter, left_producer, left_consumer),
                     || helper(len - mid, splitter, right_producer, right_consumer));
            reducer.reduce(left_result, right_result)
        } else {
            producer.fold_with(consumer.into_folder()).complete()
        }
    }
}

pub fn bridge_unindexed<P, C>(producer: P, consumer: C) -> C::Result
    where P: UnindexedProducer,
          C: UnindexedConsumer<P::Item>
{
    let splitter = Splitter::new();
    bridge_unindexed_producer_consumer(splitter, producer, consumer)
}

fn bridge_unindexed_producer_consumer<P, C>(mut splitter: Splitter,
                                            producer: P,
                                            consumer: C)
                                            -> C::Result
    where P: UnindexedProducer,
          C: UnindexedConsumer<P::Item>
{
    if consumer.full() {
        consumer.into_folder().complete()
    } else if splitter.try() {
        match producer.split() {
            (left_producer, Some(right_producer)) => {
                let (reducer, left_consumer, right_consumer) =
                    (consumer.to_reducer(), consumer.split_off_left(), consumer);
                let bridge = bridge_unindexed_producer_consumer;
                let (left_result, right_result) =
                    join(|| bridge(splitter, left_producer, left_consumer),
                         || bridge(splitter, right_producer, right_consumer));
                reducer.reduce(left_result, right_result)
            }
            (producer, None) => producer.fold_with(consumer.into_folder()).complete(),
        }
    } else {
        producer.fold_with(consumer.into_folder()).complete()
    }
}

<|endoftext|>


<commit_before>use std::io::{stdout, stderr, Write};

use argparse::{ArgumentParser, StoreTrue};

use config::Config;

pub fn print_list(config: &Config, mut args: Vec<String>)
    -> Result<i32, String>
{
    let mut all = false;
    let mut builtin = false;
    let mut hidden = false;
    let mut containers = false;
    {
        args.insert(0, String::from("vagga _list"));
        let mut ap = ArgumentParser::new();
        ap.refer(&mut containers)
            .add_option(&["--containers"], StoreTrue,
                "Show containers instead of commands");
        ap.refer(&mut all)
            .add_option(&["-A", "--all"], StoreTrue,
                "Show all commands");
        ap.refer(&mut builtin)
            .add_option(&["--builtin"], StoreTrue,
                "Show built-in commands (starting with underscore)");
        ap.refer(&mut hidden)
            .add_option(&["--hidden"], StoreTrue,
                "Show hidden commands");
        match ap.parse(args, &mut stdout(), &mut stderr()) {
            Ok(()) => {}
            Err(x) => return Ok(x),
        }
    }
    if containers {
        for (cname, _) in config.containers.iter() {
            println!("{}", cname);
        }
    } else {
        let mut out = stdout();
        for (k, cmd) in config.commands.iter() {
            if k.starts_with("_") && !hidden {
                continue;
            }
            out.write_all(k.as_bytes()).ok();
            match cmd.description() {
                Some(ref val) => {
                    if k.len() > 19 {
                        out.write_all(b"\n                    ").ok();
                    } else {
                        for _ in k.len()..19 {
                            out.write_all(b" ").ok();
                        }
                        out.write_all(b" ").ok();
                    }
                    out.write_all(val.as_bytes()).ok();
                }
                None => {}
            }
            out.write_all(b"\n").ok();
        }

        if all || builtin {
            // TODO(tailhook) fetch builtins from completion code
            write!(&mut out, "\
                _build              Build a container\n\
                _run                Run arbitrary command, \
                                    optionally building container\n\
                _clean              Clean containers and build artifacts\n\
                _list               List of built-in commands\n\
            ").ok();
        }
    }
    return Ok(0);
}

pub fn print_help(config: &Config)
    -> Result<i32, String>
{
    let mut err = stderr();
    writeln!(&mut err, "Available commands:").ok();
    for (k, cmd) in config.commands.iter() {
        if k.starts_with("_") {
            continue;
        }
        write!(&mut err, "    {}", k).ok();
        match cmd.description() {
            Some(ref val) => {
                if k.len() > 19 {
                    write!(&mut err, "\n                        ").ok();
                } else {
                    for _ in k.len()..19 {
                        err.write_all(b" ").ok();
                    }
                    err.write_all(b" ").ok();
                }
                err.write_all(val[..].as_bytes()).ok();
            }
            None => {}
        }
        err.write_all(b"\n").ok();
    }
    Ok(127)
}
<commit_msg>fix multiline command description indentation<commit_after>use std::io::{stdout, stderr, Write};

use argparse::{ArgumentParser, StoreTrue};

use config::Config;

pub fn print_list(config: &Config, mut args: Vec<String>)
    -> Result<i32, String>
{
    let mut all = false;
    let mut builtin = false;
    let mut hidden = false;
    let mut containers = false;
    {
        args.insert(0, String::from("vagga _list"));
        let mut ap = ArgumentParser::new();
        ap.refer(&mut containers)
            .add_option(&["--containers"], StoreTrue,
                "Show containers instead of commands");
        ap.refer(&mut all)
            .add_option(&["-A", "--all"], StoreTrue,
                "Show all commands");
        ap.refer(&mut builtin)
            .add_option(&["--builtin"], StoreTrue,
                "Show built-in commands (starting with underscore)");
        ap.refer(&mut hidden)
            .add_option(&["--hidden"], StoreTrue,
                "Show hidden commands");
        match ap.parse(args, &mut stdout(), &mut stderr()) {
            Ok(()) => {}
            Err(x) => return Ok(x),
        }
    }
    if containers {
        for (cname, _) in config.containers.iter() {
            println!("{}", cname);
        }
    } else {
        let mut out = stdout();
        for (k, cmd) in config.commands.iter() {
            if k.starts_with("_") && !hidden {
                continue;
            }
            out.write_all(k.as_bytes()).ok();
            match cmd.description() {
                Some(ref val) => {
                    if k.len() > 19 {
                        out.write_all(b"\n                    ").ok();
                    } else {
                        for _ in k.len()..19 {
                            out.write_all(b" ").ok();
                        }
                        out.write_all(b" ").ok();
                    }
                    if val.contains("\n") {
                        for line in val.lines() {
                            out.write_all(line.as_bytes()).ok();
                            out.write_all(b"\n                    ").ok();
                        };
                    } else {
                        out.write_all(val.as_bytes()).ok();
                    }
                }
                None => {}
            }
            out.write_all(b"\n").ok();
        }

        if all || builtin {
            // TODO(tailhook) fetch builtins from completion code
            write!(&mut out, "\
                _build              Build a container\n\
                _run                Run arbitrary command, \
                                    optionally building container\n\
                _clean              Clean containers and build artifacts\n\
                _list               List of built-in commands\n\
            ").ok();
        }
    }
    return Ok(0);
}

pub fn print_help(config: &Config)
    -> Result<i32, String>
{
    let mut err = stderr();
    writeln!(&mut err, "Available commands:").ok();
    for (k, cmd) in config.commands.iter() {
        if k.starts_with("_") {
            continue;
        }
        write!(&mut err, "    {}", k).ok();
        match cmd.description() {
            Some(ref val) => {
                if k.len() > 19 {
                    err.write_all(b"\n                        ").ok();
                } else {
                    for _ in k.len()..19 {
                        err.write_all(b" ").ok();
                    }
                    err.write_all(b" ").ok();
                }
                if val.contains("\n") {
                    for line in val.lines() {
                        err.write_all(line.as_bytes()).ok();
                        err.write_all(b"\n                        ").ok();
                    };
                } else {
                    err.write_all(val.as_bytes()).ok();
                }
            }
            None => {}
        }
        err.write_all(b"\n").ok();
    }
    Ok(127)
}
<|endoftext|>


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

//! Primitive traits representing basic 'kinds' of types
//!
//! Rust types can be classified in various useful ways according to
//! intrinsic properties of the type. These classifications, often called
//! 'kinds', are represented as traits.
//!
//! They cannot be implemented by user code, but are instead implemented
//! by the compiler automatically for the types to which they apply.

/// Types able to be transferred across task boundaries.
#[lang="send"]
pub trait Send for Sized? : 'static {
    // empty.
}

/// Types with a constant size known at compile-time.
#[lang="sized"]
pub trait Sized for Sized? {
    // Empty.
}

/// Types that can be copied by simply copying bits (i.e. `memcpy`).
#[lang="copy"]
pub trait Copy for Sized? {
    // Empty.
}

/// Types that can be safely shared between tasks when aliased.
///
/// The precise definition is: a type `T` is `Sync` if `&T` is
/// thread-safe. In other words, there is no possibility of data races
/// when passing `&T` references between tasks.
///
/// As one would expect, primitive types like `u8` and `f64` are all
/// `Sync`, and so are simple aggregate types containing them (like
/// tuples, structs and enums). More instances of basic `Sync` types
/// include "immutable" types like `&T` and those with simple
/// inherited mutability, such as `Box<T>`, `Vec<T>` and most other
/// collection types. (Generic parameters need to be `Sync` for their
/// container to be `Sync`.)
///
/// A somewhat surprising consequence of the definition is `&mut T` is
/// `Sync` (if `T` is `Sync`) even though it seems that it might
/// provide unsynchronised mutation. The trick is a mutable reference
/// stored in an aliasable reference (that is, `& &mut T`) becomes
/// read-only, as if it were a `& &T`, hence there is no risk of a data
/// race.
///
/// Types that are not `Sync` are those that have "interior
/// mutability" in a non-thread-safe way, such as `Cell` and `RefCell`
/// in `std::cell`. These types allow for mutation of their contents
/// even when in an immutable, aliasable slot, e.g. the contents of
/// `&Cell<T>` can be `.set`, and do not ensure data races are
/// impossible, hence they cannot be `Sync`. A higher level example
/// of a non-`Sync` type is the reference counted pointer
/// `std::rc::Rc`, because any reference `&Rc<T>` can clone a new
/// reference, which modifies the reference counts in a non-atomic
/// way.
///
/// For cases when one does need thread-safe interior mutability,
/// types like the atomics in `std::sync` and `Mutex` & `RWLock` in
/// the `sync` crate do ensure that any mutation cannot cause data
/// races.  Hence these types are `Sync`.
///
/// Users writing their own types with interior mutability (or anything
/// else that is not thread-safe) should use the `NoSync` marker type
/// (from `std::kinds::marker`) to ensure that the compiler doesn't
/// consider the user-defined type to be `Sync`.  Any types with
/// interior mutability must also use the `std::cell::UnsafeCell` wrapper
/// around the value(s) which can be mutated when behind a `&`
/// reference; not doing this is undefined behaviour (for example,
/// `transmute`-ing from `&T` to `&mut T` is illegal).
#[lang="sync"]
pub trait Sync for Sized? {
    // Empty
}

/// Marker types are special types that are used with unsafe code to
/// inform the compiler of special constraints. Marker types should
/// only be needed when you are creating an abstraction that is
/// implemented using unsafe code. In that case, you may want to embed
/// some of the marker types below into your type.
pub mod marker {
    use super::Copy;

    /// A marker type whose type parameter `T` is considered to be
    /// covariant with respect to the type itself. This is (typically)
    /// used to indicate that an instance of the type `T` is being stored
    /// into memory and read from, even though that may not be apparent.
    ///
    /// For more information about variance, refer to this Wikipedia
    /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
    ///
    /// *Note:* It is very unusual to have to add a covariant constraint.
    /// If you are not sure, you probably want to use `InvariantType`.
    ///
    /// # Example
    ///
    /// Given a struct `S` that includes a type parameter `T`
    /// but does not actually *reference* that type parameter:
    ///
    /// ```ignore
    /// use std::mem;
    ///
    /// struct S<T> { x: *() }
    /// fn get<T>(s: &S<T>) -> T {
    ///    unsafe {
    ///        let x: *T = mem::transmute(s.x);
    ///        *x
    ///    }
    /// }
    /// ```
    ///
    /// The type system would currently infer that the value of
    /// the type parameter `T` is irrelevant, and hence a `S<int>` is
    /// a subtype of `S<Box<int>>` (or, for that matter, `S<U>` for
    /// any `U`). But this is incorrect because `get()` converts the
    /// `*()` into a `*T` and reads from it. Therefore, we should include the
    /// a marker field `CovariantType<T>` to inform the type checker that
    /// `S<T>` is a subtype of `S<U>` if `T` is a subtype of `U`
    /// (for example, `S<&'static int>` is a subtype of `S<&'a int>`
    /// for some lifetime `'a`, but not the other way around).
    #[lang="covariant_type"]
    #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
    pub struct CovariantType<T>;

    impl<T> Copy for CovariantType<T> {}

    /// A marker type whose type parameter `T` is considered to be
    /// contravariant with respect to the type itself. This is (typically)
    /// used to indicate that an instance of the type `T` will be consumed
    /// (but not read from), even though that may not be apparent.
    ///
    /// For more information about variance, refer to this Wikipedia
    /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
    ///
    /// *Note:* It is very unusual to have to add a contravariant constraint.
    /// If you are not sure, you probably want to use `InvariantType`.
    ///
    /// # Example
    ///
    /// Given a struct `S` that includes a type parameter `T`
    /// but does not actually *reference* that type parameter:
    ///
    /// ```
    /// use std::mem;
    ///
    /// struct S<T> { x: *const () }
    /// fn get<T>(s: &S<T>, v: T) {
    ///    unsafe {
    ///        let x: fn(T) = mem::transmute(s.x);
    ///        x(v)
    ///    }
    /// }
    /// ```
    ///
    /// The type system would currently infer that the value of
    /// the type parameter `T` is irrelevant, and hence a `S<int>` is
    /// a subtype of `S<Box<int>>` (or, for that matter, `S<U>` for
    /// any `U`). But this is incorrect because `get()` converts the
    /// `*()` into a `fn(T)` and then passes a value of type `T` to it.
    ///
    /// Supplying a `ContravariantType` marker would correct the
    /// problem, because it would mark `S` so that `S<T>` is only a
    /// subtype of `S<U>` if `U` is a subtype of `T`; given that the
    /// function requires arguments of type `T`, it must also accept
    /// arguments of type `U`, hence such a conversion is safe.
    #[lang="contravariant_type"]
    #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
    pub struct ContravariantType<T>;

    impl<T> Copy for ContravariantType<T> {}

    /// A marker type whose type parameter `T` is considered to be
    /// invariant with respect to the type itself. This is (typically)
    /// used to indicate that instances of the type `T` may be read or
    /// written, even though that may not be apparent.
    ///
    /// For more information about variance, refer to this Wikipedia
    /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
    ///
    /// # Example
    ///
    /// The Cell type is an example which uses unsafe code to achieve
    /// "interior" mutability:
    ///
    /// ```
    /// pub struct Cell<T> { value: T }
    /// # fn main() {}
    /// ```
    ///
    /// The type system would infer that `value` is only read here and
    /// never written, but in fact `Cell` uses unsafe code to achieve
    /// interior mutability.
    #[lang="invariant_type"]
    #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
    pub struct InvariantType<T>;

    impl<T> Copy for InvariantType<T> {}

    /// As `CovariantType`, but for lifetime parameters. Using
    /// `CovariantLifetime<'a>` indicates that it is ok to substitute
    /// a *longer* lifetime for `'a` than the one you originally
    /// started with (e.g., you could convert any lifetime `'foo` to
    /// `'static`). You almost certainly want `ContravariantLifetime`
    /// instead, or possibly `InvariantLifetime`. The only case where
    /// it would be appropriate is that you have a (type-casted, and
    /// hence hidden from the type system) function pointer with a
    /// signature like `fn(&'a T)` (and no other uses of `'a`). In
    /// this case, it is ok to substitute a larger lifetime for `'a`
    /// (e.g., `fn(&'static T)`), because the function is only
    /// becoming more selective in terms of what it accepts as
    /// argument.
    ///
    /// For more information about variance, refer to this Wikipedia
    /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
    #[lang="covariant_lifetime"]
    #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
    pub struct CovariantLifetime<'a>;

    impl<'a> Copy for CovariantLifetime<'a> {}

    /// As `ContravariantType`, but for lifetime parameters. Using
    /// `ContravariantLifetime<'a>` indicates that it is ok to
    /// substitute a *shorter* lifetime for `'a` than the one you
    /// originally started with (e.g., you could convert `'static` to
    /// any lifetime `'foo`). This is appropriate for cases where you
    /// have an unsafe pointer that is actually a pointer into some
    /// memory with lifetime `'a`, and thus you want to limit the
    /// lifetime of your data structure to `'a`. An example of where
    /// this is used is the iterator for vectors.
    ///
    /// For more information about variance, refer to this Wikipedia
    /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
    #[lang="contravariant_lifetime"]
    #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
    pub struct ContravariantLifetime<'a>;

    impl<'a> Copy for ContravariantLifetime<'a> {}

    /// As `InvariantType`, but for lifetime parameters. Using
    /// `InvariantLifetime<'a>` indicates that it is not ok to
    /// substitute any other lifetime for `'a` besides its original
    /// value. This is appropriate for cases where you have an unsafe
    /// pointer that is actually a pointer into memory with lifetime `'a`,
    /// and this pointer is itself stored in an inherently mutable
    /// location (such as a `Cell`).
    #[lang="invariant_lifetime"]
    #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
    pub struct InvariantLifetime<'a>;

    /// A type which is considered "not sendable", meaning that it cannot
    /// be safely sent between tasks, even if it is owned. This is
    /// typically embedded in other types, such as `Gc`, to ensure that
    /// their instances remain thread-local.
    #[lang="no_send_bound"]
    #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
    #[allow(missing_copy_implementations)]
    pub struct NoSend;

    /// A type which is considered "not POD", meaning that it is not
    /// implicitly copyable. This is typically embedded in other types to
    /// ensure that they are never copied, even if they lack a destructor.
    #[lang="no_copy_bound"]
    #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
    #[allow(missing_copy_implementations)]
    pub struct NoCopy;

    /// A type which is considered "not sync", meaning that
    /// its contents are not threadsafe, hence they cannot be
    /// shared between tasks.
    #[lang="no_sync_bound"]
    #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
    #[allow(missing_copy_implementations)]
    pub struct NoSync;

    /// A type which is considered managed by the GC. This is typically
    /// embedded in other types.
    #[lang="managed_bound"]
    #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
    #[allow(missing_copy_implementations)]
    pub struct Managed;
}

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

//! Primitive traits representing basic 'kinds' of types
//!
//! Rust types can be classified in various useful ways according to
//! intrinsic properties of the type. These classifications, often called
//! 'kinds', are represented as traits.
//!
//! They cannot be implemented by user code, but are instead implemented
//! by the compiler automatically for the types to which they apply.

/// Types able to be transferred across task boundaries.
#[lang="send"]
pub trait Send for Sized? : 'static {
    // empty.
}

/// Types with a constant size known at compile-time.
#[lang="sized"]
pub trait Sized for Sized? {
    // Empty.
}

/// Types that can be copied by simply copying bits (i.e. `memcpy`).
#[lang="copy"]
pub trait Copy for Sized? {
    // Empty.
}

/// Types that can be safely shared between tasks when aliased.
///
/// The precise definition is: a type `T` is `Sync` if `&T` is
/// thread-safe. In other words, there is no possibility of data races
/// when passing `&T` references between tasks.
///
/// As one would expect, primitive types like `u8` and `f64` are all
/// `Sync`, and so are simple aggregate types containing them (like
/// tuples, structs and enums). More instances of basic `Sync` types
/// include "immutable" types like `&T` and those with simple
/// inherited mutability, such as `Box<T>`, `Vec<T>` and most other
/// collection types. (Generic parameters need to be `Sync` for their
/// container to be `Sync`.)
///
/// A somewhat surprising consequence of the definition is `&mut T` is
/// `Sync` (if `T` is `Sync`) even though it seems that it might
/// provide unsynchronised mutation. The trick is a mutable reference
/// stored in an aliasable reference (that is, `& &mut T`) becomes
/// read-only, as if it were a `& &T`, hence there is no risk of a data
/// race.
///
/// Types that are not `Sync` are those that have "interior
/// mutability" in a non-thread-safe way, such as `Cell` and `RefCell`
/// in `std::cell`. These types allow for mutation of their contents
/// even when in an immutable, aliasable slot, e.g. the contents of
/// `&Cell<T>` can be `.set`, and do not ensure data races are
/// impossible, hence they cannot be `Sync`. A higher level example
/// of a non-`Sync` type is the reference counted pointer
/// `std::rc::Rc`, because any reference `&Rc<T>` can clone a new
/// reference, which modifies the reference counts in a non-atomic
/// way.
///
/// For cases when one does need thread-safe interior mutability,
/// types like the atomics in `std::sync` and `Mutex` & `RWLock` in
/// the `sync` crate do ensure that any mutation cannot cause data
/// races.  Hence these types are `Sync`.
///
/// Users writing their own types with interior mutability (or anything
/// else that is not thread-safe) should use the `NoSync` marker type
/// (from `std::kinds::marker`) to ensure that the compiler doesn't
/// consider the user-defined type to be `Sync`.  Any types with
/// interior mutability must also use the `std::cell::UnsafeCell` wrapper
/// around the value(s) which can be mutated when behind a `&`
/// reference; not doing this is undefined behaviour (for example,
/// `transmute`-ing from `&T` to `&mut T` is illegal).
#[lang="sync"]
pub trait Sync for Sized? {
    // Empty
}

/// Marker types are special types that are used with unsafe code to
/// inform the compiler of special constraints. Marker types should
/// only be needed when you are creating an abstraction that is
/// implemented using unsafe code. In that case, you may want to embed
/// some of the marker types below into your type.
pub mod marker {
    use super::Copy;

    /// A marker type whose type parameter `T` is considered to be
    /// covariant with respect to the type itself. This is (typically)
    /// used to indicate that an instance of the type `T` is being stored
    /// into memory and read from, even though that may not be apparent.
    ///
    /// For more information about variance, refer to this Wikipedia
    /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
    ///
    /// *Note:* It is very unusual to have to add a covariant constraint.
    /// If you are not sure, you probably want to use `InvariantType`.
    ///
    /// # Example
    ///
    /// Given a struct `S` that includes a type parameter `T`
    /// but does not actually *reference* that type parameter:
    ///
    /// ```ignore
    /// use std::mem;
    ///
    /// struct S<T> { x: *() }
    /// fn get<T>(s: &S<T>) -> T {
    ///    unsafe {
    ///        let x: *T = mem::transmute(s.x);
    ///        *x
    ///    }
    /// }
    /// ```
    ///
    /// The type system would currently infer that the value of
    /// the type parameter `T` is irrelevant, and hence a `S<int>` is
    /// a subtype of `S<Box<int>>` (or, for that matter, `S<U>` for
    /// any `U`). But this is incorrect because `get()` converts the
    /// `*()` into a `*T` and reads from it. Therefore, we should include the
    /// a marker field `CovariantType<T>` to inform the type checker that
    /// `S<T>` is a subtype of `S<U>` if `T` is a subtype of `U`
    /// (for example, `S<&'static int>` is a subtype of `S<&'a int>`
    /// for some lifetime `'a`, but not the other way around).
    #[lang="covariant_type"]
    #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
    pub struct CovariantType<T>;

    impl<T> Copy for CovariantType<T> {}

    /// A marker type whose type parameter `T` is considered to be
    /// contravariant with respect to the type itself. This is (typically)
    /// used to indicate that an instance of the type `T` will be consumed
    /// (but not read from), even though that may not be apparent.
    ///
    /// For more information about variance, refer to this Wikipedia
    /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
    ///
    /// *Note:* It is very unusual to have to add a contravariant constraint.
    /// If you are not sure, you probably want to use `InvariantType`.
    ///
    /// # Example
    ///
    /// Given a struct `S` that includes a type parameter `T`
    /// but does not actually *reference* that type parameter:
    ///
    /// ```
    /// use std::mem;
    ///
    /// struct S<T> { x: *const () }
    /// fn get<T>(s: &S<T>, v: T) {
    ///    unsafe {
    ///        let x: fn(T) = mem::transmute(s.x);
    ///        x(v)
    ///    }
    /// }
    /// ```
    ///
    /// The type system would currently infer that the value of
    /// the type parameter `T` is irrelevant, and hence a `S<int>` is
    /// a subtype of `S<Box<int>>` (or, for that matter, `S<U>` for
    /// any `U`). But this is incorrect because `get()` converts the
    /// `*()` into a `fn(T)` and then passes a value of type `T` to it.
    ///
    /// Supplying a `ContravariantType` marker would correct the
    /// problem, because it would mark `S` so that `S<T>` is only a
    /// subtype of `S<U>` if `U` is a subtype of `T`; given that the
    /// function requires arguments of type `T`, it must also accept
    /// arguments of type `U`, hence such a conversion is safe.
    #[lang="contravariant_type"]
    #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
    pub struct ContravariantType<T>;

    impl<T> Copy for ContravariantType<T> {}

    /// A marker type whose type parameter `T` is considered to be
    /// invariant with respect to the type itself. This is (typically)
    /// used to indicate that instances of the type `T` may be read or
    /// written, even though that may not be apparent.
    ///
    /// For more information about variance, refer to this Wikipedia
    /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
    ///
    /// # Example
    ///
    /// The Cell type is an example which uses unsafe code to achieve
    /// "interior" mutability:
    ///
    /// ```
    /// pub struct Cell<T> { value: T }
    /// # fn main() {}
    /// ```
    ///
    /// The type system would infer that `value` is only read here and
    /// never written, but in fact `Cell` uses unsafe code to achieve
    /// interior mutability.
    #[lang="invariant_type"]
    #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
    pub struct InvariantType<T>;

    impl<T> Copy for InvariantType<T> {}

    /// As `CovariantType`, but for lifetime parameters. Using
    /// `CovariantLifetime<'a>` indicates that it is ok to substitute
    /// a *longer* lifetime for `'a` than the one you originally
    /// started with (e.g., you could convert any lifetime `'foo` to
    /// `'static`). You almost certainly want `ContravariantLifetime`
    /// instead, or possibly `InvariantLifetime`. The only case where
    /// it would be appropriate is that you have a (type-casted, and
    /// hence hidden from the type system) function pointer with a
    /// signature like `fn(&'a T)` (and no other uses of `'a`). In
    /// this case, it is ok to substitute a larger lifetime for `'a`
    /// (e.g., `fn(&'static T)`), because the function is only
    /// becoming more selective in terms of what it accepts as
    /// argument.
    ///
    /// For more information about variance, refer to this Wikipedia
    /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
    #[lang="covariant_lifetime"]
    #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
    pub struct CovariantLifetime<'a>;

    impl<'a> Copy for CovariantLifetime<'a> {}

    /// As `ContravariantType`, but for lifetime parameters. Using
    /// `ContravariantLifetime<'a>` indicates that it is ok to
    /// substitute a *shorter* lifetime for `'a` than the one you
    /// originally started with (e.g., you could convert `'static` to
    /// any lifetime `'foo`). This is appropriate for cases where you
    /// have an unsafe pointer that is actually a pointer into some
    /// memory with lifetime `'a`, and thus you want to limit the
    /// lifetime of your data structure to `'a`. An example of where
    /// this is used is the iterator for vectors.
    ///
    /// For more information about variance, refer to this Wikipedia
    /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
    #[lang="contravariant_lifetime"]
    #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
    pub struct ContravariantLifetime<'a>;

    impl<'a> Copy for ContravariantLifetime<'a> {}

    /// As `InvariantType`, but for lifetime parameters. Using
    /// `InvariantLifetime<'a>` indicates that it is not ok to
    /// substitute any other lifetime for `'a` besides its original
    /// value. This is appropriate for cases where you have an unsafe
    /// pointer that is actually a pointer into memory with lifetime `'a`,
    /// and this pointer is itself stored in an inherently mutable
    /// location (such as a `Cell`).
    #[lang="invariant_lifetime"]
    #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
    pub struct InvariantLifetime<'a>;

    impl<'a> Copy for InvariantLifetime<'a> {}

    /// A type which is considered "not sendable", meaning that it cannot
    /// be safely sent between tasks, even if it is owned. This is
    /// typically embedded in other types, such as `Gc`, to ensure that
    /// their instances remain thread-local.
    #[lang="no_send_bound"]
    #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
    #[allow(missing_copy_implementations)]
    pub struct NoSend;

    /// A type which is considered "not POD", meaning that it is not
    /// implicitly copyable. This is typically embedded in other types to
    /// ensure that they are never copied, even if they lack a destructor.
    #[lang="no_copy_bound"]
    #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
    #[allow(missing_copy_implementations)]
    pub struct NoCopy;

    /// A type which is considered "not sync", meaning that
    /// its contents are not threadsafe, hence they cannot be
    /// shared between tasks.
    #[lang="no_sync_bound"]
    #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
    #[allow(missing_copy_implementations)]
    pub struct NoSync;

    /// A type which is considered managed by the GC. This is typically
    /// embedded in other types.
    #[lang="managed_bound"]
    #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
    #[allow(missing_copy_implementations)]
    pub struct Managed;
}

<|endoftext|>