<commit_before>
use std::fs::File;
use std::u16;
use std::fmt::Write;

use crate::sim::RoutingAlgorithm;
use crate::graph_state::{Location};
use crate::graph::{Graph, ID};
use crate::utils::*;

pub fn export_file(graph: &Graph, loc: Option<&Location>,
	algo: Option<&RoutingAlgorithm>, mark_links: Option<&Graph>, path: &str) {
	use std::io::Write;
	if let Ok(mut file) = File::create(path) {
		let content = export_json(&graph, loc, algo, mark_links);
		file.write_all(content.as_bytes()).unwrap();
		//println!("Wrote {}", path);
	} else {
		println!("Failed to create: {}", path);
	}
}

pub fn export_json(graph: &Graph, loc: Option<&Location>, algo: Option<&RoutingAlgorithm>, mark_links: Option<&Graph>) -> String {
	let mut ret = String::new();
	let mut name = String::new();
	let mut label = String::new();

	write!(&mut ret, "{{").unwrap();
	write!(&mut ret, "\"nodes\": [").unwrap();

	let mut comma1 = false;
	for id in 0..graph.node_count() as ID {
		if comma1 {
			write!(&mut ret, ",").unwrap();
		}
		comma1 = true;

		if let Some(algo) = algo {
			name.clear();
			label.clear();
			algo.get_node(id, "name", &mut name);
			algo.get_node(id, "label", &mut label);
		}

		write!(&mut ret, "{{\"id\": \"{}\", ", id).unwrap();
		if let Some(loc) = loc {
			if let Some(pos) = loc.get_position(id) {
				write!(&mut ret, "\"x\": {}, \"y\": {}, ", pos[0] / DEG2KM, pos[1] / DEG2KM).unwrap();
			}
		}

		write!(&mut ret, "\"name\": \"{}\", \"label\": \"{}\"}}", name, label).unwrap();
	}

	write!(&mut ret, "], \"links\": [").unwrap();
	let mut comma2 = false;
	for link in &graph.links {
		if link.from > link.to {
			continue;
		}

		if comma2 {
			write!(&mut ret, ",").unwrap();
		}
		comma2 = true;

		// how to remember
		let source_id = link.from;
		let source_tq = (link.quality() as f32) / (u16::MAX as f32);
		let target_id = link.to;
		let target_tq = if let Some(link) = graph.get_link(target_id, source_id) {
			//println!("found reverse link: {}", link.quality());
			(link.quality() as f32) / (u16::MAX as f32)
		} else {
			0.0
		};

		write!(&mut ret, "{{\"source\": \"{}\", \"target\": \"{}\", \"source_tq\": {}, \"target_tq\": {}",
			source_id, target_id, source_tq, target_tq
		).unwrap();

		// mark link with color
		if let Some(mark) = mark_links {
			if mark.has_link(source_id, target_id) {
				write!(&mut ret, "\"color\": \"#FF00FF\"").unwrap();
			}
		}

		write!(&mut ret, "}}").unwrap();
	}

	write!(&mut ret, "]}}").unwrap();

	ret
}

/*
pub fn export_netjson(graph: &Graph) -> String {
	let mut ret = String::new();

	write!(&mut ret, "{{\"type\": \"NetworkGraph\", \"protocol\": \"\", \"version\": \"\", \"metric\": \"tq\", \"directed\": false, \"multigraph\": false,").unwrap();
	//write!(&mut ret, "\"timestamp\": \"{:?}\", ", chrono::Utc::now()).unwrap();

	write!(&mut ret, "\"nodes\": [").unwrap();
	let mut comma1 = false;
	for (id, node) in graph.nodes.iter().enumerate() {
		if comma1 {
			write!(&mut ret, ",").unwrap();
		}
		comma1 = true;
		write!(&mut ret, "{{\"id\": \"{}\"}}", id).unwrap();
	}

	write!(&mut ret, "], \"links\": [").unwrap();
	let mut comma2 = false;
	for (id, node) in graph.nodes.iter().enumerate() {
		for link in &node.links {
			if comma2 {
				write!(&mut ret, ",").unwrap();
			}
			comma2 = true;
			if link.to < (id as ID) {
				// how to remember
				let source_id = id as ID;
				let source_tq = link.quality;
				let target_id = link.to;
				let target_tq = if let Some(link) = graph.nodes[link.to as usize].find_link(source_id) {
					link.quality
				} else {
					0.0
				};
				write!(&mut ret, "{{\"source\": \"{}\", \"target\": \"{}\", \"source_tq\": {}, \"target_tq\": {}}}",
					source_id, target_id, source_tq, target_tq
				).unwrap();
			}
		}
	}

	write!(&mut ret, "]}}").unwrap();

	ret
}
*/
<commit_msg>fix json export syntax and omit empty name/label fields<commit_after>
use std::fs::File;
use std::u16;
use std::fmt::Write;

use crate::sim::RoutingAlgorithm;
use crate::graph_state::{Location};
use crate::graph::{Graph, ID};
use crate::utils::*;

pub fn export_file(graph: &Graph, loc: Option<&Location>,
	algo: Option<&RoutingAlgorithm>, mark_links: Option<&Graph>, path: &str) {
	use std::io::Write;
	if let Ok(mut file) = File::create(path) {
		let content = export_json(&graph, loc, algo, mark_links);
		file.write_all(content.as_bytes()).unwrap();
		//println!("Wrote {}", path);
	} else {
		println!("Failed to create: {}", path);
	}
}

pub fn export_json(graph: &Graph, loc: Option<&Location>, algo: Option<&RoutingAlgorithm>, mark_links: Option<&Graph>) -> String {
	let mut ret = String::new();
	let mut name = String::new();
	let mut label = String::new();

	write!(&mut ret, "{{").unwrap();
	write!(&mut ret, "\"nodes\": [").unwrap();

	let mut comma1 = false;
	for id in 0..graph.node_count() as ID {
		if comma1 {
			write!(&mut ret, ",").unwrap();
		}
		comma1 = true;

		if let Some(algo) = algo {
			name.clear();
			label.clear();
			algo.get_node(id, "name", &mut name);
			algo.get_node(id, "label", &mut label);
		}

		write!(&mut ret, "{{\"id\": \"{}\"", id).unwrap();
		if let Some(loc) = loc {
			if let Some(pos) = loc.get_position(id) {
				write!(&mut ret, ", \"x\": {}, \"y\": {}", pos[0] / DEG2KM, pos[1] / DEG2KM).unwrap();
			}
		}

		if !name.is_empty() {
			write!(&mut ret, ", \"name\": \"{}\"", name).unwrap();
		}

		if !label.is_empty() {
			write!(&mut ret, ", \"label\": \"{}\"", label).unwrap();
		}

		write!(&mut ret, "}}").unwrap();
	}

	write!(&mut ret, "], \"links\": [").unwrap();
	let mut comma2 = false;
	for link in &graph.links {
		if link.from > link.to {
			continue;
		}

		if comma2 {
			write!(&mut ret, ",").unwrap();
		}
		comma2 = true;

		let source_id = link.from;
		let source_tq = (link.quality() as f32) / (u16::MAX as f32);
		let target_id = link.to;
		let target_tq = if let Some(link) = graph.get_link(target_id, source_id) {
			(link.quality() as f32) / (u16::MAX as f32)
		} else {
			0.0
		};

		write!(&mut ret, "{{\"source\": \"{}\", \"target\": \"{}\"",
			source_id, target_id,
		).unwrap();

		// always show quality (for now)
		if true {
			write!(&mut ret, ", \"source_tq\": {}, \"target_tq\": {}",
				source_tq, target_tq
			).unwrap();
		}

		// mark link with color
		if let Some(mark) = mark_links {
			if mark.has_link(source_id, target_id) {
				write!(&mut ret, ", \"color\": \"#FF00FF\"").unwrap();
			}
		}

		write!(&mut ret, "}}").unwrap();
	}

	write!(&mut ret, "]}}").unwrap();

	ret
}

/*
pub fn export_netjson(graph: &Graph) -> String {
	let mut ret = String::new();

	write!(&mut ret, "{{\"type\": \"NetworkGraph\", \"protocol\": \"\", \"version\": \"\", \"metric\": \"tq\", \"directed\": false, \"multigraph\": false,").unwrap();
	//write!(&mut ret, "\"timestamp\": \"{:?}\", ", chrono::Utc::now()).unwrap();

	write!(&mut ret, "\"nodes\": [").unwrap();
	let mut comma1 = false;
	for (id, node) in graph.nodes.iter().enumerate() {
		if comma1 {
			write!(&mut ret, ",").unwrap();
		}
		comma1 = true;
		write!(&mut ret, "{{\"id\": \"{}\"}}", id).unwrap();
	}

	write!(&mut ret, "], \"links\": [").unwrap();
	let mut comma2 = false;
	for (id, node) in graph.nodes.iter().enumerate() {
		for link in &node.links {
			if comma2 {
				write!(&mut ret, ",").unwrap();
			}
			comma2 = true;
			if link.to < (id as ID) {
				// how to remember
				let source_id = id as ID;
				let source_tq = link.quality;
				let target_id = link.to;
				let target_tq = if let Some(link) = graph.nodes[link.to as usize].find_link(source_id) {
					link.quality
				} else {
					0.0
				};
				write!(&mut ret, "{{\"source\": \"{}\", \"target\": \"{}\", \"source_tq\": {}, \"target_tq\": {}}}",
					source_id, target_id, source_tq, target_tq
				).unwrap();
			}
		}
	}

	write!(&mut ret, "]}}").unwrap();

	ret
}
*/
<|endoftext|>


<commit_before>// Copyright 2017 Amos Onn.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//

use std::result;
use libc;

pub type Result<T> = result::Result<T, libc::c_int>;

use super::fusefl::*;

pub trait ReadFileLike {
    fn read_at(&self, buf: &mut [u8], offset: u64) -> Result<usize>;
}

pub trait WriteFileLike {
    fn write_at(&self, buf: &[u8], offset: u64) -> Result<usize>;

    fn flush(&self) -> Result<()> {
        Ok(())
    }
}

pub struct ReadWriteAdaptor<R, W> {
    reader: R,
    writer: W,
}

impl<R, _> ReadFileLike for ReadWriteAdaptor<R, _> where R: ReadFileLike {
    fn read_at(&self, buf: &mut [u8], offset: u64) -> Result<usize> {
        self.reader.read_at(buf, offset)
    }
}

impl<_, W> WriteFileLike for ReadWriteAdaptor<_, W> where W: WriteFileLike {
    fn write_at(&self, buf: &[u8], offset: u64) -> Result<usize> {
        self.writer.write_at(buf, offset)
    }

    fn flush(&self) -> Result<()> {
        self.writer.flush()
    }
}

pub enum ModalFileLike<R, W, RW> {
    ReadOnly(R),
    WriteOnly(W),
    ReadWrite(RW),
}

impl<R, _, RW> ReadFileLike for ModalFileLike<R, _, RW> where
    R: ReadFileLike, RW: ReadFileLike {
    fn read_at(&self, buf: &mut [u8], offset: u64) -> Result<usize> {
        match self {
            ReadOnly(r) => r.read_at(buf, offset),
            WriteOnly(_) => Err(libc::EBADF),
            ReadWrite(rw) => rw.read_at(buf, offset),
        }
    }
}

