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

extern crate postgres;
extern crate crypto;

use self::crypto::scrypt::{scrypt_simple,scrypt_check,ScryptParams};

use self::postgres::{Connection, TlsMode, Result as SQLResult};
use self::postgres::rows::Row;

pub struct Db(Connection);

use super::{Image,Tag,AnyWith,ImageBuilder,VoteImageError,parse_tag};

impl Default for Db { // Чтобы Clippy не жаловался
    fn default() -> Self {
        Self::new()
    }
}

static POSTGRES_LOGIN : &'static str = "easy";
static POSTGRES_PASS : &'static str = "";

lazy_static! {
    static ref SCRYPT_PARAMS: ScryptParams = ScryptParams::new(10, 8, 1); // 10 сильно быстрее чем 14
}

impl Db {
    pub fn new() -> Self {
        let conn = Connection::connect(format!("postgres://{}:{}@localhost", POSTGRES_LOGIN, POSTGRES_PASS), TlsMode::None).unwrap();
        conn.batch_execute("CREATE EXTENSION IF NOT EXISTS citext;
                            CREATE EXTENSION IF NOT EXISTS hstore;
                            CREATE TABLE IF NOT EXISTS images(
                                id SERIAL PRIMARY KEY,
                                name TEXT NOT NULL UNIQUE,
                                tags TEXT[] NOT NULL,
                                uploader TEXT,
                                score INT NOT NULL DEFAULT 0,

                                got_from TEXT,
                                original_link TEXT,
                                rating CHAR
                            );

                            CREATE TABLE IF NOT EXISTS users(
                                id SERIAL PRIMARY KEY,
                                name CITEXT UNIQUE NOT NULL,
                                pass TEXT NOT NULL,
                                votes HSTORE
                            );").unwrap();
        Db(conn)
    }

    /// Сохранить картинку, сгенерировава имя из тэгов
    pub fn add_with_tags_name(&self, tags: &[String], ext: &str, uploader: &str) -> SQLResult<String> {
        let lastnum = self.0.query("SELECT id FROM images ORDER BY id DESC LIMIT 1", &[])?.get(0).get::<_, i32>("id");

        let name = format!("{}_{}.{}", lastnum + 1  , tags.join("_").replace("'","''"),ext);
        self.add_image(&ImageBuilder::new(&name, tags).uploader(uploader).finalize())?;
        Ok(name)
    }

    pub fn add_image(&self, image: &ImageBuilder) -> SQLResult<()> {
        self.0.execute("INSERT into images (name,
                                            tags,
                                            got_from,
                                            original_link,
                                            rating,
                                            uploader,
                                            score)
                       VALUES ($1,
                               $2,
                               $3,
                               $4,
                               $5,
                               $6,
                               $7) ON CONFLICT (name) DO UPDATE SET tags = $2, score = $7",
        &[&image.name,&image.tags,&image.got_from, &image.original_link,&image.rating.map(|x| x.to_string()), &image.uploader, &image.score]).unwrap();
        Ok(())
    }

    pub fn get_image(&self, id: i32) -> SQLResult<Option<Image>> {
        let rows = self.0.query("SELECT * FROM images WHERE id = $1", &[&id])?;
        Ok(if !rows.is_empty() {
            Some(Db::extract_image(rows.get(0)))
        } else {
            None
        })
    }

    pub fn get_images<T: Into<Option<i32>>>(&self, take: T, skip: usize) -> SQLResult<Vec<Image>>{
        let take = match take.into() {
            Some(x) => x.to_string(),
            None    => "ALL".to_string()
        };

        Ok(self.0.query(&format!("SELECT * FROM images ORDER BY id DESC LIMIT {} OFFSET {}", take, skip as i32),&[])?
           .iter().fold(Vec::new(), |mut acc, row| {
               acc.push(Db::extract_image(row));
               acc
           }))
    }

    pub fn by_tags<T: Into<Option<i32>>>(&self, take: T, skip: usize, tags: &[String]) -> SQLResult<Vec<Image>> {
        let tags = tags.iter().map(|x| parse_tag(x)).collect::<Vec<_>>();
        let order = tags.iter().filter_map(|x| {
            match *x {
                Tag::OrderBy(ref by, ref ascdesc) => {
                    Some(format!("{:?}", by).to_lowercase() + " " + &format!("{:?}", ascdesc).to_uppercase())
                },
                _   => None
            }
        }).collect::<Vec<_>>();
        let order = match order.last() {
            Some(t) => t,
            None    => "id DESC"
        };

        let q = tags.clone().iter().map(|t| {
            match *t {
                Tag::Include(ref incl) => format!(r"tags @> ARRAY['{}']", incl),
                Tag::Exclude(ref excl) => format!(r"NOT tags @> ARRAY['{}']", excl),
                Tag::AnyWith(ref x) => match *x {
                    AnyWith::Before(ref bef) => format!(r"(SELECT bool_or(tag ~ '^{}') FROM unnest(tags) t (tag))", bef),
                    AnyWith::After(ref aft) => format!(r"(SELECT bool_or(tag ~ '{}$') FROM unnest(tags) t (tag))", aft),
                },
                Tag::Rating(ref r) => {
                    let mut s = "(".to_string();
                    for tg in r {
                        s.push_str(&format!("rating = '{}' OR ", tg))
                    }
                    let _ = (0..4).inspect(|_| {s.pop(); }).collect::<Vec<_>>();
                    s.push_str(")");

                    s
                },

                Tag::From(ref f) => {
                    let mut s = "(".to_string();
                    for tg in f {
                        s.push_str(&format!("got_from = '{}' OR ", tg))
                    }
                    let _ = (0..4).inspect(|_| {s.pop(); }).collect::<Vec<_>>();
                    s.push_str(")");

                    s
                },

                Tag::Uploader(ref u) => {
                    let mut s = "(".to_string();
                    for tg in u {
                        s.push_str(&format!("uploader = '{}' OR ", tg))
                    }
                    let _ = (0..4).inspect(|_| {s.pop(); }).collect::<Vec<_>>();
                    s.push_str(")");

                    s
                },
                Tag::OrderBy(_,_) => {String::new()}
            }
        }).filter(|x| !x.is_empty()).collect::<Vec<_>>().join(" AND ");
        let q = if !q.is_empty() {
            format!("WHERE {}", q)
        } else {
            String::new()
        };

        let take = match take.into() {
            Some(x) => x.to_string(),
            None    => "ALL".to_string()
        };

        Ok(self.0.query(&format!("SELECT * FROM images {} ORDER BY {} LIMIT {} OFFSET {}", q, order, take, skip),&[])?
           .iter().fold(Vec::new(), |mut acc, row| {
               acc.push(Db::extract_image(row));
               acc
           }))
    }

    pub fn delete_image(&self, id: i32) -> SQLResult<String> {
        let name = self.0.query("SELECT * FROM images WHERE id = $1", &[&id])?.get(0).get::<_,String>("name");
        self.0.execute("DELETE FROM images WHERE id = $1", &[&id])?;
        Ok(name)
    }

    // true - всё хорошо, false - пользователь уже существует
    pub fn add_user(&self, login: &str, pass: &str) -> SQLResult<bool> {
        if self.0.query("SELECT * FROM users WHERE name = $1", &[&login])?.is_empty() && login.to_lowercase() != "sync" {
            let pass = scrypt_simple(pass, &SCRYPT_PARAMS).unwrap();

            self.0.execute("INSERT INTO users (name,pass) VALUES ($1,$2)", &[&login, &pass])?;
            Ok(true)
        } else {
            Ok(false)
        }
    }

    ///Result показывает ошибки в базе, Option - существует пользователь или нет
    pub fn check_user(&self, login: &str, pass: &str) -> SQLResult<Option<bool>> {
        let pass_hash = self.0.query("SELECT * FROM USERS WHERE name = $1", &[&login])?;
        if pass_hash.is_empty() {
            Ok(None)
        } else {
            let pass_hash = pass_hash.get(0).get::<_, String>("pass");
            Ok(Some(scrypt_check(pass, &pass_hash).unwrap()))
        }
    }

    // true - плюсик, false - минус, возвращает новое число голосов
    pub fn vote_image(&self, login: &str, image_id: i32 ,vote: bool) -> SQLResult<Result<i32, VoteImageError>> {
        let tr = self.0.transaction()?;
        let votechar =  if vote { "+" } else { "-" }.to_string();
        let previous = tr.query("SELECT votes -> $2 AS vote FROM users WHERE name = $1", &[&login, &image_id.to_string()])?;

        let newcount = if !previous.is_empty() && previous.get(0).get::<_,Option<String>>("vote") == Some(votechar.to_owned()) {
            tr.set_rollback();
            Err(VoteImageError::Already)
        } else {
            let res = if vote {
                tr.query("UPDATE images SET score = score + 1 WHERE id = $1 RETURNING score", &[&image_id])?
            } else {
                tr.query("UPDATE images SET score = score - 1 WHERE id = $1 RETURNING score", &[&image_id])?
            };
            if !res.is_empty() {
                tr.set_commit();
                Ok(res.get(0).get::<_,i32>("score"))
            } else {
                tr.set_rollback();
                Err(VoteImageError::NoImage)
            }
        };

        tr.execute("UPDATE users SET votes = hstore($2,$3) WHERE name = $1", &[&login, &image_id.to_string(), &votechar])?;

        Ok(newcount)
    }

    fn extract_image(row: Row) -> Image {
        Image{
            id: row.get("id"),
            name: row.get("name"),
            tags: row.get("tags"),
            got_from: row.get::<_, Option<String>>("got_from"),
            original_link: row.get::<_, Option<String>>("original_link"),
            rating: row.get::<_,Option<String>>("rating").map(|x| x.to_string().chars().collect::<Vec<_>>()[0]),
            uploader: row.get::<_,Option<String>>("uploader"),
            score: row.get::<_,i32>("score")
        }
    }
}
<commit_msg>Надо бы его задействовать<commit_after>#![cfg(feature = "postgresql")]

extern crate postgres;
extern crate crypto;

use self::crypto::scrypt::{scrypt_simple,scrypt_check,ScryptParams};

use self::postgres::{Connection, TlsMode, Result as SQLResult};
use self::postgres::rows::Row;

pub struct Db(Connection);

use super::{Image,Tag,AnyWith,ImageBuilder,VoteImageError,parse_tag};
use super::super::CONFIG;

impl Default for Db { // Чтобы Clippy не жаловался
    fn default() -> Self {
        Self::new()
    }
}

lazy_static! {
    static ref SCRYPT_PARAMS: ScryptParams = ScryptParams::new(10, 8, 1); // 10 сильно быстрее чем 14
}

impl Db {
    pub fn new() -> Self {
        let conn = Connection::connect(format!("postgres://{}:{}@localhost", config!("postgres-login"), config!("postgres-password")), TlsMode::None).unwrap();
        conn.batch_execute("CREATE EXTENSION IF NOT EXISTS citext;
                            CREATE EXTENSION IF NOT EXISTS hstore;
                            CREATE TABLE IF NOT EXISTS images(
                                id SERIAL PRIMARY KEY,
                                name TEXT NOT NULL UNIQUE,
                                tags TEXT[] NOT NULL,
                                uploader TEXT,
                                score INT NOT NULL DEFAULT 0,

                                got_from TEXT,
                                original_link TEXT,
                                rating CHAR
                            );

                            CREATE TABLE IF NOT EXISTS users(
                                id SERIAL PRIMARY KEY,
                                name CITEXT UNIQUE NOT NULL,
                                pass TEXT NOT NULL,
                                votes HSTORE
                            );").unwrap();
        Db(conn)
    }

    /// Сохранить картинку, сгенерировава имя из тэгов
    pub fn add_with_tags_name(&self, tags: &[String], ext: &str, uploader: &str) -> SQLResult<String> {
        let lastnum = self.0.query("SELECT id FROM images ORDER BY id DESC LIMIT 1", &[])?.get(0).get::<_, i32>("id");

        let name = format!("{}_{}.{}", lastnum + 1  , tags.join("_").replace("'","''"),ext);
        self.add_image(&ImageBuilder::new(&name, tags).uploader(uploader).finalize())?;
        Ok(name)
    }

    pub fn add_image(&self, image: &ImageBuilder) -> SQLResult<()> {
        self.0.execute("INSERT into images (name,
                                            tags,
                                            got_from,
                                            original_link,
                                            rating,
                                            uploader,
                                            score)
                       VALUES ($1,
                               $2,
                               $3,
                               $4,
                               $5,
                               $6,
                               $7) ON CONFLICT (name) DO UPDATE SET tags = $2, score = $7",
        &[&image.name,&image.tags,&image.got_from, &image.original_link,&image.rating.map(|x| x.to_string()), &image.uploader, &image.score]).unwrap();
        Ok(())
    }

