<commit_before>#![feature(plugin, test)]
#![plugin(phf_macros)]

extern crate test;
extern crate phf;

mod map {
    use std::collections::{BTreeMap, HashMap};
    use test::Bencher;

    use phf;

    macro_rules! map_and_match {
        ($map:ident, $f:ident, $($key:expr => $value:expr,)+) => {
            static $map: phf::Map<&'static str, usize> = phf_map! {
                $($key => $value),+
            };

            fn $f(key: &str) -> Option<usize> {
                match key {
                    $($key => Some($value),)+
                    _ => None
                }
            }
        }
    }

    map_and_match! { MAP, match_get,
        "apple" => 0,
        "banana" => 1,
        "carrot" => 2,
        "doughnut" => 3,
        "eggplant" => 4,
        "frankincene" => 5,
        "grapes" => 6,
        "haggis" => 7,
        "ice cream" => 8,
        "jelly beans" => 9,
        "kaffir lime leaves" => 10,
        "lemonade" => 11,
        "mashmallows" => 12,
        "nectarines" => 13,
        "oranges" => 14,
        "pineapples" => 15,
        "quinoa" => 16,
        "rosemary" => 17,
        "sourdough" => 18,
        "tomatoes" => 19,
        "unleavened bread" => 20,
        "vanilla" => 21,
        "watermelon" => 22,
        "xinomavro grapes" => 23,
        "yogurt" => 24,
        "zucchini" => 25,
    }

    #[bench]
    fn bench_match_some(b: &mut Bencher) {
        b.iter(|| {
            assert_eq!(match_get("zucchini").unwrap(), 25);
        })
    }

    #[bench]
    fn bench_match_none(b: &mut Bencher) {
        b.iter(|| {
            assert_eq!(match_get("potato"), None);
        })
    }

    #[bench]
    fn bench_btreemap_some(b: &mut Bencher) {
        let mut map = BTreeMap::new();
        for (key, value) in MAP.entries() {
            map.insert(*key, *value);
        }

        b.iter(|| {
            assert_eq!(map.get("zucchini").unwrap(), &25);
        })
    }

    #[bench]
    fn bench_hashmap_some(b: &mut Bencher) {
        let mut map = HashMap::new();
        for (key, value) in MAP.entries() {
            map.insert(*key, *value);
        }

        b.iter(|| {
            assert_eq!(map.get("zucchini").unwrap(), &25);
        })
    }

    #[bench]
    fn bench_phf_some(b: &mut Bencher) {
        b.iter(|| {
            assert_eq!(MAP.get("zucchini").unwrap(), &25);
        })
    }

    #[bench]
    fn bench_btreemap_none(b: &mut Bencher) {
        let mut map = BTreeMap::new();
        for (key, value) in MAP.entries() {
            map.insert(*key, *value);
        }

        b.iter(|| {
            assert_eq!(map.get("potato"), None);
        })
    }

    #[bench]
    fn bench_hashmap_none(b: &mut Bencher) {
        let mut map = BTreeMap::new();
        for (key, value) in MAP.entries() {
            map.insert(*key, *value);
        }

        b.iter(|| {
            assert_eq!(map.get("potato"), None);
        })
    }

    #[bench]
    fn bench_phf_none(b: &mut Bencher) {
        b.iter(|| {
            assert_eq!(MAP.get("potato"), None);
        })
    }
}
<commit_msg>Fix benchmark<commit_after>#![feature(plugin, test)]
#![plugin(phf_macros)]

extern crate test;
extern crate phf;

mod map {
    use std::collections::{BTreeMap, HashMap};
    use test;
    use test::Bencher;

    use phf;

    macro_rules! map_and_match {
        ($map:ident, $f:ident, $($key:expr => $value:expr,)+) => {
            static $map: phf::Map<&'static str, usize> = phf_map! {
                $($key => $value),+
            };

            fn $f(key: &str) -> Option<usize> {
                match key {
                    $($key => Some($value),)+
                    _ => None
                }
            }
        }
    }

    map_and_match! { MAP, match_get,
        "apple" => 0,
        "banana" => 1,
        "carrot" => 2,
        "doughnut" => 3,
        "eggplant" => 4,
        "frankincene" => 5,
        "grapes" => 6,
        "haggis" => 7,
        "ice cream" => 8,
        "jelly beans" => 9,
        "kaffir lime leaves" => 10,
        "lemonade" => 11,
        "mashmallows" => 12,
        "nectarines" => 13,
        "oranges" => 14,
        "pineapples" => 15,
        "quinoa" => 16,
        "rosemary" => 17,
        "sourdough" => 18,
        "tomatoes" => 19,
        "unleavened bread" => 20,
        "vanilla" => 21,
        "watermelon" => 22,
        "xinomavro grapes" => 23,
        "yogurt" => 24,
        "zucchini" => 25,
    }

    #[bench]
    fn bench_match_some(b: &mut Bencher) {
        b.iter(|| {
            assert_eq!(match_get(test::black_box("zucchini")).unwrap(), 25);
        })
    }

    #[bench]
    fn bench_match_none(b: &mut Bencher) {
        b.iter(|| {
            assert_eq!(test::black_box(match_get("potato")), None);
        })
    }

    #[bench]
    fn bench_btreemap_some(b: &mut Bencher) {
        let mut map = BTreeMap::new();
        for (key, value) in MAP.entries() {
            map.insert(*key, *value);
        }

        b.iter(|| {
            assert_eq!(map.get("zucchini").unwrap(), &25);
        })
    }

    #[bench]
    fn bench_hashmap_some(b: &mut Bencher) {
        let mut map = HashMap::new();
        for (key, value) in MAP.entries() {
            map.insert(*key, *value);
        }

        b.iter(|| {
            assert_eq!(map.get("zucchini").unwrap(), &25);
        })
    }

    #[bench]
    fn bench_phf_some(b: &mut Bencher) {
        b.iter(|| {
            assert_eq!(MAP.get("zucchini").unwrap(), &25);
        })
    }

    #[bench]
    fn bench_btreemap_none(b: &mut Bencher) {
        let mut map = BTreeMap::new();
        for (key, value) in MAP.entries() {
            map.insert(*key, *value);
        }

        b.iter(|| {
            assert_eq!(map.get("potato"), None);
        })
    }

    #[bench]
    fn bench_hashmap_none(b: &mut Bencher) {
        let mut map = HashMap::new();
        for (key, value) in MAP.entries() {
            map.insert(*key, *value);
        }

        b.iter(|| {
            assert_eq!(map.get("potato"), None);
        })
    }

    #[bench]
    fn bench_phf_none(b: &mut Bencher) {
        b.iter(|| {
            assert_eq!(MAP.get("potato"), None);
        })
    }
}
<|endoftext|>


<commit_before>extern crate l20n;
extern crate rustc_serialize;

use std::io::prelude::*;
use std::fs::File;
use std::io;
use rustc_serialize::json::{Json, ToJson};
use std::collections::BTreeMap;

use l20n::ftl::parser::Parser as FTLParser;
use l20n::ftl::ast::Entry as FTLEntry;
use l20n::ftl::ast::Value as FTLValue;

fn read_file(path: &str) -> Result<String, io::Error> {
  let mut f = try!(File::open(path));
  let mut s = String::new();
  try!(f.read_to_string(&mut s));
  Ok(s)
}

fn read_json_file(path: &str) -> Result<Json, io::Error> {
  let mut f = try!(File::open(path));
  let mut data = String::new();
  try!(f.read_to_string(&mut data));

  let json = Json::from_str(&data).unwrap();
  Ok(json)
}

fn resource_to_json(entries: &Vec<FTLEntry>) -> Json {
  let mut d = BTreeMap::new();

  for i in 0..entries.len() {
    if let FTLEntry::Entity{ ref id, ref value, ref traits } = entries[i] {
      let FTLValue::Pattern { ref source, .. } = *value;
      d.insert(id.name.to_string(), source.to_json());
    }
  }

  Json::Object(d)
}

#[test]
fn it_works() {
  let string = read_file("./tests/fixtures/parser/ftl/01-basic01.ftl").expect("Failed to read");

  let reference_json = read_json_file("./tests/fixtures/parser/ftl/01-basic01.entries.json").expect("Failed to read");

  let mut parser = FTLParser::new(string.trim());

  let mut entries = parser.parse();

  let json = resource_to_json(&entries);

  assert_eq!(json, reference_json);
}
<commit_msg>Remove warnings<commit_after>extern crate l20n;
extern crate rustc_serialize;

use std::io::prelude::*;
use std::fs::File;
use std::io;
use rustc_serialize::json::{Json, ToJson};
use std::collections::BTreeMap;

use l20n::ftl::parser::Parser as FTLParser;
use l20n::ftl::ast::Entry as FTLEntry;
use l20n::ftl::ast::Value as FTLValue;

fn read_file(path: &str) -> Result<String, io::Error> {
  let mut f = try!(File::open(path));
  let mut s = String::new();
  try!(f.read_to_string(&mut s));
  Ok(s)
}

fn read_json_file(path: &str) -> Result<Json, io::Error> {
  let mut f = try!(File::open(path));
  let mut data = String::new();
  try!(f.read_to_string(&mut data));

  let json = Json::from_str(&data).unwrap();
  Ok(json)
}

fn resource_to_json(entries: &Vec<FTLEntry>) -> Json {
  let mut d = BTreeMap::new();

  for i in 0..entries.len() {
    if let FTLEntry::Entity{ ref id, ref value, .. } = entries[i] {
      let FTLValue::Pattern { ref source, .. } = *value;
      d.insert(id.name.to_string(), source.to_json());
    }
  }

  Json::Object(d)
}

#[test]
fn it_works() {
  let string = read_file("./tests/fixtures/parser/ftl/01-basic01.ftl").expect("Failed to read");

  let reference_json = read_json_file("./tests/fixtures/parser/ftl/01-basic01.entries.json").expect("Failed to read");

  let mut parser = FTLParser::new(string.trim());

  let entries = parser.parse();

  let json = resource_to_json(&entries);

  assert_eq!(json, reference_json);
}
<|endoftext|>


<commit_before>extern crate cuckoofilter;

use self::cuckoofilter::*;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
use std::error::Error;

#[test]
fn test_insertion() {
    let path = Path::new("/usr/share/dict/web2");
    let display = path.display();

    // Open the path in read-only mode, returns `io::Result<File>`
    let mut file = match File::open(&path) {
        // The `description` method of `io::Error` returns a string that
        // describes the error
        Err(why) => panic!("couldn't open {}: {}", display,
                                                   Error::description(&why)),
        Ok(file) => file,
    };

    let mut web2 = String::new();
    match file.read_to_string(&mut web2) {
        Err(why) => panic!("couldn't read {}: {}", display,
                                                   Error::description(&why)),
        Ok(_) => {},
    }

    let mut split: Vec<&str> = web2.split("\n").collect();

    let mut cf = CuckooFilter::new(1000000);
    for s in &mut split {
        cf.test_and_add(&s.as_bytes());
    }
    assert_eq!(cf.get_count(), 235033);

    for s in &mut split {
        cf.delete(&s.as_bytes());
    }
    assert_eq!(cf.get_count(), 0);
}<commit_msg>Adapt unit tests<commit_after>extern crate cuckoofilter;

use self::cuckoofilter::*;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
use std::error::Error;