impl<_, W, RW> WriteFileLike for ModalFileLike<_, W, RW> where
    W: WriteFileLike, RW: WriteFileLike {
    fn write_at(&self, buf: &[u8], offset: u64) -> Result<usize> {
        match self {
            ReadOnly(_) => Err(libc::EBADF),
            WriteOnly(w) => w.write_at(buf, offset),
            ReadWrite(rw) => rw.write_at(buf, offset),
        }
    }

    fn flush(&self) -> Result<()> {
        match self {
            ReadOnly(_) => Err(libc::EBADF),
            WriteOnly(w) => w.flush(),
            ReadWrite(rw) => rw.flush(),
        }
    }
}

// Part of this will become a default impl of FilesystemFL when RFC #1210 lands.
pub trait FilesystemFLOpen {
    type FileLike: ReadFileLike+WriteFileLike;

    fn open(&self, _req: RequestInfo, _path: &Path, _flags: u32) -> ResultOpenObj<Self::FileLike> {
        Err(libc::ENOSYS)
    }

    /// If this method is not implemented or under Linux kernel versions earlier than 2.6.15, the
    /// mknod() and open() methods will be called instead.
    fn create(&self, _req: RequestInfo, _parent: &Path, _name: &OsStr, _mode: u32, _flags: u32) -> ResultCreateObj<Self::FileLike> {
        Err(libc::ENOSYS)
    }

    fn read(&self, _req: RequestInfo, _path: &Path, _fl: &Self::FileLike, _offset: u64, _size: u32) -> ResultData {
        let mut vec = Vec<u8>::with_capacity(_size);
        unsafe { vec.set_len(_size) };
        let num_read = _fl.read_at(vec.as_mut_slice(), _offset)?;
        assert!(num_read <= _size);
        unsafe { vec.set_len(num_read) };
        Ok(vec)
    }

    fn write(&self, _req: RequestInfo, _path: &Path, _fl: &Self::FileLike, _offset: u64, _data: Vec<u8>, _flags: u32) -> ResultWrite {
        assert!(_data.len() <= u32::max_value());
        _fl.write_at(vec.as_slice(), _offset).map(|x| x as u32)
    }

    fn fsync(&self, _req: RequestInfo, _path: &Path, _fl: &Self::FileLike, _datasync: bool) -> ResultEmpty {
        Err(libc::ENOSYS)
    }
}
<commit_msg>Added FilesystemFLRwOpen trait.<commit_after>// Copyright 2017 Amos Onn.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//

use std::result;
use libc;

pub type Result<T> = result::Result<T, libc::c_int>;

use super::fusefl::*;

pub trait ReadFileLike {
    fn read_at(&self, buf: &mut [u8], offset: u64) -> Result<usize>;
}

pub trait WriteFileLike {
    fn write_at(&self, buf: &[u8], offset: u64) -> Result<usize>;

    fn flush(&self) -> Result<()> {
        Ok(())
    }
}

pub struct ReadWriteAdaptor<R, W> {
    reader: R,
    writer: W,
}

impl<R, _> ReadFileLike for ReadWriteAdaptor<R, _> where R: ReadFileLike {
    fn read_at(&self, buf: &mut [u8], offset: u64) -> Result<usize> {
        self.reader.read_at(buf, offset)
    }
}

impl<_, W> WriteFileLike for ReadWriteAdaptor<_, W> where W: WriteFileLike {
    fn write_at(&self, buf: &[u8], offset: u64) -> Result<usize> {
        self.writer.write_at(buf, offset)
    }

    fn flush(&self) -> Result<()> {
        self.writer.flush()
    }
}

pub enum ModalFileLike<R, W, RW> {
    ReadOnly(R),
    WriteOnly(W),
    ReadWrite(RW),
}

impl<R, _, RW> ReadFileLike for ModalFileLike<R, _, RW> where
    R: ReadFileLike, RW: ReadFileLike {
    fn read_at(&self, buf: &mut [u8], offset: u64) -> Result<usize> {
        match self {
            ReadOnly(r) => r.read_at(buf, offset),
            WriteOnly(_) => Err(libc::EBADF),
            ReadWrite(rw) => rw.read_at(buf, offset),
        }
    }
}

impl<_, W, RW> WriteFileLike for ModalFileLike<_, W, RW> where
    W: WriteFileLike, RW: WriteFileLike {
    fn write_at(&self, buf: &[u8], offset: u64) -> Result<usize> {
        match self {
            ReadOnly(_) => Err(libc::EBADF),
            WriteOnly(w) => w.write_at(buf, offset),
            ReadWrite(rw) => rw.write_at(buf, offset),
        }
    }

    fn flush(&self) -> Result<()> {
        match self {
            ReadOnly(_) => Err(libc::EBADF),
            WriteOnly(w) => w.flush(),
            ReadWrite(rw) => rw.flush(),
        }
    }
}

pub trait FilesystemFLRwOpen {
    type ReadLike: ReadFileLike;
    type WriteLike: WriteFileLike;
    type ReadWriteLike: ReadFileLike+WriteFileLike = ReadWriteAdaptor<Self::ReadLike, Self::WriteLike>;

    fn open_read(&self, _req: RequestInfo, _path: &Path, _flags: u32) -> ResultOpenObj<Self::ReadLike> {
        Err(libc::ENOSYS)
    }

    fn open_write(&self, _req: RequestInfo, _path: &Path, _flags: u32) -> ResultOpenObj<Self::WriteLike> {
        Err(libc::ENOSYS)
    }

    fn open_readwrite(&self, _req: RequestInfo, _path: &Path, _flags: u32) -> ResultOpenObj<Self::ReadWriteLike> {
        Err(libc::ENOSYS)
    }

    fn create_write(&self, _req: RequestInfo, _parent: &Path, _name: &OsStr, _mode: u32, _flags: u32) -> ResultCreateObj<Self::WriteLike> {
        Err(libc::ENOSYS)
    }

    fn create_readwrite(&self, _req: RequestInfo, _parent: &Path, _name: &OsStr, _mode: u32, _flags: u32) -> ResultCreateObj<Self::ReadWriteLike> {
        Err(libc::ENOSYS)
    }
}

// Part of this will become a default impl of FilesystemFL when RFC #1210 lands.
pub trait FilesystemFLOpen {
    type FileLike: ReadFileLike+WriteFileLike;

    fn open(&self, _req: RequestInfo, _path: &Path, _flags: u32) -> ResultOpenObj<Self::FileLike> {
        Err(libc::ENOSYS)
    }

    /// If this method is not implemented or under Linux kernel versions earlier than 2.6.15, the
    /// mknod() and open() methods will be called instead.
    fn create(&self, _req: RequestInfo, _parent: &Path, _name: &OsStr, _mode: u32, _flags: u32) -> ResultCreateObj<Self::FileLike> {
        Err(libc::ENOSYS)
    }

    fn read(&self, _req: RequestInfo, _path: &Path, _fl: &Self::FileLike, _offset: u64, _size: u32) -> ResultData {
        let mut vec = Vec<u8>::with_capacity(_size);
        unsafe { vec.set_len(_size) };
        let num_read = _fl.read_at(vec.as_mut_slice(), _offset)?;
        assert!(num_read <= _size);
        unsafe { vec.set_len(num_read) };
        Ok(vec)
    }

    fn write(&self, _req: RequestInfo, _path: &Path, _fl: &Self::FileLike, _offset: u64, _data: Vec<u8>, _flags: u32) -> ResultWrite {
        assert!(_data.len() <= u32::max_value());
        _fl.write_at(vec.as_slice(), _offset).map(|x| x as u32)
    }

    fn fsync(&self, _req: RequestInfo, _path: &Path, _fl: &Self::FileLike, _datasync: bool) -> ResultEmpty {
        Err(libc::ENOSYS)
    }
}
<|endoftext|>


<commit_before>//! Contains code to handle an IPC channel which is issuing commands.

use std::io::Error as IOError;
use std::io::prelude::*;

use std::mem::transmute;

use rustc_serialize::Encodable;
use rustc_serialize::json::{Json, ToJson, Encoder, encode, ParserError, EncoderError};

use unix_socket::UnixStream;

/// Reasons a client message might be erroneous
#[derive(Debug)]
enum ResponseError {
    /// Connection was closed
    ConnectionClosed,
    /// Some bytes dun goofed
    InvalidString,
    /// There were IO issues
    IO(IOError),
    /// Json was invalid
    InvalidJson(ParserError),
    /// Couldn't format Json server-side
    UnableToFormat(EncoderError)
}

/// Receives a packet from the given stream.
fn receive_packet(stream: &mut Read) -> Result<Json, ResponseError> {
    let mut buffer = [0u8; 4];
    try!(stream.read_exact(&mut buffer).map_err(ResponseError::IO));
    // This is what the byteorder crate does (needs testing)
    let len = u32::from_be(unsafe { buffer.as_ptr() as *const u32 } as u32);
    trace!("Listening for packet of length {}", len);
    return Json::from_reader(&mut stream.take(len as u64))
        .map_err(ResponseError::InvalidJson);
}

fn write_packet(stream: &mut Write, packet: &Json) -> Result<(), ResponseError> {
    let json_string = try!(encode(packet).map_err(ResponseError::UnableToFormat));
    trace!("Writing packet of length {}: {}", json_string.len(), json_string);
    if json_string.len() > ::std::u32::MAX as usize {
        panic!("Attempted to send reply too big for the channel!");
    }
    let _len = json_string.len() as u32;
    let len_bytes = unsafe { transmute::<_, [u8; 4]>(_len) };
    stream.write_all(&len_bytes);
    stream.write_all(json_string.as_bytes()).map_err(ResponseError::IO)
}

pub fn handle_client(mut stream: UnixStream) {
    println!("Starting connection.");

    // Listen for starting connection
}

fn command(mut stream: UnixStream) {

}

fn event(mut stream: UnixStream) {

}
<commit_msg>Remove unneeded unsafety<commit_after>//! Contains code to handle an IPC channel which is issuing commands.

use std::io::Error as IOError;
use std::io::prelude::*;

use std::mem::transmute;

use rustc_serialize::Encodable;
use rustc_serialize::json::{Json, ToJson, Encoder, encode, ParserError, EncoderError};

use unix_socket::UnixStream;

/// Reasons a client message might be erroneous
#[derive(Debug)]
enum ResponseError {
    /// Connection was closed
    ConnectionClosed,
    /// Some bytes dun goofed
    InvalidString,
    /// There were IO issues
    IO(IOError),
    /// Json was invalid
    InvalidJson(ParserError),
    /// Couldn't format Json server-side
    UnableToFormat(EncoderError)
}

/// Receives a packet from the given stream.
fn receive_packet(stream: &mut Read) -> Result<Json, ResponseError> {
    let mut buffer = [0u8; 4];
    try!(stream.read_exact(&mut buffer).map_err(ResponseError::IO));
    // This is what the byteorder crate does (needs testing)
    let len = u32::from_be(buffer.as_ptr() as *const u32 as u32);
    trace!("Listening for packet of length {}", len);
    return Json::from_reader(&mut stream.take(len as u64))
        .map_err(ResponseError::InvalidJson);
}

