urdig 0.9.6

urdig is a tool, which can be used to display informations about several (udev)-devices.
Documentation
use std::collections::HashMap;
use std::io;

use crate as urdig;
use phollaits::*;

pub fn get_subsystems() -> io::Result<Vec<String>> {
	let mut subsystems = Vec::with_capacity(80);
	let mut enumerator = udev::Enumerator::new()?;
	for device in enumerator.scan_devices()? {
		let property = device.property_value(urdig::PROPERTY_VALUE_SUBSYSTEM).to_io_result()?;
		if !subsystems.contains(&property.to_str().to_io_result()?.to_string()) {
			subsystems.push(property.to_str().to_io_result()?.to_string())
		}
	}
	subsystems.sort();
	Ok(subsystems)
}

pub fn get_nodes_from_subsystem<S: Into<String>>(subsystem: S) -> io::Result<Vec<String>> {
	let mut devnodes: Vec<String> = Vec::new();
	let mut enumerator = udev::Enumerator::new()?;
	enumerator.match_subsystem(subsystem.into())?;
	for device in enumerator.scan_devices()? {
		match device.devnode() {
			Some(x) => devnodes.push(x.to_str().to_io_result()?.to_string()),
			None => devnodes.push(device.syspath().to_str().to_io_result()?.to_string())
		}
	}
	devnodes.sort();
	Ok(devnodes)
}

pub fn get_properties<S: Into<String>>(name: S, source: Source) -> io::Result<HashMap<String, String>> {
	fn by_sysname<S: Into<String>>(name: S) -> io::Result<HashMap<String, String>> {
		let mut properties: HashMap<String, String> = HashMap::with_capacity(40);
		let mut enumerator = udev::Enumerator::new()?;
		enumerator.match_sysname(name.into().trim())?;
		for device in enumerator.scan_devices()? {
			for property in device.properties() {
				properties.insert(
					property.name().to_str().to_io_result()?.to_string(),
					property.value().to_str().to_io_result()?.to_string(),
				);
			}
		}
		Ok(properties)
	}
	fn by_devnode<S: Into<String>>(name: S) -> io::Result<HashMap<String, String>> {
		let name = name.into();
		let mut split = name.trim().rsplit(urdig::SEPARATOR_SYSTEM_DIRECTORY);
		let name = split.next().to_io_result()?;
		let mut properties: HashMap<String, String> = HashMap::with_capacity(40);
		let mut enumerator = udev::Enumerator::new()?;
		enumerator.match_sysname(name)?;
		for device in enumerator.scan_devices()? {
			for property in device.properties() {
				properties.insert(
					property.name().to_str().to_io_result()?.to_string(),
					property.value().to_str().to_io_result()?.to_string(),
				);
			}
		}
		Ok(properties)
	}

	fn by_syspath<S: Into<String>>(name: S) -> io::Result<HashMap<String, String>> {
		let name = name.into();
		let mut split = name.trim().rsplit(urdig::SEPARATOR_SYSTEM_DIRECTORY);
		let name = split.next().to_io_result()?;
		let mut properties: HashMap<String, String> = HashMap::with_capacity(40);
		let mut enumerator = udev::Enumerator::new()?;
		enumerator.match_sysname(name)?;
		for device in enumerator.scan_devices()? {
			for property in device.properties() {
				properties.insert(
					property.name().to_str().to_io_result()?.to_string(),
					property.value().to_str().to_io_result()?.to_string(),
				);
			}
		}
		Ok(properties)
	}
	match source {
		Source::Sysname => by_sysname(name),
		Source::Devnode => by_devnode(name),
		Source::Syspath => by_syspath(name),
	}
}

pub fn get_attributes<S: Into<String>>(name: S, source: Source) -> io::Result<HashMap<String, String>> {
	fn by_sysname<S: Into<String>>(name: S) -> io::Result<HashMap<String, String>> {
		let mut attributes: HashMap<String, String> = HashMap::with_capacity(40);
		let mut enumerator = udev::Enumerator::new()?;
		enumerator.match_sysname(name.into().trim())?;
		for device in enumerator.scan_devices()? {
			for attribute in device.attributes() {
				let value = match attribute.value() {
						Some(x) => x.to_str().to_string(),
						None => urdig::ERROR_VALUE_NONE.to_string()
					};
				attributes.insert(
					attribute.name().to_str().to_io_result()?.to_string(),
					value,
				);
			}
		}
		Ok(attributes)
	}
	fn by_devnode<S: Into<String>>(name: S) -> io::Result<HashMap<String, String>> {
		let name = name.into();
		let mut split = name.trim().rsplit(urdig::SEPARATOR_SYSTEM_DIRECTORY);
		let name = split.next().to_io_result()?;
		let mut attributes: HashMap<String, String> = HashMap::with_capacity(40);
		let mut enumerator = udev::Enumerator::new()?;
		enumerator.match_sysname(name)?;
		for device in enumerator.scan_devices()? {
			for attribute in device.attributes() {
				let value = match attribute.value() {
						Some(x) => x.to_str().to_string(),
						None => urdig::ERROR_VALUE_NONE.to_string()
					};
				attributes.insert(
					attribute.name().to_str().to_io_result()?.to_string(),
					value,
				);
			}
		}
		Ok(attributes)
	}

	fn by_syspath<S: Into<String>>(name: S) -> io::Result<HashMap<String, String>> {
		let name = name.into();
		let mut split = name.trim().rsplit(urdig::SEPARATOR_SYSTEM_DIRECTORY);
		let name = split.next().to_io_result()?;
		let mut attributes: HashMap<String, String> = HashMap::with_capacity(40);
		let mut enumerator = udev::Enumerator::new()?;
		enumerator.match_sysname(name)?;
		for device in enumerator.scan_devices()? {
			for attribute in device.attributes() {
				let value = match attribute.value() {
						Some(x) => x.to_str().to_string(),
						None => urdig::ERROR_VALUE_NONE.to_string()
					};
				attributes.insert(
					attribute.name().to_str().to_io_result()?.to_string(),
					value,
				);
			}
		}
		Ok(attributes)
	}
	match source {
		Source::Sysname => by_sysname(name),
		Source::Devnode => by_devnode(name),
		Source::Syspath => by_syspath(name),
	}
}


pub enum Source {
	Sysname,
	Devnode,
	Syspath
}