#[test]
fn test_insertion() {
    let path = Path::new("/usr/share/dict/web2");
    let display = path.display();

    // Open the path in read-only mode, returns `io::Result<File>`
    let mut file = match File::open(&path) {
        // The `description` method of `io::Error` returns a string that
        // describes the error
        Err(why) => panic!("couldn't open {}: {}", display,
                                                   Error::description(&why)),
        Ok(file) => file,
    };

    let mut web2 = String::new();
    match file.read_to_string(&mut web2) {
        Err(why) => panic!("couldn't read {}: {}", display,
                                                   Error::description(&why)),
        Ok(_) => {},
    }

    let mut split: Vec<&str> = web2.split("\n").collect();

    let mut cf = CuckooFilter::new();
    for s in &mut split {
        cf.test_and_add(&s.as_bytes());
    }
    assert_eq!(cf.len(), 235033);

    for s in &mut split {
        cf.delete(&s.as_bytes());
    }
    assert_eq!(cf.len(), 0);
}<|endoftext|>


<commit_before>// ignore-windows: File handling is not implemented yet
// compile-flags: -Zmiri-disable-isolation

use std::fs::{File, remove_file, rename};
use std::io::{Read, Write, ErrorKind, Result, Seek, SeekFrom};
use std::path::{PathBuf, Path};

fn test_metadata(bytes: &[u8], path: &Path) -> Result<()> {
    // Test that the file metadata is correct.
    let metadata = path.metadata()?;
    // `path` should point to a file.
    assert!(metadata.is_file());
    // The size of the file must be equal to the number of written bytes.
    assert_eq!(bytes.len() as u64, metadata.len());
    Ok(())
}

fn main() {
    let tmp = std::env::temp_dir();
    let filename = PathBuf::from("miri_test_fs.txt");
    let path = tmp.join(&filename);
    let symlink_path = tmp.join("miri_test_fs_symlink.txt");
    let bytes = b"Hello, World!\n";
    // Clean the paths for robustness.
    remove_file(&path).ok();
    remove_file(&symlink_path).ok();

    // Test creating, writing and closing a file (closing is tested when `file` is dropped).
    let mut file = File::create(&path).unwrap();
    // Writing 0 bytes should not change the file contents.
    file.write(&mut []).unwrap();
    assert_eq!(file.metadata().unwrap().len(), 0);

    file.write(bytes).unwrap();
    assert_eq!(file.metadata().unwrap().len(), bytes.len() as u64);
    // Test opening, reading and closing a file.
    let mut file = File::open(&path).unwrap();
    let mut contents = Vec::new();
    // Reading 0 bytes should not move the file pointer.
    file.read(&mut []).unwrap();
    // Reading until EOF should get the whole text.
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());

    // Test that seeking to the beginning and reading until EOF gets the text again.
    file.seek(SeekFrom::Start(0)).unwrap();
    let mut contents = Vec::new();
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());
    // Test seeking relative to the end of the file.
    file.seek(SeekFrom::End(-1)).unwrap();
    let mut contents = Vec::new();
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(&bytes[bytes.len() - 1..], contents.as_slice());
    // Test seeking relative to the current position.
    file.seek(SeekFrom::Start(5)).unwrap();
    file.seek(SeekFrom::Current(-3)).unwrap();
    let mut contents = Vec::new();
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(&bytes[2..], contents.as_slice());

    // Test that metadata of an absolute path is correct.
    test_metadata(bytes, &path).unwrap();
    // Test that metadata of a relative path is correct.
    std::env::set_current_dir(&tmp).unwrap();
    test_metadata(bytes, &filename).unwrap();

    // Creating a symbolic link should succeed.
    std::os::unix::fs::symlink(&path, &symlink_path).unwrap();
    // Test that the symbolic link has the same contents as the file.
    let mut symlink_file = File::open(&symlink_path).unwrap();
    let mut contents = Vec::new();
    symlink_file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());
    // Test that metadata of a symbolic link is correct.
    test_metadata(bytes, &symlink_path).unwrap();
    // Test that the metadata of a symbolic link is correct when not following it.
    assert!(symlink_path.symlink_metadata().unwrap().file_type().is_symlink());
    // Removing symbolic link should succeed.
    remove_file(&symlink_path).unwrap();

    // Removing file should succeed.
    remove_file(&path).unwrap();

    // Renaming a file should succeed.
    let path1 = tmp.join("rename_source.txt");
    let path2 = tmp.join("rename_destination.txt");
    // Clean files for robustness.
    remove_file(&path1).ok();
    remove_file(&path2).ok();
    let file = File::create(&path1).unwrap();
    drop(file);
    rename(&path1, &path2).unwrap();
    assert_eq!(ErrorKind::NotFound, path1.metadata().unwrap_err().kind());
    assert!(path2.metadata().unwrap().is_file());
    remove_file(&path2).ok();

    // The two following tests also check that the `__errno_location()` shim is working properly.
    // Opening a non-existing file should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, File::open(&path).unwrap_err().kind());
    // Removing a non-existing file should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, remove_file(&path).unwrap_err().kind());
    // Reading the metadata of a non-existing file should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, test_metadata(bytes, &path).unwrap_err().kind());
}
<commit_msg>Removing file after rename must succeed<commit_after>// ignore-windows: File handling is not implemented yet
// compile-flags: -Zmiri-disable-isolation

use std::fs::{File, remove_file, rename};
use std::io::{Read, Write, ErrorKind, Result, Seek, SeekFrom};
use std::path::{PathBuf, Path};

fn test_metadata(bytes: &[u8], path: &Path) -> Result<()> {
    // Test that the file metadata is correct.
    let metadata = path.metadata()?;
    // `path` should point to a file.
    assert!(metadata.is_file());
    // The size of the file must be equal to the number of written bytes.
    assert_eq!(bytes.len() as u64, metadata.len());
    Ok(())
}

fn main() {
    let tmp = std::env::temp_dir();
    let filename = PathBuf::from("miri_test_fs.txt");
    let path = tmp.join(&filename);
    let symlink_path = tmp.join("miri_test_fs_symlink.txt");
    let bytes = b"Hello, World!\n";
    // Clean the paths for robustness.
    remove_file(&path).ok();
    remove_file(&symlink_path).ok();

    // Test creating, writing and closing a file (closing is tested when `file` is dropped).
    let mut file = File::create(&path).unwrap();
    // Writing 0 bytes should not change the file contents.
    file.write(&mut []).unwrap();
    assert_eq!(file.metadata().unwrap().len(), 0);

    file.write(bytes).unwrap();
    assert_eq!(file.metadata().unwrap().len(), bytes.len() as u64);
    // Test opening, reading and closing a file.
    let mut file = File::open(&path).unwrap();
    let mut contents = Vec::new();
    // Reading 0 bytes should not move the file pointer.
    file.read(&mut []).unwrap();
    // Reading until EOF should get the whole text.
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());

    // Test that seeking to the beginning and reading until EOF gets the text again.
    file.seek(SeekFrom::Start(0)).unwrap();
    let mut contents = Vec::new();
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());
    // Test seeking relative to the end of the file.
    file.seek(SeekFrom::End(-1)).unwrap();
    let mut contents = Vec::new();
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(&bytes[bytes.len() - 1..], contents.as_slice());
    // Test seeking relative to the current position.
    file.seek(SeekFrom::Start(5)).unwrap();
    file.seek(SeekFrom::Current(-3)).unwrap();
    let mut contents = Vec::new();
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(&bytes[2..], contents.as_slice());

    // Test that metadata of an absolute path is correct.
    test_metadata(bytes, &path).unwrap();
    // Test that metadata of a relative path is correct.
    std::env::set_current_dir(&tmp).unwrap();
    test_metadata(bytes, &filename).unwrap();

    // Creating a symbolic link should succeed.
    std::os::unix::fs::symlink(&path, &symlink_path).unwrap();
    // Test that the symbolic link has the same contents as the file.
    let mut symlink_file = File::open(&symlink_path).unwrap();
    let mut contents = Vec::new();
    symlink_file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());
    // Test that metadata of a symbolic link is correct.
    test_metadata(bytes, &symlink_path).unwrap();
    // Test that the metadata of a symbolic link is correct when not following it.
    assert!(symlink_path.symlink_metadata().unwrap().file_type().is_symlink());
    // Removing symbolic link should succeed.
    remove_file(&symlink_path).unwrap();

    // Removing file should succeed.
    remove_file(&path).unwrap();

    // Renaming a file should succeed.
    let path1 = tmp.join("rename_source.txt");
    let path2 = tmp.join("rename_destination.txt");
    // Clean files for robustness.
    remove_file(&path1).ok();
    remove_file(&path2).ok();
    let file = File::create(&path1).unwrap();
    drop(file);
    rename(&path1, &path2).unwrap();
    assert_eq!(ErrorKind::NotFound, path1.metadata().unwrap_err().kind());
    assert!(path2.metadata().unwrap().is_file());
    remove_file(&path2).unwrap();

    // The two following tests also check that the `__errno_location()` shim is working properly.
    // Opening a non-existing file should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, File::open(&path).unwrap_err().kind());
    // Removing a non-existing file should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, remove_file(&path).unwrap_err().kind());
    // Reading the metadata of a non-existing file should fail with a "not found" error.
    assert_eq!(ErrorKind::NotFound, test_metadata(bytes, &path).unwrap_err().kind());
}
<|endoftext|>


<commit_before>extern crate rustbox;

use std::comm::{Receiver, Sender};
use std::num;
use std::io::{File, FileMode, FileAccess};

use super::Response;
use cursor::Direction;
use keyboard::Key;
use view::View;

enum EventStatus {
    Handled(Response),
    NotHandled,
}

pub struct Editor<'e> {
    pub running: bool,
    pub sender: Sender<rustbox::Event>,

    events: Receiver<rustbox::Event>,
    view: View<'e>,
}

impl<'e> Editor<'e> {
    pub fn new(filename: Option<String>) -> Editor<'e> {
        let view = View::new(filename);

