<commit_before>#[macro_use] extern crate nom;

use std::str::FromStr;

use self::nom::{is_digit, space, newline};

#[cfg(test)]
mod tests {
  use nom;

  #[test]
  fn it_parses_a_u32() {
    let input = b"12345";
    let result = super::take_u32(input);
    match result {
      nom::IResult::Done(_, f) => assert_eq!(f, 12345u32),
      _ => unreachable!(),
    }

  }

  #[test]
  fn it_parses_extent_allocation() {
    let example_output = b"extent_alloc 4260849 125170297 4618726 131131897";
    match super::extent_alloc(example_output) {
      nom::IResult::Done(_, result) => {
        assert_eq!(result.allocated_extents, 4260849);
        assert_eq!(result.freed_blocks, 131131897);
      },
      _ => unreachable!(),
    }
  }

  #[test]
  fn it_parses_allocation_btree() {
    let example_output = b"abt 29491162 337391304 11257328 11133039";
    match super::abt(example_output) {
      nom::IResult::Done(_, result) => {
        assert_eq!(result.inserts, 11257328);
      },
      _ => unreachable!(),
    }
  }

  #[test]
  fn it_parses_block_mapping() {
    let example_output = b"blk_map 381213360 115456141 10903633 69612322 7448401 507596777 0";
    match super::blk_map(example_output) {
      nom::IResult::Done(_, result) => {
        assert_eq!(result.list_delete, 7448401);
      },
      _ => unreachable!(),
    }
  }

  #[test]
  fn it_parses_block_map_btree() {
    let example_output = b"bmbt 771328 6236258 602114 86646";
    match super::bmbt(example_output) {
      nom::IResult::Done(_, result) => {
        assert_eq!(result.deletes, 86646);
      },
      _ => unreachable!(),
    }
  }

  #[test]
  fn it_parses_example() {
    let example_output = b"extent_alloc 4260849 125170297 4618726 131131897
abt 29491162 337391304 11257328 11133039
blk_map 381213360 115456141 10903633 69612322 7448401 507596777 0
bmbt 771328 6236258 602114 86646
dir 21253907 6921870 6969079 779205554
trans 126946406 38184616 6342392
ig 17754368 2019571 102 15734797 0 15672217 3962470
log 129491915 3992515264 458018 153771989 127040250
push_ail 171473415 0 6896837 3324292 8069877 65884 1289485 0 22535 7337
xstrat 4140059 0
rw 1595677950 1046884251
attr 194724197 0 7 0
icluster 20772185 2488203 13909520
vnodes 62578 15959666 0 0 15897088 15897088 15897088 0
buf 2090581631 1972536890 118044776 225145 9486625 0 0 2000152616 809762
xpc 6908312903680 67735504884757 19760115252482
debug 0";
    let result = super::parse(example_output).unwrap();

    assert_eq!(result.extent_allocation.freed_extents, 4618726);
    assert_eq!(result.allocation_btree.lookups, 29491162);
    assert_eq!(result.block_mapping.unmap, 10903633);
    assert_eq!(result.block_map_btree.inserts, 602114);
  }
}

pub struct XfsStat {
  pub extent_allocation: ExtentAllocation,
  pub allocation_btree: AllocationBTree,
  pub block_mapping: BlockMapping,
  pub block_map_btree: BlockMapBTree
}

pub struct ExtentAllocation {
  // Number of file system extents allocated over all XFS filesystems.
  pub allocated_extents: u32,
  // Number of file system blocks allocated over all XFS filesystems.
  pub allocated_blocks: u32,
  // Number of file system extents freed over all XFS filesystems.
  pub freed_extents: u32,
  // Number of file system blocks freed over all XFS filesystems.
  pub freed_blocks: u32,
}

pub struct AllocationBTree {
  // Number of lookup operations in XFS filesystem allocation btrees.
  pub lookups: u32,
  // Number of compares in XFS filesystem allocation btree lookups.
  pub compares: u32,
  // Number of extent records inserted into XFS filesystem allocation btrees.
  pub inserts: u32,
  // Number of extent records deleted from XFS filesystem allocation btrees.
  pub deletes: u32,
}

pub struct BlockMapping {
  // Number of block map for read operations performed on XFS files.
  pub map_read: u32,
  // Number of block map for write operations performed on XFS files.
  pub map_write: u32,
  // Number of block unmap (delete) operations performed on XFS files.
  pub unmap: u32,
  // Number of extent list insertion operations for XFS files.
  pub list_insert: u32,
  // Number of extent list deletion operations for XFS files.
  pub list_delete: u32,
  // Number of extent list lookup operations for XFS files.
  pub list_lookup: u32,
  // Number of extent list comparisons in XFS extent list lookups.
  pub list_compare: u32,
}

pub struct BlockMapBTree {
  // Number of block map btree lookup operations on XFS files.
  pub lookups: u32,
  // Number of block map btree compare operations in XFS block map lookups.
  pub compares: u32,
  // Number of block map btree records inserted for XFS files.
  pub inserts: u32,
  // Number of block map btree records deleted for XFS files.
  pub deletes: u32,
}

pub fn parse(input: &[u8]) -> Option<XfsStat> {
  match xfs_stat(input) {
    nom::IResult::Done(_, stat) =>{
      Some(stat)
    },
    _ => None
  }
}

named!(xfs_stat <XfsStat>,
  chain!(
    extent_alloc: extent_alloc ~
    newline ~
    abt: abt ~
    newline ~
    blk_map: blk_map ~
    newline ~
    block_map_btree: bmbt,
    || {
      XfsStat {
        extent_allocation: extent_alloc,
        allocation_btree: abt,
        block_mapping: blk_map,
        block_map_btree: block_map_btree,
      }
    }
  )
);

named!(take_u32 <u32>,
  chain!(
    uint_slice: take_while!(is_digit),
    || {
      let int_str = String::from_utf8_lossy(uint_slice);
      u32::from_str(&int_str[..]).unwrap()
    }
  )
);

named!(extent_alloc <ExtentAllocation>,
  chain!(
    tag!("extent_alloc") ~
    space ~
    allocx: take_u32 ~
    space ~
    allocb: take_u32 ~
    space ~
    freex: take_u32 ~
    space ~
    freeb: take_u32,
    || {
      ExtentAllocation {
        allocated_extents: allocx,
        allocated_blocks: allocb,
        freed_extents: freex,
        freed_blocks: freeb,
      }
    }
  )
);

named!(abt <AllocationBTree>,
  chain!(
    tag!("abt") ~
    space ~
    lookups: take_u32 ~
    space ~
    compares: take_u32 ~
    space ~
    inserts: take_u32 ~
    space ~
    deletes: take_u32,
    || {
      AllocationBTree {
        lookups: lookups,
        compares: compares,
        inserts: inserts,
        deletes: deletes,
      }
    }
  )
);

named!(blk_map <BlockMapping>,
  chain!(
    tag!("blk_map") ~
    space ~
    map_read: take_u32 ~
    space ~
    map_write: take_u32 ~
    space ~
    unmap: take_u32 ~
    space ~
    list_insert: take_u32 ~
    space ~
    list_delete: take_u32 ~
    space ~
    list_lookup: take_u32 ~
    space ~
    list_compare: take_u32,
    ||{
      BlockMapping {
        map_read: map_read,
        map_write: map_write,
        unmap: unmap,
        list_insert: list_insert,
        list_delete: list_delete,
        list_lookup: list_lookup,
        list_compare: list_compare,
      }
    }
  )
);

named!(bmbt <BlockMapBTree>,
  chain!(
    tag!("bmbt") ~
    space ~
    lookup: take_u32 ~
    space ~
    compare: take_u32 ~
    space ~
    insrec: take_u32 ~
    space ~
    delrec: take_u32,
    || {
      BlockMapBTree {
        lookups: lookup,
        compares: compare,
        inserts: insrec,
        deletes: delrec,
      }
    }
  )
);<commit_msg>adding structs<commit_after>#[macro_use]
extern crate nom;

use std::str::FromStr;

use self::nom::{is_digit, space, newline};

#[cfg(test)]
mod tests {
    use nom;

    #[test]
    fn it_parses_a_u32() {
        let input = b"12345";
        let result = super::take_u32(input);
        match result {
            nom::IResult::Done(_, f) => assert_eq!(f, 12345u32),
            _ => unreachable!(),
        }

    }

    #[test]
    fn it_parses_extent_allocation() {
        let example_output = b"extent_alloc 4260849 125170297 4618726 131131897";
        match super::extent_alloc(example_output) {
            nom::IResult::Done(_, result) => {
                assert_eq!(result.allocated_extents, 4260849);
                assert_eq!(result.freed_blocks, 131131897);
            }
            _ => unreachable!(),
        }
    }

    #[test]
    fn it_parses_allocation_btree() {
        let example_output = b"abt 29491162 337391304 11257328 11133039";
        match super::abt(example_output) {
            nom::IResult::Done(_, result) => {
                assert_eq!(result.inserts, 11257328);
            }
            _ => unreachable!(),
        }
    }

    #[test]
    fn it_parses_block_mapping() {
        let example_output = b"blk_map 381213360 115456141 10903633 69612322 7448401 507596777 0";
        match super::blk_map(example_output) {
            nom::IResult::Done(_, result) => {
                assert_eq!(result.list_delete, 7448401);
            }
            _ => unreachable!(),
        }
    }

    #[test]
    fn it_parses_block_map_btree() {
        let example_output = b"bmbt 771328 6236258 602114 86646";
        match super::bmbt(example_output) {
            nom::IResult::Done(_, result) => {
                assert_eq!(result.deletes, 86646);
            }
            _ => unreachable!(),
        }
    }

    #[test]
    fn it_parses_example() {
        let example_output = b"extent_alloc 4260849 125170297 4618726 131131897
abt 29491162 337391304 11257328 11133039
blk_map 381213360 115456141 10903633 69612322 7448401 507596777 0
bmbt 771328 6236258 602114 86646
dir 21253907 6921870 6969079 779205554
trans 126946406 38184616 6342392
ig 17754368 2019571 102 15734797 0 15672217 3962470
log 129491915 3992515264 458018 153771989 127040250
push_ail 171473415 0 6896837 3324292 8069877 65884 1289485 0 22535 7337
xstrat 4140059 0
rw 1595677950 1046884251
attr 194724197 0 7 0
icluster 20772185 2488203 13909520
vnodes 62578 15959666 0 0 15897088 15897088 15897088 0
buf 2090581631 1972536890 118044776 225145 9486625 0 0 2000152616 809762
xpc 6908312903680 67735504884757 19760115252482
debug 0";
        let result = super::parse(example_output).unwrap();

        assert_eq!(result.extent_allocation.freed_extents, 4618726);
        assert_eq!(result.allocation_btree.lookups, 29491162);
        assert_eq!(result.block_mapping.unmap, 10903633);
        assert_eq!(result.block_map_btree.inserts, 602114);
    }
}

pub struct XfsStat {
    pub extent_allocation: ExtentAllocation,
    pub allocation_btree: AllocationBTree,
    pub block_mapping: BlockMapping,
    pub block_map_btree: BlockMapBTree,
}