    pub fn get_image(&self, id: i32) -> SQLResult<Option<Image>> {
        let rows = self.0.query("SELECT * FROM images WHERE id = $1", &[&id])?;
        Ok(if !rows.is_empty() {
            Some(Db::extract_image(rows.get(0)))
        } else {
            None
        })
    }

    pub fn get_images<T: Into<Option<i32>>>(&self, take: T, skip: usize) -> SQLResult<Vec<Image>>{
        let take = match take.into() {
            Some(x) => x.to_string(),
            None    => "ALL".to_string()
        };

        Ok(self.0.query(&format!("SELECT * FROM images ORDER BY id DESC LIMIT {} OFFSET {}", take, skip as i32),&[])?
           .iter().fold(Vec::new(), |mut acc, row| {
               acc.push(Db::extract_image(row));
               acc
           }))
    }

    pub fn by_tags<T: Into<Option<i32>>>(&self, take: T, skip: usize, tags: &[String]) -> SQLResult<Vec<Image>> {
        let tags = tags.iter().map(|x| parse_tag(x)).collect::<Vec<_>>();
        let order = tags.iter().filter_map(|x| {
            match *x {
                Tag::OrderBy(ref by, ref ascdesc) => {
                    Some(format!("{:?}", by).to_lowercase() + " " + &format!("{:?}", ascdesc).to_uppercase())
                },
                _   => None
            }
        }).collect::<Vec<_>>();
        let order = match order.last() {
            Some(t) => t,
            None    => "id DESC"
        };

        let q = tags.clone().iter().map(|t| {
            match *t {
                Tag::Include(ref incl) => format!(r"tags @> ARRAY['{}']", incl),
                Tag::Exclude(ref excl) => format!(r"NOT tags @> ARRAY['{}']", excl),
                Tag::AnyWith(ref x) => match *x {
                    AnyWith::Before(ref bef) => format!(r"(SELECT bool_or(tag ~ '^{}') FROM unnest(tags) t (tag))", bef),
                    AnyWith::After(ref aft) => format!(r"(SELECT bool_or(tag ~ '{}$') FROM unnest(tags) t (tag))", aft),
                },
                Tag::Rating(ref r) => {
                    let mut s = "(".to_string();
                    for tg in r {
                        s.push_str(&format!("rating = '{}' OR ", tg))
                    }
                    let _ = (0..4).inspect(|_| {s.pop(); }).collect::<Vec<_>>();
                    s.push_str(")");

                    s
                },

                Tag::From(ref f) => {
                    let mut s = "(".to_string();
                    for tg in f {
                        s.push_str(&format!("got_from = '{}' OR ", tg))
                    }
                    let _ = (0..4).inspect(|_| {s.pop(); }).collect::<Vec<_>>();
                    s.push_str(")");

                    s
                },

                Tag::Uploader(ref u) => {
                    let mut s = "(".to_string();
                    for tg in u {
                        s.push_str(&format!("uploader = '{}' OR ", tg))
                    }
                    let _ = (0..4).inspect(|_| {s.pop(); }).collect::<Vec<_>>();
                    s.push_str(")");

                    s
                },
                Tag::OrderBy(_,_) => {String::new()}
            }
        }).filter(|x| !x.is_empty()).collect::<Vec<_>>().join(" AND ");
        let q = if !q.is_empty() {
            format!("WHERE {}", q)
        } else {
            String::new()
        };

        let take = match take.into() {
            Some(x) => x.to_string(),
            None    => "ALL".to_string()
        };

        Ok(self.0.query(&format!("SELECT * FROM images {} ORDER BY {} LIMIT {} OFFSET {}", q, order, take, skip),&[])?
           .iter().fold(Vec::new(), |mut acc, row| {
               acc.push(Db::extract_image(row));
               acc
           }))
    }

    pub fn delete_image(&self, id: i32) -> SQLResult<String> {
        let name = self.0.query("SELECT * FROM images WHERE id = $1", &[&id])?.get(0).get::<_,String>("name");
        self.0.execute("DELETE FROM images WHERE id = $1", &[&id])?;
        Ok(name)
    }

    // true - всё хорошо, false - пользователь уже существует
    pub fn add_user(&self, login: &str, pass: &str) -> SQLResult<bool> {
        if self.0.query("SELECT * FROM users WHERE name = $1", &[&login])?.is_empty() && login.to_lowercase() != "sync" {
            let pass = scrypt_simple(pass, &SCRYPT_PARAMS).unwrap();

            self.0.execute("INSERT INTO users (name,pass) VALUES ($1,$2)", &[&login, &pass])?;
            Ok(true)
        } else {
            Ok(false)
        }
    }

    ///Result показывает ошибки в базе, Option - существует пользователь или нет
    pub fn check_user(&self, login: &str, pass: &str) -> SQLResult<Option<bool>> {
        let pass_hash = self.0.query("SELECT * FROM USERS WHERE name = $1", &[&login])?;
        if pass_hash.is_empty() {
            Ok(None)
        } else {
            let pass_hash = pass_hash.get(0).get::<_, String>("pass");
            Ok(Some(scrypt_check(pass, &pass_hash).unwrap()))
        }
    }

    // true - плюсик, false - минус, возвращает новое число голосов
    pub fn vote_image(&self, login: &str, image_id: i32 ,vote: bool) -> SQLResult<Result<i32, VoteImageError>> {
        let tr = self.0.transaction()?;
        let votechar =  if vote { "+" } else { "-" }.to_string();
        let previous = tr.query("SELECT votes -> $2 AS vote FROM users WHERE name = $1", &[&login, &image_id.to_string()])?;

        let newcount = if !previous.is_empty() && previous.get(0).get::<_,Option<String>>("vote") == Some(votechar.to_owned()) {
            tr.set_rollback();
            Err(VoteImageError::Already)
        } else {
            let res = if vote {
                tr.query("UPDATE images SET score = score + 1 WHERE id = $1 RETURNING score", &[&image_id])?
            } else {
                tr.query("UPDATE images SET score = score - 1 WHERE id = $1 RETURNING score", &[&image_id])?
            };
            if !res.is_empty() {
                tr.set_commit();
                Ok(res.get(0).get::<_,i32>("score"))
            } else {
                tr.set_rollback();
                Err(VoteImageError::NoImage)
            }
        };

        tr.execute("UPDATE users SET votes = hstore($2,$3) WHERE name = $1", &[&login, &image_id.to_string(), &votechar])?;

        Ok(newcount)
    }

    fn extract_image(row: Row) -> Image {
        Image{
            id: row.get("id"),
            name: row.get("name"),
            tags: row.get("tags"),
            got_from: row.get::<_, Option<String>>("got_from"),
            original_link: row.get::<_, Option<String>>("original_link"),
            rating: row.get::<_,Option<String>>("rating").map(|x| x.to_string().chars().collect::<Vec<_>>()[0]),
            uploader: row.get::<_,Option<String>>("uploader"),
            score: row.get::<_,i32>("score")
        }
    }
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::fmt;
use std::slice::Iter;

pub const DBUS_TIMEOUT: i32 = 20000; // millieconds

pub const STRATIS_VERSION: &'static str = "1";
pub const MANAGER_NAME: &'static str = "/Manager";
pub const STRATIS_BASE_PATH: &'static str = "/org/storage/stratis1";
pub const STRATIS_BASE_SERVICE: &'static str = "org.storage.stratis1";
pub const STRATIS_BASE_MANAGER: &'static str = "/org/storage/stratis1/Manager";
pub const STRATIS_MANAGER_INTERFACE: &'static str = "org.storage.stratis1.Manager";
pub const STRATIS_POOL_BASE_INTERFACE: &'static str = "org.storage.stratis1.pool";
pub const STRATIS_VOLUME_BASE_INTERFACE: &'static str = "org.storage.stratis1.volume";
pub const STRATIS_DEV_BASE_INTERFACE: &'static str = "org.storage.stratis1.dev";
pub const STRATIS_CACHE_BASE_INTERFACE: &'static str = "org.storage.stratis1.cache";
pub const STRATIS_POOL_BASE_PATH: &'static str = "/org/storage/stratis/pool";

pub const LIST_POOLS: &'static str = "ListPools";
pub const CREATE_POOL: &'static str = "CreatePool";
pub const DESTROY_POOL: &'static str = "DestroyPool";
pub const GET_POOL_OBJECT_PATH: &'static str = "GetPoolObjectPath";
pub const GET_VOLUME_OBJECT_PATH: &'static str = "GetVolumeObjectPath";
pub const GET_DEV_OBJECT_PATH: &'static str = "GetDevObjectPath";
pub const GET_CACHE_OBJECT_PATH: &'static str = "GetCacheObjectPath";
pub const GET_ERROR_CODES: &'static str = "GetErrorCodes";
pub const GET_RAID_LEVELS: &'static str = "GetRaidLevels";
pub const GET_DEV_TYPES: &'static str = "GetDevTypes";

#[derive(Copy, Clone)]
#[allow(non_camel_case_types)]
pub enum StratisErrorEnum {
    STRATIS_OK,
    STRATIS_ERROR,
    STRATIS_NULL,
    STRATIS_NOTFOUND,
    STRATIS_POOL_NOTFOUND,
    STRATIS_VOLUME_NOTFOUND,
    STRATIS_DEV_NOTFOUND,
    STRATIS_CACHE_NOTFOUND,
    STRATIS_BAD_PARAM,
    STRATIS_ALREADY_EXISTS,
    STRATIS_NULL_NAME,
    STRATIS_NO_POOLS,
    STRATIS_LIST_FAILURE,
}

impl StratisErrorEnum {
    pub fn iterator() -> Iter<'static, StratisErrorEnum> {
        static CODES: [StratisErrorEnum; 13] = [StratisErrorEnum::STRATIS_OK,
                                                StratisErrorEnum::STRATIS_ERROR,
                                                StratisErrorEnum::STRATIS_NULL,
                                                StratisErrorEnum::STRATIS_NOTFOUND,
                                                StratisErrorEnum::STRATIS_POOL_NOTFOUND,
                                                StratisErrorEnum::STRATIS_VOLUME_NOTFOUND,
                                                StratisErrorEnum::STRATIS_DEV_NOTFOUND,
                                                StratisErrorEnum::STRATIS_CACHE_NOTFOUND,
                                                StratisErrorEnum::STRATIS_BAD_PARAM,
                                                StratisErrorEnum::STRATIS_ALREADY_EXISTS,
                                                StratisErrorEnum::STRATIS_NULL_NAME,
                                                StratisErrorEnum::STRATIS_NO_POOLS,
                                                StratisErrorEnum::STRATIS_LIST_FAILURE];
        CODES.into_iter()
    }

    pub fn get_error_int(error: &StratisErrorEnum) -> u16 {
        *error as u16
    }

    pub fn get_error_string(error: &StratisErrorEnum) -> &str {
        match *error {
            // TODO deal with internationalization/do this better
            StratisErrorEnum::STRATIS_OK => "Ok",
            StratisErrorEnum::STRATIS_ERROR => "A general error happened",
            StratisErrorEnum::STRATIS_NULL => "Null parameter was supplied",
            StratisErrorEnum::STRATIS_NOTFOUND => "Not found",
            StratisErrorEnum::STRATIS_POOL_NOTFOUND => "Pool not found",
            StratisErrorEnum::STRATIS_VOLUME_NOTFOUND => "Volume not found",
            StratisErrorEnum::STRATIS_CACHE_NOTFOUND => "Cache not found",
            StratisErrorEnum::STRATIS_BAD_PARAM => "Bad parameter",
            StratisErrorEnum::STRATIS_DEV_NOTFOUND => "Dev not found",
            StratisErrorEnum::STRATIS_ALREADY_EXISTS => "Already exists",
            StratisErrorEnum::STRATIS_NULL_NAME => "Null name supplied",
            StratisErrorEnum::STRATIS_NO_POOLS => "No pools",
            StratisErrorEnum::STRATIS_LIST_FAILURE => "List operation failure.",
        }
    }
}

