<commit_before>use cocoa::base::{id, nil};
use cocoa::foundation::{NSInteger, NSUInteger};
use core_foundation::base::CFRange;
use objc::runtime::YES;
use std::mem;
use std::ops::{Deref, Range};
use sys::{MTLTexture, MTLTextureType, MTLTextureUsage};
use {FromRaw, FromRawError, PixelFormat, Region, Resource, Size};
#[cfg(target_os = "ios")]
use Buffer;

pub struct Texture(id);

impl Texture {
    pub fn with_pixel_format(format: PixelFormat) -> Result<Self, FromRawError> {
        let raw_tex = unsafe { MTLTexture::newTextureViewWithPixelFormat(nil, format.into()) };
        Self::from_raw(raw_tex)
    }

    pub fn new(format: PixelFormat, tex_type: TextureType, levels: Range<isize>, slices: usize)
               -> Result<Self, FromRawError> {
        let cf_levels = CFRange::init(levels.start as NSInteger,
                                      (levels.end - levels.start) as NSInteger);
        let raw_tex = unsafe {
            MTLTexture::newTextureViewWithPixelFormat_textureType_levels_slices(
                nil, format.into(), tex_type.into(), cf_levels,
                slices as NSUInteger)
        };
        Self::from_raw(raw_tex)
    }

    pub fn replace_region_at_slice(&mut self, region: Region, slice: usize, mipmap_level: usize,
                                   bytes: &AsRef<[u8]>, bytes_per_row: usize,
                                   bytes_per_image: usize) {
        unsafe {
            self.0.replaceRegion_mipmapLevel_slice_withBytes_bytesPerRow_bytesPerImage(
                region.into(), mipmap_level as NSUInteger, slice as NSUInteger,
                bytes.as_ref().as_ptr() as *const _, bytes_per_row as NSUInteger,
                bytes_per_image as NSUInteger);
        }
    }

    pub fn replace_region(&mut self, mipmap_level: usize, region: Region, bytes: &AsRef<[u8]>,
                          bytes_per_row: usize) {
        let bytes = bytes.as_ref();
        if bytes.len() % bytes_per_row != 0 {
            return;
        }
        unsafe {
            self.0.replaceRegion_mipmapLevel_withBytes_bytesPerRow(region.into(),
                                                                   mipmap_level as NSUInteger,
                                                                   bytes.as_ptr() as *const _,
                                                                   bytes_per_row as NSUInteger);
        }
    }

    // TODO(George): Investigate non-allocating APIs, and add predicates in rust code so that
    // panics can be generated
    pub fn get_bytes_at_slice(&self, bytes_storage: &mut Vec<u8>, bytes_per_row: usize,
                              bytes_per_image: usize, region: Region, mipmap_level: usize,
                              slice: usize) {
        bytes_storage.resize(self.width() * self.height() * self.depth(), 0u8);
        unsafe {
            self.0.getBytes_bytesPerRow_bytesPerImage_fromRegion_mipmapLevel_slice(
                bytes_storage.as_mut_ptr() as *mut _, bytes_per_row as NSUInteger,
                bytes_per_image as NSUInteger, region.into(), mipmap_level as NSUInteger,
                slice as NSUInteger);
        }
        bytes_storage.shrink_to_fit();
    }

    pub fn get_bytes(&self, bytes_storage: &mut Vec<u8>, bytes_per_row: usize, region: Region,
                     mipmap_level: usize) {
        bytes_storage.resize(self.width() * self.height() * self.depth(), 0u8);
        unsafe {
            self.0
                .getBytes_bytesPerRow_fromRegion_mipmapLevel(bytes_storage.as_mut_ptr() as *mut _,
                                                             bytes_per_row as NSUInteger,
                                                             region.into(),
                                                             mipmap_level as NSUInteger);
        }
        bytes_storage.shrink_to_fit();
    }

    pub fn texture_type(&self) -> TextureType {
        unsafe { self.0.textureType().into() }
    }

    pub fn pixel_format(&self) -> PixelFormat {
        unsafe { self.0.pixelFormat().into() }
    }

    pub fn width(&self) -> usize {
        unsafe { self.0.width() as usize }
    }

    pub fn height(&self) -> usize {
        unsafe { self.0.height() as usize }
    }

    pub fn depth(&self) -> usize {
        unsafe { self.0.depth() as usize }
    }

    pub fn size(&self) -> Size {
        Size::new(self.width(), self.height(), self.depth())
    }

    pub fn mipmap_level_count(&self) -> usize {
        unsafe { self.0.mipmapLevelCount() as usize }
    }

    pub fn array_length(&self) -> usize {
        unsafe { self.0.arrayLength() as usize }
    }

    pub fn sample_count(&self) -> usize {
        unsafe { self.0.sampleCount() as usize }
    }

    pub fn is_frame_buffer_only(&self) -> bool {
        unsafe { self.0.frameBufferOnly() == YES }
    }

    pub fn root_resource(&self) -> Option<Resource> {
        unsafe { FromRaw::from_raw(self.0.rootResource()).ok() }
    }

    pub fn usage(&self) -> TextureUsage {
        unsafe { self.0.usage().into() }
    }

    pub fn parent_texture(&self) -> Option<Self> {
        unsafe { Self::from_raw(self.0.parentTexture()).ok() }
    }

    pub fn parent_relative_level(&self) -> usize {
        unsafe { self.0.parentRelativeLevel() as usize }
    }

    pub fn parent_relative_slice(&self) -> usize {
        unsafe { self.0.parentRelativeSlice() as usize }
    }
}

#[cfg(target_os = "macos")]
impl Texture {}

#[cfg(target_os = "ios")]
impl Texture {
    pub fn buffer(&self) -> Option<Buffer> {
        unsafe { FromRaw::from_raw(MTLTexture::buffer(self.0)).ok() }
    }

    pub fn buffer_offset(&self) -> usize {
        unsafe { self.0.bufferOffset() as usize }
    }

    pub fn buffer_bytes_per_row(&self) -> usize {
        unsafe { self.0.bufferBytesPerRow() as usize }
    }
}

impl Deref for Texture {
    type Target = Resource;
    fn deref(&self) -> &Self::Target {
        unsafe { mem::transmute(self) }
    }
}

impl_from_into_raw!(Texture, of protocol "MTLTexture");

pub struct TextureDescriptor(id);

impl_from_into_raw!(TextureDescriptor, of class "MTLTextureDescriptor");

convertible_enum! {
    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
    pub enum TextureType: MTLTextureType {
        Type1D => MTLTextureType1D,
        Type1DArray => MTLTextureType1DArray,
        Type2D => MTLTextureType2D,
        Type2DArray => MTLTextureType2DArray,
        Type2DMultisample => MTLTextureType2DMultisample,
        TypeCube => MTLTextureTypeCube,
        Type3D => MTLTextureType3D
    }
}

convertible_enum! {
    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
    pub enum TextureUsage: MTLTextureUsage {
        Unknown => MTLTextureUsageUnknown,
        ShaderRead => MTLTextureUsageShaderRead,
        ShaderWrite => MTLTextureUsageShaderWrite,
        RenderTarget => MTLTextureUsageRenderTarget,
        PixelFormatView => MTLTextureUsagePixelFormatView
    }
}
<commit_msg>Add full implementation of TextureDescriptor<commit_after>use cocoa::base::{id, nil};
use cocoa::foundation::{NSInteger, NSUInteger};
use core_foundation::base::CFRange;
use objc::runtime::{BOOL, YES};
use std::mem;
use std::ops::{Deref, Range};
use sys::{MTLTexture, MTLTextureDescriptor, MTLTextureType, MTLTextureUsage};
use {CpuCacheMode, FromRaw, FromRawError, PixelFormat, Region, Resource, ResourceOptions, Size,
     StorageMode};
#[cfg(target_os = "ios")]
use Buffer;

pub struct Texture(id);

impl Texture {
    pub fn with_pixel_format(format: PixelFormat) -> Result<Self, FromRawError> {
        let raw_tex = unsafe { MTLTexture::newTextureViewWithPixelFormat(nil, format.into()) };
        Self::from_raw(raw_tex)
    }

    pub fn new(format: PixelFormat, tex_type: TextureType, levels: Range<isize>, slices: usize)
               -> Result<Self, FromRawError> {
        let cf_levels = CFRange::init(levels.start as NSInteger,
                                      (levels.end - levels.start) as NSInteger);
        let raw_tex = unsafe {
            MTLTexture::newTextureViewWithPixelFormat_textureType_levels_slices(
                nil, format.into(), tex_type.into(), cf_levels,
                slices as NSUInteger)
        };
        Self::from_raw(raw_tex)
    }

    pub fn replace_region_at_slice(&mut self, region: Region, slice: usize, mipmap_level: usize,
                                   bytes: &AsRef<[u8]>, bytes_per_row: usize,
                                   bytes_per_image: usize) {
        unsafe {
            self.0.replaceRegion_mipmapLevel_slice_withBytes_bytesPerRow_bytesPerImage(
                region.into(), mipmap_level as NSUInteger, slice as NSUInteger,
                bytes.as_ref().as_ptr() as *const _, bytes_per_row as NSUInteger,
                bytes_per_image as NSUInteger);
        }
    }

    pub fn replace_region(&mut self, mipmap_level: usize, region: Region, bytes: &AsRef<[u8]>,
                          bytes_per_row: usize) {
        let bytes = bytes.as_ref();
        if bytes.len() % bytes_per_row != 0 {
            return;
        }
        unsafe {
            self.0.replaceRegion_mipmapLevel_withBytes_bytesPerRow(region.into(),
                                                                   mipmap_level as NSUInteger,
                                                                   bytes.as_ptr() as *const _,
                                                                   bytes_per_row as NSUInteger);
        }
    }

    // TODO(George): Investigate non-allocating APIs, and add predicates in rust code so that
    // panics can be generated
    pub fn get_bytes_at_slice(&self, bytes_storage: &mut Vec<u8>, bytes_per_row: usize,
                              bytes_per_image: usize, region: Region, mipmap_level: usize,
                              slice: usize) {
        bytes_storage.resize(self.width() * self.height() * self.depth(), 0u8);
        unsafe {
            self.0.getBytes_bytesPerRow_bytesPerImage_fromRegion_mipmapLevel_slice(
                bytes_storage.as_mut_ptr() as *mut _, bytes_per_row as NSUInteger,
                bytes_per_image as NSUInteger, region.into(), mipmap_level as NSUInteger,
                slice as NSUInteger);
        }
        bytes_storage.shrink_to_fit();
    }

    pub fn get_bytes(&self, bytes_storage: &mut Vec<u8>, bytes_per_row: usize, region: Region,
                     mipmap_level: usize) {
        bytes_storage.resize(self.width() * self.height() * self.depth(), 0u8);
        unsafe {
            self.0
                .getBytes_bytesPerRow_fromRegion_mipmapLevel(bytes_storage.as_mut_ptr() as *mut _,
                                                             bytes_per_row as NSUInteger,
                                                             region.into(),
                                                             mipmap_level as NSUInteger);
        }
        bytes_storage.shrink_to_fit();
    }

    pub fn texture_type(&self) -> TextureType {
        unsafe { MTLTexture::textureType(self.0).into() }
    }

    pub fn pixel_format(&self) -> PixelFormat {
        unsafe { MTLTexture::pixelFormat(self.0).into() }
    }

    pub fn width(&self) -> usize {
        unsafe { MTLTexture::width(self.0) as usize }
    }

    pub fn height(&self) -> usize {
        unsafe { MTLTexture::height(self.0) as usize }
    }

    pub fn depth(&self) -> usize {
        unsafe { MTLTexture::depth(self.0) as usize }
    }

