ev3dev-lang-rust 0.1.0

C++ language bindings for ev3dev
Documentation
use std::collections::HashMap;
use std::fs;
use std::fs::File;
use std::fs::OpenOptions;
use std::io;
use std::io::Read;
use std::io::Seek;
use std::io::SeekFrom;
use std::io::Write;
use std::os::unix::fs::PermissionsExt;
use std::string::String;

use core::Port;

pub type AttributeResult<T> = Result<T, io::Error>;

const ROOT_PATH: &str = "/sys/class/";

pub struct Attribute {
    file: File
}

impl Attribute {
    pub fn new(class_name: &str, name: &str, attribute_name: &str) -> Option<Attribute> {
        let file = Attribute::open_file(class_name, name, attribute_name);
        if file.is_some() {
            Some(Attribute {
                file: file.unwrap(),
            })
        } else {
            None
        }
    }

    fn open_file(class_name: &str, name: &str, attribute_name: &str) -> Option<File> {
        let mut filename = String::from(ROOT_PATH);
        filename.push_str(class_name);
        filename.push_str("/");
        filename.push_str(name);
        filename.push_str("/");
        filename.push_str(attribute_name);

        let stat = fs::metadata(&filename);

        if stat.is_ok() {
            let mode = stat.unwrap().permissions().mode();

            let readable = mode & 256 == 256;
            let writeable = mode & 128 == 128;

            let file = OpenOptions::new()
                .read(readable)
                .write(writeable)
                .open(&filename);

            file.ok()
        } else {
            None
        }
    }

    pub fn get_str(&self) -> AttributeResult<String> {
        let mut value = String::new();
        (&self.file).seek(SeekFrom::Start(0))?;
        (&self.file).read_to_string(&mut value)?;
        Ok(String::from(value.trim_right()))
    }

    pub fn set_str(&self, value: String) -> AttributeResult<()> {
        (&self.file).seek(SeekFrom::Start(0))?;
        (&self.file).write_all(value.as_bytes())?;
        Ok(())
    }

    pub fn get_int(&self) -> AttributeResult<isize> {
        let value = self.get_str()?;
        Ok(value.parse::<isize>().unwrap())
    }

    pub fn set_int(&self, value: isize) -> AttributeResult<()> {
        self.set_str(value.to_string())
    }

    pub fn get_float(&self) -> AttributeResult<f32> {
        let value = self.get_str()?;
        Ok(value.parse::<f32>().unwrap())
    }

    pub fn set_float(&self, value: f32) -> AttributeResult<()> {
        self.set_str(value.to_string())
    }

    pub fn get_vec(&self) -> AttributeResult<Vec<String>> {
        let value = self.get_str()?;
        let vec = value
            .split_whitespace()
            .map(|word| word.to_string())
            .collect();
        Ok(vec)
    }
}

pub struct Driver {
    class_name: String,
    name: String,
    attributes: HashMap<String, Attribute>,
}

impl Driver {
    pub fn new(class_name: String, name: String) -> Driver {
        Driver {
            class_name,
            name,
            attributes: HashMap::new(),
        }
    }

    pub fn find_name_by_port_and_driver(class_name: &str, port: &Port, driver_name: &str) -> Option<String> {
        let port_address = port.address();

        let mut filename = String::from(ROOT_PATH);
        filename.push_str(class_name);
        let paths = fs::read_dir(filename).unwrap();

        for path in paths {
            let file_name = path.unwrap().file_name();
            let name = file_name.to_str().unwrap();

            let address = Attribute::new(class_name, name, "address").unwrap();

            if address.get_str().unwrap() == port_address {
                let driver = Attribute::new(class_name, name, "driver_name").unwrap();

                if driver.get_str().unwrap() == driver_name {
                    return Some(String::from(name));
                }
            }
        }
        None
    }

    pub fn find_name_by_port(class_name: &str, port: &Port) -> Option<String> {
        let port_address = port.address();

        let mut filename = String::from(ROOT_PATH);
        filename.push_str(class_name);
        let paths = fs::read_dir(filename).unwrap();

        for path in paths {
            let file_name = path.unwrap().file_name();
            let name = file_name.to_str().unwrap();

            let address = Attribute::new(class_name, name, "address").unwrap();

            if address.get_str().unwrap() == port_address {
                return Some(String::from(name));
            }
        }
        None
    }

    pub fn find_name_by_driver(class_name: &str, driver_name: &str) -> Option<String> {
        let mut filename = String::from(ROOT_PATH);
        filename.push_str(class_name);
        let paths = fs::read_dir(filename).unwrap();

        for path in paths {
            let file_name = path.unwrap().file_name();
            let name = file_name.to_str().unwrap();

            let driver = Attribute::new(class_name, name, "driver_name").unwrap();

            if driver.get_str().unwrap() == driver_name {
                return Some(String::from(name));
            }
        }
        None
    }

    pub fn get_attribute(&mut self, attribute_name: &str) -> &Attribute {
        if !self.attributes.contains_key(attribute_name) {
            if let Some(v) = Attribute::new(self.class_name.as_ref(), self.name.as_ref(), attribute_name) {
                self.attributes.insert(String::from(attribute_name), v);
            };
        };

        return self.attributes.get(attribute_name).unwrap();
    }
}