impl fmt::Display for StratisErrorEnum {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            StratisErrorEnum::STRATIS_OK => write!(f, "STRATIS_OK"),
            StratisErrorEnum::STRATIS_ERROR => write!(f, "STRATIS_ERROR"),
            StratisErrorEnum::STRATIS_NULL => write!(f, "STRATIS_NULL"),
            StratisErrorEnum::STRATIS_NOTFOUND => write!(f, "STRATIS_NOTFOUND"),
            StratisErrorEnum::STRATIS_POOL_NOTFOUND => write!(f, "STRATIS_POOL_NOTFOUND"),
            StratisErrorEnum::STRATIS_VOLUME_NOTFOUND => write!(f, "STRATIS_VOLUME_NOTFOUND"),
            StratisErrorEnum::STRATIS_CACHE_NOTFOUND => write!(f, "STRATIS_CACHE_NOTFOUND"),
            StratisErrorEnum::STRATIS_BAD_PARAM => write!(f, "STRATIS_BAD_PARAM"),
            StratisErrorEnum::STRATIS_DEV_NOTFOUND => write!(f, "STRATIS_DEV_NOTFOUND"),
            StratisErrorEnum::STRATIS_ALREADY_EXISTS => write!(f, "STRATIS_ALREADY_EXISTS"),
            StratisErrorEnum::STRATIS_NULL_NAME => write!(f, "STRATIS_NULL_NAME"),
            StratisErrorEnum::STRATIS_NO_POOLS => write!(f, "STRATIS_NO_POOLS"),
            StratisErrorEnum::STRATIS_LIST_FAILURE => write!(f, "STRATIS_LIST_FAILURE"),
        }
    }
}

#[derive(Copy, Clone)]
#[allow(non_camel_case_types)]
pub enum StratisRaidType {
    STRATIS_RAID_TYPE_UNKNOWN,
    /** Single */
    STRATIS_RAID_TYPE_SINGLE,
    /** Mirror between two disks. For 4 disks or more, they are RAID10.*/
    STRATIS_RAID_TYPE_RAID1,
    /** Block-level striping with distributed parity */
    STRATIS_RAID_TYPE_RAID5,
    /** Block-level striping with two distributed parities, aka, RAID-DP */
    STRATIS_RAID_TYPE_RAID6,
}

impl StratisRaidType {
    pub fn iterator() -> Iter<'static, StratisRaidType> {
        static TYPES: [StratisRaidType; 5] = [StratisRaidType::STRATIS_RAID_TYPE_UNKNOWN,
                                              StratisRaidType::STRATIS_RAID_TYPE_SINGLE,
                                              StratisRaidType::STRATIS_RAID_TYPE_RAID1,
                                              StratisRaidType::STRATIS_RAID_TYPE_RAID5,
                                              StratisRaidType::STRATIS_RAID_TYPE_RAID6];
        TYPES.into_iter()
    }

    pub fn get_error_int(error: &StratisRaidType) -> u16 {
        *error as u16
    }

    pub fn get_error_string(error: &StratisRaidType) -> &str {
        match *error {
            // TODO deal with internationalization/do this better
            StratisRaidType::STRATIS_RAID_TYPE_UNKNOWN => "Ok",
            StratisRaidType::STRATIS_RAID_TYPE_SINGLE => "Single",
            StratisRaidType::STRATIS_RAID_TYPE_RAID1 => {
                "Mirror between two disks. For 4 disks or more, they are RAID10"
            }
            StratisRaidType::STRATIS_RAID_TYPE_RAID5 => {
                "Block-level striping with distributed parity"
            }
            StratisRaidType::STRATIS_RAID_TYPE_RAID6 => {
                "Block-level striping with two distributed parities, aka, RAID-DP"
            }
        }
    }
}

impl fmt::Display for StratisRaidType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            StratisRaidType::STRATIS_RAID_TYPE_UNKNOWN => write!(f, "STRATIS_RAID_TYPE_UNKNOWN"),
            StratisRaidType::STRATIS_RAID_TYPE_SINGLE => write!(f, "STRATIS_RAID_TYPE_SINGLE"),
            StratisRaidType::STRATIS_RAID_TYPE_RAID1 => write!(f, "STRATIS_RAID_TYPE_RAID1"),
            StratisRaidType::STRATIS_RAID_TYPE_RAID5 => write!(f, "STRATIS_RAID_TYPE_RAID5"),
            StratisRaidType::STRATIS_RAID_TYPE_RAID6 => write!(f, "STRATIS_RAID_TYPE_RAID6"),
        }
    }
}
<commit_msg>Get rid of a TODO.<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::fmt;
use std::slice::Iter;

pub const DBUS_TIMEOUT: i32 = 20000; // millieconds

pub const STRATIS_VERSION: &'static str = "1";
pub const MANAGER_NAME: &'static str = "/Manager";
pub const STRATIS_BASE_PATH: &'static str = "/org/storage/stratis1";
pub const STRATIS_BASE_SERVICE: &'static str = "org.storage.stratis1";
pub const STRATIS_BASE_MANAGER: &'static str = "/org/storage/stratis1/Manager";
pub const STRATIS_MANAGER_INTERFACE: &'static str = "org.storage.stratis1.Manager";
pub const STRATIS_POOL_BASE_INTERFACE: &'static str = "org.storage.stratis1.pool";
pub const STRATIS_VOLUME_BASE_INTERFACE: &'static str = "org.storage.stratis1.volume";
pub const STRATIS_DEV_BASE_INTERFACE: &'static str = "org.storage.stratis1.dev";
pub const STRATIS_CACHE_BASE_INTERFACE: &'static str = "org.storage.stratis1.cache";
pub const STRATIS_POOL_BASE_PATH: &'static str = "/org/storage/stratis/pool";

pub const LIST_POOLS: &'static str = "ListPools";
pub const CREATE_POOL: &'static str = "CreatePool";
pub const DESTROY_POOL: &'static str = "DestroyPool";
pub const GET_POOL_OBJECT_PATH: &'static str = "GetPoolObjectPath";
pub const GET_VOLUME_OBJECT_PATH: &'static str = "GetVolumeObjectPath";
pub const GET_DEV_OBJECT_PATH: &'static str = "GetDevObjectPath";
pub const GET_CACHE_OBJECT_PATH: &'static str = "GetCacheObjectPath";
pub const GET_ERROR_CODES: &'static str = "GetErrorCodes";
pub const GET_RAID_LEVELS: &'static str = "GetRaidLevels";
pub const GET_DEV_TYPES: &'static str = "GetDevTypes";

#[derive(Copy, Clone)]
#[allow(non_camel_case_types)]
pub enum StratisErrorEnum {
    STRATIS_OK,
    STRATIS_ERROR,
    STRATIS_NULL,
    STRATIS_NOTFOUND,
    STRATIS_POOL_NOTFOUND,
    STRATIS_VOLUME_NOTFOUND,
    STRATIS_DEV_NOTFOUND,
    STRATIS_CACHE_NOTFOUND,
    STRATIS_BAD_PARAM,
    STRATIS_ALREADY_EXISTS,
    STRATIS_NULL_NAME,
    STRATIS_NO_POOLS,
    STRATIS_LIST_FAILURE,
}

impl StratisErrorEnum {
    pub fn iterator() -> Iter<'static, StratisErrorEnum> {
        static CODES: [StratisErrorEnum; 13] = [StratisErrorEnum::STRATIS_OK,
                                                StratisErrorEnum::STRATIS_ERROR,
                                                StratisErrorEnum::STRATIS_NULL,
                                                StratisErrorEnum::STRATIS_NOTFOUND,
                                                StratisErrorEnum::STRATIS_POOL_NOTFOUND,
                                                StratisErrorEnum::STRATIS_VOLUME_NOTFOUND,
                                                StratisErrorEnum::STRATIS_DEV_NOTFOUND,
                                                StratisErrorEnum::STRATIS_CACHE_NOTFOUND,
                                                StratisErrorEnum::STRATIS_BAD_PARAM,
                                                StratisErrorEnum::STRATIS_ALREADY_EXISTS,
                                                StratisErrorEnum::STRATIS_NULL_NAME,
                                                StratisErrorEnum::STRATIS_NO_POOLS,
                                                StratisErrorEnum::STRATIS_LIST_FAILURE];
        CODES.into_iter()
    }

    pub fn get_error_int(error: &StratisErrorEnum) -> u16 {
        *error as u16
    }

    pub fn get_error_string(error: &StratisErrorEnum) -> &str {
        match *error {
            // TODO deal with internationalization/do this better
            StratisErrorEnum::STRATIS_OK => "Ok",
            StratisErrorEnum::STRATIS_ERROR => "A general error happened",
            StratisErrorEnum::STRATIS_NULL => "Null parameter was supplied",
            StratisErrorEnum::STRATIS_NOTFOUND => "Not found",
            StratisErrorEnum::STRATIS_POOL_NOTFOUND => "Pool not found",
            StratisErrorEnum::STRATIS_VOLUME_NOTFOUND => "Volume not found",
            StratisErrorEnum::STRATIS_CACHE_NOTFOUND => "Cache not found",
            StratisErrorEnum::STRATIS_BAD_PARAM => "Bad parameter",
            StratisErrorEnum::STRATIS_DEV_NOTFOUND => "Dev not found",
            StratisErrorEnum::STRATIS_ALREADY_EXISTS => "Already exists",
            StratisErrorEnum::STRATIS_NULL_NAME => "Null name supplied",
            StratisErrorEnum::STRATIS_NO_POOLS => "No pools",
            StratisErrorEnum::STRATIS_LIST_FAILURE => "List operation failure.",
        }
    }
}

impl fmt::Display for StratisErrorEnum {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            StratisErrorEnum::STRATIS_OK => write!(f, "STRATIS_OK"),
            StratisErrorEnum::STRATIS_ERROR => write!(f, "STRATIS_ERROR"),
            StratisErrorEnum::STRATIS_NULL => write!(f, "STRATIS_NULL"),
            StratisErrorEnum::STRATIS_NOTFOUND => write!(f, "STRATIS_NOTFOUND"),
            StratisErrorEnum::STRATIS_POOL_NOTFOUND => write!(f, "STRATIS_POOL_NOTFOUND"),
            StratisErrorEnum::STRATIS_VOLUME_NOTFOUND => write!(f, "STRATIS_VOLUME_NOTFOUND"),
            StratisErrorEnum::STRATIS_CACHE_NOTFOUND => write!(f, "STRATIS_CACHE_NOTFOUND"),
            StratisErrorEnum::STRATIS_BAD_PARAM => write!(f, "STRATIS_BAD_PARAM"),
            StratisErrorEnum::STRATIS_DEV_NOTFOUND => write!(f, "STRATIS_DEV_NOTFOUND"),
            StratisErrorEnum::STRATIS_ALREADY_EXISTS => write!(f, "STRATIS_ALREADY_EXISTS"),
            StratisErrorEnum::STRATIS_NULL_NAME => write!(f, "STRATIS_NULL_NAME"),
            StratisErrorEnum::STRATIS_NO_POOLS => write!(f, "STRATIS_NO_POOLS"),
            StratisErrorEnum::STRATIS_LIST_FAILURE => write!(f, "STRATIS_LIST_FAILURE"),
        }
    }
}

#[derive(Copy, Clone)]
#[allow(non_camel_case_types)]
pub enum StratisRaidType {
    STRATIS_RAID_TYPE_UNKNOWN,
    /** Single */
    STRATIS_RAID_TYPE_SINGLE,
    /** Mirror between two disks. For 4 disks or more, they are RAID10.*/
    STRATIS_RAID_TYPE_RAID1,
    /** Block-level striping with distributed parity */
    STRATIS_RAID_TYPE_RAID5,
    /** Block-level striping with two distributed parities, aka, RAID-DP */
    STRATIS_RAID_TYPE_RAID6,
}