    pub fn size(&self) -> Size {
        Size::new(self.width(), self.height(), self.depth())
    }

    pub fn mipmap_level_count(&self) -> usize {
        unsafe { MTLTexture::mipmapLevelCount(self.0) as usize }
    }

    pub fn array_length(&self) -> usize {
        unsafe { MTLTexture::arrayLength(self.0) as usize }
    }

    pub fn sample_count(&self) -> usize {
        unsafe { MTLTexture::sampleCount(self.0) as usize }
    }

    pub fn is_frame_buffer_only(&self) -> bool {
        unsafe { self.0.frameBufferOnly() == YES }
    }

    pub fn root_resource(&self) -> Option<Resource> {
        unsafe { FromRaw::from_raw(self.0.rootResource()).ok() }
    }

    pub fn usage(&self) -> TextureUsage {
        unsafe { MTLTexture::usage(self.0).into() }
    }

    pub fn parent_texture(&self) -> Option<Self> {
        unsafe { Self::from_raw(self.0.parentTexture()).ok() }
    }

    pub fn parent_relative_level(&self) -> usize {
        unsafe { self.0.parentRelativeLevel() as usize }
    }

    pub fn parent_relative_slice(&self) -> usize {
        unsafe { self.0.parentRelativeSlice() as usize }
    }
}

#[cfg(target_os = "macos")]
impl Texture {}

#[cfg(target_os = "ios")]
impl Texture {
    pub fn buffer(&self) -> Option<Buffer> {
        unsafe { FromRaw::from_raw(MTLTexture::buffer(self.0)).ok() }
    }

    pub fn buffer_offset(&self) -> usize {
        unsafe { self.0.bufferOffset() as usize }
    }

    pub fn buffer_bytes_per_row(&self) -> usize {
        unsafe { self.0.bufferBytesPerRow() as usize }
    }
}

impl Deref for Texture {
    type Target = Resource;
    fn deref(&self) -> &Self::Target {
        unsafe { mem::transmute(self) }
    }
}

impl_from_into_raw!(Texture, of protocol "MTLTexture");

pub struct TextureDescriptor(id);

impl TextureDescriptor {
    pub fn new() -> Self {
        unsafe { FromRaw::from_raw(MTLTextureDescriptor::new(nil)).unwrap() }
    }

    pub fn new_2d(pixel_format: PixelFormat, width: usize, height: usize, mipmapped: bool) -> Self {
        let raw = unsafe {
            MTLTextureDescriptor::texture2DDescriptorWithPixelFormat_width_height_mipmapped(
                nil, pixel_format.into(), width as NSUInteger, height as NSUInteger,
                mipmapped as BOOL)
        };
        FromRaw::from_raw(raw).unwrap()
    }

    pub fn new_cube(pixel_format: PixelFormat, size: usize, mipmapped: bool) -> Self {
        let raw = unsafe {
            MTLTextureDescriptor::textureCubeDescriptorWithPixelFormat_size_mipmapped(
                nil, pixel_format.into(), size as NSUInteger, mipmapped as BOOL)
        };
        FromRaw::from_raw(raw).unwrap()
    }

    pub fn texture_type(&self) -> TextureType {
        unsafe { MTLTextureDescriptor::textureType(self.0).into() }
    }

    pub fn set_texture_type(&mut self, texture_type: TextureType) {
        unsafe { self.0.setTextureType(texture_type.into()) }
    }

    pub fn pixel_format(&self) -> PixelFormat {
        unsafe { MTLTextureDescriptor::pixelFormat(self.0).into() }
    }

    pub fn set_pixel_format(&mut self, pixel_format: PixelFormat) {
        unsafe { self.0.setPixelFormat(pixel_format.into()) }
    }

    pub fn width(&self) -> usize {
        unsafe { MTLTextureDescriptor::width(self.0) as usize }
    }

    pub fn set_width(&mut self, width: usize) {
        unsafe { self.0.setWidth(width as NSUInteger) }
    }

    pub fn height(&self) -> usize {
        unsafe { MTLTextureDescriptor::height(self.0) as usize }
    }

    pub fn set_height(&mut self, height: usize) {
        unsafe { self.0.setHeight(height as NSUInteger) }
    }

    pub fn depth(&self) -> usize {
        unsafe { MTLTextureDescriptor::depth(self.0) as usize }
    }

    pub fn set_depth(&mut self, depth: usize) {
        unsafe { self.0.setDepth(depth as NSUInteger) }
    }

    pub fn size(&self) -> Size {
        Size::new(self.width(), self.height(), self.depth())
    }

    pub fn set_size(&mut self, Size {width, height, depth}: Size) {
        self.set_width(width);
        self.set_height(height);
        self.set_depth(depth);
    }

    pub fn mipmap_level_count(&self) -> usize {
        unsafe { MTLTextureDescriptor::mipmapLevelCount(self.0) as usize }
    }

    pub fn set_mipmap_level_count(&mut self, mipmap_level_count: usize) {
        unsafe { self.0.setMipmapLevelCount(mipmap_level_count as NSUInteger) }
    }

    pub fn sample_count(&self) -> usize {
        unsafe { MTLTextureDescriptor::sampleCount(self.0) as usize }
    }

    pub fn set_sample_count(&mut self, sample_count: usize) {
        unsafe { self.0.setSampleCount(sample_count as NSUInteger) }
    }

    pub fn array_length(&self) -> usize {
        unsafe { MTLTextureDescriptor::arrayLength(self.0) as usize }
    }

    pub fn set_array_length(&mut self, array_length: usize) {
        unsafe { self.0.setArrayLength(array_length as NSUInteger) }
    }

    pub fn resource_options(&self) -> ResourceOptions {
        unsafe { self.0.resourceOptions().into() }
    }

    pub fn set_resource_options(&mut self, options: ResourceOptions) {
        unsafe { self.0.setResourceOptions(options.into()) }
    }

    pub fn cpu_cache_mode(&self) -> CpuCacheMode {
        unsafe { self.0.cpuCacheMode().into() }
    }

    pub fn set_cpu_cache_mode(&mut self, cache_mode: CpuCacheMode) {
        unsafe { self.0.setCpuCacheMode(cache_mode.into()) }
    }

    pub fn storage_mode(&self) -> StorageMode {
        unsafe { self.0.storageMode().into() }
    }

    pub fn set_storage_mode(&mut self, storage_mode: StorageMode) {
        unsafe { self.0.setStorageMode(storage_mode.into()) }
    }

    pub fn usage(&self) -> TextureUsage {
        unsafe { MTLTextureDescriptor::usage(self.0).into() }
    }

    pub fn set_usage(&mut self, usage: TextureUsage) {
        unsafe { self.0.setUsage(usage.into()) }
    }
}

impl Clone for TextureDescriptor {
    fn clone(&self) -> Self {
        unsafe { FromRaw::from_raw(self.0.copy()).unwrap() }
    }
}

impl_from_into_raw!(TextureDescriptor, of class "MTLTextureDescriptor");

convertible_enum! {
    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
    pub enum TextureType: MTLTextureType {
        Type1D => MTLTextureType1D,
        Type1DArray => MTLTextureType1DArray,
        Type2D => MTLTextureType2D,
        Type2DArray => MTLTextureType2DArray,
        Type2DMultisample => MTLTextureType2DMultisample,
        TypeCube => MTLTextureTypeCube,
        Type3D => MTLTextureType3D
    }
}

convertible_enum! {
    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
    pub enum TextureUsage: MTLTextureUsage {
        Unknown => MTLTextureUsageUnknown,
        ShaderRead => MTLTextureUsageShaderRead,
        ShaderWrite => MTLTextureUsageShaderWrite,
        RenderTarget => MTLTextureUsageRenderTarget,
        PixelFormatView => MTLTextureUsagePixelFormatView
    }
}
<|endoftext|>


<commit_before>/// An interface to timerfd in linux
///
/// This interface is specific to the use of Amy and not general enough to be in its own crate.

use std::ptr;
use std::mem;
use std::os::unix::io::{IntoRawFd, RawFd};
use nix::{Error, Result};
use nix::errno::Errno;
use libc::{self, c_int, CLOCK_MONOTONIC, O_NONBLOCK, O_CLOEXEC, timespec};

static TFD_NONBLOCK: c_int = O_NONBLOCK;
static TFD_CLOEXEC: c_int = O_CLOEXEC;

mod ffi {
    use libc::{c_int, timespec};

    #[repr(C)]
    pub struct Itimerspec {
        pub it_interval: timespec,
        pub it_value: timespec
    }

    extern {
        pub fn timerfd_create(clockid: c_int, flags: c_int) -> c_int;
        pub fn timerfd_settime(fd: c_int,
                               flags: c_int,
                               new: *const Itimerspec,
                               old: *mut Itimerspec) -> c_int;
    }
}

pub struct TimerFd {
    fd: c_int
}

impl TimerFd {
    pub fn new(timeout_in_ms: usize, recurring: bool) -> Result<TimerFd> {
        let fd = unsafe { ffi::timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC) };
        if fd < 0 {
            return Err(Error::Sys(Errno::last()));
        }
        let timer_fd = TimerFd {fd: fd};
        try!(arm_timer(fd, timeout_in_ms, recurring));

        Ok(timer_fd)
    }

}

impl Drop for TimerFd {
    fn drop(&mut self) {
        unsafe {
            libc::close(self.fd);
        }
    }
}

impl IntoRawFd for TimerFd {
    fn into_raw_fd(self) -> RawFd {
        let fd = self.fd;
        // Don't run drop on self when it goes out of scope because the purpose of this function is
        // to take ownership of the fd
        mem::forget(self);
        fd
    }
}

fn arm_timer(fd: c_int, timeout: usize, recurring: bool) -> Result<()> {
    let it_value = ms_to_timespec(timeout as i64);
    let it_interval = if recurring {
        it_value.clone()
    } else {
        timespec {
            tv_sec: 0,
            tv_nsec: 0
        }
    };
    let itimerspec = ffi::Itimerspec {
        it_interval: it_interval,
        it_value: it_value
    };

    let res = unsafe { ffi::timerfd_settime(fd, 0, &itimerspec, ptr::null_mut()) };
    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    Ok(())
}

fn ms_to_timespec(timeout_in_ms: i64) -> timespec {
    timespec {
        tv_sec: timeout_in_ms / 1000,
        tv_nsec: (timeout_in_ms % 1000) * 1000 * 1000
    }
}
<commit_msg>Cast timeout to time_t instead of i64 in timerfd<commit_after>/// An interface to timerfd in linux
///
/// This interface is specific to the use of Amy and not general enough to be in its own crate.

use std::ptr;
use std::mem;
use std::os::unix::io::{IntoRawFd, RawFd};
use nix::{Error, Result};
use nix::errno::Errno;
use libc::{self, c_int, CLOCK_MONOTONIC, O_NONBLOCK, O_CLOEXEC, timespec, time_t};

static TFD_NONBLOCK: c_int = O_NONBLOCK;
static TFD_CLOEXEC: c_int = O_CLOEXEC;

mod ffi {
    use libc::{c_int, timespec};

    #[repr(C)]
    pub struct Itimerspec {
        pub it_interval: timespec,
        pub it_value: timespec
    }

    extern {
        pub fn timerfd_create(clockid: c_int, flags: c_int) -> c_int;
        pub fn timerfd_settime(fd: c_int,
                               flags: c_int,
                               new: *const Itimerspec,
                               old: *mut Itimerspec) -> c_int;
    }
}

pub struct TimerFd {
    fd: c_int
}

impl TimerFd {
    pub fn new(timeout_in_ms: usize, recurring: bool) -> Result<TimerFd> {
        let fd = unsafe { ffi::timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC) };
        if fd < 0 {
            return Err(Error::Sys(Errno::last()));
        }
        let timer_fd = TimerFd {fd: fd};
        try!(arm_timer(fd, timeout_in_ms, recurring));