pub struct ExtentAllocation {
    // Number of file system extents allocated over all XFS filesystems.
    pub allocated_extents: u32,
    // Number of file system blocks allocated over all XFS filesystems.
    pub allocated_blocks: u32,
    // Number of file system extents freed over all XFS filesystems.
    pub freed_extents: u32,
    // Number of file system blocks freed over all XFS filesystems.
    pub freed_blocks: u32,
}

pub struct AllocationBTree {
    // Number of lookup operations in XFS filesystem allocation btrees.
    pub lookups: u32,
    // Number of compares in XFS filesystem allocation btree lookups.
    pub compares: u32,
    // Number of extent records inserted into XFS filesystem allocation btrees.
    pub inserts: u32,
    // Number of extent records deleted from XFS filesystem allocation btrees.
    pub deletes: u32,
}

pub struct BlockMapping {
    // Number of block map for read operations performed on XFS files.
    pub map_read: u32,
    // Number of block map for write operations performed on XFS files.
    pub map_write: u32,
    // Number of block unmap (delete) operations performed on XFS files.
    pub unmap: u32,
    // Number of extent list insertion operations for XFS files.
    pub list_insert: u32,
    // Number of extent list deletion operations for XFS files.
    pub list_delete: u32,
    // Number of extent list lookup operations for XFS files.
    pub list_lookup: u32,
    // Number of extent list comparisons in XFS extent list lookups.
    pub list_compare: u32,
}

pub struct BlockMapBTree {
    // Number of block map btree lookup operations on XFS files.
    pub lookups: u32,
    // Number of block map btree compare operations in XFS block map lookups.
    pub compares: u32,
    // Number of block map btree records inserted for XFS files.
    pub inserts: u32,
    // Number of block map btree records deleted for XFS files.
    pub deletes: u32,
}

pub struct DirectoryOperations {
    // This is a count of the number of file name directory lookups in XFS
    // filesystems. It counts only those lookups which miss in the operating
    // system's directory name lookup cache and must search the real directory
    // structure for the name in question. The count is incremented once for each
    // level of a pathname search that results in a directory lookup.
    pub lookups: u32,
    // This is the number of times a new directory entry was created in XFS filesystems. Each time that a new file, directory, link, symbolic link, or special file is created in the directory hierarchy the count is incremented.
    pub creates: u32,
    // This is the number of times an existing directory entry was removed in XFS filesystems. Each time that a file, directory, link, symbolic link, or special file is removed from the directory hierarchy the count is incremented.
    pub removes: u32,
    // This is the number of times the XFS directory getdents operation was performed. The getdents operation is used by programs to read the contents of directories in a file system independent fashion. This count corresponds exactly to the number of times the getdents(2) system call was successfully used on an XFS directory.
    pub get_dents: u32,
}

pub struct Transactions {
    // This is the number of meta-data transactions which waited to be committed to the on-disk log before allowing the process performing the transaction to continue. These transactions are slower and more expensive than asynchronous transactions, because they force the in memory log buffers to be forced to disk more often and they wait for the completion of the log buffer writes. Synchronous transactions include file truncations and all directory updates when the file system is mounted with the 'wsync' option.
    pub waited: u32,
    // This is the number of meta-data transactions which did not wait to be committed to the on-disk log before allowing the process performing the transaction to continue. These transactions are faster and more efficient than synchronous transactions, because they commit their data to the in memory log buffers without forcing those buffers to be written to disk. This allows multiple asynchronous transactions to be committed to disk in a single log buffer write. Most transactions used in XFS file systems are asynchronous.
    pub async: u32,
    // This is the number of meta-data transactions which did not actually change anything. These are transactions which were started for some purpose, but in the end it turned out that no change was necessary.
    pub empty: u32,
}

pub struct InodeOperations {
    // This is the number of times the operating system looked for an XFS inode in the inode cache. Whether the inode was found in the cache or needed to be read in from the disk is not indicated here, but this can be computed from the ig_found and ig_missed counts.
    pub cache_lookups: u32,
    // This is the number of times the operating system looked for an XFS inode in the inode cache and found it. The closer this count is to the ig_attempts count the better the inode cache is performing.
    pub cache_hits: u32,
    // This is the number of times the operating system looked for an XFS inode in the inode cache and saw that it was there but was unable to use the in memory inode because it was being recycled by another process.
    pub cache_recycle: u32,
    // This is the number of times the operating system looked for an XFS inode in the inode cache and the inode was not there. The further this count is from the ig_attempts count the better.
    pub cache_missed: u32,
    // This is the number of times the operating system looked for an XFS inode in the inode cache and found that it was not there but upon attempting to add the inode to the cache found that another process had already inserted it.
    pub cache_dup: u32,
    // This is the number of times the operating system recycled an XFS inode from the inode cache in order to use the memory for that inode for another purpose. Inodes are recycled in order to keep the inode cache from growing without bound. If the reclaim rate is high it may be beneficial to raise the vnode_free_ratio kernel tunable variable to increase the size of the inode cache.
    pub cache_reclaime: u32,
    // This is the number of times the operating system explicitly changed the attributes of an XFS inode. For example, this could be to change the inode's owner, the inode's size, or the inode's timestamps.
    pub inode_attr_changes: u32,
}

pub struct LogOperations {
    // This variable counts the number of log buffer writes going to the physical log partitions of all XFS filesystems. Log data traffic is proportional to the level of meta-data updating. Log buffer writes get generated when they fill up or external syncs occur.
    pub log_writes: u32,
    // This variable counts (in 512-byte units) the information being written to the physical log partitions of all XFS filesystems. Log data traffic is proportional to the level of meta-data updating. The rate with which log data gets written depends on the size of internal log buffers and disk write speed. Therefore, filesystems with very high meta-data updating may need to stripe the log partition or put the log partition on a separate drive.
    pub log_blocks: u32,
    // This variable keeps track of times when a logged transaction can not get any log buffer space. When this occurs, all of the internal log buffers are busy flushing their data to the physical on-disk log.
    pub noiclogs: u32,
    // The number of times the in-core log is forced to disk. It is equivalent to the number of successful calls to the function xfs_log_force().
    pub log_forced: u32,
    // Value exported from the xs_log_force_sleep field of struct xfsstats.
    pub force_sleep: u32,
}

pub struct TailPushingStats {
    // Value from the xs_try_logspace field of struct xfsstats.
    pub logspace: u32,
    // Value from the xs_sleep_logspace field of struct xfsstats.
    pub sleep_logspace: u32,
    // The number of times the tail of the AIL is moved forward. It is equivalent to the number of successful calls to the function xfs_trans_push_ail().
    pub push_ails: u32,
    // Value from xs_push_ail_success field of struct xfsstats.
    pub push_ail_success: u32,
    // Value from xs_push_ail_pushbuf field of struct xfsstats.
    pub push_ail_pushbuf: u32,
    // Value from xs_push_ail_pinned field of struct xfsstats.
    pub push_ail_pinned: u32,
    // Value from xs_push_ail_locked field of struct xfsstats.
    pub push_ail_locked: u32,
    // Value from xs_push_ail_flushing field of struct xfsstats.
    pub push_ail_flushing: u32,
    // Value from xs_push_ail_restarts field of struct xfsstats.
    pub push_ail_restarts: u32,
    // Value from xs_push_ail_flush field of struct xfsstats.
    pub push_ail_flush: u32,
}

pub fn parse(input: &[u8]) -> Option<XfsStat> {
    match xfs_stat(input) {
        nom::IResult::Done(_, stat) => Some(stat),
        _ => None,
    }
}

named!(xfs_stat <XfsStat>,
  chain!(
    extent_alloc: extent_alloc ~
    newline ~
    abt: abt ~
    newline ~
    blk_map: blk_map ~
    newline ~
    block_map_btree: bmbt,
    || {
      XfsStat {
        extent_allocation: extent_alloc,
        allocation_btree: abt,
        block_mapping: blk_map,
        block_map_btree: block_map_btree,
      }
    }
  )
);

named!(take_u32 <u32>,
  chain!(
    uint_slice: take_while!(is_digit),
    || {
      let int_str = String::from_utf8_lossy(uint_slice);
      u32::from_str(&int_str[..]).unwrap()
    }
  )
);

named!(extent_alloc <ExtentAllocation>,
  chain!(
    tag!("extent_alloc") ~
    space ~
    allocx: take_u32 ~
    space ~
    allocb: take_u32 ~
    space ~
    freex: take_u32 ~
    space ~
    freeb: take_u32,
    || {
      ExtentAllocation {
        allocated_extents: allocx,
        allocated_blocks: allocb,
        freed_extents: freex,
        freed_blocks: freeb,
      }
    }
  )
);

named!(abt <AllocationBTree>,
  chain!(
    tag!("abt") ~
    space ~
    lookups: take_u32 ~
    space ~
    compares: take_u32 ~
    space ~
    inserts: take_u32 ~
    space ~
    deletes: take_u32,
    || {
      AllocationBTree {
        lookups: lookups,
        compares: compares,
        inserts: inserts,
        deletes: deletes,
      }
    }
  )
);

named!(blk_map <BlockMapping>,
  chain!(
    tag!("blk_map") ~
    space ~
    map_read: take_u32 ~
    space ~
    map_write: take_u32 ~
    space ~
    unmap: take_u32 ~
    space ~
    list_insert: take_u32 ~
    space ~
    list_delete: take_u32 ~
    space ~
    list_lookup: take_u32 ~
    space ~
    list_compare: take_u32,
    ||{
      BlockMapping {
        map_read: map_read,
        map_write: map_write,
        unmap: unmap,
        list_insert: list_insert,
        list_delete: list_delete,
        list_lookup: list_lookup,
        list_compare: list_compare,
      }
    }
  )
);

named!(bmbt <BlockMapBTree>,
  chain!(
    tag!("bmbt") ~
    space ~
    lookup: take_u32 ~
    space ~
    compare: take_u32 ~
    space ~
    insrec: take_u32 ~
    space ~
    delrec: take_u32,
    || {
      BlockMapBTree {
        lookups: lookup,
        compares: compare,
        inserts: insrec,
        deletes: delrec,
      }
    }
  )
);
<|endoftext|>


<commit_before>#![no_std]
#![feature(asm)]
#![feature(const_fn)]
#![feature(use_extern_macros)]
#![feature(integer_atomics)]
#![feature(lang_items)]

#![allow(unknown_lints)]

#[macro_use]
extern crate log;
extern crate spin;

pub mod vmx;
pub mod runtime;

#[cfg(not(test))]
mod serial_logger;
use serial_logger as logger;

include!(concat!(env!("OUT_DIR"), "/version.rs"));

#[repr(C)]
pub struct PerCoreData {
    task: *const u8,
    vmxon_region: *mut u8,
    vmcs: *mut u8,
    vmxon_region_phys: u64,
    vmcs_phys: u64,
    vmxon_region_size: usize,
    vmcs_region_size: usize,
    loaded_successfully: bool,
}

#[no_mangle]
pub extern "C" fn rustyvisor_load() -> i32 {
    #[cfg(not(test))]
    {
        match logger::init() {
            Ok(()) => {}
            Err(_) => return 1,
        }
    }

    info!("{}", VERSION);

    #[cfg(feature = "runtime_tests")] runtime_tests();

    0

}