fn write_packet(stream: &mut Write, packet: &Json) -> Result<(), ResponseError> {
    let json_string = try!(encode(packet).map_err(ResponseError::UnableToFormat));
    trace!("Writing packet of length {}: {}", json_string.len(), json_string);
    if json_string.len() > ::std::u32::MAX as usize {
        panic!("Attempted to send reply too big for the channel!");
    }
    let _len = json_string.len() as u32;
    let len_bytes = unsafe { transmute::<_, [u8; 4]>(_len) };
    stream.write_all(&len_bytes);
    stream.write_all(json_string.as_bytes()).map_err(ResponseError::IO)
}

pub fn handle_client(mut stream: UnixStream) {
    println!("Starting connection.");

    // Listen for starting connection
}

fn command(mut stream: UnixStream) {

}

fn event(mut stream: UnixStream) {

}
<|endoftext|>


<commit_before>/*!
A macro for declaring lazily evaluated statics.

Using this macro, it is possible to have `static`s that require code to be
executed at runtime in order to be initialized.
This includes anything requiring heap allocations, like vectors or hash maps,
as well as anything that requires function calls to be computed.

# Syntax

```ignore
lazy_static! {
    [pub] static ref NAME_1: TYPE_1 = EXPR_1;
    [pub] static ref NAME_2: TYPE_2 = EXPR_2;
    ...
    [pub] static ref NAME_N: TYPE_N = EXPR_N;
}
```

# Semantic

For a given `static ref NAME: TYPE = EXPR;`, the macro generates a
unique type that implements `Deref<TYPE>` and stores it in a static with name `NAME`.

On first deref, `EXPR` gets evaluated and stored internally, such that all further derefs
can return a reference to the same object.

Like regular `static mut`s, this macro only works for types that fulfill the `Sync`
trait.

# Example

Using the macro:

```rust
#[macro_use]
extern crate lazy_static;

use std::collections::HashMap;

lazy_static! {
    static ref HASHMAP: HashMap<u32, &'static str> = {
        let mut m = HashMap::new();
        m.insert(0, "foo");
        m.insert(1, "bar");
        m.insert(2, "baz");
        m
    };
    static ref COUNT: usize = HASHMAP.len();
    static ref NUMBER: u32 = times_two(21);
}

fn times_two(n: u32) -> u32 { n * 2 }

fn main() {
    println!("The map has {} entries.", *COUNT);
    println!("The entry for `0` is \"{}\".", HASHMAP.get(&0).unwrap());
    println!("A expensive calculation on a static results in: {}.", *NUMBER);
}
```

# Implementation details

The `Deref` implementation uses a hidden `static mut` that is guarded by a atomic check
using the `sync::Once` abstraction. All lazily evaluated values are currently
put in a heap allocated box, due to the Rust language currently not providing any way to
define uninitialized `static mut` values.

*/

#![crate_type = "dylib"]

#[macro_export]
macro_rules! lazy_static {
    (static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(PRIV static ref $N : $T = $e; $($t)*);
    };
    (pub static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(PUB static ref $N : $T = $e; $($t)*);
    };
    ($VIS:ident static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(MAKE TY $VIS $N);
        impl ::std::ops::Deref for $N {
            type Target = $T;
            fn deref<'a>(&'a self) -> &'a $T {
                use std::sync::{Once, ONCE_INIT};
                use std::mem::transmute;

                #[inline(always)]
                fn require_sync<T: Sync>(_: &T) { }

                unsafe {
                    static mut __static: *const $T = 0 as *const $T;
                    static mut __ONCE: Once = ONCE_INIT;
                    __ONCE.call_once(|| {
                        __static = transmute::<Box<$T>, *const $T>(box() ($e));
                    });
                    let static_ref = &*__static;
                    require_sync(static_ref);
                    static_ref
                }
            }
        }
        lazy_static!($($t)*);
    };
    (MAKE TY PUB $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        pub struct $N {__private_field: ()}
        pub static $N: $N = $N {__private_field: ()};
    };
    (MAKE TY PRIV $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        struct $N {__private_field: ()}
        static $N: $N = $N {__private_field: ()};
    };
    () => ()
}
<commit_msg>Move to new box syntax<commit_after>/*!
A macro for declaring lazily evaluated statics.

Using this macro, it is possible to have `static`s that require code to be
executed at runtime in order to be initialized.
This includes anything requiring heap allocations, like vectors or hash maps,
as well as anything that requires function calls to be computed.

# Syntax

```ignore
lazy_static! {
    [pub] static ref NAME_1: TYPE_1 = EXPR_1;
    [pub] static ref NAME_2: TYPE_2 = EXPR_2;
    ...
    [pub] static ref NAME_N: TYPE_N = EXPR_N;
}
```

# Semantic

For a given `static ref NAME: TYPE = EXPR;`, the macro generates a
unique type that implements `Deref<TYPE>` and stores it in a static with name `NAME`.

On first deref, `EXPR` gets evaluated and stored internally, such that all further derefs
can return a reference to the same object.

Like regular `static mut`s, this macro only works for types that fulfill the `Sync`
trait.

# Example

Using the macro:

```rust
#[macro_use]
extern crate lazy_static;

use std::collections::HashMap;

lazy_static! {
    static ref HASHMAP: HashMap<u32, &'static str> = {
        let mut m = HashMap::new();
        m.insert(0, "foo");
        m.insert(1, "bar");
        m.insert(2, "baz");
        m
    };
    static ref COUNT: usize = HASHMAP.len();
    static ref NUMBER: u32 = times_two(21);
}

fn times_two(n: u32) -> u32 { n * 2 }

fn main() {
    println!("The map has {} entries.", *COUNT);
    println!("The entry for `0` is \"{}\".", HASHMAP.get(&0).unwrap());
    println!("A expensive calculation on a static results in: {}.", *NUMBER);
}
```

# Implementation details

The `Deref` implementation uses a hidden `static mut` that is guarded by a atomic check
using the `sync::Once` abstraction. All lazily evaluated values are currently
put in a heap allocated box, due to the Rust language currently not providing any way to
define uninitialized `static mut` values.

*/

#![crate_type = "dylib"]

#[macro_export]
macro_rules! lazy_static {
    (static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(PRIV static ref $N : $T = $e; $($t)*);
    };
    (pub static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(PUB static ref $N : $T = $e; $($t)*);
    };
    ($VIS:ident static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(MAKE TY $VIS $N);
        impl ::std::ops::Deref for $N {
            type Target = $T;
            fn deref<'a>(&'a self) -> &'a $T {
                use std::sync::{Once, ONCE_INIT};
                use std::mem::transmute;

                #[inline(always)]
                fn require_sync<T: Sync>(_: &T) { }

                unsafe {
                    static mut __static: *const $T = 0 as *const $T;
                    static mut __ONCE: Once = ONCE_INIT;
                    __ONCE.call_once(|| {
                        __static = transmute::<Box<$T>, *const $T>(Box::new(($e)));
                    });
                    let static_ref = &*__static;
                    require_sync(static_ref);
                    static_ref
                }
            }
        }
        lazy_static!($($t)*);
    };
    (MAKE TY PUB $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        pub struct $N {__private_field: ()}
        pub static $N: $N = $N {__private_field: ()};
    };
    (MAKE TY PRIV $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        struct $N {__private_field: ()}
        static $N: $N = $N {__private_field: ()};
    };
    () => ()
}
<|endoftext|>


<commit_before>extern crate goblin;
extern crate env_logger;

use goblin::error;
use std::path::Path;
use std::env;
use std::fs::File;
use std::io::Read;

fn run () -> error::Result<()> {
    for (i, arg) in env::args().enumerate() {
        if i == 1 {
            let path = Path::new(arg.as_str());
            let mut fd = File::open(path)?;
            let buffer = { let mut v = Vec::new(); fd.read_to_end(&mut v).unwrap(); v};
            let res = goblin::Object::parse(&buffer)?;
            println!("{:#?}", res);
        }
    }
    Ok(())
}

pub fn main () {
    env_logger::init().unwrap();
    match run() {
        Ok(()) => (),
        Err(err) => println!("{:#}", err)
    }
}
<commit_msg>examples: fix env_logger unwrap<commit_after>extern crate goblin;
extern crate env_logger;

use goblin::error;
use std::path::Path;
use std::env;
use std::fs::File;
use std::io::Read;

fn run () -> error::Result<()> {
    for (i, arg) in env::args().enumerate() {
        if i == 1 {
            let path = Path::new(arg.as_str());
            let mut fd = File::open(path)?;
            let buffer = { let mut v = Vec::new(); fd.read_to_end(&mut v).unwrap(); v};
            let res = goblin::Object::parse(&buffer)?;
            println!("{:#?}", res);
        }
    }
    Ok(())
}

pub fn main () {
    env_logger::init();
    match run() {
        Ok(()) => (),
        Err(err) => println!("{:#}", err)
    }
}
<|endoftext|>


<commit_before>/// An enum of all possible tokens allowed by the
/// [WebIDL grammar](https://heycam.github.io/webidl/#idl-grammar) A token in this case is a
/// terminal, either a static string or regular expression based token. Note that not all possible
/// simplifications are made such as converting the "True" and "False" tokens to actual booleans.
/// This choice was made to be as consistent as possible with the WebIDL grammar.
#[allow(missing_docs)]
#[derive(Clone, Debug, PartialEq)]
pub enum Token {
    // Keywords
    Any,
    ArrayBuffer,
    Attribute,
    Boolean,
    Byte,
    ByteString,
    Callback,
    Const,
    DataView,
    Deleter,
    Dictionary,
    DOMException,
    DOMString,
    Double,
    Enum,
    Error,
    False,
    Float,
    Float64Array,
    Float32Array,
    FrozenArray,
    Getter,
    Implements,
    Inherit,
    Int16Array,
    Int32Array,
    Int8Array,
    Interface,
    Iterable,
    LegacyCaller,
    Long,
    Maplike,
    Namespace,
    NaN,
    NegativeInfinity,
    Null,
    Object,
    Octet,
    Optional,
    Or,
    Partial,
    PositiveInfinity,
    Promise,
    ReadOnly,
    Record,
    Required,
    Sequence,
    Serializer,
    Setlike,
    Setter,
    Short,
    Static,
    Stringifier,
    True,
    Typedef,
    USVString,
    Uint16Array,
    Uint32Array,
    Uint8Array,
    Uint8ClampedArray,
    Unrestricted,
    Unsigned,
    Void,

    // Regular expressions
    FloatLiteral(f64),
    Identifier(String),
    IntegerLiteral(i64),
    OtherLiteral(char),
    StringLiteral(String),

    // Symbols
    Colon,
    Comma,
    Ellipsis,
    Equals,
    GreaterThan,
    Hyphen,
    LeftBrace,
    LeftBracket,
    LeftParenthesis,
    LessThan,
    Period,
    QuestionMark,
    RightBrace,
    RightBracket,
    RightParenthesis,
    Semicolon,
}
<commit_msg>docs(lexer): change token documentation<commit_after>/// An enum of all possible tokens allowed by the
/// [WebIDL grammar](https://heycam.github.io/webidl/#idl-grammar) A token in this case is a
/// terminal, either a static string or regular expression based token. Note that not all possible
/// simplifications are made such as converting the `True` and `False` tokens to actual booleans.
/// This choice was made to be as consistent as possible with the WebIDL grammar.
#[allow(missing_docs)]
#[derive(Clone, Debug, PartialEq)]
pub enum Token {
    // Keywords
    Any,
    ArrayBuffer,
    Attribute,
    Boolean,
    Byte,
    ByteString,
    Callback,
    Const,
    DataView,
    Deleter,
    Dictionary,
    DOMException,
    DOMString,
    Double,
    Enum,
    Error,
    False,
    Float,
    Float32Array,
    Float64Array,
    FrozenArray,
    Getter,
    Implements,
    Inherit,
    Int16Array,
    Int32Array,
    Int8Array,
    Interface,
    Iterable,
    LegacyCaller,
    Long,
    Maplike,
    Namespace,
    NaN,
    NegativeInfinity,
    Null,
    Object,
    Octet,
    Optional,
    Or,
    Partial,
    PositiveInfinity,
    Promise,
    ReadOnly,
    Record,
    Required,
    Sequence,
    Serializer,
    Setlike,
    Setter,
    Short,
    Static,
    Stringifier,
    True,
    Typedef,
    USVString,
    Uint16Array,
    Uint32Array,
    Uint8Array,
    Uint8ClampedArray,
    Unrestricted,
    Unsigned,
    Void,