        let (send, recv) = channel();
        Editor {
            sender: send,
            events: recv,
            view: view,
            running: false,
        }
    }

    pub fn handle_key_event(&mut self, key: u16, ch: u32) -> Response {
        let key_code = key as u32 + ch;
        let input_key: Option<Key> = num::from_u32(key_code);

        match self.handle_system_event(input_key) {
            EventStatus::Handled(response) => { response }
            EventStatus::NotHandled        => { Response::Continue }
        }
    }

    pub fn save_active_buffer(&mut self) {
        let lines = &self.view.buffer.lines;
        let path = Path::new(&self.view.buffer.file_path);

        let mut file = match File::open_mode(&path, FileMode::Open, FileAccess::Write) {
            Ok(f) => f,
            Err(e) => panic!("file error: {}", e),
        };

        for line in lines.iter() {
            let mut data = line.borrow().data.clone();
            data.push('\n' as u8);
            let result = file.write(data.as_slice());

            if result.is_err() {
                // TODO(greg): figure out what to do here.
            }
        }
    }

    pub fn draw(&mut self) {
        self.view.draw();
        self.view.draw_status();
        self.view.draw_cursor();
    }

    pub fn start(&mut self) {
        self.running = true;
        self.event_loop();
        self.main_loop();
    }

    fn main_loop(&mut self) {
        while self.running {
            self.view.clear();
            self.draw();
            rustbox::present();
            match self.events.recv() {
                rustbox::Event::KeyEvent(_, key, ch) => {
                    match self.handle_key_event(key, ch) {
                        // TODO(greg): refactor event handling responses
                        Response::Continue => { /* keep going*/ }
                        Response::Quit     => self.running = false,
                    }
                },
                _ => {}
            }
        }
    }

    fn event_loop(&self) {
        // clone the sender so that we can use it in the proc
        let sender = self.sender.clone();

        spawn(proc() {
            loop {
                sender.send(rustbox::poll_event());
            }
        });
    }

    fn handle_system_event(&mut self, k: Option<Key>) -> EventStatus {
        if k.is_none() {
            return EventStatus::NotHandled
        }

        let key = k.unwrap();
        match key {
            Key::Up        => { self.view.move_cursor(Direction::Up); }
            Key::Down      => { self.view.move_cursor(Direction::Down); }
            Key::Left      => { self.view.move_cursor(Direction::Left); }
            Key::Right     => { self.view.move_cursor(Direction::Right); }
            Key::Enter     => { self.view.insert_line(); }

            // Tab inserts 4 spaces, rather than a \t
            Key::Tab       => { self.view.insert_tab(); }

            Key::Backspace => { self.view.delete_char(Direction::Left); }
            Key::Delete    => { self.view.delete_char(Direction::Right); }
            Key::CtrlS     => { self.save_active_buffer(); }
            Key::CtrlQ     => { return EventStatus::Handled(Response::Quit) }

            // TODO(greg): move these keys to event handlers of each mode
            // This block is for matching keys which will insert a char to the buffer
            Key::Exclaim   |  Key::Hash |
            Key::Dollar    | Key::Percent |
            Key::Ampersand | Key::Quote |
            Key::LeftParen | Key::RightParen |
            Key::Asterisk  | Key::Plus |
            Key::Comma     | Key::Minus |
            Key::Period    | Key::Slash |
            Key::D0 | Key::D1 | Key::D2 |
            Key::D3 | Key::D4 | Key::D5 |
            Key::D6 | Key::D7 | Key::D8 |
            Key::D9 | Key::Colon |
            Key::Semicolon | Key::Less |
            Key::Equals    | Key::Greater |
            Key::Question  | Key::At |
            Key::LeftBracket  | Key::Backslash |
            Key::RightBracket | Key::Caret |
            Key::Underscore   | Key::Backquote |
            Key::A | Key::B | Key::C | Key::D |
            Key::E | Key::F | Key::G | Key::H |
            Key::I | Key::J | Key::K | Key::L |
            Key::M | Key::N | Key::O | Key::P |
            Key::Q | Key::R | Key::S | Key::T |
            Key::U | Key::V | Key::W | Key::X |
            Key::Y | Key::Z | Key::LeftBrace |
            Key::Pipe       | Key::RightBrace |
            Key::Tilde      | Key::Space => { self.view.insert_char(key.get_char().unwrap()) }

            // default
            _              => { return EventStatus::NotHandled }
        }
        // event is handled and we want to keep the editor running
        EventStatus::Handled(Response::Continue)
    }

}

<commit_msg>Panic if file saving fails<commit_after>extern crate rustbox;

use std::comm::{Receiver, Sender};
use std::num;
use std::io::{File, FileMode, FileAccess};

use super::Response;
use cursor::Direction;
use keyboard::Key;
use view::View;

enum EventStatus {
    Handled(Response),
    NotHandled,
}

pub struct Editor<'e> {
    pub running: bool,
    pub sender: Sender<rustbox::Event>,

    events: Receiver<rustbox::Event>,
    view: View<'e>,
}

impl<'e> Editor<'e> {
    pub fn new(filename: Option<String>) -> Editor<'e> {
        let view = View::new(filename);

        let (send, recv) = channel();
        Editor {
            sender: send,
            events: recv,
            view: view,
            running: false,
        }
    }

    pub fn handle_key_event(&mut self, key: u16, ch: u32) -> Response {
        let key_code = key as u32 + ch;
        let input_key: Option<Key> = num::from_u32(key_code);

        match self.handle_system_event(input_key) {
            EventStatus::Handled(response) => { response }
            EventStatus::NotHandled        => { Response::Continue }
        }
    }

    pub fn save_active_buffer(&mut self) {
        let lines = &self.view.buffer.lines;
        let path = Path::new(&self.view.buffer.file_path);

        let mut file = match File::open_mode(&path, FileMode::Open, FileAccess::Write) {
            Ok(f) => f,
            Err(e) => panic!("file error: {}", e),
        };

        for line in lines.iter() {
            let mut data = line.borrow().data.clone();
            data.push('\n' as u8);
            let result = file.write(data.as_slice());

            if result.is_err() {
                // TODO(greg): figure out what to do here.
                panic!("Something went wrong while writing the file");
            }
        }
    }

    pub fn draw(&mut self) {
        self.view.draw();
        self.view.draw_status();
        self.view.draw_cursor();
    }

    pub fn start(&mut self) {
        self.running = true;
        self.event_loop();
        self.main_loop();
    }

    fn main_loop(&mut self) {
        while self.running {
            self.view.clear();
            self.draw();
            rustbox::present();
            match self.events.recv() {
                rustbox::Event::KeyEvent(_, key, ch) => {
                    match self.handle_key_event(key, ch) {
                        // TODO(greg): refactor event handling responses
                        Response::Continue => { /* keep going*/ }
                        Response::Quit     => self.running = false,
                    }
                },
                _ => {}
            }
        }
    }

    fn event_loop(&self) {
        // clone the sender so that we can use it in the proc
        let sender = self.sender.clone();

        spawn(proc() {
            loop {
                sender.send(rustbox::poll_event());
            }
        });
    }

    fn handle_system_event(&mut self, k: Option<Key>) -> EventStatus {
        if k.is_none() {
            return EventStatus::NotHandled
        }

        let key = k.unwrap();
        match key {
            Key::Up        => { self.view.move_cursor(Direction::Up); }
            Key::Down      => { self.view.move_cursor(Direction::Down); }
            Key::Left      => { self.view.move_cursor(Direction::Left); }
            Key::Right     => { self.view.move_cursor(Direction::Right); }
            Key::Enter     => { self.view.insert_line(); }

            // Tab inserts 4 spaces, rather than a \t
            Key::Tab       => { self.view.insert_tab(); }

            Key::Backspace => { self.view.delete_char(Direction::Left); }
            Key::Delete    => { self.view.delete_char(Direction::Right); }
            Key::CtrlS     => { self.save_active_buffer(); }
            Key::CtrlQ     => { return EventStatus::Handled(Response::Quit) }

            // TODO(greg): move these keys to event handlers of each mode
            // This block is for matching keys which will insert a char to the buffer
            Key::Exclaim   |  Key::Hash |
            Key::Dollar    | Key::Percent |
            Key::Ampersand | Key::Quote |
            Key::LeftParen | Key::RightParen |
            Key::Asterisk  | Key::Plus |
            Key::Comma     | Key::Minus |
            Key::Period    | Key::Slash |
            Key::D0 | Key::D1 | Key::D2 |
            Key::D3 | Key::D4 | Key::D5 |
            Key::D6 | Key::D7 | Key::D8 |
            Key::D9 | Key::Colon |
            Key::Semicolon | Key::Less |
            Key::Equals    | Key::Greater |
            Key::Question  | Key::At |
            Key::LeftBracket  | Key::Backslash |
            Key::RightBracket | Key::Caret |
            Key::Underscore   | Key::Backquote |
            Key::A | Key::B | Key::C | Key::D |
            Key::E | Key::F | Key::G | Key::H |
            Key::I | Key::J | Key::K | Key::L |
            Key::M | Key::N | Key::O | Key::P |
            Key::Q | Key::R | Key::S | Key::T |
            Key::U | Key::V | Key::W | Key::X |
            Key::Y | Key::Z | Key::LeftBrace |
            Key::Pipe       | Key::RightBrace |
            Key::Tilde      | Key::Space => { self.view.insert_char(key.get_char().unwrap()) }

            // default
            _              => { return EventStatus::NotHandled }
        }
        // event is handled and we want to keep the editor running
        EventStatus::Handled(Response::Continue)
    }

}

<|endoftext|>


<commit_before><commit_msg>Removed test.rs, empty file<commit_after><|endoftext|>


<commit_before>//! Main module to handle the layout.
//! This is where the i3-specific code is.

use std::sync::{Mutex, MutexGuard, TryLockError};
use std::ptr;

use super::container::{Container, Handle, ContainerType};
use super::node::{Node};
use super::super::rustwlc::handle::{WlcView, WlcOutput};

pub type TreeResult = Result<(), TryLockError<MutexGuard<'static, Tree>>>;

const ERR_BAD_TREE: &'static str = "Layout tree was in an invalid configuration";

pub struct Tree {
    root: Node,
    active_container: *const Node,
}

impl Tree {
    fn get_active_container(&self) -> Option<&Node> {
        if self.active_container.is_null() {
            None
        } else {
            unsafe {
                Some(&*self.active_container)
            }
        }
    }
}

unsafe impl Send for Tree {}

lazy_static! {
    static ref TREE: Mutex<Tree> = {
        Mutex::new(Tree{
            root: Node::new(Container::new_root()),
            active_container: ptr::null(),
        })
    };
}

pub fn add_output(wlc_output: WlcOutput) -> TreeResult {
    {
        let mut tree = try!(TREE.try_lock());
        let output = Container::new_output(wlc_output);
        tree.root.new_child(output);
    }
    try!(add_workspace(&"1"));
    try!(switch_workspace(&"1"));
    Ok(())
}

pub fn add_workspace(name: &str) -> TreeResult {
    trace!("Adding new workspace to root");
    let mut tree = try!(TREE.lock());
    let workspace = Container::new_workspace(name.to_string());
    // NOTE handle multiple outputs
    tree.root.get_children_mut()[0].new_child(workspace);
    Ok(())
}

pub fn add_view(wlc_view: WlcView) -> TreeResult {
    let tree = try!(TREE.lock());
    if let Some(current_workspace) = get_current_workspace(&tree) {
        trace!("Adding view {:?} to {:?}", wlc_view, current_workspace);
        current_workspace.new_child(Container::new_view(wlc_view));
    }
    Ok(())
}

pub fn remove_view(wlc_view: &WlcView) -> TreeResult {
    let tree = try!(TREE.lock());
    if let Some(view) = tree.root.find_view_by_handle(&wlc_view) {
        let parent = view.get_parent().expect(ERR_BAD_TREE);
        parent.remove_child(view);
    }
    Ok(())
}

pub fn switch_workspace(name: &str) -> TreeResult {
    trace!("Switching to workspace {}", name);
    let mut tree = try!(TREE.lock());
    if let Some(old_workspace) = get_current_workspace(&tree) {
        // Make all the views in the original workspace to be invisible
        for view in old_workspace.get_children_mut() {
            trace!("Setting {:?} invisible", view);
            match view.get_val().get_handle().expect(ERR_BAD_TREE) {
                Handle::View(view) => view.set_mask(0),
                _ => {},
            }
        }
    }
    let current_workspace: *const Node;
    {
        let new_current_workspace: &mut Node;
        if let Some(_) = get_workspace_by_name(&tree, name) {
            trace!("Found workspace {}", name);
            new_current_workspace = get_workspace_by_name_mut(&mut tree, name)
                .expect(ERR_BAD_TREE);
        } else {
            drop(tree);
            try!(add_workspace(name));
            tree = try!(TREE.lock());
            new_current_workspace = get_workspace_by_name_mut(&mut tree, name)
                .expect(ERR_BAD_TREE);
        }
        for view in new_current_workspace.get_children_mut() {
            trace!("Setting {:?} visible", view);
            match view.get_val().get_handle().expect(ERR_BAD_TREE) {
                Handle::View(view) => view.set_mask(1),
                _ => {},
            }
        }
        // Set the first view to be focused, so that the view is updated to this new workspace
        if new_current_workspace.get_children().len() > 0 {
            trace!("Focusing view");
            match new_current_workspace.get_children_mut()[0]
                .get_val().get_handle().expect(ERR_BAD_TREE) {
                Handle::View(view) => view.focus(),
                _ => {},
            }
        } else {
            WlcView::root().focus();
        }
        current_workspace = new_current_workspace as *const Node;
    }
    tree.active_container = current_workspace;
    Ok(())
}