#[no_mangle]
pub extern "C" fn rustyvisor_core_load(data: *const PerCoreData) -> i32 {
    if data.is_null() {
        return 1;
    }

    unsafe {
        if vmx::enable(
            (*data).vmxon_region,
            (*data).vmxon_region_phys,
            (*data).vmxon_region_size,
        ) != Ok(())
        {
            return 1;
        }
    }

    0
}

#[no_mangle]
pub extern "C" fn rustyvisor_core_unload() {
    info!("core unload");
    vmx::disable();
}

#[no_mangle]
pub extern "C" fn rustyvisor_unload() {

    info!("Hypervisor unloaded.");

    #[cfg(not(test))]
    {
        let _ = logger::fini();
    }
}

#[cfg(feature = "runtime_tests")]
fn runtime_tests() {
    info!("Executing runtime tests...");
    info!("Runtime tests succeeded");
}
<commit_msg>Set using statement as not test<commit_after>#![no_std]
#![feature(asm)]
#![feature(const_fn)]
#![feature(use_extern_macros)]
#![feature(integer_atomics)]
#![feature(lang_items)]

#![allow(unknown_lints)]

#[macro_use]
extern crate log;
extern crate spin;

pub mod vmx;
pub mod runtime;

#[cfg(not(test))]
mod serial_logger;
#[cfg(not(test))]
use serial_logger as logger;

include!(concat!(env!("OUT_DIR"), "/version.rs"));

#[repr(C)]
pub struct PerCoreData {
    task: *const u8,
    vmxon_region: *mut u8,
    vmcs: *mut u8,
    vmxon_region_phys: u64,
    vmcs_phys: u64,
    vmxon_region_size: usize,
    vmcs_region_size: usize,
    loaded_successfully: bool,
}

#[no_mangle]
pub extern "C" fn rustyvisor_load() -> i32 {
    #[cfg(not(test))]
    {
        match logger::init() {
            Ok(()) => {}
            Err(_) => return 1,
        }
    }

    info!("{}", VERSION);

    #[cfg(feature = "runtime_tests")] runtime_tests();

    0

}

#[no_mangle]
pub extern "C" fn rustyvisor_core_load(data: *const PerCoreData) -> i32 {
    if data.is_null() {
        return 1;
    }

    unsafe {
        if vmx::enable(
            (*data).vmxon_region,
            (*data).vmxon_region_phys,
            (*data).vmxon_region_size,
        ) != Ok(())
        {
            return 1;
        }
    }

    0
}

#[no_mangle]
pub extern "C" fn rustyvisor_core_unload() {
    info!("core unload");
    vmx::disable();
}

#[no_mangle]
pub extern "C" fn rustyvisor_unload() {

    info!("Hypervisor unloaded.");

    #[cfg(not(test))]
    {
        let _ = logger::fini();
    }
}

#[cfg(feature = "runtime_tests")]
fn runtime_tests() {
    info!("Executing runtime tests...");
    info!("Runtime tests succeeded");
}
<|endoftext|>


<commit_before>#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        foo();
    }
}

pub fn foo()
{
    println!("Hello world!");
}<commit_msg>fixed code test<commit_after>#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        ::foo();
    }
}

pub fn foo()
{
    println!("Hello world!");
}<|endoftext|>


<commit_before>#![cfg(feature = "full")]

#[macro_use]
extern crate quote;
extern crate syn;
extern crate synom;
extern crate syntex_pos;
extern crate syntex_syntax;
extern crate walkdir;

use syntex_pos::Span;
use syntex_syntax::ast;
use syntex_syntax::parse::{self, ParseSess, PResult};
use syntex_syntax::codemap::FilePathMapping;
use walkdir::{DirEntry, WalkDir, WalkDirIterator};

use std::fs::File;
use std::io::{self, Read, Write};
use std::panic;
use std::time::Instant;

macro_rules! errorf {
    ($($tt:tt)*) => {
        write!(io::stderr(), $($tt)*).unwrap();
    };
}

fn filter(entry: &DirEntry) -> bool {
    let path = entry.path();
    if path.is_dir() {
        return true; // otherwise walkdir does not visit the files
    }
    if path.extension().map(|e| e != "rs").unwrap_or(true) {
        return false;
    }
    let path_string = path.to_string_lossy();
    let path_string = if cfg!(windows) {
        path_string.replace('\\', "/").into()
    } else {
        path_string
    };
    // TODO assert that parsing fails on the parse-fail cases
    if path_string.starts_with("tests/rust/src/test/parse-fail") ||
       path_string.starts_with("tests/rust/src/test/compile-fail") {
        return false;
    }

    if path_string.starts_with("tests/rust/src/test/ui") {
        let stderr_path = path.with_extension("stderr");
        if stderr_path.exists() {
            // Expected to fail in some way
            return false;
        }
    }

    match path_string.as_ref() {
        // TODO placement syntax
        "tests/rust/src/libcollections/tests/binary_heap.rs" |
        // TODO placement syntax
        "tests/rust/src/libcollections/tests/vec.rs" |
        // TODO placement syntax
        "tests/rust/src/libcollections/tests/vec_deque.rs" |
        // TODO better support for attributes
        "tests/rust/src/librustc_data_structures/blake2b.rs" |
        // TODO placement syntax
        "tests/rust/src/librustc_mir/build/matches/test.rs" |
        // TODO placement syntax
        "tests/rust/src/libstd/collections/hash/map.rs" |
        // TODO better support for attributes
        "tests/rust/src/test/incremental/hashes/enum_defs.rs" |
        // TODO better support for attributes
        "tests/rust/src/test/pretty/stmt_expr_attributes.rs" |
        // not actually a test case
        "tests/rust/src/test/run-pass/auxiliary/macro-include-items-expr.rs" |
        // TODO better support for attributes
        "tests/rust/src/test/run-pass/cfg_stmt_expr.rs" |
        // TODO weird glob import
        "tests/rust/src/test/run-pass/import-glob-crate.rs" |
        // TODO better support for attributes
        "tests/rust/src/test/run-pass/inner-attrs-on-impl.rs" |
        // TODO better support for attributes
        "tests/rust/src/test/run-pass/item-attributes.rs" |
        // TODO precedence issue with binop vs poly trait ref
        "tests/rust/src/test/run-pass/try-macro.rs" => false,
        _ => true,
    }
}

