<commit_before>

use super::{NoCrate, MetaData, duration_to_str, match_version, render_markdown};
use super::page::Page;
use db::connect_db;
use iron::prelude::*;
use iron::status;
use std::collections::BTreeMap;
use time;
use rustc_serialize::json::{Json, ToJson};
use router::Router;
use postgres::Connection;
use semver;

// TODO: Add target name and versions

#[derive(Debug)]
struct CrateDetails {
    name: String,
    version: String,
    description: Option<String>,
    authors: Vec<(String, String)>,
    authors_json: Option<Json>,
    dependencies: Option<Json>,
    readme: Option<String>,
    rustdoc: Option<String>, // this is description_long in database
    release_time: time::Timespec,
    build_status: bool,
    rustdoc_status: bool,
    repository_url: Option<String>,
    homepage_url: Option<String>,
    keywords: Option<Json>,
    have_examples: bool, // need to check this manually
    target_name: Option<String>,
    versions: Vec<String>,
    github: bool, // is crate hosted in github
    github_stars: Option<i32>,
    github_forks: Option<i32>,
    github_issues: Option<i32>,
    metadata: MetaData,
}

impl ToJson for CrateDetails {
    fn to_json(&self) -> Json {
        let mut m: BTreeMap<String, Json> = BTreeMap::new();
        m.insert("name".to_string(), self.name.to_json());
        m.insert("version".to_string(), self.version.to_json());
        m.insert("description".to_string(), self.description.to_json());
        m.insert("authors".to_string(), self.authors.to_json());
        m.insert("authors_json".to_string(), self.authors_json.to_json());
        m.insert("dependencies".to_string(), self.dependencies.to_json());
        if let Some(ref readme) = self.readme {
            m.insert("readme".to_string(), render_markdown(&readme).to_json());
        }
        if let Some(ref rustdoc) = self.rustdoc {
            m.insert("rustdoc".to_string(), render_markdown(&rustdoc).to_json());
        }
        m.insert("release_time".to_string(),
                 duration_to_str(self.release_time).to_json());
        m.insert("build_status".to_string(), self.build_status.to_json());
        m.insert("rustdoc_status".to_string(), self.rustdoc_status.to_json());
        m.insert("repository_url".to_string(), self.repository_url.to_json());
        m.insert("homepage_url".to_string(), self.homepage_url.to_json());
        m.insert("keywords".to_string(), self.keywords.to_json());
        m.insert("have_examples".to_string(), self.have_examples.to_json());
        m.insert("target_name".to_string(), self.target_name.to_json());
        m.insert("versions".to_string(), self.versions.to_json());
        m.insert("github".to_string(), self.github.to_json());
        m.insert("github_stars".to_string(), self.github_stars.to_json());
        m.insert("github_forks".to_string(), self.github_forks.to_json());
        m.insert("github_issues".to_string(), self.github_forks.to_json());
        m.insert("metadata".to_string(), self.metadata.to_json());
        m.to_json()
    }
}

impl CrateDetails {
    fn new(conn: &Connection, name: &str, version: &str) -> Option<CrateDetails> {

        // get all stuff, I love you rustfmt
        let query = "SELECT crates.name, \
                            releases.version, \
                            releases.description, \
                            releases.authors, \
                            releases.dependencies, \
                            releases.readme, \
                            releases.description_long, \
                            releases.release_time, \
                            releases.build_status, \
                            releases.rustdoc_status, \
                            releases.repository_url, \
                            releases.homepage_url, \
                            releases.keywords, \
                            releases.have_examples, \
                            releases.target_name, \
                            crates.versions, \
                            authors.name, \
                            authors.slug, \
                            crates.github_stars, \
                            crates.github_forks, \
                            crates.github_issues \
                     FROM author_rels \
                     LEFT OUTER JOIN authors ON authors.id = author_rels.aid \
                     LEFT OUTER JOIN releases ON releases.id = author_rels.rid \
                     LEFT OUTER JOIN crates ON crates.id = releases.crate_id \
                     WHERE crates.name = $1 AND releases.version = $2;";

        let rows = conn.query(query, &[&name, &version]).unwrap();

        if rows.len() == 0 {
            return None;
        }

        // sort versions with semver
        let versions = {
            let mut versions: Vec<semver::Version> = Vec::new();
            let versions_from_db: Json = rows.get(0).get(15);

            versions_from_db.as_array().map(|vers| {
                for version in vers {
                    version.as_string().map(|version| {
                        if let Ok(sem_ver) = semver::Version::parse(&version) {
                            versions.push(sem_ver);
                        };
                    });
                }
            });

            versions.sort();
            versions.reverse();
            versions.iter().map(|semver| format!("{}", semver)).collect()
        };

        let metadata = MetaData {
            name: rows.get(0).get(0),
            version: rows.get(0).get(1),
            description: rows.get(0).get(2),
            rustdoc_status: rows.get(0).get(9),
            target_name: rows.get(0).get(14),
        };

        let mut crate_details = CrateDetails {
            name: rows.get(0).get(0),
            version: rows.get(0).get(1),
            description: rows.get(0).get(2),
            authors: Vec::new(),
            authors_json: rows.get(0).get(3),
            dependencies: rows.get(0).get(4),
            readme: rows.get(0).get(5),
            rustdoc: rows.get(0).get(6),
            release_time: rows.get(0).get(7),
            build_status: rows.get(0).get(8),
            rustdoc_status: rows.get(0).get(9),
            repository_url: rows.get(0).get(10),
            homepage_url: rows.get(0).get(11),
            keywords: rows.get(0).get(12),
            have_examples: rows.get(0).get(13),
            target_name: rows.get(0).get(14),
            versions: versions,
            github: false,
            github_stars: rows.get(0).get(18),
            github_forks: rows.get(0).get(19),
            github_issues: rows.get(0).get(20),
            metadata: metadata,
        };

        if let Some(repository_url) = crate_details.repository_url.clone() {
            crate_details.github = repository_url.starts_with("http://github.com") ||
                                   repository_url.starts_with("https://github.com");
        }

        // Insert authors with name and slug
        for row in &rows {
            crate_details.authors.push((row.get(16), row.get(17)));
        }

        Some(crate_details)
    }
}

pub fn crate_details_handler(req: &mut Request) -> IronResult<Response> {
    // this handler must always called with a crate name
    let name = req.extensions.get::<Router>().unwrap().find("name").unwrap();
    let req_version = req.extensions.get::<Router>().unwrap().find("version");

    let conn = connect_db().unwrap();

    match_version(&conn, &name, req_version)
        .and_then(|version| CrateDetails::new(&conn, &name, &version))
        .ok_or(IronError::new(NoCrate, status::NotFound))
        .and_then(|details| {
            Page::new(details)
                .set_true("show_package_navigation")
                .set_true("javascript_highlightjs")
                .set_true("package_navigation_crate_tab")
                .to_resp("crate_details")
        })
}
<commit_msg>Fix github issue count<commit_after>

use super::{NoCrate, MetaData, duration_to_str, match_version, render_markdown};
use super::page::Page;
use db::connect_db;
use iron::prelude::*;
use iron::status;
use std::collections::BTreeMap;
use time;
use rustc_serialize::json::{Json, ToJson};
use router::Router;
use postgres::Connection;
use semver;

// TODO: Add target name and versions

#[derive(Debug)]
struct CrateDetails {
    name: String,
    version: String,
    description: Option<String>,
    authors: Vec<(String, String)>,
    authors_json: Option<Json>,
    dependencies: Option<Json>,
    readme: Option<String>,
    rustdoc: Option<String>, // this is description_long in database
    release_time: time::Timespec,
    build_status: bool,
    rustdoc_status: bool,
    repository_url: Option<String>,
    homepage_url: Option<String>,
    keywords: Option<Json>,
    have_examples: bool, // need to check this manually
    target_name: Option<String>,
    versions: Vec<String>,
    github: bool, // is crate hosted in github
    github_stars: Option<i32>,
    github_forks: Option<i32>,
    github_issues: Option<i32>,
    metadata: MetaData,
}

impl ToJson for CrateDetails {
    fn to_json(&self) -> Json {
        let mut m: BTreeMap<String, Json> = BTreeMap::new();
        m.insert("name".to_string(), self.name.to_json());
        m.insert("version".to_string(), self.version.to_json());
        m.insert("description".to_string(), self.description.to_json());
        m.insert("authors".to_string(), self.authors.to_json());
        m.insert("authors_json".to_string(), self.authors_json.to_json());
        m.insert("dependencies".to_string(), self.dependencies.to_json());
        if let Some(ref readme) = self.readme {
            m.insert("readme".to_string(), render_markdown(&readme).to_json());
        }
        if let Some(ref rustdoc) = self.rustdoc {
            m.insert("rustdoc".to_string(), render_markdown(&rustdoc).to_json());
        }
        m.insert("release_time".to_string(),
                 duration_to_str(self.release_time).to_json());
        m.insert("build_status".to_string(), self.build_status.to_json());
        m.insert("rustdoc_status".to_string(), self.rustdoc_status.to_json());
        m.insert("repository_url".to_string(), self.repository_url.to_json());
        m.insert("homepage_url".to_string(), self.homepage_url.to_json());
        m.insert("keywords".to_string(), self.keywords.to_json());
        m.insert("have_examples".to_string(), self.have_examples.to_json());
        m.insert("target_name".to_string(), self.target_name.to_json());
        m.insert("versions".to_string(), self.versions.to_json());
        m.insert("github".to_string(), self.github.to_json());
        m.insert("github_stars".to_string(), self.github_stars.to_json());
        m.insert("github_forks".to_string(), self.github_forks.to_json());
        m.insert("github_issues".to_string(), self.github_issues.to_json());
        m.insert("metadata".to_string(), self.metadata.to_json());
        m.to_json()
    }
}

impl CrateDetails {
    fn new(conn: &Connection, name: &str, version: &str) -> Option<CrateDetails> {

        // get all stuff, I love you rustfmt
        let query = "SELECT crates.name, \
                            releases.version, \
                            releases.description, \
                            releases.authors, \
                            releases.dependencies, \
                            releases.readme, \
                            releases.description_long, \
                            releases.release_time, \
                            releases.build_status, \
                            releases.rustdoc_status, \
                            releases.repository_url, \
                            releases.homepage_url, \
                            releases.keywords, \
                            releases.have_examples, \
                            releases.target_name, \
                            crates.versions, \
                            authors.name, \
                            authors.slug, \
                            crates.github_stars, \
                            crates.github_forks, \
                            crates.github_issues \
                     FROM author_rels \
                     LEFT OUTER JOIN authors ON authors.id = author_rels.aid \
                     LEFT OUTER JOIN releases ON releases.id = author_rels.rid \
                     LEFT OUTER JOIN crates ON crates.id = releases.crate_id \
                     WHERE crates.name = $1 AND releases.version = $2;";

        let rows = conn.query(query, &[&name, &version]).unwrap();

        if rows.len() == 0 {
            return None;
        }

        // sort versions with semver
        let versions = {
            let mut versions: Vec<semver::Version> = Vec::new();
            let versions_from_db: Json = rows.get(0).get(15);

            versions_from_db.as_array().map(|vers| {
                for version in vers {
                    version.as_string().map(|version| {
                        if let Ok(sem_ver) = semver::Version::parse(&version) {
                            versions.push(sem_ver);
                        };
                    });
                }
            });

            versions.sort();
            versions.reverse();
            versions.iter().map(|semver| format!("{}", semver)).collect()
        };

        let metadata = MetaData {
            name: rows.get(0).get(0),
            version: rows.get(0).get(1),
            description: rows.get(0).get(2),
            rustdoc_status: rows.get(0).get(9),
            target_name: rows.get(0).get(14),
        };

        let mut crate_details = CrateDetails {
            name: rows.get(0).get(0),
            version: rows.get(0).get(1),
            description: rows.get(0).get(2),
            authors: Vec::new(),
            authors_json: rows.get(0).get(3),
            dependencies: rows.get(0).get(4),
            readme: rows.get(0).get(5),
            rustdoc: rows.get(0).get(6),
            release_time: rows.get(0).get(7),
            build_status: rows.get(0).get(8),
            rustdoc_status: rows.get(0).get(9),
            repository_url: rows.get(0).get(10),
            homepage_url: rows.get(0).get(11),
            keywords: rows.get(0).get(12),
            have_examples: rows.get(0).get(13),
            target_name: rows.get(0).get(14),
            versions: versions,
            github: false,
            github_stars: rows.get(0).get(18),
            github_forks: rows.get(0).get(19),
            github_issues: rows.get(0).get(20),
            metadata: metadata,
        };

        if let Some(repository_url) = crate_details.repository_url.clone() {
            crate_details.github = repository_url.starts_with("http://github.com") ||
                                   repository_url.starts_with("https://github.com");
        }

        // Insert authors with name and slug
        for row in &rows {
            crate_details.authors.push((row.get(16), row.get(17)));
        }

        Some(crate_details)
    }
}

