<commit_before>use std::mem;

use AsMutLua;
use AsLua;

use Push;
use PushGuard;
use LuaRead;

macro_rules! tuple_impl {
    ($ty:ident) => (

    );

    ($first:ident, $($other:ident),+) => (
        #[allow(non_snake_case)]
        impl<LU, $first: for<'a> Push<&'a mut LU>, $($other: for<'a> Push<&'a mut LU>),+> Push<LU> for ($first, $($other),+)
                                                                          where LU: AsMutLua
        {
            fn push_to_lua(self, mut lua: LU) -> PushGuard<LU> {
                match self {
                    ($first, $($other),+) => {
                        let mut total = 0;

                        {
                            let guard = $first.push_to_lua(&mut lua);
                            total += guard.size;
                            unsafe { mem::forget(guard) };
                        }

                        $(
                            {
                                let guard = $other.push_to_lua(&mut lua);
                                total += guard.size;
                                unsafe { mem::forget(guard) };
                            }
                        )+
                        PushGuard { lua: lua, size: total }
                    }
                }
            }
        }

        /*// TODO: what if T or U are also tuples? indices won't match
        #[allow(unused_assignments)]
        impl<LU: AsLua, $($ty: CopyRead<LU>),+> CopyRead<LU> for ($($ty),+) {
            fn read_from_lua(lua: &mut LU, index: i32) -> Option<($($ty),+)> {

                let mut i = index;
                $(
                    let $nb: Option<$ty> = CopyRead::read_from_lua(lua, i);
                    i += 1;
                )+

                if $($nb.is_none())||+ {
                    return None;
                }

                Some(($($nb.unwrap()),+))

            }
        }*/

        tuple_impl!($($other),+);
    );
}

tuple_impl!(A, B, C, D, E, F, G, H, I, J, K, L, M);
<commit_msg>Restore reading tuples<commit_after>use std::mem;

use AsMutLua;
use AsLua;

use Push;
use PushGuard;
use LuaRead;

macro_rules! tuple_impl {
    ($ty:ident) => (

    );

    ($first:ident, $($other:ident),+) => (
        #[allow(non_snake_case)]
        impl<LU, $first: for<'a> Push<&'a mut LU>, $($other: for<'a> Push<&'a mut LU>),+> Push<LU> for ($first, $($other),+)
                                                                          where LU: AsMutLua
        {
            fn push_to_lua(self, mut lua: LU) -> PushGuard<LU> {
                match self {
                    ($first, $($other),+) => {
                        let mut total = 0;

                        {
                            let guard = $first.push_to_lua(&mut lua);
                            total += guard.size;
                            unsafe { mem::forget(guard) };
                        }

                        $(
                            {
                                let guard = $other.push_to_lua(&mut lua);
                                total += guard.size;
                                unsafe { mem::forget(guard) };
                            }
                        )+
                        PushGuard { lua: lua, size: total }
                    }
                }
            }
        }

        // TODO: what if T or U are also tuples? indices won't match
        #[allow(unused_assignments)]
        #[allow(non_snake_case)]
        impl<LU, $first: for<'a> LuaRead<&'a mut LU>, $($other: for<'a> LuaRead<&'a mut LU>),+> LuaRead<LU> for ($first, $($other),+) where LU: AsLua {
            fn lua_read_at_position(mut lua: LU, index: i32) -> Option<($first, $($other),+)> {
                let mut i = index;

                let $first: Option<$first> = LuaRead::lua_read_at_position(&mut lua, i);
                i += 1;

                $(
                    let $other: Option<$other> = LuaRead::lua_read_at_position(&mut lua, i);
                    i += 1;
                )+

                if $first.is_none() {
                    return None;
                }

                if $($other.is_none())||+ {
                    return None;
                }

                Some(($first.unwrap(), $($other.unwrap()),+))

            }
        }

        tuple_impl!($($other),+);
    );
}

tuple_impl!(A, B, C, D, E, F, G, H, I, J, K, L, M);
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// error-pattern:assertion failed: `(left == right) && (right == left)` (left: `14`, right: `15`)

#[deriving(Eq)]
struct Point { x : int }

fn main() {
    assert_eq!(14,15);
}
<commit_msg>Remove the unused Point struct in the assert-eq-macro-fail.rs test.<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// error-pattern:assertion failed: `(left == right) && (right == left)` (left: `14`, right: `15`)

fn main() {
    assert_eq!(14,15);
}
<|endoftext|>


<commit_before>use std;
use sdl2;
use cgmath::*;
use sdl2::surface;
use utils::get_full_path;
use dll_import::IMG_Load;

pub struct Surface {
    pub size_x: usize,
    pub size_y: usize,
    pub data: Vec<Vector3<f32>>,
}

pub struct Texture {
    pub levels: Vec<Surface>,
}

impl Surface {
    fn new(size_x: usize, size_y: usize) -> Surface {
        Surface {
            size_x: size_x,
            size_y: size_y,
            data: Vec::<Vector3<f32>>::with_capacity(size_x * size_y),
        }
    }
}

impl Texture {
    pub fn new(filename: &str) -> Result<Texture, String> {
        let fullpath = try!(get_full_path(filename));
        let surface_load: surface::Surface;
        unsafe {
            let raw = IMG_Load(std::ffi::CString::new(fullpath).unwrap().as_ptr());
            if (raw as *mut ()).is_null() {
                return Err(format!("can't load texture {}, error = {}", filename, sdl2::get_error()));
            } else {
                surface_load = surface::Surface::from_ll(raw);
            }
        }
        let standart: surface::Surface =
            match surface::Surface::new(1, 1, sdl2::pixels::PixelFormatEnum::ARGB8888) {
                Ok(v) => v,
                Err(e) => return Err(format!("can't create standart surface for texture {}, error = {}",
                                             filename, e))
            };
        let mut surface: surface::Surface =
            match surface_load.as_ref().convert(&standart.as_ref().pixel_format()) {
                Ok(v) => v,
                Err(e) => return Err(format!("can't convert surface for texture {}, error = {}",
                                             filename, e))
            };

        let size_x = surface.as_ref().width() as usize;
        let size_y = surface.as_ref().height() as usize;
        let mut lvl0 = Surface::new(size_x, size_y);

        let data_u8: &[u8] = match surface.as_mut().without_lock() {
            Some(v) => v,
            None => return Err(format!("can't lock surface for texture {}", filename))
        };

        for x in 0..size_x {
            for y in 0..size_y {
                lvl0.data.push(Vector3::new(
                    data_u8[(y * size_x + size_x - x - 1) * 4 + 0] as f32,
                    data_u8[(y * size_x + size_x - x - 1) * 4 + 1] as f32,
                    data_u8[(y * size_x + size_x - x - 1) * 4 + 2] as f32));
            }
        }

        Ok(
            Texture {
                levels: vec![lvl0]
            })
    }
}
<commit_msg>mipmaps<commit_after>use std;
use sdl2;
use cgmath::*;
use sdl2::surface;
use utils::get_full_path;
use dll_import::IMG_Load;

pub struct Surface {
    pub size_x: usize,
    pub size_y: usize,
    pub data: Vec<Vector3<f32>>,
}

pub struct Texture {
    pub levels: Vec<Surface>,
}

impl Surface {
    fn new(size_x: usize, size_y: usize) -> Surface {
        Surface {
            size_x: size_x,
            size_y: size_y,
            data: Vec::<Vector3<f32>>::with_capacity(size_x * size_y),
        }
    }
}

impl Texture {
    fn load_surface<'a>(filename: &str) -> Result<surface::Surface<'a>, String> {
        let standart =
            match surface::Surface::new(1, 1, sdl2::pixels::PixelFormatEnum::ARGB8888) {
                Ok(v) => v,
                Err(e) => return Err(format!("can't create standart surface for texture {}, error = {}",
                                             filename, e))
            };

        let fullpath = try!(get_full_path(filename));
        let surface_load =
            unsafe {
                let raw = IMG_Load(std::ffi::CString::new(fullpath).unwrap().as_ptr());
                if (raw as *mut ()).is_null() {
                    return Err(format!("can't load texture {}, error = {}", filename, sdl2::get_error()));
                } else {
                    surface::Surface::from_ll(raw)
                }
            };

        match surface_load.as_ref().convert(&standart.as_ref().pixel_format()) {
            Ok(v) => Ok(v),
            Err(e) => return Err(format!("can't convert surface for texture {}, error = {}",
                                         filename, e))
        }
    }

    #[inline]
    fn add_color(clr: &mut Vector3<f32>, src: &Surface, x: i32, y: i32, k: u32) -> u32 {
        if x >= 0 && y >= 0 && x < (src.size_x as i32) && y < (src.size_y as i32) {
            let ind = (y as usize) * src.size_x + x as usize;
            clr.add_self_v(&src.data[ind].mul_s(k as f32));
            k
        } else {
            0
        }
    }