#[test]
fn test_round_trip() {
    {
        let min_stack_value = std::env::var("RUST_MIN_STACK").expect("RUST_MIN_STACK env var should be set since some tests require it.");
        let min_stack_value: usize = min_stack_value.parse().expect("RUST_MIN_STACK env var should be set since some tests require it.");
        assert!(min_stack_value >= 16000000);
    }

    let mut failed = 0;

    let walk = WalkDir::new("tests/rust").sort_by(|a, b| a.cmp(b));
    for entry in walk.into_iter().filter_entry(filter) {
        let entry = entry.unwrap();

        let path = entry.path();
        if path.is_dir() {
            continue;
        }
        errorf!("=== {}: ", path.display());

        let mut file = File::open(path).unwrap();
        let mut content = String::new();
        file.read_to_string(&mut content).unwrap();

        let start = Instant::now();
        let (krate, elapsed) = match content.parse::<syn::Crate>() {
            Ok(krate) => (krate, start.elapsed()),
            Err(msg) => {
                errorf!("syn failed to parse\n{:?}\n", msg);
                failed += 1;
                continue;
            }
        };
        let back = quote!(#krate).to_string();

        let equal = panic::catch_unwind(|| {
            let sess = ParseSess::new(FilePathMapping::empty());
            let before = match syntex_parse(content, &sess) {
                Ok(before) => before,
                Err(mut diagnostic) => {
                    diagnostic.cancel();
                    if diagnostic.message().starts_with("file not found for module") {
                        errorf!("ignore\n");
                    } else {
                        errorf!("ignore - syntex failed to parse original content: {}\n", diagnostic.message());
                    }
                    return true;
                }
            };
            let after = match syntex_parse(back, &sess) {
                Ok(after) => after,
                Err(mut diagnostic) => {
                    errorf!("syntex failed to parse");
                    diagnostic.emit();
                    return false;
                }
            };

            if before == after {
                errorf!("pass in {}ms\n",
                        elapsed.as_secs() * 1000 + elapsed.subsec_nanos() as u64 / 1_000_000);
                true
            } else {
                errorf!("FAIL\nbefore: {}\nafter: {}\n",
                        format!("{:?}", before).replace("\n", ""),
                        format!("{:?}", after).replace("\n", ""));
                false
            }
        });
        match equal {
            Err(_) => errorf!("ignoring syntex panic\n"),
            Ok(true) => {}
            Ok(false) => failed += 1,
        }
    }

    if failed > 0 {
        panic!("{} failures", failed);
    }
}

fn syntex_parse(content: String, sess: &ParseSess) -> PResult<ast::Crate> {
    let name = "test_round_trip".to_string();
    parse::parse_crate_from_source_str(name, content, sess).map(respan_crate)
}

fn respan_crate(krate: ast::Crate) -> ast::Crate {
    use std::rc::Rc;
    use syntex_syntax::ast::{Attribute, Expr, ExprKind, Field, FnDecl, FunctionRetTy, ImplItem,
                             ImplItemKind, ItemKind, Mac, MetaItem, MetaItemKind, MethodSig,
                             NestedMetaItem, NestedMetaItemKind, TraitItem, TraitItemKind, TyParam,
                             Visibility};
    use syntex_syntax::codemap::{self, Spanned};
    use syntex_syntax::fold::{self, Folder};
    use syntex_syntax::parse::token::{Lit, Token};
    use syntex_syntax::ptr::P;
    use syntex_syntax::symbol::Symbol;
    use syntex_syntax::tokenstream::{Delimited, TokenTree};
    use syntex_syntax::util::move_map::MoveMap;
    use syntex_syntax::util::small_vector::SmallVector;

    struct Respanner;

    impl Respanner {
        fn fold_spanned<T>(&mut self, spanned: Spanned<T>) -> Spanned<T> {
            codemap::respan(self.new_span(spanned.span), spanned.node)
        }

        fn fold_lit(&mut self, l: Lit) -> Lit {
            // Give up on comparing literals inside of macros because there are
            // so many equivalent representations of the same literal; they are
            // tested elsewhere
            match l {
                Lit::Byte(_) => Lit::Byte(Symbol::intern("")),
                Lit::Char(_) => Lit::Char(Symbol::intern("")),
                Lit::Integer(_) => Lit::Integer(Symbol::intern("")),
                Lit::Float(_) => Lit::Float(Symbol::intern("")),
                Lit::Str_(_) => Lit::Str_(Symbol::intern("")),
                Lit::ByteStr(_) => Lit::ByteStr(Symbol::intern("")),
                _ => l,
            }
        }
    }

    impl Folder for Respanner {
        fn new_span(&mut self, _: Span) -> Span {
            syntex_pos::DUMMY_SP
        }

        fn fold_item_kind(&mut self, i: ItemKind) -> ItemKind {
            match i {
                ItemKind::Fn(decl, unsafety, constness, abi, generics, body) => {
                    let generics = self.fold_generics(generics);
                    let decl = self.fold_fn_decl(decl);
                    let body = self.fold_block(body);
                    // default fold_item_kind does not fold this span
                    let constness = self.fold_spanned(constness);
                    ItemKind::Fn(decl, unsafety, constness, abi, generics, body)
                }
                _ => fold::noop_fold_item_kind(i, self),
            }
        }

        fn fold_expr(&mut self, e: P<Expr>) -> P<Expr> {
            e.map(|e| {
                let folded = fold::noop_fold_expr(e, self);
                Expr {
                    node: match folded.node {
                        ExprKind::Lit(l) => {
                            // default fold_expr does not fold lits
                            ExprKind::Lit(l.map(|l| self.fold_spanned(l)))
                        }
                        ExprKind::Binary(op, lhs, rhs) => {
                            // default fold_expr does not fold the op span
                            ExprKind::Binary(self.fold_spanned(op),
                                             self.fold_expr(lhs),
                                             self.fold_expr(rhs))
                        }
                        ExprKind::AssignOp(op, lhs, rhs) => {
                            // default fold_expr does not fold the op span
                            ExprKind::AssignOp(self.fold_spanned(op),
                                               self.fold_expr(lhs),
                                               self.fold_expr(rhs))
                        }
                        other => other,
                    },
                    ..folded
                }
            })
        }

        fn fold_ty_param(&mut self, tp: TyParam) -> TyParam {
            TyParam {
                // default fold_ty_param does not fold the span
                span: self.new_span(tp.span),
                ..fold::noop_fold_ty_param(tp, self)
            }
        }

        fn fold_fn_decl(&mut self, decl: P<FnDecl>) -> P<FnDecl> {
            decl.map(|FnDecl { inputs, output, variadic }| {
                FnDecl {
                    inputs: inputs.move_map(|x| self.fold_arg(x)),
                    output: match output {
                        FunctionRetTy::Ty(ty) => FunctionRetTy::Ty(self.fold_ty(ty)),
                        // default fold_fn_decl does not fold this span
                        FunctionRetTy::Default(span) => FunctionRetTy::Default(self.new_span(span)),
                    },
                    variadic: variadic,
                }
            })
        }

        fn fold_field(&mut self, field: Field) -> Field {
            Field {
                ident: codemap::respan(// default fold_field does not fold this span
                                       self.new_span(field.ident.span),
                                       self.fold_ident(field.ident.node)),
                expr: self.fold_expr(field.expr),
                span: self.new_span(field.span),
                is_shorthand: field.is_shorthand,
                attrs: ast::ThinVec::new(),
            }
        }

        fn fold_trait_item(&mut self, i: TraitItem) -> SmallVector<TraitItem> {
            let noop = fold::noop_fold_trait_item(i, self).expect_one("");
            SmallVector::one(TraitItem {
                                 node: match noop.node {
                                     TraitItemKind::Method(sig, body) => {
                        TraitItemKind::Method(MethodSig {
                                                  constness: self.fold_spanned(sig.constness),
                                                  ..sig
                                              },
                                              body)
                    }
                                     node => node,
                                 },
                                 ..noop
                             })
        }

        fn fold_impl_item(&mut self, i: ImplItem) -> SmallVector<ImplItem> {
            let noop = fold::noop_fold_impl_item(i, self).expect_one("");
            SmallVector::one(ImplItem {
                                 node: match noop.node {
                                     ImplItemKind::Method(sig, body) => {
                        ImplItemKind::Method(MethodSig {
                                                 constness: self.fold_spanned(sig.constness),
                                                 ..sig
                                             },
                                             body)
                    }
                                     node => node,
                                 },
                                 ..noop
                             })
        }

        fn fold_attribute(&mut self, mut at: Attribute) -> Option<Attribute> {
            at.id.0 = 0;
            fold::noop_fold_attribute(at, self)
        }

        fn fold_meta_item(&mut self, meta_item: MetaItem) -> MetaItem {
            let MetaItem { name, node, span } = meta_item;
            MetaItem {
                name: name,
                node: match node {
                    MetaItemKind::Word => MetaItemKind::Word,
                    MetaItemKind::List(nested) => {
                        MetaItemKind::List(nested.move_map(|e| self.fold_meta_list_item(e)))
                    }
                    // default fold_meta_item does not fold the value span
                    MetaItemKind::NameValue(lit) => MetaItemKind::NameValue(self.fold_spanned(lit)),
                },
                span: self.new_span(span),
            }
        }

        fn fold_meta_list_item(&mut self, list_item: NestedMetaItem) -> NestedMetaItem {
            Spanned {
                node: match list_item.node {
                    NestedMetaItemKind::MetaItem(mi) => {
                        NestedMetaItemKind::MetaItem(self.fold_meta_item(mi))
                    }
                    // default fold_meta_list_item does not fold the span
                    NestedMetaItemKind::Literal(lit) => {
                        NestedMetaItemKind::Literal(self.fold_spanned(lit))
                    }
                },
                span: self.new_span(list_item.span),
            }
        }

        fn fold_mac(&mut self, mac: Mac) -> Mac {
            fold::noop_fold_mac(mac, self)
        }

        fn fold_tt(&mut self, tt: TokenTree) -> TokenTree {
            match tt {
                TokenTree::Token(span, ref tok) => {
                    TokenTree::Token(self.new_span(span), self.fold_token(tok.clone()))
                }
                TokenTree::Delimited(span, ref delimed) => {
                    TokenTree::Delimited(self.new_span(span),
                                         Delimited {
                                             delim: delimed.delim,
                                             tts: self.fold_tts(delimed.tts.clone().into()).into(),
                                         })
                }
            }
        }

        fn fold_token(&mut self, t: Token) -> Token {
            match t {
                // default fold_token does not fold literals
                Token::Literal(lit, repr) => Token::Literal(self.fold_lit(lit), repr),
                Token::Ident(id) => Token::Ident(self.fold_ident(id)),
                Token::Lifetime(id) => Token::Lifetime(self.fold_ident(id)),
                Token::Interpolated(nt) => {
                    let nt = match Rc::try_unwrap(nt) {
                        Ok(nt) => nt,
                        Err(nt) => (*nt).clone(),
                    };
                    Token::Interpolated(Rc::new(self.fold_interpolated(nt)))
                }
                Token::SubstNt(ident) => Token::SubstNt(self.fold_ident(ident)),
                _ => t,
            }
        }

        fn fold_vis(&mut self, vis: Visibility) -> Visibility {
            match vis {
                Visibility::Crate(span) => Visibility::Crate(self.new_span(span)),
                _ => fold::noop_fold_vis(vis, self),
            }
        }
    }

    Respanner.fold_crate(krate)
}
<commit_msg>Add an environment variable to make debugging test_round_trip easier<commit_after>#![cfg(feature = "full")]

#[macro_use]
extern crate quote;
extern crate syn;
extern crate synom;
extern crate syntex_pos;
extern crate syntex_syntax;
extern crate walkdir;

use syntex_pos::Span;
use syntex_syntax::ast;
use syntex_syntax::parse::{self, ParseSess, PResult};
use syntex_syntax::codemap::FilePathMapping;
use walkdir::{DirEntry, WalkDir, WalkDirIterator};

use std::fs::File;
use std::io::{self, Read, Write};
use std::panic;
use std::time::Instant;

macro_rules! errorf {
    ($($tt:tt)*) => {
        write!(io::stderr(), $($tt)*).unwrap();
    };
}

fn filter(entry: &DirEntry) -> bool {
    let path = entry.path();
    if path.is_dir() {
        return true; // otherwise walkdir does not visit the files
    }
    if path.extension().map(|e| e != "rs").unwrap_or(true) {
        return false;
    }
    let path_string = path.to_string_lossy();
    let path_string = if cfg!(windows) {
        path_string.replace('\\', "/").into()
    } else {
        path_string
    };
    // TODO assert that parsing fails on the parse-fail cases
    if path_string.starts_with("tests/rust/src/test/parse-fail") ||
       path_string.starts_with("tests/rust/src/test/compile-fail") {
        return false;
    }

    if path_string.starts_with("tests/rust/src/test/ui") {
        let stderr_path = path.with_extension("stderr");
        if stderr_path.exists() {
            // Expected to fail in some way
            return false;
        }
    }

    match path_string.as_ref() {
        // TODO placement syntax
        "tests/rust/src/libcollections/tests/binary_heap.rs" |
        // TODO placement syntax
        "tests/rust/src/libcollections/tests/vec.rs" |
        // TODO placement syntax
        "tests/rust/src/libcollections/tests/vec_deque.rs" |
        // TODO better support for attributes
        "tests/rust/src/librustc_data_structures/blake2b.rs" |
        // TODO placement syntax
        "tests/rust/src/librustc_mir/build/matches/test.rs" |
        // TODO placement syntax
        "tests/rust/src/libstd/collections/hash/map.rs" |
        // TODO better support for attributes
        "tests/rust/src/test/incremental/hashes/enum_defs.rs" |
        // TODO better support for attributes
        "tests/rust/src/test/pretty/stmt_expr_attributes.rs" |
        // not actually a test case
        "tests/rust/src/test/run-pass/auxiliary/macro-include-items-expr.rs" |
        // TODO better support for attributes
        "tests/rust/src/test/run-pass/cfg_stmt_expr.rs" |
        // TODO weird glob import
        "tests/rust/src/test/run-pass/import-glob-crate.rs" |
        // TODO better support for attributes
        "tests/rust/src/test/run-pass/inner-attrs-on-impl.rs" |
        // TODO better support for attributes
        "tests/rust/src/test/run-pass/item-attributes.rs" |
        // TODO precedence issue with binop vs poly trait ref
        "tests/rust/src/test/run-pass/try-macro.rs" => false,
        _ => true,
    }
}

/// Abort immediately after this many failures.
fn abort_after() -> u32 {
    if let Ok(s) = std::env::var("ABORT_AFTER_FAILURE") {
        if let Ok(n) = s.parse::<u32>() {
            return n;
        }
    }
    std::u32::MAX
}

#[test]
fn test_round_trip() {
    {
        let min_stack_value = std::env::var("RUST_MIN_STACK").expect("RUST_MIN_STACK env var should be set since some tests require it.");
        let min_stack_value: usize = min_stack_value.parse().expect("RUST_MIN_STACK env var should be set since some tests require it.");
        assert!(min_stack_value >= 16000000);
    }

    let abort_after = abort_after();
    if abort_after == 0 {
        panic!("Skipping all round_trip tests");
    }

    let mut failed = 0;

    let walk = WalkDir::new("tests/rust").sort_by(|a, b| a.cmp(b));
    for entry in walk.into_iter().filter_entry(filter) {
        let entry = entry.unwrap();

        let path = entry.path();
        if path.is_dir() {
            continue;
        }
        errorf!("=== {}: ", path.display());

        let mut file = File::open(path).unwrap();
        let mut content = String::new();
        file.read_to_string(&mut content).unwrap();

        let start = Instant::now();
        let (krate, elapsed) = match content.parse::<syn::Crate>() {
            Ok(krate) => (krate, start.elapsed()),
            Err(msg) => {
                errorf!("syn failed to parse\n{:?}\n", msg);
                failed += 1;
                if failed >= abort_after {
                    panic!("Aborting Immediately due to ABORT_AFTER_FAILURE");
                }
                continue;
            }
        };
        let back = quote!(#krate).to_string();

        let equal = panic::catch_unwind(|| {
            let sess = ParseSess::new(FilePathMapping::empty());
            let before = match syntex_parse(content, &sess) {
                Ok(before) => before,
                Err(mut diagnostic) => {
                    diagnostic.cancel();
                    if diagnostic.message().starts_with("file not found for module") {
                        errorf!("ignore\n");
                    } else {
                        errorf!("ignore - syntex failed to parse original content: {}\n", diagnostic.message());
                    }
                    return true;
                }
            };
            let after = match syntex_parse(back, &sess) {
                Ok(after) => after,
                Err(mut diagnostic) => {
                    errorf!("syntex failed to parse");
                    diagnostic.emit();
                    return false;
                }
            };

            if before == after {
                errorf!("pass in {}ms\n",
                        elapsed.as_secs() * 1000 + elapsed.subsec_nanos() as u64 / 1_000_000);
                true
            } else {
                errorf!("FAIL\nbefore: {}\nafter: {}\n",
                        format!("{:?}", before).replace("\n", ""),
                        format!("{:?}", after).replace("\n", ""));
                false
            }
        });
        match equal {
            Err(_) => errorf!("ignoring syntex panic\n"),
            Ok(true) => {}
            Ok(false) => {
                failed += 1;
                if failed >= abort_after {
                    panic!("Aborting Immediately due to ABORT_AFTER_FAILURE");
                }
            },
        }
    }

    if failed > 0 {
        panic!("{} failures", failed);
    }
}

fn syntex_parse(content: String, sess: &ParseSess) -> PResult<ast::Crate> {
    let name = "test_round_trip".to_string();
    parse::parse_crate_from_source_str(name, content, sess).map(respan_crate)
}

fn respan_crate(krate: ast::Crate) -> ast::Crate {
    use std::rc::Rc;
    use syntex_syntax::ast::{Attribute, Expr, ExprKind, Field, FnDecl, FunctionRetTy, ImplItem,
                             ImplItemKind, ItemKind, Mac, MetaItem, MetaItemKind, MethodSig,
                             NestedMetaItem, NestedMetaItemKind, TraitItem, TraitItemKind, TyParam,
                             Visibility};
    use syntex_syntax::codemap::{self, Spanned};
    use syntex_syntax::fold::{self, Folder};
    use syntex_syntax::parse::token::{Lit, Token};
    use syntex_syntax::ptr::P;
    use syntex_syntax::symbol::Symbol;
    use syntex_syntax::tokenstream::{Delimited, TokenTree};
    use syntex_syntax::util::move_map::MoveMap;
    use syntex_syntax::util::small_vector::SmallVector;

    struct Respanner;

    impl Respanner {
        fn fold_spanned<T>(&mut self, spanned: Spanned<T>) -> Spanned<T> {
            codemap::respan(self.new_span(spanned.span), spanned.node)
        }

        fn fold_lit(&mut self, l: Lit) -> Lit {
            // Give up on comparing literals inside of macros because there are
            // so many equivalent representations of the same literal; they are
            // tested elsewhere
            match l {
                Lit::Byte(_) => Lit::Byte(Symbol::intern("")),
                Lit::Char(_) => Lit::Char(Symbol::intern("")),
                Lit::Integer(_) => Lit::Integer(Symbol::intern("")),
                Lit::Float(_) => Lit::Float(Symbol::intern("")),
                Lit::Str_(_) => Lit::Str_(Symbol::intern("")),
                Lit::ByteStr(_) => Lit::ByteStr(Symbol::intern("")),
                _ => l,
            }
        }
    }

    impl Folder for Respanner {
        fn new_span(&mut self, _: Span) -> Span {
            syntex_pos::DUMMY_SP
        }

        fn fold_item_kind(&mut self, i: ItemKind) -> ItemKind {
            match i {
                ItemKind::Fn(decl, unsafety, constness, abi, generics, body) => {
                    let generics = self.fold_generics(generics);
                    let decl = self.fold_fn_decl(decl);
                    let body = self.fold_block(body);
                    // default fold_item_kind does not fold this span
                    let constness = self.fold_spanned(constness);
                    ItemKind::Fn(decl, unsafety, constness, abi, generics, body)
                }
                _ => fold::noop_fold_item_kind(i, self),
            }
        }

        fn fold_expr(&mut self, e: P<Expr>) -> P<Expr> {
            e.map(|e| {
                let folded = fold::noop_fold_expr(e, self);
                Expr {
                    node: match folded.node {
                        ExprKind::Lit(l) => {
                            // default fold_expr does not fold lits
                            ExprKind::Lit(l.map(|l| self.fold_spanned(l)))
                        }
                        ExprKind::Binary(op, lhs, rhs) => {
                            // default fold_expr does not fold the op span
                            ExprKind::Binary(self.fold_spanned(op),
                                             self.fold_expr(lhs),
                                             self.fold_expr(rhs))
                        }
                        ExprKind::AssignOp(op, lhs, rhs) => {
                            // default fold_expr does not fold the op span
                            ExprKind::AssignOp(self.fold_spanned(op),
                                               self.fold_expr(lhs),
                                               self.fold_expr(rhs))
                        }
                        other => other,
                    },
                    ..folded
                }
            })
        }

        fn fold_ty_param(&mut self, tp: TyParam) -> TyParam {
            TyParam {
                // default fold_ty_param does not fold the span
                span: self.new_span(tp.span),
                ..fold::noop_fold_ty_param(tp, self)
            }
        }

        fn fold_fn_decl(&mut self, decl: P<FnDecl>) -> P<FnDecl> {
            decl.map(|FnDecl { inputs, output, variadic }| {
                FnDecl {
                    inputs: inputs.move_map(|x| self.fold_arg(x)),
                    output: match output {
                        FunctionRetTy::Ty(ty) => FunctionRetTy::Ty(self.fold_ty(ty)),
                        // default fold_fn_decl does not fold this span
                        FunctionRetTy::Default(span) => FunctionRetTy::Default(self.new_span(span)),
                    },
                    variadic: variadic,
                }
            })
        }

        fn fold_field(&mut self, field: Field) -> Field {
            Field {
                ident: codemap::respan(// default fold_field does not fold this span
                                       self.new_span(field.ident.span),
                                       self.fold_ident(field.ident.node)),
                expr: self.fold_expr(field.expr),
                span: self.new_span(field.span),
                is_shorthand: field.is_shorthand,
                attrs: ast::ThinVec::new(),
            }
        }

        fn fold_trait_item(&mut self, i: TraitItem) -> SmallVector<TraitItem> {
            let noop = fold::noop_fold_trait_item(i, self).expect_one("");
            SmallVector::one(TraitItem {
                                 node: match noop.node {
                                     TraitItemKind::Method(sig, body) => {
                        TraitItemKind::Method(MethodSig {
                                                  constness: self.fold_spanned(sig.constness),
                                                  ..sig
                                              },
                                              body)
                    }
                                     node => node,
                                 },
                                 ..noop
                             })
        }

        fn fold_impl_item(&mut self, i: ImplItem) -> SmallVector<ImplItem> {
            let noop = fold::noop_fold_impl_item(i, self).expect_one("");
            SmallVector::one(ImplItem {
                                 node: match noop.node {
                                     ImplItemKind::Method(sig, body) => {
                        ImplItemKind::Method(MethodSig {
                                                 constness: self.fold_spanned(sig.constness),
                                                 ..sig
                                             },
                                             body)
                    }
                                     node => node,
                                 },
                                 ..noop
                             })
        }

        fn fold_attribute(&mut self, mut at: Attribute) -> Option<Attribute> {
            at.id.0 = 0;
            fold::noop_fold_attribute(at, self)
        }

        fn fold_meta_item(&mut self, meta_item: MetaItem) -> MetaItem {
            let MetaItem { name, node, span } = meta_item;
            MetaItem {
                name: name,
                node: match node {
                    MetaItemKind::Word => MetaItemKind::Word,
                    MetaItemKind::List(nested) => {
                        MetaItemKind::List(nested.move_map(|e| self.fold_meta_list_item(e)))
                    }
                    // default fold_meta_item does not fold the value span
                    MetaItemKind::NameValue(lit) => MetaItemKind::NameValue(self.fold_spanned(lit)),
                },
                span: self.new_span(span),
            }
        }

        fn fold_meta_list_item(&mut self, list_item: NestedMetaItem) -> NestedMetaItem {
            Spanned {
                node: match list_item.node {
                    NestedMetaItemKind::MetaItem(mi) => {
                        NestedMetaItemKind::MetaItem(self.fold_meta_item(mi))
                    }
                    // default fold_meta_list_item does not fold the span
                    NestedMetaItemKind::Literal(lit) => {
                        NestedMetaItemKind::Literal(self.fold_spanned(lit))
                    }
                },
                span: self.new_span(list_item.span),
            }
        }

        fn fold_mac(&mut self, mac: Mac) -> Mac {
            fold::noop_fold_mac(mac, self)
        }

        fn fold_tt(&mut self, tt: TokenTree) -> TokenTree {
            match tt {
                TokenTree::Token(span, ref tok) => {
                    TokenTree::Token(self.new_span(span), self.fold_token(tok.clone()))
                }
                TokenTree::Delimited(span, ref delimed) => {
                    TokenTree::Delimited(self.new_span(span),
                                         Delimited {
                                             delim: delimed.delim,
                                             tts: self.fold_tts(delimed.tts.clone().into()).into(),
                                         })
                }
            }
        }

        fn fold_token(&mut self, t: Token) -> Token {
            match t {
                // default fold_token does not fold literals
                Token::Literal(lit, repr) => Token::Literal(self.fold_lit(lit), repr),
                Token::Ident(id) => Token::Ident(self.fold_ident(id)),
                Token::Lifetime(id) => Token::Lifetime(self.fold_ident(id)),
                Token::Interpolated(nt) => {
                    let nt = match Rc::try_unwrap(nt) {
                        Ok(nt) => nt,
                        Err(nt) => (*nt).clone(),
                    };
                    Token::Interpolated(Rc::new(self.fold_interpolated(nt)))
                }
                Token::SubstNt(ident) => Token::SubstNt(self.fold_ident(ident)),
                _ => t,
            }
        }

        fn fold_vis(&mut self, vis: Visibility) -> Visibility {
            match vis {
                Visibility::Crate(span) => Visibility::Crate(self.new_span(span)),
                _ => fold::noop_fold_vis(vis, self),
            }
        }
    }

    Respanner.fold_crate(krate)
}
<|endoftext|>


<commit_before>pub mod atkin {
    extern crate std;

    struct Squares {
        count: u64,
        max: u64,
    }

    impl Squares {
        pub fn new(max: u64) -> Squares {
            Squares { count: 0, max: max }
        }
    }

    impl Iterator for Squares {
        type Item = u64;
        fn next(&mut self) -> Option<Self::Item> {
            self.count += 1;
            let square = self.count*self.count;
            if square > self.max {
                None
            } else {
                Some(self.count*self.count)
            }
        }
    }

    #[derive(Copy)]
    #[derive(Eq)]
    struct TestInteger {
        value: u64,
        is_prime: bool
    }

    impl Clone for TestInteger {
        fn clone(&self) -> TestInteger { *self }
    }

    impl Ord for TestInteger {
        fn cmp(&self, other: &TestInteger) -> std::cmp::Ordering {
            self.value.cmp(&other.value)
        }
    }

    impl PartialOrd for TestInteger {
        fn partial_cmp(&self, other: &TestInteger) -> std::option::Option<std::cmp::Ordering> {
            Some(self.cmp(other))
        }
    }

    impl PartialEq for TestInteger {
        fn eq(&self, other: &TestInteger) -> bool {
            (self.value == other.value) && (self.is_prime == other.is_prime)
        }
    }

    impl TestInteger {
        pub fn is_prime(&self) -> bool {
            self.is_prime
        }

        pub fn value(&self) -> u64 {
            self.value
        }

        pub fn set_prime(&mut self, prime: bool) -> bool {
            self.is_prime = prime;
            self.is_prime
        }

        pub fn flip(&mut self) -> bool {
            self.is_prime ^= true;
            self.is_prime
        }
    }

    pub struct SieveOfAtkin {
        results: Vec<u64>,
        tests: Vec<TestInteger>,
    }

    enum AtkinCases {
        C1,
        C2,
        C3,
        C4,
    }

    impl SieveOfAtkin {
        pub fn new(limit: u64) -> SieveOfAtkin {
            let res = vec![2,3,5];
            let mut tests: Vec<TestInteger> = Vec::new();
            if limit < 2 {
                panic!("The limit for the sieve must be above 2. {} was set as limit.", limit);
            } else {

                for i in 2..limit {
                    tests.push(TestInteger{ value: i, is_prime: false });
                }
            }
            SieveOfAtkin { results: res, tests: tests }
        }

        // returns a copy so we don't need to worry about our vector being mutated
        pub fn get_results(&self) -> Vec<u64> {
            self.results.clone()
        }

        fn process_case(&mut self, n : u64, index : usize, case: AtkinCases) {
            //Case 1: flip for each solution to 4x^2 + y^2 = n
            //Case 2: flip for each solution to 3x^2 + y^2 = n
            //Case 3: flip for each solution to 3x^2 - y^2 = n where x > y
            //Case 4: do nothing

            let (co_x,co_y): (u64, u64) = match case {
                AtkinCases::C1  => (4,1),
                AtkinCases::C2  => (3,1),
                AtkinCases::C3  => (3,1),
                _               => { return; },
            };

            let expression: Box<Fn(u64, u64) -> u64> = match case {
                AtkinCases::C3  => Box::new( |x, y| { if x > y { co_x*x - co_y*y } else { 0 } } ),
                _               => Box::new( |x, y| { co_x*x + co_y*y } ),
            };

            for i in Squares::new(n) {
                for j in Squares::new(n) {
                    if expression(i, j) == n {
                        self.tests.get_mut(index)
                            .expect("Index passed in process is invalid. This shouldn't happen.")
                            .flip();
                    }
                }
            }
        }

        pub fn run(&mut self) {
            // process test integers for different cases
            for i in 0..self.tests.len()-1 {
                let val = self.tests.get(i)
                    .expect("Index passed in process is invalid. This shouldn't happen.")
                    .clone();
                let case: AtkinCases = match val.value() % 60 {
                    1  | 13 | 17 | 29 | 37 | 41 | 49 | 53   => AtkinCases::C1,
                    7  | 19 | 31 | 43                       => AtkinCases::C2,
                    11 | 23 | 47 | 59                       => AtkinCases::C3,
                    _                                       => AtkinCases::C4,
                };
                self.process_case(val.value(), i, case);
            }

            // start sieving
            while !self.tests.is_empty() {
                let first = self.tests.first()
                    .expect("Attempted to get item from tests vector while it was empty.")
                    .clone();
                if first.is_prime() {
                    self.results.push(first.value());
                    let square = first.value() * first.value();
                    let naturals = std::ops::RangeFrom{ start: 1 };
                    for i in naturals {
                        let n_square = i*square;
                        if n_square > self.tests.last()
                            .expect("Attempted to get item from tests vector while it was empty.")
                            .value() {
                            break;
                        }

                        match self.tests.binary_search(&TestInteger{ value: n_square, is_prime: true }) {
                            Ok(index)   => {
                                self.tests.get_mut(index)
                                        .expect("Attempted to get known index from tests vector. This shouldn't happen.")
                                        .set_prime(false);
                            },
                            Err(_)      => (),
                        }
                    }
                }
                self.tests.remove(0);
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use atkin::*;
    #[test]
    fn atkin_test() {
        let primes_to_50 = [2u64, 3u64, 5u64, 7u64, 11u64, 13u64, 17u64, 19u64, 23u64, 29u64, 31u64, 37u64, 41u64, 43u64, 47u64];
        let mut sieve = SieveOfAtkin::new(50);

        sieve.run();
        assert_eq!(sieve.get_results(), primes_to_50);
    }

    #[test]
    fn atkin_output() {
        let mut sieve = SieveOfAtkin::new(10000);
        sieve.run();
        let results = sieve.get_results();
        for prime in results.iter() {
           assert!(is_n_prime(*prime), "Failed with {}", prime);
        }
    }

    fn is_n_prime(n: u64) -> bool {
        let mut prime: bool = true;
        if n > 2 {
            for i in 2..n/2 {
                if n % i == 0 {
                    prime = false;
                    break;
                }
            }
        }
        prime
    }
}

<commit_msg>fixed library file<commit_after>pub mod atkin {
    extern crate std;
    use std::thread;

    struct Squares {
        count: u64,
        max: u64,
    }

    impl Squares {
        pub fn new(max: u64) -> Squares {
            Squares { count: 0, max: max }
        }
    }

    impl Iterator for Squares {
        type Item = u64;
        fn next(&mut self) -> Option<Self::Item> {
            self.count += 1;
            let square = self.count*self.count;
            if square > self.max {
                None
            } else {
                Some(self.count*self.count)
            }
        }
    }

    #[derive(Copy)]
    #[derive(Eq)]
    struct TestInteger {
        value: u64,
        is_prime: bool
    }

    impl Clone for TestInteger {
        fn clone(&self) -> TestInteger { *self }
    }

    impl Ord for TestInteger {
        fn cmp(&self, other: &TestInteger) -> std::cmp::Ordering {
            self.value.cmp(&other.value)
        }
    }

    impl PartialOrd for TestInteger {
        fn partial_cmp(&self, other: &TestInteger) -> std::option::Option<std::cmp::Ordering> {
            Some(self.cmp(other))
        }
    }

    impl PartialEq for TestInteger {
        fn eq(&self, other: &TestInteger) -> bool {
            (self.value == other.value) && (self.is_prime == other.is_prime)
        }
    }

    impl TestInteger {
        pub fn is_prime(&self) -> bool {
            self.is_prime
        }

        pub fn value(&self) -> u64 {
            self.value
        }

        pub fn set_prime(&mut self, prime: bool) -> bool {
            self.is_prime = prime;
            self.is_prime
        }

        pub fn flip(&mut self) -> bool {
            self.is_prime ^= true;
            self.is_prime
        }
    }

    pub struct SieveOfAtkin {
        results: Vec<u64>,
        tests: Vec<TestInteger>,
    }

    enum AtkinCases {
        C1,
        C2,
        C3,
        C4,
    }

    impl SieveOfAtkin {
        pub fn new(limit: u64) -> SieveOfAtkin {
            let res = vec![2,3,5];
            let mut tests: Vec<TestInteger> = Vec::new();
            if limit < 2 {
                panic!("The limit for the sieve must be above 2. {} was set as limit.", limit);
            } else {

                for i in 2..limit {
                    tests.push(TestInteger{ value: i, is_prime: false });
                }
            }
            SieveOfAtkin { results: res, tests: tests }
        }

        // returns a copy so we don't need to worry about our vector being mutated
        pub fn get_results(&self) -> Vec<u64> {
            self.results.clone()
        }

        fn process_case(&mut self, n : u64, index : usize, case: AtkinCases) {
            //Case 1: flip for each solution to 4x^2 + y^2 = n
            //Case 2: flip for each solution to 3x^2 + y^2 = n
            //Case 3: flip for each solution to 3x^2 - y^2 = n where x > y
            //Case 4: do nothing

            let (co_x,co_y): (u64, u64) = match case {
                AtkinCases::C1  => (4,1),
                AtkinCases::C2  => (3,1),
                AtkinCases::C3  => (3,1),
                _               => { return; },
            };

            let expression: Box<Fn(u64, u64) -> u64> = match case {
                AtkinCases::C3  => Box::new( |x, y| { if x > y { co_x*x - co_y*y } else { 0 } } ),
                _               => Box::new( |x, y| { co_x*x + co_y*y } ),
            };

            for i in Squares::new(n) {
                for j in Squares::new(n) {
                    if expression(i, j) == n {
                        self.tests.get_mut(index)
                            .expect("Index passed in process is invalid. This shouldn't happen.")
                            .flip();
                    }
                }
            }
        }

        pub fn run(&mut self) {
            // process test integers for different cases
            for i in 0..self.tests.len()-1 {
                let val = self.tests.get(i)
                    .expect("Index passed in process is invalid. This shouldn't happen.")
                    .clone();
                let case: AtkinCases = match val.value() % 60 {
                    1  | 13 | 17 | 29 | 37 | 41 | 49 | 53   => AtkinCases::C1,
                    7  | 19 | 31 | 43                       => AtkinCases::C2,
                    11 | 23 | 47 | 59                       => AtkinCases::C3,
                    _                                       => AtkinCases::C4,
                };
                self.process_case(val.value(), i, case);
            }

            // start sieving
            while !self.tests.is_empty() {
                let first = self.tests.first()
                    .expect("Attempted to get item from tests vector while it was empty.")
                    .clone();
                if first.is_prime() {
                    self.results.push(first.value());
                    let square = first.value() * first.value();
                    let naturals = std::ops::RangeFrom{ start: 1 };
                    for i in naturals {
                        let n_square = i*square;
                        if n_square > self.tests.last()
                            .expect("Attempted to get item from tests vector while it was empty.")
                            .value() {
                            break;
                        }

                        match self.tests.binary_search(&TestInteger{ value: n_square, is_prime: true }) {
                            Ok(index)   => {
                                self.tests.get_mut(index)
                                        .expect("Attempted to get known index from tests vector. This shouldn't happen.")
                                        .set_prime(false);
                            },
                            Err(_)      => (),
                        }
                    }
                }
                self.tests.remove(0);
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use atkin::*;
    #[test]
    fn atkin_test() {
        let primes_to_50 = [2u64, 3u64, 5u64, 7u64, 11u64, 13u64, 17u64, 19u64, 23u64, 29u64, 31u64, 37u64, 41u64, 43u64, 47u64];
        let mut sieve = SieveOfAtkin::new(50);

        sieve.run();
        assert_eq!(sieve.get_results(), primes_to_50);
    }

    #[test]
    fn atkin_output() {
        let mut sieve = SieveOfAtkin::new(10000);
        sieve.run();
        let results = sieve.get_results();
        for prime in results.iter() {
           assert!(is_n_prime(*prime), "Failed with {}", prime);
        }
    }

    fn is_n_prime(n: u64) -> bool {
        let mut prime: bool = true;
        if n > 2 {
            for i in 2..n/2 {
                if n % i == 0 {
                    prime = false;
                    break;
                }
            }
        }
        prime
    }
}

<|endoftext|>


<commit_before>//! Mutex and RwLock types that do not poison themselves.
//!
//! These types expose identical APIs to the standard library `Mutex` and
//! `RwLock` except that they do not return `PoisonError`s.
#![doc(html_root_url="https://sfackler.github.io/rust-antidote/doc/v0.1.0")]
#![warn(missing_docs)]

use std::error::Error;
use std::fmt;
use std::ops::{Deref, DerefMut};
use std::sync;

/// Like `std::sync::Mutex` except that it does not poison itself.
pub struct Mutex<T: ?Sized>(sync::Mutex<T>);

impl<T: ?Sized + fmt::Debug> fmt::Debug for Mutex<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl<T> Mutex<T> {
    /// Like `std::sync::Mutex::new`.
    #[inline]
    pub fn new(t: T) -> Mutex<T> {
        Mutex(sync::Mutex::new(t))
    }

    /// Like `std::sync::Mutex::into_inner`.
    #[inline]
    pub fn into_inner(self) -> T {
        self.0.into_inner().unwrap_or_else(|e| e.into_inner())
    }
}

impl<T: ?Sized> Mutex<T> {
    /// Like `std::sync::Mutex::lock`.
    #[inline]
    pub fn lock<'a>(&'a self) -> MutexGuard<'a, T> {
        MutexGuard(self.0.lock().unwrap_or_else(|e| e.into_inner()))
    }

    /// Like `std::sync::Mutex::try_lock`.
    #[inline]
    pub fn try_lock<'a>(&'a self) -> TryLockResult<MutexGuard<'a, T>> {
        match self.0.try_lock() {
            Ok(t) => Ok(MutexGuard(t)),
            Err(sync::TryLockError::Poisoned(e)) => Ok(MutexGuard(e.into_inner())),
            Err(sync::TryLockError::WouldBlock) => Err(TryLockError(())),
        }
    }

    /// Like `std::sync::Mutex::get_mut`.
    #[inline]
    pub fn get_mut(&mut self) -> &mut T {
        self.0.get_mut().unwrap_or_else(|e| e.into_inner())
    }
}

/// Like `std::sync::MutexGuard`.
#[must_use]
pub struct MutexGuard<'a, T: ?Sized + 'a>(sync::MutexGuard<'a, T>);

impl<'a, T: ?Sized> Deref for MutexGuard<'a, T> {
    type Target = T;

    #[inline]
    fn deref(&self) -> &T {
        self.0.deref()
    }
}

impl<'a, T: ?Sized> DerefMut for MutexGuard<'a, T> {
    #[inline]
    fn deref_mut(&mut self) -> &mut T {
        self.0.deref_mut()
    }
}

/// Like `std::sync::TryLockResult`.
pub type TryLockResult<T> = Result<T, TryLockError>;

/// Like `std::sync::TryLockError`.
#[derive(Debug)]
pub struct TryLockError(());

impl fmt::Display for TryLockError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.write_str(self.description())
    }
}

impl Error for TryLockError {
    fn description(&self) -> &str {
        "lock call failed because the operation would block"
    }
}

/// Like `std::sync::RwLock` except that it does not poison itself.
pub struct RwLock<T: ?Sized>(sync::RwLock<T>);

impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLock<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl<T> RwLock<T> {
    /// Like `std::sync::RwLock::new`.
    #[inline]
    pub fn new(t: T) -> RwLock<T> {
        RwLock(sync::RwLock::new(t))
    }

    /// Like `std::sync::RwLock::into_inner`.
    #[inline]
    pub fn into_inner(self) -> T where T: Sized {
        self.0.into_inner().unwrap_or_else(|e| e.into_inner())
    }
}

impl<T: ?Sized> RwLock<T> {
    /// Like `std::sync::RwLock::read`.
    #[inline]
    pub fn read<'a>(&'a self) -> RwLockReadGuard<'a, T> {
        RwLockReadGuard(self.0.read().unwrap_or_else(|e| e.into_inner()))
    }

    /// Like `std::sync::RwLock::try_read`.
    #[inline]
    pub fn try_read<'a>(&'a self) -> TryLockResult<RwLockReadGuard<'a, T>> {
        match self.0.try_read() {
            Ok(t) => Ok(RwLockReadGuard(t)),
            Err(sync::TryLockError::Poisoned(e)) => Ok(RwLockReadGuard(e.into_inner())),
            Err(sync::TryLockError::WouldBlock) => Err(TryLockError(())),
        }
    }

    /// Like `std::sync::RwLock::write`.
    #[inline]
    pub fn write<'a>(&'a self) -> RwLockWriteGuard<'a, T> {
        RwLockWriteGuard(self.0.write().unwrap_or_else(|e| e.into_inner()))
    }

    /// Like `std::sync::RwLock::try_write`.
    #[inline]
    pub fn try_write<'a>(&'a self) -> TryLockResult<RwLockWriteGuard<'a, T>> {
        match self.0.try_write() {
            Ok(t) => Ok(RwLockWriteGuard(t)),
            Err(sync::TryLockError::Poisoned(e)) => Ok(RwLockWriteGuard(e.into_inner())),
            Err(sync::TryLockError::WouldBlock) => Err(TryLockError(())),
        }
    }

    /// Like `std::sync::RwLock::get_mut`.
    #[inline]
    pub fn get_mut(&mut self) -> &mut T {
        self.0.get_mut().unwrap_or_else(|e| e.into_inner())
    }
}