pub fn crate_details_handler(req: &mut Request) -> IronResult<Response> {
    // this handler must always called with a crate name
    let name = req.extensions.get::<Router>().unwrap().find("name").unwrap();
    let req_version = req.extensions.get::<Router>().unwrap().find("version");

    let conn = connect_db().unwrap();

    match_version(&conn, &name, req_version)
        .and_then(|version| CrateDetails::new(&conn, &name, &version))
        .ok_or(IronError::new(NoCrate, status::NotFound))
        .and_then(|details| {
            Page::new(details)
                .set_true("show_package_navigation")
                .set_true("javascript_highlightjs")
                .set_true("package_navigation_crate_tab")
                .to_resp("crate_details")
        })
}
<|endoftext|>


<commit_before>extern crate collections;
extern crate sync;
#[cfg(test)]
extern crate rand;
use collections::HashMap;
use std::io::{File, Open, Read, Write, TempDir};
use sync::{Arc, RWLock};
#[cfg(test)]
use std::task::spawn;
#[cfg(test)]
use rand::random;
#[cfg(test)]
use rand::task_rng;
#[cfg(test)]
use rand::distributions::{IndependentSample, Range};

struct BufferManager {
	size: uint,
	entries: HashMap<u64, BufferEntry>,
	directory: TempDir,
}

struct BufferEntry {
	frame: Arc<RWLock<BufferFrame>>,
}

struct BufferFrame {
	pageId: u64,
	data: Vec<u8>,
}

/* Destructor trait implementation */
impl Drop for BufferManager {
	fn drop(&mut self) {
		println!("Dropping");
		// TODO
	}
}

impl BufferManager {
	pub fn new(size: uint) -> BufferManager {
		let h = HashMap::with_capacity(size);
		let dir = match TempDir::new("buffermanager") {
			Some(temp_dir) => temp_dir,
			None => fail!("creation of temporary directory"),
		};
		BufferManager {size: size, entries: h, directory: dir}
	}

	fn openOrCreate(&self, pageId: u64) -> File {
		let page_path = self.directory.path();
		let file_path = page_path.join(pageId.to_str());
		match File::open_mode(&file_path, Open, Read) {
			Ok(f) => f,
			Err(e) => {
				match File::open_mode(&file_path, Open, Write) {
					Ok(mut f) => {
						f.write([0_u8, ..4 * 1024]);
						match File::open_mode(&file_path, Open, Read) {
							Ok(f) => f,
							Err(e) => fail!("failed reading file: {}", e),
						}
					},
					Err(e) => fail!("Writing file failed: {}", e),
				}
			},
		}
	}

	fn loadPage(&mut self, pageId: u64) {
		if self.entries.len() == self.size {
			self.evictPage();
		}

		let mut file_handle = self.openOrCreate(pageId);
		let content = match file_handle.read_exact(4*1024) {
			Ok(c) => Vec::from_slice(c),
			Err(e) => fail!("Couldn't read from page: {}", e),
		};

		let frame = BufferFrame {data: content, pageId: pageId};
		let entry = BufferEntry {frame: Arc::new(RWLock::new(frame))};
		self.entries.insert(pageId, entry);
	}

	fn evictPage(&mut self) {
		// TODO delete a random page
		// evicting is hard, let's go shopping
	}

	pub fn fixPage(&mut self, pageId: u64, exclusive: bool) -> Option<Arc<RWLock<BufferFrame>>> {
		// TODO
		if !self.entries.contains_key(&pageId) {
			self.loadPage(pageId);
		}
		let entry = self.entries.get(&pageId);
		// Arcs can be cloned and they will all point to the same RWLock
		Some(entry.frame.clone())
	}

	pub fn unfixPage(&mut self, frame: Arc<RWLock<BufferFrame>>, isDirty: bool) {
		if !isDirty {
			return;
		}
		let frame = frame.read();
		self.writePage(frame.pageId, frame.get_data());
	}

	fn writePage(&mut self, pageId: u64, data: &[u8]) {
		// TODO: write page back to disk
		println!("Writing {}", data);
	}
}

/*
 * A buffer frame, the unit that gets the data
 */
impl BufferFrame {
	/*
	 * get_mut_data returns a borrowed reference to a mutable slice to the vector
	 * contents.
	 */
	pub fn get_mut_data<'a>(&'a mut self) -> &'a mut [u8] {
		self.data.as_mut_slice()
	}
	pub fn get_data<'a>(&'a self) -> &'a [u8] {
		self.data.as_slice()
	}
}

#[test]
fn test_create() {
	let mut bm = BufferManager::new(16);
	let pageref = match bm.fixPage(42, false) {
		Some(p) => p,
		None => fail!("Getting page failed"),
	};
	{
		let mut page = pageref.write();
		let data = page.get_mut_data();
		data[0] = 42;
		println!("data: {}", Vec::from_slice(data));
	}
	bm.unfixPage(pageref, true);
	fail!("always");
}

#[test]
fn test_threads() {
	let pages_in_ram = 20;
	let pages_on_disk: u64 = 20;
	let thread_count = 10;
	let mut buffermanager = BufferManager::new(pages_in_ram);

	for i in range(0, pages_on_disk) {
		let bf = match buffermanager.fixPage(i, true) {
			Some(frame) => frame,
			None => fail!("Couldn't fix page {}", i),
		};
		{
			let mut lock = bf.write();
			lock.get_mut_data()[0] = 0;
		}
		buffermanager.unfixPage(bf, true);
	}
	let bm = Arc::new(RWLock::new(buffermanager));

	// start read/write threads
	for _ in range(0, thread_count) {
		let bm = bm.clone();
		spawn(proc() {
			let is_write = random::<bool>();
			let between = Range::new(0, pages_on_disk);
			let mut rng = rand::task_rng();
			let page_number = between.ind_sample(&mut rng);
			let mut bm = bm.write();
			println!("Creating new {} task",
				if is_write {"write"} else {"read"});
			if is_write {
				let bf = match bm.fixPage(page_number, is_write) {
					Some(frame) => frame,
					None => fail!("Cound't fix page"),
				};
				{
					let mut lock = bf.write();
					let data = lock.get_mut_data();
					data[0] = data[0] + 1;
				}
				bm.unfixPage(bf, is_write);
			} else {
				let bf = match bm.fixPage(page_number, is_write) {
					Some(frame) => frame,
					None => fail!("Cound't fix page"),
				};
				bm.unfixPage(bf, is_write);
			}
		});
	}
}
<commit_msg>Moved imports for stuff used only in tests into test<commit_after>extern crate collections;
extern crate sync;
#[cfg(test)]
extern crate rand;
use collections::HashMap;
use std::io::{File, Open, Read, Write, TempDir};
use sync::{Arc, RWLock};

struct BufferManager {
	size: uint,
	entries: HashMap<u64, BufferEntry>,
	directory: TempDir,
}

struct BufferEntry {
	frame: Arc<RWLock<BufferFrame>>,
}

struct BufferFrame {
	pageId: u64,
	data: Vec<u8>,
}

/* Destructor trait implementation */
impl Drop for BufferManager {
	fn drop(&mut self) {
		println!("Dropping");
		// TODO
	}
}

impl BufferManager {
	pub fn new(size: uint) -> BufferManager {
		let h = HashMap::with_capacity(size);
		let dir = match TempDir::new("buffermanager") {
			Some(temp_dir) => temp_dir,
			None => fail!("creation of temporary directory"),
		};
		BufferManager {size: size, entries: h, directory: dir}
	}

	fn openOrCreate(&self, pageId: u64) -> File {
		let page_path = self.directory.path();
		let file_path = page_path.join(pageId.to_str());
		match File::open_mode(&file_path, Open, Read) {
			Ok(f) => f,
			Err(e) => {
				match File::open_mode(&file_path, Open, Write) {
					Ok(mut f) => {
						f.write([0_u8, ..4 * 1024]);
						match File::open_mode(&file_path, Open, Read) {
							Ok(f) => f,
							Err(e) => fail!("failed reading file: {}", e),
						}
					},
					Err(e) => fail!("Writing file failed: {}", e),
				}
			},
		}
	}

	fn loadPage(&mut self, pageId: u64) {
		if self.entries.len() == self.size {
			self.evictPage();
		}

		let mut file_handle = self.openOrCreate(pageId);
		let content = match file_handle.read_exact(4*1024) {
			Ok(c) => Vec::from_slice(c),
			Err(e) => fail!("Couldn't read from page: {}", e),
		};

		let frame = BufferFrame {data: content, pageId: pageId};
		let entry = BufferEntry {frame: Arc::new(RWLock::new(frame))};
		self.entries.insert(pageId, entry);
	}

	fn evictPage(&mut self) {
		// TODO delete a random page
		// evicting is hard, let's go shopping
	}

	pub fn fixPage(&mut self, pageId: u64, exclusive: bool) -> Option<Arc<RWLock<BufferFrame>>> {
		// TODO
		if !self.entries.contains_key(&pageId) {
			self.loadPage(pageId);
		}
		let entry = self.entries.get(&pageId);
		// Arcs can be cloned and they will all point to the same RWLock
		Some(entry.frame.clone())
	}

	pub fn unfixPage(&mut self, frame: Arc<RWLock<BufferFrame>>, isDirty: bool) {
		if !isDirty {
			return;
		}
		let frame = frame.read();
		self.writePage(frame.pageId, frame.get_data());
	}

	fn writePage(&mut self, pageId: u64, data: &[u8]) {
		// TODO: write page back to disk
		println!("Writing {}", data);
	}
}

/*
 * A buffer frame, the unit that gets the data
 */
impl BufferFrame {
	/*
	 * get_mut_data returns a borrowed reference to a mutable slice to the vector
	 * contents.
	 */
	pub fn get_mut_data<'a>(&'a mut self) -> &'a mut [u8] {
		self.data.as_mut_slice()
	}
	pub fn get_data<'a>(&'a self) -> &'a [u8] {
		self.data.as_slice()
	}
}

#[test]
fn test_create() {
	let mut bm = BufferManager::new(16);
	let pageref = match bm.fixPage(42, false) {
		Some(p) => p,
		None => fail!("Getting page failed"),
	};
	{
		let mut page = pageref.write();
		let data = page.get_mut_data();
		data[0] = 42;
		println!("data: {}", Vec::from_slice(data));
	}
	bm.unfixPage(pageref, true);
	fail!("always");
}

#[test]
fn test_threads() {
	use rand::random;
	use rand::task_rng;
	use rand::distributions::{IndependentSample, Range};
	use std::task::spawn;

	let pages_in_ram = 20;
	let pages_on_disk: u64 = 20;
	let thread_count = 10;
	let mut buffermanager = BufferManager::new(pages_in_ram);

	for i in range(0, pages_on_disk) {
		let bf = match buffermanager.fixPage(i, true) {
			Some(frame) => frame,
			None => fail!("Couldn't fix page {}", i),
		};
		{
			let mut lock = bf.write();
			lock.get_mut_data()[0] = 0;
		}
		buffermanager.unfixPage(bf, true);
	}
	let bm = Arc::new(RWLock::new(buffermanager));

	// start read/write threads
	for _ in range(0, thread_count) {
		let bm = bm.clone();
		spawn(proc() {
			let is_write = random::<bool>();
			let between = Range::new(0, pages_on_disk);
			let mut rng = rand::task_rng();
			let page_number = between.ind_sample(&mut rng);
			let mut bm = bm.write();
			println!("Creating new {} task",
				if is_write {"write"} else {"read"});
			if is_write {
				let bf = match bm.fixPage(page_number, is_write) {
					Some(frame) => frame,
					None => fail!("Cound't fix page"),
				};
				{
					let mut lock = bf.write();
					let data = lock.get_mut_data();
					data[0] = data[0] + 1;
				}
				bm.unfixPage(bf, is_write);
			} else {
				let bf = match bm.fixPage(page_number, is_write) {
					Some(frame) => frame,
					None => fail!("Cound't fix page"),
				};
				bm.unfixPage(bf, is_write);
			}
		});
	}
}
<|endoftext|>