        Ok(timer_fd)
    }

}

impl Drop for TimerFd {
    fn drop(&mut self) {
        unsafe {
            libc::close(self.fd);
        }
    }
}

impl IntoRawFd for TimerFd {
    fn into_raw_fd(self) -> RawFd {
        let fd = self.fd;
        // Don't run drop on self when it goes out of scope because the purpose of this function is
        // to take ownership of the fd
        mem::forget(self);
        fd
    }
}

fn arm_timer(fd: c_int, timeout: usize, recurring: bool) -> Result<()> {
    let it_value = ms_to_timespec(timeout as time_t);
    let it_interval = if recurring {
        it_value.clone()
    } else {
        timespec {
            tv_sec: 0,
            tv_nsec: 0
        }
    };
    let itimerspec = ffi::Itimerspec {
        it_interval: it_interval,
        it_value: it_value
    };

    let res = unsafe { ffi::timerfd_settime(fd, 0, &itimerspec, ptr::null_mut()) };
    if res < 0 {
        return Err(Error::Sys(Errno::last()));
    }

    Ok(())
}

fn ms_to_timespec(timeout_in_ms: time_t) -> timespec {
    timespec {
        tv_sec: timeout_in_ms / 1000,
        tv_nsec: (timeout_in_ms % 1000) * 1000 * 1000
    }
}
<|endoftext|>


<commit_before>#[doc(hidden)]
pub const NRBITS: u32 = 8;
#[doc(hidden)]
pub const TYPEBITS: u32 = 8;

#[cfg(any(target_arch = "mips", target_arch = "mips64", target_arch = "powerpc", target_arch = "powerpc64"))]
mod consts {
    #[doc(hidden)]
    pub const NONE: u8 = 1;
    #[doc(hidden)]
    pub const READ: u8 = 2;
    #[doc(hidden)]
    pub const WRITE: u8 = 4;
    #[doc(hidden)]
    pub const SIZEBITS: u8 = 13;
    #[doc(hidden)]
    pub const DIRBITS: u8 = 3;
}

#[cfg(not(any(target_arch = "powerpc",
              target_arch = "mips",
              target_arch = "mips64",
              target_arch = "x86",
              target_arch = "arm",
              target_arch = "x86_64",
              target_arch = "powerpc64",
              target_arch = "s390x",
              target_arch = "aarch64")))]
use this_arch_not_supported;

// "Generic" ioctl protocol
#[cfg(any(target_arch = "x86",
          target_arch = "arm",
          target_arch = "s390x",
          target_arch = "x86_64",
          target_arch = "aarch64"))]
mod consts {
    #[doc(hidden)]
    pub const NONE: u8 = 0;
    #[doc(hidden)]
    pub const READ: u8 = 2;
    #[doc(hidden)]
    pub const WRITE: u8 = 1;
    #[doc(hidden)]
    pub const SIZEBITS: u8 = 14;
    #[doc(hidden)]
    pub const DIRBITS: u8 = 2;
}

pub use self::consts::*;

#[doc(hidden)]
pub const NRSHIFT: u32 = 0;
#[doc(hidden)]
pub const TYPESHIFT: u32 = NRSHIFT + NRBITS as u32;
#[doc(hidden)]
pub const SIZESHIFT: u32 = TYPESHIFT + TYPEBITS as u32;
#[doc(hidden)]
pub const DIRSHIFT: u32 = SIZESHIFT + SIZEBITS as u32;

#[doc(hidden)]
pub const NRMASK: u32 = (1 << NRBITS) - 1;
#[doc(hidden)]
pub const TYPEMASK: u32 = (1 << TYPEBITS) - 1;
#[doc(hidden)]
pub const SIZEMASK: u32 = (1 << SIZEBITS) - 1;
#[doc(hidden)]
pub const DIRMASK: u32 = (1 << DIRBITS) - 1;

/// Encode an ioctl command.
#[macro_export]
#[doc(hidden)]
macro_rules! ioc {
    ($dir:expr, $ty:expr, $nr:expr, $sz:expr) => (
        (($dir as u32) << $crate::sys::ioctl::DIRSHIFT) |
        (($ty as u32) << $crate::sys::ioctl::TYPESHIFT) |
        (($nr as u32) << $crate::sys::ioctl::NRSHIFT) |
        (($sz as u32) << $crate::sys::ioctl::SIZESHIFT))
}

/// Encode an ioctl command that has no associated data.
#[macro_export]
#[doc(hidden)]
macro_rules! io {
    ($ty:expr, $nr:expr) => (ioc!($crate::sys::ioctl::NONE, $ty, $nr, 0))
}

/// Encode an ioctl command that reads.
#[macro_export]
#[doc(hidden)]
macro_rules! ior {
    ($ty:expr, $nr:expr, $sz:expr) => (ioc!($crate::sys::ioctl::READ, $ty, $nr, $sz))
}

/// Encode an ioctl command that writes.
#[macro_export]
#[doc(hidden)]
macro_rules! iow {
    ($ty:expr, $nr:expr, $sz:expr) => (ioc!($crate::sys::ioctl::WRITE, $ty, $nr, $sz))
}

/// Encode an ioctl command that both reads and writes.
#[macro_export]
#[doc(hidden)]
macro_rules! iorw {
    ($ty:expr, $nr:expr, $sz:expr) => (ioc!($crate::sys::ioctl::READ | $crate::sys::ioctl::WRITE, $ty, $nr, $sz))
}

/// Extracts the "direction" (read/write/none) from an encoded ioctl command.
#[inline(always)]
#[doc(hidden)]
pub fn ioc_dir(nr: u32) -> u8 {
    ((nr >> DIRSHIFT) & DIRMASK) as u8
}

/// Extracts the type from an encoded ioctl command.
#[inline(always)]
#[doc(hidden)]
pub fn ioc_type(nr: u32) -> u32 {
    (nr >> TYPESHIFT) & TYPEMASK
}

/// Extracts the ioctl number from an encoded ioctl command.
#[inline(always)]
#[doc(hidden)]
pub fn ioc_nr(nr: u32) -> u32 {
    (nr >> NRSHIFT) & NRMASK
}

/// Extracts the size from an encoded ioctl command.
#[inline(always)]
#[doc(hidden)]
pub fn ioc_size(nr: u32) -> u32 {
    ((nr >> SIZESHIFT) as u32) & SIZEMASK
}

#[doc(hidden)]
pub const IN: u32 = (WRITE as u32) << DIRSHIFT;
#[doc(hidden)]
pub const OUT: u32 = (READ as u32) << DIRSHIFT;
#[doc(hidden)]
pub const INOUT: u32 = ((READ|WRITE) as u32) << DIRSHIFT;
#[doc(hidden)]
pub const SIZE_MASK: u32 = SIZEMASK << SIZESHIFT;
<commit_msg>Remove ioc_* functions<commit_after>#[doc(hidden)]
pub const NRBITS: u32 = 8;
#[doc(hidden)]
pub const TYPEBITS: u32 = 8;

#[cfg(any(target_arch = "mips", target_arch = "mips64", target_arch = "powerpc", target_arch = "powerpc64"))]
mod consts {
    #[doc(hidden)]
    pub const NONE: u8 = 1;
    #[doc(hidden)]
    pub const READ: u8 = 2;
    #[doc(hidden)]
    pub const WRITE: u8 = 4;
    #[doc(hidden)]
    pub const SIZEBITS: u8 = 13;
    #[doc(hidden)]
    pub const DIRBITS: u8 = 3;
}

#[cfg(not(any(target_arch = "powerpc",
              target_arch = "mips",
              target_arch = "mips64",
              target_arch = "x86",
              target_arch = "arm",
              target_arch = "x86_64",
              target_arch = "powerpc64",
              target_arch = "s390x",
              target_arch = "aarch64")))]
use this_arch_not_supported;

// "Generic" ioctl protocol
#[cfg(any(target_arch = "x86",
          target_arch = "arm",
          target_arch = "s390x",
          target_arch = "x86_64",
          target_arch = "aarch64"))]
mod consts {
    #[doc(hidden)]
    pub const NONE: u8 = 0;
    #[doc(hidden)]
    pub const READ: u8 = 2;
    #[doc(hidden)]
    pub const WRITE: u8 = 1;
    #[doc(hidden)]
    pub const SIZEBITS: u8 = 14;
    #[doc(hidden)]
    pub const DIRBITS: u8 = 2;
}

pub use self::consts::*;

#[doc(hidden)]
pub const NRSHIFT: u32 = 0;
#[doc(hidden)]
pub const TYPESHIFT: u32 = NRSHIFT + NRBITS as u32;
#[doc(hidden)]
pub const SIZESHIFT: u32 = TYPESHIFT + TYPEBITS as u32;
#[doc(hidden)]
pub const DIRSHIFT: u32 = SIZESHIFT + SIZEBITS as u32;

#[doc(hidden)]
pub const NRMASK: u32 = (1 << NRBITS) - 1;
#[doc(hidden)]
pub const TYPEMASK: u32 = (1 << TYPEBITS) - 1;
#[doc(hidden)]
pub const SIZEMASK: u32 = (1 << SIZEBITS) - 1;
#[doc(hidden)]
pub const DIRMASK: u32 = (1 << DIRBITS) - 1;

/// Encode an ioctl command.
#[macro_export]
#[doc(hidden)]
macro_rules! ioc {
    ($dir:expr, $ty:expr, $nr:expr, $sz:expr) => (
        (($dir as u32) << $crate::sys::ioctl::DIRSHIFT) |
        (($ty as u32) << $crate::sys::ioctl::TYPESHIFT) |
        (($nr as u32) << $crate::sys::ioctl::NRSHIFT) |
        (($sz as u32) << $crate::sys::ioctl::SIZESHIFT))
}

/// Encode an ioctl command that has no associated data.
#[macro_export]
#[doc(hidden)]
macro_rules! io {
    ($ty:expr, $nr:expr) => (ioc!($crate::sys::ioctl::NONE, $ty, $nr, 0))
}

/// Encode an ioctl command that reads.
#[macro_export]
#[doc(hidden)]
macro_rules! ior {
    ($ty:expr, $nr:expr, $sz:expr) => (ioc!($crate::sys::ioctl::READ, $ty, $nr, $sz))
}

/// Encode an ioctl command that writes.
#[macro_export]
#[doc(hidden)]
macro_rules! iow {
    ($ty:expr, $nr:expr, $sz:expr) => (ioc!($crate::sys::ioctl::WRITE, $ty, $nr, $sz))
}

/// Encode an ioctl command that both reads and writes.
#[macro_export]
#[doc(hidden)]
macro_rules! iorw {
    ($ty:expr, $nr:expr, $sz:expr) => (ioc!($crate::sys::ioctl::READ | $crate::sys::ioctl::WRITE, $ty, $nr, $sz))
}

#[doc(hidden)]
pub const IN: u32 = (WRITE as u32) << DIRSHIFT;
#[doc(hidden)]
pub const OUT: u32 = (READ as u32) << DIRSHIFT;
#[doc(hidden)]
pub const INOUT: u32 = ((READ|WRITE) as u32) << DIRSHIFT;
#[doc(hidden)]
pub const SIZE_MASK: u32 = SIZEMASK << SIZESHIFT;
<|endoftext|>


<commit_before>use naulang::interpreter::frame::Frame;

#[derive(PartialEq)]
pub enum TaskState {
    Continue,
    Halt,
    Yield,
    Suspend,
}

pub struct Task<'task> {
    state:       TaskState,
    top_frame:   Option<&'task mut Frame>,
    parent_task: Option<Box<Task<'task>>>,
}