impl StratisRaidType {
    pub fn iterator() -> Iter<'static, StratisRaidType> {
        static TYPES: [StratisRaidType; 5] = [StratisRaidType::STRATIS_RAID_TYPE_UNKNOWN,
                                              StratisRaidType::STRATIS_RAID_TYPE_SINGLE,
                                              StratisRaidType::STRATIS_RAID_TYPE_RAID1,
                                              StratisRaidType::STRATIS_RAID_TYPE_RAID5,
                                              StratisRaidType::STRATIS_RAID_TYPE_RAID6];
        TYPES.into_iter()
    }

    pub fn get_error_int(error: &StratisRaidType) -> u16 {
        *error as u16
    }

    pub fn get_error_string(error: &StratisRaidType) -> &str {
        match *error {
            StratisRaidType::STRATIS_RAID_TYPE_UNKNOWN => "Ok",
            StratisRaidType::STRATIS_RAID_TYPE_SINGLE => "Single",
            StratisRaidType::STRATIS_RAID_TYPE_RAID1 => {
                "Mirror between two disks. For 4 disks or more, they are RAID10"
            }
            StratisRaidType::STRATIS_RAID_TYPE_RAID5 => {
                "Block-level striping with distributed parity"
            }
            StratisRaidType::STRATIS_RAID_TYPE_RAID6 => {
                "Block-level striping with two distributed parities, aka, RAID-DP"
            }
        }
    }
}

impl fmt::Display for StratisRaidType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            StratisRaidType::STRATIS_RAID_TYPE_UNKNOWN => write!(f, "STRATIS_RAID_TYPE_UNKNOWN"),
            StratisRaidType::STRATIS_RAID_TYPE_SINGLE => write!(f, "STRATIS_RAID_TYPE_SINGLE"),
            StratisRaidType::STRATIS_RAID_TYPE_RAID1 => write!(f, "STRATIS_RAID_TYPE_RAID1"),
            StratisRaidType::STRATIS_RAID_TYPE_RAID5 => write!(f, "STRATIS_RAID_TYPE_RAID5"),
            StratisRaidType::STRATIS_RAID_TYPE_RAID6 => write!(f, "STRATIS_RAID_TYPE_RAID6"),
        }
    }
}
<|endoftext|>


<commit_before>
use std::fs::File;
use std::io::{self, BufRead};
use std::path::Path;
use regex::Regex;

#[macro_use]
extern crate lazy_static;

pub fn get_number<P: AsRef<Path>>(filename: P) -> io::Result<u32> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"NUMBER=(\d+)").unwrap();
    }
    let mut matches = match_lines(filename, &*RE)?;
    return Ok(matches.next().unwrap().parse().unwrap());
}

pub fn get_output<'a, P:'a + AsRef<Path>>(filename: P) -> io::Result<impl Iterator<Item = u32> + 'a> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"OUTPUT:(.*)").unwrap();
    }
    get_numbers(filename, &*RE)
}

pub fn get_collection<'a, P:'a + AsRef<Path>>(filename: P, idx: u32) -> io::Result<impl Iterator<Item = u32> + 'a> {
    let regex: Regex = {
        let r = format!("COLLECTION{}:(.*)", idx);
        Regex::new(&r).unwrap()
    };
    get_numbers(filename, &regex)
}

pub fn get_numbers<'a, P:'a + AsRef<Path>>(filename: P, regex: &Regex) -> io::Result<impl Iterator<Item = u32> + 'a> {
    let matches = match_lines(filename, regex)?;
    let values = matches.map(|s| {
        let numbers = s.split(',').map(|v| v.parse::<u32>().unwrap());
        numbers.collect::<Vec<_>>()
    }).flatten();
    Ok(values)
}

fn match_lines<'a, P: 'a + AsRef<Path>>(filename: P, regex: &Regex) -> io::Result<impl Iterator<Item = String> + 'a> {
    let read_lines = move || -> io::Result<_> {
        let file = File::open(filename)?;
        Ok(io::BufReader::new(file).lines().map(|line|
            line.unwrap()))
    };
    let lines = read_lines()?;
    let r = regex.clone(); // TODO
    let matches = lines.filter_map(move |line| {
        r.captures(&line).map(|captures|
            captures[1].to_string()
        )
    });
    Ok(matches)
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_number() {
        assert_eq!(get_number("../data/test.txt").unwrap() , 3);
    }

    #[test]
    fn test_output() {
        let output = [1,1,2,2,3,4,4,6,7,9,9,20,21];
        assert_eq!(get_output("../data/test.txt").unwrap().collect::<Vec<_>>(), output);
    }

    #[test]
    fn test_collection() {
        let output = [2, 4, 6, 9, 20];
        assert_eq!(get_collection("../data/test.txt", 1).unwrap().collect::<Vec<_>>(), output);
    }
}
<commit_msg>Removed all lifetimes<commit_after>
use std::fs::File;
use std::io::{self, BufRead};
use regex::Regex;

#[macro_use]
extern crate lazy_static;

pub fn get_number(filename: &str) -> io::Result<u32> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"NUMBER=(\d+)").unwrap();
    }
    let mut matches = match_lines(filename, &*RE)?;
    return Ok(matches.next().unwrap().parse().unwrap());
}

pub fn get_output(filename: &str) -> io::Result<impl Iterator<Item = u32>> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"OUTPUT:(.*)").unwrap();
    }
    get_numbers(filename, &*RE)
}

pub fn get_collection(filename: &str, idx: u32) -> io::Result<impl Iterator<Item = u32>> {
    let regex: Regex = {
        let r = format!("COLLECTION{}:(.*)", idx);
        Regex::new(&r).unwrap()
    };
    get_numbers(filename, &regex)
}

pub fn get_numbers(filename: &str, regex: &Regex) -> io::Result<impl Iterator<Item = u32>> {
    let matches = match_lines(filename, regex)?;
    let values = matches.map(|s| {
        let numbers = s.split(',').map(|v| v.parse::<u32>().unwrap());
        numbers.collect::<Vec<_>>()
    }).flatten();
    Ok(values)
}

fn match_lines(filename: &str, regex: &Regex) -> io::Result<impl Iterator<Item = String>> {
    let read_lines = move || -> io::Result<_> {
        let file = File::open(filename)?;
        Ok(io::BufReader::new(file).lines().map(|line|
            line.unwrap()))
    };
    let lines = read_lines()?;
    let r = regex.clone(); // TODO
    let matches = lines.filter_map(move |line| {
        r.captures(&line).map(|captures|
            captures[1].to_string()
        )
    });
    Ok(matches)
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_number() {
        assert_eq!(get_number("../data/test.txt").unwrap() , 3);
    }

    #[test]
    fn test_output() {
        let output = [1,1,2,2,3,4,4,6,7,9,9,20,21];
        assert_eq!(get_output("../data/test.txt").unwrap().collect::<Vec<_>>(), output);
    }

    #[test]
    fn test_collection() {
        let output = [2, 4, 6, 9, 20];
        assert_eq!(get_collection("../data/test.txt", 1).unwrap().collect::<Vec<_>>(), output);
    }
}
<|endoftext|>


<commit_before>// run-pass
#![allow(non_camel_case_types)]

// ignore-emscripten

// Test that the simd_select intrinsics produces correct results.

#![feature(repr_simd, platform_intrinsics)]
#[allow(non_camel_case_types)]

#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
struct i32x4(pub i32, pub i32, pub i32, pub i32);

#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
struct u32x4(pub u32, pub u32, pub u32, pub u32);

#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
struct u32x8(u32, u32, u32, u32, u32, u32, u32, u32);

#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
struct f32x4(pub f32, pub f32, pub f32, pub f32);

#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
struct b8x4(pub i8, pub i8, pub i8, pub i8);

extern "platform-intrinsic" {
    fn simd_select<T, U>(x: T, a: U, b: U) -> U;
    fn simd_select_bitmask<T, U>(x: T, a: U, b: U) -> U;
}

fn main() {
    let m0 = b8x4(!0, !0, !0, !0);
    let m1 = b8x4(0, 0, 0, 0);
    let m2 = b8x4(!0, !0, 0, 0);
    let m3 = b8x4(0, 0, !0, !0);
    let m4 = b8x4(!0, 0, !0, 0);

    unsafe {
        let a = i32x4(1, -2, 3, 4);
        let b = i32x4(5, 6, -7, 8);

        let r: i32x4 = simd_select(m0, a, b);
        let e = a;
        assert_eq!(r, e);

        let r: i32x4 = simd_select(m1, a, b);
        let e = b;
        assert_eq!(r, e);

        let r: i32x4 = simd_select(m2, a, b);
        let e = i32x4(1, -2, -7, 8);
        assert_eq!(r, e);

        let r: i32x4 = simd_select(m3, a, b);
        let e = i32x4(5, 6, 3, 4);
        assert_eq!(r, e);

        let r: i32x4 = simd_select(m4, a, b);
        let e = i32x4(1, 6, 3, 8);
        assert_eq!(r, e);
    }

    unsafe {
        let a = u32x4(1, 2, 3, 4);
        let b = u32x4(5, 6, 7, 8);

        let r: u32x4 = simd_select(m0, a, b);
        let e = a;
        assert_eq!(r, e);

        let r: u32x4 = simd_select(m1, a, b);
        let e = b;
        assert_eq!(r, e);

        let r: u32x4 = simd_select(m2, a, b);
        let e = u32x4(1, 2, 7, 8);
        assert_eq!(r, e);

        let r: u32x4 = simd_select(m3, a, b);
        let e = u32x4(5, 6, 3, 4);
        assert_eq!(r, e);

        let r: u32x4 = simd_select(m4, a, b);
        let e = u32x4(1, 6, 3, 8);
        assert_eq!(r, e);
    }

    unsafe {
        let a = f32x4(1., 2., 3., 4.);
        let b = f32x4(5., 6., 7., 8.);

        let r: f32x4 = simd_select(m0, a, b);
        let e = a;
        assert_eq!(r, e);

        let r: f32x4 = simd_select(m1, a, b);
        let e = b;
        assert_eq!(r, e);

        let r: f32x4 = simd_select(m2, a, b);
        let e = f32x4(1., 2., 7., 8.);
        assert_eq!(r, e);

        let r: f32x4 = simd_select(m3, a, b);
        let e = f32x4(5., 6., 3., 4.);
        assert_eq!(r, e);

        let r: f32x4 = simd_select(m4, a, b);
        let e = f32x4(1., 6., 3., 8.);
        assert_eq!(r, e);
    }

    unsafe {
        let t = !0 as i8;
        let f = 0 as i8;
        let a = b8x4(t, f, t, f);
        let b = b8x4(f, f, f, t);

        let r: b8x4 = simd_select(m0, a, b);
        let e = a;
        assert_eq!(r, e);

        let r: b8x4 = simd_select(m1, a, b);
        let e = b;
        assert_eq!(r, e);

        let r: b8x4 = simd_select(m2, a, b);
        let e = b8x4(t, f, f, t);
        assert_eq!(r, e);

        let r: b8x4 = simd_select(m3, a, b);
        let e = b8x4(f, f, t, f);
        assert_eq!(r, e);

        let r: b8x4 = simd_select(m4, a, b);
        let e = b8x4(t, f, t, t);
        assert_eq!(r, e);
    }

    unsafe {
        let a = u32x8(0, 1, 2, 3, 4, 5, 6, 7);
        let b = u32x8(8, 9, 10, 11, 12, 13, 14, 15);

        let r: u32x8 = simd_select_bitmask(0u8, a, b);
        let e = b;
        assert_eq!(r, e);

        let r: u32x8 = simd_select_bitmask(0xffu8, a, b);
        let e = a;
        assert_eq!(r, e);

        let r: u32x8 = simd_select_bitmask(0b01010101u8, a, b);
        let e = u32x8(0, 9, 2, 11, 4, 13, 6, 15);
        assert_eq!(r, e);

        let r: u32x8 = simd_select_bitmask(0b10101010u8, a, b);
        let e = u32x8(8, 1, 10, 3, 12, 5, 14, 7);
        assert_eq!(r, e);

        let r: u32x8 = simd_select_bitmask(0b11110000u8, a, b);
        let e = u32x8(8, 9, 10, 11, 4, 5, 6, 7);
        assert_eq!(r, e);
    }
}
<commit_msg>Rollup merge of #62774 - smaeul:pr/simd-tests, r=petrochenkov<commit_after>// run-pass
#![allow(non_camel_case_types)]

// ignore-emscripten
// ignore-mips       behavior of simd_select_bitmask is endian-specific
// ignore-mips64     behavior of simd_select_bitmask is endian-specific
// ignore-powerpc    behavior of simd_select_bitmask is endian-specific
// ignore-powerpc64  behavior of simd_select_bitmask is endian-specific

// Test that the simd_select intrinsics produces correct results.

#![feature(repr_simd, platform_intrinsics)]
#[allow(non_camel_case_types)]