<commit_before>use std::fs::*;
use std::fmt;
use std::path::PathBuf; // Still unclear on the difference between Path and PathBuf
use std::collections::vec_deque::VecDeque;

pub struct DirectoryFiles<'a> {
    root_dir: &'a PathBuf, // We can just borrow a root path so we don't have to make a copy for ourselves-- or is it better design for this struct to own its own copy of the path?
    queue: VecDeque<DirEntry>,
    pub num_found_items: u32
    // what do we put in here? Probably a queue of some sort for our BFS.
    // Probably a representation of the top level directory
    // and maybe a count of files found so far?
}

impl<'a> DirectoryFiles<'a> {
    pub fn new(root_dir: &PathBuf) -> DirectoryFiles {
        let mut df = DirectoryFiles { root_dir: root_dir, queue: VecDeque::new(), num_found_items: 0 };
        df.enqueue(root_dir);
        df
    }

    fn enqueue(&mut self, dir: &PathBuf) {
        match read_dir(dir) {
            Ok(dir_entries) =>
                for entry in dir_entries {
                    match entry {
                        Ok(result) => self.queue.push_back(result),
                        Err(msg) => println!("Failed to read directory entry under {}: {}", dir.display(), msg)
                    }
                },
            Err(msg) => println!("Failed to read {}: {}", dir.display(), msg)
        }
    }
}

// Breadth-first trasversal popping off files one at a time
impl<'a> Iterator for DirectoryFiles<'a> {
    // may have to be a different representation of file names?
    type Item = DirEntry;

    fn next(&mut self) -> Option<DirEntry> {
        match self.queue.pop_front() {
            None => None,
            Some(elem) => {
                self.num_found_items += 1;
                if elem.path().is_dir() {
                    self.enqueue(&elem.path());
                    self.next() // we only wanna give out files
                }
                else {
                    Some(elem)
                }
            }
        }
    }
}

// Pretty-printing state
impl<'a> fmt::Display for DirectoryFiles<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} items found under directory {}", self.num_found_items, self.root_dir.display())
    }
}<commit_msg>refactoring so that our struct owns its own original path<commit_after>use std::fs::*;
use std::fmt;
use std::path::PathBuf; // Still unclear on the difference between Path and PathBuf
use std::collections::vec_deque::VecDeque;

pub struct DirectoryFiles {
    root_dir: PathBuf, // I think it's better design for the struct to own its own copy, especially because we aren't making many of these so there's little overhead
    queue: VecDeque<DirEntry>,
    pub num_found_items: u32
}

impl DirectoryFiles {
    pub fn new(root_dir: &PathBuf) -> DirectoryFiles {
        // The struct will make and keep its own copy of the root directory it was set loose on
        let mut df = DirectoryFiles { root_dir: root_dir.clone(), queue: VecDeque::new(), num_found_items: 0 };
        df.enqueue(&root_dir);
        df
    }

    fn enqueue(&mut self, dir: &PathBuf) {
        match read_dir(dir) {
            Ok(dir_entries) =>
                for entry in dir_entries {
                    match entry {
                        Ok(result) => self.queue.push_back(result),
                        Err(msg) => println!("Failed to read directory entry under {}: {}", dir.display(), msg)
                    }
                },
            Err(msg) => println!("Failed to read {}: {}", dir.display(), msg)
        }
    }
}

// Breadth-first trasversal popping off files one at a time
impl Iterator for DirectoryFiles {
    // may have to be a different representation of file names?
    type Item = DirEntry;

    fn next(&mut self) -> Option<DirEntry> {
        match self.queue.pop_front() {
            None => None,
            Some(elem) => {
                self.num_found_items += 1;
                if elem.path().is_dir() {
                    self.enqueue(&elem.path());
                    self.next() // we only wanna give out files
                }
                else {
                    Some(elem)
                }
            }
        }
    }
}

// Pretty-printing state
impl fmt::Display for DirectoryFiles {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} items found under directory {}", self.num_found_items, self.root_dir.display())
    }
}<|endoftext|>


<commit_before>use predicates::prelude::*;

pub fn assert_dirs_eq<Want: AsRef<std::path::Path>, Got: AsRef<std::path::Path>>(
    want_dir: Want,
    got_dir: Got,
) -> std::io::Result<()> {
    for entry in walkdir::WalkDir::new(&got_dir) {
        let entry = entry?;
        if !entry.file_type().is_file() {
            continue;
        }
        let relative_path = entry
            .path()
            .strip_prefix(&got_dir)
            .expect("path to have directory prefix");
        let got_file = entry.path();
        let want_file = want_dir.as_ref().join(relative_path);
        // println!("{:?} {:?} {:?}", relative_path, got_file, want_file);
        let predicate_file = predicate::path::eq_file(&want_file);
        if !predicate_file.eval(got_file) {
            let want_file_contents = std::fs::read_to_string(&want_file)?;
            let got_file_contents = std::fs::read_to_string(&got_file)?;
            similar_asserts::assert_eq!(want_file_contents, got_file_contents);
        }
    }
    Ok(())
}
<commit_msg>Fix clippy lint<commit_after>use predicates::prelude::*;

pub fn assert_dirs_eq<Want: AsRef<std::path::Path>, Got: AsRef<std::path::Path>>(
    want_dir: Want,
    got_dir: Got,
) -> std::io::Result<()> {
    for entry in walkdir::WalkDir::new(&got_dir) {
        let entry = entry?;
        if !entry.file_type().is_file() {
            continue;
        }
        let relative_path = entry
            .path()
            .strip_prefix(&got_dir)
            .expect("path to have directory prefix");
        let got_file = entry.path();
        let want_file = want_dir.as_ref().join(relative_path);
        // println!("{:?} {:?} {:?}", relative_path, got_file, want_file);
        let predicate_file = predicate::path::eq_file(&want_file);
        if !predicate_file.eval(got_file) {
            let want_file_contents = std::fs::read_to_string(&want_file)?;
            let got_file_contents = std::fs::read_to_string(got_file)?;
            similar_asserts::assert_eq!(want_file_contents, got_file_contents);
        }
    }
    Ok(())
}
<|endoftext|>


<commit_before>use display_sysinfo::{self, show_if_necessary};
use glib::Cast;
use graph::Graph;
use gtk::{
    self, AdjustmentExt, BoxExt, ContainerExt, LabelExt, ScrolledWindowExt, ToggleButtonExt,
    WidgetExt,
};
use notebook::NoteBook;
use settings::Settings;
use sysinfo::{NetworkExt, SystemExt};
use utils::{connect_graph, format_number, RotateVec};

use std::cell::RefCell;
use std::iter;
use std::rc::Rc;

struct NetworkData {
    name: String,
    history: Rc<RefCell<Graph>>,
    check_box: gtk::CheckButton,
    non_graph_layout: gtk::Box,
    updated: bool,
    // network in usage
    in_usage: gtk::Label,
    // network out usage
    out_usage: gtk::Label,
}

pub struct Network {
    elems: Rc<RefCell<Vec<NetworkData>>>,
    layout: gtk::Box,
}

impl Network {
    pub fn new(sys: &sysinfo::System, note: &mut NoteBook, settings: &Settings) -> Network {
        let mut elems = Vec::new();
        let layout = gtk::Box::new(gtk::Orientation::Vertical, 0);
        let scroll = gtk::ScrolledWindow::new(None::<&gtk::Adjustment>, None::<&gtk::Adjustment>);

        let mut tmp_elems = Vec::new();
        for (interface_name, _) in sys.get_networks() {
            tmp_elems.push(interface_name.clone());
        }
        tmp_elems.sort_unstable();
        for interface_name in tmp_elems {
            elems.push(create_network_interface(&layout, interface_name, &settings));
        }
        scroll.add(&layout);
        note.create_tab("Networks", &scroll);

        let elems = Rc::new(RefCell::new(elems));
        scroll.connect_show(clone!(@weak elems => move |_| {
                let elems = elems.borrow();
                for elem in elems.iter() {
                    show_if_necessary(
                        &elem.check_box.clone().upcast::<gtk::ToggleButton>(),
                        &elem.history.borrow(),
                        &elem.non_graph_layout,
                    );
                }
            }
        ));
        // It greatly improves the scrolling on the system information tab. No more clipping.
        if let Some(adjustment) = scroll.get_vadjustment() {
            adjustment.connect_value_changed(clone!(@weak elems => move |_| {
                let elems = elems.borrow();
                for elem in elems.iter() {
                    elem.history.borrow().invalidate();
                }
            }));
        }
        Network { elems, layout }
        // TODO: add button "refresh networks list"
    }

    // Maybe move the caller to a higher level?
    pub fn set_size_request(&self, width: i32, height: i32) {
        let elems = self.elems.borrow();
        for elem in elems.iter() {
            let history = elem.history.borrow();
            history.area.set_size_request(width, height);
        }
    }

    pub fn update_network(&mut self, sys: &sysinfo::System) {
        let mut networks = self.elems.borrow_mut();
        for (name, data) in sys.get_networks() {
            for network in networks.iter_mut().filter(|x| x.name == *name) {
                network
                    .in_usage
                    .set_text(format_number(data.get_income()).as_str());
                network
                    .out_usage
                    .set_text(format_number(data.get_outcome()).as_str());

                let mut history = network.history.borrow_mut();
                history.data[0].move_start();
                *history.data[0].get_mut(0).expect("cannot get data 0") = data.get_income() as f64;
                history.data[1].move_start();
                *history.data[1].get_mut(0).expect("cannot get data 1") = data.get_outcome() as f64;
                history.invalidate();
            }
        }
    }

    pub fn set_checkboxes_state(&self, active: bool) {
        let elems = self.elems.borrow();
        for elem in elems.iter() {
            elem.check_box.set_active(active);
        }
    }
}

fn create_network_interface(layout: &gtk::Box, name: String, settings: &Settings) -> NetworkData {
    let mut history = Graph::new(Some(1.), false);
    history.set_overhead(Some(20.));
    history.set_label_callbacks(Some(Box::new(|v| {
        let v = v as u64;
        if v < 1000 {
            return [
                v.to_string(),
                (v >> 1).to_string(),
                "0".to_string(),
                "B/sec".to_string(),
            ];
        }
        let nb = v / 1000;
        if nb < 100_000 {
            [
                nb.to_string(),
                (nb >> 1).to_string(),
                "0".to_string(),
                "kB/sec".to_string(),
            ]
        } else if nb < 10_000_000 {
            [
                (nb >> 10).to_string(),
                (nb >> 11).to_string(),
                "0".to_string(),
                "MB/sec".to_string(),
            ]
        } else if nb < 10_000_000_000 {
            [
                (nb >> 20).to_string(),
                (nb >> 21).to_string(),
                "0".to_string(),
                "GB/sec".to_string(),
            ]
        } else {
            [
                (nb >> 30).to_string(),
                (nb >> 31).to_string(),
                "0".to_string(),
                "TB/sec".to_string(),
            ]
        }
    })));
    history.set_labels_width(70);

    let non_graph_layout = gtk::Box::new(gtk::Orientation::Vertical, 0);
    let check_box = display_sysinfo::create_header(&name, &layout, settings.display_graph);
    // input data
    let in_usage = gtk::Label::new(Some(&format_number(0)));
    let horizontal_layout = gtk::Box::new(gtk::Orientation::Horizontal, 10);
    horizontal_layout.pack_start(&gtk::Label::new(Some("Input data")), true, false, 0);
    horizontal_layout.pack_start(&in_usage, true, false, 0);
    horizontal_layout.set_homogeneous(true);
    non_graph_layout.add(&horizontal_layout);
    history.push(
        RotateVec::new(iter::repeat(0f64).take(61).collect()),
        "Input data",
        None,
    );
    // output data
    let out_usage = gtk::Label::new(Some(&format_number(0)));
    let horizontal_layout = gtk::Box::new(gtk::Orientation::Horizontal, 10);
    horizontal_layout.pack_start(&gtk::Label::new(Some("Output data")), true, false, 0);
    horizontal_layout.pack_start(&out_usage, true, false, 0);
    horizontal_layout.set_homogeneous(true);
    non_graph_layout.add(&horizontal_layout);
    history.push(
        RotateVec::new(iter::repeat(0f64).take(61).collect()),
        "Output data",
        None,
    );
    layout.add(&non_graph_layout);
    history.attach_to(&layout);
    history.area.set_margin_bottom(20);

    let history = connect_graph(history);

    check_box
        .clone()
        .upcast::<gtk::ToggleButton>()
        .connect_toggled(clone!(@weak non_graph_layout, @weak history => move |c| {
            show_if_necessary(c, &history.borrow(), &non_graph_layout);
        }));
    NetworkData {
        name,
        history,
        check_box,
        non_graph_layout,
        in_usage,
        out_usage,
        updated: false,
    }
}
<commit_msg>More information for networks<commit_after>use display_sysinfo::{self, show_if_necessary};
use glib::Cast;
use graph::Graph;
use gtk::{
    self, AdjustmentExt, BoxExt, ContainerExt, LabelExt, ScrolledWindowExt, ToggleButtonExt,
    WidgetExt,
};
use notebook::NoteBook;
use settings::Settings;
use sysinfo::{NetworkExt, SystemExt};
use utils::{connect_graph, format_number, RotateVec};