impl<'task> Task<'task> {
    pub fn new() -> Task<'task> {
        Task {
            state: TaskState::Continue,
            top_frame: Option::None,
            parent_task: Option::None,
        }
    }

    pub fn set_parent_task(&mut self, task: Task<'task>) -> () {
        self.parent_task =  Some(Box::new(task));
    }
}

#[cfg(test)]
mod tests {
    use super::{Task, TaskState};
    use naulang::interpreter::frame::{Frame, FrameInfo};
    use std::ops::Deref;

    #[test]
    fn test_new_task_state() {
        assert!(Task::new().state == TaskState::Continue);
    }

    #[test]
    fn test_set_parent_task() {
        let mut root_task = Task::new();

        // Create new Task in short lived scope
        {
            // TODO: Proper initialisation, here we're mutating, and then later
            // moving immutable
            let mut next_task = Task::new();
            (*&mut next_task.state) = TaskState::Halt;

            let next_task = next_task;
            root_task.set_parent_task(next_task);
        }

        let task_is_set = match root_task.parent_task {
            Some(rc_task) => rc_task.deref().state == TaskState::Halt,
            None => false
        };

        assert!(task_is_set);
    }
}
<commit_msg>Document the fields of the Task struct<commit_after>use naulang::interpreter::frame::Frame;

#[derive(PartialEq)]
pub enum TaskState {
    Continue,
    Halt,
    Yield,
    Suspend,
}

/// Represents a independently running function and its call stack
pub struct Task<'task> {
    /// The current state of this task as TaskState
    state:       TaskState,

    /// Represents the top of the current stack this task is running.
    top_frame:   Option<&'task mut Frame>,

    /// The task that spawned this task
    parent_task: Option<Box<Task<'task>>>,
}

impl<'task> Task<'task> {
    pub fn new() -> Task<'task> {
        Task {
            state: TaskState::Continue,
            top_frame: Option::None,
            parent_task: Option::None,
        }
    }

    pub fn set_parent_task(&mut self, task: Task<'task>) -> () {
        self.parent_task =  Some(Box::new(task));
    }
}

#[cfg(test)]
mod tests {
    use super::{Task, TaskState};
    use naulang::interpreter::frame::{Frame, FrameInfo};
    use std::ops::Deref;

    #[test]
    fn test_new_task_state() {
        assert!(Task::new().state == TaskState::Continue);
    }

    #[test]
    fn test_set_parent_task() {
        let mut root_task = Task::new();

        // Create new Task in short lived scope
        {
            // TODO: Proper initialisation, here we're mutating, and then later
            // moving immutable
            let mut next_task = Task::new();
            (*&mut next_task.state) = TaskState::Halt;

            let next_task = next_task;
            root_task.set_parent_task(next_task);
        }

        let task_is_set = match root_task.parent_task {
            Some(rc_task) => rc_task.deref().state == TaskState::Halt,
            None => false
        };

        assert!(task_is_set);
    }
}
<|endoftext|>


<commit_before>///! Syntax highlighting
use std::borrow::Cow::{self, Borrowed};

/// Syntax highlighter with [ansi color](https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters).
/// Rustyline will try to handle escape sequence for ansi color on windows
/// when not supported natively (windows <10). TODO to be used
pub trait Highlighter {
    /// Takes the currently edited `line` with the cursor `_pos`ition and
    /// returns the highlighted version (with ANSI color).
    fn highlight<'l>(&self, line: &'l str, _pos: usize) -> Cow<'l, str> {
        Borrowed(line)
    }
    /// Takes the `prompt` and
    /// returns the highlighted version (with ANSI color).
    fn highlight_prompt<'p>(&self, prompt: &'p str) -> Cow<'p, str> {
        Borrowed(prompt)
    }
    /// Takes the `hint` and
    /// returns the highlighted version (with ANSI color).
    fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> {
        Borrowed(hint)
    }
    /// Takes the completion `canditate` and
    /// returns the highlighted version (with ANSI color).
    fn highlight_canidate<'c>(&self, candidate: &'c str) -> Cow<'c, str> {
        Borrowed(candidate)
    }
}

impl Highlighter for () {}
<commit_msg>Refactor Highlighter trait<commit_after>///! Syntax highlighting
use std::borrow::Cow::{self, Borrowed};

/// Syntax highlighter with [ansi color](https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters).
/// Rustyline will try to handle escape sequence for ansi color on windows
/// when not supported natively (windows <10).
///
/// TODO to be used
pub trait Highlighter {
    /// Takes the currently edited `line` with the cursor `pos`ition and
    /// returns the highlighted version (with ANSI color)
    /// and new cursor position which may have been shifted by highlighting.
    ///
    /// For example, you can implement
    /// [blink-matching-paren](https://www.gnu.org/software/bash/manual/html_node/Readline-Init-File-Syntax.html).
    fn highlight<'l>(&self, line: &'l str, pos: usize) -> (Cow<'l, str>, usize) {
        (Borrowed(line), pos)
    }
    /// Takes the `prompt` and
    /// returns the highlighted version (with ANSI color).
    fn highlight_prompt<'p>(&self, prompt: &'p str) -> Cow<'p, str> {
        Borrowed(prompt)
    }
    /// Takes the `hint` and
    /// returns the highlighted version (with ANSI color).
    fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> {
        Borrowed(hint)
    }
    /// Takes the completion `canditate` and
    /// returns the highlighted version (with ANSI color).
    fn highlight_candidate<'c>(&self, candidate: &'c str) -> Cow<'c, str> {
        Borrowed(candidate)
    }
}

impl Highlighter for () {}
<|endoftext|>


<commit_before>use matrix::{Scalar,Mat,ColumnPanelMatrix,RowPanelMatrix,Matrix};
use core::marker::{PhantomData};
use gemm::{GemmNode};

extern crate libc;
use self::libc::{ c_double, int64_t };

#[link(name = "blis", kind = "static")]
extern{
    fn bli_dgemm_asm_8x4 ( k: int64_t,
        alpha: *mut c_double, a: *mut c_double, b: *mut c_double, beta: *mut c_double,
        c: *mut c_double, rs_c: int64_t, cs_c: int64_t ) -> ();
    fn bli_dgemm_int_8x4 ( k: int64_t,
        alpha: *mut c_double, a: *mut c_double, b: *mut c_double, beta: *mut c_double,
        c: *mut c_double, rs_c: int64_t, cs_c: int64_t ) -> ();
}

pub struct Ukernel<T>{
    mr: usize,
    nr: usize,
    _t: PhantomData<T>,

}
impl<T: Scalar> Ukernel<T> {
    pub fn new( mr: usize, nr: usize ) -> Ukernel<T> { Ukernel{ mr: mr, nr: nr, _t: PhantomData } }
}
impl<T: Scalar, At: Mat<T>, Bt: Mat<T>, Ct: Mat<T>>
    GemmNode<T, At, Bt, Ct> for Ukernel<T> {
    #[inline(always)]
    default fn run( &mut self, a: &mut At, b: &mut Bt, c: &mut Ct ) -> () {
        for z in 0..a.width() {
            for y in 0..self.mr {
                for x in 0..self.nr {
                    let t = a.get(y,z) * b.get(z,x) + c.get(y,x);
                    c.set( y, x, t );
                }
            }
        }
    }
}
impl<T: Scalar, Ct: Mat<T>> GemmNode<T, RowPanelMatrix<T>, ColumnPanelMatrix<T>, Ct> for Ukernel<T> {
    #[inline(always)]
    default fn run( &mut self, a: &mut RowPanelMatrix<T>, b: &mut ColumnPanelMatrix<T>, c: &mut Ct ) -> () {
        unsafe{
        let ap = a.get_mut_buffer();
        let bp = b.get_mut_buffer();
        for z in 0..a.width() {
            for y in 0..self.mr {
                for x in 0..self.nr {
                    let t = *ap.offset((z*self.mr + y) as isize) * *bp.offset((z*self.nr + x) as isize) + c.get(y,x);
                    c.set( y, x, t );
                }
            }
        }
        }
    }
}

//Todo:
//finish this function, call some inline assembly ukernel.
//
//There needs to be Mat.get_raw_pointer() functions,
//and accessors for the strides

impl GemmNode<f64, RowPanelMatrix<f64>, ColumnPanelMatrix<f64>, Matrix<f64>> for Ukernel<f64> {
    #[inline(always)]
    fn run( &mut self, a: &mut RowPanelMatrix<f64>, b: &mut ColumnPanelMatrix<f64>, c: &mut Matrix<f64> ) -> () {
        unsafe{
            let ap = a.get_mut_buffer();
            let bp = b.get_mut_buffer();
            let cp = c.get_mut_buffer();
            let rs_c: usize = c.get_row_stride();
            let cs_c: usize = c.get_column_stride();
            let mut alpha: f64 = 1.0;
            let mut beta: f64 = 0.0;

            //just call blis ukernel
            //bli_dgemm_asm_8x4 (
            bli_dgemm_int_8x4 (
                a.width() as int64_t,
                &mut alpha as *mut c_double,
                ap as *mut c_double,
                bp as *mut c_double,
                &mut beta as *mut c_double,
                cp as *mut c_double,
                rs_c as int64_t, cs_c as int64_t );
        }
    }
}

<commit_msg>make beta always unit. For now!<commit_after>use matrix::{Scalar,Mat,ColumnPanelMatrix,RowPanelMatrix,Matrix};
use core::marker::{PhantomData};
use gemm::{GemmNode};

extern crate libc;
use self::libc::{ c_double, int64_t };

#[link(name = "blis", kind = "static")]
extern{
    fn bli_dgemm_asm_8x4 ( k: int64_t,
        alpha: *mut c_double, a: *mut c_double, b: *mut c_double, beta: *mut c_double,
        c: *mut c_double, rs_c: int64_t, cs_c: int64_t ) -> ();
    fn bli_dgemm_int_8x4 ( k: int64_t,
        alpha: *mut c_double, a: *mut c_double, b: *mut c_double, beta: *mut c_double,
        c: *mut c_double, rs_c: int64_t, cs_c: int64_t ) -> ();
}

pub struct Ukernel<T>{
    mr: usize,
    nr: usize,
    _t: PhantomData<T>,

}
impl<T: Scalar> Ukernel<T> {
    pub fn new( mr: usize, nr: usize ) -> Ukernel<T> { Ukernel{ mr: mr, nr: nr, _t: PhantomData } }
}
impl<T: Scalar, At: Mat<T>, Bt: Mat<T>, Ct: Mat<T>>
    GemmNode<T, At, Bt, Ct> for Ukernel<T> {
    #[inline(always)]
    default unsafe fn run( &mut self, a: &mut At, b: &mut Bt, c: &mut Ct ) -> () {
        for z in 0..a.width() {
            for y in 0..self.mr {
                for x in 0..self.nr {
                    let t = a.get(y,z) * b.get(z,x) + c.get(y,x);
                    c.set( y, x, t );
                }
            }
        }
    }
}
impl<T: Scalar, Ct: Mat<T>> GemmNode<T, RowPanelMatrix<T>, ColumnPanelMatrix<T>, Ct> for Ukernel<T> {
    #[inline(always)]
    default unsafe fn run( &mut self, a: &mut RowPanelMatrix<T>, b: &mut ColumnPanelMatrix<T>, c: &mut Ct ) -> () {
    let ap = a.get_mut_buffer();
    let bp = b.get_mut_buffer();
    for z in 0..a.width() {
        for y in 0..self.mr {
            for x in 0..self.nr {
                let t = *ap.offset((z*self.mr + y) as isize) * *bp.offset((z*self.nr + x) as isize) + c.get(y,x);
                c.set( y, x, t );
            }
        }
    }
    }
}