    // Regular expressions
    FloatLiteral(f64),
    Identifier(String),
    IntegerLiteral(i64),
    OtherLiteral(char),
    StringLiteral(String),

    // Symbols
    Colon,
    Comma,
    Ellipsis,
    Equals,
    GreaterThan,
    Hyphen,
    LeftBrace,
    LeftBracket,
    LeftParenthesis,
    LessThan,
    Period,
    QuestionMark,
    RightBrace,
    RightBracket,
    RightParenthesis,
    Semicolon,
}
<|endoftext|>


<commit_before>//! **GraphMap\<N, E\>** is an undirected graph where node values are mapping keys.

use std::hash::{Hash};
use std::collections::HashMap;
use std::collections::hash_map::Hasher;
use std::iter::Map;
use std::collections::hash_map::{
    Keys,
};
use std::collections::hash_map::Entry::{
    Occupied,
    Vacant,
};
use std::slice::{
    Iter,
};
use std::fmt;
use std::ops::{Index, IndexMut};

/// **GraphMap\<N, E\>** is an undirected graph, with generic node values **N** and edge weights **E**.
///
/// It uses an combined adjacency list and sparse adjacency matrix representation, using **O(|V|
/// + |E|)** space, and allows testing for edge existance in constant time.
///
/// The node type **N** must implement **Copy** and will be used as node identifier, duplicated
/// into several places in the data structure.
/// It must be suitable as a hash table key (implementing **Eq + Hash**).
/// The node type must also implement **Ord** so that the implementation can
/// order the pair (**a**, **b**) for an edge connecting any two nodes **a** and **b**.
///
/// **GraphMap** does not allow parallel edges, but self loops are allowed.
#[derive(Clone)]
pub struct GraphMap<N: Eq + Hash<Hasher>, E> {
    nodes: HashMap<N, Vec<N>>,
    edges: HashMap<(N, N), E>,
}

impl<N: Eq + Hash<Hasher> + fmt::Debug, E: fmt::Debug> fmt::Debug for GraphMap<N, E>
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.nodes.fmt(f)
    }
}

#[inline]
fn edge_key<N: Copy + Ord>(a: N, b: N) -> (N, N)
{
    if a <= b { (a, b) } else { (b, a) }
}

#[inline]
fn copy<N: Copy>(n: &N) -> N { *n }

/// A trait group for **GraphMap**'s node identifier.
pub trait NodeTrait : Copy + Ord + Eq + Hash<Hasher> {}
impl<N> NodeTrait for N where N: Copy + Ord + Eq + Hash<Hasher> {}

impl<N, E> GraphMap<N, E> where N: NodeTrait
{
    /// Create a new **GraphMap**.
    pub fn new() -> Self
    {
        GraphMap {
            nodes: HashMap::new(),
            edges: HashMap::new(),
        }
    }

    /// Create a new **GraphMap** with estimated capacity.
    pub fn with_capacity(nodes: usize, edges: usize) -> Self
    {
        GraphMap {
            nodes: HashMap::with_capacity(nodes),
            edges: HashMap::with_capacity(edges),
        }
    }

    /// Return the number of nodes in the graph.
    pub fn node_count(&self) -> usize
    {
        self.nodes.len()
    }

    /// Return the number of edges in the graph.
    pub fn edge_count(&self) -> usize
    {
        self.edges.len()
    }

    /// Remove all nodes and edges
    pub fn clear(&mut self)
    {
        self.nodes.clear();
        self.edges.clear();
    }

    /// Add node **n** to the graph.
    pub fn add_node(&mut self, n: N) -> N {
        match self.nodes.entry(n) {
            Occupied(_) => {}
            Vacant(ent) => { ent.insert(Vec::new()); }
        }
        n
    }

    /// Return **true** if node **n** was removed.
    pub fn remove_node(&mut self, n: N) -> bool {
        let successors = match self.nodes.remove(&n) {
            None => return false,
            Some(sus) => sus,
        };
        for succ in successors.into_iter() {
            // remove all successor links
            self.remove_single_edge(&succ, &n);
            // Remove all edge values
            self.edges.remove(&edge_key(n, succ));
        }
        true
    }

    /// Return **true** if the node is contained in the graph.
    pub fn contains_node(&self, n: N) -> bool {
        self.nodes.contains_key(&n)
    }

    /// Add an edge connecting **a** and **b** to the graph.
    ///
    /// Inserts nodes **a** and/or **b** if they aren't already part of the graph.
    ///
    /// Return **true** if edge did not previously exist.
    ///
    /// ## Example
    /// ```
    /// use petgraph::GraphMap;
    ///
    /// let mut g = GraphMap::new();
    /// g.add_edge(1, 2, -1);
    /// assert_eq!(g.node_count(), 2);
    /// assert_eq!(g.edge_count(), 1);
    /// ```
    pub fn add_edge(&mut self, a: N, b: N, edge: E) -> bool
    {
        // Use Ord to order the edges
        match self.nodes.entry(a) {
            Occupied(ent) => { ent.into_mut().push(b); }
            Vacant(ent) => { ent.insert(vec![b]); }
        }
        match self.nodes.entry(b) {
            Occupied(ent) => { ent.into_mut().push(a); }
            Vacant(ent) => { ent.insert(vec![a]); }
        }
        self.edges.insert(edge_key(a, b), edge).is_none()
    }

    /// Remove successor relation from a to b
    ///
    /// Return **true** if it did exist.
    fn remove_single_edge(&mut self, a: &N, b: &N) -> bool
    {
        match self.nodes.get_mut(a) {
            None => false,
            Some(sus) => {
                match sus.iter().position(|elt| elt == b) {
                    Some(index) => { sus.swap_remove(index); true }
                    None => false,
                }
            }
        }
    }

    /// Remove edge from **a** to **b** from the graph and return the edge weight.
    ///
    /// Return **None** if the edge didn't exist.
    ///
    /// ## Example
    ///
    /// ```
    /// use petgraph::GraphMap;
    ///
    /// let mut g = GraphMap::new();
    /// g.add_node(1);
    /// g.add_node(2);
    /// g.add_edge(1, 2, -1);
    ///
    /// let edge = g.remove_edge(2, 1);
    /// assert_eq!(edge, Some(-1));
    /// assert_eq!(g.edge_count(), 0);
    /// ```
    pub fn remove_edge(&mut self, a: N, b: N) -> Option<E>
    {
        let exist1 = self.remove_single_edge(&a, &b);
        let exist2 = self.remove_single_edge(&b, &a);
        let weight = self.edges.remove(&edge_key(a, b));
        debug_assert!(exist1 == exist2 && exist1 == weight.is_some());
        weight
    }

    /// Return **true** if the edge connecting **a** with **b** is contained in the graph.
    pub fn contains_edge(&self, a: N, b: N) -> bool {
        self.edges.contains_key(&edge_key(a, b))
    }

    /// Return an iterator over the nodes of the graph.
    ///
    /// Iterator element type is **N**.
    pub fn nodes<'a>(&'a self) -> Nodes<'a, N>
    {
        Nodes{iter: self.nodes.keys().map(copy)}
    }

    /// Return an iterator over the nodes that are connected with **from** by edges.
    ///
    /// If the node **from** does not exist in the graph, return an empty iterator.
    ///
    /// Iterator element type is **N**.
    pub fn neighbors<'a>(&'a self, from: N) -> Neighbors<'a, N>
    {
        Neighbors{iter:
            match self.nodes.get(&from) {
                Some(neigh) => neigh.iter(),
                None => [].iter(),
            }.map(copy)
        }
    }

    /// Return an iterator over the nodes that are connected with **from** by edges,
    /// paired with the edge weight.
    ///
    /// If the node **from** does not exist in the graph, return an empty iterator.
    ///
    /// Iterator element type is **(N, &'a E)**.
    pub fn edges<'a>(&'a self, from: N) -> Edges<'a, N, E>
    {
        Edges {
            from: from,
            iter: self.neighbors(from),
            edges: &self.edges,
        }
    }

    /// Return a reference to the edge weight connecting **a** with **b**, or
    /// **None** if the edge does not exist in the graph.
    pub fn edge_weight<'a>(&'a self, a: N, b: N) -> Option<&'a E>
    {
        self.edges.get(&edge_key(a, b))
    }

    /// Return a mutable reference to the edge weight connecting **a** with **b**, or
    /// **None** if the edge does not exist in the graph.
    pub fn edge_weight_mut<'a>(&'a mut self, a: N, b: N) -> Option<&'a mut E>
    {
        self.edges.get_mut(&edge_key(a, b))
    }
}

macro_rules! iterator_methods {
    () => (
        #[inline]
        fn next(&mut self) -> Option<<Self as Iterator>::Item>
        {
            self.iter.next()
        }

        #[inline]
        fn size_hint(&self) -> (usize, Option<usize>)
        {
            self.iter.size_hint()
        }
    )
}

pub struct Nodes<'a, N: 'a> {
    iter: Map<&'a N, N, Keys<'a, N, Vec<N>>, fn(&N) -> N>,
}

impl<'a, N> Iterator for Nodes<'a, N>
{
    type Item = N;
    iterator_methods!();
}

pub struct Neighbors<'a, N: 'a> {
    iter: Map<&'a N, N, Iter<'a, N>, fn(&N) -> N>,
}

impl<'a, N> Iterator for Neighbors<'a, N>
{
    type Item = N;
    iterator_methods!();
}

pub struct Edges<'a, N, E: 'a> where N: 'a + NodeTrait
{
    pub from: N,
    pub edges: &'a HashMap<(N, N), E>,
    pub iter: Neighbors<'a, N>,
}