use std::cell::RefCell;
use std::iter;
use std::rc::Rc;

struct NetworkData {
    name: String,
    history: Rc<RefCell<Graph>>,
    check_box: gtk::CheckButton,
    non_graph_layout: gtk::Box,
    updated: bool,
    // network in usage
    in_usage: gtk::Label,
    // network out usage
    out_usage: gtk::Label,
    // network income packets
    income_packets: gtk::Label,
    // network outcome packets
    outcome_packets: gtk::Label,
    // network income errors
    income_errors: gtk::Label,
    // network outcome errors
    outcome_errors: gtk::Label,
}

pub struct Network {
    elems: Rc<RefCell<Vec<NetworkData>>>,
    layout: gtk::Box,
}

impl Network {
    pub fn new(sys: &sysinfo::System, note: &mut NoteBook, settings: &Settings) -> Network {
        let mut elems = Vec::new();
        let layout = gtk::Box::new(gtk::Orientation::Vertical, 0);
        let scroll = gtk::ScrolledWindow::new(None::<&gtk::Adjustment>, None::<&gtk::Adjustment>);

        let mut tmp_elems = Vec::new();
        for (interface_name, _) in sys.get_networks() {
            tmp_elems.push(interface_name.clone());
        }
        tmp_elems.sort_unstable();
        for interface_name in tmp_elems {
            elems.push(create_network_interface(&layout, interface_name, &settings));
        }
        scroll.add(&layout);
        note.create_tab("Networks", &scroll);

        let elems = Rc::new(RefCell::new(elems));
        scroll.connect_show(clone!(@weak elems => move |_| {
                let elems = elems.borrow();
                for elem in elems.iter() {
                    show_if_necessary(
                        &elem.check_box.clone().upcast::<gtk::ToggleButton>(),
                        &elem.history.borrow(),
                        &elem.non_graph_layout,
                    );
                }
            }
        ));
        // It greatly improves the scrolling on the system information tab. No more clipping.
        if let Some(adjustment) = scroll.get_vadjustment() {
            adjustment.connect_value_changed(clone!(@weak elems => move |_| {
                let elems = elems.borrow();
                for elem in elems.iter() {
                    elem.history.borrow().invalidate();
                }
            }));
        }
        Network { elems, layout }
        // TODO: add button "refresh networks list"
    }

    // Maybe move the caller to a higher level?
    pub fn set_size_request(&self, width: i32, height: i32) {
        let elems = self.elems.borrow();
        for elem in elems.iter() {
            let history = elem.history.borrow();
            history.area.set_size_request(width, height);
        }
    }

    pub fn update_network(&mut self, sys: &sysinfo::System) {
        let mut networks = self.elems.borrow_mut();
        for (name, data) in sys.get_networks() {
            for network in networks.iter_mut().filter(|x| x.name == *name) {
                network
                    .in_usage
                    .set_text(format_number(data.get_income()).as_str());
                network
                    .out_usage
                    .set_text(format_number(data.get_outcome()).as_str());

                let mut history = network.history.borrow_mut();
                history.data[0].move_start();
                *history.data[0].get_mut(0).expect("cannot get data 0") = data.get_income() as f64;
                history.data[1].move_start();
                *history.data[1].get_mut(0).expect("cannot get data 1") = data.get_outcome() as f64;
                history.invalidate();

                network
                    .income_packets
                    .set_text(&better_number(data.get_total_packets_income()));
                network
                    .outcome_packets
                    .set_text(&better_number(data.get_total_packets_outcome()));
                network
                    .income_errors
                    .set_text(&better_number(data.get_total_errors_income()));
                network
                    .outcome_errors
                    .set_text(&better_number(data.get_total_errors_outcome()));
            }
        }
    }

    pub fn set_checkboxes_state(&self, active: bool) {
        let elems = self.elems.borrow();
        for elem in elems.iter() {
            elem.check_box.set_active(active);
        }
    }
}

fn create_non_graph_labels(label_text: &str, text: &str, non_graph_layout: &gtk::Box) -> gtk::Label {
    let label = gtk::Label::new(Some(text));
    let horizontal_layout = gtk::Box::new(gtk::Orientation::Horizontal, 10);
    horizontal_layout.pack_start(&gtk::Label::new(Some(label_text)), true, false, 0);
    horizontal_layout.pack_start(&label, true, false, 0);
    horizontal_layout.set_homogeneous(true);
    non_graph_layout.add(&horizontal_layout);
    label
}

fn better_number(mut f: u64) -> String {
    if f < 1000 {
        f.to_string()
    } else {
        let mut s = String::new();
        let mut count = 0;
        while f > 0 {
            if !s.is_empty() && count % 3 == 0 {
                s.push(' ');
            }
            s.push((((f % 10) as u8) + b'0') as char);
            f /= 10;
            count += 1;
        }
        {
            let vec = unsafe { s.as_mut_vec() };
            vec.reverse();
        }
        s
    }
}

fn create_network_interface(layout: &gtk::Box, name: String, settings: &Settings) -> NetworkData {
    let mut history = Graph::new(Some(1.), false);
    history.set_overhead(Some(20.));
    history.set_label_callbacks(Some(Box::new(|v| {
        let v = v as u64;
        if v < 1000 {
            return [
                v.to_string(),
                (v >> 1).to_string(),
                "0".to_string(),
                "B/sec".to_string(),
            ];
        }
        let nb = v / 1000;
        if nb < 100_000 {
            [
                nb.to_string(),
                (nb >> 1).to_string(),
                "0".to_string(),
                "kB/sec".to_string(),
            ]
        } else if nb < 10_000_000 {
            [
                (nb >> 10).to_string(),
                (nb >> 11).to_string(),
                "0".to_string(),
                "MB/sec".to_string(),
            ]
        } else if nb < 10_000_000_000 {
            [
                (nb >> 20).to_string(),
                (nb >> 21).to_string(),
                "0".to_string(),
                "GB/sec".to_string(),
            ]
        } else {
            [
                (nb >> 30).to_string(),
                (nb >> 31).to_string(),
                "0".to_string(),
                "TB/sec".to_string(),
            ]
        }
    })));
    history.set_labels_width(70);

    let non_graph_layout = gtk::Box::new(gtk::Orientation::Vertical, 0);
    let check_box = display_sysinfo::create_header(&name, &layout, settings.display_graph);
    // input data
    let in_usage = create_non_graph_labels("Input data", &format_number(0), &non_graph_layout);
    history.push(
        RotateVec::new(iter::repeat(0f64).take(61).collect()),
        "Input data",
        None,
    );
    // output data
    let out_usage = create_non_graph_labels("Output data", &format_number(0), &non_graph_layout);
    history.push(
        RotateVec::new(iter::repeat(0f64).take(61).collect()),
        "Output data",
        None,
    );
    // packets
    let income_packets = create_non_graph_labels("Total income packets", "0", &non_graph_layout);
    let outcome_packets = create_non_graph_labels("Total outcome packets", "0", &non_graph_layout);
    // errors
    let income_errors = create_non_graph_labels("Total income errors", "0", &non_graph_layout);
    let outcome_errors = create_non_graph_labels("Total outcome errors", "0", &non_graph_layout);

    layout.add(&non_graph_layout);
    history.attach_to(&layout);
    history.area.set_margin_bottom(20);

    let history = connect_graph(history);

    check_box
        .clone()
        .upcast::<gtk::ToggleButton>()
        .connect_toggled(clone!(@weak non_graph_layout, @weak history => move |c| {
            show_if_necessary(c, &history.borrow(), &non_graph_layout);
        }));
    NetworkData {
        name,
        history,
        check_box,
        non_graph_layout,
        in_usage,
        out_usage,
        updated: false,
        income_packets,
        outcome_packets,
        income_errors,
        outcome_errors,
    }
}
<|endoftext|>


<commit_before>use base_db::{fixture::WithFixture, SourceDatabase};
use test_utils::mark;

use crate::{test_db::TestDB, ModuleDefId};

use super::*;

fn lower(ra_fixture: &str) -> Arc<Body> {
    let (db, file_id) = crate::test_db::TestDB::with_single_file(ra_fixture);

    let krate = db.crate_graph().iter().next().unwrap();
    let def_map = db.crate_def_map(krate);
    let module = def_map.modules_for_file(file_id).next().unwrap();
    let module = &def_map[module];
    let fn_def = match module.scope.declarations().next().unwrap() {
        ModuleDefId::FunctionId(it) => it,
        _ => panic!(),
    };

    db.body(fn_def.into())
}

fn check_diagnostics(ra_fixture: &str) {
    let db: TestDB = TestDB::with_files(ra_fixture);
    db.check_diagnostics();
}

#[test]
fn your_stack_belongs_to_me() {
    mark::check!(your_stack_belongs_to_me);
    lower(
        "
macro_rules! n_nuple {
    ($e:tt) => ();
    ($($rest:tt)*) => {{
        (n_nuple!($($rest)*)None,)
    }};
}
fn main() { n_nuple!(1,2,3); }
",
    );
}