    fn gen_mipmap(&mut self) {
        let mut surface_ind = 0;
        let mut size_x = self.levels[surface_ind].size_x as i32;
        let mut size_y = self.levels[surface_ind].size_y as i32;

        while std::cmp::min(size_x, size_y) != 1 {
            let next_size_x = size_x >> 1;
            let next_size_y = size_y >> 1;
            let mut s = Surface::new(next_size_x as usize, next_size_y as usize);
            {
                let src = &(self.levels[surface_ind]);
                let mut dst = &mut s.data;

                // koeff table
                // 1 2 1
		        // 2 4 2
		        // 1 2 1
                for y in 0..next_size_y {
                    for x in 0..next_size_x {
                        let mut clr = Vector3::zero();
                        let mut cnt: u32 = 0;
                        {
                            let mut f = |add_x: i32, add_y: i32, k: u32| {
                                Texture::add_color(&mut clr, src, x * 2 + add_x, y * 2 + add_y, k)
                            };

                            cnt += f(-1, -1, 1);
                            cnt += f( 0, -1, 2);
                            cnt += f( 1, -1, 1);
                            cnt += f(-1,  0, 2);
                            cnt += f( 0,  0, 4);
                            cnt += f( 1,  0, 2);
                            cnt += f(-1,  1, 1);
                            cnt += f( 0,  1, 2);
                            cnt += f( 1,  1, 1);
                        }
                        dst.push(clr.div_s(cnt as f32));
                    }
                }
            }

            self.levels.push(s);
            size_x = next_size_x;
            size_y = next_size_y;
            surface_ind += 1;
        }
    }

    pub fn new(filename: &str) -> Result<Texture, String> {
        let surface = try!(Texture::load_surface(filename));

        let size_x = surface.as_ref().width() as usize;
        let size_y = surface.as_ref().height() as usize;
        let data_u8: &[u8] = match surface.as_ref().without_lock() {
            Some(v) => v,
            None => return Err(format!("can't lock surface for texture {}", filename))
        };

        let mut lvl0 = Surface::new(size_x, size_y);
        for y in 0..size_y {
            for x in 0..size_x {
                lvl0.data.push(Vector3::new(
                    data_u8[(y * size_x + size_x - x - 1) * 4 + 2] as f32,
                    data_u8[(y * size_x + size_x - x - 1) * 4 + 1] as f32,
                    data_u8[(y * size_x + size_x - x - 1) * 4 + 0] as f32));
            }
        }

        let mut tex = Texture {levels: vec![lvl0], };
        tex.gen_mipmap();

        Ok(tex)
    }
}
<|endoftext|>


<commit_before>use std::borrow::Cow;
use std::collections::HashMap;
use page::Slug;

#[derive(Debug)]
struct TocTreeElement {
    slug: Slug,
    title: Option<String>,
}

pub struct TocTree {
    root: Slug,

    /// Maps parent -> children
    children: HashMap<Slug, Vec<TocTreeElement>>,

    /// Maps child -> parents
    inverse_children: HashMap<Slug, Vec<Slug>>,

    titles: HashMap<Slug, String>,
    pretty_url: bool,
}

impl TocTree {
    pub fn new(root: Slug, pretty_url: bool) -> Self {
        TocTree {
            root: root,
            children: HashMap::new(),
            inverse_children: HashMap::new(),
            titles: HashMap::new(),
            pretty_url: pretty_url,
        }
    }

    pub fn new_empty() -> Self {
        Self::new(Slug::new("".to_owned()), false)
    }

    pub fn add(&mut self, parent_slug: &Slug, child: Slug, title: Option<String>) {
        let new_element = TocTreeElement {
            slug: child.to_owned(),
            title: title,
        };

        self.inverse_children
            .entry(child)
            .or_insert_with(|| vec![parent_slug.to_owned()]);
        self.children
            .entry(parent_slug.to_owned())
            .or_insert_with(|| vec![new_element]);
    }

    pub fn finish(&mut self, titles: HashMap<Slug, String>) {
        self.titles = titles;
    }

    pub fn generate_html(&self, root: &Slug, current_slug: &Slug, is_root: bool) -> Result<Vec<Cow<'static, str>>, String> {
        let children = match self.children.get(root) {
            Some(children) => children,
            None => {
                return Ok(vec![Cow::Borrowed("")]);
            }
        };

        let mut result = vec![];