#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
struct i32x4(pub i32, pub i32, pub i32, pub i32);

#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
struct u32x4(pub u32, pub u32, pub u32, pub u32);

#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
struct u32x8(u32, u32, u32, u32, u32, u32, u32, u32);

#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
struct f32x4(pub f32, pub f32, pub f32, pub f32);

#[repr(simd)]
#[derive(Copy, Clone, PartialEq, Debug)]
struct b8x4(pub i8, pub i8, pub i8, pub i8);

extern "platform-intrinsic" {
    fn simd_select<T, U>(x: T, a: U, b: U) -> U;
    fn simd_select_bitmask<T, U>(x: T, a: U, b: U) -> U;
}

fn main() {
    let m0 = b8x4(!0, !0, !0, !0);
    let m1 = b8x4(0, 0, 0, 0);
    let m2 = b8x4(!0, !0, 0, 0);
    let m3 = b8x4(0, 0, !0, !0);
    let m4 = b8x4(!0, 0, !0, 0);

    unsafe {
        let a = i32x4(1, -2, 3, 4);
        let b = i32x4(5, 6, -7, 8);

        let r: i32x4 = simd_select(m0, a, b);
        let e = a;
        assert_eq!(r, e);

        let r: i32x4 = simd_select(m1, a, b);
        let e = b;
        assert_eq!(r, e);

        let r: i32x4 = simd_select(m2, a, b);
        let e = i32x4(1, -2, -7, 8);
        assert_eq!(r, e);

        let r: i32x4 = simd_select(m3, a, b);
        let e = i32x4(5, 6, 3, 4);
        assert_eq!(r, e);

        let r: i32x4 = simd_select(m4, a, b);
        let e = i32x4(1, 6, 3, 8);
        assert_eq!(r, e);
    }

    unsafe {
        let a = u32x4(1, 2, 3, 4);
        let b = u32x4(5, 6, 7, 8);

        let r: u32x4 = simd_select(m0, a, b);
        let e = a;
        assert_eq!(r, e);

        let r: u32x4 = simd_select(m1, a, b);
        let e = b;
        assert_eq!(r, e);

        let r: u32x4 = simd_select(m2, a, b);
        let e = u32x4(1, 2, 7, 8);
        assert_eq!(r, e);

        let r: u32x4 = simd_select(m3, a, b);
        let e = u32x4(5, 6, 3, 4);
        assert_eq!(r, e);

        let r: u32x4 = simd_select(m4, a, b);
        let e = u32x4(1, 6, 3, 8);
        assert_eq!(r, e);
    }

    unsafe {
        let a = f32x4(1., 2., 3., 4.);
        let b = f32x4(5., 6., 7., 8.);

        let r: f32x4 = simd_select(m0, a, b);
        let e = a;
        assert_eq!(r, e);

        let r: f32x4 = simd_select(m1, a, b);
        let e = b;
        assert_eq!(r, e);

        let r: f32x4 = simd_select(m2, a, b);
        let e = f32x4(1., 2., 7., 8.);
        assert_eq!(r, e);

        let r: f32x4 = simd_select(m3, a, b);
        let e = f32x4(5., 6., 3., 4.);
        assert_eq!(r, e);

        let r: f32x4 = simd_select(m4, a, b);
        let e = f32x4(1., 6., 3., 8.);
        assert_eq!(r, e);
    }

    unsafe {
        let t = !0 as i8;
        let f = 0 as i8;
        let a = b8x4(t, f, t, f);
        let b = b8x4(f, f, f, t);

        let r: b8x4 = simd_select(m0, a, b);
        let e = a;
        assert_eq!(r, e);

        let r: b8x4 = simd_select(m1, a, b);
        let e = b;
        assert_eq!(r, e);

        let r: b8x4 = simd_select(m2, a, b);
        let e = b8x4(t, f, f, t);
        assert_eq!(r, e);

        let r: b8x4 = simd_select(m3, a, b);
        let e = b8x4(f, f, t, f);
        assert_eq!(r, e);

        let r: b8x4 = simd_select(m4, a, b);
        let e = b8x4(t, f, t, t);
        assert_eq!(r, e);
    }

    unsafe {
        let a = u32x8(0, 1, 2, 3, 4, 5, 6, 7);
        let b = u32x8(8, 9, 10, 11, 12, 13, 14, 15);

        let r: u32x8 = simd_select_bitmask(0u8, a, b);
        let e = b;
        assert_eq!(r, e);

        let r: u32x8 = simd_select_bitmask(0xffu8, a, b);
        let e = a;
        assert_eq!(r, e);

        let r: u32x8 = simd_select_bitmask(0b01010101u8, a, b);
        let e = u32x8(0, 9, 2, 11, 4, 13, 6, 15);
        assert_eq!(r, e);

        let r: u32x8 = simd_select_bitmask(0b10101010u8, a, b);
        let e = u32x8(8, 1, 10, 3, 12, 5, 14, 7);
        assert_eq!(r, e);

        let r: u32x8 = simd_select_bitmask(0b11110000u8, a, b);
        let e = u32x8(8, 9, 10, 11, 4, 5, 6, 7);
        assert_eq!(r, e);
    }
}
<|endoftext|>


<commit_before>use crate::{Geometry, Wkt, WktFloat};
use serde::de::{Deserializer, Error, Visitor};
use std::{
    default::Default,
    fmt::{self, Debug},
    marker::PhantomData,
    str::FromStr,
};

struct WktVisitor<T> {
    _marker: PhantomData<T>,
}

impl<T> Default for WktVisitor<T> {
    fn default() -> Self {
        WktVisitor {
            _marker: PhantomData::default(),
        }
    }
}

impl<'de, T> Visitor<'de> for WktVisitor<T>
where
    T: FromStr + Default + Debug + WktFloat,
{
    type Value = Wkt<T>;
    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(formatter, "a valid WKT format")
    }
    fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
    where
        E: Error,
    {
        Wkt::from_str(s).map_err(|e| serde::de::Error::custom(e))
    }
}

impl<'de, T> serde::Deserialize<'de> for Wkt<T>
where
    T: FromStr + Default + Debug + WktFloat,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_str(WktVisitor::default())
    }
}

struct GeometryVisitor<T> {
    _marker: PhantomData<T>,
}

impl<T> Default for GeometryVisitor<T> {
    fn default() -> Self {
        GeometryVisitor {
            _marker: PhantomData::default(),
        }
    }
}

impl<'de, T> Visitor<'de> for GeometryVisitor<T>
where
    T: FromStr + Default + WktFloat,
{
    type Value = Geometry<T>;
    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(formatter, "a valid WKT format")
    }
    fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
    where
        E: Error,
    {
        let mut wkt = Wkt::from_str(s).map_err(|e| serde::de::Error::custom(e))?;
        if wkt.items.len() == 1 {
            Ok(wkt.items.remove(0))
        } else {
            Err(serde::de::Error::custom(
                "WKT should have only 1 Geometry item",
            ))
        }
    }
}

impl<'de, T> serde::Deserialize<'de> for Geometry<T>
where
    T: FromStr + Default + WktFloat,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_str(GeometryVisitor::default())
    }
}

/// Deserializes directly from WKT format into a geo_types::Geometry.
/// ```
/// # extern crate wkt;
/// # extern crate geo_types;
/// # extern crate serde_json;
/// use geo_types::Geometry;
///
/// #[derive(serde::Deserialize)]
/// struct MyType {
///     #[serde(deserialize_with = "wkt::deserialize_geometry")]
///     pub geometry: Geometry<f64>,
/// }
///
/// let json = r#"{ "geometry": "POINT (3.14 42)" }"#;
/// let my_type: MyType = serde_json::from_str(json).unwrap();
/// assert!(matches!(my_type.geometry, Geometry::Point(_)));
/// ```
#[cfg(feature = "geo-types")]
pub fn deserialize_geometry<'de, D, T>(deserializer: D) -> Result<geo_types::Geometry<T>, D::Error>
where
    D: Deserializer<'de>,
    T: FromStr + Default + WktFloat,
{
    use serde::Deserialize;
    Geometry::deserialize(deserializer).and_then(|g: Geometry<T>| {
        use std::convert::TryInto;
        g.try_into().map_err(|e| D::Error::custom(e))
    })
}

/// Deserializes directly from WKT format into a `Option<geo_types::Point>`.
///
/// ```
/// # extern crate wkt;
/// # extern crate geo_types;
/// # extern crate serde_json;
/// use geo_types::Geometry;
///
/// #[derive(serde::Deserialize)]
/// struct MyType {
///     #[serde(deserialize_with = "wkt::deserialize_point")]
///     pub geometry: Option<Point<f64>>,
/// }
///
/// let json = r#"{ "geometry": "POINT (3.14 42)" }"#;
/// let my_type: MyType = serde_json::from_str(json).unwrap();
/// assert!(matches!(my_type.geometry, Some(Point(_))));
///
/// let json = r#"{ "geometry": "POINT EMPTY" }"#;
/// let my_type: MyType = serde_json::from_str(json).unwrap();
/// assert!(matches!(my_type.geometry, None));
/// ```
#[cfg(feature = "geo-types")]
pub fn deserialize_point<'de, D, T>(deserializer: D) -> Result<Option<geo_types::Point<T>>, D::Error>
    where
        D: Deserializer<'de>,
        T: FromStr + Default + WktFloat,
{
    use serde::Deserialize;
    Wkt::deserialize(deserializer).and_then(|wkt: Wkt<T>| {
        use std::convert::TryFrom;
        geo_types::Point::try_from(wkt).map(|p| Some(p))
            .or_else(|e| {
            if let crate::conversion::Error::PointConversionError = e {
                // map a WKT: 'POINT EMPTY' to an `Option<geo_types::Point>::None`
                return Ok(None);
            }

            Err(D::Error::custom(e))
        })
    })
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::{
        types::{Coord, Point},
        Geometry,
    };
    use serde::de::{
        value::{Error, StrDeserializer},
        Deserializer, Error as _, IntoDeserializer,
    };

    mod wkt {
        use super::*;

        #[test]
        fn deserialize() {
            let deserializer: StrDeserializer<'_, Error> = "POINT (10 20.1)".into_deserializer();
            let wkt = deserializer
                .deserialize_any(WktVisitor::<f64>::default())
                .unwrap();
            assert!(matches!(
                wkt.items[0],
                Geometry::Point(Point(Some(Coord {
                    x: _, // floating-point types cannot be used in patterns
                    y: _, // floating-point types cannot be used in patterns
                    z: None,
                    m: None,
                })))
            ));
        }

        #[test]
        fn deserialize_error() {
            let deserializer: StrDeserializer<'_, Error> = "POINT (10 20.1A)".into_deserializer();
            let wkt = deserializer.deserialize_any(WktVisitor::<f64>::default());
            assert_eq!(
                wkt.unwrap_err(),
                Error::custom("Expected a number for the Y coordinate")
            );
        }
    }

    mod geometry {
        use super::*;

        #[test]
        fn deserialize() {
            let deserializer: StrDeserializer<'_, Error> = "POINT (42 3.14)".into_deserializer();
            let geometry = deserializer
                .deserialize_any(GeometryVisitor::<f64>::default())
                .unwrap();
            assert!(matches!(
                geometry,
                Geometry::Point(Point(Some(Coord {
                    x: _, // floating-point types cannot be used in patterns
                    y: _, // floating-point types cannot be used in patterns
                    z: None,
                    m: None,
                })))
            ));
        }

        #[test]
        fn deserialize_error() {
            let deserializer: StrDeserializer<'_, Error> = "POINT (42 PI3.14)".into_deserializer();
            let geometry = deserializer.deserialize_any(GeometryVisitor::<f64>::default());
            assert_eq!(
                geometry.unwrap_err(),
                Error::custom("Expected a number for the Y coordinate")
            );
        }
    }
}
<commit_msg>fix failing doctest<commit_after>use crate::{Geometry, Wkt, WktFloat};
use serde::de::{Deserializer, Error, Visitor};
use std::{
    default::Default,
    fmt::{self, Debug},
    marker::PhantomData,
    str::FromStr,
};

struct WktVisitor<T> {
    _marker: PhantomData<T>,
}

impl<T> Default for WktVisitor<T> {
    fn default() -> Self {
        WktVisitor {
            _marker: PhantomData::default(),
        }
    }
}