#[test]
fn cfg_diagnostics() {
    check_diagnostics(
        r"
fn f() {
    // The three g̶e̶n̶d̶e̶r̶s̶ statements:

    #[cfg(a)] fn f() {}  // Item statement
  //^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: a is disabled
    #[cfg(a)] {}         // Expression statement
  //^^^^^^^^^^^^ code is inactive due to #[cfg] directives: a is disabled
    #[cfg(a)] let x = 0; // let statement
  //^^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: a is disabled

    abc(#[cfg(a)] 0);
      //^^^^^^^^^^^ code is inactive due to #[cfg] directives: a is disabled
    let x = Struct {
        #[cfg(a)] f: 0,
      //^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: a is disabled
    };
    match () {
        () => (),
        #[cfg(a)] () => (),
      //^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: a is disabled
    }

    #[cfg(a)] 0          // Trailing expression of block
  //^^^^^^^^^^^ code is inactive due to #[cfg] directives: a is disabled
}
    ",
    );
}

#[test]
fn macro_diag_builtin() {
    check_diagnostics(
        r#"
fn f() {
    // Test a handful of built-in (eager) macros:

    include!(invalid);
  //^^^^^^^^^^^^^^^^^ failed to parse or resolve macro invocation
    include!("does not exist");
  //^^^^^^^^^^^^^^^^^^^^^^^^^^ failed to parse or resolve macro invocation

    env!(invalid);
  //^^^^^^^^^^^^^ failed to parse or resolve macro invocation

    // Lazy:

    format_args!();
  //^^^^^^^^^^^^^^ failed to parse or resolve macro invocation
}
        "#,
    );
}

#[test]
fn macro_rules_diag() {
    check_diagnostics(
        r#"
macro_rules! m {
    () => {};
}
fn f() {
    m!();

    m!(hi);
  //^^^^^^ leftover tokens
}
      "#,
    );
}
<commit_msg>Update/Fix tests<commit_after>use base_db::{fixture::WithFixture, SourceDatabase};
use test_utils::mark;

use crate::{test_db::TestDB, ModuleDefId};

use super::*;

fn lower(ra_fixture: &str) -> Arc<Body> {
    let (db, file_id) = crate::test_db::TestDB::with_single_file(ra_fixture);

    let krate = db.crate_graph().iter().next().unwrap();
    let def_map = db.crate_def_map(krate);
    let module = def_map.modules_for_file(file_id).next().unwrap();
    let module = &def_map[module];
    let fn_def = match module.scope.declarations().next().unwrap() {
        ModuleDefId::FunctionId(it) => it,
        _ => panic!(),
    };

    db.body(fn_def.into())
}

fn check_diagnostics(ra_fixture: &str) {
    let db: TestDB = TestDB::with_files(ra_fixture);
    db.check_diagnostics();
}

#[test]
fn your_stack_belongs_to_me() {
    mark::check!(your_stack_belongs_to_me);
    lower(
        "
macro_rules! n_nuple {
    ($e:tt) => ();
    ($($rest:tt)*) => {{
        (n_nuple!($($rest)*)None,)
    }};
}
fn main() { n_nuple!(1,2,3); }
",
    );
}

#[test]
fn cfg_diagnostics() {
    check_diagnostics(
        r"
fn f() {
    // The three g̶e̶n̶d̶e̶r̶s̶ statements:

    #[cfg(a)] fn f() {}  // Item statement
  //^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: a is disabled
    #[cfg(a)] {}         // Expression statement
  //^^^^^^^^^^^^ code is inactive due to #[cfg] directives: a is disabled
    #[cfg(a)] let x = 0; // let statement
  //^^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: a is disabled

    abc(#[cfg(a)] 0);
      //^^^^^^^^^^^ code is inactive due to #[cfg] directives: a is disabled
    let x = Struct {
        #[cfg(a)] f: 0,
      //^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: a is disabled
    };
    match () {
        () => (),
        #[cfg(a)] () => (),
      //^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: a is disabled
    }

    #[cfg(a)] 0          // Trailing expression of block
  //^^^^^^^^^^^ code is inactive due to #[cfg] directives: a is disabled
}
    ",
    );
}

#[test]
fn macro_diag_builtin() {
    check_diagnostics(
        r#"
#[rustc_builtin_macro]
macro_rules! env {}

#[rustc_builtin_macro]
macro_rules! include {}

#[rustc_builtin_macro]
macro_rules! format_args {
    () => {}
}

fn f() {
    // Test a handful of built-in (eager) macros:

    include!(invalid);
  //^^^^^^^^^^^^^^^^^ could not convert tokens
    include!("does not exist");
  //^^^^^^^^^^^^^^^^^^^^^^^^^^ could not convert tokens

    env!(invalid);
  //^^^^^^^^^^^^^ could not convert tokens

    // Lazy:

    format_args!();
  //^^^^^^^^^^^^^^ no rule matches input tokens
}
        "#,
    );
}

#[test]
fn macro_rules_diag() {
    check_diagnostics(
        r#"
macro_rules! m {
    () => {};
}
fn f() {
    m!();

    m!(hi);
  //^^^^^^ leftover tokens
}
      "#,
    );
}
<|endoftext|>


<commit_before>use std::io::{self,ErrorKind,Read,Write};
use std::net::{SocketAddr,SocketAddrV4,SocketAddrV6};
use mio::tcp::{TcpListener,TcpStream};
use rustls::{ServerSession, Session};
use net2::TcpBuilder;
use net2::unix::UnixTcpBuilderExt;
#[cfg(feature = "use_openssl")]
use openssl::ssl::{Error, SslStream};

#[derive(Debug,PartialEq,Copy,Clone)]
pub enum SocketResult {
  Continue,
  WouldBlock,
  Error
}

pub trait SocketHandler {
  fn socket_read(&mut self,  buf: &mut[u8]) -> (usize, SocketResult);
  fn socket_write(&mut self, buf: &[u8])    -> (usize, SocketResult);
  fn socket_ref(&self) -> &TcpStream;
}

impl SocketHandler for TcpStream {
  fn socket_read(&mut self,  buf: &mut[u8]) -> (usize, SocketResult) {
    let mut size = 0usize;
    loop {
      if size == buf.len() {
        return (size, SocketResult::Continue);
      }
      match self.read(&mut buf[size..]) {
        Ok(0)  => return (size, SocketResult::Continue),
        Ok(sz) => size +=sz,
        Err(e) => match e.kind() {
          ErrorKind::WouldBlock => return (size, SocketResult::WouldBlock),
          ErrorKind::BrokenPipe => {
            error!("SOCKET\tbroken pipe reading from the socket");
            return (size, SocketResult::Error)
          },
          _ => {
            error!("SOCKET\tsocket_read error={:?}", e);
            return (size, SocketResult::Error)
          },
        }
      }
    }
  }

  fn socket_write(&mut self,  buf: &[u8]) -> (usize, SocketResult) {
    let mut size = 0usize;
    loop {
      if size == buf.len() {
        return (size, SocketResult::Continue);
      }
      match self.write(&buf[size..]) {
        Ok(0)  => return (size, SocketResult::Continue),
        Ok(sz) => size += sz,
        Err(e) => match e.kind() {
          ErrorKind::WouldBlock => return (size, SocketResult::WouldBlock),
          ErrorKind::BrokenPipe => {
            error!("SOCKET\tbroken pipe writing to the socket");
            return (size, SocketResult::Error)
          },
          _ => {
            //FIXME: timeout and other common errors should be sent up
            error!("SOCKET\tsocket_write error={:?}", e);
            return (size, SocketResult::Error)
          },
        }
      }
    }
  }

  fn socket_ref(&self) -> &TcpStream { self }
}

#[cfg(feature = "use_openssl")]
impl SocketHandler for SslStream<TcpStream> {
  fn socket_read(&mut self,  buf: &mut[u8]) -> (usize, SocketResult) {
    let mut size = 0usize;
    loop {
      if size == buf.len() {
        return (size, SocketResult::Continue);
      }
      match self.ssl_read(&mut buf[size..]) {
        Ok(0)  => return (size, SocketResult::Continue),
        Ok(sz) => size += sz,
        Err(Error::WantRead(_))  => return (size, SocketResult::WouldBlock),
        Err(Error::WantWrite(_)) => return (size, SocketResult::WouldBlock),
        Err(Error::Stream(e))    => {
          error!("SOCKET-TLS\treadable TLS socket err={:?}", e);
          return (size, SocketResult::Error)
        },
        _ => return (size, SocketResult::Error)
      }
    }
  }

  fn socket_write(&mut self,  buf: &[u8]) -> (usize, SocketResult) {
    let mut size = 0usize;
    loop {
      if size == buf.len() {
        return (size, SocketResult::Continue);
      }
      match self.ssl_write(&buf[size..]) {
        Ok(0)  => return (size, SocketResult::Continue),
        Ok(sz) => size +=sz,
        Err(Error::WantRead(_))  => return (size, SocketResult::WouldBlock),
        Err(Error::WantWrite(_)) => return (size, SocketResult::WouldBlock),
        Err(Error::Stream(e))    => {
          error!("SOCKET-TLS\twritable TLS socket err={:?}", e);
          return (size, SocketResult::Error)
        },
        e => {
          error!("SOCKET-TLS\twritable TLS socket err={:?}", e);
          return (size, SocketResult::Error)
        }
      }
    }
  }

  fn socket_ref(&self) -> &TcpStream { self.get_ref() }
}

pub struct FrontRustls {
  pub stream:  TcpStream,
  pub session: ServerSession,
}

impl SocketHandler for FrontRustls {
  fn socket_read(&mut self,  buf: &mut[u8]) -> (usize, SocketResult) {
    let mut size = 0usize;
    let mut can_read = true;

    while self.session.wants_read() && can_read {
      if size == buf.len() {
        return (size, SocketResult::Continue);
      }

      match self.session.read_tls(&mut self.stream) {
        Ok(0)  => can_read = false,
        Ok(sz) => {},
        Err(e) => match e.kind() {
          ErrorKind::WouldBlock => {
            error!("rustls socket_read wouldblock");
            can_read = false;
          },
          _ => {
            error!("could not read TLS stream from socket: {:?}", e);
            return (size, SocketResult::Error)
           }
        }
      }

      if let Err(e) = self.session.process_new_packets() {
        error!("could not process read TLS packets: {:?}", e);
        return (size, SocketResult::Error);
      }

      match self.session.read(&mut buf[size..]) {
        Ok(0)  => if !can_read {
          return (size, SocketResult::Continue)
        },
        Ok(sz) => size += sz,
        Err(e) => match e.kind() {
          ErrorKind::WouldBlock => {
            if !can_read {
              return (size, SocketResult::WouldBlock);
            }
          },
           _ => {
             error!("could not read data from TLS stream: {:?}", e);
            return (size, SocketResult::Error)
           }
        }

      }
    }

    if can_read {
    (size, SocketResult::Continue)
    } else {
    (size, SocketResult::WouldBlock)
    }
  }

  fn socket_write(&mut self,  buf: &[u8]) -> (usize, SocketResult) {
    let mut sent_size = 0usize;
    let mut buffered_size = 0usize;
    let mut can_write = true;

    match self.session.write(buf) {
      Ok(0)  => {
      },
      Ok(sz) => {
        buffered_size += sz;
      },
      Err(e) => match e.kind() {
        ErrorKind::WouldBlock => {
          // we don't need to do anything, the session will return false in wants_write?
          error!("rustls socket_write wouldblock");
        },
        _ => {
          error!("could not write data to TLS stream: {:?}", e);
          return (buffered_size, SocketResult::Error)
        }
      }
    }

    while self.session.wants_write() && can_write {
      if sent_size == buf.len() {
        return (buffered_size, SocketResult::Continue);
      }

      if sent_size == buffered_size && buffered_size < buf.len() {
        match self.session.write(&buf[buffered_size..]) {
          Ok(0)  => {
          },
          Ok(sz) => {
            buffered_size += sz;
          },
          Err(e) => match e.kind() {
            ErrorKind::WouldBlock => {
              // we don't need to do anything, the session will return false in wants_write?
              error!("rustls socket_write wouldblock");
            },
             _ => {
               error!("could not write data to TLS stream: {:?}", e);
              return (buffered_size, SocketResult::Error)
             }
          }
        }

      }

      match self.session.write_tls(&mut self.stream) {
        Ok(0)  => {
          can_write = false;
        },
        Ok(sz) => {
          sent_size += sz;
        },
        Err(e) => match e.kind() {
          ErrorKind::WouldBlock => can_write = false,
          _ => {
            error!("could not write TLS stream to socket: {:?}", e);
            return (buffered_size, SocketResult::Error)
          }
        }
      }

    }

    if can_write {
      (buffered_size, SocketResult::Continue)
    } else {
      (buffered_size, SocketResult::WouldBlock)
    }
  }

  fn socket_ref(&self) -> &TcpStream { &self.stream }
}

pub fn server_bind(addr: &SocketAddr) -> io::Result<TcpListener> {
  let sock = try!(match *addr {
    SocketAddr::V4(..) => TcpBuilder::new_v4(),
    SocketAddr::V6(..) => TcpBuilder::new_v6(),
  });

  // set so_reuseaddr, but only on unix (mirrors what libstd does)
  if cfg!(unix) {
    try!(sock.reuse_address(true));
  }

  try!(sock.reuse_port(true));

  // bind the socket
  try!(sock.bind(addr));

  // listen
  let listener = try!(sock.listen(1024));
  TcpListener::from_listener(listener, addr)
}

<commit_msg>remove a noisy log message<commit_after>use std::io::{self,ErrorKind,Read,Write};
use std::net::{SocketAddr,SocketAddrV4,SocketAddrV6};
use mio::tcp::{TcpListener,TcpStream};
use rustls::{ServerSession, Session};
use net2::TcpBuilder;
use net2::unix::UnixTcpBuilderExt;
#[cfg(feature = "use_openssl")]
use openssl::ssl::{Error, SslStream};

#[derive(Debug,PartialEq,Copy,Clone)]
pub enum SocketResult {
  Continue,
  WouldBlock,
  Error
}

pub trait SocketHandler {
  fn socket_read(&mut self,  buf: &mut[u8]) -> (usize, SocketResult);
  fn socket_write(&mut self, buf: &[u8])    -> (usize, SocketResult);
  fn socket_ref(&self) -> &TcpStream;
}

impl SocketHandler for TcpStream {
  fn socket_read(&mut self,  buf: &mut[u8]) -> (usize, SocketResult) {
    let mut size = 0usize;
    loop {
      if size == buf.len() {
        return (size, SocketResult::Continue);
      }
      match self.read(&mut buf[size..]) {
        Ok(0)  => return (size, SocketResult::Continue),
        Ok(sz) => size +=sz,
        Err(e) => match e.kind() {
          ErrorKind::WouldBlock => return (size, SocketResult::WouldBlock),
          ErrorKind::BrokenPipe => {
            error!("SOCKET\tbroken pipe reading from the socket");
            return (size, SocketResult::Error)
          },
          _ => {
            error!("SOCKET\tsocket_read error={:?}", e);
            return (size, SocketResult::Error)
          },
        }
      }
    }
  }

  fn socket_write(&mut self,  buf: &[u8]) -> (usize, SocketResult) {
    let mut size = 0usize;
    loop {
      if size == buf.len() {
        return (size, SocketResult::Continue);
      }
      match self.write(&buf[size..]) {
        Ok(0)  => return (size, SocketResult::Continue),
        Ok(sz) => size += sz,
        Err(e) => match e.kind() {
          ErrorKind::WouldBlock => return (size, SocketResult::WouldBlock),
          ErrorKind::BrokenPipe => {
            error!("SOCKET\tbroken pipe writing to the socket");
            return (size, SocketResult::Error)
          },
          _ => {
            //FIXME: timeout and other common errors should be sent up
            error!("SOCKET\tsocket_write error={:?}", e);
            return (size, SocketResult::Error)
          },
        }
      }
    }
  }

  fn socket_ref(&self) -> &TcpStream { self }
}

#[cfg(feature = "use_openssl")]
impl SocketHandler for SslStream<TcpStream> {
  fn socket_read(&mut self,  buf: &mut[u8]) -> (usize, SocketResult) {
    let mut size = 0usize;
    loop {
      if size == buf.len() {
        return (size, SocketResult::Continue);
      }
      match self.ssl_read(&mut buf[size..]) {
        Ok(0)  => return (size, SocketResult::Continue),
        Ok(sz) => size += sz,
        Err(Error::WantRead(_))  => return (size, SocketResult::WouldBlock),
        Err(Error::WantWrite(_)) => return (size, SocketResult::WouldBlock),
        Err(Error::Stream(e))    => {
          error!("SOCKET-TLS\treadable TLS socket err={:?}", e);
          return (size, SocketResult::Error)
        },
        _ => return (size, SocketResult::Error)
      }
    }
  }

  fn socket_write(&mut self,  buf: &[u8]) -> (usize, SocketResult) {
    let mut size = 0usize;
    loop {
      if size == buf.len() {
        return (size, SocketResult::Continue);
      }
      match self.ssl_write(&buf[size..]) {
        Ok(0)  => return (size, SocketResult::Continue),
        Ok(sz) => size +=sz,
        Err(Error::WantRead(_))  => return (size, SocketResult::WouldBlock),
        Err(Error::WantWrite(_)) => return (size, SocketResult::WouldBlock),
        Err(Error::Stream(e))    => {
          error!("SOCKET-TLS\twritable TLS socket err={:?}", e);
          return (size, SocketResult::Error)
        },
        e => {
          error!("SOCKET-TLS\twritable TLS socket err={:?}", e);
          return (size, SocketResult::Error)
        }
      }
    }
  }

  fn socket_ref(&self) -> &TcpStream { self.get_ref() }
}

pub struct FrontRustls {
  pub stream:  TcpStream,
  pub session: ServerSession,
}

impl SocketHandler for FrontRustls {
  fn socket_read(&mut self,  buf: &mut[u8]) -> (usize, SocketResult) {
    let mut size = 0usize;
    let mut can_read = true;

    while self.session.wants_read() && can_read {
      if size == buf.len() {
        return (size, SocketResult::Continue);
      }

      match self.session.read_tls(&mut self.stream) {
        Ok(0)  => can_read = false,
        Ok(sz) => {},
        Err(e) => match e.kind() {
          ErrorKind::WouldBlock => {
            can_read = false;
          },
          _ => {
            error!("could not read TLS stream from socket: {:?}", e);
            return (size, SocketResult::Error)
           }
        }
      }

      if let Err(e) = self.session.process_new_packets() {
        error!("could not process read TLS packets: {:?}", e);
        return (size, SocketResult::Error);
      }

      match self.session.read(&mut buf[size..]) {
        Ok(0)  => if !can_read {
          return (size, SocketResult::Continue)
        },
        Ok(sz) => size += sz,
        Err(e) => match e.kind() {
          ErrorKind::WouldBlock => {
            if !can_read {
              return (size, SocketResult::WouldBlock);
            }
          },
           _ => {
             error!("could not read data from TLS stream: {:?}", e);
            return (size, SocketResult::Error)
           }
        }

      }
    }

    if can_read {
    (size, SocketResult::Continue)
    } else {
    (size, SocketResult::WouldBlock)
    }
  }

  fn socket_write(&mut self,  buf: &[u8]) -> (usize, SocketResult) {
    let mut sent_size = 0usize;
    let mut buffered_size = 0usize;
    let mut can_write = true;

    match self.session.write(buf) {
      Ok(0)  => {
      },
      Ok(sz) => {
        buffered_size += sz;
      },
      Err(e) => match e.kind() {
        ErrorKind::WouldBlock => {
          // we don't need to do anything, the session will return false in wants_write?
          error!("rustls socket_write wouldblock");
        },
        _ => {
          error!("could not write data to TLS stream: {:?}", e);
          return (buffered_size, SocketResult::Error)
        }
      }
    }

    while self.session.wants_write() && can_write {
      if sent_size == buf.len() {
        return (buffered_size, SocketResult::Continue);
      }

      if sent_size == buffered_size && buffered_size < buf.len() {
        match self.session.write(&buf[buffered_size..]) {
          Ok(0)  => {
          },
          Ok(sz) => {
            buffered_size += sz;
          },
          Err(e) => match e.kind() {
            ErrorKind::WouldBlock => {
              // we don't need to do anything, the session will return false in wants_write?
              error!("rustls socket_write wouldblock");
            },
             _ => {
               error!("could not write data to TLS stream: {:?}", e);
              return (buffered_size, SocketResult::Error)
             }
          }
        }

      }

      match self.session.write_tls(&mut self.stream) {
        Ok(0)  => {
          can_write = false;
        },
        Ok(sz) => {
          sent_size += sz;
        },
        Err(e) => match e.kind() {
          ErrorKind::WouldBlock => can_write = false,
          _ => {
            error!("could not write TLS stream to socket: {:?}", e);
            return (buffered_size, SocketResult::Error)
          }
        }
      }

    }

    if can_write {
      (buffered_size, SocketResult::Continue)
    } else {
      (buffered_size, SocketResult::WouldBlock)
    }
  }

  fn socket_ref(&self) -> &TcpStream { &self.stream }
}

pub fn server_bind(addr: &SocketAddr) -> io::Result<TcpListener> {
  let sock = try!(match *addr {
    SocketAddr::V4(..) => TcpBuilder::new_v4(),
    SocketAddr::V6(..) => TcpBuilder::new_v6(),
  });

  // set so_reuseaddr, but only on unix (mirrors what libstd does)
  if cfg!(unix) {
    try!(sock.reuse_address(true));
  }

  try!(sock.reuse_port(true));

  // bind the socket
  try!(sock.bind(addr));

  // listen
  let listener = try!(sock.listen(1024));
  TcpListener::from_listener(listener, addr)
}

<|endoftext|>


<commit_before>use std::error::Error;
use std::fmt::Error as FmtError;
use std::fmt::{Debug, Display, Formatter};
use std::fmt;
use std::convert::From;

/**
 * Kind of store error
 */
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum StoreErrorKind {
    ConfigurationError,
    FileError,
    IdLocked,
    IdNotFound,
    OutOfMemory,
    FileNotFound,
    FileNotCreated,
    IoError,
    StorePathExists,
    StorePathCreate,
    LockError,
    LockPoisoned,
    EntryAlreadyBorrowed,
    EntryAlreadyExists,
    MalformedEntry,
    HeaderPathSyntaxError,
    HeaderPathTypeFailure,
    HeaderKeyNotFound,
    HeaderTypeFailure,
    HookRegisterError,
    AspectNameNotFoundError,
    HookExecutionError,
    PreHookExecuteError,
    PostHookExecuteError,
    StorePathLacksVersion,
    GlobError,
    EncodingError,
        // maybe more
}

fn store_error_type_as_str(e: &StoreErrorKind) -> &'static str {
    match *e {
        StoreErrorKind::ConfigurationError => "Store Configuration Error",
        StoreErrorKind::FileError       |
        StoreErrorKind::IoError         => "File Error",
        StoreErrorKind::IdLocked        => "ID locked",
        StoreErrorKind::IdNotFound      => "ID not found",
        StoreErrorKind::OutOfMemory     => "Out of Memory",
        StoreErrorKind::FileNotFound    => "File corresponding to ID not found",
        StoreErrorKind::FileNotCreated  => "File corresponding to ID could not be created",
        StoreErrorKind::StorePathExists |
        StoreErrorKind::StorePathCreate => "Store path create",
        StoreErrorKind::LockError       => "Error locking datastructure",
        StoreErrorKind::LockPoisoned
            => "The internal Store Lock has been poisoned",
        StoreErrorKind::EntryAlreadyBorrowed => "Entry is already borrowed",
        StoreErrorKind::EntryAlreadyExists   => "Entry already exists",
        StoreErrorKind::MalformedEntry => "Entry has invalid formatting, missing header",
        StoreErrorKind::HeaderPathSyntaxError => "Syntax error in accessor string",
        StoreErrorKind::HeaderPathTypeFailure => "Header has wrong type for path",
        StoreErrorKind::HeaderKeyNotFound     => "Header Key not found",
        StoreErrorKind::HeaderTypeFailure     => "Header type is wrong",
        StoreErrorKind::HookRegisterError     => "Hook register error",
        StoreErrorKind::AspectNameNotFoundError => "Aspect name not found",
        StoreErrorKind::HookExecutionError    => "Hook execution error",
        StoreErrorKind::PreHookExecuteError   => "Pre-Hook execution error",
        StoreErrorKind::PostHookExecuteError  => "Post-Hook execution error",
        StoreErrorKind::StorePathLacksVersion => "The supplied store path has no version part",
        StoreErrorKind::GlobError             => "glob() error",
        StoreErrorKind::EncodingError         => "Encoding error",
    }
}

impl Display for StoreErrorKind {

    fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
        try!(write!(fmt, "{}", store_error_type_as_str(self)));
        Ok(())
    }

}