/// Finds the WlcOutput associated with the WlcView from the tree
pub fn get_output_of_view(wlc_view: &WlcView) -> Option<WlcOutput> {
    let tree = TREE.lock().expect("Unable to lock layout tree!");
    if let Some(view_node) = tree.root.find_view_by_handle(wlc_view) {
        if let Some(output_node) = view_node.get_ancestor_of_type(ContainerType::Output) {
            if let Some(handle) =  output_node.get_val().get_handle() {
                return match handle {
                    Handle::Output(output) => Some(output),
                    _ => None
                }
            }
        }
    }
    return None;
}

#[allow(dead_code)]
fn get_focused_workspace<'a>(tree: &'a Tree) -> Option<&'a Node> {
    for output in tree.root.get_children() {
        if output.get_val().is_focused() {
            for workspace in output.get_children() {
                if workspace.get_val().is_focused() {
                    return Some(workspace);
                }
            }
        }
    }
    None

}

fn get_current_workspace<'a>(tree: &'a Tree) -> Option<&'a mut Node> {
    if let Some(container) = tree.get_active_container() {
        //if let Some(child) = container.get_ancestor_of_type(ContainerType::Workspace) {
            //return child.get_children()[0].get_parent()

        //}
        // NOTE hack here, remove commented code above to make this work properly
        let parent = container.get_parent().expect(ERR_BAD_TREE);
        for child in parent.get_children_mut() {
            if child == container {
                return Some(child);
            }
        }
    }
    return None
}

fn get_workspace_by_name<'a, 'b>(tree: &'a Tree, name: &'b str) -> Option<&'a Node> {
    for child in tree.root.get_children()[0].get_children() {
        if child.get_val().get_name().expect(ERR_BAD_TREE) != name {
            continue
        }
        return Some(child);
    }
    return None
}

fn get_workspace_by_name_mut<'a, 'b>(tree: &'a mut Tree, name: &'b str) -> Option<&'a mut Node> {
    for child in tree.root.get_children_mut()[0].get_children_mut() {
        if child.get_val().get_name().expect(ERR_BAD_TREE) != name {
            continue
        }
        return Some(child);
    }
    return None
}

<commit_msg>All non-public facing functions in the tree (all the helpers) have been made methods of the root tree struct. This will allows us to wrote code to perform operations on the tree without having to do a lock dance. The old methods that grab the lock and do a single operation are still there, for too much code relies on it and it's nice to have an abstraction layer without having to deal with the locks themselves if only a single operation is being done<commit_after>//! Main module to handle the layout.
//! This is where the i3-specific code is.

use std::sync::{Mutex, MutexGuard, TryLockError};
use std::ptr;

use super::container::{Container, Handle, ContainerType};
use super::node::{Node};
use super::super::rustwlc::handle::{WlcView, WlcOutput};

pub type TreeResult = Result<(), TryLockError<MutexGuard<'static, Tree>>>;

const ERR_BAD_TREE: &'static str = "Layout tree was in an invalid configuration";

pub struct Tree {
    root: Node,
    active_container: *const Node,
}

impl Tree {
    fn get_active_container(&self) -> Option<&Node> {
        if self.active_container.is_null() {
            None
        } else {
            unsafe {
                Some(&*self.active_container)
            }
        }
    }

    fn get_active_output(&self) -> Option<&Node> {
        if let Some(node) = self.get_active_container() {
            node.get_ancestor_of_type(ContainerType::Output)
        } else {
            None
        }
    }

    fn get_current_workspace(&self) -> Option<&mut Node> {
        if let Some(container) = self.get_active_container() {
            //if let Some(child) = container.get_ancestor_of_type(ContainerType::Workspace) {
            //return child.get_children()[0].get_parent()

            //}
            // NOTE hack here, remove commented code above to make this work properly
            let parent = container.get_parent().expect(ERR_BAD_TREE);
            for child in parent.get_children_mut() {
                if child == container {
                    return Some(child);
                }
            }
        }
        return None
    }

    fn get_output_of_view(&self, wlc_view: &WlcView) -> Option<WlcOutput> {
        if let Some(view_node) = self.root.find_view_by_handle(wlc_view) {
            if let Some(output_node) = view_node.get_ancestor_of_type(ContainerType::Output) {
                if let Some(handle) =  output_node.get_val().get_handle() {
                    return match handle {
                        Handle::Output(output) => Some(output),
                        _ => None
                    }
                }
            }
        }
        return None;
    }

    fn get_workspace_by_name(&self, name: &str) -> Option<&Node> {
        for child in self.root.get_children()[0].get_children() {
            if child.get_val().get_name().expect(ERR_BAD_TREE) != name {
                continue
            }
            return Some(child);
        }
        return None
    }

    fn get_workspace_by_name_mut(&mut self, name: &str) -> Option<&mut Node> {
        for child in self.root.get_children_mut()[0].get_children_mut() {
            if child.get_val().get_name().expect(ERR_BAD_TREE) != name {
                continue
            }
            return Some(child);
        }
        return None
    }

    fn add_output(&mut self, wlc_output: WlcOutput) {
        self.root.new_child(Container::new_output(wlc_output));
    }

    fn add_workspace(&mut self, name: &str) {
        let workspace = Container::new_workspace(name.to_string());
        let mut index = 0;
        if let Some(output) = self.get_active_output() {
            for (cur_index, child) in self.root.get_children().iter().enumerate() {
                if child == output {
                    index = cur_index;
                    break;
                }
            }
        }
        self.root.get_children_mut()[index].new_child(workspace);
    }

    fn add_view(&self, wlc_view: WlcView) {
        if let Some(current_workspace) = self.get_current_workspace() {
            trace!("Adding view {:?} to {:?}", wlc_view, current_workspace);
            current_workspace.new_child(Container::new_view(wlc_view));
        }
    }

    fn remove_view(&self, wlc_view: &WlcView) {
        if let Some(view) = self.root.find_view_by_handle(&wlc_view) {
            let parent = view.get_parent().expect(ERR_BAD_TREE);
            parent.remove_child(view);
        }
    }
}

unsafe impl Send for Tree {}

lazy_static! {
    static ref TREE: Mutex<Tree> = {
        Mutex::new(Tree{
            root: Node::new(Container::new_root()),
            active_container: ptr::null(),
        })
    };
}

pub fn add_output(wlc_output: WlcOutput) -> TreeResult {
    {
        let mut tree = try!(TREE.try_lock());
        tree.add_output(wlc_output);
    }
    try!(add_workspace(&"1"));
    try!(switch_workspace(&"1"));
    Ok(())
}

pub fn add_workspace(name: &str) -> TreeResult {
    trace!("Adding new workspace to root");
    let mut tree = try!(TREE.lock());
    tree.add_workspace(name);
    Ok(())
}

pub fn add_view(wlc_view: WlcView) -> TreeResult {
    let tree = try!(TREE.lock());
    tree.add_view(wlc_view);
    Ok(())
}

pub fn remove_view(wlc_view: &WlcView) -> TreeResult {
    let tree = try!(TREE.lock());
    tree.remove_view(wlc_view);
    Ok(())
}

pub fn switch_workspace(name: &str) -> TreeResult {
    trace!("Switching to workspace {}", name);
    let mut tree = try!(TREE.lock());
    if let Some(old_workspace) = tree.get_current_workspace() {
        // Make all the views in the original workspace to be invisible
        for view in old_workspace.get_children_mut() {
            trace!("Setting {:?} invisible", view);
            match view.get_val().get_handle().expect(ERR_BAD_TREE) {
                Handle::View(view) => view.set_mask(0),
                _ => {},
            }
        }
    }
    let current_workspace: *const Node;
    {
        let new_current_workspace: &mut Node;
        if let Some(_) = tree.get_workspace_by_name(name) {
            trace!("Found workspace {}", name);
            new_current_workspace = tree.get_workspace_by_name_mut(name)
                .expect(ERR_BAD_TREE);
        } else {
            drop(tree);
            try!(add_workspace(name));
            tree = try!(TREE.lock());
            new_current_workspace = tree.get_workspace_by_name_mut(name)
                .expect(ERR_BAD_TREE);
        }
        for view in new_current_workspace.get_children_mut() {
            trace!("Setting {:?} visible", view);
            match view.get_val().get_handle().expect(ERR_BAD_TREE) {
                Handle::View(view) => view.set_mask(1),
                _ => {},
            }
        }
        // Set the first view to be focused, so that the view is updated to this new workspace
        if new_current_workspace.get_children().len() > 0 {
            trace!("Focusing view");
            match new_current_workspace.get_children_mut()[0]
                .get_val().get_handle().expect(ERR_BAD_TREE) {
                Handle::View(view) => view.focus(),
                _ => {},
            }
        } else {
            WlcView::root().focus();
        }
        current_workspace = new_current_workspace as *const Node;
    }
    tree.active_container = current_workspace;
    Ok(())
}

/// Finds the WlcOutput associated with the WlcView from the tree
pub fn get_output_of_view(wlc_view: &WlcView) -> Option<WlcOutput> {
    let tree = TREE.lock().expect("Unable to lock layout tree!");
    tree.get_output_of_view(wlc_view)
}

<|endoftext|>


<commit_before>#![stable(feature = "", since = "1.30.0")]

#![allow(non_camel_case_types)]

//! Utilities related to FFI bindings.

use ::fmt;

/// Equivalent to C's `void` type when used as a [pointer].
///
/// In essence, `*const c_void` is equivalent to C's `const void*`
/// and `*mut c_void` is equivalent to C's `void*`. That said, this is
/// *not* the same as C's `void` return type, which is Rust's `()` type.
///
/// To model pointers to opaque types in FFI, until `extern type` is
/// stabilized, it is recommended to use a newtype wrapper around an empty
/// byte array. See the [Nomicon] for details.
///
/// [pointer]: ../../std/primitive.pointer.html
/// [Nomicon]: https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs
// N.B., for LLVM to recognize the void pointer type and by extension
//     functions like malloc(), we need to have it represented as i8* in
//     LLVM bitcode. The enum used here ensures this and prevents misuse
//     of the "raw" type by only having private variants. We need two
//     variants, because the compiler complains about the repr attribute
//     otherwise and we need at least one variant as otherwise the enum
//     would be uninhabited and at least dereferencing such pointers would
//     be UB.
#[repr(u8)]
#[stable(feature = "raw_os", since = "1.1.0")]
pub enum c_void {
    #[unstable(feature = "c_void_variant", reason = "temporary implementation detail",
               issue = "0")]
    #[doc(hidden)] __variant1,
    #[unstable(feature = "c_void_variant", reason = "temporary implementation detail",
               issue = "0")]
    #[doc(hidden)] __variant2,
}

#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for c_void {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad("c_void")
    }
}

/// Basic implementation of a `va_list`.
#[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
              not(target_arch = "x86_64")),
          all(target_arch = "aarch64", target_os = "ios"),
          windows))]
#[unstable(feature = "c_variadic",
           reason = "the `c_variadic` feature has not been properly tested on \
                     all supported platforms",
           issue = "44930")]
extern {
    type VaListImpl;
}

#[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
              not(target_arch = "x86_64")),
          windows))]
impl fmt::Debug for VaListImpl {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "va_list* {:p}", self)
    }
}

/// AArch64 ABI implementation of a `va_list`. See the
/// [AArch64 Procedure Call Standard] for more details.
///
/// [AArch64 Procedure Call Standard]:
/// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
#[cfg(all(target_arch = "aarch64", not(windows)))]
#[repr(C)]
#[derive(Debug)]
#[unstable(feature = "c_variadic",
           reason = "the `c_variadic` feature has not been properly tested on \
                     all supported platforms",
           issue = "44930")]