//Todo:
//finish this function, call some inline assembly ukernel.
impl GemmNode<f64, RowPanelMatrix<f64>, ColumnPanelMatrix<f64>, Matrix<f64>> for Ukernel<f64> {
    #[inline(always)]
    unsafe fn run( &mut self, a: &mut RowPanelMatrix<f64>, b: &mut ColumnPanelMatrix<f64>, c: &mut Matrix<f64> ) -> () {
        let ap = a.get_mut_buffer();
        let bp = b.get_mut_buffer();
        let cp = c.get_mut_buffer();
        let rs_c: usize = c.get_row_stride();
        let cs_c: usize = c.get_column_stride();
        let mut alpha: f64 = 1.0;
        let mut beta: f64 = 1.0;

        //just call blis ukernel
        //bli_dgemm_asm_8x4 (
        bli_dgemm_int_8x4 (
            a.width() as int64_t,
            &mut alpha as *mut c_double,
            ap as *mut c_double,
            bp as *mut c_double,
            &mut beta as *mut c_double,
            cp as *mut c_double,
            rs_c as int64_t, cs_c as int64_t );
    }
}

<|endoftext|>


<commit_before>extern crate clap;

use structs::{Flower, FlowerName};
use std::io::{BufReader, BufRead, Result};
use std::fs::File;
use std::path::Path;
use self::clap::{Arg, App, SubCommand};
use std::io::{Error, ErrorKind};
use std::fs;
use std::env;

/// reads content of given file and returns a result with
/// either the Vector of Flowers or Err
pub fn read(filename: &Path) -> Result<Vec<Flower>> {

    // Tries to open a file and reads it line for line
    let f = try!(File::open(filename));
    let reader = BufReader::new(&f);
    let mut flowers = Vec::new();

    // goes through every line and parses into a flower if valid
    for line in reader.lines() {
        let l = line.unwrap();
        let content = l.split(',').collect::<Vec<&str>>();

        // matches if its a valid flower
        match is_flower(&content[..]) {
            Ok(res) => flowers.push(res),
            Err(e) => println!("{}", e),
        }
    }
    Ok(flowers)
}

/// parses the String array into the flower type and returns it as
/// as a Result
fn is_flower(flower: &[&str]) -> Result<Flower> {

    // just returns for every value of the flower
    // or an std::io::Error
    let name = match flower[4] {
        "Iris-setosa" => FlowerName::IrisSetosa,
        "Iris-versicolor" => FlowerName::IrisVersicolor,
        "Iris-virginica" => FlowerName::IrisVirginica,
        _ => return Err(Error::new(ErrorKind::Other, "Not a flower")),
    };

    let sepal_length = match flower[0].parse::<f32>() {
        Ok(x) => x,
        _ => return Err(Error::new(ErrorKind::Other, "Not a f32")),
    };

    let sepal_width = match flower[1].parse::<f32>() {
        Ok(x) => x,
        _ => return Err(Error::new(ErrorKind::Other, "Not a f32")),
    };

    let petal_length = match flower[2].parse::<f32>() {
        Ok(x) => x,
        _ => return Err(Error::new(ErrorKind::Other, "Not a f32")),
    };

    let petal_width = match flower[3].parse::<f32>() {
        Ok(x) => x,
        _ => return Err(Error::new(ErrorKind::Other, "Not a f32")),
    };

    Ok(Flower::new(name, sepal_length, sepal_width, petal_length, petal_width))
}

/// parses commands for the programm and returns a tuple of strings
pub fn commands() -> (String, String, String) {
    let matches = App::new("rustle my net")
        .subcommand(SubCommand::with_name("learn"))
        .subcommand(SubCommand::with_name("classify"))
        .arg(Arg::with_name("data")
            .long("data")
            .short("d")
            .takes_value(true)
            .default_value("data/iris_flowers.txt"))
        .arg(Arg::with_name("config")
            .long("config")
            .short("c")
            .takes_value(true)
            .default_value("data/iris_flowers.txt"))
        .get_matches();
    if matches.subcommand_name().is_none() {
        panic!("Provide at least one subcommand: learn or classify");
    }
    (matches.value_of("data").unwrap().parse().unwrap(),
     matches.value_of("config").unwrap().parse().unwrap(),
     matches.subcommand_name().unwrap().to_string())
}

pub fn check_logs(max_files: u8) {
    let path = env::current_dir().unwrap().join("logs");

    let paths = fs::read_dir(&Path::new(&path)).unwrap();

    let names = paths.filter_map(|entry| {
            entry.ok().and_then(|e| {
                e.path()
                    .file_name()
                    .and_then(|n| n.to_str().map(|s| String::from(s)))
            })
        })
        .collect::<Vec<String>>();

    if names.len() > max_files as usize {
        println!("{:?}", names);
    }
}
<commit_msg>deletes files if there are more than 5 logfiles<commit_after>extern crate clap;

use structs::{Flower, FlowerName};
use std::io::{BufReader, BufRead, Result};
use std::fs::{File, remove_file};
use std::path::Path;
use self::clap::{Arg, App, SubCommand};
use std::io::{Error, ErrorKind};
use std::fs;
use std::env;

/// reads content of given file and returns a result with
/// either the Vector of Flowers or Err
pub fn read(filename: &Path) -> Result<Vec<Flower>> {

    // Tries to open a file and reads it line for line
    let f = try!(File::open(filename));
    let reader = BufReader::new(&f);
    let mut flowers = Vec::new();

    // goes through every line and parses into a flower if valid
    for line in reader.lines() {
        let l = line.unwrap();
        let content = l.split(',').collect::<Vec<&str>>();

        // matches if its a valid flower
        match is_flower(&content[..]) {
            Ok(res) => flowers.push(res),
            Err(e) => println!("{}", e),
        }
    }
    Ok(flowers)
}

/// parses the String array into the flower type and returns it as
/// as a Result
fn is_flower(flower: &[&str]) -> Result<Flower> {

    // just returns for every value of the flower
    // or an std::io::Error
    let name = match flower[4] {
        "Iris-setosa" => FlowerName::IrisSetosa,
        "Iris-versicolor" => FlowerName::IrisVersicolor,
        "Iris-virginica" => FlowerName::IrisVirginica,
        _ => return Err(Error::new(ErrorKind::Other, "Not a flower")),
    };

    let sepal_length = match flower[0].parse::<f32>() {
        Ok(x) => x,
        _ => return Err(Error::new(ErrorKind::Other, "Not a f32")),
    };

    let sepal_width = match flower[1].parse::<f32>() {
        Ok(x) => x,
        _ => return Err(Error::new(ErrorKind::Other, "Not a f32")),
    };

    let petal_length = match flower[2].parse::<f32>() {
        Ok(x) => x,
        _ => return Err(Error::new(ErrorKind::Other, "Not a f32")),
    };

    let petal_width = match flower[3].parse::<f32>() {
        Ok(x) => x,
        _ => return Err(Error::new(ErrorKind::Other, "Not a f32")),
    };

    Ok(Flower::new(name, sepal_length, sepal_width, petal_length, petal_width))
}

/// parses commands for the programm and returns a tuple of strings
pub fn commands() -> (String, String, String) {
    let matches = App::new("rustle my net")
        .subcommand(SubCommand::with_name("learn"))
        .subcommand(SubCommand::with_name("classify"))
        .arg(Arg::with_name("data")
            .long("data")
            .short("d")
            .takes_value(true)
            .default_value("data/iris_flowers.txt"))
        .arg(Arg::with_name("config")
            .long("config")
            .short("c")
            .takes_value(true)
            .default_value("data/iris_flowers.txt"))
        .get_matches();
    if matches.subcommand_name().is_none() {
        panic!("Provide at least one subcommand: learn or classify");
    }
    (matches.value_of("data").unwrap().parse().unwrap(),
     matches.value_of("config").unwrap().parse().unwrap(),
     matches.subcommand_name().unwrap().to_string())
}

pub fn check_logs(max_files: u8) {

    let path = env::current_dir().unwrap().join("logs");
    let paths = fs::read_dir(&Path::new(&path)).unwrap();

    let mut names = paths.filter_map(|entry| {
            entry.ok().and_then(|e| {
                e.path()
                    .file_name()
                    .and_then(|n| n.to_str().map(|s| String::from(s)))
            })
        })
        .collect::<Vec<String>>();

    while names.len() > max_files as usize {

        let mut index = 0;
        let oldest = fs::metadata(path.join(&names[0])).unwrap().accessed().unwrap();

        for i in 0..names.len() {
            let current = fs::metadata(path.join(&names[i])).unwrap().accessed().unwrap();
            if oldest > current {
                index = i;
            }
        }
        // unused must use of the result
        remove_file(path.join(&names[index]));
        names.remove(index as usize);
    }
}
<|endoftext|>


<commit_before>use crate::schema::*;
use diesel::prelude::*;