/**
 * Store error type
 */
#[derive(Debug)]
pub struct StoreError {
    err_type: StoreErrorKind,
    cause: Option<Box<Error>>,
}

impl StoreError {

    /**
     * Build a new StoreError from an StoreErrorKind, optionally with cause
     */
    pub fn new(errtype: StoreErrorKind, cause: Option<Box<Error>>)
        -> StoreError
        {
            StoreError {
                err_type: errtype,
                cause: cause,
            }
        }

    /**
     * Get the error type of this StoreError
     */
    pub fn err_type(&self) -> StoreErrorKind {
        self.err_type
    }

}

impl Display for StoreError {

    fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
        try!(write!(fmt, "[{}]", store_error_type_as_str(&self.err_type)));
        Ok(())
    }

}

impl Error for StoreError {

    fn description(&self) -> &str {
        store_error_type_as_str(&self.err_type)
    }

    fn cause(&self) -> Option<&Error> {
        self.cause.as_ref().map(|e| &**e)
    }

}

impl From<ParserError> for StoreError {
    fn from(ps: ParserError) -> StoreError {
        StoreError {
            err_type: StoreErrorKind::MalformedEntry,
            cause: Some(Box::new(ps)),
        }
    }
}

impl From<::std::io::Error> for StoreError {
    fn from(ps: ::std::io::Error) -> StoreError {
        StoreError {
            err_type: StoreErrorKind::IoError,
            cause: Some(Box::new(ps)),
        }
    }
}

#[derive(Clone)]
pub enum ParserErrorKind {
    TOMLParserErrors,
    MissingMainSection,
    MissingVersionInfo,
    NonTableInBaseTable,
    HeaderInconsistency,
}

pub struct ParserError {
    kind: ParserErrorKind,
    cause: Option<Box<Error>>,
}

impl ParserError {

    pub fn new(k: ParserErrorKind, cause: Option<Box<Error>>) -> ParserError {
        ParserError {
            kind: k,
            cause: cause,
        }
    }

}

impl Debug for ParserError {

    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "{:?}", self.description()));
        Ok(())
    }

}