struct VaListImpl {
    stack: *mut c_void,
    gr_top: *mut c_void,
    vr_top: *mut c_void,
    gr_offs: i32,
    vr_offs: i32,
}

/// PowerPC ABI implementation of a `va_list`.
#[cfg(all(target_arch = "powerpc", not(windows)))]
#[repr(C)]
#[derive(Debug)]
#[unstable(feature = "c_variadic",
           reason = "the `c_variadic` feature has not been properly tested on \
                     all supported platforms",
           issue = "44930")]
struct VaListImpl {
    gpr: u8,
    fpr: u8,
    reserved: u16,
    overflow_arg_area: *mut c_void,
    reg_save_area: *mut c_void,
}

/// x86_64 ABI implementation of a `va_list`.
#[cfg(all(target_arch = "x86_64", not(windows)))]
#[repr(C)]
#[derive(Debug)]
#[unstable(feature = "c_variadic",
           reason = "the `c_variadic` feature has not been properly tested on \
                     all supported platforms",
           issue = "44930")]
struct VaListImpl {
    gp_offset: i32,
    fp_offset: i32,
    overflow_arg_area: *mut c_void,
    reg_save_area: *mut c_void,
}

/// A wrapper for a `va_list`
#[lang = "va_list"]
#[derive(Debug)]
#[unstable(feature = "c_variadic",
           reason = "the `c_variadic` feature has not been properly tested on \
                     all supported platforms",
           issue = "44930")]
#[repr(transparent)]
pub struct VaList<'a>(&'a mut VaListImpl);

// The VaArgSafe trait needs to be used in public interfaces, however, the trait
// itself must not be allowed to be used outside this module. Allowing users to
// implement the trait for a new type (thereby allowing the va_arg intrinsic to
// be used on a new type) is likely to cause undefined behavior.
//
// FIXME(dlrobertson): In order to use the VaArgSafe trait in a public interface
// but also ensure it cannot be used elsewhere, the trait needs to be public
// within a private module. Once RFC 2145 has been implemented look into
// improving this.
mod sealed_trait {
    /// Trait which whitelists the allowed types to be used with [VaList::arg]
    ///
    /// [VaList::va_arg]: struct.VaList.html#method.arg
    #[unstable(feature = "c_variadic",
               reason = "the `c_variadic` feature has not been properly tested on \
                         all supported platforms",
               issue = "44930")]
    pub trait VaArgSafe {}
}

macro_rules! impl_va_arg_safe {
    ($($t:ty),+) => {
        $(
            #[unstable(feature = "c_variadic",
                       reason = "the `c_variadic` feature has not been properly tested on \
                                 all supported platforms",
                       issue = "44930")]
            impl sealed_trait::VaArgSafe for $t {}
        )+
    }
}

impl_va_arg_safe!{i8, i16, i32, i64, usize}
impl_va_arg_safe!{u8, u16, u32, u64, isize}
impl_va_arg_safe!{f64}

#[unstable(feature = "c_variadic",
           reason = "the `c_variadic` feature has not been properly tested on \
                     all supported platforms",
           issue = "44930")]
impl<T> sealed_trait::VaArgSafe for *mut T {}
#[unstable(feature = "c_variadic",
           reason = "the `c_variadic` feature has not been properly tested on \
                     all supported platforms",
           issue = "44930")]
impl<T> sealed_trait::VaArgSafe for *const T {}

impl<'a> VaList<'a> {
    /// Advance to the next arg.
    #[unstable(feature = "c_variadic",
               reason = "the `c_variadic` feature has not been properly tested on \
                         all supported platforms",
               issue = "44930")]
    pub unsafe fn arg<T: sealed_trait::VaArgSafe>(&mut self) -> T {
        va_arg(self)
    }

    /// Copies the `va_list` at the current location.
    #[unstable(feature = "c_variadic",
               reason = "the `c_variadic` feature has not been properly tested on \
                         all supported platforms",
               issue = "44930")]
    pub unsafe fn copy<F, R>(&self, f: F) -> R
            where F: for<'copy> FnOnce(VaList<'copy>) -> R {
        #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
                      not(target_arch = "x86_64")),
                  all(target_arch = "aarch64", target_os = "ios"),
                  windows))]
        let mut ap = va_copy(self);
        #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
                  not(windows)))]
        let mut ap_inner = va_copy(self);
        #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
                  not(windows)))]
        let mut ap = VaList(&mut ap_inner);
        let ret = f(VaList(ap.0));
        va_end(&mut ap);
        ret
    }
}

extern "rust-intrinsic" {
    /// Destroy the arglist `ap` after initialization with `va_start` or
    /// `va_copy`.
    fn va_end(ap: &mut VaList);

    /// Copies the current location of arglist `src` to the arglist `dst`.
    #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
                  not(target_arch = "x86_64")),
              windows))]
    fn va_copy<'a>(src: &VaList<'a>) -> VaList<'a>;
    #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
              not(windows)))]
    fn va_copy(src: &VaList) -> VaListImpl;

    /// Loads an argument of type `T` from the `va_list` `ap` and increment the
    /// argument `ap` points to.
    fn va_arg<T: sealed_trait::VaArgSafe>(ap: &mut VaList) -> T;
}
<commit_msg>Fix missing cfg for aarch64 + ios in ffi.rs<commit_after>#![stable(feature = "", since = "1.30.0")]

#![allow(non_camel_case_types)]

//! Utilities related to FFI bindings.

use ::fmt;

/// Equivalent to C's `void` type when used as a [pointer].
///
/// In essence, `*const c_void` is equivalent to C's `const void*`
/// and `*mut c_void` is equivalent to C's `void*`. That said, this is
/// *not* the same as C's `void` return type, which is Rust's `()` type.
///
/// To model pointers to opaque types in FFI, until `extern type` is
/// stabilized, it is recommended to use a newtype wrapper around an empty
/// byte array. See the [Nomicon] for details.
///
/// [pointer]: ../../std/primitive.pointer.html
/// [Nomicon]: https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs
// N.B., for LLVM to recognize the void pointer type and by extension
//     functions like malloc(), we need to have it represented as i8* in
//     LLVM bitcode. The enum used here ensures this and prevents misuse
//     of the "raw" type by only having private variants. We need two
//     variants, because the compiler complains about the repr attribute
//     otherwise and we need at least one variant as otherwise the enum
//     would be uninhabited and at least dereferencing such pointers would
//     be UB.
#[repr(u8)]
#[stable(feature = "raw_os", since = "1.1.0")]
pub enum c_void {
    #[unstable(feature = "c_void_variant", reason = "temporary implementation detail",
               issue = "0")]
    #[doc(hidden)] __variant1,
    #[unstable(feature = "c_void_variant", reason = "temporary implementation detail",
               issue = "0")]
    #[doc(hidden)] __variant2,
}

#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for c_void {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad("c_void")
    }
}

/// Basic implementation of a `va_list`.
#[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
              not(target_arch = "x86_64")),
          all(target_arch = "aarch64", target_os = "ios"),
          windows))]
#[unstable(feature = "c_variadic",
           reason = "the `c_variadic` feature has not been properly tested on \
                     all supported platforms",
           issue = "44930")]
extern {
    type VaListImpl;
}

#[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
              not(target_arch = "x86_64")),
          all(target_arch = "aarch64", target_os = "ios"),
          windows))]
impl fmt::Debug for VaListImpl {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "va_list* {:p}", self)
    }
}

/// AArch64 ABI implementation of a `va_list`. See the
/// [AArch64 Procedure Call Standard] for more details.
///
/// [AArch64 Procedure Call Standard]:
/// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
#[cfg(all(target_arch = "aarch64", not(target_os = "ios"), not(windows)))]
#[repr(C)]
#[derive(Debug)]
#[unstable(feature = "c_variadic",
           reason = "the `c_variadic` feature has not been properly tested on \
                     all supported platforms",
           issue = "44930")]
struct VaListImpl {
    stack: *mut c_void,
    gr_top: *mut c_void,
    vr_top: *mut c_void,
    gr_offs: i32,
    vr_offs: i32,
}

/// PowerPC ABI implementation of a `va_list`.
#[cfg(all(target_arch = "powerpc", not(windows)))]
#[repr(C)]
#[derive(Debug)]
#[unstable(feature = "c_variadic",
           reason = "the `c_variadic` feature has not been properly tested on \
                     all supported platforms",
           issue = "44930")]
struct VaListImpl {
    gpr: u8,
    fpr: u8,
    reserved: u16,
    overflow_arg_area: *mut c_void,
    reg_save_area: *mut c_void,
}

/// x86_64 ABI implementation of a `va_list`.
#[cfg(all(target_arch = "x86_64", not(windows)))]
#[repr(C)]
#[derive(Debug)]
#[unstable(feature = "c_variadic",
           reason = "the `c_variadic` feature has not been properly tested on \
                     all supported platforms",
           issue = "44930")]
struct VaListImpl {
    gp_offset: i32,
    fp_offset: i32,
    overflow_arg_area: *mut c_void,
    reg_save_area: *mut c_void,
}

/// A wrapper for a `va_list`
#[lang = "va_list"]
#[derive(Debug)]
#[unstable(feature = "c_variadic",
           reason = "the `c_variadic` feature has not been properly tested on \
                     all supported platforms",
           issue = "44930")]
#[repr(transparent)]
pub struct VaList<'a>(&'a mut VaListImpl);

// The VaArgSafe trait needs to be used in public interfaces, however, the trait
// itself must not be allowed to be used outside this module. Allowing users to
// implement the trait for a new type (thereby allowing the va_arg intrinsic to
// be used on a new type) is likely to cause undefined behavior.
//
// FIXME(dlrobertson): In order to use the VaArgSafe trait in a public interface
// but also ensure it cannot be used elsewhere, the trait needs to be public
// within a private module. Once RFC 2145 has been implemented look into
// improving this.
mod sealed_trait {
    /// Trait which whitelists the allowed types to be used with [VaList::arg]
    ///
    /// [VaList::va_arg]: struct.VaList.html#method.arg
    #[unstable(feature = "c_variadic",
               reason = "the `c_variadic` feature has not been properly tested on \
                         all supported platforms",
               issue = "44930")]
    pub trait VaArgSafe {}
}

macro_rules! impl_va_arg_safe {
    ($($t:ty),+) => {
        $(
            #[unstable(feature = "c_variadic",
                       reason = "the `c_variadic` feature has not been properly tested on \
                                 all supported platforms",
                       issue = "44930")]
            impl sealed_trait::VaArgSafe for $t {}
        )+
    }
}

impl_va_arg_safe!{i8, i16, i32, i64, usize}
impl_va_arg_safe!{u8, u16, u32, u64, isize}
impl_va_arg_safe!{f64}

#[unstable(feature = "c_variadic",
           reason = "the `c_variadic` feature has not been properly tested on \
                     all supported platforms",
           issue = "44930")]
impl<T> sealed_trait::VaArgSafe for *mut T {}
#[unstable(feature = "c_variadic",
           reason = "the `c_variadic` feature has not been properly tested on \
                     all supported platforms",
           issue = "44930")]
impl<T> sealed_trait::VaArgSafe for *const T {}