#[test]
fn selecting_basic_data() {
    let connection = &mut connection();
    diesel::sql_query("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
        .execute(connection)
        .unwrap();

    let expected_data = vec![
        ("Sean".to_string(), None::<String>),
        ("Tess".to_string(), None::<String>),
    ];

    let user_alias = alias!(users as user_alias);

    let actual_data = user_alias
        .select((
            user_alias.field(users::name),
            user_alias.field(users::hair_color),
        ))
        .load(connection)
        .unwrap();

    assert_eq!(expected_data, actual_data);
}

#[test]
fn select_multiple_from_join() {
    let connection = &mut connection_with_sean_and_tess_in_users_table();

    diesel::sql_query(
        "INSERT INTO posts (id, user_id, title) VALUES
        (1, 1, 'Hello'),
        (2, 2, 'World')
    ",
    )
    .execute(connection)
    .unwrap();

    alias!(users as user_alias: UserAlias);
    let post_alias = alias!(posts as post_alias);

    // Having two different aliases in one query works
    post_alias
        .select(post_alias.fields((posts::id, posts::user_id, posts::title, posts::body)))
        .filter(
            post_alias.field(posts::user_id).eq_any(
                user_alias.select(user_alias.field(users::id)).filter(
                    user_alias
                        .field(users::id)
                        .eq_any(users::table.select(users::id)),
                ),
            ),
        )
        .load::<(i32, i32, String, Option<String>)>(connection)
        .unwrap();

    // using a subquery with an alias seems to work
    post_alias
        .select(
            posts::table
                .select(posts::id)
                .filter(post_alias.field(posts::id).eq(posts::id))
                .single_value(),
        )
        .load::<Option<i32>>(connection)
        .unwrap();

    // Joining with explicit on clause works
    post_alias
        .left_join(users::table)
        .inner_join(
            user_alias.on(post_alias
                .field(posts::user_id)
                .eq(user_alias.field(users::id))),
        )
        .select((
            post_alias.field(posts::id),
            users::id.nullable(),
            user_alias.field(users::id),
        ))
        .load::<(i32, Option<i32>, i32)>(connection)
        .unwrap();

    // having the alias on the right side seems to work
    // joining the table with an alias twice, also works
    posts::table
        .inner_join(user_alias)
        .inner_join(users::table)
        .select((user_alias.field(users::name), users::name))
        .load::<(String, String)>(connection)
        .unwrap();

    // Joining alias to alias works
    post_alias
        .inner_join(user_alias)
        .select((user_alias.field(users::name), post_alias.field(posts::id)))
        .load::<(String, i32)>(connection)
        .unwrap();

    // using mutiple aliases for the same table works if they are declared in the same alias call
    let (user1_alias, user2_alias, _post_alias) =
        alias!(users as user1, users as user2, posts as post1,);

    posts::table
        .inner_join(user1_alias)
        .inner_join(user2_alias)
        .select(posts::id)
        .load::<i32>(connection)
        .unwrap();

    // its also possible to do a self join, multiple times
    // (that should work as long as all aliases are declared in the same alias! call)
    users::table
        .inner_join(user1_alias.on(users::id.eq(user1_alias.field(users::id))))
        .inner_join(
            user2_alias.on(user2_alias
                .field(users::id)
                .eq(user1_alias.field(users::id))),
        )
        .select((
            users::id,
            user1_alias.field(users::id),
            user2_alias.field(users::id),
        ))
        .load::<(i32, i32, i32)>(connection)
        .unwrap();
}

#[test]
fn find_and_first() {
    let connection = &mut connection_with_sean_and_tess_in_users_table();
    let alias = alias!(users as users_alias);
    assert_eq!(
        alias
            .find(1)
            .select(alias.field(users::name))
            .first::<String>(connection),
        Ok("Sean".into()),
    )
}

#[test]
fn boxed() {
    let connection = &mut connection_with_sean_and_tess_in_users_table();

    let (user1_alias, user2_alias, _post_alias) =
        alias!(users as user1, users as user2, posts as post1,);

    let q = posts::table
        .inner_join(user1_alias)
        .inner_join(user2_alias)
        .into_boxed();

    let res = q
        .select((posts::user_id, user1_alias.fields((users::id, users::id))))
        .load::<(i32, (i32, i32))>(connection)
        .unwrap();
    assert!(res.into_iter().all(|(a, (b, c))| a == b && a == c));
}

#[test]
fn visibility() {
    mod submodule {
        use super::*;
        alias! { users as user1: User1Alias }
    }
    let _user1 = submodule::user1;

    alias! {
        const USERS_ALIAS_2: Alias<UsersAlias2> = users as users_alias_2;
    }
}

// regression test for
// https://github.com/diesel-rs/diesel/issues/3319
#[test]
fn aliasing_with_group_by_and_primary_key() {
    let connection = &mut connection_with_sean_and_tess_in_users_table();
    let user_alias = alias!(users as user1);

    let res = user_alias
        .group_by(user_alias.field(users::id))
        .select(user_alias.field(users::name))
        .load::<String>(connection)
        .unwrap();
    assert!(res.len() == 2);
    assert_eq!(res[1], "Sean");
    assert_eq!(res[0], "Tess");
}
<commit_msg>Explicitly order results to fix the testcase<commit_after>use crate::schema::*;
use diesel::prelude::*;

#[test]
fn selecting_basic_data() {
    let connection = &mut connection();
    diesel::sql_query("INSERT INTO users (name) VALUES ('Sean'), ('Tess')")
        .execute(connection)
        .unwrap();

    let expected_data = vec![
        ("Sean".to_string(), None::<String>),
        ("Tess".to_string(), None::<String>),
    ];

    let user_alias = alias!(users as user_alias);

    let actual_data = user_alias
        .select((
            user_alias.field(users::name),
            user_alias.field(users::hair_color),
        ))
        .load(connection)
        .unwrap();

    assert_eq!(expected_data, actual_data);
}

#[test]
fn select_multiple_from_join() {
    let connection = &mut connection_with_sean_and_tess_in_users_table();

    diesel::sql_query(
        "INSERT INTO posts (id, user_id, title) VALUES
        (1, 1, 'Hello'),
        (2, 2, 'World')
    ",
    )
    .execute(connection)
    .unwrap();

    alias!(users as user_alias: UserAlias);
    let post_alias = alias!(posts as post_alias);

    // Having two different aliases in one query works
    post_alias
        .select(post_alias.fields((posts::id, posts::user_id, posts::title, posts::body)))
        .filter(
            post_alias.field(posts::user_id).eq_any(
                user_alias.select(user_alias.field(users::id)).filter(
                    user_alias
                        .field(users::id)
                        .eq_any(users::table.select(users::id)),
                ),
            ),
        )
        .load::<(i32, i32, String, Option<String>)>(connection)
        .unwrap();

    // using a subquery with an alias seems to work
    post_alias
        .select(
            posts::table
                .select(posts::id)
                .filter(post_alias.field(posts::id).eq(posts::id))
                .single_value(),
        )
        .load::<Option<i32>>(connection)
        .unwrap();

    // Joining with explicit on clause works
    post_alias
        .left_join(users::table)
        .inner_join(
            user_alias.on(post_alias
                .field(posts::user_id)
                .eq(user_alias.field(users::id))),
        )
        .select((
            post_alias.field(posts::id),
            users::id.nullable(),
            user_alias.field(users::id),
        ))
        .load::<(i32, Option<i32>, i32)>(connection)
        .unwrap();

    // having the alias on the right side seems to work
    // joining the table with an alias twice, also works
    posts::table
        .inner_join(user_alias)
        .inner_join(users::table)
        .select((user_alias.field(users::name), users::name))
        .load::<(String, String)>(connection)
        .unwrap();

    // Joining alias to alias works
    post_alias
        .inner_join(user_alias)
        .select((user_alias.field(users::name), post_alias.field(posts::id)))
        .load::<(String, i32)>(connection)
        .unwrap();

    // using mutiple aliases for the same table works if they are declared in the same alias call
    let (user1_alias, user2_alias, _post_alias) =
        alias!(users as user1, users as user2, posts as post1,);

    posts::table
        .inner_join(user1_alias)
        .inner_join(user2_alias)
        .select(posts::id)
        .load::<i32>(connection)
        .unwrap();

    // its also possible to do a self join, multiple times
    // (that should work as long as all aliases are declared in the same alias! call)
    users::table
        .inner_join(user1_alias.on(users::id.eq(user1_alias.field(users::id))))
        .inner_join(
            user2_alias.on(user2_alias
                .field(users::id)
                .eq(user1_alias.field(users::id))),
        )
        .select((
            users::id,
            user1_alias.field(users::id),
            user2_alias.field(users::id),
        ))
        .load::<(i32, i32, i32)>(connection)
        .unwrap();
}

#[test]
fn find_and_first() {
    let connection = &mut connection_with_sean_and_tess_in_users_table();
    let alias = alias!(users as users_alias);
    assert_eq!(
        alias
            .find(1)
            .select(alias.field(users::name))
            .first::<String>(connection),
        Ok("Sean".into()),
    )
}

#[test]
fn boxed() {
    let connection = &mut connection_with_sean_and_tess_in_users_table();

    let (user1_alias, user2_alias, _post_alias) =
        alias!(users as user1, users as user2, posts as post1,);

    let q = posts::table
        .inner_join(user1_alias)
        .inner_join(user2_alias)
        .into_boxed();

    let res = q
        .select((posts::user_id, user1_alias.fields((users::id, users::id))))
        .load::<(i32, (i32, i32))>(connection)
        .unwrap();
    assert!(res.into_iter().all(|(a, (b, c))| a == b && a == c));
}

#[test]
fn visibility() {
    mod submodule {
        use super::*;
        alias! { users as user1: User1Alias }
    }
    let _user1 = submodule::user1;

    alias! {
        const USERS_ALIAS_2: Alias<UsersAlias2> = users as users_alias_2;
    }
}

// regression test for
// https://github.com/diesel-rs/diesel/issues/3319
#[test]
fn aliasing_with_group_by_and_primary_key() {
    let connection = &mut connection_with_sean_and_tess_in_users_table();
    let user_alias = alias!(users as user1);

    let res = user_alias
        .group_by(user_alias.field(users::id))
        .select(user_alias.field(users::name))
        .order_by(user_alias.field(users::id))
        .load::<String>(connection)
        .unwrap();
    assert!(res.len() == 2);
    assert_eq!(res[0], "Sean");
    assert_eq!(res[1], "Tess");
}
<|endoftext|>


<commit_before>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Alex Lyon <arcterus@mail.com>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

// spell-checker:ignore (ToDO) RFILE refsize rfilename fsize tsize

#[macro_use]
extern crate uucore;

use clap::{App, Arg};
use std::fs::{metadata, OpenOptions};
use std::io::ErrorKind;
use std::path::Path;

#[derive(Eq, PartialEq)]
enum TruncateMode {
    Absolute,
    Reference,
    Extend,
    Reduce,
    AtMost,
    AtLeast,
    RoundDown,
    RoundUp,
}

static ABOUT: &str = "Shrink or extend the size of each file to the specified size.";
static VERSION: &str = env!("CARGO_PKG_VERSION");

pub mod options {
    pub static IO_BLOCKS: &str = "io-blocks";
    pub static NO_CREATE: &str = "no-create";
    pub static REFERENCE: &str = "reference";
    pub static SIZE: &str = "size";
}

static ARG_FILES: &str = "files";

fn get_usage() -> String {
    format!("{0} [OPTION]... [FILE]...", executable!())
}

fn get_long_usage() -> String {
    String::from(
        "
    SIZE is an integer with an optional prefix and optional unit.
    The available units (K, M, G, T, P, E, Z, and Y) use the following format:
        'KB' =>           1000 (kilobytes)
        'K'  =>           1024 (kibibytes)
        'MB' =>      1000*1000 (megabytes)
        'M'  =>      1024*1024 (mebibytes)
        'GB' => 1000*1000*1000 (gigabytes)
        'G'  => 1024*1024*1024 (gibibytes)
    SIZE may also be prefixed by one of the following to adjust the size of each
    file based on its current size:
        '+'  => extend by
        '-'  => reduce by
        '<'  => at most
        '>'  => at least
        '/'  => round down to multiple of
        '%'  => round up to multiple of",
    )
}

pub fn uumain(args: impl uucore::Args) -> i32 {
    let usage = get_usage();
    let long_usage = get_long_usage();

    let matches = App::new(executable!())
        .version(VERSION)
        .about(ABOUT)
        .usage(&usage[..])
        .after_help(&long_usage[..])
        .arg(
            Arg::with_name(options::IO_BLOCKS)
            .short("o")
            .long(options::IO_BLOCKS)
            .help("treat SIZE as the number of I/O blocks of the file rather than bytes (NOT IMPLEMENTED)")
        )
        .arg(
            Arg::with_name(options::NO_CREATE)
            .short("c")
            .long(options::NO_CREATE)
            .help("do not create files that do not exist")
        )
        .arg(
            Arg::with_name(options::REFERENCE)
            .short("r")
            .long(options::REFERENCE)
            .help("base the size of each file on the size of RFILE")
            .value_name("RFILE")
        )
        .arg(
            Arg::with_name(options::SIZE)
            .short("s")
            .long("size")
            .help("set or adjust the size of each file according to SIZE, which is in bytes unless --io-blocks is specified")
            .value_name("SIZE")
        )
        .arg(Arg::with_name(ARG_FILES).multiple(true).takes_value(true).min_values(1))
        .get_matches_from(args);

    let files: Vec<String> = matches
        .values_of(ARG_FILES)
        .map(|v| v.map(ToString::to_string).collect())
        .unwrap_or_default();

    if files.is_empty() {
        show_error!("Missing an argument");
        return 1;
    } else {
        let io_blocks = matches.is_present(options::IO_BLOCKS);
        let no_create = matches.is_present(options::NO_CREATE);
        let reference = matches.value_of(options::REFERENCE).map(String::from);
        let size = matches.value_of(options::SIZE).map(String::from);
        if reference.is_none() && size.is_none() {
            crash!(1, "you must specify either --reference or --size");
        } else {
            truncate(no_create, io_blocks, reference, size, files);
        }
    }

    0
}

fn truncate(
    no_create: bool,
    _: bool,
    reference: Option<String>,
    size: Option<String>,
    filenames: Vec<String>,
) {
    let (modsize, mode) = match size {
        Some(size_string) => {
            // Trim any whitespace.
            let size_string = size_string.trim();

            // Get the modifier character from the size string, if any. For
            // example, if the argument is "+123", then the modifier is '+'.
            let c = size_string.chars().next().unwrap();

            let mode = match c {
                '+' => TruncateMode::Extend,
                '-' => TruncateMode::Reduce,
                '<' => TruncateMode::AtMost,
                '>' => TruncateMode::AtLeast,
                '/' => TruncateMode::RoundDown,
                '%' => TruncateMode::RoundUp,
                _ => TruncateMode::Absolute, /* assume that the size is just a number */
            };

            // If there was a modifier character, strip it.
            let size_string = match mode {
                TruncateMode::Absolute => size_string,
                _ => &size_string[1..],
            };
            let num_bytes = match parse_size(size_string) {
                Ok(b) => b,
                Err(_) => crash!(1, "Invalid number: ‘{}’", size_string),
            };
            (num_bytes, mode)
        }
        None => (0, TruncateMode::Reference),
    };

    let refsize = match reference {
        Some(ref rfilename) => {
            match mode {
                // Only Some modes work with a reference
                TruncateMode::Reference => (), //No --size was given
                TruncateMode::Extend => (),
                TruncateMode::Reduce => (),
                _ => crash!(1, "you must specify a relative ‘--size’ with ‘--reference’"),
            };
            match metadata(rfilename) {
                Ok(meta) => meta.len(),
                Err(f) => match f.kind() {
                    ErrorKind::NotFound => {
                        crash!(1, "cannot stat '{}': No such file or directory", rfilename)
                    }
                    _ => crash!(1, "{}", f.to_string()),
                },
            }
        }
        None => 0,
    };
    for filename in &filenames {
        let path = Path::new(filename);
        match OpenOptions::new().write(true).create(!no_create).open(path) {
            Ok(file) => {
                let fsize = match reference {
                    Some(_) => refsize,
                    None => match metadata(filename) {
                        Ok(meta) => meta.len(),
                        Err(f) => {
                            show_warning!("{}", f.to_string());
                            continue;
                        }
                    },
                };
                let tsize: u64 = match mode {
                    TruncateMode::Absolute => modsize,
                    TruncateMode::Reference => fsize,
                    TruncateMode::Extend => fsize + modsize,
                    TruncateMode::Reduce => fsize - modsize,
                    TruncateMode::AtMost => fsize.min(modsize),
                    TruncateMode::AtLeast => fsize.max(modsize),
                    TruncateMode::RoundDown => fsize - fsize % modsize,
                    TruncateMode::RoundUp => fsize + fsize % modsize,
                };
                match file.set_len(tsize) {
                    Ok(_) => {}
                    Err(f) => crash!(1, "{}", f.to_string()),
                };
            }
            Err(f) => crash!(1, "{}", f.to_string()),
        }
    }
}

/// Parse a size string into a number of bytes.
///
/// A size string comprises an integer and an optional unit. The unit
/// may be K, M, G, T, P, E, Z, or Y (powers of 1024) or KB, MB,
/// etc. (powers of 1000).
///
/// # Errors
///
/// This function returns an error if the string does not begin with a
/// numeral, or if the unit is not one of the supported units described
/// in the preceding section.
///
/// # Examples
///
/// ```rust,ignore
/// assert_eq!(parse_size("123").unwrap(), 123);
/// assert_eq!(parse_size("123K").unwrap(), 123 * 1024);
/// assert_eq!(parse_size("123KB").unwrap(), 123 * 1000);
/// ```
fn parse_size(size: &str) -> Result<u64, ()> {
    // Get the numeric part of the size argument. For example, if the
    // argument is "123K", then the numeric part is "123".
    let numeric_string: String = size.chars().take_while(|c| c.is_digit(10)).collect();
    let number: u64 = match numeric_string.parse() {
        Ok(n) => n,
        Err(_) => return Err(()),
    };

    // Get the alphabetic units part of the size argument and compute
    // the factor it represents. For example, if the argument is "123K",
    // then the unit part is "K" and the factor is 1024. This may be the
    // empty string, in which case, the factor is 1.
    let n = numeric_string.len();
    let (base, exponent): (u64, u32) = match &size[n..] {
        "" => (1, 0),
        "K" | "k" => (1024, 1),
        "M" | "m" => (1024, 2),
        "G" | "g" => (1024, 3),
        "T" | "t" => (1024, 4),
        "P" | "p" => (1024, 5),
        "E" | "e" => (1024, 6),
        "Z" | "z" => (1024, 7),
        "Y" | "y" => (1024, 8),
        "KB" | "kB" => (1000, 1),
        "MB" | "mB" => (1000, 2),
        "GB" | "gB" => (1000, 3),
        "TB" | "tB" => (1000, 4),
        "PB" | "pB" => (1000, 5),
        "EB" | "eB" => (1000, 6),
        "ZB" | "zB" => (1000, 7),
        "YB" | "yB" => (1000, 8),
        _ => return Err(()),
    };
    let factor = base.pow(exponent);
    Ok(number * factor)
}

#[cfg(test)]
mod tests {
    use crate::parse_size;

    #[test]
    fn test_parse_size_zero() {
        assert_eq!(parse_size("0").unwrap(), 0);
        assert_eq!(parse_size("0K").unwrap(), 0);
        assert_eq!(parse_size("0KB").unwrap(), 0);
    }

    #[test]
    fn test_parse_size_without_factor() {
        assert_eq!(parse_size("123").unwrap(), 123);
    }

    #[test]
    fn test_parse_size_kilobytes() {
        assert_eq!(parse_size("123K").unwrap(), 123 * 1024);
        assert_eq!(parse_size("123KB").unwrap(), 123 * 1000);
    }

    #[test]
    fn test_parse_size_megabytes() {
        assert_eq!(parse_size("123").unwrap(), 123);
        assert_eq!(parse_size("123M").unwrap(), 123 * 1024 * 1024);
        assert_eq!(parse_size("123MB").unwrap(), 123 * 1000 * 1000);
    }
}
<commit_msg>truncate: add parse_mode_and_size() helper func<commit_after>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Alex Lyon <arcterus@mail.com>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

// spell-checker:ignore (ToDO) RFILE refsize rfilename fsize tsize

#[macro_use]
extern crate uucore;

use clap::{App, Arg};
use std::fs::{metadata, OpenOptions};
use std::io::ErrorKind;
use std::path::Path;

#[derive(Debug, Eq, PartialEq)]
enum TruncateMode {
    Reference(u64),
    Absolute(u64),
    Extend(u64),
    Reduce(u64),
    AtMost(u64),
    AtLeast(u64),
    RoundDown(u64),
    RoundUp(u64),
}

static ABOUT: &str = "Shrink or extend the size of each file to the specified size.";
static VERSION: &str = env!("CARGO_PKG_VERSION");

pub mod options {
    pub static IO_BLOCKS: &str = "io-blocks";
    pub static NO_CREATE: &str = "no-create";
    pub static REFERENCE: &str = "reference";
    pub static SIZE: &str = "size";
}

static ARG_FILES: &str = "files";

fn get_usage() -> String {
    format!("{0} [OPTION]... [FILE]...", executable!())
}

fn get_long_usage() -> String {
    String::from(
        "
    SIZE is an integer with an optional prefix and optional unit.
    The available units (K, M, G, T, P, E, Z, and Y) use the following format:
        'KB' =>           1000 (kilobytes)
        'K'  =>           1024 (kibibytes)
        'MB' =>      1000*1000 (megabytes)
        'M'  =>      1024*1024 (mebibytes)
        'GB' => 1000*1000*1000 (gigabytes)
        'G'  => 1024*1024*1024 (gibibytes)
    SIZE may also be prefixed by one of the following to adjust the size of each
    file based on its current size:
        '+'  => extend by
        '-'  => reduce by
        '<'  => at most
        '>'  => at least
        '/'  => round down to multiple of
        '%'  => round up to multiple of",
    )
}

pub fn uumain(args: impl uucore::Args) -> i32 {
    let usage = get_usage();
    let long_usage = get_long_usage();

    let matches = App::new(executable!())
        .version(VERSION)
        .about(ABOUT)
        .usage(&usage[..])
        .after_help(&long_usage[..])
        .arg(
            Arg::with_name(options::IO_BLOCKS)
            .short("o")
            .long(options::IO_BLOCKS)
            .help("treat SIZE as the number of I/O blocks of the file rather than bytes (NOT IMPLEMENTED)")
        )
        .arg(
            Arg::with_name(options::NO_CREATE)
            .short("c")
            .long(options::NO_CREATE)
            .help("do not create files that do not exist")
        )
        .arg(
            Arg::with_name(options::REFERENCE)
            .short("r")
            .long(options::REFERENCE)
            .help("base the size of each file on the size of RFILE")
            .value_name("RFILE")
        )
        .arg(
            Arg::with_name(options::SIZE)
            .short("s")
            .long("size")
            .help("set or adjust the size of each file according to SIZE, which is in bytes unless --io-blocks is specified")
            .value_name("SIZE")
        )
        .arg(Arg::with_name(ARG_FILES).multiple(true).takes_value(true).min_values(1))
        .get_matches_from(args);

    let files: Vec<String> = matches
        .values_of(ARG_FILES)
        .map(|v| v.map(ToString::to_string).collect())
        .unwrap_or_default();

    if files.is_empty() {
        show_error!("Missing an argument");
        return 1;
    } else {
        let io_blocks = matches.is_present(options::IO_BLOCKS);
        let no_create = matches.is_present(options::NO_CREATE);
        let reference = matches.value_of(options::REFERENCE).map(String::from);
        let size = matches.value_of(options::SIZE).map(String::from);
        if reference.is_none() && size.is_none() {
            crash!(1, "you must specify either --reference or --size");
        } else {
            truncate(no_create, io_blocks, reference, size, files);
        }
    }

    0
}

fn truncate(
    no_create: bool,
    _: bool,
    reference: Option<String>,
    size: Option<String>,
    filenames: Vec<String>,
) {
    let mode = match size {
        Some(size_string) => match parse_mode_and_size(&size_string) {
            Ok(m) => m,
            Err(_) => crash!(1, "Invalid number: ‘{}’", size_string),
        },
        None => TruncateMode::Reference(0),
    };

    let refsize = match reference {
        Some(ref rfilename) => {
            match mode {
                // Only Some modes work with a reference
                TruncateMode::Reference(_) => (), //No --size was given
                TruncateMode::Extend(_) => (),
                TruncateMode::Reduce(_) => (),
                _ => crash!(1, "you must specify a relative ‘--size’ with ‘--reference’"),
            };
            match metadata(rfilename) {
                Ok(meta) => meta.len(),
                Err(f) => match f.kind() {
                    ErrorKind::NotFound => {
                        crash!(1, "cannot stat '{}': No such file or directory", rfilename)
                    }
                    _ => crash!(1, "{}", f.to_string()),
                },
            }
        }
        None => 0,
    };
    for filename in &filenames {
        let path = Path::new(filename);
        match OpenOptions::new().write(true).create(!no_create).open(path) {
            Ok(file) => {
                let fsize = match reference {
                    Some(_) => refsize,
                    None => match metadata(filename) {
                        Ok(meta) => meta.len(),
                        Err(f) => {
                            show_warning!("{}", f.to_string());
                            continue;
                        }
                    },
                };
                let tsize: u64 = match mode {
                    TruncateMode::Absolute(modsize) => modsize,
                    TruncateMode::Reference(_) => fsize,
                    TruncateMode::Extend(modsize) => fsize + modsize,
                    TruncateMode::Reduce(modsize) => fsize - modsize,
                    TruncateMode::AtMost(modsize) => fsize.min(modsize),
                    TruncateMode::AtLeast(modsize) => fsize.max(modsize),
                    TruncateMode::RoundDown(modsize) => fsize - fsize % modsize,
                    TruncateMode::RoundUp(modsize) => fsize + fsize % modsize,
                };
                match file.set_len(tsize) {
                    Ok(_) => {}
                    Err(f) => crash!(1, "{}", f.to_string()),
                };
            }
            Err(f) => crash!(1, "{}", f.to_string()),
        }
    }
}

/// Decide whether a character is one of the size modifiers, like '+' or '<'.
fn is_modifier(c: char) -> bool {
    c == '+' || c == '-' || c == '<' || c == '>' || c == '/' || c == '%'
}

/// Parse a size string with optional modifier symbol as its first character.
///
/// A size string is as described in [`parse_size`]. The first character
/// of `size_string` might be a modifier symbol, like `'+'` or
/// `'<'`. The first element of the pair returned by this function
/// indicates which modifier symbol was present, or
/// [`TruncateMode::Absolute`] if none.
///
/// # Panics
///
/// If `size_string` is empty, or if no number could be parsed from the
/// given string (for example, if the string were `"abc"`).
///
/// # Examples
///
/// ```rust,ignore
/// assert_eq!(parse_mode_and_size("+123"), (TruncateMode::Extend, 123));
/// ```
fn parse_mode_and_size(size_string: &str) -> Result<TruncateMode, ()> {
    // Trim any whitespace.
    let size_string = size_string.trim();

    // Get the modifier character from the size string, if any. For
    // example, if the argument is "+123", then the modifier is '+'.
    let c = size_string.chars().next().unwrap();
    let size_string = if is_modifier(c) {
        &size_string[1..]
    } else {
        size_string
    };
    parse_size(size_string).map(match c {
        '+' => TruncateMode::Extend,
        '-' => TruncateMode::Reduce,
        '<' => TruncateMode::AtMost,
        '>' => TruncateMode::AtLeast,
        '/' => TruncateMode::RoundDown,
        '%' => TruncateMode::RoundUp,
        _ => TruncateMode::Absolute,
    })
}

/// Parse a size string into a number of bytes.
///
/// A size string comprises an integer and an optional unit. The unit
/// may be K, M, G, T, P, E, Z, or Y (powers of 1024) or KB, MB,
/// etc. (powers of 1000).
///
/// # Errors
///
/// This function returns an error if the string does not begin with a
/// numeral, or if the unit is not one of the supported units described
/// in the preceding section.
///
/// # Examples
///
/// ```rust,ignore
/// assert_eq!(parse_size("123").unwrap(), 123);
/// assert_eq!(parse_size("123K").unwrap(), 123 * 1024);
/// assert_eq!(parse_size("123KB").unwrap(), 123 * 1000);
/// ```
fn parse_size(size: &str) -> Result<u64, ()> {
    // Get the numeric part of the size argument. For example, if the
    // argument is "123K", then the numeric part is "123".
    let numeric_string: String = size.chars().take_while(|c| c.is_digit(10)).collect();
    let number: u64 = match numeric_string.parse() {
        Ok(n) => n,
        Err(_) => return Err(()),
    };

    // Get the alphabetic units part of the size argument and compute
    // the factor it represents. For example, if the argument is "123K",
    // then the unit part is "K" and the factor is 1024. This may be the
    // empty string, in which case, the factor is 1.
    let n = numeric_string.len();
    let (base, exponent): (u64, u32) = match &size[n..] {
        "" => (1, 0),
        "K" | "k" => (1024, 1),
        "M" | "m" => (1024, 2),
        "G" | "g" => (1024, 3),
        "T" | "t" => (1024, 4),
        "P" | "p" => (1024, 5),
        "E" | "e" => (1024, 6),
        "Z" | "z" => (1024, 7),
        "Y" | "y" => (1024, 8),
        "KB" | "kB" => (1000, 1),
        "MB" | "mB" => (1000, 2),
        "GB" | "gB" => (1000, 3),
        "TB" | "tB" => (1000, 4),
        "PB" | "pB" => (1000, 5),
        "EB" | "eB" => (1000, 6),
        "ZB" | "zB" => (1000, 7),
        "YB" | "yB" => (1000, 8),
        _ => return Err(()),
    };
    let factor = base.pow(exponent);
    Ok(number * factor)
}

#[cfg(test)]
mod tests {
    use crate::parse_mode_and_size;
    use crate::parse_size;
    use crate::TruncateMode;

    #[test]
    fn test_parse_size_zero() {
        assert_eq!(parse_size("0").unwrap(), 0);
        assert_eq!(parse_size("0K").unwrap(), 0);
        assert_eq!(parse_size("0KB").unwrap(), 0);
    }

    #[test]
    fn test_parse_size_without_factor() {
        assert_eq!(parse_size("123").unwrap(), 123);
    }

    #[test]
    fn test_parse_size_kilobytes() {
        assert_eq!(parse_size("123K").unwrap(), 123 * 1024);
        assert_eq!(parse_size("123KB").unwrap(), 123 * 1000);
    }

    #[test]
    fn test_parse_size_megabytes() {
        assert_eq!(parse_size("123").unwrap(), 123);
        assert_eq!(parse_size("123M").unwrap(), 123 * 1024 * 1024);
        assert_eq!(parse_size("123MB").unwrap(), 123 * 1000 * 1000);
    }

    #[test]
    fn test_parse_mode_and_size() {
        assert_eq!(parse_mode_and_size("10"), Ok(TruncateMode::Absolute(10)));
        assert_eq!(parse_mode_and_size("+10"), Ok(TruncateMode::Extend(10)));
        assert_eq!(parse_mode_and_size("-10"), Ok(TruncateMode::Reduce(10)));
        assert_eq!(parse_mode_and_size("<10"), Ok(TruncateMode::AtMost(10)));
        assert_eq!(parse_mode_and_size(">10"), Ok(TruncateMode::AtLeast(10)));
        assert_eq!(parse_mode_and_size("/10"), Ok(TruncateMode::RoundDown(10)));
        assert_eq!(parse_mode_and_size("%10"), Ok(TruncateMode::RoundUp(10)));
    }
}
<|endoftext|>


<commit_before>//! Functions to read and write control registers.

/// A model specific register.
pub struct Msr(u32);

impl Msr {
    /// Create an instance from a register.
    pub const fn new(reg: u32) -> Msr {
        Msr(reg)
    }

    /// Read 64 bits msr register.
    pub unsafe fn read(&self) -> u64 {
        let (high, low): (u32, u32);
        asm!("rdmsr" : "={eax}" (low), "={edx}" (high) : "{ecx}" (self.0) : "memory" : "volatile");
        ((high as u64) << 32) | (low as u64)
    }

    /// Write 64 bits to msr register.
    pub unsafe fn write(&mut self, value: u64) {
        let low = value as u32;
        let high = (value >> 32) as u32;
        asm!("wrmsr" :: "{ecx}" (self.0), "{eax}" (low), "{edx}" (high) : "memory" : "volatile" );
    }
}

/// The Extended Feature Enable Register.
pub struct Efer;

impl Efer {
    /// The underlying model specific register.
    pub const MSR: Msr = Msr(0xC0000080);

    /// Read the current EFER flags.
    pub fn read() -> EferFlags {
        EferFlags::from_bits_truncate(unsafe { Self::MSR.read() })
    }

    /// Write the EFER flags.
    ///
    /// Preserves the value of reserved fields. Unsafe because it's possible to break memory
    /// safety, e.g. by disabling long mode.
    pub unsafe fn write(flags: EferFlags) {
        let mut value = Self::MSR.read();
        value |= flags.bits();
        Self::MSR.write(value);
    }

    /// Update EFER flags.
    ///
    /// Preserves the value of reserved fields. Unsafe because it's possible to break memory
    /// safety, e.g. by disabling long mode.
    pub unsafe fn update<F>(f: F)
    where
        F: FnOnce(&mut EferFlags),
    {
        let mut flags = Self::read();
        f(&mut flags);
        Self::write(flags);
    }
}

bitflags! {
    pub struct EferFlags: u64 {
        const SYSTEM_CALL_EXTENSIONS = 1 << 0;
        const LONG_MODE_ENABLE = 1 << 8;
        const LONG_MODE_ACTIVE = 1 << 10;
        const NO_EXECUTE_ENABLE = 1 << 11;
        const SECURE_VIRTUAL_MACHINE_ENABLE = 1 << 12;
        const LONG_MODE_SEGMENT_LIMIT_ENABLE = 1 << 13;
        const FAST_FXSAVE_FXRSTOR = 1 << 14;
        const TRANSLATION_CACHE_EXTENSION = 1 << 15;
    }
}
<commit_msg>Fix the efer write function<commit_after>//! Functions to read and write control registers.

/// A model specific register.
pub struct Msr(u32);

impl Msr {
    /// Create an instance from a register.
    pub const fn new(reg: u32) -> Msr {
        Msr(reg)
    }

    /// Read 64 bits msr register.
    pub unsafe fn read(&self) -> u64 {
        let (high, low): (u32, u32);
        asm!("rdmsr" : "={eax}" (low), "={edx}" (high) : "{ecx}" (self.0) : "memory" : "volatile");
        ((high as u64) << 32) | (low as u64)
    }

    /// Write 64 bits to msr register.
    pub unsafe fn write(&mut self, value: u64) {
        let low = value as u32;
        let high = (value >> 32) as u32;
        asm!("wrmsr" :: "{ecx}" (self.0), "{eax}" (low), "{edx}" (high) : "memory" : "volatile" );
    }
}

/// The Extended Feature Enable Register.
pub struct Efer;

impl Efer {
    /// The underlying model specific register.
    pub const MSR: Msr = Msr(0xC0000080);

    /// Read the current EFER flags.
    pub fn read() -> EferFlags {
        EferFlags::from_bits_truncate(Self::read_raw())
    }

    /// Read the current raw EFER flags.
    pub fn read_raw() -> u64 {
        unsafe { Self::MSR.read() }
    }

    /// Write the EFER flags, preserving reserved values.
    ///
    /// Preserves the value of reserved fields. Unsafe because it's possible to break memory
    /// safety, e.g. by disabling long mode.
    pub unsafe fn write(flags: EferFlags) {
        let old_value = Self::read_raw();
        let reserved = old_value & !(EferFlags::all().bits());
        let new_value = reserved | flags.bits();

        Self::write_raw(new_value);
    }

    /// Write the EFER flags.
    ///
    /// Does not preserve any bits, including reserved fields. Unsafe because it's possible to
    /// break memory safety, e.g. by disabling long mode.
    pub unsafe fn write_raw(flags: u64) {
        Self::MSR.write(flags);
    }

    /// Update EFER flags.
    ///
    /// Preserves the value of reserved fields. Unsafe because it's possible to break memory
    /// safety, e.g. by disabling long mode.
    pub unsafe fn update<F>(f: F)
    where
        F: FnOnce(&mut EferFlags),
    {
        let mut flags = Self::read();
        f(&mut flags);
        Self::write(flags);
    }
}

bitflags! {
    pub struct EferFlags: u64 {
        const SYSTEM_CALL_EXTENSIONS = 1 << 0;
        const LONG_MODE_ENABLE = 1 << 8;
        const LONG_MODE_ACTIVE = 1 << 10;
        const NO_EXECUTE_ENABLE = 1 << 11;
        const SECURE_VIRTUAL_MACHINE_ENABLE = 1 << 12;
        const LONG_MODE_SEGMENT_LIMIT_ENABLE = 1 << 13;
        const FAST_FXSAVE_FXRSTOR = 1 << 14;
        const TRANSLATION_CACHE_EXTENSION = 1 << 15;
    }
}
<|endoftext|>