/// Like `std::sync::RwLockReadGuard`.
#[must_use]
pub struct RwLockReadGuard<'a, T: ?Sized + 'a>(sync::RwLockReadGuard<'a, T>);

impl<'a, T: ?Sized> Deref for RwLockReadGuard<'a, T> {
    type Target = T;

    #[inline]
    fn deref(&self) -> &T {
        self.0.deref()
    }
}

/// Like `std::sync::RwLockWriteGuard`.
#[must_use]
pub struct RwLockWriteGuard<'a, T: ?Sized + 'a>(sync::RwLockWriteGuard<'a, T>);

impl<'a, T: ?Sized> Deref for RwLockWriteGuard<'a, T> {
    type Target = T;

    #[inline]
    fn deref(&self) -> &T {
        self.0.deref()
    }
}

impl<'a, T: ?Sized> DerefMut for RwLockWriteGuard<'a, T> {
    #[inline]
    fn deref_mut(&mut self) -> &mut T {
        self.0.deref_mut()
    }
}
<commit_msg>Add Condvar<commit_after>//! Mutex and RwLock types that do not poison themselves.
//!
//! These types expose identical APIs to the standard library `Mutex` and
//! `RwLock` except that they do not return `PoisonError`s.
#![doc(html_root_url="https://sfackler.github.io/rust-antidote/doc/v0.1.0")]
#![warn(missing_docs)]

use std::error::Error;
use std::fmt;
use std::ops::{Deref, DerefMut};
use std::sync;
use std::time::Duration;

#[doc(inline)]
pub use std::sync::WaitTimeoutResult;

/// Like `std::sync::Mutex` except that it does not poison itself.
pub struct Mutex<T: ?Sized>(sync::Mutex<T>);

impl<T: ?Sized + fmt::Debug> fmt::Debug for Mutex<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl<T> Mutex<T> {
    /// Like `std::sync::Mutex::new`.
    #[inline]
    pub fn new(t: T) -> Mutex<T> {
        Mutex(sync::Mutex::new(t))
    }

    /// Like `std::sync::Mutex::into_inner`.
    #[inline]
    pub fn into_inner(self) -> T {
        self.0.into_inner().unwrap_or_else(|e| e.into_inner())
    }
}

impl<T: ?Sized> Mutex<T> {
    /// Like `std::sync::Mutex::lock`.
    #[inline]
    pub fn lock<'a>(&'a self) -> MutexGuard<'a, T> {
        MutexGuard(self.0.lock().unwrap_or_else(|e| e.into_inner()))
    }

    /// Like `std::sync::Mutex::try_lock`.
    #[inline]
    pub fn try_lock<'a>(&'a self) -> TryLockResult<MutexGuard<'a, T>> {
        match self.0.try_lock() {
            Ok(t) => Ok(MutexGuard(t)),
            Err(sync::TryLockError::Poisoned(e)) => Ok(MutexGuard(e.into_inner())),
            Err(sync::TryLockError::WouldBlock) => Err(TryLockError(())),
        }
    }

    /// Like `std::sync::Mutex::get_mut`.
    #[inline]
    pub fn get_mut(&mut self) -> &mut T {
        self.0.get_mut().unwrap_or_else(|e| e.into_inner())
    }
}