impl<'a, N, E> Iterator for Edges<'a, N, E>
    where N: 'a + NodeTrait, E: 'a
{
    type Item = (N, &'a E);
    fn next(&mut self) -> Option<(N, &'a E)>
    {
        match self.iter.next() {
            None => None,
            Some(b) => {
                let a = self.from;
                match self.edges.get(&edge_key(a, b)) {
                    None => unreachable!(),
                    Some(edge) => {
                        Some((b, edge))
                    }
                }
            }
        }
    }
}

impl<N, E> Index<(N, N)> for GraphMap<N, E> where N: NodeTrait
{
    type Output = E;
    /// Index **GraphMap** by node pairs to access edge weights.
    fn index(&self, index: &(N, N)) -> &E
    {
        self.edge_weight(index.0, index.1).expect("GraphMap::index: no such edge")
    }
}

impl<N, E> IndexMut<(N, N)> for GraphMap<N, E> where N: NodeTrait
{
    type Output = E;
    /// Index **GraphMap** by node pairs to access edge weights.
    fn index_mut(&mut self, index: &(N, N)) -> &mut E
    {
        self.edge_weight_mut(index.0, index.1).expect("GraphMap::index: no such edge")
    }
}
<commit_msg>Update iterators for Map change<commit_after>//! **GraphMap\<N, E\>** is an undirected graph where node values are mapping keys.

use std::hash::{Hash};
use std::collections::HashMap;
use std::collections::hash_map::Hasher;
use std::iter::Map;
use std::collections::hash_map::{
    Keys,
};
use std::collections::hash_map::Entry::{
    Occupied,
    Vacant,
};
use std::slice::{
    Iter,
};
use std::fmt;
use std::ops::{Index, IndexMut};

/// **GraphMap\<N, E\>** is an undirected graph, with generic node values **N** and edge weights **E**.
///
/// It uses an combined adjacency list and sparse adjacency matrix representation, using **O(|V|
/// + |E|)** space, and allows testing for edge existance in constant time.
///
/// The node type **N** must implement **Copy** and will be used as node identifier, duplicated
/// into several places in the data structure.
/// It must be suitable as a hash table key (implementing **Eq + Hash**).
/// The node type must also implement **Ord** so that the implementation can
/// order the pair (**a**, **b**) for an edge connecting any two nodes **a** and **b**.
///
/// **GraphMap** does not allow parallel edges, but self loops are allowed.
#[derive(Clone)]
pub struct GraphMap<N: Eq + Hash<Hasher>, E> {
    nodes: HashMap<N, Vec<N>>,
    edges: HashMap<(N, N), E>,
}

impl<N: Eq + Hash<Hasher> + fmt::Debug, E: fmt::Debug> fmt::Debug for GraphMap<N, E>
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.nodes.fmt(f)
    }
}

#[inline]
fn edge_key<N: Copy + Ord>(a: N, b: N) -> (N, N)
{
    if a <= b { (a, b) } else { (b, a) }
}

#[inline]
fn copy<N: Copy>(n: &N) -> N { *n }

/// A trait group for **GraphMap**'s node identifier.
pub trait NodeTrait : Copy + Ord + Eq + Hash<Hasher> {}
impl<N> NodeTrait for N where N: Copy + Ord + Eq + Hash<Hasher> {}

impl<N, E> GraphMap<N, E> where N: NodeTrait
{
    /// Create a new **GraphMap**.
    pub fn new() -> Self
    {
        GraphMap {
            nodes: HashMap::new(),
            edges: HashMap::new(),
        }
    }

    /// Create a new **GraphMap** with estimated capacity.
    pub fn with_capacity(nodes: usize, edges: usize) -> Self
    {
        GraphMap {
            nodes: HashMap::with_capacity(nodes),
            edges: HashMap::with_capacity(edges),
        }
    }

    /// Return the number of nodes in the graph.
    pub fn node_count(&self) -> usize
    {
        self.nodes.len()
    }

    /// Return the number of edges in the graph.
    pub fn edge_count(&self) -> usize
    {
        self.edges.len()
    }

    /// Remove all nodes and edges
    pub fn clear(&mut self)
    {
        self.nodes.clear();
        self.edges.clear();
    }

    /// Add node **n** to the graph.
    pub fn add_node(&mut self, n: N) -> N {
        match self.nodes.entry(n) {
            Occupied(_) => {}
            Vacant(ent) => { ent.insert(Vec::new()); }
        }
        n
    }

    /// Return **true** if node **n** was removed.
    pub fn remove_node(&mut self, n: N) -> bool {
        let successors = match self.nodes.remove(&n) {
            None => return false,
            Some(sus) => sus,
        };
        for succ in successors.into_iter() {
            // remove all successor links
            self.remove_single_edge(&succ, &n);
            // Remove all edge values
            self.edges.remove(&edge_key(n, succ));
        }
        true
    }

    /// Return **true** if the node is contained in the graph.
    pub fn contains_node(&self, n: N) -> bool {
        self.nodes.contains_key(&n)
    }

    /// Add an edge connecting **a** and **b** to the graph.
    ///
    /// Inserts nodes **a** and/or **b** if they aren't already part of the graph.
    ///
    /// Return **true** if edge did not previously exist.
    ///
    /// ## Example
    /// ```
    /// use petgraph::GraphMap;
    ///
    /// let mut g = GraphMap::new();
    /// g.add_edge(1, 2, -1);
    /// assert_eq!(g.node_count(), 2);
    /// assert_eq!(g.edge_count(), 1);
    /// ```
    pub fn add_edge(&mut self, a: N, b: N, edge: E) -> bool
    {
        // Use Ord to order the edges
        match self.nodes.entry(a) {
            Occupied(ent) => { ent.into_mut().push(b); }
            Vacant(ent) => { ent.insert(vec![b]); }
        }
        match self.nodes.entry(b) {
            Occupied(ent) => { ent.into_mut().push(a); }
            Vacant(ent) => { ent.insert(vec![a]); }
        }
        self.edges.insert(edge_key(a, b), edge).is_none()
    }

    /// Remove successor relation from a to b
    ///
    /// Return **true** if it did exist.
    fn remove_single_edge(&mut self, a: &N, b: &N) -> bool
    {
        match self.nodes.get_mut(a) {
            None => false,
            Some(sus) => {
                match sus.iter().position(|elt| elt == b) {
                    Some(index) => { sus.swap_remove(index); true }
                    None => false,
                }
            }
        }
    }

    /// Remove edge from **a** to **b** from the graph and return the edge weight.
    ///
    /// Return **None** if the edge didn't exist.
    ///
    /// ## Example
    ///
    /// ```
    /// use petgraph::GraphMap;
    ///
    /// let mut g = GraphMap::new();
    /// g.add_node(1);
    /// g.add_node(2);
    /// g.add_edge(1, 2, -1);
    ///
    /// let edge = g.remove_edge(2, 1);
    /// assert_eq!(edge, Some(-1));
    /// assert_eq!(g.edge_count(), 0);
    /// ```
    pub fn remove_edge(&mut self, a: N, b: N) -> Option<E>
    {
        let exist1 = self.remove_single_edge(&a, &b);
        let exist2 = self.remove_single_edge(&b, &a);
        let weight = self.edges.remove(&edge_key(a, b));
        debug_assert!(exist1 == exist2 && exist1 == weight.is_some());
        weight
    }

    /// Return **true** if the edge connecting **a** with **b** is contained in the graph.
    pub fn contains_edge(&self, a: N, b: N) -> bool {
        self.edges.contains_key(&edge_key(a, b))
    }

    /// Return an iterator over the nodes of the graph.
    ///
    /// Iterator element type is **N**.
    pub fn nodes<'a>(&'a self) -> Nodes<'a, N>
    {
        Nodes{iter: self.nodes.keys().map(copy)}
    }

    /// Return an iterator over the nodes that are connected with **from** by edges.
    ///
    /// If the node **from** does not exist in the graph, return an empty iterator.
    ///
    /// Iterator element type is **N**.
    pub fn neighbors<'a>(&'a self, from: N) -> Neighbors<'a, N>
    {
        Neighbors{iter:
            match self.nodes.get(&from) {
                Some(neigh) => neigh.iter(),
                None => [].iter(),
            }.map(copy)
        }
    }

    /// Return an iterator over the nodes that are connected with **from** by edges,
    /// paired with the edge weight.
    ///
    /// If the node **from** does not exist in the graph, return an empty iterator.
    ///
    /// Iterator element type is **(N, &'a E)**.
    pub fn edges<'a>(&'a self, from: N) -> Edges<'a, N, E>
    {
        Edges {
            from: from,
            iter: self.neighbors(from),
            edges: &self.edges,
        }
    }

    /// Return a reference to the edge weight connecting **a** with **b**, or
    /// **None** if the edge does not exist in the graph.
    pub fn edge_weight<'a>(&'a self, a: N, b: N) -> Option<&'a E>
    {
        self.edges.get(&edge_key(a, b))
    }

    /// Return a mutable reference to the edge weight connecting **a** with **b**, or
    /// **None** if the edge does not exist in the graph.
    pub fn edge_weight_mut<'a>(&'a mut self, a: N, b: N) -> Option<&'a mut E>
    {
        self.edges.get_mut(&edge_key(a, b))
    }
}

macro_rules! iterator_methods {
    () => (
        #[inline]
        fn next(&mut self) -> Option<<Self as Iterator>::Item>
        {
            self.iter.next()
        }

        #[inline]
        fn size_hint(&self) -> (usize, Option<usize>)
        {
            self.iter.size_hint()
        }
    )
}

pub struct Nodes<'a, N: 'a> {
    iter: Map<Keys<'a, N, Vec<N>>, fn(&N) -> N>,
}

impl<'a, N> Iterator for Nodes<'a, N>
{
    type Item = N;
    iterator_methods!();
}

pub struct Neighbors<'a, N: 'a> {
    iter: Map<Iter<'a, N>, fn(&N) -> N>,
}

impl<'a, N> Iterator for Neighbors<'a, N>
{
    type Item = N;
    iterator_methods!();
}

pub struct Edges<'a, N, E: 'a> where N: 'a + NodeTrait
{
    pub from: N,
    pub edges: &'a HashMap<(N, N), E>,
    pub iter: Neighbors<'a, N>,
}

impl<'a, N, E> Iterator for Edges<'a, N, E>
    where N: 'a + NodeTrait, E: 'a
{
    type Item = (N, &'a E);
    fn next(&mut self) -> Option<(N, &'a E)>
    {
        match self.iter.next() {
            None => None,
            Some(b) => {
                let a = self.from;
                match self.edges.get(&edge_key(a, b)) {
                    None => unreachable!(),
                    Some(edge) => {
                        Some((b, edge))
                    }
                }
            }
        }
    }
}

impl<N, E> Index<(N, N)> for GraphMap<N, E> where N: NodeTrait
{
    type Output = E;
    /// Index **GraphMap** by node pairs to access edge weights.
    fn index(&self, index: &(N, N)) -> &E
    {
        self.edge_weight(index.0, index.1).expect("GraphMap::index: no such edge")
    }
}

impl<N, E> IndexMut<(N, N)> for GraphMap<N, E> where N: NodeTrait
{
    type Output = E;
    /// Index **GraphMap** by node pairs to access edge weights.
    fn index_mut(&mut self, index: &(N, N)) -> &mut E
    {
        self.edge_weight_mut(index.0, index.1).expect("GraphMap::index: no such edge")
    }
}
<|endoftext|>


<commit_before>use std::fmt::{Show,Formatter};
use std::fmt;
use std::hash::Hasher;
use std::hash::sip::SipHasher;
use std::str;

use core::source::{Source, SourceId, GitKind, Location, Remote, Local};
use core::{Package,PackageId,Summary};
use util::{CargoResult, Config, to_hex};
use sources::PathSource;
use sources::git::utils::{GitReference,GitRemote,Master,Other};

/* TODO: Refactor GitSource to delegate to a PathSource
 */
pub struct GitSource<'a, 'b> {
    remote: GitRemote,
    reference: GitReference,
    db_path: Path,
    checkout_path: Path,
    path_source: PathSource,
    config: &'a mut Config<'b>
}

impl<'a, 'b> GitSource<'a, 'b> {
    pub fn new<'a, 'b>(source_id: &SourceId, config: &'a mut Config<'b>) -> GitSource<'a, 'b> {
        assert!(source_id.is_git(), "id is not git, id={}", source_id);

        let reference = match source_id.kind {
            GitKind(ref reference) => reference,
            _ => fail!("Not a git source; id={}", source_id)
        };

        let remote = GitRemote::new(source_id.get_location());
        let ident = ident(source_id.get_location());

        let db_path = config.git_db_path()
            .join(ident.as_slice());

        let checkout_path = config.git_checkout_path()
            .join(ident.as_slice()).join(reference.as_slice());

        let path_source = PathSource::new(&checkout_path, source_id);

        GitSource {
            remote: remote,
            reference: GitReference::for_str(reference.as_slice()),
            db_path: db_path,
            checkout_path: checkout_path,
            path_source: path_source,
            config: config
        }
    }

    pub fn get_namespace<'a>(&'a self) -> &'a Location {
        self.remote.get_location()
    }
}