impl Display for ParserError {

    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "{}", self.description()));
        Ok(())
    }

}

impl Error for ParserError {

    fn description(&self) -> &str {
        match self.kind {
            ParserErrorKind::TOMLParserErrors   => "Several TOML-Parser-Errors",
            ParserErrorKind::MissingMainSection => "Missing main section",
            ParserErrorKind::MissingVersionInfo => "Missing version information in main section",
            ParserErrorKind::NonTableInBaseTable => "A non-table was found in the base table",
            ParserErrorKind::HeaderInconsistency => "The header is inconsistent",
        }
    }

    fn cause(&self) -> Option<&Error> {
        self.cause.as_ref().map(|e| &**e)
    }

}

<commit_msg>Replace error code with macro for code generation<commit_after>use std::error::Error;
use std::fmt::Error as FmtError;
use std::fmt::{Display, Formatter};
use std::convert::From;

generate_error_types!(StoreError, StoreErrorKind,
    ConfigurationError      => "Store Configuration Error",
    FileError               => "File Error",
    IoError                 => "IO Error",
    IdLocked                => "ID locked",
    IdNotFound              => "ID not found",
    OutOfMemory             => "Out of Memory",
    FileNotFound            => "File corresponding to ID not found",
    FileNotCreated          => "File corresponding to ID could not be created",
    StorePathExists         => "Store path exists",
    StorePathCreate         => "Store path create",
    LockError               => "Error locking datastructure",
    LockPoisoned            => "The internal Store Lock has been poisoned",
    EntryAlreadyBorrowed    => "Entry is already borrowed",
    EntryAlreadyExists      => "Entry already exists",
    MalformedEntry          => "Entry has invalid formatting, missing header",
    HeaderPathSyntaxError   => "Syntax error in accessor string",
    HeaderPathTypeFailure   => "Header has wrong type for path",
    HeaderKeyNotFound       => "Header Key not found",
    HeaderTypeFailure       => "Header type is wrong",
    HookRegisterError       => "Hook register error",
    AspectNameNotFoundError => "Aspect name not found",
    HookExecutionError      => "Hook execution error",
    PreHookExecuteError     => "Pre-Hook execution error",
    PostHookExecuteError    => "Post-Hook execution error",
    StorePathLacksVersion   => "The supplied store path has no version part",
    GlobError               => "glob() error",
    EncodingError           => "Encoding error"
);

generate_error_types!(ParserError, ParserErrorKind,
    TOMLParserErrors    => "Several TOML-Parser-Errors",
    MissingMainSection  => "Missing main section",
    MissingVersionInfo  => "Missing version information in main section",
    NonTableInBaseTable => "A non-table was found in the base table",
    HeaderInconsistency => "The header is inconsistent"
);

impl From<ParserError> for StoreError {
    fn from(ps: ParserError) -> StoreError {
        StoreError {
            err_type: StoreErrorKind::MalformedEntry,
            cause: Some(Box::new(ps)),
        }
    }
}

impl From<::std::io::Error> for StoreError {
    fn from(ps: ::std::io::Error) -> StoreError {
        StoreError {
            err_type: StoreErrorKind::IoError,
            cause: Some(Box::new(ps)),
        }
    }
}

<|endoftext|>


<commit_before>//! On windows we cannot get read (or write) events for sockets in the
//! IOCP model; we only can run asynchronous reads!
//!
//! So we need to use select() to poll for read, and run it in a
//! separate thread.  To cancel that select() we'd need another socket
//! to select() for, and there is no socketpair() - we could use a
//! loopback TCP connection, but a firewall might block it.
//!
//! Instead we use a small (1 second) timeout for the select; it is only
//! used to terminate the thread anyway.
//!
//! This of course wastes one thread per fd we want to watch; a bigger
//! solution would reuse the same backend thread over and over, but then
//! we'd have to try the loopback TCP connection to wake it and fall
//! back to a smaller timeout.

use futures::{
	sink::Wait,
	sync::mpsc as futures_mpsc,
	Async,
	Poll,
	Sink,
	Stream,
};
use log::debug;
use std::{
	cell::UnsafeCell,
	io,
	os::raw::c_int,
	sync::mpsc as std_mpsc,
	thread,
	time::Duration,
};
use winapi::um::winsock2;

use self::fd_set::FdSet;

#[derive(Clone, Copy, PartialEq, Eq, Debug)]
enum PollRequest {
	Poll,
	Close,
}

struct SelectFdRead {
	fd: c_int,
	read_fds: FdSet,
}
impl SelectFdRead {
	pub fn new(fd: c_int) -> Self {
		SelectFdRead { fd, read_fds: FdSet::new() }
	}

	pub fn select(&mut self, timeout: Option<Duration>) -> bool {
		use std::ptr::null_mut;
		let mut timeout = timeout.map(|timeout| winsock2::timeval {
			tv_sec: timeout.as_secs() as libc::c_long,
			tv_usec: (timeout.subsec_nanos() / 1000) as libc::c_long,
		});
		self.read_fds.set(self.fd);
		unsafe {
			winsock2::select(
				self.fd + 1,
				self.read_fds.inner(),
				null_mut(),
				null_mut(),
				timeout.as_mut().map(|x| x as *mut _).unwrap_or(null_mut()),
			);
		}
		self.read_fds.is_set(self.fd)
	}
}

struct Inner {
	/// file descriptor to watch read events for
	fd: c_int,
	/// background select thread
	_thread: thread::JoinHandle<()>,
	/// either the select thread is running a Poll request or we manually
	/// sent a response through `send_response`
	pending_request: bool,
	/// send poll or close request to select thread
	send_request: std_mpsc::SyncSender<PollRequest>,
	/// when clear_read_ready() is called we use this to trigger a response if
	/// we already know the read event is pending
	send_response: Wait<futures_mpsc::Sender<()>>,
	/// a response means a read event is pending
	recv_response: futures_mpsc::Receiver<()>,
}

impl Inner {
	fn poll_read_ready(&mut self) -> Poll<(), io::Error> {
		debug!("poll read");
		if !self.pending_request {
			let mut read_fds = SelectFdRead::new(self.fd);
			if read_fds.select(Some(Duration::from_millis(0))) {
				debug!("poll read: local ready");
				return Ok(Async::Ready(()));
			} else {
				debug!("poll read: not ready, start thread");
				self.send_request
					.send(PollRequest::Poll)
					.expect("select thread terminated");
				self.pending_request = true;
			}
		}

		match self.recv_response.poll().unwrap() {
			Async::Ready(None) => unreachable!(),
			Async::Ready(Some(())) => {
				debug!("poll read: thread ready");
				self.pending_request = false;
				Ok(Async::Ready(()))
			},
			Async::NotReady => {
				debug!("poll read: thread not ready");
				Ok(Async::NotReady)
			},
		}
	}

	fn clear_read_ready(&mut self) -> io::Result<()> {
		// we need to get Async::NotReady from recv_response.poll
		match self.recv_response.poll().unwrap() {
			Async::Ready(None) => unreachable!(),
			Async::Ready(Some(())) => {
				// was ready. damn...
				assert!(self.pending_request);
				// try again - can't be ready again
				match self.recv_response.poll().unwrap() {
					Async::Ready(None) => unreachable!(),
					Async::Ready(Some(())) => unreachable!(),
					Async::NotReady => (),
				}
				// now send a response - it was ready after all
				self.send_response.send(()).unwrap();
			},
			Async::NotReady => {
				// yay!
				//
				// now we need something to trigger a response
				let mut read_fds = SelectFdRead::new(self.fd);
				self.pending_request = true;
				if read_fds.select(Some(Duration::from_millis(0))) {
					// ready, send a response
					self.send_response.send(()).unwrap();
				} else {
					debug!("poll need read: not ready, start thread");
					self.send_request
						.send(PollRequest::Poll)
						.expect("select thread terminated");
				}
			},
		}
		Ok(())
	}
}

pub fn is_readable(fd: c_int) -> io::Result<bool> {
	let mut read_fds = SelectFdRead::new(fd);
	Ok(read_fds.select(Some(Duration::from_millis(0))))
}

pub struct PollReadFd(UnsafeCell<Inner>);
impl PollReadFd {
	/// does not take overship of fd
	pub fn new(fd: c_int) -> io::Result<Self> {
		// buffer one request for "Close"
		let (send_request, recv_request) = std_mpsc::sync_channel(1);
		// buffer one notification
		let (send_response, recv_response) = futures_mpsc::channel(1);
		let outer_send_response = send_response.clone().wait();

		let thread = thread::spawn(move || {
			let mut read_fds = SelectFdRead::new(fd);
			let mut send_response = send_response.wait();
			loop {
				debug!("[select thread] waiting for request");
				match recv_request.recv() {
					Ok(PollRequest::Poll) => (),
					Ok(PollRequest::Close) => return,
					Err(_) => return,
				}
				debug!("[select thread] start polling");

				while !read_fds.select(Some(Duration::from_millis(1000))) {
					match recv_request.try_recv() {
						Ok(PollRequest::Poll) => unreachable!(),
						Ok(PollRequest::Close) => return,
						Err(_) => (), // back to select()
					}
				}

				debug!("[select thread] read event");

				if send_response.send(()).is_err() {
					return;
				}
			}
		});

		Ok(PollReadFd(UnsafeCell::new(Inner {
			fd,
			_thread: thread,
			pending_request: false,
			send_request,
			send_response: outer_send_response,
			recv_response,
		})))
	}

	fn inner(&self) -> &mut Inner {
		unsafe { &mut *self.0.get() }
	}

	pub fn poll_read_ready(&self) -> Poll<(), io::Error> {
		self.inner().poll_read_ready()
	}

	pub fn clear_read_ready(&self) -> io::Result<()> {
		self.inner().clear_read_ready()
	}
}

impl Drop for PollReadFd {
	fn drop(&mut self) {
		let _ = self.inner().send_request.send(PollRequest::Close);
	}
}

mod fd_set {
	use libc::{c_int, c_uint};
	use winapi::um::winsock2::{
		u_int,
		fd_set,
		FD_SETSIZE,
		SOCKET,
	};
	use std::mem::MaybeUninit;
	use std::ptr;

	/// Layout compatible struct of `fd_set`, but it holds maybe uninitialized `fd_array`.
	///
	/// # Safety
	/// The first `fd_count` slots of `fd_array` must be initialized,
	/// and the rest may be uninitialized.
	#[repr(C)]
	pub(super) struct FdSet {
		fd_count: u_int,
		fd_array: [MaybeUninit<SOCKET>; FD_SETSIZE],
	}

	impl FdSet {
		pub fn new() -> Self {
			FdSet {
				fd_count: 0,
				// safe according to:
				// https://doc.rust-lang.org/std/mem/union.MaybeUninit.html#initializing-an-array-element-by-element
				fd_array: unsafe { MaybeUninit::uninit().assume_init() },
			}
		}

		pub fn inner(&mut self) -> *mut fd_set {
			self as *mut FdSet as *mut _
		}

		pub fn set(&mut self, fd: c_int) {
			if self.is_set(fd) {
				return;
			}
			let count = self.fd_count as usize;
			if count < FD_SETSIZE {
				let fd = fd as c_uint as SOCKET;
				// This is safe because this slot is uninitialized.
				unsafe { ptr::write(self.fd_array[count].as_mut_ptr(), fd) };
				self.fd_count += 1;
			}
		}

		pub fn is_set(&self, fd: c_int) -> bool {
			let fd = fd as c_uint as SOCKET;
			let count = self.fd_count as usize;
			self.fd_array[..count].iter().any(|slot| {
				// This is safe because it's reading from first `fd_count` slots.
				fd == unsafe { ptr::read(slot.as_ptr()) }
			})
		}
	}

	#[cfg(test)]
	mod tests {
		use super::*;
		use std::mem::{needs_drop, transmute};

		// Check that `FdSet` is layout compatible with `fd_set`.
		#[test]
		fn fd_set_layout_compatible() {
			let mut fd_set = FdSet::new();
			(0..FD_SETSIZE as c_int).for_each(|i| fd_set.set(i));
			let fd_set: fd_set = unsafe { transmute(fd_set) };
			assert_eq!(fd_set.fd_count, FD_SETSIZE as u32);
			for i in 0..FD_SETSIZE as usize {
				assert_eq!(fd_set.fd_array[i], i as SOCKET);
			}
		}