impl<'de, T> Visitor<'de> for WktVisitor<T>
where
    T: FromStr + Default + Debug + WktFloat,
{
    type Value = Wkt<T>;
    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(formatter, "a valid WKT format")
    }
    fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
    where
        E: Error,
    {
        Wkt::from_str(s).map_err(|e| serde::de::Error::custom(e))
    }
}

impl<'de, T> serde::Deserialize<'de> for Wkt<T>
where
    T: FromStr + Default + Debug + WktFloat,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_str(WktVisitor::default())
    }
}

struct GeometryVisitor<T> {
    _marker: PhantomData<T>,
}

impl<T> Default for GeometryVisitor<T> {
    fn default() -> Self {
        GeometryVisitor {
            _marker: PhantomData::default(),
        }
    }
}

impl<'de, T> Visitor<'de> for GeometryVisitor<T>
where
    T: FromStr + Default + WktFloat,
{
    type Value = Geometry<T>;
    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(formatter, "a valid WKT format")
    }
    fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
    where
        E: Error,
    {
        let mut wkt = Wkt::from_str(s).map_err(|e| serde::de::Error::custom(e))?;
        if wkt.items.len() == 1 {
            Ok(wkt.items.remove(0))
        } else {
            Err(serde::de::Error::custom(
                "WKT should have only 1 Geometry item",
            ))
        }
    }
}

impl<'de, T> serde::Deserialize<'de> for Geometry<T>
where
    T: FromStr + Default + WktFloat,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_str(GeometryVisitor::default())
    }
}

/// Deserializes directly from WKT format into a geo_types::Geometry.
/// ```
/// # extern crate wkt;
/// # extern crate geo_types;
/// # extern crate serde_json;
/// use geo_types::Geometry;
///
/// #[derive(serde::Deserialize)]
/// struct MyType {
///     #[serde(deserialize_with = "wkt::deserialize_geometry")]
///     pub geometry: Geometry<f64>,
/// }
///
/// let json = r#"{ "geometry": "POINT (3.14 42)" }"#;
/// let my_type: MyType = serde_json::from_str(json).unwrap();
/// assert!(matches!(my_type.geometry, Geometry::Point(_)));
/// ```
#[cfg(feature = "geo-types")]
pub fn deserialize_geometry<'de, D, T>(deserializer: D) -> Result<geo_types::Geometry<T>, D::Error>
where
    D: Deserializer<'de>,
    T: FromStr + Default + WktFloat,
{
    use serde::Deserialize;
    Geometry::deserialize(deserializer).and_then(|g: Geometry<T>| {
        use std::convert::TryInto;
        g.try_into().map_err(|e| D::Error::custom(e))
    })
}

/// Deserializes directly from WKT format into a `Option<geo_types::Point>`.
///
/// ```
/// # extern crate wkt;
/// # extern crate geo_types;
/// # extern crate serde_json;
/// use geo_types::Point;
///
/// #[derive(serde::Deserialize)]
/// struct MyType {
///     #[serde(deserialize_with = "wkt::deserialize_point")]
///     pub geometry: Option<Point<f64>>,
/// }
///
/// let json = r#"{ "geometry": "POINT (3.14 42)" }"#;
/// let my_type: MyType = serde_json::from_str(json).unwrap();
/// assert!(matches!(my_type.geometry, Some(Point(_))));
///
/// let json = r#"{ "geometry": "POINT EMPTY" }"#;
/// let my_type: MyType = serde_json::from_str(json).unwrap();
/// assert!(matches!(my_type.geometry, None));
/// ```
#[cfg(feature = "geo-types")]
pub fn deserialize_point<'de, D, T>(deserializer: D) -> Result<Option<geo_types::Point<T>>, D::Error>
    where
        D: Deserializer<'de>,
        T: FromStr + Default + WktFloat,
{
    use serde::Deserialize;
    Wkt::deserialize(deserializer).and_then(|wkt: Wkt<T>| {
        use std::convert::TryFrom;
        geo_types::Point::try_from(wkt).map(|p| Some(p))
            .or_else(|e| {
            if let crate::conversion::Error::PointConversionError = e {
                // map a WKT: 'POINT EMPTY' to an `Option<geo_types::Point>::None`
                return Ok(None);
            }

            Err(D::Error::custom(e))
        })
    })
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::{
        types::{Coord, Point},
        Geometry,
    };
    use serde::de::{
        value::{Error, StrDeserializer},
        Deserializer, Error as _, IntoDeserializer,
    };

    mod wkt {
        use super::*;

        #[test]
        fn deserialize() {
            let deserializer: StrDeserializer<'_, Error> = "POINT (10 20.1)".into_deserializer();
            let wkt = deserializer
                .deserialize_any(WktVisitor::<f64>::default())
                .unwrap();
            assert!(matches!(
                wkt.items[0],
                Geometry::Point(Point(Some(Coord {
                    x: _, // floating-point types cannot be used in patterns
                    y: _, // floating-point types cannot be used in patterns
                    z: None,
                    m: None,
                })))
            ));
        }

        #[test]
        fn deserialize_error() {
            let deserializer: StrDeserializer<'_, Error> = "POINT (10 20.1A)".into_deserializer();
            let wkt = deserializer.deserialize_any(WktVisitor::<f64>::default());
            assert_eq!(
                wkt.unwrap_err(),
                Error::custom("Expected a number for the Y coordinate")
            );
        }
    }

    mod geometry {
        use super::*;

        #[test]
        fn deserialize() {
            let deserializer: StrDeserializer<'_, Error> = "POINT (42 3.14)".into_deserializer();
            let geometry = deserializer
                .deserialize_any(GeometryVisitor::<f64>::default())
                .unwrap();
            assert!(matches!(
                geometry,
                Geometry::Point(Point(Some(Coord {
                    x: _, // floating-point types cannot be used in patterns
                    y: _, // floating-point types cannot be used in patterns
                    z: None,
                    m: None,
                })))
            ));
        }

        #[test]
        fn deserialize_error() {
            let deserializer: StrDeserializer<'_, Error> = "POINT (42 PI3.14)".into_deserializer();
            let geometry = deserializer.deserialize_any(GeometryVisitor::<f64>::default());
            assert_eq!(
                geometry.unwrap_err(),
                Error::custom("Expected a number for the Y coordinate")
            );
        }
    }
}
<|endoftext|>