/// Like `std::sync::MutexGuard`.
#[must_use]
pub struct MutexGuard<'a, T: ?Sized + 'a>(sync::MutexGuard<'a, T>);

impl<'a, T: ?Sized> Deref for MutexGuard<'a, T> {
    type Target = T;

    #[inline]
    fn deref(&self) -> &T {
        self.0.deref()
    }
}

impl<'a, T: ?Sized> DerefMut for MutexGuard<'a, T> {
    #[inline]
    fn deref_mut(&mut self) -> &mut T {
        self.0.deref_mut()
    }
}

/// Like `std::sync::Condvar`.
pub struct Condvar(sync::Condvar);

impl Condvar {
    /// Like `std::sync::Condvar::new`.
    #[inline]
    pub fn new() -> Condvar {
        Condvar(sync::Condvar::new())
    }

    /// Like `std::sync::Condvar::wait`.
    #[inline]
    pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>) -> MutexGuard<'a, T> {
        MutexGuard(self.0.wait(guard.0).unwrap_or_else(|e| e.into_inner()))
    }

    /// Like `std::sync::Condvar::wait_timeout`.
    #[inline]
    pub fn wait_timeout<'a, T>(&self,
                               guard: MutexGuard<'a, T>,
                               dur: Duration)
                               -> (MutexGuard<'a, T>, WaitTimeoutResult) {
        let (guard, result) = self.0.wait_timeout(guard.0, dur).unwrap_or_else(|e| e.into_inner());
        (MutexGuard(guard), result)
    }

    /// Like `std::sync::Condvar::notify_one`.
    #[inline]
    pub fn notify_one(&self) {
        self.0.notify_one()
    }

    /// Like `std::sync::Condvar::notify_all`.
    #[inline]
    pub fn notify_all(&self) {
        self.0.notify_all()
    }
}