        let slug_prefix = "../".repeat(current_slug.depth(self.pretty_url));
        result.push(Cow::Borrowed("
"));

        if is_root {
            result.push(Cow::Borrowed(r#"
"#));
            let title = self.titles.get(&self.root).ok_or_else(|| format!("Failed to find toctree root '{}'", &self.root))?;
            result.push(Cow::Owned(format!(r#"{}"#,
                                           slug_prefix,
                                           Slug::new("".to_owned()),
                                           title)));
            result.push(Cow::Borrowed("
"));
        }

        for child in children {
            if self.is_child_of(root, &child.slug) {
                result.push(Cow::Borrowed(r#"
"#));
            } else {
                result.push(Cow::Borrowed("
"));
            }

            let title = match child.title.as_ref() {
                Some(t) => t,
                None => {
                    self.titles
                        .get(&child.slug)
                        .ok_or_else(|| format!("Failed to find toctree entry '{}'", &child.slug))?
                }
            };

            result.push(Cow::Owned(format!(r#"{}"#,
                                           slug_prefix,
                                           child.slug,
                                           title)));
            result.extend(self.generate_html(&child.slug, current_slug, false)?);
            result.push(Cow::Borrowed("
"));
        }
        result.push(Cow::Borrowed("
"));

        if is_root {
            result.push(Cow::Borrowed("
"));
        }

        Ok(result)
    }

    /// Return True if slug is a child/grand-child/... of ancestor.
    fn is_child_of(&self, slug: &Slug, ancestor: &Slug) -> bool {
        if slug == ancestor {
            return true;
        }

        match self.inverse_children.get(slug) {
            Some(parents) => {
                parents
                    .iter()
                    .any(|parent| self.is_child_of(parent, ancestor))
            }
            _ => false,
        }
    }
}
<commit_msg>toctree: Fix document tree<commit_after>use std::borrow::Cow;
use std::collections::HashMap;
use page::Slug;

#[derive(Debug)]
struct TocTreeElement {
    slug: Slug,
    title: Option<String>,
}

pub struct TocTree {
    root: Slug,

    /// Maps parent -> children
    children: HashMap<Slug, Vec<TocTreeElement>>,

    /// Maps child -> parents
    inverse_children: HashMap<Slug, Vec<Slug>>,

    titles: HashMap<Slug, String>,
    pretty_url: bool,
}

impl TocTree {
    pub fn new(root: Slug, pretty_url: bool) -> Self {
        TocTree {
            root: root,
            children: HashMap::new(),
            inverse_children: HashMap::new(),
            titles: HashMap::new(),
            pretty_url: pretty_url,
        }
    }

    pub fn new_empty() -> Self {
        Self::new(Slug::new("".to_owned()), false)
    }

    pub fn add(&mut self, parent_slug: &Slug, child: Slug, title: Option<String>) {
        let new_element = TocTreeElement {
            slug: child.to_owned(),
            title: title,
        };

        self.inverse_children
            .entry(child)
            .or_insert_with(|| vec![]).push(parent_slug.to_owned());
        self.children
            .entry(parent_slug.to_owned())
            .or_insert_with(|| vec![]).push(new_element);
    }

    pub fn finish(&mut self, titles: HashMap<Slug, String>) {
        self.titles = titles;
    }

    pub fn generate_html(&self, root: &Slug, current_slug: &Slug, is_root: bool) -> Result<Vec<Cow<'static, str>>, String> {
        let children = match self.children.get(root) {
            Some(children) => children,
            None => {
                return Ok(vec![Cow::Borrowed("")]);
            }
        };

        let mut result = vec![];

        let slug_prefix = "../".repeat(current_slug.depth(self.pretty_url));
        result.push(Cow::Borrowed("
"));

        if is_root {
            result.push(Cow::Borrowed(r#"
"#));
            let title = self.titles.get(&self.root).ok_or_else(|| format!("Failed to find toctree root '{}'", &self.root))?;
            result.push(Cow::Owned(format!(r#"{}"#,
                                           slug_prefix,
                                           Slug::new("".to_owned()),
                                           title)));
            result.push(Cow::Borrowed("
"));
        }

        for child in children {
            if self.is_child_of(root, &child.slug) {
                result.push(Cow::Borrowed(r#"
"#));
            } else {
                result.push(Cow::Borrowed("
"));
            }

            let title = match child.title.as_ref() {
                Some(t) => t,
                None => {
                    self.titles
                        .get(&child.slug)
                        .ok_or_else(|| format!("Failed to find toctree entry '{}'", &child.slug))?
                }
            };

            result.push(Cow::Owned(format!(r#"{}"#,
                                           slug_prefix,
                                           child.slug,
                                           title)));
            result.extend(self.generate_html(&child.slug, current_slug, false)?);
            result.push(Cow::Borrowed("
"));
        }
        result.push(Cow::Borrowed("
"));

        if is_root {
            result.push(Cow::Borrowed("
"));
        }

        Ok(result)
    }

    /// Return True if slug is a child/grand-child/... of ancestor.
    fn is_child_of(&self, slug: &Slug, ancestor: &Slug) -> bool {
        if slug == ancestor {
            return true;
        }

        match self.inverse_children.get(slug) {
            Some(parents) => {
                parents
                    .iter()
                    .any(|parent| self.is_child_of(parent, ancestor))
            }
            _ => false,
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

pub mod convert;

use std::path::PathBuf;

use convert::FromLossy;

use rrg_macro::ack;

include!(concat!(env!("OUT_DIR"), "/grr.rs"));

impl From<bool> for DataBlob {

    fn from(value: bool) -> DataBlob {
        DataBlob {
            boolean: Some(value),
            ..Default::default()
        }
    }
}

impl From<i64> for DataBlob {

    fn from(value: i64) -> DataBlob {
        DataBlob {
            integer: Some(value),
            ..Default::default()
        }
    }
}

impl From<f32> for DataBlob {

    fn from(value: f32) -> DataBlob {
        DataBlob {
            float: Some(value),
            ..Default::default()
        }
    }
}

impl From<Vec<u8>> for DataBlob {

    fn from(value: Vec<u8>) -> DataBlob {
        DataBlob {
            data: Some(value),
            ..Default::default()
        }
    }
}

impl From<String> for DataBlob {

    fn from(value: String) -> DataBlob  {
        DataBlob {
            string: Some(value),
            ..Default::default()
        }
    }
}

impl KeyValue {

    /// Creates an empty key-value.
    ///
    /// Both the key and the value are going to be equal to `None`.
    ///
    /// # Examples
    ///
    /// ```
    /// use rrg_proto::KeyValue;
    ///
    /// let entry = KeyValue::empty();
    /// assert_eq!(entry.k, None);
    /// assert_eq!(entry.v, None);
    /// ```
    pub fn empty() -> KeyValue {
        KeyValue {
            k: None,
            v: None,
        }
    }

    /// Creates a key-value pair.
    ///
    /// Both the key and the value are going to be equal to the given values.
    ///
    /// # Examples
    ///
    /// ```
    /// use rrg_proto::KeyValue;
    ///
    /// let entry = KeyValue::pair(String::from("foo"), 42i64);
    /// assert_eq!(entry.k.unwrap().string, Some(String::from("foo")));
    /// assert_eq!(entry.v.unwrap().integer, Some(42));
    /// ```
    pub fn pair<K, V>(key: K, value: V) -> KeyValue
    where
        K: Into<DataBlob>,
        V: Into<DataBlob>,
    {
        KeyValue {
            k: Some(key.into()),
            v: Some(value.into()),
        }
    }

    /// Creates a key-only key-value.
    ///
    /// The key is going to be equal to the given value and the key will be
    /// `None`.
    ///
    /// # Examples
    ///
    /// ```
    /// use rrg_proto::KeyValue;
    ///
    /// let entry = KeyValue::key(String::from("quux"));
    /// assert_eq!(entry.k.unwrap().string, Some(String::from("quux")));
    /// assert_eq!(entry.v, None);
    /// ```
    pub fn key<K>(key: K) -> KeyValue
    where
        K: Into<DataBlob>,
    {
        KeyValue {
            k: Some(key.into()),
            v: None,
        }
    }
}

impl std::iter::FromIterator<KeyValue> for AttributedDict {

    fn from_iter<I>(iter: I) -> AttributedDict
    where
        I: IntoIterator<Item = KeyValue>,
    {
        AttributedDict {
            dat: iter.into_iter().collect(),
        }
    }
}

impl<K, V> std::iter::FromIterator<(K, V)> for AttributedDict
where
    K: Into<DataBlob>,
    V: Into<DataBlob>,
{
    fn from_iter<I>(iter: I) -> AttributedDict
    where
        I: IntoIterator<Item = (K, V)>,
    {
        let pair = |(key, value)| KeyValue::pair(key, value);
        iter.into_iter().map(pair).collect()
    }
}

impl FromLossy<std::fs::Metadata> for StatEntry {

    fn from_lossy(metadata: std::fs::Metadata) -> StatEntry {
        use std::convert::{TryFrom, TryInto};
        #[cfg(target_family = "unix")]
        use std::os::unix::fs::MetadataExt;

        // TODO: Fix definition of `StatEntry`.
        // `StatEntry` defines insufficient integer width for some fields. For
        // now we just ignore errors, but the definition should be improved.
        let some = |value: u64| Some(value.try_into().unwrap_or(0));

        let atime_secs = ack! {
            metadata.accessed(),
            error: "failed to obtain file access time"
        }.and_then(|atime| ack! {
            secs(atime),
            error: "failed to convert access time to seconds"
        });

        let mtime_secs = ack! {
            metadata.modified(),
            error: "failed to obtain file modification time"
        }.and_then(|mtime| ack! {
            secs(mtime),
            error: "failed to convert modification time to seconds"
        });

        let btime_secs = ack! {
            metadata.created(),
            error: "failed to obtain file creation time"
        }.and_then(|btime| ack! {
            secs(btime),
            error: "failed to convert creation time to seconds"
        });

        #[cfg(target_family = "unix")]
        let ctime_secs = ack! {
            u64::try_from(metadata.ctime()),
            error: "negative inode change time"
        };

        StatEntry {
            #[cfg(target_family = "unix")]
            st_mode: Some(metadata.mode().into()),
            #[cfg(target_family = "unix")]
            st_ino: some(metadata.ino()),
            #[cfg(target_family = "unix")]
            st_dev: some(metadata.dev()),
            #[cfg(target_family = "unix")]
            st_rdev: some(metadata.rdev()),
            #[cfg(target_family = "unix")]
            st_nlink: some(metadata.nlink()),
            #[cfg(target_family = "unix")]
            st_uid: Some(metadata.uid()),
            #[cfg(target_family = "unix")]
            st_gid: Some(metadata.gid()),
            st_size: Some(metadata.len()),
            st_atime: atime_secs,
            st_mtime: mtime_secs,
            #[cfg(target_family = "unix")]
            st_ctime: ctime_secs,
            st_btime: btime_secs,
            #[cfg(target_family = "unix")]
            st_blocks: some(metadata.blocks()),
            #[cfg(target_family = "unix")]
            st_blksize: some(metadata.blksize()),
            ..Default::default()
        }
    }
}

/// An error type for situations where parsing path specification failed.
#[derive(Clone, Debug)]
pub enum ParsePathSpecError {
    /// Attempted to parse an empty path.
    Empty,
    /// Attempted to parse a path of unknown type.
    UnknownType(i32),
    /// Attempted to parse a path of invalid type.
    InvalidType(path_spec::PathType),
}

impl std::fmt::Display for ParsePathSpecError {

    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        use ParsePathSpecError::*;

        match *self {
            Empty => {
                write!(fmt, "empty path")
            }
            UnknownType(value) => {
                write!(fmt, "unknown path type value: {}", value)
            }
            InvalidType(value) => {
                write!(fmt, "invalid path type: {:?}", value)
            }
        }
    }
}

impl std::error::Error for ParsePathSpecError {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        None
    }
}

impl std::convert::TryFrom<PathSpec> for PathBuf {

    type Error = ParsePathSpecError;

    fn try_from(spec: PathSpec) -> Result<PathBuf, ParsePathSpecError> {
        use ParsePathSpecError::*;

        let path_type = spec.pathtype.unwrap_or_default();
        match path_spec::PathType::from_i32(path_type) {
            Some(path_spec::PathType::Os) => (),
            Some(path_type) => return Err(InvalidType(path_type)),
            None => return Err(UnknownType(path_type)),
        };

        match spec.path {
            Some(path) if path.len() > 0 => Ok(PathBuf::from(path)),
            _ => Err(ParsePathSpecError::Empty),
        }
    }
}

impl From<PathBuf> for PathSpec {

    fn from(path: PathBuf) -> PathSpec {
        PathSpec {
            path: Some(path.to_string_lossy().into_owned()),
            pathtype: Some(path_spec::PathType::Os.into()),
            ..Default::default()
        }
    }
}

/// An error type for failures of converting timestamps to microseconds.
#[derive(Clone, Debug)]
pub enum MicrosError {
    /// Attempted to convert pre-epoch system time.
    Epoch(std::time::SystemTimeError),
    /// Attempted to convert a value outside of 64-bit unsigned integer range.
    Overflow(std::num::TryFromIntError),
}

impl MicrosError {

    /// Creates a microsecond conversion error from an integer overflow error.
    pub fn overflow(error: std::num::TryFromIntError) -> MicrosError {
        MicrosError::Overflow(error)
    }
}

impl std::fmt::Display for MicrosError {

    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        use MicrosError::*;

        match *self {
            Epoch(ref error) => {
                write!(fmt, "pre-epoch system time: {}", error)
            }
            Overflow(ref error) => {
                write!(fmt, "system time value too big: {}", error)
            }
        }
    }
}

impl std::error::Error for MicrosError {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        use MicrosError::*;

        match *self {
            Epoch(ref error) => Some(error),
            Overflow(ref error) => Some(error),
        }
    }
}

impl From<std::time::SystemTimeError> for MicrosError {

    fn from(error: std::time::SystemTimeError) -> MicrosError {
        MicrosError::Epoch(error)
    }
}

/// An error type for failures of converting timestamps to seconds.
#[derive(Clone, Debug)]
pub struct SecsError {
    error: MicrosError,
}

impl std::fmt::Display for SecsError {

    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        self.error.fmt(fmt)
    }
}

impl From<MicrosError> for SecsError {

    fn from(error: MicrosError) -> SecsError {
        SecsError {
            error: error,
        }
    }
}

impl From<SecsError> for MicrosError {

    fn from(error: SecsError) -> MicrosError {
        error.error
    }
}

/// Converts system time into epoch microseconds.
///
/// Because most GRR messages use epoch microseconds for representing timestamps
/// this function be be useful to convert from more idiomatic representations.
///
/// # Examples
///
/// ```
/// use rrg_proto::micros;
///
/// assert_eq!(micros(std::time::UNIX_EPOCH).unwrap(), 0);
/// ```
pub fn micros(time: std::time::SystemTime) -> Result<u64, MicrosError> {
    let time_micros = time.duration_since(std::time::UNIX_EPOCH)?.as_micros();

    use std::convert::TryInto as _;
    time_micros.try_into().map_err(MicrosError::overflow)
}

/// Converts system time into epoch seconds.
///
/// Some GRR messages use epoch seconds for representing timestamps. In such
/// cases this function can be useful to convert from more idiomatic types.
///
/// # Examples
///
/// ```
/// use rrg_proto::secs;
///
/// assert_eq!(secs(std::time::UNIX_EPOCH).unwrap(), 0);
/// ```
pub fn secs(time: std::time::SystemTime) -> Result<u64, SecsError> {
    Ok(micros(time)? / 1_000_000)
}
<commit_msg>Create an utility for nanosecond conversions.<commit_after>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

pub mod convert;

use std::path::PathBuf;

use convert::FromLossy;

use rrg_macro::ack;

include!(concat!(env!("OUT_DIR"), "/grr.rs"));

impl From<bool> for DataBlob {

    fn from(value: bool) -> DataBlob {
        DataBlob {
            boolean: Some(value),
            ..Default::default()
        }
    }
}

impl From<i64> for DataBlob {

    fn from(value: i64) -> DataBlob {
        DataBlob {
            integer: Some(value),
            ..Default::default()
        }
    }
}

impl From<f32> for DataBlob {

    fn from(value: f32) -> DataBlob {
        DataBlob {
            float: Some(value),
            ..Default::default()
        }
    }
}

impl From<Vec<u8>> for DataBlob {

    fn from(value: Vec<u8>) -> DataBlob {
        DataBlob {
            data: Some(value),
            ..Default::default()
        }
    }
}

impl From<String> for DataBlob {

    fn from(value: String) -> DataBlob  {
        DataBlob {
            string: Some(value),
            ..Default::default()
        }
    }
}

impl KeyValue {

    /// Creates an empty key-value.
    ///
    /// Both the key and the value are going to be equal to `None`.
    ///
    /// # Examples
    ///
    /// ```
    /// use rrg_proto::KeyValue;
    ///
    /// let entry = KeyValue::empty();
    /// assert_eq!(entry.k, None);
    /// assert_eq!(entry.v, None);
    /// ```
    pub fn empty() -> KeyValue {
        KeyValue {
            k: None,
            v: None,
        }
    }

    /// Creates a key-value pair.
    ///
    /// Both the key and the value are going to be equal to the given values.
    ///
    /// # Examples
    ///
    /// ```
    /// use rrg_proto::KeyValue;
    ///
    /// let entry = KeyValue::pair(String::from("foo"), 42i64);
    /// assert_eq!(entry.k.unwrap().string, Some(String::from("foo")));
    /// assert_eq!(entry.v.unwrap().integer, Some(42));
    /// ```
    pub fn pair<K, V>(key: K, value: V) -> KeyValue
    where
        K: Into<DataBlob>,
        V: Into<DataBlob>,
    {
        KeyValue {
            k: Some(key.into()),
            v: Some(value.into()),
        }
    }

    /// Creates a key-only key-value.
    ///
    /// The key is going to be equal to the given value and the key will be
    /// `None`.
    ///
    /// # Examples
    ///
    /// ```
    /// use rrg_proto::KeyValue;
    ///
    /// let entry = KeyValue::key(String::from("quux"));
    /// assert_eq!(entry.k.unwrap().string, Some(String::from("quux")));
    /// assert_eq!(entry.v, None);
    /// ```
    pub fn key<K>(key: K) -> KeyValue
    where
        K: Into<DataBlob>,
    {
        KeyValue {
            k: Some(key.into()),
            v: None,
        }
    }
}

impl std::iter::FromIterator<KeyValue> for AttributedDict {

    fn from_iter<I>(iter: I) -> AttributedDict
    where
        I: IntoIterator<Item = KeyValue>,
    {
        AttributedDict {
            dat: iter.into_iter().collect(),
        }
    }
}

impl<K, V> std::iter::FromIterator<(K, V)> for AttributedDict
where
    K: Into<DataBlob>,
    V: Into<DataBlob>,
{
    fn from_iter<I>(iter: I) -> AttributedDict
    where
        I: IntoIterator<Item = (K, V)>,
    {
        let pair = |(key, value)| KeyValue::pair(key, value);
        iter.into_iter().map(pair).collect()
    }
}

impl FromLossy<std::fs::Metadata> for StatEntry {

    fn from_lossy(metadata: std::fs::Metadata) -> StatEntry {
        use std::convert::{TryFrom, TryInto};
        #[cfg(target_family = "unix")]
        use std::os::unix::fs::MetadataExt;

        // TODO: Fix definition of `StatEntry`.
        // `StatEntry` defines insufficient integer width for some fields. For
        // now we just ignore errors, but the definition should be improved.
        let some = |value: u64| Some(value.try_into().unwrap_or(0));

        let atime_secs = ack! {
            metadata.accessed(),
            error: "failed to obtain file access time"
        }.and_then(|atime| ack! {
            secs(atime),
            error: "failed to convert access time to seconds"
        });

        let mtime_secs = ack! {
            metadata.modified(),
            error: "failed to obtain file modification time"
        }.and_then(|mtime| ack! {
            secs(mtime),
            error: "failed to convert modification time to seconds"
        });

        let btime_secs = ack! {
            metadata.created(),
            error: "failed to obtain file creation time"
        }.and_then(|btime| ack! {
            secs(btime),
            error: "failed to convert creation time to seconds"
        });

        #[cfg(target_family = "unix")]
        let ctime_secs = ack! {
            u64::try_from(metadata.ctime()),
            error: "negative inode change time"
        };

        StatEntry {
            #[cfg(target_family = "unix")]
            st_mode: Some(metadata.mode().into()),
            #[cfg(target_family = "unix")]
            st_ino: some(metadata.ino()),
            #[cfg(target_family = "unix")]
            st_dev: some(metadata.dev()),
            #[cfg(target_family = "unix")]
            st_rdev: some(metadata.rdev()),
            #[cfg(target_family = "unix")]
            st_nlink: some(metadata.nlink()),
            #[cfg(target_family = "unix")]
            st_uid: Some(metadata.uid()),
            #[cfg(target_family = "unix")]
            st_gid: Some(metadata.gid()),
            st_size: Some(metadata.len()),
            st_atime: atime_secs,
            st_mtime: mtime_secs,
            #[cfg(target_family = "unix")]
            st_ctime: ctime_secs,
            st_btime: btime_secs,
            #[cfg(target_family = "unix")]
            st_blocks: some(metadata.blocks()),
            #[cfg(target_family = "unix")]
            st_blksize: some(metadata.blksize()),
            ..Default::default()
        }
    }
}

/// An error type for situations where parsing path specification failed.
#[derive(Clone, Debug)]
pub enum ParsePathSpecError {
    /// Attempted to parse an empty path.
    Empty,
    /// Attempted to parse a path of unknown type.
    UnknownType(i32),
    /// Attempted to parse a path of invalid type.
    InvalidType(path_spec::PathType),
}

impl std::fmt::Display for ParsePathSpecError {

    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        use ParsePathSpecError::*;

        match *self {
            Empty => {
                write!(fmt, "empty path")
            }
            UnknownType(value) => {
                write!(fmt, "unknown path type value: {}", value)
            }
            InvalidType(value) => {
                write!(fmt, "invalid path type: {:?}", value)
            }
        }
    }
}

impl std::error::Error for ParsePathSpecError {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        None
    }
}

impl std::convert::TryFrom<PathSpec> for PathBuf {

    type Error = ParsePathSpecError;

    fn try_from(spec: PathSpec) -> Result<PathBuf, ParsePathSpecError> {
        use ParsePathSpecError::*;

        let path_type = spec.pathtype.unwrap_or_default();
        match path_spec::PathType::from_i32(path_type) {
            Some(path_spec::PathType::Os) => (),
            Some(path_type) => return Err(InvalidType(path_type)),
            None => return Err(UnknownType(path_type)),
        };

        match spec.path {
            Some(path) if path.len() > 0 => Ok(PathBuf::from(path)),
            _ => Err(ParsePathSpecError::Empty),
        }
    }
}

impl From<PathBuf> for PathSpec {

    fn from(path: PathBuf) -> PathSpec {
        PathSpec {
            path: Some(path.to_string_lossy().into_owned()),
            pathtype: Some(path_spec::PathType::Os.into()),
            ..Default::default()
        }
    }
}

/// An error type for failures of converting timestamps to nanoseconds.
#[derive(Clone, Debug)]
pub enum NanosError {
    /// Attempted to convert pre-epoch system time.
    Epoch(std::time::SystemTimeError),
    /// Attempted to convert a value outside of 64-bit unsigned integer range.
    Overflow(std::num::TryFromIntError),
}

impl NanosError {

    /// Creates a nanosecond conversion error from an integer overflow error.
    pub fn overflow(error: std::num::TryFromIntError) -> NanosError {
        NanosError::Overflow(error)
    }
}

impl std::fmt::Display for NanosError {

    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        use NanosError::*;

        match *self {
            Epoch(ref error) => {
                write!(fmt, "pre-epoch system time: {}", error)
            }
            Overflow(ref error) => {
                write!(fmt, "system time value too big: {}", error)
            }
        }
    }
}

impl std::error::Error for NanosError {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        use NanosError::*;

        match *self {
            Epoch(ref error) => Some(error),
            Overflow(ref error) => Some(error),
        }
    }
}

impl From<std::time::SystemTimeError> for NanosError {

    fn from(error: std::time::SystemTimeError) -> NanosError {
        NanosError::Epoch(error)
    }
}

/// An error type for failures of converting timestamps to microseconds.
#[derive(Clone, Debug)]
pub enum MicrosError {
    /// Attempted to convert pre-epoch system time.
    Epoch(std::time::SystemTimeError),
    /// Attempted to convert a value outside of 64-bit unsigned integer range.
    Overflow(std::num::TryFromIntError),
}

impl MicrosError {

    /// Creates a microsecond conversion error from an integer overflow error.
    pub fn overflow(error: std::num::TryFromIntError) -> MicrosError {
        MicrosError::Overflow(error)
    }
}

impl std::fmt::Display for MicrosError {

    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        use MicrosError::*;

        match *self {
            Epoch(ref error) => {
                write!(fmt, "pre-epoch system time: {}", error)
            }
            Overflow(ref error) => {
                write!(fmt, "system time value too big: {}", error)
            }
        }
    }
}

impl std::error::Error for MicrosError {

    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        use MicrosError::*;

        match *self {
            Epoch(ref error) => Some(error),
            Overflow(ref error) => Some(error),
        }
    }
}

impl From<std::time::SystemTimeError> for MicrosError {

    fn from(error: std::time::SystemTimeError) -> MicrosError {
        MicrosError::Epoch(error)
    }
}

/// An error type for failures of converting timestamps to seconds.
#[derive(Clone, Debug)]
pub struct SecsError {
    error: MicrosError,
}

impl std::fmt::Display for SecsError {

    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        self.error.fmt(fmt)
    }
}

impl From<MicrosError> for SecsError {

    fn from(error: MicrosError) -> SecsError {
        SecsError {
            error: error,
        }
    }
}

impl From<SecsError> for MicrosError {

    fn from(error: SecsError) -> MicrosError {
        error.error
    }
}

/// Converts system time into epoch nanoseconds.
///
/// Some GRR messages use epoch nanoseconds for representing timestamps. In such
/// cases this function can be useful to convert from more idiomatic types.
///
/// # Examples
///
/// ```
/// use rrg_proto::nanos;
///
/// assert_eq!(nanos(std::time::UNIX_EPOCH).unwrap(), 0);
/// ```
pub fn nanos(time: std::time::SystemTime) -> Result<u64, NanosError> {
    let time_nanos = time.duration_since(std::time::UNIX_EPOCH)?.as_nanos();

    use std::convert::TryInto as _;
    time_nanos.try_into().map_err(NanosError::overflow)
}

/// Converts system time into epoch microseconds.
///
/// Because most GRR messages use epoch microseconds for representing timestamps
/// this function be be useful to convert from more idiomatic representations.
///
/// # Examples
///
/// ```
/// use rrg_proto::micros;
///
/// assert_eq!(micros(std::time::UNIX_EPOCH).unwrap(), 0);
/// ```
pub fn micros(time: std::time::SystemTime) -> Result<u64, MicrosError> {
    let time_micros = time.duration_since(std::time::UNIX_EPOCH)?.as_micros();

    use std::convert::TryInto as _;
    time_micros.try_into().map_err(MicrosError::overflow)
}

/// Converts system time into epoch seconds.
///
/// Some GRR messages use epoch seconds for representing timestamps. In such
/// cases this function can be useful to convert from more idiomatic types.
///
/// # Examples
///
/// ```
/// use rrg_proto::secs;
///
/// assert_eq!(secs(std::time::UNIX_EPOCH).unwrap(), 0);
/// ```
pub fn secs(time: std::time::SystemTime) -> Result<u64, SecsError> {
    Ok(micros(time)? / 1_000_000)
}
<|endoftext|>


<commit_before>//! SDK Configuration
//!
//! Configuration represents the global tracing configuration, overrides
//! can be set for the default OpenTelemetry limits and Sampler.
use crate::{api, sdk};
use std::sync::Arc;

/// Tracer configuration
#[derive(Debug)]
pub struct Config {
    /// The sampler that the sdk should use
    pub default_sampler: Box<dyn api::Sampler>,
    /// The id generator that the sdk should use
    pub id_generator: Box<dyn api::IdGenerator>,
    /// The max events that can be added to a `Span`.
    pub max_events_per_span: u32,
    /// The max attributes that can be added to a `Span`.
    pub max_attributes_per_span: u32,
    /// The max links that can be added to a `Span`.
    pub max_links_per_span: u32,
    /// Contains attributes representing an entity that produces telemetry.
    pub resource: Arc<sdk::Resource>,
}

impl Default for Config {
    /// Create default global sdk configuration.
    fn default() -> Self {
        Config {
            default_sampler: Box::new(sdk::Sampler::AlwaysOn),
            id_generator: Box::new(sdk::IdGenerator::default()),
            max_events_per_span: 128,
            max_attributes_per_span: 32,
            max_links_per_span: 32,
            resource: Arc::new(sdk::Resource::default()),
        }
    }
}
<commit_msg>Change the default sampler to be ParentOrElse(AlwaysOn) (#163)<commit_after>//! SDK Configuration
//!
//! Configuration represents the global tracing configuration, overrides
//! can be set for the default OpenTelemetry limits and Sampler.
use crate::{api, sdk};
use std::sync::Arc;

/// Tracer configuration
#[derive(Debug)]
pub struct Config {
    /// The sampler that the sdk should use
    pub default_sampler: Box<dyn api::Sampler>,
    /// The id generator that the sdk should use
    pub id_generator: Box<dyn api::IdGenerator>,
    /// The max events that can be added to a `Span`.
    pub max_events_per_span: u32,
    /// The max attributes that can be added to a `Span`.
    pub max_attributes_per_span: u32,
    /// The max links that can be added to a `Span`.
    pub max_links_per_span: u32,
    /// Contains attributes representing an entity that produces telemetry.
    pub resource: Arc<sdk::Resource>,
}

impl Default for Config {
    /// Create default global sdk configuration.
    fn default() -> Self {
        Config {
            default_sampler: Box::new(sdk::Sampler::ParentOrElse(Box::new(sdk::Sampler::AlwaysOn))),
            id_generator: Box::new(sdk::IdGenerator::default()),
            max_events_per_span: 128,
            max_attributes_per_span: 32,
            max_links_per_span: 32,
            resource: Arc::new(sdk::Resource::default()),
        }
    }
}
<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::iter::Iterator;
use std::rc::Rc;
use std::ops::Deref;

use storage::file::File;

pub trait FilePrinter {

    fn new(verbose: bool, debug: bool) -> Self;

    /*
     * Print a single file
     */
    fn print_file(&self, Rc<RefCell<File>>);

    /*
     * Print a list of files
     */
    fn print_files<I: Iterator<Item = Rc<RefCell<File>>>>(&self, files: I) {
        for file in files {
            self.print_file(file);
        }
    }

    fn print_file_custom<F>(&self, file: Rc<RefCell<File>>, f: &F)
        where F: Fn(Rc<RefCell<File>>) -> String
    {
        info!("{}", f(file));
    }

    fn print_files_custom<F, I>(&self, files: I, f: &F)
        where I: Iterator<Item = Rc<RefCell<File>>>,
              F: Fn(Rc<RefCell<File>>) -> String
    {
        for file in files {
            self.print_file_custom(file, f);
        }
    }

}

struct DebugPrinter {
    debug: bool,
}

impl FilePrinter for DebugPrinter {

    fn new(_: bool, debug: bool) -> DebugPrinter {
        DebugPrinter {
            debug: debug,
        }
    }

    fn print_file(&self, f: Rc<RefCell<File>>) {
        if self.debug {
            debug!("[DebugPrinter] ->\n{:?}", f);
        }
    }

}

struct SimplePrinter {
    verbose:    bool,
    debug:      bool,
}

impl FilePrinter for SimplePrinter {

    fn new(verbose: bool, debug: bool) -> SimplePrinter {
        SimplePrinter {
            debug:      debug,
            verbose:    verbose,
        }
    }

    fn print_file(&self, f: Rc<RefCell<File>>) {
        if self.debug {
            debug!("{:?}", f);
        } else if self.verbose {
            info!("{}", &*f.deref().borrow());
        } else {
            info!("[File]: {}", f.deref().borrow().id());
        }
    }

}

pub struct TablePrinter {
    verbose:    bool,
    debug:      bool,
    sp:         SimplePrinter,
}

impl FilePrinter for TablePrinter {

    fn new(verbose: bool, debug: bool) -> TablePrinter {
        TablePrinter {
            debug:      debug,
            verbose:    verbose,
            sp:         SimplePrinter::new(verbose, debug),
        }
    }

    fn print_file(&self, f: Rc<RefCell<File>>) {
        self.sp.print_file(f);
    }

    fn print_files<I: Iterator<Item = Rc<RefCell<File>>>>(&self, files: I) {
        use prettytable::Table;
        use prettytable::row::Row;
        use prettytable::cell::Cell;

        let titles = row!["File#", "Owner", "ID"];

        let mut tab = Table::new();
        tab.set_titles(titles);

        let mut i = 0;
        for file in files {
            debug!("Printing file: {:?}", file);
            i += 1;
            let cell_i  = Cell::new(&format!("{}", i)[..]);
            let cell_o  = Cell::new(&format!("{}", file.deref().borrow().owner_name())[..]);

            let id : String = file.deref().borrow().id().clone().into();
            let cell_id = Cell::new(&id[..]);
            let row = Row::new(vec![cell_i, cell_o, cell_id]);
            tab.add_row(row);
        }

        if i != 0 {
            debug!("Printing {} table entries", i);
            tab.printstd();
        } else {
            debug!("Not printing table because there are zero entries");
        }
    }

}
<commit_msg>Impl FilePrinter for DebugPrinter ::print_file_custom()<commit_after>use std::cell::RefCell;
use std::iter::Iterator;
use std::rc::Rc;
use std::ops::Deref;

use storage::file::File;

pub trait FilePrinter {

    fn new(verbose: bool, debug: bool) -> Self;

    /*
     * Print a single file
     */
    fn print_file(&self, Rc<RefCell<File>>);

    /*
     * Print a list of files
     */
    fn print_files<I: Iterator<Item = Rc<RefCell<File>>>>(&self, files: I) {
        for file in files {
            self.print_file(file);
        }
    }

    fn print_file_custom<F>(&self, file: Rc<RefCell<File>>, f: &F)
        where F: Fn(Rc<RefCell<File>>) -> String
    {
        info!("{}", f(file));
    }

    fn print_files_custom<F, I>(&self, files: I, f: &F)
        where I: Iterator<Item = Rc<RefCell<File>>>,
              F: Fn(Rc<RefCell<File>>) -> String
    {
        for file in files {
            self.print_file_custom(file, f);
        }
    }

}

struct DebugPrinter {
    debug: bool,
}

impl FilePrinter for DebugPrinter {

    fn new(_: bool, debug: bool) -> DebugPrinter {
        DebugPrinter {
            debug: debug,
        }
    }

    fn print_file(&self, f: Rc<RefCell<File>>) {
        if self.debug {
            debug!("[DebugPrinter] ->\n{:?}", f);
        }
    }

    fn print_file_custom<F>(&self, file: Rc<RefCell<File>>, f: &F)
        where F: Fn(Rc<RefCell<File>>) -> String
    {
        if self.debug {
            debug!("[DebugPrinter] ->\n{:?}", f(file));
        }
    }

}

struct SimplePrinter {
    verbose:    bool,
    debug:      bool,
}

impl FilePrinter for SimplePrinter {

    fn new(verbose: bool, debug: bool) -> SimplePrinter {
        SimplePrinter {
            debug:      debug,
            verbose:    verbose,
        }
    }

    fn print_file(&self, f: Rc<RefCell<File>>) {
        if self.debug {
            debug!("{:?}", f);
        } else if self.verbose {
            info!("{}", &*f.deref().borrow());
        } else {
            info!("[File]: {}", f.deref().borrow().id());
        }
    }

}

pub struct TablePrinter {
    verbose:    bool,
    debug:      bool,
    sp:         SimplePrinter,
}

impl FilePrinter for TablePrinter {

    fn new(verbose: bool, debug: bool) -> TablePrinter {
        TablePrinter {
            debug:      debug,
            verbose:    verbose,
            sp:         SimplePrinter::new(verbose, debug),
        }
    }

    fn print_file(&self, f: Rc<RefCell<File>>) {
        self.sp.print_file(f);
    }

    fn print_files<I: Iterator<Item = Rc<RefCell<File>>>>(&self, files: I) {
        use prettytable::Table;
        use prettytable::row::Row;
        use prettytable::cell::Cell;

        let titles = row!["File#", "Owner", "ID"];

        let mut tab = Table::new();
        tab.set_titles(titles);

        let mut i = 0;
        for file in files {
            debug!("Printing file: {:?}", file);
            i += 1;
            let cell_i  = Cell::new(&format!("{}", i)[..]);
            let cell_o  = Cell::new(&format!("{}", file.deref().borrow().owner_name())[..]);

            let id : String = file.deref().borrow().id().clone().into();
            let cell_id = Cell::new(&id[..]);
            let row = Row::new(vec![cell_i, cell_o, cell_id]);
            tab.add_row(row);
        }

        if i != 0 {
            debug!("Printing {} table entries", i);
            tab.printstd();
        } else {
            debug!("Not printing table because there are zero entries");
        }
    }

}
<|endoftext|>


<commit_before>use sqlite::Connection;
use std::collections::HashMap;
use std::rc::Rc;

use platform::{self, ElementKind};

use {Config, Result};

/// A workload pattern.
#[derive(Clone, Debug)]
pub struct Pattern(Rc<Content>);

deref! { Pattern::0 => Content }

/// The content of a workload pattern.
#[derive(Clone, Debug)]
pub struct Content {
    /// The name.
    pub name: String,
    /// The number of processing elements.
    pub units: usize,
    /// The number of time steps.
    pub steps: usize,
    /// The time step (sampling interval).
    pub time_step: f64,
    /// The processing elements.
    pub elements: Vec<Element>,
}

/// A processing element of a workload pattern.
#[derive(Clone, Debug)]
pub struct Element {
    /// The type.
    pub kind: ElementKind,
    /// The dynamic power.
    pub dynamic_power: Vec<f64>,
    /// The static power.
    pub leakage_power: f64,
}

impl Pattern {
    /// Create a pattern.
    pub fn new(config: &Config) -> Result<Pattern> {
        let path = path!(config, "a workload-pattern database is required");
        let backend = ok!(Connection::open(&path));

        info!(target: "Workload", "Reading {:?}...", &path);
        let name = match config.get::<String>("name") {
            Some(name) => name.to_string(),
            _ => path.file_stem().unwrap().to_str().unwrap().to_string(),
        };
        let time_step = *some!(config.get::<f64>("time_step"), "a time step is required");
        let mut names = try!(read_names(&backend));
        let mut dynamic_power = try!(read_dynamic_power(&backend));
        let mut leakage_power = try!(read_leakage_power(&backend));

        let mut ids = names.keys().map(|&id| id).collect::<Vec<_>>();
        ids.sort();

        let mut elements = vec![];
        for id in ids {
            elements.push(Element {
                kind: try!(names.remove(&id).unwrap().parse()),
                dynamic_power: some!(dynamic_power.remove(&id),
                                     "cannot find the dynamic power of a processing element"),
                leakage_power: some!(leakage_power.remove(&id),
                                     "cannot find the leakage power of a processing element"),
            });
        }

        let units = elements.len();
        if units == 0 {
            raise!("found a workload pattern without processing elements");
        }

        let steps = elements[0].dynamic_power.len();
        if steps == 0 {
            raise!("found a workload pattern without dynamic-power data");
        }

        Ok(Pattern(Rc::new(Content {
            name: name,
            units: units,
            steps: steps,
            time_step: time_step,
            elements: elements,
        })))
    }

    /// Return the time duration.
    #[inline]
    pub fn duration(&self) -> f64 {
        self.steps as f64 * self.time_step
    }
}

impl Element {
    /// Check if the type matches the type of a processing element of a
    /// platform.
    pub fn accept(&self, element: &platform::Element) -> bool {
        self.kind == element.kind
    }
}

fn read_names(backend: &Connection) -> Result<HashMap<i64, String>> {
    use sql::prelude::*;

    let mut data = HashMap::new();
    let statement = select_from("static").columns(&["component_id", "name"]);
    let mut cursor = ok!(backend.prepare(ok!(statement.compile()))).cursor();
    while let Some(row) = ok!(cursor.next()) {
        if let (Some(id), Some(value)) = (row[0].as_integer(), row[1].as_string()) {
            data.insert(id, value.to_string());
        } else {
            raise!("failed to read the names of processing elements");
        }
    }
    Ok(data)
}

fn read_dynamic_power(backend: &Connection) -> Result<HashMap<i64, Vec<f64>>> {
    use sql::prelude::*;

    let mut data = HashMap::new();
    let statement = select_from("dynamic").columns(&["time", "component_id", "dynamic_power"])
                                          .order_by(column("time").ascend());
    let mut cursor = ok!(backend.prepare(ok!(statement.compile()))).cursor();
    while let Some(row) = ok!(cursor.next()) {
        if let (Some(id), Some(value)) = (row[1].as_integer(), row[2].as_float()) {
            data.entry(id).or_insert_with(|| vec![]).push(value);
        } else {
            raise!("failed to read the dynamic power");
        }
    }
    Ok(data)
}

fn read_leakage_power(backend: &Connection) -> Result<HashMap<i64, f64>> {
    use sql::prelude::*;

    let mut data = HashMap::new();
    let statement = select_from("static").columns(&["component_id", "leakage_power"]);
    let mut cursor = ok!(backend.prepare(ok!(statement.compile()))).cursor();
    while let Some(row) = ok!(cursor.next()) {
        if let (Some(id), Some(value)) = (row[0].as_integer(), row[1].as_float()) {
            data.insert(id, value);
        } else {
            raise!("failed to read the leakage power");
        }
    }
    Ok(data)
}

#[cfg(test)]
mod tests {
    use assert;
    use sqlite::Connection;

    #[test]
    fn read_names() {
        let backend = open();
        let data = super::read_names(&backend).unwrap();

        assert_eq!(data.len(), 2 + 1);
        assert_eq!(data.get(&0).unwrap(), "core0");
        assert_eq!(data.get(&1).unwrap(), "core1");
        assert_eq!(data.get(&2).unwrap(), "l30");
    }

    #[test]
    fn read_dynamic_power() {
        let backend = open();
        let data = super::read_dynamic_power(&backend).unwrap();

        assert_eq!(data.len(), 2 + 1);
        for (_, data) in &data {
            assert_eq!(data.len(), 69);
        }
        assert::close(&[data.get(&0).unwrap()[2]], &[0.60806580312727], 1e-14);
        assert::close(&[data.get(&1).unwrap()[4]], &[8.68983889250007], 1e-14);
        assert::close(&[data.get(&2).unwrap()[0]], &[0.00620192518435], 1e-14);
    }

    #[test]
    fn read_leakage_power() {
        let backend = open();
        let data = super::read_leakage_power(&backend).unwrap();

        assert_eq!(data.len(), 2 + 1);
        assert_eq!(data.get(&0).unwrap(), data.get(&1).unwrap());
    }

    fn open() -> Connection {
        Connection::open("tests/fixtures/blackscholes.sqlite3").unwrap()
    }
}
<commit_msg>Workload: read areas as well<commit_after>use sqlite::Connection;
use std::collections::HashMap;
use std::rc::Rc;

use platform::{self, ElementKind};

use {Config, Result};

/// A workload pattern.
#[derive(Clone, Debug)]
pub struct Pattern(Rc<Content>);

deref! { Pattern::0 => Content }

/// The content of a workload pattern.
#[derive(Clone, Debug)]
pub struct Content {
    /// The name.
    pub name: String,
    /// The number of processing elements.
    pub units: usize,
    /// The number of time steps.
    pub steps: usize,
    /// The time step (sampling interval).
    pub time_step: f64,
    /// The processing elements.
    pub elements: Vec<Element>,
}

/// A processing element of a workload pattern.
#[derive(Clone, Debug)]
pub struct Element {
    /// The type.
    pub kind: ElementKind,
    /// The area.
    pub area: f64,
    /// The static power.
    pub leakage_power: f64,
    /// The dynamic power.
    pub dynamic_power: Vec<f64>,
}

impl Pattern {
    /// Create a pattern.
    pub fn new(config: &Config) -> Result<Pattern> {
        let path = path!(config, "a workload-pattern database is required");
        let backend = ok!(Connection::open(&path));

        let name = match config.get::<String>("name") {
            Some(name) => name.to_string(),
            _ => path.file_stem().unwrap().to_str().unwrap().to_string(),
        };
        let time_step = *some!(config.get::<f64>("time_step"), "a time step is required");

        info!(target: "Workload", "Reading {:?}...", &path);
        let mut names = try!(read_names(&backend));
        let mut areas = try!(read_static(&backend, "area"));
        let mut leakage_power = try!(read_static(&backend, "leakage_power"));
        let mut dynamic_power = try!(read_dynamic(&backend, "dynamic_power"));

        let mut ids = names.keys().map(|&id| id).collect::<Vec<_>>();
        ids.sort();

        let mut elements = vec![];
        for id in ids {
            elements.push(Element {
                kind: try!(names.remove(&id).unwrap().parse()),
                area: some!(areas.remove(&id), "cannot find the area of a processing element"),
                leakage_power: some!(leakage_power.remove(&id),
                                     "cannot find the leakage power of a processing element"),
                dynamic_power: some!(dynamic_power.remove(&id),
                                     "cannot find the dynamic power of a processing element"),
            });
        }

        let units = elements.len();
        if units == 0 {
            raise!("found a workload pattern without processing elements");
        }

        let steps = elements[0].dynamic_power.len();
        if steps == 0 {
            raise!("found a workload pattern without dynamic-power data");
        }

        Ok(Pattern(Rc::new(Content {
            name: name,
            units: units,
            steps: steps,
            time_step: time_step,
            elements: elements,
        })))
    }

    /// Return the time duration.
    #[inline]
    pub fn duration(&self) -> f64 {
        self.steps as f64 * self.time_step
    }
}

impl Element {
    /// Check if the type matches the type of a processing element of a
    /// platform.
    pub fn accept(&self, element: &platform::Element) -> bool {
        self.kind == element.kind
    }
}

fn read_names(backend: &Connection) -> Result<HashMap<i64, String>> {
    use sql::prelude::*;

    let mut data = HashMap::new();
    let statement = select_from("static").columns(&["component_id", "name"]);
    let mut cursor = ok!(backend.prepare(ok!(statement.compile()))).cursor();
    while let Some(row) = ok!(cursor.next()) {
        if let (Some(id), Some(value)) = (row[0].as_integer(), row[1].as_string()) {
            data.insert(id, value.to_string());
        } else {
            raise!("failed to read the names of processing elements");
        }
    }
    Ok(data)
}

fn read_static(backend: &Connection, name: &str) -> Result<HashMap<i64, f64>> {
    use sql::prelude::*;

    let mut data = HashMap::new();
    let statement = select_from("static").columns(&["component_id", name]);
    let mut cursor = ok!(backend.prepare(ok!(statement.compile()))).cursor();
    while let Some(row) = ok!(cursor.next()) {
        if let (Some(id), Some(value)) = (row[0].as_integer(), row[1].as_float()) {
            data.insert(id, value);
        } else {
            raise!("failed to read the {} column", name);
        }
    }
    Ok(data)
}

fn read_dynamic(backend: &Connection, name: &str) -> Result<HashMap<i64, Vec<f64>>> {
    use sql::prelude::*;

    let mut data = HashMap::new();
    let statement = select_from("dynamic").columns(&["time", "component_id", name])
                                          .order_by(column("time").ascend());
    let mut cursor = ok!(backend.prepare(ok!(statement.compile()))).cursor();
    while let Some(row) = ok!(cursor.next()) {
        if let (Some(id), Some(value)) = (row[1].as_integer(), row[2].as_float()) {
            data.entry(id).or_insert_with(|| vec![]).push(value);
        } else {
            raise!("failed to read the {} column", name);
        }
    }
    Ok(data)
}

#[cfg(test)]
mod tests {
    use assert;
    use sqlite::Connection;

    #[test]
    fn read_names() {
        let backend = open();
        let data = super::read_names(&backend).unwrap();

        assert_eq!(data.len(), 2 + 1);
        assert_eq!(data.get(&0).unwrap(), "core0");
        assert_eq!(data.get(&1).unwrap(), "core1");
        assert_eq!(data.get(&2).unwrap(), "l30");
    }

    #[test]
    fn read_dynamic() {
        let backend = open();
        let data = super::read_dynamic(&backend, "dynamic_power").unwrap();

        assert_eq!(data.len(), 2 + 1);
        for (_, data) in &data {
            assert_eq!(data.len(), 69);
        }
        assert::close(&[data.get(&0).unwrap()[2]], &[0.60806580312727], 1e-14);
        assert::close(&[data.get(&1).unwrap()[4]], &[8.68983889250007], 1e-14);
        assert::close(&[data.get(&2).unwrap()[0]], &[0.00620192518435], 1e-14);
    }

    #[test]
    fn read_static() {
        let backend = open();
        let data = super::read_static(&backend, "leakage_power").unwrap();

        assert_eq!(data.len(), 2 + 1);
        assert_eq!(data.get(&0).unwrap(), data.get(&1).unwrap());
    }

    fn open() -> Connection {
        Connection::open("tests/fixtures/blackscholes.sqlite3").unwrap()
    }
}
<|endoftext|>


<commit_before>use num::Float;
use approx::ApproxEq;

use {Xyz, Yxy, Lab, Lch, Rgb, Hsl, Hsv, Hwb, Luma, LabHue, RgbHue, flt};

macro_rules! impl_eq {
    (  $self_ty: ident , [$($element: ident),+]) => {
        impl<T: Float + ApproxEq> ApproxEq for $self_ty<T>
        where T::Epsilon: Copy + Float
        {
            type Epsilon = <T as ApproxEq>::Epsilon;

            fn default_epsilon() -> Self::Epsilon {
                T::default_epsilon()
            }
            fn default_max_relative() -> Self::Epsilon {
                T::default_max_relative()
            }
            fn default_max_ulps() -> u32 {
                T::default_max_ulps()
            }
            fn relative_eq(&self, other: &Self, epsilon: Self::Epsilon, max_relative: Self::Epsilon) -> bool {
                $( self.$element.relative_eq(&other.$element, epsilon, max_relative) )&&+
            }
            fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool{
                $( self.$element.ulps_eq(&other.$element, epsilon, max_ulps) )&&+
            }

            fn relative_ne(&self, other: &Self, epsilon: Self::Epsilon, max_relative: Self::Epsilon) -> bool {
                $( self.$element.relative_ne(&other.$element, epsilon, max_relative) )&&+
            }
            fn ulps_ne(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
                $( self.$element.ulps_ne(&other.$element, epsilon, max_ulps) )&&+
            }
        }
    }
}

impl_eq!( Xyz, [x, y, z] );
impl_eq!( Yxy, [y, x, luma] );
impl_eq!( Lab, [l, a, b] );
impl_eq!( Rgb, [red, blue, green] );
impl_eq!( Luma, [luma] );
impl_eq!( Lch, [l, chroma, hue] );
impl_eq!( Hsl, [hue, saturation, lightness] );
impl_eq!( Hsv, [hue, saturation, value] );
impl_eq!( Hwb, [hue, whiteness, blackness] );

// For hues diffence is calculated and compared to zero. However due to the way floating point's
// work this is not so simple
// reference
// https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
//
// The recommendation is use 180 * epsilon as the epsilon and do not compare by ulps.
// Because of this we loose some precision for values close to 0.0.
macro_rules! impl_eq_hue {
    (  $self_ty: ident ) => {
        impl<T: Float + ApproxEq> ApproxEq for $self_ty<T>
        where <T as ApproxEq>::Epsilon: Float
        {
            type Epsilon = <T as ApproxEq>::Epsilon;

            fn default_epsilon() -> Self::Epsilon {
                T::default_epsilon() * flt(180.0)
            }
            fn default_max_relative() -> Self::Epsilon {
                T::default_max_relative() * flt(180.0)
            }
            fn default_max_ulps() -> u32 {
                T::default_max_ulps() * 180
            }
            fn relative_eq(&self, other: &Self, epsilon: Self::Epsilon, max_relative: Self::Epsilon) -> bool {
                let diff: T = (*self - *other).to_degrees();
                T::relative_eq(&diff, &T::zero(), epsilon, max_relative)
            }
            fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool{
                let diff: T = (*self - *other).to_degrees();
                T::ulps_eq(&diff, &T::zero(), epsilon, max_ulps)
            }

            fn relative_ne(&self, other: &Self, epsilon: Self::Epsilon, max_relative: Self::Epsilon) -> bool {
                let diff: T = (*self - *other).to_degrees();
                T::relative_ne(&diff, &T::zero(), epsilon, max_relative)
            }
            fn ulps_ne(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
                let diff: T = (*self - *other).to_degrees();
                T::ulps_ne(&diff, &T::zero(), epsilon, max_ulps)
            }
        }

    }
}

impl_eq_hue!( LabHue);
impl_eq_hue!( RgbHue);
<commit_msg>Implement ApproxEq for Srgb and GammaRgb<commit_after>use num::Float;
use approx::ApproxEq;

use {Xyz, Yxy, Lab, Lch, Rgb, Hsl, Hsv, Hwb, Luma, LabHue, RgbHue, flt};
use pixel::{Srgb, GammaRgb};

macro_rules! impl_eq {
    (  $self_ty: ident , [$($element: ident),+]) => {
        impl<T: Float + ApproxEq> ApproxEq for $self_ty<T>
        where T::Epsilon: Copy + Float
        {
            type Epsilon = <T as ApproxEq>::Epsilon;

            fn default_epsilon() -> Self::Epsilon {
                T::default_epsilon()
            }
            fn default_max_relative() -> Self::Epsilon {
                T::default_max_relative()
            }
            fn default_max_ulps() -> u32 {
                T::default_max_ulps()
            }
            fn relative_eq(&self, other: &Self, epsilon: Self::Epsilon, max_relative: Self::Epsilon) -> bool {
                $( self.$element.relative_eq(&other.$element, epsilon, max_relative) )&&+
            }
            fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool{
                $( self.$element.ulps_eq(&other.$element, epsilon, max_ulps) )&&+
            }

            fn relative_ne(&self, other: &Self, epsilon: Self::Epsilon, max_relative: Self::Epsilon) -> bool {
                $( self.$element.relative_ne(&other.$element, epsilon, max_relative) )&&+
            }
            fn ulps_ne(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
                $( self.$element.ulps_ne(&other.$element, epsilon, max_ulps) )&&+
            }
        }
    }
}

impl_eq!( Xyz, [x, y, z] );
impl_eq!( Yxy, [y, x, luma] );
impl_eq!( Lab, [l, a, b] );
impl_eq!( Rgb, [red, blue, green] );
impl_eq!( Luma, [luma] );
impl_eq!( Lch, [l, chroma, hue] );
impl_eq!( Hsl, [hue, saturation, lightness] );
impl_eq!( Hsv, [hue, saturation, value] );
impl_eq!( Hwb, [hue, whiteness, blackness] );
impl_eq!( Srgb, [red, blue, green, alpha] );
impl_eq!( GammaRgb, [red, blue, green, alpha, gamma] );

// For hues diffence is calculated and compared to zero. However due to the way floating point's
// work this is not so simple
// reference
// https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
//
// The recommendation is use 180 * epsilon as the epsilon and do not compare by ulps.
// Because of this we loose some precision for values close to 0.0.
macro_rules! impl_eq_hue {
    (  $self_ty: ident ) => {
        impl<T: Float + ApproxEq> ApproxEq for $self_ty<T>
        where <T as ApproxEq>::Epsilon: Float
        {
            type Epsilon = <T as ApproxEq>::Epsilon;

            fn default_epsilon() -> Self::Epsilon {
                T::default_epsilon() * flt(180.0)
            }
            fn default_max_relative() -> Self::Epsilon {
                T::default_max_relative() * flt(180.0)
            }
            fn default_max_ulps() -> u32 {
                T::default_max_ulps() * 180
            }
            fn relative_eq(&self, other: &Self, epsilon: Self::Epsilon, max_relative: Self::Epsilon) -> bool {
                let diff: T = (*self - *other).to_degrees();
                T::relative_eq(&diff, &T::zero(), epsilon, max_relative)
            }
            fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool{
                let diff: T = (*self - *other).to_degrees();
                T::ulps_eq(&diff, &T::zero(), epsilon, max_ulps)
            }

            fn relative_ne(&self, other: &Self, epsilon: Self::Epsilon, max_relative: Self::Epsilon) -> bool {
                let diff: T = (*self - *other).to_degrees();
                T::relative_ne(&diff, &T::zero(), epsilon, max_relative)
            }
            fn ulps_ne(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
                let diff: T = (*self - *other).to_degrees();
                T::ulps_ne(&diff, &T::zero(), epsilon, max_ulps)
            }
        }

    }
}

impl_eq_hue!( LabHue);
impl_eq_hue!( RgbHue);
<|endoftext|>


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

use std::result;
use std::ffi::OsStr;
use std::path::Path;
use libc;

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

use super::fusefl::*;
use fuse_mt::*;

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

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

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

pub enum NoFile {}

#[allow(unused_variables)]
impl ReadFileLike for NoFile {
    fn read_at(&self, buf: &mut [u8], offset: u64) -> Result<usize> {
        Err(libc::ENOSYS)
    }
}

#[allow(unused_variables)]
impl WriteFileLike for NoFile {
    fn write_at(&self, buf: &[u8], offset: u64) -> Result<usize> {
        Err(libc::ENOSYS)
    }

    fn flush(&self) -> Result<()> {
        Err(libc::ENOSYS)
    }
}

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

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

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

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

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

use self::ModalFileLike::*;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

use std::result;
use std::ffi::OsStr;
use std::path::Path;
use libc;

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

use super::fusefl::*;
use fuse_mt::*;

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

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

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

pub enum NoFile {}

#[allow(unused_variables)]
impl ReadFileLike for NoFile {
    fn read_at(&self, buf: &mut [u8], offset: u64) -> Result<usize> {
        Err(libc::ENOSYS)
    }
}

#[allow(unused_variables)]
impl WriteFileLike for NoFile {
    fn write_at(&self, buf: &[u8], offset: u64) -> Result<usize> {
        Err(libc::ENOSYS)
    }

    fn flush(&self) -> Result<()> {
        Err(libc::ENOSYS)
    }
}

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

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

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

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

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

use self::ModalFileLike::*;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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