<commit_before>use serde::Deserialize;

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Mass {
    pub value: f64,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Inertia {
    pub ixx: f64,
    pub ixy: f64,
    pub ixz: f64,
    pub iyy: f64,
    pub iyz: f64,
    pub izz: f64,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Inertial {
    #[serde(default)]
    pub origin: Pose,
    pub mass: Mass,
    pub inertia: Inertia,
}

#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "snake_case")]
pub enum Geometry {
    Box {
        #[serde(with = "urdf_vec3")]
        size: [f64; 3],
    },
    Cylinder {
        radius: f64,
        length: f64,
    },
    Capsule {
        radius: f64,
        length: f64,
    },
    Sphere {
        radius: f64,
    },
    Mesh {
        filename: String,
        #[serde(with = "urdf_option_vec3")]
        scale: Option<[f64; 3]>,
    },
}

impl Default for Geometry {
    fn default() -> Geometry {
        Geometry::Box {
            size: [0.0f64, 0.0, 0.0],
        }
    }
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Color {
    #[serde(with = "urdf_vec4")]
    pub rgba: [f64; 4],
}

#[derive(Debug, Deserialize, Clone)]
pub struct Texture {
    pub filename: String,
}

impl Default for Texture {
    fn default() -> Texture {
        Texture {
            filename: "".to_string(),
        }
    }
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Material {
    pub name: String,
    pub color: Option<Color>,
    pub texture: Option<Texture>,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Visual {
    pub name: Option<String>,
    #[serde(default)]
    pub origin: Pose,
    pub geometry: Geometry,
    pub material: Option<Material>,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Collision {
    pub name: Option<String>,
    #[serde(default)]
    pub origin: Pose,
    pub geometry: Geometry,
}

/// Urdf Link element
/// See <http://wiki.ros.org/urdf/XML/link> for more detail.
#[derive(Debug, Deserialize, Clone)]
pub struct Link {
    pub name: String,
    #[serde(default)]
    pub inertial: Inertial,
    #[serde(default)]
    pub visual: Vec<Visual>,
    #[serde(default)]
    pub collision: Vec<Collision>,
}

#[derive(Deserialize, Debug, Clone)]
pub struct Vec3 {
    #[serde(with = "urdf_vec3")]
    pub data: [f64; 3],
}

mod urdf_vec3 {
    use serde::{self, Deserialize, Deserializer};
    pub fn deserialize<'a, D>(deserializer: D) -> Result<[f64; 3], D::Error>
    where
        D: Deserializer<'a>,
    {
        let s = String::deserialize(deserializer)?;
        let vec = s
            .split(' ')
            .filter_map(|x| x.parse::<f64>().ok())
            .collect::<Vec<_>>();
        if vec.len() != 3 {
            return Err(serde::de::Error::custom(format!(
                "failed to parse float array in {}",
                s
            )));
        }
        let mut arr = [0.0f64; 3];
        for i in 0..3 {
            arr[i] = vec[i];
        }
        Ok(arr)
    }
}

mod urdf_option_vec3 {
    use serde::{self, Deserialize, Deserializer};
    pub fn deserialize<'a, D>(deserializer: D) -> Result<Option<[f64; 3]>, D::Error>
    where
        D: Deserializer<'a>,
    {
        let s = String::deserialize(deserializer)?;
        let vec = s
            .split(' ')
            .filter_map(|x| x.parse::<f64>().ok())
            .collect::<Vec<_>>();
        if vec.is_empty() {
            Ok(None)
        } else if vec.len() == 3 {
            let mut arr = [0.0; 3];
            arr.copy_from_slice(&vec);
            Ok(Some(arr))
        } else {
            Err(serde::de::Error::custom(format!(
                "failed to parse float array in {}",
                s
            )))
        }
    }
}

mod urdf_vec4 {
    use serde::{self, Deserialize, Deserializer};
    pub fn deserialize<'a, D>(deserializer: D) -> Result<[f64; 4], D::Error>
    where
        D: Deserializer<'a>,
    {
        let s = String::deserialize(deserializer)?;
        let vec = s
            .split(' ')
            .filter_map(|x| x.parse::<f64>().ok())
            .collect::<Vec<_>>();
        if vec.len() != 4 {
            return Err(serde::de::Error::custom(format!(
                "failed to parse float array in {}",
                s
            )));
        }
        let mut arr = [0.0f64; 4];
        for i in 0..4 {
            arr[i] = vec[i];
        }
        Ok(arr)
    }
}

#[derive(Debug, Deserialize, Clone)]
pub struct Axis {
    #[serde(with = "urdf_vec3")]
    pub xyz: [f64; 3],
}

impl Default for Axis {
    fn default() -> Axis {
        Axis {
            xyz: [1.0f64, 0.0, 0.0],
        }
    }
}

#[derive(Debug, Deserialize, Clone)]
pub struct Pose {
    #[serde(with = "urdf_vec3")]
    #[serde(default = "default_zero3")]
    pub xyz: [f64; 3],
    #[serde(with = "urdf_vec3")]
    #[serde(default = "default_zero3")]
    pub rpy: [f64; 3],
}

fn default_zero3() -> [f64; 3] {
    [0.0f64, 0.0, 0.0]
}

impl Default for Pose {
    fn default() -> Pose {
        Pose {
            xyz: default_zero3(),
            rpy: default_zero3(),
        }
    }
}

#[derive(Debug, Deserialize, Clone)]
pub struct LinkName {
    pub link: String,
}

#[derive(Debug, Deserialize, Clone, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum JointType {
    Revolute,
    Continuous,
    Prismatic,
    Fixed,
    Floating,
    Planar,
    Spherical,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct JointLimit {
    #[serde(default)]
    pub lower: f64,
    #[serde(default)]
    pub upper: f64,
    pub effort: f64,
    pub velocity: f64,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Mimic {
    pub joint: String,
    pub multiplier: Option<f64>,
    pub offset: Option<f64>,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct SafetyController {
    #[serde(default)]
    pub soft_lower_limit: f64,
    #[serde(default)]
    pub soft_upper_limit: f64,
    #[serde(default)]
    pub k_position: f64,
    pub k_velocity: f64,
}

/// Urdf Joint element
/// See <http://wiki.ros.org/urdf/XML/joint> for more detail.
#[derive(Debug, Deserialize, Clone)]
pub struct Joint {
    pub name: String,
    #[serde(rename = "type")]
    pub joint_type: JointType,
    #[serde(default)]
    pub origin: Pose,
    pub parent: LinkName,
    pub child: LinkName,
    #[serde(default)]
    pub axis: Axis,
    #[serde(default)]
    pub limit: JointLimit,
    pub dynamics: Option<Dynamics>,
    pub mimic: Option<Mimic>,
    pub safety_controller: Option<SafetyController>,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Dynamics {
    #[serde(default)]
    pub damping: f64,
    #[serde(default)]
    pub friction: f64,
}

/// Top level struct to access urdf.
#[derive(Debug, Deserialize, Clone)]
pub struct Robot {
    #[serde(default)]
    pub name: String,

    #[serde(rename = "link", default)]
    pub links: Vec<Link>,

    #[serde(rename = "joint", default)]
    pub joints: Vec<Joint>,

    #[serde(rename = "material", default)]
    pub materials: Vec<Material>,
}
<commit_msg>Use copy_from_slice instead of for-loops<commit_after>use serde::Deserialize;

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Mass {
    pub value: f64,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Inertia {
    pub ixx: f64,
    pub ixy: f64,
    pub ixz: f64,
    pub iyy: f64,
    pub iyz: f64,
    pub izz: f64,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Inertial {
    #[serde(default)]
    pub origin: Pose,
    pub mass: Mass,
    pub inertia: Inertia,
}

#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "snake_case")]
pub enum Geometry {
    Box {
        #[serde(with = "urdf_vec3")]
        size: [f64; 3],
    },
    Cylinder {
        radius: f64,
        length: f64,
    },
    Capsule {
        radius: f64,
        length: f64,
    },
    Sphere {
        radius: f64,
    },
    Mesh {
        filename: String,
        #[serde(with = "urdf_option_vec3")]
        scale: Option<[f64; 3]>,
    },
}

impl Default for Geometry {
    fn default() -> Geometry {
        Geometry::Box {
            size: [0.0f64, 0.0, 0.0],
        }
    }
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Color {
    #[serde(with = "urdf_vec4")]
    pub rgba: [f64; 4],
}

#[derive(Debug, Deserialize, Clone)]
pub struct Texture {
    pub filename: String,
}

impl Default for Texture {
    fn default() -> Texture {
        Texture {
            filename: "".to_string(),
        }
    }
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Material {
    pub name: String,
    pub color: Option<Color>,
    pub texture: Option<Texture>,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Visual {
    pub name: Option<String>,
    #[serde(default)]
    pub origin: Pose,
    pub geometry: Geometry,
    pub material: Option<Material>,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Collision {
    pub name: Option<String>,
    #[serde(default)]
    pub origin: Pose,
    pub geometry: Geometry,
}

/// Urdf Link element
/// See <http://wiki.ros.org/urdf/XML/link> for more detail.
#[derive(Debug, Deserialize, Clone)]
pub struct Link {
    pub name: String,
    #[serde(default)]
    pub inertial: Inertial,
    #[serde(default)]
    pub visual: Vec<Visual>,
    #[serde(default)]
    pub collision: Vec<Collision>,
}

#[derive(Deserialize, Debug, Clone)]
pub struct Vec3 {
    #[serde(with = "urdf_vec3")]
    pub data: [f64; 3],
}

mod urdf_vec3 {
    use serde::{self, Deserialize, Deserializer};
    pub fn deserialize<'a, D>(deserializer: D) -> Result<[f64; 3], D::Error>
    where
        D: Deserializer<'a>,
    {
        let s = String::deserialize(deserializer)?;
        let vec = s
            .split(' ')
            .filter_map(|x| x.parse::<f64>().ok())
            .collect::<Vec<_>>();
        if vec.len() != 3 {
            return Err(serde::de::Error::custom(format!(
                "failed to parse float array in {}",
                s
            )));
        }
        let mut arr = [0.0f64; 3];
        arr.copy_from_slice(&vec);
        Ok(arr)
    }
}

mod urdf_option_vec3 {
    use serde::{self, Deserialize, Deserializer};
    pub fn deserialize<'a, D>(deserializer: D) -> Result<Option<[f64; 3]>, D::Error>
    where
        D: Deserializer<'a>,
    {
        let s = String::deserialize(deserializer)?;
        let vec = s
            .split(' ')
            .filter_map(|x| x.parse::<f64>().ok())
            .collect::<Vec<_>>();
        if vec.is_empty() {
            Ok(None)
        } else if vec.len() == 3 {
            let mut arr = [0.0; 3];
            arr.copy_from_slice(&vec);
            Ok(Some(arr))
        } else {
            Err(serde::de::Error::custom(format!(
                "failed to parse float array in {}",
                s
            )))
        }
    }
}

mod urdf_vec4 {
    use serde::{self, Deserialize, Deserializer};
    pub fn deserialize<'a, D>(deserializer: D) -> Result<[f64; 4], D::Error>
    where
        D: Deserializer<'a>,
    {
        let s = String::deserialize(deserializer)?;
        let vec = s
            .split(' ')
            .filter_map(|x| x.parse::<f64>().ok())
            .collect::<Vec<_>>();
        if vec.len() != 4 {
            return Err(serde::de::Error::custom(format!(
                "failed to parse float array in {}",
                s
            )));
        }
        let mut arr = [0.0f64; 4];
        arr.copy_from_slice(&vec);
        Ok(arr)
    }
}

#[derive(Debug, Deserialize, Clone)]
pub struct Axis {
    #[serde(with = "urdf_vec3")]
    pub xyz: [f64; 3],
}

impl Default for Axis {
    fn default() -> Axis {
        Axis {
            xyz: [1.0f64, 0.0, 0.0],
        }
    }
}

#[derive(Debug, Deserialize, Clone)]
pub struct Pose {
    #[serde(with = "urdf_vec3")]
    #[serde(default = "default_zero3")]
    pub xyz: [f64; 3],
    #[serde(with = "urdf_vec3")]
    #[serde(default = "default_zero3")]
    pub rpy: [f64; 3],
}

fn default_zero3() -> [f64; 3] {
    [0.0f64, 0.0, 0.0]
}

impl Default for Pose {
    fn default() -> Pose {
        Pose {
            xyz: default_zero3(),
            rpy: default_zero3(),
        }
    }
}

#[derive(Debug, Deserialize, Clone)]
pub struct LinkName {
    pub link: String,
}

#[derive(Debug, Deserialize, Clone, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum JointType {
    Revolute,
    Continuous,
    Prismatic,
    Fixed,
    Floating,
    Planar,
    Spherical,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct JointLimit {
    #[serde(default)]
    pub lower: f64,
    #[serde(default)]
    pub upper: f64,
    pub effort: f64,
    pub velocity: f64,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Mimic {
    pub joint: String,
    pub multiplier: Option<f64>,
    pub offset: Option<f64>,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct SafetyController {
    #[serde(default)]
    pub soft_lower_limit: f64,
    #[serde(default)]
    pub soft_upper_limit: f64,
    #[serde(default)]
    pub k_position: f64,
    pub k_velocity: f64,
}

/// Urdf Joint element
/// See <http://wiki.ros.org/urdf/XML/joint> for more detail.
#[derive(Debug, Deserialize, Clone)]
pub struct Joint {
    pub name: String,
    #[serde(rename = "type")]
    pub joint_type: JointType,
    #[serde(default)]
    pub origin: Pose,
    pub parent: LinkName,
    pub child: LinkName,
    #[serde(default)]
    pub axis: Axis,
    #[serde(default)]
    pub limit: JointLimit,
    pub dynamics: Option<Dynamics>,
    pub mimic: Option<Mimic>,
    pub safety_controller: Option<SafetyController>,
}

#[derive(Debug, Deserialize, Default, Clone)]
pub struct Dynamics {
    #[serde(default)]
    pub damping: f64,
    #[serde(default)]
    pub friction: f64,
}

/// Top level struct to access urdf.
#[derive(Debug, Deserialize, Clone)]
pub struct Robot {
    #[serde(default)]
    pub name: String,

    #[serde(rename = "link", default)]
    pub links: Vec<Link>,

    #[serde(rename = "joint", default)]
    pub joints: Vec<Joint>,

    #[serde(rename = "material", default)]
    pub materials: Vec<Material>,
}
<|endoftext|>


<commit_before>use alga::general::Real;
use crate::shape;
use crate::procedural::TriMesh;
use super::ToTriMesh;

impl<N: Real> ToTriMesh<N> for shape::HeightField<N> {
    type DiscretizationParameter = ();

    fn to_trimesh(&self, _: ()) -> TriMesh<N> {
        let mut vertices = Vec::new();

        for tri in self.triangles() {
            vertices.push(*tri.a());
            vertices.push(*tri.b());
            vertices.push(*tri.c());
        }

        /*
        for i in 0..self.nrows() {
            for j in 0..self.ncols() {
                let triangles = self.triangles_at(i, j);

                if let Some(tri) = triangles.0 {
                    vertices.push(*tri.a());
                    vertices.push(*tri.b());
                    vertices.push(*tri.c());
                }

                if let Some(tri) = triangles.1 {
                    vertices.push(*tri.a());
                    vertices.push(*tri.b());
                    vertices.push(*tri.c());
                }
            }
        }
        */

        TriMesh::new(vertices, None, None, None)
    }
}
<commit_msg>Remove useless commented code.<commit_after>use alga::general::Real;
use crate::shape;
use crate::procedural::TriMesh;
use super::ToTriMesh;

impl<N: Real> ToTriMesh<N> for shape::HeightField<N> {
    type DiscretizationParameter = ();

    fn to_trimesh(&self, _: ()) -> TriMesh<N> {
        let mut vertices = Vec::new();

        for tri in self.triangles() {
            vertices.push(*tri.a());
            vertices.push(*tri.b());
            vertices.push(*tri.c());
        }

        TriMesh::new(vertices, None, None, None)
    }
}
<|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

#![deny(
    non_camel_case_types,
    non_snake_case,
    path_statements,
    trivial_numeric_casts,
    unstable_features,
    unused_allocation,
    unused_import_braces,
    unused_imports,
    unused_must_use,
    unused_mut,
    unused_qualifications,
    while_true,
)]

extern crate clap;
#[macro_use] extern crate log;
#[macro_use] extern crate version;
extern crate toml;
extern crate toml_query;
extern crate kairos;

extern crate libimaghabit;
extern crate libimagstore;
extern crate libimagrt;
extern crate libimagerror;
extern crate libimagutil;

use std::process::exit;

use libimagrt::runtime::Runtime;
use libimagrt::setup::generate_runtime_setup;
use libimagerror::trace::{MapErrTrace, trace_error};
use libimaghabit::store::HabitStore;
use libimaghabit::habit::builder::HabitBuilder;
use libimaghabit::habit::HabitTemplate;

mod ui;

fn main() {
    let rt = generate_runtime_setup("imag-habit",
                                    &version!()[..],
                                    "Habit tracking tool",
                                    ui::build_ui);

    rt.cli()
        .subcommand_name()
        .map(|name| {
            debug!("Call {}", name);
            match name {
                "create" => create(&rt),
                "delete" => delete(&rt),
                "list"   => list(&rt),
                "show"   => show(&rt),
                _        => {
                    debug!("Unknown command"); // More error handling
                    exit(1)
                },
            }
        });
}

fn create(rt: &Runtime) {
    unimplemented!()
}

fn delete(rt: &Runtime) {
    unimplemented!()
}

fn list(rt: &Runtime) {
    unimplemented!()
}

fn show(rt: &Runtime) {
    unimplemented!()
}

<commit_msg>Implement create()<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

#![deny(
    non_camel_case_types,
    non_snake_case,
    path_statements,
    trivial_numeric_casts,
    unstable_features,
    unused_allocation,
    unused_import_braces,
    unused_imports,
    unused_must_use,
    unused_mut,
    unused_qualifications,
    while_true,
)]

extern crate clap;
#[macro_use] extern crate log;
#[macro_use] extern crate version;
extern crate toml;
extern crate toml_query;
extern crate kairos;

extern crate libimaghabit;
extern crate libimagstore;
extern crate libimagrt;
extern crate libimagerror;
extern crate libimagutil;

use std::process::exit;

use libimagrt::runtime::Runtime;
use libimagrt::setup::generate_runtime_setup;
use libimagerror::trace::{MapErrTrace, trace_error};
use libimaghabit::store::HabitStore;
use libimaghabit::habit::builder::HabitBuilder;
use libimaghabit::habit::HabitTemplate;

mod ui;

fn main() {
    let rt = generate_runtime_setup("imag-habit",
                                    &version!()[..],
                                    "Habit tracking tool",
                                    ui::build_ui);

    rt.cli()
        .subcommand_name()
        .map(|name| {
            debug!("Call {}", name);
            match name {
                "create" => create(&rt),
                "delete" => delete(&rt),
                "list"   => list(&rt),
                "show"   => show(&rt),
                _        => {
                    debug!("Unknown command"); // More error handling
                    exit(1)
                },
            }
        });
}

fn create(rt: &Runtime) {
    let scmd = rt.cli().subcommand_matches("create").unwrap();                      // safe by call from main()
    let name = scmd.value_of("create-name").map(String::from).unwrap();             // safe by clap
    let recu = scmd.value_of("create-date-recurr-spec").map(String::from).unwrap(); // safe by clap
    let comm = scmd.value_of("create-comment").map(String::from).unwrap();          // safe by clap
    let date = scmd.value_of("create-date").unwrap();                               // safe by clap

    let date = match ::kairos::parser::parse(date).map_err_trace_exit_unwrap(1) {
        ::kairos::parser::Parsed::TimeType(tt) => match tt.get_moment() {
            Some(mom) => mom.date(),
            None => {
                error!("Error: 'date' parameter does not yield a point in time");
                exit(1);
            },
        },
        _ => {
            error!("Error: 'date' parameter does not yield a point in time");
            exit(1);
        },
    };

    let _ = HabitBuilder::default()
        .with_name(name)
        .with_basedate(date)
        .with_recurspec(recu)
        .with_comment(comm)
        .build(rt.store())
        .map_err_trace_exit_unwrap(1);

    info!("Ok");
}

fn delete(rt: &Runtime) {
    unimplemented!()
}

fn list(rt: &Runtime) {
    unimplemented!()
}

fn show(rt: &Runtime) {
    unimplemented!()
}

<|endoftext|>


<commit_before>pub use std::{
    any::{Any, TypeId},
    cell::RefCell,
    collections::{HashMap, HashSet},
    fmt::Debug,
    rc::Rc,
};

pub use crate::*;
pub use api::*;
pub use ecs::*;
pub use orbtk_api::css_engine::{Selector, Theme};
pub use orbtk_render::prelude::Image;
pub use proc_macros::*;
pub use theme::{colors, default_theme, fonts, light_theme, vector_graphics::material_font_icons};
pub use utils::*;
<commit_msg>widgets/prelude: incorporate the new vector_graphics fonts<commit_after>pub use std::{
    any::{Any, TypeId},
    cell::RefCell,
    collections::{HashMap, HashSet},
    fmt::Debug,
    rc::Rc,
};

pub use crate::*;
pub use api::*;
pub use ecs::*;
pub use orbtk_api::css_engine::{Selector, Theme};
pub use orbtk_render::prelude::Image;
pub use proc_macros::*;
pub use theme::{
    colors,
    default_theme,
    fonts,
    light_theme,
    vector_graphics::{
	material_icons_font_ttf,
	material_icons_font,
	material_icons_round_font,
	material_icons_sharp_font,
	material_icons_twotone_font,
    }
};
pub use utils::*;
<|endoftext|>


<commit_before>extern crate num;

use num::{BigUint, One, FromPrimitive};

fn factorial(n: usize) -> BigUint {
    let mut f: BigUint = One::one();
    for i in 1..(n+1) {
        let bu: BigUint = FromPrimitive::from_usize(i).unwrap();
        f = f * bu;
    }
    f
}

fn main() {
    println!("{}", factorial(1000));
}
<commit_msg>Rust - changed value to biggest<commit_after>extern crate num;

use num::{BigUint, One, FromPrimitive};

fn factorial(n: usize) -> BigUint {
    let mut f: BigUint = One::one();
    for i in 1..(n+1) {
        let bu: BigUint = FromPrimitive::from_usize(i).unwrap();
        f = f * bu;
    }
    f
}

fn main() {
    println!("{}", factorial(1000000));
}
<|endoftext|>


<commit_before>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

use anyhow::{bail, Context, Result};

use std::cell::{Cell, RefCell};
use std::io::{Read, Write};
use std::os::unix::net::UnixStream;
use std::path::PathBuf;
use std::rc::Rc;
use std::time::Duration;

use crate::io::emu::EmuState;
use crate::io::uart::{Uart, UartError};
use crate::transport::ti50emulator::emu::EMULATOR_INVALID_ID;
use crate::transport::ti50emulator::Inner;
use crate::transport::ti50emulator::Ti50Emulator;

const TI50_UART_BAUDRATE: u32 = 115200;

pub struct Ti50Uart {
    inner: Rc<RefCell<Inner>>,
    // This socket is valid as long as SubProcess is running.
    socket: RefCell<Option<UnixStream>>,
    // full path to socket file
    path: PathBuf,
    // last SubProcess ID
    last_id: Cell<u64>,
}

impl Ti50Uart {
    pub fn open(ti50: &Ti50Emulator, path: &str) -> Result<Self> {
        let soc_path = ti50.inner.borrow().process.get_runtime_dir().join(path);
        Ok(Self {
            inner: Rc::clone(&ti50.inner),
            socket: RefCell::default(),
            path: soc_path,
            last_id: Cell::new(EMULATOR_INVALID_ID),
        })
    }

    pub fn reconnect(&self) -> Result<()> {
        let mut socket = self.socket.borrow_mut();
        let id = self.inner.borrow_mut().process.get_id();
        if self.last_id.get() != id {
            *socket = Some(UnixStream::connect(&self.path)?);
            self.last_id.set(id);
        }
        Ok(())
    }

    pub fn check_state(&self) -> Result<bool> {
        let process = &mut self.inner.borrow_mut().process;
        process.update_status()?;
        let valid = match process.get_state() {
            EmuState::On | EmuState::Error => true,
            _ => false,
        };
        return Ok(valid);
    }
}

/// A trait which represents a UART.
impl Uart for Ti50Uart {
    /// Returns the UART baudrate.  May return zero for virtual UARTs.
    fn get_baudrate(&self) -> Result<u32> {
        // As a virtual uart, the value is set only for compatibility with common hardware
        // Real speed of uart is much higher and it is mostly limited by IPC speed.
        Ok(TI50_UART_BAUDRATE)
    }

    /// Sets the UART baudrate.  May do nothing for virtual UARTs.
    fn set_baudrate(&self, _baudrate: u32) -> Result<()> {
        // As a virtual uart, setting the baudrate is a no-op.
        Ok(())
    }

    /// Reads UART receive data into `buf`, returning the number of bytes read.
    /// This function _may_ block.
    fn read(&self, buf: &mut [u8]) -> Result<usize> {
        if self.check_state()? {
            self.reconnect()?;
            if let Some(ref mut fd) = *self.socket.borrow_mut() {
                fd.set_read_timeout(None)?;
                return Ok(fd.read(buf)?);
            }
            bail!(UartError::GenericError("Invalid socket".to_string()));
        };
        Ok(0)
    }

    /// Reads UART receive data into `buf`, returning the number of bytes read.
    /// The `timeout` may be used to specify a duration to wait for data.
    /// If timeout expires without any data arriving `Ok(0)` will be returned, never `Err(_)`.
    fn read_timeout(&self, buf: &mut [u8], timeout: Duration) -> Result<usize> {
        if self.check_state()? {
            self.reconnect()?;
            if let Some(ref mut fd) = *self.socket.borrow_mut() {
                fd.set_read_timeout(Some(timeout))?;
                return Ok(fd.read(buf).context("UART read error")?);
            }
            bail!(UartError::GenericError("Invalid socket".to_string()));
        };
        Ok(0)
    }

    /// Writes data from `buf` to the UART.
    fn write(&self, buf: &[u8]) -> Result<()> {
        if self.check_state()? {
            self.reconnect()?;
            if let Some(ref mut fd) = *self.socket.borrow_mut() {
                fd.write(buf).context("UART read error")?;
                return Ok(());
            }
            bail!(UartError::GenericError("Invalid socket".to_string()));
        };
        Ok(())
    }
}
<commit_msg>[opentitantool] Add get_socket() to refactor some duplicate code in ti50emulator<commit_after>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

use anyhow::{bail, Context, Result};

use std::cell::{Cell, RefCell, RefMut};
use std::io::{Read, Write};
use std::os::unix::net::UnixStream;
use std::path::PathBuf;
use std::rc::Rc;
use std::time::Duration;

use crate::io::emu::EmuState;
use crate::io::uart::{Uart, UartError};
use crate::transport::ti50emulator::emu::EMULATOR_INVALID_ID;
use crate::transport::ti50emulator::Inner;
use crate::transport::ti50emulator::Ti50Emulator;

const TI50_UART_BAUDRATE: u32 = 115200;

pub struct Ti50Uart {
    inner: Rc<RefCell<Inner>>,
    // This socket is valid as long as SubProcess is running.
    socket: RefCell<Option<UnixStream>>,
    // full path to socket file
    path: PathBuf,
    // last SubProcess ID
    last_id: Cell<u64>,
}

impl Ti50Uart {
    pub fn open(ti50: &Ti50Emulator, path: &str) -> Result<Self> {
        let soc_path = ti50.inner.borrow().process.get_runtime_dir().join(path);
        Ok(Self {
            inner: Rc::clone(&ti50.inner),
            socket: RefCell::default(),
            path: soc_path,
            last_id: Cell::new(EMULATOR_INVALID_ID),
        })
    }

    pub fn reconnect(&self) -> Result<()> {
        let mut socket = self.socket.borrow_mut();
        let id = self.inner.borrow_mut().process.get_id();
        if self.last_id.get() != id {
            *socket = Some(UnixStream::connect(&self.path)?);
            self.last_id.set(id);
        }
        Ok(())
    }

    pub fn check_state(&self) -> Result<bool> {
        let process = &mut self.inner.borrow_mut().process;
        process.update_status()?;
        let valid = match process.get_state() {
            EmuState::On | EmuState::Error => true,
            _ => false,
        };
        return Ok(valid);
    }

    pub fn get_socket(&self) -> Result<RefMut<UnixStream>> {
        if self.check_state()? {
            self.reconnect()?;
            // Socket should be valid as long as the subprocess is running.
            return Ok(RefMut::map(self.socket.borrow_mut(), |socket| {
                socket.as_mut().unwrap()
            }));
        }
        bail!(UartError::GenericError("Invalid socket".to_string()));
    }
}

/// A trait which represents a UART.
impl Uart for Ti50Uart {
    /// Returns the UART baudrate.  May return zero for virtual UARTs.
    fn get_baudrate(&self) -> Result<u32> {
        // As a virtual uart, the value is set only for compatibility with common hardware
        // Real speed of uart is much higher and it is mostly limited by IPC speed.
        Ok(TI50_UART_BAUDRATE)
    }

    /// Sets the UART baudrate.  May do nothing for virtual UARTs.
    fn set_baudrate(&self, _baudrate: u32) -> Result<()> {
        // As a virtual uart, setting the baudrate is a no-op.
        Ok(())
    }

    /// Reads UART receive data into `buf`, returning the number of bytes read.
    /// This function _may_ block.
    fn read(&self, buf: &mut [u8]) -> Result<usize> {
        let mut socket = self.get_socket()?;
        socket.set_read_timeout(None)?;
        return Ok(socket.read(buf)?);
    }

    /// Reads UART receive data into `buf`, returning the number of bytes read.
    /// The `timeout` may be used to specify a duration to wait for data.
    /// If timeout expires without any data arriving `Ok(0)` will be returned, never `Err(_)`.
    fn read_timeout(&self, buf: &mut [u8], timeout: Duration) -> Result<usize> {
        let mut socket = self.get_socket()?;
        socket.set_read_timeout(Some(timeout))?;
        return Ok(socket.read(buf).context("UART read error")?);
    }

    /// Writes data from `buf` to the UART.
    fn write(&self, buf: &[u8]) -> Result<()> {
        self.get_socket()?.write(buf).context("UART read error")?;
        return Ok(());
    }
}
<|endoftext|>