/// Like `std::sync::TryLockResult`.
pub type TryLockResult<T> = Result<T, TryLockError>;

/// Like `std::sync::TryLockError`.
#[derive(Debug)]
pub struct TryLockError(());

impl fmt::Display for TryLockError {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.write_str(self.description())
    }
}

impl Error for TryLockError {
    fn description(&self) -> &str {
        "lock call failed because the operation would block"
    }
}

/// Like `std::sync::RwLock` except that it does not poison itself.
pub struct RwLock<T: ?Sized>(sync::RwLock<T>);

impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLock<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl<T> RwLock<T> {
    /// Like `std::sync::RwLock::new`.
    #[inline]
    pub fn new(t: T) -> RwLock<T> {
        RwLock(sync::RwLock::new(t))
    }

    /// Like `std::sync::RwLock::into_inner`.
    #[inline]
    pub fn into_inner(self) -> T where T: Sized {
        self.0.into_inner().unwrap_or_else(|e| e.into_inner())
    }
}

impl<T: ?Sized> RwLock<T> {
    /// Like `std::sync::RwLock::read`.
    #[inline]
    pub fn read<'a>(&'a self) -> RwLockReadGuard<'a, T> {
        RwLockReadGuard(self.0.read().unwrap_or_else(|e| e.into_inner()))
    }

    /// Like `std::sync::RwLock::try_read`.
    #[inline]
    pub fn try_read<'a>(&'a self) -> TryLockResult<RwLockReadGuard<'a, T>> {
        match self.0.try_read() {
            Ok(t) => Ok(RwLockReadGuard(t)),
            Err(sync::TryLockError::Poisoned(e)) => Ok(RwLockReadGuard(e.into_inner())),
            Err(sync::TryLockError::WouldBlock) => Err(TryLockError(())),
        }
    }

    /// Like `std::sync::RwLock::write`.
    #[inline]
    pub fn write<'a>(&'a self) -> RwLockWriteGuard<'a, T> {
        RwLockWriteGuard(self.0.write().unwrap_or_else(|e| e.into_inner()))
    }

    /// Like `std::sync::RwLock::try_write`.
    #[inline]
    pub fn try_write<'a>(&'a self) -> TryLockResult<RwLockWriteGuard<'a, T>> {
        match self.0.try_write() {
            Ok(t) => Ok(RwLockWriteGuard(t)),
            Err(sync::TryLockError::Poisoned(e)) => Ok(RwLockWriteGuard(e.into_inner())),
            Err(sync::TryLockError::WouldBlock) => Err(TryLockError(())),
        }
    }

    /// Like `std::sync::RwLock::get_mut`.
    #[inline]
    pub fn get_mut(&mut self) -> &mut T {
        self.0.get_mut().unwrap_or_else(|e| e.into_inner())
    }
}