impl<'a> VaList<'a> {
    /// Advance to the next arg.
    #[unstable(feature = "c_variadic",
               reason = "the `c_variadic` feature has not been properly tested on \
                         all supported platforms",
               issue = "44930")]
    pub unsafe fn arg<T: sealed_trait::VaArgSafe>(&mut self) -> T {
        va_arg(self)
    }

    /// Copies the `va_list` at the current location.
    #[unstable(feature = "c_variadic",
               reason = "the `c_variadic` feature has not been properly tested on \
                         all supported platforms",
               issue = "44930")]
    pub unsafe fn copy<F, R>(&self, f: F) -> R
            where F: for<'copy> FnOnce(VaList<'copy>) -> R {
        #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
                      not(target_arch = "x86_64")),
                  all(target_arch = "aarch64", target_os = "ios"),
                  windows))]
        let mut ap = va_copy(self);
        #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
                  not(windows), not(all(target_arch = "aarch64", target_os = "ios"))))]
        let mut ap_inner = va_copy(self);
        #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
                  not(windows), not(all(target_arch = "aarch64", target_os = "ios"))))]
        let mut ap = VaList(&mut ap_inner);
        let ret = f(VaList(ap.0));
        va_end(&mut ap);
        ret
    }
}

extern "rust-intrinsic" {
    /// Destroy the arglist `ap` after initialization with `va_start` or
    /// `va_copy`.
    fn va_end(ap: &mut VaList);

    /// Copies the current location of arglist `src` to the arglist `dst`.
    #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
                  not(target_arch = "x86_64")),
              all(target_arch = "aarch64", target_os = "ios"),
              windows))]
    fn va_copy<'a>(src: &VaList<'a>) -> VaList<'a>;
    #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
              not(windows), not(all(target_arch = "aarch64", target_os = "ios"))))]
    fn va_copy(src: &VaList) -> VaListImpl;

    /// Loads an argument of type `T` from the `va_list` `ap` and increment the
    /// argument `ap` points to.
    fn va_arg<T: sealed_trait::VaArgSafe>(ap: &mut VaList) -> T;
}
<|endoftext|>


<commit_before>// Copyright 2012-2014 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.

//! Basic functions for dealing with memory
//!
//! This module contains functions for querying the size and alignment of
//! types, initializing and manipulating memory.

#![stable]

use kinds::Sized;
use intrinsics;
use ptr;

#[stable]
pub use intrinsics::transmute;

/// Moves a thing into the void.
///
/// The forget function will take ownership of the provided value but neglect
/// to run any required cleanup or memory management operations on it.
///
/// This function is the unsafe version of the `drop` function because it does
/// not run any destructors.
#[stable]
pub use intrinsics::forget;

/// Returns the size of a type in bytes.
#[inline]
#[stable]
pub fn size_of<T>() -> uint {
    unsafe { intrinsics::size_of::<T>() }
}

/// Returns the size of the type that `_val` points to in bytes.
#[inline]
#[stable]
pub fn size_of_val<T>(_val: &T) -> uint {
    size_of::<T>()
}

/// Returns the ABI-required minimum alignment of a type
///
/// This is the alignment used for struct fields. It may be smaller
/// than the preferred alignment.
#[inline]
#[stable]
pub fn min_align_of<T>() -> uint {
    unsafe { intrinsics::min_align_of::<T>() }
}

/// Returns the ABI-required minimum alignment of the type of the value that
/// `_val` points to
#[inline]
#[stable]
pub fn min_align_of_val<T>(_val: &T) -> uint {
    min_align_of::<T>()
}

/// Returns the alignment in memory for a type.
///
/// This function will return the alignment, in bytes, of a type in memory. If
/// the alignment returned is adhered to, then the type is guaranteed to
/// function properly.
#[inline]
#[stable]
pub fn align_of<T>() -> uint {
    // We use the preferred alignment as the default alignment for a type. This
    // appears to be what clang migrated towards as well:
    //
    // http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20110725/044411.html
    unsafe { intrinsics::pref_align_of::<T>() }
}

/// Returns the alignment of the type of the value that `_val` points to.
///
/// This is similar to `align_of`, but function will properly handle types such
/// as trait objects (in the future), returning the alignment for an arbitrary
/// value at runtime.
#[inline]
#[stable]
pub fn align_of_val<T>(_val: &T) -> uint {
    align_of::<T>()
}

/// Create a value initialized to zero.
///
/// This function is similar to allocating space for a local variable and
/// zeroing it out (an unsafe operation).
///
/// Care must be taken when using this function, if the type `T` has a
/// destructor and the value falls out of scope (due to unwinding or returning)
/// before being initialized, then the destructor will run on zeroed
/// data, likely leading to crashes.
///
/// This is useful for FFI functions sometimes, but should generally be avoided.
#[inline]
#[stable]
pub unsafe fn zeroed<T>() -> T {
    intrinsics::init()
}

/// Create an uninitialized value.
///
/// Care must be taken when using this function, if the type `T` has a
/// destructor and the value falls out of scope (due to unwinding or returning)
/// before being initialized, then the destructor will run on uninitialized
/// data, likely leading to crashes.
///
/// This is useful for FFI functions sometimes, but should generally be avoided.
#[inline]
#[stable]
pub unsafe fn uninitialized<T>() -> T {
    intrinsics::uninit()
}

/// Swap the values at two mutable locations of the same type, without
/// deinitialising or copying either one.
#[inline]
#[stable]
pub fn swap<T>(x: &mut T, y: &mut T) {
    unsafe {
        // Give ourselves some scratch space to work with
        let mut t: T = uninitialized();

        // Perform the swap, `&mut` pointers never alias
        ptr::copy_nonoverlapping_memory(&mut t, &*x, 1);
        ptr::copy_nonoverlapping_memory(x, &*y, 1);
        ptr::copy_nonoverlapping_memory(y, &t, 1);

        // y and t now point to the same thing, but we need to completely forget `t`
        // because it's no longer relevant.
        forget(t);
    }
}

/// Replace the value at a mutable location with a new one, returning the old
/// value, without deinitialising or copying either one.
///
/// This is primarily used for transferring and swapping ownership of a value
/// in a mutable location. For example, this function allows consumption of
/// one field of a struct by replacing it with another value. The normal approach
/// doesn't always work:
///
/// ```rust,ignore
/// struct Buffer<T> { buf: Vec<T> }
///
/// impl<T> Buffer<T> {
///     fn get_and_reset(&mut self) -> Vec<T> {
///         // error: cannot move out of dereference of `&mut`-pointer
///         let buf = self.buf;
///         self.buf = Vec::new();
///         buf
///     }
/// }
/// ```
///
/// Note that `T` does not necessarily implement `Clone`, so it can't even
/// clone and reset `self.buf`. But `replace` can be used to disassociate
/// the original value of `self.buf` from `self`, allowing it to be returned:
///
/// ```rust
/// # struct Buffer<T> { buf: Vec<T> }
/// impl<T> Buffer<T> {
///     fn get_and_reset(&mut self) -> Vec<T> {
///         use std::mem::replace;
///         replace(&mut self.buf, Vec::new())
///     }
/// }
/// ```
#[inline]
#[stable]
pub fn replace<T>(dest: &mut T, mut src: T) -> T {
    swap(dest, &mut src);
    src
}

/// Disposes of a value.
///
/// This function can be used to destroy any value by allowing `drop` to take
/// ownership of its argument.
///
/// # Example
///
/// ```
/// use std::cell::RefCell;
///
/// let x = RefCell::new(1i);
///
/// let mut mutable_borrow = x.borrow_mut();
/// *mutable_borrow = 1;
/// drop(mutable_borrow); // relinquish the mutable borrow on this slot
///
/// let borrow = x.borrow();
/// println!("{}", *borrow);
/// ```
#[inline]
#[stable]
pub fn drop<T>(_x: T) { }

/// Interprets `src` as `&U`, and then reads `src` without moving the contained
/// value.
///
/// This function will unsafely assume the pointer `src` is valid for
/// `sizeof(U)` bytes by transmuting `&T` to `&U` and then reading the `&U`. It
/// will also unsafely create a copy of the contained value instead of moving
/// out of `src`.
///
/// It is not a compile-time error if `T` and `U` have different sizes, but it
/// is highly encouraged to only invoke this function where `T` and `U` have the
/// same size. This function triggers undefined behavior if `U` is larger than
/// `T`.
#[inline]
#[stable]
pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
    ptr::read(src as *const T as *const U)
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
#[unstable = "this function may be removed in the future due to its \
              questionable utility"]
pub unsafe fn copy_lifetime<'a, Sized? S, Sized? T: 'a>(_ptr: &'a S,
                                                        ptr: &T) -> &'a T {
    transmute(ptr)
}

/// Transforms lifetime of the second mutable pointer to match the first.
#[inline]
#[unstable = "this function may be removed in the future due to its \
              questionable utility"]
pub unsafe fn copy_mut_lifetime<'a, Sized? S, Sized? T: 'a>(_ptr: &'a mut S,
                                                            ptr: &mut T)
                                                            -> &'a mut T {
    transmute(ptr)
}
<commit_msg>rollup merge of #19942: steveklabnik/doc_std_mem<commit_after>// Copyright 2012-2014 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.

//! Basic functions for dealing with memory
//!
//! This module contains functions for querying the size and alignment of
//! types, initializing and manipulating memory.

#![stable]

use kinds::Sized;
use intrinsics;
use ptr;

#[stable]
pub use intrinsics::transmute;

/// Moves a thing into the void.
///
/// The forget function will take ownership of the provided value but neglect
/// to run any required cleanup or memory management operations on it.
///
/// This function is the unsafe version of the `drop` function because it does
/// not run any destructors.
#[stable]
pub use intrinsics::forget;

/// Returns the size of a type in bytes.
///
/// # Examples
///
/// ```
/// use std::mem;
///
/// assert_eq!(4, mem::size_of::<i32>());
/// ```
#[inline]
#[stable]
pub fn size_of<T>() -> uint {
    unsafe { intrinsics::size_of::<T>() }
}

/// Returns the size of the type that `_val` points to in bytes.
///
/// # Examples
///
/// ```
/// use std::mem;
///
/// assert_eq!(4, mem::size_of_val(&5i32));
/// ```
#[inline]
#[stable]
pub fn size_of_val<T>(_val: &T) -> uint {
    size_of::<T>()
}

/// Returns the ABI-required minimum alignment of a type
///
/// This is the alignment used for struct fields. It may be smaller than the preferred alignment.
///
/// # Examples
///
/// ```
/// use std::mem;
///
/// assert_eq!(4, mem::min_align_of::<i32>());
/// ```
#[inline]
#[stable]
pub fn min_align_of<T>() -> uint {
    unsafe { intrinsics::min_align_of::<T>() }
}

/// Returns the ABI-required minimum alignment of the type of the value that `_val` points to
///
/// # Examples
///
/// ```
/// use std::mem;
///
/// assert_eq!(4, mem::min_align_of_val(&5i32));
/// ```
#[inline]
#[stable]
pub fn min_align_of_val<T>(_val: &T) -> uint {
    min_align_of::<T>()
}

/// Returns the alignment in memory for a type.
///
/// This function will return the alignment, in bytes, of a type in memory. If the alignment
/// returned is adhered to, then the type is guaranteed to function properly.
///
/// # Examples
///
/// ```
/// use std::mem;
///
/// assert_eq!(4, mem::align_of::<i32>());
/// ```
#[inline]
#[stable]
pub fn align_of<T>() -> uint {
    // We use the preferred alignment as the default alignment for a type. This
    // appears to be what clang migrated towards as well:
    //
    // http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20110725/044411.html
    unsafe { intrinsics::pref_align_of::<T>() }
}

/// Returns the alignment of the type of the value that `_val` points to.
///
/// This is similar to `align_of`, but function will properly handle types such as trait objects
/// (in the future), returning the alignment for an arbitrary value at runtime.
///
/// # Examples
///
/// ```
/// use std::mem;
///
/// assert_eq!(4, mem::align_of_val(&5i32));
/// ```
#[inline]
#[stable]
pub fn align_of_val<T>(_val: &T) -> uint {
    align_of::<T>()
}