		// Check that `SOCKET` doesn't need to be dropped, so that we don't need to
		// implement `Drop` for `FdSet`.
		#[test]
		fn socket_not_drop() {
			assert!(!needs_drop::<SOCKET>());
		}
	}
}
<commit_msg>cargo fmt<commit_after>//! On windows we cannot get read (or write) events for sockets in the
//! IOCP model; we only can run asynchronous reads!
//!
//! So we need to use select() to poll for read, and run it in a
//! separate thread.  To cancel that select() we'd need another socket
//! to select() for, and there is no socketpair() - we could use a
//! loopback TCP connection, but a firewall might block it.
//!
//! Instead we use a small (1 second) timeout for the select; it is only
//! used to terminate the thread anyway.
//!
//! This of course wastes one thread per fd we want to watch; a bigger
//! solution would reuse the same backend thread over and over, but then
//! we'd have to try the loopback TCP connection to wake it and fall
//! back to a smaller timeout.

use futures::{
	sink::Wait,
	sync::mpsc as futures_mpsc,
	Async,
	Poll,
	Sink,
	Stream,
};
use log::debug;
use std::{
	cell::UnsafeCell,
	io,
	os::raw::c_int,
	sync::mpsc as std_mpsc,
	thread,
	time::Duration,
};
use winapi::um::winsock2;

use self::fd_set::FdSet;

#[derive(Clone, Copy, PartialEq, Eq, Debug)]
enum PollRequest {
	Poll,
	Close,
}

struct SelectFdRead {
	fd: c_int,
	read_fds: FdSet,
}
impl SelectFdRead {
	pub fn new(fd: c_int) -> Self {
		SelectFdRead {
			fd,
			read_fds: FdSet::new(),
		}
	}

	pub fn select(&mut self, timeout: Option<Duration>) -> bool {
		use std::ptr::null_mut;
		let mut timeout = timeout.map(|timeout| winsock2::timeval {
			tv_sec: timeout.as_secs() as libc::c_long,
			tv_usec: (timeout.subsec_nanos() / 1000) as libc::c_long,
		});
		self.read_fds.set(self.fd);
		unsafe {
			winsock2::select(
				self.fd + 1,
				self.read_fds.inner(),
				null_mut(),
				null_mut(),
				timeout.as_mut().map(|x| x as *mut _).unwrap_or(null_mut()),
			);
		}
		self.read_fds.is_set(self.fd)
	}
}

struct Inner {
	/// file descriptor to watch read events for
	fd: c_int,
	/// background select thread
	_thread: thread::JoinHandle<()>,
	/// either the select thread is running a Poll request or we manually
	/// sent a response through `send_response`
	pending_request: bool,
	/// send poll or close request to select thread
	send_request: std_mpsc::SyncSender<PollRequest>,
	/// when clear_read_ready() is called we use this to trigger a response if
	/// we already know the read event is pending
	send_response: Wait<futures_mpsc::Sender<()>>,
	/// a response means a read event is pending
	recv_response: futures_mpsc::Receiver<()>,
}

impl Inner {
	fn poll_read_ready(&mut self) -> Poll<(), io::Error> {
		debug!("poll read");
		if !self.pending_request {
			let mut read_fds = SelectFdRead::new(self.fd);
			if read_fds.select(Some(Duration::from_millis(0))) {
				debug!("poll read: local ready");
				return Ok(Async::Ready(()));
			} else {
				debug!("poll read: not ready, start thread");
				self.send_request
					.send(PollRequest::Poll)
					.expect("select thread terminated");
				self.pending_request = true;
			}
		}

		match self.recv_response.poll().unwrap() {
			Async::Ready(None) => unreachable!(),
			Async::Ready(Some(())) => {
				debug!("poll read: thread ready");
				self.pending_request = false;
				Ok(Async::Ready(()))
			},
			Async::NotReady => {
				debug!("poll read: thread not ready");
				Ok(Async::NotReady)
			},
		}
	}

	fn clear_read_ready(&mut self) -> io::Result<()> {
		// we need to get Async::NotReady from recv_response.poll
		match self.recv_response.poll().unwrap() {
			Async::Ready(None) => unreachable!(),
			Async::Ready(Some(())) => {
				// was ready. damn...
				assert!(self.pending_request);
				// try again - can't be ready again
				match self.recv_response.poll().unwrap() {
					Async::Ready(None) => unreachable!(),
					Async::Ready(Some(())) => unreachable!(),
					Async::NotReady => (),
				}
				// now send a response - it was ready after all
				self.send_response.send(()).unwrap();
			},
			Async::NotReady => {
				// yay!
				//
				// now we need something to trigger a response
				let mut read_fds = SelectFdRead::new(self.fd);
				self.pending_request = true;
				if read_fds.select(Some(Duration::from_millis(0))) {
					// ready, send a response
					self.send_response.send(()).unwrap();
				} else {
					debug!("poll need read: not ready, start thread");
					self.send_request
						.send(PollRequest::Poll)
						.expect("select thread terminated");
				}
			},
		}
		Ok(())
	}
}

pub fn is_readable(fd: c_int) -> io::Result<bool> {
	let mut read_fds = SelectFdRead::new(fd);
	Ok(read_fds.select(Some(Duration::from_millis(0))))
}

pub struct PollReadFd(UnsafeCell<Inner>);
impl PollReadFd {
	/// does not take overship of fd
	pub fn new(fd: c_int) -> io::Result<Self> {
		// buffer one request for "Close"
		let (send_request, recv_request) = std_mpsc::sync_channel(1);
		// buffer one notification
		let (send_response, recv_response) = futures_mpsc::channel(1);
		let outer_send_response = send_response.clone().wait();

		let thread = thread::spawn(move || {
			let mut read_fds = SelectFdRead::new(fd);
			let mut send_response = send_response.wait();
			loop {
				debug!("[select thread] waiting for request");
				match recv_request.recv() {
					Ok(PollRequest::Poll) => (),
					Ok(PollRequest::Close) => return,
					Err(_) => return,
				}
				debug!("[select thread] start polling");

				while !read_fds.select(Some(Duration::from_millis(1000))) {
					match recv_request.try_recv() {
						Ok(PollRequest::Poll) => unreachable!(),
						Ok(PollRequest::Close) => return,
						Err(_) => (), // back to select()
					}
				}

				debug!("[select thread] read event");

				if send_response.send(()).is_err() {
					return;
				}
			}
		});

		Ok(PollReadFd(UnsafeCell::new(Inner {
			fd,
			_thread: thread,
			pending_request: false,
			send_request,
			send_response: outer_send_response,
			recv_response,
		})))
	}

	fn inner(&self) -> &mut Inner {
		unsafe { &mut *self.0.get() }
	}

	pub fn poll_read_ready(&self) -> Poll<(), io::Error> {
		self.inner().poll_read_ready()
	}

	pub fn clear_read_ready(&self) -> io::Result<()> {
		self.inner().clear_read_ready()
	}
}

impl Drop for PollReadFd {
	fn drop(&mut self) {
		let _ = self.inner().send_request.send(PollRequest::Close);
	}
}

mod fd_set {
	use libc::{
		c_int,
		c_uint,
	};
	use std::{
		mem::MaybeUninit,
		ptr,
	};
	use winapi::um::winsock2::{
		fd_set,
		u_int,
		FD_SETSIZE,
		SOCKET,
	};

	/// Layout compatible struct of `fd_set`, but it holds maybe uninitialized `fd_array`.
	///
	/// # Safety
	/// The first `fd_count` slots of `fd_array` must be initialized,
	/// and the rest may be uninitialized.
	#[repr(C)]
	pub(super) struct FdSet {
		fd_count: u_int,
		fd_array: [MaybeUninit<SOCKET>; FD_SETSIZE],
	}

	impl FdSet {
		pub fn new() -> Self {
			FdSet {
				fd_count: 0,
				// safe according to:
				// https://doc.rust-lang.org/std/mem/union.MaybeUninit.html#initializing-an-array-element-by-element
				fd_array: unsafe { MaybeUninit::uninit().assume_init() },
			}
		}

		pub fn inner(&mut self) -> *mut fd_set {
			self as *mut FdSet as *mut _
		}

		pub fn set(&mut self, fd: c_int) {
			if self.is_set(fd) {
				return;
			}
			let count = self.fd_count as usize;
			if count < FD_SETSIZE {
				let fd = fd as c_uint as SOCKET;
				// This is safe because this slot is uninitialized.
				unsafe { ptr::write(self.fd_array[count].as_mut_ptr(), fd) };
				self.fd_count += 1;
			}
		}

		pub fn is_set(&self, fd: c_int) -> bool {
			let fd = fd as c_uint as SOCKET;
			let count = self.fd_count as usize;
			self.fd_array[..count].iter().any(|slot| {
				// This is safe because it's reading from first `fd_count` slots.
				fd == unsafe { ptr::read(slot.as_ptr()) }
			})
		}
	}

	#[cfg(test)]
	mod tests {
		use super::*;
		use std::mem::{
			needs_drop,
			transmute,
		};

		// Check that `FdSet` is layout compatible with `fd_set`.
		#[test]
		fn fd_set_layout_compatible() {
			let mut fd_set = FdSet::new();
			(0..FD_SETSIZE as c_int).for_each(|i| fd_set.set(i));
			let fd_set: fd_set = unsafe { transmute(fd_set) };
			assert_eq!(fd_set.fd_count, FD_SETSIZE as u32);
			for i in 0..FD_SETSIZE as usize {
				assert_eq!(fd_set.fd_array[i], i as SOCKET);
			}
		}

		// Check that `SOCKET` doesn't need to be dropped, so that we don't need to
		// implement `Drop` for `FdSet`.
		#[test]
		fn socket_not_drop() {
			assert!(!needs_drop::<SOCKET>());
		}
	}
}
<|endoftext|>


<commit_before>//! Support for the KDE Idle Protocol

use wayland_sys::server::wl_display as wl_server_display;
use wlroots_sys::{wl_display, wlr_seat, wlr_idle, wlr_idle_create,
                  wlr_idle_destroy, wlr_idle_notify_activity,
                  wlr_idle_set_enabled};

#[derive(Debug)]
pub struct Manager {
    manager: *mut wlr_idle
}

impl Manager {
    pub(crate) unsafe fn new(display: *mut wl_server_display) -> Option<Self> {
        let manager_raw = wlr_idle_create(display as *mut wl_display);

        if !manager_raw.is_null() {
            Some(Manager { manager: manager_raw })
        } else {
            None
        }
    }

    /// Restart the timers for the seat
    pub fn notify_activity(&mut self, seat: *mut wlr_seat) {
        unsafe { wlr_idle_notify_activity(self.manager, seat as *mut wlr_seat) }
    }

    /// If we are passed a null pointer,
    /// update timers for all seats.
    pub fn set_enabled(&mut self, seat: *mut wlr_seat, enabled: bool) {
        wlr_log!(WLR_INFO, "Idle timer status: {:?}", enabled);
        unsafe { wlr_idle_set_enabled(self.manager, seat as *mut wlr_seat, enabled) }
    }
}

impl Drop for Manager {
    fn drop(&mut self) {
        unsafe { wlr_idle_destroy(self.manager) }
    }
}
<commit_msg>use the safe version of seat<commit_after>//! Support for the KDE Idle Protocol

use seat::Seat;

use wayland_sys::server::wl_display as wl_server_display;
use wlroots_sys::{wl_display, wlr_idle, wlr_idle_create,
                  wlr_idle_destroy, wlr_idle_notify_activity,
                  wlr_idle_set_enabled};

#[derive(Debug)]
pub struct Manager {
    manager: *mut wlr_idle
}

impl Manager {
    pub(crate) unsafe fn new(display: *mut wl_server_display) -> Option<Self> {
        let manager_raw = wlr_idle_create(display as *mut wl_display);

        if !manager_raw.is_null() {
            Some(Manager { manager: manager_raw })
        } else {
            None
        }
    }

    /// Restart the timers for the seat
    pub fn notify_activity(&mut self, seat: &Seat) {
        unsafe { wlr_idle_notify_activity(self.manager, seat.as_ptr()) }
    }

    /// If we are passed a null pointer, update timers for all seats.
    pub fn set_enabled(&mut self, seat: &Seat, enabled: bool) {
        unsafe { wlr_idle_set_enabled(self.manager, seat.as_ptr(), enabled) }
    }
}

impl Drop for Manager {
    fn drop(&mut self) {
        unsafe { wlr_idle_destroy(self.manager) }
    }
}
<|endoftext|>