fn ident(location: &Location) -> String {
    let hasher = SipHasher::new_with_keys(0,0);

    // FIXME: this really should be able to not use to_str() everywhere, but the
    //        compiler seems to currently ask for static lifetimes spuriously.
    //        Perhaps related to rust-lang/rust#15144
    let ident = match *location {
        Local(ref path) => {
            let last = path.components().last().unwrap();
            str::from_utf8(last).unwrap().to_str()
        }
        Remote(ref url) => url.path.as_slice().split('/').last().unwrap().to_str()
    };

    let ident = if ident.as_slice() == "" {
        "_empty".to_string()
    } else {
        ident
    };

    format!("{}-{}", ident, to_hex(hasher.hash(&location.to_str())))
}

impl<'a, 'b> Show for GitSource<'a, 'b> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        try!(write!(f, "git repo at {}", self.remote.get_location()));

        match self.reference {
            Master => Ok(()),
            Other(ref reference) => write!(f, " ({})", reference)
        }
    }
}

impl<'a, 'b> Source for GitSource<'a, 'b> {
    fn update(&mut self) -> CargoResult<()> {
        let should_update = self.config.update_remotes() || {
            !self.remote.has_ref(&self.db_path, self.reference.as_slice()).is_ok()
        };

        let repo = if should_update {
            try!(self.config.shell().status("Updating",
                format!("git repository `{}`", self.remote.get_location())));

            log!(5, "updating git source `{}`", self.remote);
            try!(self.remote.checkout(&self.db_path))
        } else {
            self.remote.db_at(&self.db_path)
        };

        try!(repo.copy_to(self.reference.as_slice(), &self.checkout_path));

        self.path_source.update()
    }

    fn list(&self) -> CargoResult<Vec<Summary>> {
        self.path_source.list()
    }

    fn download(&self, _: &[PackageId]) -> CargoResult<()> {
        // TODO: assert! that the PackageId is contained by the source
        Ok(())
    }

    fn get(&self, ids: &[PackageId]) -> CargoResult<Vec<Package>> {
        log!(5, "getting packages for package ids `{}` from `{}`", ids, self.remote);
        self.path_source.get(ids)
    }

    fn fingerprint(&self, _pkg: &Package) -> CargoResult<String> {
        let db = self.remote.db_at(&self.db_path);
        db.rev_for(self.reference.as_slice())
    }
}

#[cfg(test)]
mod test {
    use url;
    use url::Url;
    use core::source::Remote;
    use super::ident;

    #[test]
    pub fn test_url_to_path_ident_with_path() {
        let ident = ident(&Remote(url("https://github.com/carlhuda/cargo")));
        assert_eq!(ident.as_slice(), "cargo-0eed735c8ffd7c88");
    }

    #[test]
    pub fn test_url_to_path_ident_without_path() {
        let ident = ident(&Remote(url("https://github.com")));
        assert_eq!(ident.as_slice(), "_empty-fc065c9b6b16fc00");
    }

    fn url(s: &str) -> Url {
        url::from_str(s).unwrap()
    }
}
<commit_msg>auto merge of #90 : brson/cargo/fix, r=alexcrichton<commit_after>use std::fmt::{Show,Formatter};
use std::fmt;
use std::hash::Hasher;
use std::hash::sip::SipHasher;
use std::str;

use core::source::{Source, SourceId, GitKind, Location, Remote, Local};
use core::{Package,PackageId,Summary};
use util::{CargoResult, Config, to_hex};
use sources::PathSource;
use sources::git::utils::{GitReference,GitRemote,Master,Other};

/* TODO: Refactor GitSource to delegate to a PathSource
 */
pub struct GitSource<'a, 'b> {
    remote: GitRemote,
    reference: GitReference,
    db_path: Path,
    checkout_path: Path,
    path_source: PathSource,
    config: &'a mut Config<'b>
}

impl<'a, 'b> GitSource<'a, 'b> {
    pub fn new<'a, 'b>(source_id: &SourceId, config: &'a mut Config<'b>) -> GitSource<'a, 'b> {
        assert!(source_id.is_git(), "id is not git, id={}", source_id);

        let reference = match source_id.kind {
            GitKind(ref reference) => reference,
            _ => fail!("Not a git source; id={}", source_id)
        };

        let remote = GitRemote::new(source_id.get_location());
        let ident = ident(source_id.get_location());

        let db_path = config.git_db_path()
            .join(ident.as_slice());

        let checkout_path = config.git_checkout_path()
            .join(ident.as_slice()).join(reference.as_slice());

        let path_source = PathSource::new(&checkout_path, source_id);

        GitSource {
            remote: remote,
            reference: GitReference::for_str(reference.as_slice()),
            db_path: db_path,
            checkout_path: checkout_path,
            path_source: path_source,
            config: config
        }
    }

    pub fn get_namespace<'a>(&'a self) -> &'a Location {
        self.remote.get_location()
    }
}

fn ident(location: &Location) -> String {
    let hasher = SipHasher::new_with_keys(0,0);

    // FIXME: this really should be able to not use to_str() everywhere, but the
    //        compiler seems to currently ask for static lifetimes spuriously.
    //        Perhaps related to rust-lang/rust#15144
    let ident = match *location {
        Local(ref path) => {
            let last = path.components().last().unwrap();
            str::from_utf8(last).unwrap().to_str()
        }
        Remote(ref url) => {
            let path = canonicalize_url(url.path.as_slice());
            path.as_slice().split('/').last().unwrap().to_str()
        }
    };

    let ident = if ident.as_slice() == "" {
        "_empty".to_string()
    } else {
        ident
    };

    let location = canonicalize_url(location.to_str().as_slice());

    format!("{}-{}", ident, to_hex(hasher.hash(&location.as_slice())))
}

fn strip_trailing_slash<'a>(path: &'a str) -> &'a str {
    // Remove the trailing '/' so that 'split' doesn't give us
    // an empty string, making '../foo/' and '../foo' both
    // result in the name 'foo' (#84)
    if path.as_bytes().last() != Some(&('/' as u8)) {
        path.clone()
    } else {
        path.slice(0, path.len() - 1)
    }
}

// Some hacks and heuristics for making equivalent URLs hash the same
fn canonicalize_url(url: &str) -> String {
    let url = strip_trailing_slash(url);

    // HACKHACK: For github URL's specifically just lowercase
    // everything.  GitHub traits both the same, but they hash
    // differently, and we're gonna be hashing them. This wants a more
    // general solution, and also we're almost certainly not using the
    // same case conversion rules that GitHub does. (#84)

    let lower_url = url.chars().map(|c|c.to_lowercase()).collect::<String>();
    let url = if lower_url.as_slice().contains("github.com") {
        lower_url
    } else {
        url.to_string()
    };

    // Repos generally can be accessed with or w/o '.git'
    let url = if !url.as_slice().ends_with(".git") {
        url
    } else {
        url.as_slice().slice(0, url.len() - 4).to_string()
    };

    return url;
}

impl<'a, 'b> Show for GitSource<'a, 'b> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        try!(write!(f, "git repo at {}", self.remote.get_location()));

        match self.reference {
            Master => Ok(()),
            Other(ref reference) => write!(f, " ({})", reference)
        }
    }
}

impl<'a, 'b> Source for GitSource<'a, 'b> {
    fn update(&mut self) -> CargoResult<()> {
        let should_update = self.config.update_remotes() || {
            !self.remote.has_ref(&self.db_path, self.reference.as_slice()).is_ok()
        };

        let repo = if should_update {
            try!(self.config.shell().status("Updating",
                format!("git repository `{}`", self.remote.get_location())));

            log!(5, "updating git source `{}`", self.remote);
            try!(self.remote.checkout(&self.db_path))
        } else {
            self.remote.db_at(&self.db_path)
        };

        try!(repo.copy_to(self.reference.as_slice(), &self.checkout_path));

        self.path_source.update()
    }

    fn list(&self) -> CargoResult<Vec<Summary>> {
        self.path_source.list()
    }

    fn download(&self, _: &[PackageId]) -> CargoResult<()> {
        // TODO: assert! that the PackageId is contained by the source
        Ok(())
    }

    fn get(&self, ids: &[PackageId]) -> CargoResult<Vec<Package>> {
        log!(5, "getting packages for package ids `{}` from `{}`", ids, self.remote);
        self.path_source.get(ids)
    }

    fn fingerprint(&self, _pkg: &Package) -> CargoResult<String> {
        let db = self.remote.db_at(&self.db_path);
        db.rev_for(self.reference.as_slice())
    }
}

#[cfg(test)]
mod test {
    use url;
    use url::Url;
    use core::source::Remote;
    use super::ident;

    #[test]
    pub fn test_url_to_path_ident_with_path() {
        let ident = ident(&Remote(url("https://github.com/carlhuda/cargo")));
        assert_eq!(ident.as_slice(), "cargo-0eed735c8ffd7c88");
    }

    #[test]
    pub fn test_url_to_path_ident_without_path() {
        let ident = ident(&Remote(url("https://github.com")));
        assert_eq!(ident.as_slice(), "_empty-fc065c9b6b16fc00");
    }

    #[test]
    fn test_canonicalize_idents_by_stripping_trailing_url_slash() {
        let ident1 = ident(&Remote(url("https://github.com/PistonDevelopers/piston/")));
        let ident2 = ident(&Remote(url("https://github.com/PistonDevelopers/piston")));
        assert_eq!(ident1, ident2);
    }

    #[test]
    fn test_canonicalize_idents_by_lowercasing_github_urls() {
        let ident1 = ident(&Remote(url("https://github.com/PistonDevelopers/piston")));
        let ident2 = ident(&Remote(url("https://github.com/pistondevelopers/piston")));
        assert_eq!(ident1, ident2);
    }

    #[test]
    fn test_canonicalize_idents_by_stripping_dot_git() {
        let ident1 = ident(&Remote(url("https://github.com/PistonDevelopers/piston")));
        let ident2 = ident(&Remote(url("https://github.com/PistonDevelopers/piston.git")));
        assert_eq!(ident1, ident2);
    }

    fn url(s: &str) -> Url {
        url::from_str(s).unwrap()
    }
}
<|endoftext|>


<commit_before>//! `libproc` module provides library methods for getting various types of
//! information about running processes.
//!
//! In the future there will probably be a shorter list of public
//! modules implementing a cleaner and reduced API - built on these
//! methods.
//!