/// Create a value initialized to zero.
///
/// This function is similar to allocating space for a local variable and zeroing it out (an unsafe
/// operation).
///
/// Care must be taken when using this function, if the type `T` has a destructor and the value
/// falls out of scope (due to unwinding or returning) before being initialized, then the
/// destructor will run on zeroed data, likely leading to crashes.
///
/// This is useful for FFI functions sometimes, but should generally be avoided.
///
/// # Examples
///
/// ```
/// use std::mem;
///
/// let x: int = unsafe { mem::zeroed() };
/// ```
#[inline]
#[stable]
pub unsafe fn zeroed<T>() -> T {
    intrinsics::init()
}

/// Create an uninitialized value.
///
/// Care must be taken when using this function, if the type `T` has a destructor and the value
/// falls out of scope (due to unwinding or returning) before being initialized, then the
/// destructor will run on uninitialized data, likely leading to crashes.
///
/// This is useful for FFI functions sometimes, but should generally be avoided.
///
/// # Examples
///
/// ```
/// use std::mem;
///
/// let x: int = unsafe { mem::uninitialized() };
/// ```
#[inline]
#[stable]
pub unsafe fn uninitialized<T>() -> T {
    intrinsics::uninit()
}

/// Swap the values at two mutable locations of the same type, without deinitialising or copying
/// either one.
///
/// # Examples
///
/// ```
/// use std::mem;
///
/// let x = &mut 5i;
/// let y = &mut 42i;
///
/// mem::swap(x, y);
///
/// assert_eq!(42i, *x);
/// assert_eq!(5i, *y);
/// ```
#[inline]
#[stable]
pub fn swap<T>(x: &mut T, y: &mut T) {
    unsafe {
        // Give ourselves some scratch space to work with
        let mut t: T = uninitialized();

        // Perform the swap, `&mut` pointers never alias
        ptr::copy_nonoverlapping_memory(&mut t, &*x, 1);
        ptr::copy_nonoverlapping_memory(x, &*y, 1);
        ptr::copy_nonoverlapping_memory(y, &t, 1);

        // y and t now point to the same thing, but we need to completely forget `t`
        // because it's no longer relevant.
        forget(t);
    }
}

/// Replace the value at a mutable location with a new one, returning the old value, without
/// deinitialising or copying either one.
///
/// This is primarily used for transferring and swapping ownership of a value in a mutable
/// location.
///
/// # Examples
///
/// A simple example:
///
/// ```
/// use std::mem;
///
/// let mut v: Vec<i32> = Vec::new();
///
/// mem::replace(&mut v, Vec::new());
/// ```
///
/// This function allows consumption of one field of a struct by replacing it with another value.
/// The normal approach doesn't always work:
///
/// ```rust,ignore
/// struct Buffer<T> { buf: Vec<T> }
///
/// impl<T> Buffer<T> {
///     fn get_and_reset(&mut self) -> Vec<T> {
///         // error: cannot move out of dereference of `&mut`-pointer
///         let buf = self.buf;
///         self.buf = Vec::new();
///         buf
///     }
/// }
/// ```
///
/// Note that `T` does not necessarily implement `Clone`, so it can't even clone and reset
/// `self.buf`. But `replace` can be used to disassociate the original value of `self.buf` from
/// `self`, allowing it to be returned:
///
/// ```rust
/// use std::mem;
/// # struct Buffer<T> { buf: Vec<T> }
/// impl<T> Buffer<T> {
///     fn get_and_reset(&mut self) -> Vec<T> {
///         mem::replace(&mut self.buf, Vec::new())
///     }
/// }
/// ```
#[inline]
#[stable]
pub fn replace<T>(dest: &mut T, mut src: T) -> T {
    swap(dest, &mut src);
    src
}

/// Disposes of a value.
///
/// This function can be used to destroy any value by allowing `drop` to take ownership of its
/// argument.
///
/// # Examples
///
/// ```
/// use std::cell::RefCell;
///
/// let x = RefCell::new(1i);
///
/// let mut mutable_borrow = x.borrow_mut();
/// *mutable_borrow = 1;
///
/// drop(mutable_borrow); // relinquish the mutable borrow on this slot
///
/// let borrow = x.borrow();
/// println!("{}", *borrow);
/// ```
#[inline]
#[stable]
pub fn drop<T>(_x: T) { }

/// Interprets `src` as `&U`, and then reads `src` without moving the contained value.
///
/// This function will unsafely assume the pointer `src` is valid for `sizeof(U)` bytes by
/// transmuting `&T` to `&U` and then reading the `&U`. It will also unsafely create a copy of the
/// contained value instead of moving out of `src`.
///
/// It is not a compile-time error if `T` and `U` have different sizes, but it is highly encouraged
/// to only invoke this function where `T` and `U` have the same size. This function triggers
/// undefined behavior if `U` is larger than `T`.
///
/// # Examples
///
/// ```
/// use std::mem;
///
/// let one = unsafe { mem::transmute_copy(&1i) };
///
/// assert_eq!(1u, one);
/// ```
#[inline]
#[stable]
pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
    ptr::read(src as *const T as *const U)
}

/// Transforms lifetime of the second pointer to match the first.
#[inline]
#[unstable = "this function may be removed in the future due to its \
              questionable utility"]
pub unsafe fn copy_lifetime<'a, Sized? S, Sized? T: 'a>(_ptr: &'a S,
                                                        ptr: &T) -> &'a T {
    transmute(ptr)
}

/// Transforms lifetime of the second mutable pointer to match the first.
#[inline]
#[unstable = "this function may be removed in the future due to its \
              questionable utility"]
pub unsafe fn copy_mut_lifetime<'a, Sized? S, Sized? T: 'a>(_ptr: &'a mut S,
                                                            ptr: &mut T)
                                                            -> &'a mut T {
    transmute(ptr)
}
<|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.

//! Misc low level stuff

use cast;
use cmp::{Eq, Ord};
use gc;
use io;
use libc;
use libc::{c_void, c_char, size_t};
use repr;
use str;

pub type FreeGlue<'self> = &'self fn(*TypeDesc, *c_void);

// Corresponds to runtime type_desc type
pub struct TypeDesc {
    size: uint,
    align: uint,
    take_glue: uint,
    drop_glue: uint,
    free_glue: uint
    // Remaining fields not listed
}

/// The representation of a Rust closure
pub struct Closure {
    code: *(),
    env: *(),
}

pub mod rusti {
    #[abi = "rust-intrinsic"]
    pub extern "rust-intrinsic" {
        fn get_tydesc<T>() -> *();
        fn size_of<T>() -> uint;
        fn pref_align_of<T>() -> uint;
        fn min_align_of<T>() -> uint;
    }
}

pub mod rustrt {
    use libc::{c_char, size_t};

    pub extern {
        #[rust_stack]
        unsafe fn rust_upcall_fail(expr: *c_char,
                                   file: *c_char,
                                   line: size_t);
    }
}

/// Compares contents of two pointers using the default method.
/// Equivalent to `*x1 == *x2`.  Useful for hashtables.
pub fn shape_eq<T:Eq>(x1: &T, x2: &T) -> bool {
    *x1 == *x2
}

pub fn shape_lt<T:Ord>(x1: &T, x2: &T) -> bool {
    *x1 < *x2
}

pub fn shape_le<T:Ord>(x1: &T, x2: &T) -> bool {
    *x1 <= *x2
}

/**
 * Returns a pointer to a type descriptor.
 *
 * Useful for calling certain function in the Rust runtime or otherwise
 * performing dark magick.
 */
#[inline(always)]
pub fn get_type_desc<T>() -> *TypeDesc {
    unsafe { rusti::get_tydesc::<T>() as *TypeDesc }
}

/// Returns the size of a type
#[inline(always)]
pub fn size_of<T>() -> uint {
    unsafe { rusti::size_of::<T>() }
}

/**
 * Returns the size of a type, or 1 if the actual size is zero.
 *
 * Useful for building structures containing variable-length arrays.
 */
#[inline(always)]
pub fn nonzero_size_of<T>() -> uint {
    let s = size_of::<T>();
    if s == 0 { 1 } else { s }
}

/**
 * Returns the ABI-required minimum alignment of a type
 *
 * This is the alignment used for struct fields. It may be smaller
 * than the preferred alignment.
 */
#[inline(always)]
pub fn min_align_of<T>() -> uint {
    unsafe { rusti::min_align_of::<T>() }
}

/// Returns the preferred alignment of a type
#[inline(always)]
pub fn pref_align_of<T>() -> uint {
    unsafe { rusti::pref_align_of::<T>() }
}

/// Returns the refcount of a shared box (as just before calling this)
#[inline(always)]
pub fn refcount<T>(t: @T) -> uint {
    unsafe {
        let ref_ptr: *uint = cast::reinterpret_cast(&t);
        *ref_ptr - 1
    }
}

pub fn log_str<T>(t: &T) -> ~str {
    do io::with_str_writer |wr| {
        repr::write_repr(wr, t)
    }
}

/** Initiate task failure */
pub fn begin_unwind(msg: ~str, file: ~str, line: uint) -> ! {
    do str::as_buf(msg) |msg_buf, _msg_len| {
        do str::as_buf(file) |file_buf, _file_len| {
            unsafe {
                let msg_buf = cast::transmute(msg_buf);
                let file_buf = cast::transmute(file_buf);
                begin_unwind_(msg_buf, file_buf, line as libc::size_t)
            }
        }
    }
}

// FIXME #4427: Temporary until rt::rt_fail_ goes away
pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! {
    unsafe {
        gc::cleanup_stack_for_failure();
        rustrt::rust_upcall_fail(msg, file, line);
        cast::transmute(())
    }
}

pub fn fail_assert(msg: &str, file: &str, line: uint) -> ! {
    let (msg, file) = (msg.to_owned(), file.to_owned());
    begin_unwind(~"assertion failed: " + msg, file, line)
}

#[cfg(test)]
mod tests {
    use cast;
    use sys::{Closure, pref_align_of, size_of, nonzero_size_of};

    #[test]
    fn size_of_basic() {
        assert!(size_of::<u8>() == 1u);
        assert!(size_of::<u16>() == 2u);
        assert!(size_of::<u32>() == 4u);
        assert!(size_of::<u64>() == 8u);
    }

    #[test]
    #[cfg(target_arch = "x86")]
    #[cfg(target_arch = "arm")]
    #[cfg(target_arch = "mips")]
    fn size_of_32() {
        assert!(size_of::<uint>() == 4u);
        assert!(size_of::<*uint>() == 4u);
    }

    #[test]
    #[cfg(target_arch = "x86_64")]
    fn size_of_64() {
        assert!(size_of::<uint>() == 8u);
        assert!(size_of::<*uint>() == 8u);
    }

    #[test]
    fn nonzero_size_of_basic() {
        type Z = [i8, ..0];
        assert!(size_of::<Z>() == 0u);
        assert!(nonzero_size_of::<Z>() == 1u);
        assert!(nonzero_size_of::<uint>() == size_of::<uint>());
    }

    #[test]
    fn align_of_basic() {
        assert!(pref_align_of::<u8>() == 1u);
        assert!(pref_align_of::<u16>() == 2u);
        assert!(pref_align_of::<u32>() == 4u);
    }

    #[test]
    #[cfg(target_arch = "x86")]
    #[cfg(target_arch = "arm")]
    #[cfg(target_arch = "mips")]
    fn align_of_32() {
        assert!(pref_align_of::<uint>() == 4u);
        assert!(pref_align_of::<*uint>() == 4u);
    }