/// Like `std::sync::RwLockReadGuard`.
#[must_use]
pub struct RwLockReadGuard<'a, T: ?Sized + 'a>(sync::RwLockReadGuard<'a, T>);

impl<'a, T: ?Sized> Deref for RwLockReadGuard<'a, T> {
    type Target = T;

    #[inline]
    fn deref(&self) -> &T {
        self.0.deref()
    }
}

/// Like `std::sync::RwLockWriteGuard`.
#[must_use]
pub struct RwLockWriteGuard<'a, T: ?Sized + 'a>(sync::RwLockWriteGuard<'a, T>);

impl<'a, T: ?Sized> Deref for RwLockWriteGuard<'a, T> {
    type Target = T;

    #[inline]
    fn deref(&self) -> &T {
        self.0.deref()
    }
}

impl<'a, T: ?Sized> DerefMut for RwLockWriteGuard<'a, T> {
    #[inline]
    fn deref_mut(&mut self) -> &mut T {
        self.0.deref_mut()
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! # Cap'n Proto Schema Compiler Plugin Library
//!
//! This library allows you to do Cap'n Proto code generation within a Cargo build.
//!
//! In your Cargo.toml:
//!
//! ```ignore
//!   [build-dependencies]
//!   capnpc = "0.1.5"
//! ```
//!
//! In your build.rs, call
//!
//! ```ignore
//! ::capnpc::compile(Path::new("schema"),
//!                   &[Path::new("schema/foo.capnp"),
//!                     Path::new("schema/bar.capnp")]);
//! ```
//!
//! This will be equivalent to executing the shell command
//!
//! ```ignore
//!   capnp compile -orust:$OUT_DIR --src-prefix=schema schema/foo.capnp schema/bar.capnp
//! ```
//!

#![crate_name="capnpc"]
#![crate_type = "lib"]
#![feature(box_syntax, core)]

extern crate capnp;

pub mod schema_capnp;
pub mod codegen;
pub mod schema;

pub fn compile(prefix : &::std::path::Path, files : &[&::std::path::Path]) -> ::capnp::Result<()> {
    let mut command = ::std::process::Command::new("capnp");
    command.arg("compile").arg("-o/bin/cat")
           .arg(&format!("--src-prefix={}", prefix.display()));

    for file in files.iter() {
        command.arg(&format!("{}", file.display()));
    }

    command.stdout(::std::process::Stdio::piped());
    command.stderr(::std::process::Stdio::inherit());

    let mut p =  try!(command.spawn());
    let child_stdout = ::capnp::io::ReadInputStream::new(p.stdout.take().unwrap());
    try!(::codegen::main(child_stdout,
                         ::std::path::Path::new(&::std::env::var("OUT_DIR").unwrap())));
    try!(p.wait());
    return Ok(());
}

<commit_msg>Use 'which' to detect location of 'cat'.<commit_after>// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! # Cap'n Proto Schema Compiler Plugin Library
//!
//! This library allows you to do Cap'n Proto code generation within a Cargo build.
//!
//! In your Cargo.toml:
//!
//! ```ignore
//!   [build-dependencies]
//!   capnpc = "0.1.5"
//! ```
//!
//! In your build.rs, call
//!
//! ```ignore
//! ::capnpc::compile(Path::new("schema"),
//!                   &[Path::new("schema/foo.capnp"),
//!                     Path::new("schema/bar.capnp")]);
//! ```
//!
//! This will be equivalent to executing the shell command
//!
//! ```ignore
//!   capnp compile -orust:$OUT_DIR --src-prefix=schema schema/foo.capnp schema/bar.capnp
//! ```
//!

#![crate_name="capnpc"]
#![crate_type = "lib"]
#![feature(box_syntax, core)]

extern crate capnp;

pub mod schema_capnp;
pub mod codegen;
pub mod schema;

pub fn compile(prefix : &::std::path::Path, files : &[&::std::path::Path]) -> ::capnp::Result<()> {

    // Find the absolute path of `cat`.
    //
    // TODO: Once a resleased version of `capnp compile` includes the '-o -' option, switch to
    //       using that. (see https://github.com/sandstorm-io/capnproto/pull/190)
    let which_output = ::std::process::Command::new("which").arg("cat").output().unwrap().stdout;

    let mut command = ::std::process::Command::new("capnp");
    command.arg("compile").arg("-o").arg(&::std::str::from_utf8(&which_output).unwrap().trim())
           .arg(&format!("--src-prefix={}", prefix.display()));

    for file in files.iter() {
        command.arg(&format!("{}", file.display()));
    }

    command.stdout(::std::process::Stdio::piped());
    command.stderr(::std::process::Stdio::inherit());

    let mut p =  try!(command.spawn());
    let child_stdout = ::capnp::io::ReadInputStream::new(p.stdout.take().unwrap());
    try!(::codegen::main(child_stdout,
                         ::std::path::Path::new(&::std::env::var("OUT_DIR").unwrap())));
    try!(p.wait());
    return Ok(());
}

<|endoftext|>


<commit_before>pub struct Hidden<T> {
    opt_val: Option<T>
}

impl<T> Hidden<T> {
    /// Creates a Hidden<T> container, which should never be directly visible
    ///
    /// Should not be called directly. Only public so that `noleak!()` can call it
    pub unsafe fn new() -> Self {
        Hidden { opt_val: None }
    }
}

pub struct Acceptor<'a, T: 'a> {
    mut_hidden: &'a mut Hidden<T>
}

impl<'a, T: 'a> Acceptor<'a, T> {
    pub unsafe fn new(hid: &'a mut Hidden<T>) -> Self {
        Acceptor { mut_hidden: hid }
    }

    pub fn fill(self, t: T) -> Handle<'a, T> {
        self.mut_hidden.opt_val = Some(t);
        Handle { mut_hidden: self.mut_hidden }
    }

    pub fn fill_from<'b>(self, handle_t: Handle<'b, T>) -> Handle<'a, T> {
        let new = handle_t.mut_hidden.opt_val.take().expect("Attempting to .fill_from() an emptied Handle!");
        self.fill(new)
    }
}

pub struct Handle<'a, T: 'a> {
    mut_hidden: &'a mut Hidden<T>
}

impl<'a, T: 'a> std::ops::Deref for Handle<'a, T> {
    type Target = T;
    fn deref(&self) -> &T {
        self.mut_hidden.opt_val.as_ref().expect("Tried to deref() an emptied Handle!")
    }
}

impl <'a, T: 'a> std::ops::DerefMut for Handle<'a, T> {
    fn deref_mut(&mut self) -> &mut T {
        self.mut_hidden.opt_val.as_mut().expect("Tried to deref_mut() an emptied Handle!")
    }
}

#[cfg(test)]
mod test {
    #[test]
    fn it_works() {
    }
}
<commit_msg>Rename Hidden<T> to Lock<T><commit_after>pub struct Lock<T> {
    opt_val: Option<T>
}

impl<T> Lock<T> {
    /// Creates a Lock<T> container, which should never be directly visible
    ///
    /// Should not be called directly. Only public so that `noleak!()` can call it
    pub unsafe fn new() -> Self {
        Lock { opt_val: None }
    }
}

pub struct Acceptor<'a, T: 'a> {
    mut_lock: &'a mut Lock<T>
}

impl<'a, T: 'a> Acceptor<'a, T> {
    pub unsafe fn new(lock: &'a mut Lock<T>) -> Self {
        Acceptor { mut_lock: lock }
    }

    pub fn fill(self, t: T) -> Handle<'a, T> {
        self.mut_lock.opt_val = Some(t);
        Handle { mut_lock: self.mut_lock }
    }

    pub fn fill_from<'b>(self, handle_t: Handle<'b, T>) -> Handle<'a, T> {
        let new = handle_t.mut_lock.opt_val.take().expect("Attempting to .fill_from() an emptied Handle!");
        self.fill(new)
    }
}

pub struct Handle<'a, T: 'a> {
    mut_lock: &'a mut Lock<T>
}

impl<'a, T: 'a> std::ops::Deref for Handle<'a, T> {
    type Target = T;
    fn deref(&self) -> &T {
        self.mut_lock.opt_val.as_ref().expect("Tried to deref() an emptied Handle!")
    }
}

impl <'a, T: 'a> std::ops::DerefMut for Handle<'a, T> {
    fn deref_mut(&mut self) -> &mut T {
        self.mut_lock.opt_val.as_mut().expect("Tried to deref_mut() an emptied Handle!")
    }
}

#[cfg(test)]
mod test {
    #[test]
    fn it_works() {
    }
}
<|endoftext|>