/// Get basic information about processes by PID
pub mod proc_pid;
/// Read from the Kernel Message buffer
#[cfg(target_os = "macos")]
pub mod kmesg_buffer;
/// Information about Work Queues - very MacOS specific
pub mod work_queue_info;
/// Information abou tThreads runing inside processes
pub mod thread_info;
/// Information about Tasks - very MacOS specific
pub mod task_info;
/// BSD specific information - very MacOS specific
pub mod bsd_info;
#[cfg(target_os = "macos")]
/// Information about Process Resource Usage
pub mod pid_rusage;
/// Information about Files and File Descriptors used by processes
#[cfg(target_os = "macos")]
pub mod file_info;

/// Information about Network usage by a process
#[cfg(target_os = "macos")]
pub mod net_info;

mod helpers;<commit_msg>Fix typo<commit_after>//! `libproc` module provides library methods for getting various types of
//! information about running processes.
//!
//! In the future there will probably be a shorter list of public
//! modules implementing a cleaner and reduced API - built on these
//! methods.
//!

/// Get basic information about processes by PID
pub mod proc_pid;
/// Read from the Kernel Message buffer
#[cfg(target_os = "macos")]
pub mod kmesg_buffer;
/// Information about Work Queues - very MacOS specific
pub mod work_queue_info;
/// Information about Threads runing inside processes
pub mod thread_info;
/// Information about Tasks - very MacOS specific
pub mod task_info;
/// BSD specific information - very MacOS specific
pub mod bsd_info;
#[cfg(target_os = "macos")]
/// Information about Process Resource Usage
pub mod pid_rusage;
/// Information about Files and File Descriptors used by processes
#[cfg(target_os = "macos")]
pub mod file_info;

/// Information about Network usage by a process
#[cfg(target_os = "macos")]
pub mod net_info;

mod helpers;<|endoftext|>


<commit_before>// Copyright 2015 Deyan Ginev. See the LICENSE
// file at the top-level directory of this distribution.
//
// Licensed under the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed
// except according to those terms.
extern crate glob;
extern crate Archive;

use glob::glob;
// use regex::Regex;
use Archive::*;
use std::path::Path;
use std::path::PathBuf;
use std::fs;
use std::env;
use std::io::Error;
use backend::{Backend};
use data::{Task, TaskStatus, Corpus};

// Only initialize auxiliary resources once and keep them in a Importer struct

/// Given a corpus specification, the Importer traverses the filesystem and records each found entry
/// in the Task store, as a NoProblem Task for the "import" service
pub struct Importer {
  pub corpus : Corpus,
  pub backend : Backend,
  pub cwd : PathBuf
}
impl Default for Importer {
  fn default() -> Importer {
    let default_backend = Backend::default();
    Importer {
      corpus : default_backend.add(
        Corpus {
          id: None,
          path : ".".to_string(),
          name : "default".to_string(),
          complex : false }).unwrap(),
      backend : default_backend,
      cwd : Importer::cwd()
    }
  }
}

impl Importer {
  pub fn cwd() -> PathBuf {
    env::current_dir().unwrap()
  }
  pub fn unpack(&self) -> Result<(),()> {
    try!(self.unpack_arxiv_top());
    try!(self.unpack_arxiv_months());
    Ok(())
  }
  pub fn unpack_arxiv_top(&self) -> Result<(),()> {
    // println!("Greetings from unpack_arxiv_top");
    let path_str = self.corpus.path.clone();
    let tars_path = path_str.to_string() + "/*.tar";
    for entry in glob(&tars_path).unwrap() {
      match entry {
        Ok(path) => {
          // let base_name = path.file_stem().unwrap().to_str().unwrap();
          // If we wanted fine-grained control, we could infer the dir name:
          // let arxiv_name_re = Regex::new(r"arXiv_src_(\d+)_").unwrap();
          // let captures = arxiv_name_re.captures(base_name).unwrap();
          // let unpack_dirname = match captures.at(1) {
          //   Some(month) => month,
          //   None => base_name
          // };
          // --- but not for now

          // Let's open the tar file and unpack it:
          let archive_reader = Reader::new().unwrap()
            .support_filter_all()
            .support_format_all()
            .open_filename(path.to_str().unwrap(), 10240).unwrap();
          loop {
            match archive_reader.next_header() {
              Ok(e) => {
                let full_extract_path = path_str.to_string() + &e.pathname();
                match fs::metadata(full_extract_path.clone()) {
                  Ok(_) => println!("File {:?} exists, won't unpack.", e.pathname()),
                  Err(_) => {
                    println!("To unpack: {:?}", full_extract_path);
                    e.extract_to(&full_extract_path, Vec::new()).unwrap();
                  }
                }
              },
              Err(_) => { break }
            }
          }
        },
        Err(e) => {println!("Failed tar glob: {:?}", e)}
      }
    }
    Ok(())
  }
  pub fn unpack_arxiv_months(&self) -> Result<(),()> {
    // println!("Greetings from unpack_arxiv_months");
    let path_str = self.corpus.path.clone();
    let gzs_path = path_str.to_string() + "/*/*.gz";
    for entry in glob(&gzs_path).unwrap() {
      match entry {
        Ok(path) => {
          let entry_path = path.to_str().unwrap();
          let entry_dir = path.parent().unwrap().to_str().unwrap();
          let base_name = path.file_stem().unwrap().to_str().unwrap();
          let entry_cp_dir = entry_dir.to_string() + "/" + base_name;
          fs::create_dir_all(entry_cp_dir.clone()).unwrap_or_else( |reason| {
            println!("Failed to mkdir -p {:?} because: {:?}", entry_cp_dir.clone(), reason.kind());
          });
          // Careful here, some of arXiv's .gz files are really plain-text TeX files (surprise!!!)
          let archive_reader_new = Reader::new().unwrap()
            .support_filter_all()
            .support_format_all()
            .open_filename(entry_path, 10240);
          // We'll write out a ZIP file for each entry
          let full_extract_path = entry_cp_dir.to_string() + "/" + base_name + ".zip";
          let mut archive_writer_new = Writer::new().unwrap()
            //.add_filter(ArchiveFilter::Lzip)
            .set_compression(ArchiveFilter::None)
            .set_format(ArchiveFormat::Zip);
          archive_writer_new.open_filename(&full_extract_path.clone()).unwrap();

          match archive_reader_new {
            Err(_) => {
              let raw_reader_new = Reader::new().unwrap()
                .support_filter_all()
                .support_format_raw()
                .open_filename(entry_path, 10240);
              match raw_reader_new {
                Ok(raw_reader) => {
                  match raw_reader.next_header() {
                    Ok(_) => {
                      let tex_target = base_name.to_string() + ".tex";
                      // In a "raw" read, we don't know the data size in advance. So we bite the bullet and
                      // read the usually tiny tex file in memory, obtaining a size estimate
                      let mut raw_data = Vec::new();
                      loop {
                        let chunk_data = raw_reader.read_data(10240);
                        match chunk_data {
                          Ok(chunk) => raw_data.extend(chunk.into_iter()),
                          Err(_) => {break}
                        };
                      }
                      match archive_writer_new.write_header_new(&tex_target,raw_data.len() as i64) {
                        Ok(_) => {},
                        Err(e) => {
                          println!("Couldn't write header: {:?}", e);
                          break;
                        }
                      }
                      archive_writer_new.write_data(raw_data).unwrap();
                    },
                    Err(_) => println!("No content in archive: {:?}", entry_path)
                  }
                },
                Err(_) => println!("Unrecognizeable archive: {:?}", entry_path)
              }
            },
            Ok(archive_reader) => {
              loop {
                match archive_reader.next_header() {
                  Ok(e) => {
                    archive_writer_new.write_header(e).unwrap();
                    loop {
                      let entry_data = archive_reader.read_data(10240);
                      match entry_data {
                        Ok(chunk) => { archive_writer_new.write_data(chunk).unwrap(); },
                        Err(_) => { break; }
                      };
                    }
                  },
                  Err(_) => { break; }
                }
              }
            }
          }
          // Done with this .gz , remove it:
          match fs::remove_file(path.clone()) {
            Ok(_) => {},
            Err(e) => println!("Can't remove source .gz: {:?}", e)
          };
        },
        Err(e) => println!("Failed gz glob: {:?}", e)
      }
    }
    Ok(())
  }

  pub fn walk_import<'walk>(&self) -> Result<(),Error> {
    let import_extension = if self.corpus.complex { "zip" } else { "tex" };
    let mut walk_q : Vec<PathBuf> = vec![Path::new(&self.corpus.path).to_owned()];
    let mut import_q : Vec<Task> = Vec::new();
    let mut import_counter = 0;
    while walk_q.len() > 0 {
      let current_path = walk_q.pop().unwrap();
      // println!("-- current path {:?}", current_path);
      let current_metadata = try!(fs::metadata(current_path.clone()));
      if current_metadata.is_dir() { // Ignore files
        // First, test if we just found an entry:
        let current_local_dir = current_path.file_name().unwrap();
        let current_entry = current_local_dir.to_str().unwrap().to_string() + "." + import_extension;
        let current_entry_path = current_path.to_str().unwrap().to_string() + "/" + &current_entry;
        match fs::metadata(current_entry_path.clone()) {
          Ok(_) => {
            // Found the expected file, import this entry:
            println!("Found entry: {:?}", current_entry_path);
            import_counter += 1;
            import_q.push(self.new_task(current_entry_path));
            if import_q.len() >= 1000 {
              // Flush the import queue to backend:
              self.backend.mark_imported(&import_q).unwrap(); // TODO: Proper Error-handling
              import_q.clear();
            }
          },
          Err(_) => {
            //  No such entry found, traversing into the directory:
            for subentry in try!(fs::read_dir(current_path.clone())) {
              let subentry = try!(subentry);
              walk_q.push(subentry.path());
            }
          }
        }
      }
    }
    if !import_q.is_empty() {
      self.backend.mark_imported(&import_q).unwrap();} // TODO: Proper Error-handling
    println!("--- Imported {:?} entries.", import_counter);
    Ok(())
  }

  /// Create a new NoProblem task for the "import" service and the Importer-specified corpus
  pub fn new_task(&self, entry : String) -> Task {
    let abs_entry : String = if Path::new(&entry).is_relative() {
      let mut new_abs = self.cwd.clone();
      new_abs.push(&entry);
      new_abs.to_str().unwrap().to_string()
    } else {
      entry.clone()
    };

    Task {id: None, entry : abs_entry, status : TaskStatus::NoProblem.raw(), corpusid : self.corpus.id.unwrap(), serviceid: 2}
  }

  pub fn process(&self) -> Result<(),()> {
    // println!("Greetings from the import processor");
    if self.corpus.complex { // Complex setup has an unpack step:
      self.unpack().unwrap(); }
    // Walk the directory tree and import the files in the TaskDB:
    self.walk_import().unwrap();

    Ok(())
  }
}

<commit_msg>robustly survive broken ZIP headers<commit_after>// Copyright 2015 Deyan Ginev. See the LICENSE
// file at the top-level directory of this distribution.
//
// Licensed under the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed
// except according to those terms.
extern crate glob;
extern crate Archive;

use glob::glob;
// use regex::Regex;
use Archive::*;
use std::path::Path;
use std::path::PathBuf;
use std::fs;
use std::env;
use std::io::Error;
use backend::{Backend};
use data::{Task, TaskStatus, Corpus};

// Only initialize auxiliary resources once and keep them in a Importer struct