    #[test]
    #[cfg(target_arch = "x86_64")]
    fn align_of_64() {
        assert!(pref_align_of::<uint>() == 8u);
        assert!(pref_align_of::<*uint>() == 8u);
    }

    #[test]
    fn synthesize_closure() {
        unsafe {
            let x = 10;
            let f: &fn(int) -> int = |y| x + y;

            assert!(f(20) == 30);

            let original_closure: Closure = cast::transmute(f);

            let actual_function_pointer = original_closure.code;
            let environment = original_closure.env;

            let new_closure = Closure {
                code: actual_function_pointer,
                env: environment
            };

            let new_f: &fn(int) -> int = cast::transmute(new_closure);
            assert!(new_f(20) == 30);
        }
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>libcore: wrappers for size/align_of to act on values without needing explicit ::<type> annotations<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.

//! Misc low level stuff

use cast;
use cmp::{Eq, Ord};
use gc;
use io;
use libc;
use libc::{c_void, c_char, size_t};
use repr;
use str;

pub type FreeGlue<'self> = &'self fn(*TypeDesc, *c_void);

// Corresponds to runtime type_desc type
pub struct TypeDesc {
    size: uint,
    align: uint,
    take_glue: uint,
    drop_glue: uint,
    free_glue: uint
    // Remaining fields not listed
}

/// The representation of a Rust closure
pub struct Closure {
    code: *(),
    env: *(),
}

pub mod rusti {
    #[abi = "rust-intrinsic"]
    pub extern "rust-intrinsic" {
        fn get_tydesc<T>() -> *();
        fn size_of<T>() -> uint;
        fn pref_align_of<T>() -> uint;
        fn min_align_of<T>() -> uint;
    }
}

pub mod rustrt {
    use libc::{c_char, size_t};

    pub extern {
        #[rust_stack]
        unsafe fn rust_upcall_fail(expr: *c_char,
                                   file: *c_char,
                                   line: size_t);
    }
}

/// Compares contents of two pointers using the default method.
/// Equivalent to `*x1 == *x2`.  Useful for hashtables.
pub fn shape_eq<T:Eq>(x1: &T, x2: &T) -> bool {
    *x1 == *x2
}

pub fn shape_lt<T:Ord>(x1: &T, x2: &T) -> bool {
    *x1 < *x2
}

pub fn shape_le<T:Ord>(x1: &T, x2: &T) -> bool {
    *x1 <= *x2
}

/**
 * Returns a pointer to a type descriptor.
 *
 * Useful for calling certain function in the Rust runtime or otherwise
 * performing dark magick.
 */
#[inline(always)]
pub fn get_type_desc<T>() -> *TypeDesc {
    unsafe { rusti::get_tydesc::<T>() as *TypeDesc }
}

/// Returns a pointer to a type descriptor.
#[inline(always)]
pub fn get_type_desc_val<T>(_val: &T) -> *TypeDesc {
    get_type_desc::<T>()
}

/// Returns the size of a type
#[inline(always)]
pub fn size_of<T>() -> uint {
    unsafe { rusti::size_of::<T>() }
}

/// Returns the size of the type that `_val` points to
#[inline(always)]
pub fn size_of_val<T>(_val: &T) -> uint {
    size_of::<T>()
}

/**
 * Returns the size of a type, or 1 if the actual size is zero.
 *
 * Useful for building structures containing variable-length arrays.
 */
#[inline(always)]
pub fn nonzero_size_of<T>() -> uint {
    let s = size_of::<T>();
    if s == 0 { 1 } else { s }
}

/// Returns the size of the type of the value that `_val` points to
#[inline(always)]
pub fn nonzero_size_of_val<T>(_val: &T) -> uint {
    nonzero_size_of::<T>()
}

/**
 * Returns the ABI-required minimum alignment of a type
 *
 * This is the alignment used for struct fields. It may be smaller
 * than the preferred alignment.
 */
#[inline(always)]
pub fn min_align_of<T>() -> uint {
    unsafe { rusti::min_align_of::<T>() }
}

/// Returns the ABI-required minimum alignment of the type of the value that
/// `_val` points to
#[inline(always)]
pub fn min_align_of_val<T>(_val: &T) -> uint {
    min_align_of::<T>()
}

/// Returns the preferred alignment of a type
#[inline(always)]
pub fn pref_align_of<T>() -> uint {
    unsafe { rusti::pref_align_of::<T>() }
}

/// Returns the preferred alignment of the type of the value that
/// `_val` points to
#[inline(always)]
pub fn pref_align_of_val<T>(_val: &T) -> uint {
    pref_align_of::<T>()
}

/// Returns the refcount of a shared box (as just before calling this)
#[inline(always)]
pub fn refcount<T>(t: @T) -> uint {
    unsafe {
        let ref_ptr: *uint = cast::reinterpret_cast(&t);
        *ref_ptr - 1
    }
}

pub fn log_str<T>(t: &T) -> ~str {
    do io::with_str_writer |wr| {
        repr::write_repr(wr, t)
    }
}

/** Initiate task failure */
pub fn begin_unwind(msg: ~str, file: ~str, line: uint) -> ! {
    do str::as_buf(msg) |msg_buf, _msg_len| {
        do str::as_buf(file) |file_buf, _file_len| {
            unsafe {
                let msg_buf = cast::transmute(msg_buf);
                let file_buf = cast::transmute(file_buf);
                begin_unwind_(msg_buf, file_buf, line as libc::size_t)
            }
        }
    }
}

// FIXME #4427: Temporary until rt::rt_fail_ goes away
pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! {
    unsafe {
        gc::cleanup_stack_for_failure();
        rustrt::rust_upcall_fail(msg, file, line);
        cast::transmute(())
    }
}

pub fn fail_assert(msg: &str, file: &str, line: uint) -> ! {
    let (msg, file) = (msg.to_owned(), file.to_owned());
    begin_unwind(~"assertion failed: " + msg, file, line)
}

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

    #[test]
    fn size_of_basic() {
        assert!(size_of::<u8>() == 1u);
        assert!(size_of::<u16>() == 2u);
        assert!(size_of::<u32>() == 4u);
        assert!(size_of::<u64>() == 8u);
    }

    #[test]
    #[cfg(target_arch = "x86")]
    #[cfg(target_arch = "arm")]
    #[cfg(target_arch = "mips")]
    fn size_of_32() {
        assert!(size_of::<uint>() == 4u);
        assert!(size_of::<*uint>() == 4u);
    }

    #[test]
    #[cfg(target_arch = "x86_64")]
    fn size_of_64() {
        assert!(size_of::<uint>() == 8u);
        assert!(size_of::<*uint>() == 8u);
    }

    #[test]
    fn size_of_val_basic() {
        assert_eq!(size_of_val(&1u8), 1);
        assert_eq!(size_of_val(&1u16), 2);
        assert_eq!(size_of_val(&1u32), 4);
        assert_eq!(size_of_val(&1u64), 8);
    }

    #[test]
    fn nonzero_size_of_basic() {
        type Z = [i8, ..0];
        assert!(size_of::<Z>() == 0u);
        assert!(nonzero_size_of::<Z>() == 1u);
        assert!(nonzero_size_of::<uint>() == size_of::<uint>());
    }

    #[test]
    fn nonzero_size_of_val_basic() {
        let z = [0u8, ..0];
        assert_eq!(size_of_val(&z), 0u);
        assert_eq!(nonzero_size_of_val(&z), 1u);
        assert_eq!(nonzero_size_of_val(&1u), size_of_val(&1u));
    }

    #[test]
    fn align_of_basic() {
        assert!(pref_align_of::<u8>() == 1u);
        assert!(pref_align_of::<u16>() == 2u);
        assert!(pref_align_of::<u32>() == 4u);
    }

    #[test]
    #[cfg(target_arch = "x86")]
    #[cfg(target_arch = "arm")]
    #[cfg(target_arch = "mips")]
    fn align_of_32() {
        assert!(pref_align_of::<uint>() == 4u);
        assert!(pref_align_of::<*uint>() == 4u);
    }

    #[test]
    #[cfg(target_arch = "x86_64")]
    fn align_of_64() {
        assert!(pref_align_of::<uint>() == 8u);
        assert!(pref_align_of::<*uint>() == 8u);
    }

    #[test]
    fn align_of_val_basic() {
        assert_eq!(pref_align_of_val(&1u8), 1u);
        assert_eq!(pref_align_of_val(&1u16), 2u);
        assert_eq!(pref_align_of_val(&1u32), 4u);
    }

    #[test]
    fn synthesize_closure() {
        unsafe {
            let x = 10;
            let f: &fn(int) -> int = |y| x + y;

            assert!(f(20) == 30);

            let original_closure: Closure = cast::transmute(f);

            let actual_function_pointer = original_closure.code;
            let environment = original_closure.env;

            let new_closure = Closure {
                code: actual_function_pointer,
                env: environment
            };

            let new_f: &fn(int) -> int = cast::transmute(new_closure);
            assert!(new_f(20) == 30);
        }
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


<commit_before>use anyhow::anyhow;
use std::error::Error as StdError;
use std::fmt::{self, Display};
use std::io;

#[derive(Debug)]
enum TestError {
    Io(io::Error),
}

impl Display for TestError {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match self {
            TestError::Io(e) => Display::fmt(e, formatter),
        }
    }
}

impl StdError for TestError {
    fn source(&self) -> Option<&(dyn StdError + 'static)> {
        match self {
            TestError::Io(io) => Some(io),
        }
    }
}

#[test]
fn test_literal_source() {
    let error = anyhow!("oh no!");
    assert!(error.source().is_none());
}

#[test]
fn test_variable_source() {
    let msg = "oh no!";
    let error = anyhow!(msg);
    assert!(error.source().is_none());

    let msg = msg.to_owned();
    let error = anyhow!(msg);
    assert!(error.source().is_none());
}

#[test]
fn test_fmt_source() {
    let error = anyhow!("{} {}!", "oh", "no");
    assert!(error.source().is_none());
}

#[test]
fn test_io_source() {
    let io = io::Error::new(io::ErrorKind::Other, "oh no!");
    let error = anyhow!(TestError::Io(io));
    assert_eq!("oh no!", error.source().unwrap().to_string());
}
<commit_msg>Add test for anyhow from anyhow<commit_after>use anyhow::anyhow;
use std::error::Error as StdError;
use std::fmt::{self, Display};
use std::io;

#[derive(Debug)]
enum TestError {
    Io(io::Error),
}

impl Display for TestError {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match self {
            TestError::Io(e) => Display::fmt(e, formatter),
        }
    }
}

impl StdError for TestError {
    fn source(&self) -> Option<&(dyn StdError + 'static)> {
        match self {
            TestError::Io(io) => Some(io),
        }
    }
}

#[test]
fn test_literal_source() {
    let error = anyhow!("oh no!");
    assert!(error.source().is_none());
}

#[test]
fn test_variable_source() {
    let msg = "oh no!";
    let error = anyhow!(msg);
    assert!(error.source().is_none());

    let msg = msg.to_owned();
    let error = anyhow!(msg);
    assert!(error.source().is_none());
}

#[test]
fn test_fmt_source() {
    let error = anyhow!("{} {}!", "oh", "no");
    assert!(error.source().is_none());
}

#[test]
fn test_io_source() {
    let io = io::Error::new(io::ErrorKind::Other, "oh no!");
    let error = anyhow!(TestError::Io(io));
    assert_eq!("oh no!", error.source().unwrap().to_string());
}

#[test]
fn test_anyhow_from_anyhow() {
    let error = anyhow!("oh no!").context("context");
    let error = anyhow!(error);
    assert_eq!("oh no!", error.source().unwrap().to_string());
}
<|endoftext|>