/// Given a corpus specification, the Importer traverses the filesystem and records each found entry
/// in the Task store, as a NoProblem Task for the "import" service
pub struct Importer {
  pub corpus : Corpus,
  pub backend : Backend,
  pub cwd : PathBuf
}
impl Default for Importer {
  fn default() -> Importer {
    let default_backend = Backend::default();
    Importer {
      corpus : default_backend.add(
        Corpus {
          id: None,
          path : ".".to_string(),
          name : "default".to_string(),
          complex : false }).unwrap(),
      backend : default_backend,
      cwd : Importer::cwd()
    }
  }
}

impl Importer {
  pub fn cwd() -> PathBuf {
    env::current_dir().unwrap()
  }
  pub fn unpack(&self) -> Result<(),()> {
    try!(self.unpack_arxiv_top());
    try!(self.unpack_arxiv_months());
    Ok(())
  }
  pub fn unpack_arxiv_top(&self) -> Result<(),()> {
    println!("-- Starting top-level unpack process");
    let path_str = self.corpus.path.clone();
    let tars_path = path_str.to_string() + "/*.tar";
    for entry in glob(&tars_path).unwrap() {
      match entry {
        Ok(path) => {
          // let base_name = path.file_stem().unwrap().to_str().unwrap();
          // If we wanted fine-grained control, we could infer the dir name:
          // let arxiv_name_re = Regex::new(r"arXiv_src_(\d+)_").unwrap();
          // let captures = arxiv_name_re.captures(base_name).unwrap();
          // let unpack_dirname = match captures.at(1) {
          //   Some(month) => month,
          //   None => base_name
          // };
          // --- but not for now

          // Let's open the tar file and unpack it:
          let archive_reader = Reader::new().unwrap()
            .support_filter_all()
            .support_format_all()
            .open_filename(path.to_str().unwrap(), 10240).unwrap();
          loop {
            match archive_reader.next_header() {
              Ok(e) => {
                let full_extract_path = path_str.to_string() + &e.pathname();
                match fs::metadata(full_extract_path.clone()) {
                  Ok(_) => println!("File {:?} exists, won't unpack.", e.pathname()),
                  Err(_) => {
                    println!("To unpack: {:?}", full_extract_path);
                    match e.extract_to(&full_extract_path, Vec::new()) {
                      Ok(_) => {},
                      _ => {
                        println!("Failed to extract {:?}", full_extract_path);
                      }
                    }
                  }
                }
              },
              Err(_) => { break }
            }
          }
        },
        Err(e) => {println!("Failed tar glob: {:?}", e)}
      }
    }
    Ok(())
  }
  pub fn unpack_arxiv_months(&self) -> Result<(),()> {
    println!("-- Starting to unpack monthly .gz archives");
    let path_str = self.corpus.path.clone();
    let gzs_path = path_str.to_string() + "/*/*.gz";
    for entry in glob(&gzs_path).unwrap() {
      match entry {
        Ok(path) => {
          let entry_path = path.to_str().unwrap();
          let entry_dir = path.parent().unwrap().to_str().unwrap();
          let base_name = path.file_stem().unwrap().to_str().unwrap();
          let entry_cp_dir = entry_dir.to_string() + "/" + base_name;
          fs::create_dir_all(entry_cp_dir.clone()).unwrap_or_else( |reason| {
            println!("Failed to mkdir -p {:?} because: {:?}", entry_cp_dir.clone(), reason.kind());
          });
          // Careful here, some of arXiv's .gz files are really plain-text TeX files (surprise!!!)
          let archive_reader_new = Reader::new().unwrap()
            .support_filter_all()
            .support_format_all()
            .open_filename(entry_path, 10240);
          // We'll write out a ZIP file for each entry
          let full_extract_path = entry_cp_dir.to_string() + "/" + base_name + ".zip";
          let mut archive_writer_new = Writer::new().unwrap()
            //.add_filter(ArchiveFilter::Lzip)
            .set_compression(ArchiveFilter::None)
            .set_format(ArchiveFormat::Zip);
          archive_writer_new.open_filename(&full_extract_path.clone()).unwrap();

          match archive_reader_new {
            Err(_) => {
              let raw_reader_new = Reader::new().unwrap()
                .support_filter_all()
                .support_format_raw()
                .open_filename(entry_path, 10240);
              match raw_reader_new {
                Ok(raw_reader) => {
                  match raw_reader.next_header() {
                    Ok(_) => {
                      let tex_target = base_name.to_string() + ".tex";
                      // In a "raw" read, we don't know the data size in advance. So we bite the bullet and
                      // read the usually tiny tex file in memory, obtaining a size estimate
                      let mut raw_data = Vec::new();
                      loop {
                        let chunk_data = raw_reader.read_data(10240);
                        match chunk_data {
                          Ok(chunk) => raw_data.extend(chunk.into_iter()),
                          Err(_) => {break}
                        };
                      }
                      match archive_writer_new.write_header_new(&tex_target,raw_data.len() as i64) {
                        Ok(_) => {},
                        Err(e) => {
                          println!("Couldn't write header: {:?}", e);
                          break;
                        }
                      }
                      match archive_writer_new.write_data(raw_data) {
                        Ok(_) => {},
                        Err(e) => println!("Failed to write data to {:?} because {:?}", tex_target.clone(), e)
                      };
                    },
                    Err(_) => println!("No content in archive: {:?}", entry_path)
                  }
                },
                Err(_) => println!("Unrecognizeable archive: {:?}", entry_path)
              }
            },
            Ok(archive_reader) => {
              loop {
                match archive_reader.next_header() {
                  Ok(e) => {
                    match archive_writer_new.write_header(e) {
                      Ok(_) => {},
                      _ => {} // TODO: If we need to print an error message, we can do so later.
                    };
                    loop {
                      let entry_data = archive_reader.read_data(10240);
                      match entry_data {
                        Ok(chunk) => { archive_writer_new.write_data(chunk).unwrap(); },
                        Err(_) => { break; }
                      };
                    }
                  },
                  Err(_) => { break; }
                }
              }
            }
          }
          // Done with this .gz , remove it:
          match fs::remove_file(path.clone()) {
            Ok(_) => {},
            Err(e) => println!("Can't remove source .gz: {:?}", e)
          };
        },
        Err(e) => println!("Failed gz glob: {:?}", e)
      }
    }
    Ok(())
  }

  pub fn walk_import<'walk>(&self) -> Result<(),Error> {
    println!("-- Starting import walk");
    let import_extension = if self.corpus.complex { "zip" } else { "tex" };
    let mut walk_q : Vec<PathBuf> = vec![Path::new(&self.corpus.path).to_owned()];
    let mut import_q : Vec<Task> = Vec::new();
    let mut import_counter = 0;
    while walk_q.len() > 0 {
      let current_path = walk_q.pop().unwrap();
      // println!("-- current path {:?}", current_path);
      let current_metadata = try!(fs::metadata(current_path.clone()));
      if current_metadata.is_dir() { // Ignore files
        // First, test if we just found an entry:
        let current_local_dir = current_path.file_name().unwrap();
        let current_entry = current_local_dir.to_str().unwrap().to_string() + "." + import_extension;
        let current_entry_path = current_path.to_str().unwrap().to_string() + "/" + &current_entry;
        match fs::metadata(current_entry_path.clone()) {
          Ok(_) => {
            // Found the expected file, import this entry:
            println!("Found entry: {:?}", current_entry_path);
            import_counter += 1;
            import_q.push(self.new_task(current_entry_path));
            if import_q.len() >= 1000 {
              // Flush the import queue to backend:
              self.backend.mark_imported(&import_q).unwrap(); // TODO: Proper Error-handling
              import_q.clear();
            }
          },
          Err(_) => {
            //  No such entry found, traversing into the directory:
            for subentry in try!(fs::read_dir(current_path.clone())) {
              let subentry = try!(subentry);
              walk_q.push(subentry.path());
            }
          }
        }
      }
    }
    if !import_q.is_empty() {
      self.backend.mark_imported(&import_q).unwrap();} // TODO: Proper Error-handling
    println!("--- Imported {:?} entries.", import_counter);
    Ok(())
  }

  /// Create a new NoProblem task for the "import" service and the Importer-specified corpus
  pub fn new_task(&self, entry : String) -> Task {
    let abs_entry : String = if Path::new(&entry).is_relative() {
      let mut new_abs = self.cwd.clone();
      new_abs.push(&entry);
      new_abs.to_str().unwrap().to_string()
    } else {
      entry.clone()
    };

    Task {id: None, entry : abs_entry, status : TaskStatus::NoProblem.raw(), corpusid : self.corpus.id.unwrap(), serviceid: 2}
  }

  pub fn process(&self) -> Result<(),()> {
    // println!("Greetings from the import processor");
    if self.corpus.complex { // Complex setup has an unpack step:
      self.unpack().unwrap(); }
    // Walk the directory tree and import the files in the TaskDB:
    self.walk_import().unwrap();

    Ok(())
  }
}

<|endoftext|>


<commit_before>use Queriable;
use db_result::DbResult;
use types::{NativeSqlType, FromSqlRow};

use std::marker::PhantomData;

pub struct Cursor<ST, T> {
    current_row: usize,
    db_result: DbResult,
    _marker: PhantomData<(ST, T)>,
}

impl<ST, T> Cursor<ST, T> {
    pub fn new(db_result: DbResult) -> Self {
        Cursor {
            current_row: 0,
            db_result: db_result,
            _marker: PhantomData,
        }
    }
}

impl<ST, T> Iterator for Cursor<ST, T> where
    ST: NativeSqlType,
    T: Queriable<ST>,
{
    type Item = T;

    fn next(&mut self) -> Option<T> {
        if self.current_row >= self.db_result.num_rows() {
            None
        } else {
            let mut row = self.db_result.get_row(self.current_row);
            self.current_row += 1;
            let values = match T::Row::build_from_row(&mut row) {
                Ok(value) => value,
                Err(reason) => panic!("Error reading values {}", reason.description()),
            };
            let result = T::build(values);
            Some(result)
        }
    }
}
<commit_msg>Add a short description of `Cursor`, hide internal functions<commit_after>use Queriable;
use db_result::DbResult;
use types::{NativeSqlType, FromSqlRow};

use std::marker::PhantomData;

/// The type returned by various [`Connection`](struct.Connection.html) methods.
/// Acts as an iterator over `T`.
pub struct Cursor<ST, T> {
    current_row: usize,
    db_result: DbResult,
    _marker: PhantomData<(ST, T)>,
}

impl<ST, T> Cursor<ST, T> {
    #[doc(hidden)]
    pub fn new(db_result: DbResult) -> Self {
        Cursor {
            current_row: 0,
            db_result: db_result,
            _marker: PhantomData,
        }
    }
}

impl<ST, T> Iterator for Cursor<ST, T> where
    ST: NativeSqlType,
    T: Queriable<ST>,
{
    type Item = T;

    fn next(&mut self) -> Option<T> {
        if self.current_row >= self.db_result.num_rows() {
            None
        } else {
            let mut row = self.db_result.get_row(self.current_row);
            self.current_row += 1;
            let values = match T::Row::build_from_row(&mut row) {
                Ok(value) => value,
                Err(reason) => panic!("Error reading values {}", reason.description()),
            };
            let result = T::build(values);
            Some(result)
        }
    }
}
<|endoftext|>