<commit_before>// (C)opyleft 2013,2014 Frank Denis

/*!
 * Bindings for the GeoIP library
 */
#![desc = "Bindings for the GeoIP library."]
#![license = "BSD"]
#![crate_name = "geoip"]
#![crate_type = "rlib"]

#![warn(non_camel_case_types,
        non_upper_case_globals,
        unused_qualifications)]

extern crate libc;
extern crate serialize;

use libc::{c_void, c_char, c_int, c_ulong, c_float};
use std::c_str::CString;
use std::fmt;
use std::io::net::ip::{IpAddr,Ipv4Addr,Ipv6Addr};

type RawGeoIp = *const c_void;
type In6Addr = [u8, ..16];

#[repr(C)]
struct GeoIpLookup {
    netmask: c_int
}

impl GeoIpLookup {
    fn new() -> GeoIpLookup {
        GeoIpLookup {
            netmask: 0
        }
    }
}

#[link(name = "GeoIP")]
extern {
    fn GeoIP_open(dbtype: *const c_char, flags: c_int) -> RawGeoIp;
    fn GeoIP_delete(db: RawGeoIp);
    fn GeoIP_name_by_ipnum_gl(db: RawGeoIp, ipnum: c_ulong, gl: &GeoIpLookup) -> *const c_char;
    fn GeoIP_name_by_ipnum_v6_gl(db: RawGeoIp, ipnum: In6Addr, gl: &GeoIpLookup) -> *const c_char;
    fn GeoIP_record_by_ipnum(db: RawGeoIp, ipnum: c_ulong) -> *const GeoIpRecord;
    fn GeoIP_record_by_ipnum_v6(db: RawGeoIp, ipnum: In6Addr) -> *const GeoIpRecord;
    fn GeoIPRecord_delete(gir: *const GeoIpRecord);
    fn GeoIP_set_charset(db: RawGeoIp, charset: c_int) -> c_int;
}

enum Charset {
    UTF8 = 1
}

pub enum Options {
    Standard = 0,
    MemoryCache = 1,
    CheckCache = 2,
    IndexCache = 4,
    MmapCache = 8
}

pub enum DBType {
    CountryEdition = 1,
    RegionEditionRev0 = 7,
    CityEditionRev0 = 6,
    ORGEdition = 5,
    ISPEdition = 4,
    CityEditionRev1 = 2,
    RegionEditionRev1 = 3,
    ProxyEdition = 8,
    ASNUMEdition = 9,
    NetSpeedEdition = 10,
    DomainEdition = 11,
    CountryEditionV6 = 12,
    LocationAEdition = 13,
    AccuracyRadiusEdition = 14,
    LargeCountryEdition = 17,
    LargeCountryEditionV6 = 18,
    ASNumEditionV6 = 21,
    ISPEditionV6 = 22,
    ORGEditionV6 = 23,
    DomainEditionV6 = 24,
    LoctionAEditionV6 = 25,
    RegistrarEdition = 26,
    RegistrarEditionV6 = 27,
    UserTypeEdition = 28,
    UserTypeEditionV6 = 29,
    CityEditionRev1V6 = 30,
    CityEditionRev0V6 = 31,
    NetSpeedEditionRev1 = 32,
    NetSpeedEditionRev1V6 = 33,
    CountryConfEdition = 34,
    CityConfEdition = 35,
    RegionConfEdition = 36,
    PostalConfEdition = 37,
    AccuracyRadiusEditionV6 = 38
}

pub struct GeoIp {
    db: RawGeoIp
}

#[repr(C)]
pub struct GeoIpRecord {
    country_code: *const c_char,
    country_code3: *const c_char,
    country_name: *const c_char,
    region: *const c_char,
    city: *const c_char,
    postal_code: *const c_char,
    latitude: c_float,
    longitude: c_float,
    dma_code: c_int,
    area_code: c_int,
    charset: c_int,
    continent_code: *const c_char,
    netmask: c_int
}

#[deriving(Decodable, Encodable)]
pub struct ASInfo {
    pub asn: uint,
    pub name: String,
    pub netmask: uint
}

#[deriving(Decodable, Encodable)]
pub struct CityInfo {
    pub country_code: Option<String>,
    pub country_code3: Option<String>,
    pub country_name: Option<String>,
    pub region: Option<String>,
    pub city: Option<String>,
    pub postal_code: Option<String>,
    pub latitude: f32,
    pub longitude: f32,
    pub dma_code: uint,
    pub area_code: uint,
    pub charset: uint,
    pub continent_code: Option<String>,
    pub netmask: uint
}

unsafe fn maybe_string(c_str: *const c_char) -> Option<String> {
    c_str.as_ref().and_then(|opt| {
        CString::new(opt, false).as_str().map(|s| s.to_string())
    })
}

impl CityInfo {
    unsafe fn from_geoiprecord(res: &GeoIpRecord) -> CityInfo {
        CityInfo {
            country_code: maybe_string(res.country_code),
            country_code3: maybe_string(res.country_code3),
            country_name: maybe_string(res.country_name),
            region: maybe_string(res.region),
            city: maybe_string(res.city),
            postal_code: maybe_string(res.postal_code),
            latitude: res.latitude as f32,
            longitude: res.longitude as f32,
            dma_code: res.dma_code as uint,
            area_code: res.area_code as uint,
            charset: res.charset as uint,
            continent_code: maybe_string(res.continent_code),
            netmask: res.netmask as uint
        }
    }
}

impl fmt::Show for ASInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}\t{}", self.asn, self.name)
    }
}

enum CNetworkIp {
    V4(c_ulong),
    V6(In6Addr)
}

impl CNetworkIp {
    fn new(ip: IpAddr) -> CNetworkIp {
        match ip {
            Ipv4Addr(a, b, c, d) => {
                V4((a as c_ulong << 24) | (b as c_ulong << 16) |
                   (c as c_ulong << 8)  | (d as c_ulong))
            },
            Ipv6Addr(a, b, c, d, e, f, g, h) => {
                V6([(a >> 8) as u8, a as u8,
                    (b >> 8) as u8, b as u8,
                    (c >> 8) as u8, c as u8,
                    (d >> 8) as u8, d as u8,
                    (e >> 8) as u8, e as u8,
                    (f >> 8) as u8, f as u8,
                    (g >> 8) as u8, g as u8,
                    (h >> 8) as u8, h as u8])
            }
        }
    }
}

impl GeoIp {
    pub fn open(path: &Path, options: Options) -> Result<GeoIp, String> {
        let file = match path.as_str() {
            None => return Err(format!("Invalid path {}", path.display())),
            Some(file) => file
        };
        let db = unsafe {
            GeoIP_open(file.to_c_str().unwrap(), options as c_int)
        };
        if db.is_null() {
            return Err(format!("Can't open {}", file));
        }
        if unsafe { GeoIP_set_charset(db, UTF8 as c_int) } != 0 {
            return Err("Can't set charset to UTF8".to_string());
        }
        Ok(GeoIp { db: db })
    }

    pub fn city_info_by_ip(&self, ip: IpAddr) -> Option<CityInfo> {
        let cres = match CNetworkIp::new(ip) {
            V4(ip) => unsafe { GeoIP_record_by_ipnum(self.db, ip) },
            V6(ip) => unsafe { GeoIP_record_by_ipnum_v6(self.db, ip) }
        };

        if cres.is_null() { return None; }

        unsafe {
            let city_info = CityInfo::from_geoiprecord(&*cres);
            GeoIPRecord_delete(cres);
            std::mem::forget(cres);
            Some(city_info)
        }
    }

    pub fn as_info_by_ip(&self, ip: IpAddr) -> Option<ASInfo> {
        let gl = GeoIpLookup::new();
        let cres = match CNetworkIp::new(ip) {
            V4(ip) => unsafe { GeoIP_name_by_ipnum_gl(self.db, ip, &gl) },
            V6(ip) => unsafe { GeoIP_name_by_ipnum_v6_gl(self.db, ip, &gl) }
        };

        if cres.is_null() {
            return None;
        }
        let description_cstr = unsafe { CString::new(cres, true) };
        let description = match description_cstr.as_str() {
            None => return None,
            Some(description) => description
        };
        let mut di = description.splitn(1, ' ');
        let asn = match di.next() {
            None => return None,
            Some(asn) => {
                if ! asn.starts_with("AS") {
                    return None
                } else {
                    from_str::<uint>(asn.slice_from(2)).unwrap()
                }
            }
        };
        let name = di.next().unwrap_or("(none)");
        let as_info = ASInfo {
            asn: asn,
            name: name.to_string(),
            netmask: gl.netmask as uint
        };
        Some(as_info)
    }
}

impl Drop for GeoIp {
    fn drop(&mut self) {
        unsafe {
            GeoIP_delete(self.db);
        }
    }
}

#[test]
fn geoip_test_basic() {
    let geoip = match GeoIp::open(&from_str("/opt/geoip/GeoIPASNum.dat").unwrap(), MemoryCache) {
        Err(err) => panic!(err),
        Ok(geoip) => geoip
    };
    let ip = from_str("91.203.184.192").unwrap();
    let res = geoip.as_info_by_ip(ip).unwrap();
    assert!(res.asn == 41064);
    assert!(res.name.as_slice().contains("Telefun"));
    assert!(res.netmask == 22);
}

#[test]
fn geoip_test_city() {
    let geoip = match GeoIp::open(&from_str("/opt/geoip/GeoLiteCity.dat").unwrap(), MemoryCache) {
        Err(err) => panic!(err),
        Ok(geoip) => geoip
    };
    let ip = from_str("8.8.8.8").unwrap();
    let res = geoip.city_info_by_ip(ip).unwrap();
    assert!(res.city.unwrap().as_slice() == "Mountain View");
}
<commit_msg>gl is an outparam<commit_after>// (C)opyleft 2013,2014 Frank Denis

/*!
 * Bindings for the GeoIP library
 */
#![desc = "Bindings for the GeoIP library."]
#![license = "BSD"]
#![crate_name = "geoip"]
#![crate_type = "rlib"]

#![warn(non_camel_case_types,
        non_upper_case_globals,
        unused_qualifications)]

extern crate libc;
extern crate serialize;

use libc::{c_void, c_char, c_int, c_ulong, c_float};
use std::c_str::CString;
use std::fmt;
use std::io::net::ip::{IpAddr,Ipv4Addr,Ipv6Addr};

type RawGeoIp = *const c_void;
type In6Addr = [u8, ..16];

#[repr(C)]
struct GeoIpLookup {
    netmask: c_int
}

impl GeoIpLookup {
    fn new() -> GeoIpLookup {
        GeoIpLookup {
            netmask: 0
        }
    }
}

#[link(name = "GeoIP")]
extern {
    fn GeoIP_open(dbtype: *const c_char, flags: c_int) -> RawGeoIp;
    fn GeoIP_delete(db: RawGeoIp);
    fn GeoIP_name_by_ipnum_gl(db: RawGeoIp, ipnum: c_ulong, gl: *mut GeoIpLookup) -> *const c_char;
    fn GeoIP_name_by_ipnum_v6_gl(db: RawGeoIp, ipnum: In6Addr, gl: *mut GeoIpLookup) -> *const c_char;
    fn GeoIP_record_by_ipnum(db: RawGeoIp, ipnum: c_ulong) -> *const GeoIpRecord;
    fn GeoIP_record_by_ipnum_v6(db: RawGeoIp, ipnum: In6Addr) -> *const GeoIpRecord;
    fn GeoIPRecord_delete(gir: *const GeoIpRecord);
    fn GeoIP_set_charset(db: RawGeoIp, charset: c_int) -> c_int;
}

enum Charset {
    UTF8 = 1
}

pub enum Options {
    Standard = 0,
    MemoryCache = 1,
    CheckCache = 2,
    IndexCache = 4,
    MmapCache = 8
}

pub enum DBType {
    CountryEdition = 1,
    RegionEditionRev0 = 7,
    CityEditionRev0 = 6,
    ORGEdition = 5,
    ISPEdition = 4,
    CityEditionRev1 = 2,
    RegionEditionRev1 = 3,
    ProxyEdition = 8,
    ASNUMEdition = 9,
    NetSpeedEdition = 10,
    DomainEdition = 11,
    CountryEditionV6 = 12,
    LocationAEdition = 13,
    AccuracyRadiusEdition = 14,
    LargeCountryEdition = 17,
    LargeCountryEditionV6 = 18,
    ASNumEditionV6 = 21,
    ISPEditionV6 = 22,
    ORGEditionV6 = 23,
    DomainEditionV6 = 24,
    LoctionAEditionV6 = 25,
    RegistrarEdition = 26,
    RegistrarEditionV6 = 27,
    UserTypeEdition = 28,
    UserTypeEditionV6 = 29,
    CityEditionRev1V6 = 30,
    CityEditionRev0V6 = 31,
    NetSpeedEditionRev1 = 32,
    NetSpeedEditionRev1V6 = 33,
    CountryConfEdition = 34,
    CityConfEdition = 35,
    RegionConfEdition = 36,
    PostalConfEdition = 37,
    AccuracyRadiusEditionV6 = 38
}

pub struct GeoIp {
    db: RawGeoIp
}

#[repr(C)]
pub struct GeoIpRecord {
    country_code: *const c_char,
    country_code3: *const c_char,
    country_name: *const c_char,
    region: *const c_char,
    city: *const c_char,
    postal_code: *const c_char,
    latitude: c_float,
    longitude: c_float,
    dma_code: c_int,
    area_code: c_int,
    charset: c_int,
    continent_code: *const c_char,
    netmask: c_int
}

#[deriving(Decodable, Encodable)]
pub struct ASInfo {
    pub asn: uint,
    pub name: String,
    pub netmask: uint
}

#[deriving(Decodable, Encodable)]
pub struct CityInfo {
    pub country_code: Option<String>,
    pub country_code3: Option<String>,
    pub country_name: Option<String>,
    pub region: Option<String>,
    pub city: Option<String>,
    pub postal_code: Option<String>,
    pub latitude: f32,
    pub longitude: f32,
    pub dma_code: uint,
    pub area_code: uint,
    pub charset: uint,
    pub continent_code: Option<String>,
    pub netmask: uint
}

unsafe fn maybe_string(c_str: *const c_char) -> Option<String> {
    c_str.as_ref().and_then(|opt| {
        CString::new(opt, false).as_str().map(|s| s.to_string())
    })
}

impl CityInfo {
    unsafe fn from_geoiprecord(res: &GeoIpRecord) -> CityInfo {
        CityInfo {
            country_code: maybe_string(res.country_code),
            country_code3: maybe_string(res.country_code3),
            country_name: maybe_string(res.country_name),
            region: maybe_string(res.region),
            city: maybe_string(res.city),
            postal_code: maybe_string(res.postal_code),
            latitude: res.latitude as f32,
            longitude: res.longitude as f32,
            dma_code: res.dma_code as uint,
            area_code: res.area_code as uint,
            charset: res.charset as uint,
            continent_code: maybe_string(res.continent_code),
            netmask: res.netmask as uint
        }
    }
}

impl fmt::Show for ASInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}\t{}", self.asn, self.name)
    }
}

enum CNetworkIp {
    V4(c_ulong),
    V6(In6Addr)
}

impl CNetworkIp {
    fn new(ip: IpAddr) -> CNetworkIp {
        match ip {
            Ipv4Addr(a, b, c, d) => {
                V4((a as c_ulong << 24) | (b as c_ulong << 16) |
                   (c as c_ulong << 8)  | (d as c_ulong))
            },
            Ipv6Addr(a, b, c, d, e, f, g, h) => {
                V6([(a >> 8) as u8, a as u8,
                    (b >> 8) as u8, b as u8,
                    (c >> 8) as u8, c as u8,
                    (d >> 8) as u8, d as u8,
                    (e >> 8) as u8, e as u8,
                    (f >> 8) as u8, f as u8,
                    (g >> 8) as u8, g as u8,
                    (h >> 8) as u8, h as u8])
            }
        }
    }
}

impl GeoIp {
    pub fn open(path: &Path, options: Options) -> Result<GeoIp, String> {
        let file = match path.as_str() {
            None => return Err(format!("Invalid path {}", path.display())),
            Some(file) => file
        };
        let db = unsafe {
            GeoIP_open(file.to_c_str().unwrap(), options as c_int)
        };
        if db.is_null() {
            return Err(format!("Can't open {}", file));
        }
        if unsafe { GeoIP_set_charset(db, UTF8 as c_int) } != 0 {
            return Err("Can't set charset to UTF8".to_string());
        }
        Ok(GeoIp { db: db })
    }

    pub fn city_info_by_ip(&self, ip: IpAddr) -> Option<CityInfo> {
        let cres = match CNetworkIp::new(ip) {
            V4(ip) => unsafe { GeoIP_record_by_ipnum(self.db, ip) },
            V6(ip) => unsafe { GeoIP_record_by_ipnum_v6(self.db, ip) }
        };

        if cres.is_null() { return None; }

        unsafe {
            let city_info = CityInfo::from_geoiprecord(&*cres);
            GeoIPRecord_delete(cres);
            std::mem::forget(cres);
            Some(city_info)
        }
    }

    pub fn as_info_by_ip(&self, ip: IpAddr) -> Option<ASInfo> {
        let mut gl = GeoIpLookup::new();
        let cres = match CNetworkIp::new(ip) {
            V4(ip) => unsafe { GeoIP_name_by_ipnum_gl(self.db, ip, &mut gl) },
            V6(ip) => unsafe { GeoIP_name_by_ipnum_v6_gl(self.db, ip, &mut gl) }
        };

        if cres.is_null() {
            return None;
        }
        let description_cstr = unsafe { CString::new(cres, true) };
        let description = match description_cstr.as_str() {
            None => return None,
            Some(description) => description
        };
        let mut di = description.splitn(1, ' ');
        let asn = match di.next() {
            None => return None,
            Some(asn) => {
                if ! asn.starts_with("AS") {
                    return None
                } else {
                    from_str::<uint>(asn.slice_from(2)).unwrap()
                }
            }
        };
        let name = di.next().unwrap_or("(none)");
        let as_info = ASInfo {
            asn: asn,
            name: name.to_string(),
            netmask: gl.netmask as uint
        };
        Some(as_info)
    }
}

impl Drop for GeoIp {
    fn drop(&mut self) {
        unsafe {
            GeoIP_delete(self.db);
        }
    }
}

#[test]
fn geoip_test_basic() {
    let geoip = match GeoIp::open(&from_str("/opt/geoip/GeoIPASNum.dat").unwrap(), MemoryCache) {
        Err(err) => panic!(err),
        Ok(geoip) => geoip
    };
    let ip = from_str("91.203.184.192").unwrap();
    let res = geoip.as_info_by_ip(ip).unwrap();
    assert!(res.asn == 41064);
    assert!(res.name.as_slice().contains("Telefun"));
    assert!(res.netmask == 22);
}

#[test]
fn geoip_test_city() {
    let geoip = match GeoIp::open(&from_str("/opt/geoip/GeoLiteCity.dat").unwrap(), MemoryCache) {
        Err(err) => panic!(err),
        Ok(geoip) => geoip
    };
    let ip = from_str("8.8.8.8").unwrap();
    let res = geoip.city_info_by_ip(ip).unwrap();
    assert!(res.city.unwrap().as_slice() == "Mountain View");
}
<|endoftext|>


<commit_before>//! Enum grouping the most useful geometric shapes.

use std::raw::TraitObject;
use std::intrinsics::TypeId;
use std::cast;
use std::any::{Any, AnyRefExt};
use ray::{Ray, RayCast};
use volumetric::Volumetric;
use bounding_volume::{HasAABB, AABB};
use math::Matrix;

/// Trait implemented by each geometry supported by `ncollide`.
pub trait Geom : Volumetric  +
                 HasAABB     +
                 RayCast     +
                 Any {
    /// Duplicates (clones) this geometry.
    fn duplicate(&self) -> Box<Geom:Send>;
}

/// Trait implemented by concave, composite geometries supported by `ncollide`.
///
/// A composite geometry is composed of several `Geom`. Typically, it is a convex decomposition of
/// a concave geometry.
pub trait ConcaveGeom : Geom {
    /// Applies a function to each sub-geometry of this concave geometry.
    fn map_part_at<T>(&self, uint, |&Matrix, &Geom| -> T) -> T;
    /// Applies a transformation matrix and a function to each sub-geometry of this concave
    /// geometry.
    fn map_transformed_part_at<T>(&self, m: &Matrix, uint, |&Matrix, &Geom| -> T) -> T;

    // FIXME: replace those by a visitor?
    /// Computes the indices of every sub-geometry which might intersect a given AABB.
    fn approx_interferences_with_aabb(&self, &AABB, &mut Vec<uint>);
    /// Computes the indices of every sub-geometry which might intersect a given Ray.
    fn approx_interferences_with_ray(&self, &Ray, &mut Vec<uint>);
    // FIXME: kind of ad-hoc…
    /// Gets the AABB of the geometry identified by the index `i`.
    fn aabb_at<'a>(&'a self, i: uint) -> &'a AABB;
}

impl<T: 'static + Send + Clone + Volumetric + HasAABB + RayCast + Any>
Geom for T {
    fn duplicate(&self) -> Box<Geom:Send> {
        (box self.clone()) as Box<Geom:Send>
    }
}
// FIXME: we need to implement that since AnyRefExt is only implemented for Any, and it does not
// seem possible to convert a &Geom to a &Any…
impl<'a> AnyRefExt<'a> for &'a Geom {
    #[inline]
    fn is<T: 'static>(self) -> bool {
        // Get TypeId of the type this function is instantiated with
        let t = TypeId::of::<T>();

        // Get TypeId of the type in the trait object
        let boxed = self.get_type_id();

        // Compare both TypeIds on equality
        t == boxed
    }

    #[inline]
    fn as_ref<T: 'static>(self) -> Option<&'a T> {
        if self.is::<T>() {
            unsafe {
                let to: TraitObject = cast::transmute_copy(&self);

                Some(cast::transmute(to.data))
            }
        } else {
            None
        }
    }
}
<commit_msg>Update to latest rust<commit_after>//! Enum grouping the most useful geometric shapes.

use std::raw::TraitObject;
use std::intrinsics::TypeId;
use std::mem;
use std::any::{Any, AnyRefExt};
use ray::{Ray, RayCast};
use volumetric::Volumetric;
use bounding_volume::{HasAABB, AABB};
use math::Matrix;

/// Trait implemented by each geometry supported by `ncollide`.
pub trait Geom : Volumetric  +
                 HasAABB     +
                 RayCast     +
                 Any {
    /// Duplicates (clones) this geometry.
    fn duplicate(&self) -> Box<Geom:Send>;
}

/// Trait implemented by concave, composite geometries supported by `ncollide`.
///
/// A composite geometry is composed of several `Geom`. Typically, it is a convex decomposition of
/// a concave geometry.
pub trait ConcaveGeom : Geom {
    /// Applies a function to each sub-geometry of this concave geometry.
    fn map_part_at<T>(&self, uint, |&Matrix, &Geom| -> T) -> T;
    /// Applies a transformation matrix and a function to each sub-geometry of this concave
    /// geometry.
    fn map_transformed_part_at<T>(&self, m: &Matrix, uint, |&Matrix, &Geom| -> T) -> T;

    // FIXME: replace those by a visitor?
    /// Computes the indices of every sub-geometry which might intersect a given AABB.
    fn approx_interferences_with_aabb(&self, &AABB, &mut Vec<uint>);
    /// Computes the indices of every sub-geometry which might intersect a given Ray.
    fn approx_interferences_with_ray(&self, &Ray, &mut Vec<uint>);
    // FIXME: kind of ad-hoc…
    /// Gets the AABB of the geometry identified by the index `i`.
    fn aabb_at<'a>(&'a self, i: uint) -> &'a AABB;
}

impl<T: 'static + Send + Clone + Volumetric + HasAABB + RayCast + Any>
Geom for T {
    fn duplicate(&self) -> Box<Geom:Send> {
        (box self.clone()) as Box<Geom:Send>
    }
}
// FIXME: we need to implement that since AnyRefExt is only implemented for Any, and it does not
// seem possible to convert a &Geom to a &Any…
impl<'a> AnyRefExt<'a> for &'a Geom {
    #[inline]
    fn is<T: 'static>(self) -> bool {
        // Get TypeId of the type this function is instantiated with
        let t = TypeId::of::<T>();

        // Get TypeId of the type in the trait object
        let boxed = self.get_type_id();

        // Compare both TypeIds on equality
        t == boxed
    }

    #[inline]
    fn as_ref<T: 'static>(self) -> Option<&'a T> {
        if self.is::<T>() {
            unsafe {
                let to: TraitObject = mem::transmute_copy(&self);

                Some(mem::transmute(to.data))
            }
        } else {
            None
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2013-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.

//! Interfaces to the operating system provided random number
//! generators.

pub use self::imp::OsRng;

#[cfg(all(unix, not(target_os = "ios")))]
mod imp {
    use io::{IoResult, File};
    use path::Path;
    use rand::Rng;
    use rand::reader::ReaderRng;
    use result::{Ok, Err};

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    #[cfg(unix)]
    pub struct OsRng {
        inner: ReaderRng<File>
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            let reader = try!(File::open(&Path::new("/dev/urandom")));
            let reader_rng = ReaderRng::new(reader);

            Ok(OsRng { inner: reader_rng })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            self.inner.next_u32()
        }
        fn next_u64(&mut self) -> u64 {
            self.inner.next_u64()
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            self.inner.fill_bytes(v)
        }
    }
}

#[cfg(target_os = "ios")]
mod imp {
    extern crate libc;

    use collections::Collection;
    use io::{IoResult};
    use kinds::marker;
    use mem;
    use os;
    use rand::Rng;
    use result::{Ok};
    use self::libc::{c_int, size_t};
    use slice::MutableSlice;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    pub struct OsRng {
        marker: marker::NoCopy
    }

    #[repr(C)]
    struct SecRandom;

    static kSecRandomDefault: *const SecRandom = 0 as *const SecRandom;

    #[link(name = "Security", kind = "framework")]
    extern "C" {
        fn SecRandomCopyBytes(rnd: *const SecRandom,
                              count: size_t, bytes: *mut u8) -> c_int;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            Ok(OsRng {marker: marker::NoCopy} )
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 8];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t, v.as_mut_ptr())
            };
            if ret == -1 {
                fail!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    extern crate libc;

    use core_collections::Collection;
    use io::{IoResult, IoError};
    use mem;
    use ops::Drop;
    use os;
    use rand::Rng;
    use result::{Ok, Err};
    use self::libc::{DWORD, BYTE, LPCSTR, BOOL};
    use self::libc::types::os::arch::extra::{LONG_PTR};
    use slice::MutableSlice;

    type HCRYPTPROV = LONG_PTR;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    ///
    /// This does not block.
    pub struct OsRng {
        hcryptprov: HCRYPTPROV
    }

    static PROV_RSA_FULL: DWORD = 1;
    static CRYPT_SILENT: DWORD = 64;
    static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;

    #[allow(non_snake_case)]
    extern "system" {
        fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
                                pszContainer: LPCSTR,
                                pszProvider: LPCSTR,
                                dwProvType: DWORD,
                                dwFlags: DWORD) -> BOOL;
        fn CryptGenRandom(hProv: HCRYPTPROV,
                          dwLen: DWORD,
                          pbBuffer: *mut BYTE) -> BOOL;
        fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            let mut hcp = 0;
            let ret = unsafe {
                CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
                                     PROV_RSA_FULL,
                                     CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
            };

            if ret == 0 {
                Err(IoError::last_error())
            } else {
                Ok(OsRng { hcryptprov: hcp })
            }
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 8];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                CryptGenRandom(self.hcryptprov, v.len() as DWORD,
                               v.as_mut_ptr())
            };
            if ret == 0 {
                fail!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }

    impl Drop for OsRng {
        fn drop(&mut self) {
            let ret = unsafe {
                CryptReleaseContext(self.hcryptprov, 0)
            };
            if ret == 0 {
                fail!("couldn't release context: {}", os::last_os_error());
            }
        }
    }
}

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

    use super::OsRng;
    use rand::Rng;
    use task;

    #[test]
    fn test_os_rng() {
        let mut r = OsRng::new().unwrap();

        r.next_u32();
        r.next_u64();

        let mut v = [0u8, .. 1000];
        r.fill_bytes(v);
    }

    #[test]
    fn test_os_rng_tasks() {

        let mut txs = vec!();
        for _ in range(0u, 20) {
            let (tx, rx) = channel();
            txs.push(tx);
            task::spawn(proc() {
                // wait until all the tasks are ready to go.
                rx.recv();

                // deschedule to attempt to interleave things as much
                // as possible (XXX: is this a good test?)
                let mut r = OsRng::new().unwrap();
                task::deschedule();
                let mut v = [0u8, .. 1000];

                for _ in range(0u, 100) {
                    r.next_u32();
                    task::deschedule();
                    r.next_u64();
                    task::deschedule();
                    r.fill_bytes(v);
                    task::deschedule();
                }
            })
        }

        // start all the tasks
        for tx in txs.iter() {
            tx.send(())
        }
    }
}
<commit_msg>Fixed iOS build (statics name lint)<commit_after>// Copyright 2013-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.

//! Interfaces to the operating system provided random number
//! generators.

pub use self::imp::OsRng;

#[cfg(all(unix, not(target_os = "ios")))]
mod imp {
    use io::{IoResult, File};
    use path::Path;
    use rand::Rng;
    use rand::reader::ReaderRng;
    use result::{Ok, Err};

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    #[cfg(unix)]
    pub struct OsRng {
        inner: ReaderRng<File>
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            let reader = try!(File::open(&Path::new("/dev/urandom")));
            let reader_rng = ReaderRng::new(reader);

            Ok(OsRng { inner: reader_rng })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            self.inner.next_u32()
        }
        fn next_u64(&mut self) -> u64 {
            self.inner.next_u64()
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            self.inner.fill_bytes(v)
        }
    }
}

#[cfg(target_os = "ios")]
mod imp {
    extern crate libc;

    use collections::Collection;
    use io::{IoResult};
    use kinds::marker;
    use mem;
    use os;
    use rand::Rng;
    use result::{Ok};
    use self::libc::{c_int, size_t};
    use slice::MutableSlice;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    pub struct OsRng {
        marker: marker::NoCopy
    }

    #[repr(C)]
    struct SecRandom;

    #[allow(non_uppercase_statics)]
    static kSecRandomDefault: *const SecRandom = 0 as *const SecRandom;

    #[link(name = "Security", kind = "framework")]
    extern "C" {
        fn SecRandomCopyBytes(rnd: *const SecRandom,
                              count: size_t, bytes: *mut u8) -> c_int;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            Ok(OsRng {marker: marker::NoCopy} )
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 8];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t, v.as_mut_ptr())
            };
            if ret == -1 {
                fail!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    extern crate libc;

    use core_collections::Collection;
    use io::{IoResult, IoError};
    use mem;
    use ops::Drop;
    use os;
    use rand::Rng;
    use result::{Ok, Err};
    use self::libc::{DWORD, BYTE, LPCSTR, BOOL};
    use self::libc::types::os::arch::extra::{LONG_PTR};
    use slice::MutableSlice;

    type HCRYPTPROV = LONG_PTR;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    ///
    /// This does not block.
    pub struct OsRng {
        hcryptprov: HCRYPTPROV
    }

    static PROV_RSA_FULL: DWORD = 1;
    static CRYPT_SILENT: DWORD = 64;
    static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;

    #[allow(non_snake_case)]
    extern "system" {
        fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
                                pszContainer: LPCSTR,
                                pszProvider: LPCSTR,
                                dwProvType: DWORD,
                                dwFlags: DWORD) -> BOOL;
        fn CryptGenRandom(hProv: HCRYPTPROV,
                          dwLen: DWORD,
                          pbBuffer: *mut BYTE) -> BOOL;
        fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            let mut hcp = 0;
            let ret = unsafe {
                CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
                                     PROV_RSA_FULL,
                                     CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
            };

            if ret == 0 {
                Err(IoError::last_error())
            } else {
                Ok(OsRng { hcryptprov: hcp })
            }
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 8];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                CryptGenRandom(self.hcryptprov, v.len() as DWORD,
                               v.as_mut_ptr())
            };
            if ret == 0 {
                fail!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }

    impl Drop for OsRng {
        fn drop(&mut self) {
            let ret = unsafe {
                CryptReleaseContext(self.hcryptprov, 0)
            };
            if ret == 0 {
                fail!("couldn't release context: {}", os::last_os_error());
            }
        }
    }
}

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

    use super::OsRng;
    use rand::Rng;
    use task;

    #[test]
    fn test_os_rng() {
        let mut r = OsRng::new().unwrap();

        r.next_u32();
        r.next_u64();

        let mut v = [0u8, .. 1000];
        r.fill_bytes(v);
    }

    #[test]
    fn test_os_rng_tasks() {

        let mut txs = vec!();
        for _ in range(0u, 20) {
            let (tx, rx) = channel();
            txs.push(tx);
            task::spawn(proc() {
                // wait until all the tasks are ready to go.
                rx.recv();

                // deschedule to attempt to interleave things as much
                // as possible (XXX: is this a good test?)
                let mut r = OsRng::new().unwrap();
                task::deschedule();
                let mut v = [0u8, .. 1000];

                for _ in range(0u, 100) {
                    r.next_u32();
                    task::deschedule();
                    r.next_u64();
                    task::deschedule();
                    r.fill_bytes(v);
                    task::deschedule();
                }
            })
        }

        // start all the tasks
        for tx in txs.iter() {
            tx.send(())
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Add remove::remove_tag()<commit_after>
use libimagstore::store::Entry;

use result::Result;
use tag::Tag;

pub fn remove_tag(e: &Entry, t: &Tag) -> Result<()> {
    unimplemented!()
}
<|endoftext|>


<commit_before>#[repr(C)]
#[derive(Copy, Clone)]
struct Foo {
    a: u64,
    b: u64,
    c: u64,
}

fn main() {
    const LENGTH: usize = 10;
    let mut v: [u64; LENGTH] = [0; LENGTH];

    for idx in 0..LENGTH {
        assert_eq!(v[idx], 0);
    }

    unsafe {
        let p = v.as_mut_ptr();
        ::std::ptr::write_bytes(p, 0xab, LENGTH);
    }

    for idx in 0..LENGTH {
        assert_eq!(v[idx], 0xabababababababab);
    }

    // -----

    let mut w: [Foo; LENGTH] = [Foo { a: 0, b: 0, c: 0 }; LENGTH];
    for idx in 0..LENGTH {
        assert_eq!(w[idx].a, 0);
        assert_eq!(w[idx].b, 0);
        assert_eq!(w[idx].c, 0);
    }

    unsafe {
        let p = w.as_mut_ptr();
        ::std::ptr::write_bytes(p, 0xcd, LENGTH);
    }

    for idx in 0..LENGTH {
        assert_eq!(w[idx].a, 0xcdcdcdcdcdcdcdcd);
        assert_eq!(w[idx].b, 0xcdcdcdcdcdcdcdcd);
        assert_eq!(w[idx].c, 0xcdcdcdcdcdcdcdcd);
    }
}
<commit_msg>Add test for `volatile_set_memory`<commit_after>#![feature(core_intrinsics)] // for `volatile_set_memory`

#[repr(C)]
#[derive(Copy, Clone)]
struct Foo {
    a: u64,
    b: u64,
    c: u64,
}

fn main() {
    const LENGTH: usize = 10;
    let mut v: [u64; LENGTH] = [0; LENGTH];

    for idx in 0..LENGTH {
        assert_eq!(v[idx], 0);
    }

    unsafe {
        let p = v.as_mut_ptr();
        ::std::ptr::write_bytes(p, 0xab, LENGTH);
    }

    for idx in 0..LENGTH {
        assert_eq!(v[idx], 0xabababababababab);
    }

    // -----

    let mut w: [Foo; LENGTH] = [Foo { a: 0, b: 0, c: 0 }; LENGTH];
    for idx in 0..LENGTH {
        assert_eq!(w[idx].a, 0);
        assert_eq!(w[idx].b, 0);
        assert_eq!(w[idx].c, 0);
    }

    unsafe {
        let p = w.as_mut_ptr();
        ::std::ptr::write_bytes(p, 0xcd, LENGTH);
    }

    for idx in 0..LENGTH {
        assert_eq!(w[idx].a, 0xcdcdcdcdcdcdcdcd);
        assert_eq!(w[idx].b, 0xcdcdcdcdcdcdcdcd);
        assert_eq!(w[idx].c, 0xcdcdcdcdcdcdcdcd);
    }

    // -----
    // `std::intrinsics::volatile_set_memory` should behave identically

    let mut v: [u64; LENGTH] = [0; LENGTH];

    for idx in 0..LENGTH {
        assert_eq!(v[idx], 0);
    }

    unsafe {
        let p = v.as_mut_ptr();
        ::std::intrinsics::volatile_set_memory(p, 0xab, LENGTH);
    }

    for idx in 0..LENGTH {
        assert_eq!(v[idx], 0xabababababababab);
    }

    // -----

    let mut w: [Foo; LENGTH] = [Foo { a: 0, b: 0, c: 0 }; LENGTH];
    for idx in 0..LENGTH {
        assert_eq!(w[idx].a, 0);
        assert_eq!(w[idx].b, 0);
        assert_eq!(w[idx].c, 0);
    }

    unsafe {
        let p = w.as_mut_ptr();
        ::std::intrinsics::volatile_set_memory(p, 0xcd, LENGTH);
    }

    for idx in 0..LENGTH {
        assert_eq!(w[idx].a, 0xcdcdcdcdcdcdcdcd);
        assert_eq!(w[idx].b, 0xcdcdcdcdcdcdcdcd);
        assert_eq!(w[idx].c, 0xcdcdcdcdcdcdcdcd);
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2022, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

#[allow(unused)]
/// Find k-means for a sorted slice of integers that can be summed in `i64`.
pub fn kmeans<T, const N: usize>(data: &[T]) -> [T; N]
where
  T: Copy,
  T: Into<i64>,
  T: PartialEq,
  T: PartialOrd,
  i64: TryInto<T>,
  <i64 as std::convert::TryInto<T>>::Error: std::fmt::Debug,
{
  let mut low = {
    let mut i = 0..N;
    [(); N].map(|_| (i.next().unwrap() * (data.len() - 1)) / (N - 1))
  };
  let mut centroids = low.map(|i| unsafe { *data.get_unchecked(i) });
  let mut high = low;
  let mut sum = [0i64; N];
  high[N - 1] = data.len();
  sum[N - 1] = centroids[N - 1].into();

  let data_to = |n: usize| unsafe { data.get_unchecked(..n) }.iter();
  let data_from = |n: usize| unsafe { data.get_unchecked(n..) }.iter();

  // Constrain complexity to O(n log n)
  let limit = 2 * (usize::BITS - data.len().leading_zeros());
  for _ in 0..limit {
    for (i, (threshold, (low, high))) in
      (centroids.iter().skip(1).zip(&centroids))
        .map(|(&c1, &c2)| unsafe {
          ((c1.into() + c2.into() + 1) >> 1).try_into().unwrap_unchecked()
        })
        .zip(low.iter_mut().skip(1).zip(&mut high))
        .enumerate()
    {
      let mut n = *high;
      let mut s = sum[i];
      for &d in data_to(n).rev().take_while(|&d| *d > threshold) {
        s -= d.into();
        n -= 1;
      }
      for &d in data_from(n).take_while(|&d| *d <= threshold) {
        s += d.into();
        n += 1;
      }
      *high = n;
      sum[i] = s;

      let mut n = *low;
      let mut s = sum[i + 1];
      for &d in data_from(n).take_while(|&d| *d < threshold) {
        s -= d.into();
        n += 1;
      }
      for &d in data_to(n).rev().take_while(|&d| *d >= threshold) {
        s += d.into();
        n -= 1;
      }
      *low = n;
      sum[i + 1] = s;
    }
    let mut changed = false;
    for (c, (sum, (high, low))) in
      centroids.iter_mut().zip(sum.iter().zip(high.iter().zip(low)))
    {
      let count = (high - low) as i64;
      if count == 0 {
        continue;
      }
      let new_centroid = unsafe {
        ((sum + (count >> 1)).saturating_div(count))
          .try_into()
          .unwrap_unchecked()
      };
      changed |= *c != new_centroid;
      *c = new_centroid;
    }
    if !changed {
      break;
    }
  }

  centroids
}

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

  #[test]
  fn three_means() {
    let mut data = [1, 2, 3, 10, 11, 12, 20, 21, 22];
    data.sort_unstable();
    let centroids = kmeans(&data);
    assert_eq!(centroids, [2, 11, 21]);
  }

  #[test]
  fn four_means() {
    let mut data = [30, 31, 32, 1, 2, 3, 10, 11, 12, 20, 21, 22];
    data.sort_unstable();
    let centroids = kmeans(&data);
    assert_eq!(centroids, [2, 11, 21, 31]);
  }
}
<commit_msg>kmeans: Tidy up all but the inner loop<commit_after>// Copyright (c) 2022, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

/// Find k-means for a sorted slice of integers that can be summed in `i64`.
pub fn kmeans<T, const K: usize>(data: &[T]) -> [T; K]
where
  T: Copy,
  T: Into<i64>,
  T: PartialEq,
  T: PartialOrd,
  i64: TryInto<T>,
  <i64 as std::convert::TryInto<T>>::Error: std::fmt::Debug,
{
  let mut low = {
    let mut i = 0..K;
    [(); K].map(|_| (i.next().unwrap() * (data.len() - 1)) / (K - 1))
  };
  let mut means = low.map(|i| unsafe { *data.get_unchecked(i) });
  let mut high = low;
  let mut sum = [0i64; K];
  high[K - 1] = data.len();
  sum[K - 1] = means[K - 1].into();

  let data_to = |n: usize| unsafe { data.get_unchecked(..n) }.iter();
  let data_from = |n: usize| unsafe { data.get_unchecked(n..) }.iter();

  // Constrain complexity to O(n log n)
  let limit = 2 * (usize::BITS - data.len().leading_zeros());
  for _ in 0..limit {
    for (i, (threshold, (low, high))) in (means.iter().skip(1).zip(&means))
      .map(|(&c1, &c2)| unsafe {
        ((c1.into() + c2.into() + 1) >> 1).try_into().unwrap_unchecked()
      })
      .zip(low.iter_mut().skip(1).zip(&mut high))
      .enumerate()
    {
      let mut n = *high;
      let mut s = sum[i];
      for &d in data_to(n).rev().take_while(|&d| *d > threshold) {
        s -= d.into();
        n -= 1;
      }
      for &d in data_from(n).take_while(|&d| *d <= threshold) {
        s += d.into();
        n += 1;
      }
      *high = n;
      sum[i] = s;

      let mut n = *low;
      let mut s = sum[i + 1];
      for &d in data_from(n).take_while(|&d| *d < threshold) {
        s -= d.into();
        n += 1;
      }
      for &d in data_to(n).rev().take_while(|&d| *d >= threshold) {
        s += d.into();
        n -= 1;
      }
      *low = n;
      sum[i + 1] = s;
    }
    let mut changed = false;
    for (((m, sum), high), low) in
      means.iter_mut().zip(&sum).zip(&high).zip(&low)
    {
      let count = (high - low) as i64;
      if count == 0 {
        continue;
      }
      let new_mean = unsafe {
        ((sum + (count >> 1)).saturating_div(count))
          .try_into()
          .unwrap_unchecked()
      };
      changed |= *m != new_mean;
      *m = new_mean;
    }
    if !changed {
      break;
    }
  }

  means
}

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

  #[test]
  fn three_means() {
    let mut data = [1, 2, 3, 10, 11, 12, 20, 21, 22];
    data.sort_unstable();
    let centroids = kmeans(&data);
    assert_eq!(centroids, [2, 11, 21]);
  }

  #[test]
  fn four_means() {
    let mut data = [30, 31, 32, 1, 2, 3, 10, 11, 12, 20, 21, 22];
    data.sort_unstable();
    let centroids = kmeans(&data);
    assert_eq!(centroids, [2, 11, 21, 31]);
  }
}
<|endoftext|>


<commit_before>mod crc;
#[macro_use]
mod macros;
mod types;

pub use self::crc::{crc8, crc16};
pub use self::types::{ErrorKind, ByteStream, ReadStream};

use nom::IResult;
use metadata::{Metadata, metadata_parser};

/// An interface for parsing through some type of producer to a byte stream.
///
/// External parsers get passed in and consumes the bytes held internally
/// and outputs the `Result` of that parser.
pub trait StreamProducer {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T>;
}

// Convert one to four byte slices into an unsigned 32-bit number.
//
// NOTE: This assumes big-endian since most numbers in the FLAC binary are
// that endianness.
#[inline]
pub fn to_u32(bytes: &[u8]) -> u32 {
  let length = bytes.len();

  debug_assert!(length <= 4);

  (0..length).fold(0, |result, i|
    result + ((bytes[i] as u32) << ((length - 1 - i) * 8))
  )
}

// Extends a signed value of a specific bit size to a larger bit size.
//
// NOTE: This assumes that the larger bit size will be 32 bit since that is
// the largest sample size supported in FLAC.
pub fn extend_sign(value: u32, bit_count: usize) -> i32 {
  if bit_count >= 32 || value < (1 << (bit_count - 1)) {
    value as i32
  } else {
    (value as i32).wrapping_sub(1 << bit_count)
  }
}

fn parser<'a>(input: &'a [u8], is_start: &mut bool)
              -> IResult<&'a [u8], Metadata> {
  let mut slice = input;

  if *is_start {
    let (i, _) = try_parse!(slice, tag!("fLaC"));

    slice     = i;
    *is_start = false;
  }

  metadata_parser(slice)
}

pub fn many_metadata<S, F>(stream: &mut S, mut f: F) -> bool
 where S: StreamProducer,
       F: FnMut(Metadata) {
  let mut is_start = true;
  let mut is_error = false;

  loop {
    match stream.parse(|i| parser(i, &mut is_start)) {
      Ok(block)                => {
        let is_last = block.is_last;

        f(block);

        if is_last {
          break;
        }
      }
      Err(ErrorKind::Continue) => continue,
      Err(_)                   => {
        is_error = true;

        break;
      }
    }
  }

  is_error
}

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

  #[test]
  #[should_panic]
  fn test_panic_to_u32() {
    to_u32(&[0x00, 0x00, 0x00, 0x00, 0x00]);
  }

  #[test]
  fn test_to_u32() {
    let bytes = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];

    assert_eq!(to_u32(&bytes[0..1]), 0x00000001);
    assert_eq!(to_u32(&bytes[3..5]), 0x00006789);
    assert_eq!(to_u32(&bytes[1..4]), 0x00234567);
    assert_eq!(to_u32(&bytes[4..]), 0x89abcdef);
  }

  #[test]
  fn test_extend_sign() {
    assert_eq!(extend_sign(32, 6), -32);
    assert_eq!(extend_sign(31, 6), 31);
    assert_eq!(extend_sign(128, 8), -128);
    assert_eq!(extend_sign(127, 8), 127);

    assert_eq!(extend_sign(2048, 12), -2048);
    assert_eq!(extend_sign(2047, 12), 2047);
    assert_eq!(extend_sign(32768, 16), -32768);
    assert_eq!(extend_sign(32767, 16), 32767);

    assert_eq!(extend_sign(8388608, 24), -8388608);
    assert_eq!(extend_sign(8388607, 24), 8388607);
    assert_eq!(extend_sign(2147483648, 32), -2147483648);
    assert_eq!(extend_sign(2147483647, 32), 2147483647);
  }
}
<commit_msg>Change is_state to a parser state<commit_after>mod crc;
#[macro_use]
mod macros;
mod types;

pub use self::crc::{crc8, crc16};
pub use self::types::{ErrorKind, ByteStream, ReadStream};

use nom::IResult;
use metadata::{Metadata, metadata_parser};

/// An interface for parsing through some type of producer to a byte stream.
///
/// External parsers get passed in and consumes the bytes held internally
/// and outputs the `Result` of that parser.
pub trait StreamProducer {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T>;
}

// Convert one to four byte slices into an unsigned 32-bit number.
//
// NOTE: This assumes big-endian since most numbers in the FLAC binary are
// that endianness.
#[inline]
pub fn to_u32(bytes: &[u8]) -> u32 {
  let length = bytes.len();

  debug_assert!(length <= 4);

  (0..length).fold(0, |result, i|
    result + ((bytes[i] as u32) << ((length - 1 - i) * 8))
  )
}

// Extends a signed value of a specific bit size to a larger bit size.
//
// NOTE: This assumes that the larger bit size will be 32 bit since that is
// the largest sample size supported in FLAC.
pub fn extend_sign(value: u32, bit_count: usize) -> i32 {
  if bit_count >= 32 || value < (1 << (bit_count - 1)) {
    value as i32
  } else {
    (value as i32).wrapping_sub(1 << bit_count)
  }
}

#[derive(PartialEq, Eq)]
enum ParserState {
  Header,
  StreamInfo,
  Metadata
}

fn parser<'a>(input: &'a [u8], state: &mut ParserState)
              -> IResult<&'a [u8], Metadata> {
  let mut slice = input;

  if *state == ParserState::Header {
    let (i, _) = try_parse!(slice, tag!("fLaC"));

    slice  = i;
    *state = ParserState::StreamInfo;
  }

  metadata_parser(slice)
}

pub fn many_metadata<S, F>(stream: &mut S, mut f: F) -> bool
 where S: StreamProducer,
       F: FnMut(Metadata) {
  let mut state    = ParserState::Header;
  let mut is_error = false;

  loop {
    match stream.parse(|i| parser(i, &mut state)) {
      Ok(block)                => {
        let is_last = block.is_last;

        f(block);

        if is_last {
          break;
        }
      }
      Err(ErrorKind::Continue) => continue,
      Err(_)                   => {
        is_error = true;

        break;
      }
    }
  }

  is_error
}

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

  #[test]
  #[should_panic]
  fn test_panic_to_u32() {
    to_u32(&[0x00, 0x00, 0x00, 0x00, 0x00]);
  }

  #[test]
  fn test_to_u32() {
    let bytes = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];

    assert_eq!(to_u32(&bytes[0..1]), 0x00000001);
    assert_eq!(to_u32(&bytes[3..5]), 0x00006789);
    assert_eq!(to_u32(&bytes[1..4]), 0x00234567);
    assert_eq!(to_u32(&bytes[4..]), 0x89abcdef);
  }

  #[test]
  fn test_extend_sign() {
    assert_eq!(extend_sign(32, 6), -32);
    assert_eq!(extend_sign(31, 6), 31);
    assert_eq!(extend_sign(128, 8), -128);
    assert_eq!(extend_sign(127, 8), 127);

    assert_eq!(extend_sign(2048, 12), -2048);
    assert_eq!(extend_sign(2047, 12), 2047);
    assert_eq!(extend_sign(32768, 16), -32768);
    assert_eq!(extend_sign(32767, 16), 32767);

    assert_eq!(extend_sign(8388608, 24), -8388608);
    assert_eq!(extend_sign(8388607, 24), 8388607);
    assert_eq!(extend_sign(2147483648, 32), -2147483648);
    assert_eq!(extend_sign(2147483647, 32), 2147483647);
  }
}
<|endoftext|>


<commit_before>//! Simple hashed wheel timer with bounded interval.
//!
//! Relevant:
//! http://www.cs.columbia.edu/~nahum/w6998/papers/sosp87-timing-wheels.pdf

#![unstable]
#![allow(unstable)]

use std::mem;
use std::ops::IndexMut;

/// A simple wheel timer implementation with a fixed ring size.
pub struct WheelTimer<T> {
  max_interval: usize,
  current_tick: usize,
  size: usize,

  ring: Vec<Vec<T>>
}

/// Iterator implementation allows for using the wheel timer in a for loop.
///
/// # Example
///
/// ```
/// use wheel_timer::WheelTimer;
///
/// let mut timer: WheelTimer<usize> = WheelTimer::new(20us);
/// for result in timer {
///   // result is a vector of the values at that step
/// }
/// ```
impl<T> Iterator for WheelTimer<T> {
  type Item = Vec<T>;

  fn next(&mut self) -> Option<Vec<T>> {
    let size = self.size();
    return if size > 0 {
      Some(self.tick())
    } else {
      None
    };
  }
}

impl<T> WheelTimer<T> {

  /// Creates a new timer with the specified max interval.
  ///
  /// # Example
  ///
  /// ```
  /// use wheel_timer::WheelTimer;
  ///
  /// let mut timer: WheelTimer<usize> = WheelTimer::new(20us);
  /// ```
  pub fn new(max_interval: usize) -> WheelTimer<T> {
    // Initialize the ring with Nil values
    let mut ring = Vec::with_capacity(max_interval);
    for _ in range(0us, max_interval) {
      ring.push(Vec::new())
    }

    return WheelTimer{
      max_interval: max_interval,
      current_tick: 0,
      ring: ring,
      size: 0,
    }
  }

  /// Returns the number of items currently scheduled.
  ///
  /// # Example
  ///
  /// ```
  /// use wheel_timer::WheelTimer;
  ///
  /// let mut timer: WheelTimer<usize> = WheelTimer::new(20us);
  /// timer.schedule(4, 1);
  /// timer.schedule(7, 1);
  /// timer.schedule(1, 1);
  /// assert_eq!(timer.size(), 3);
  /// ```
  pub fn size(&self) -> usize {
    self.size
  }

  /// Schedules a new value, available after `ticks` have passed.
  ///
  /// # Example
  ///
  /// ```
  /// use wheel_timer::WheelTimer;
  ///
  /// let mut timer: WheelTimer<usize> = WheelTimer::new(20us);
  /// timer.schedule(4, 7); // schedule value 7 for 4 ticks
  /// ```
  pub fn schedule(&mut self, ticks: usize, value: T) {
    // Compute the scheduled position in the wheel
    let index = (self.current_tick + ticks) % self.max_interval;

    // Get the current node at `index` in the wheel and append the new node
    self.ring.index_mut(&index).push(value);

    // Increment the size counter
    self.size = self.size + 1;
  }

  /// Tick the timer, returning the node at the current tick.
  ///
  /// # Example
  ///
  /// ```
  /// use wheel_timer::WheelTimer;
  ///
  /// let mut timer: WheelTimer<usize> = WheelTimer::new(20us);
  /// timer.schedule(3, 4); // schedule value 4 for 3 ticks
  /// timer.tick();
  /// timer.tick();
  /// timer.tick();
  /// let result = timer.tick(); // vec![4]
  /// assert_eq!(result.len(), 1);
  /// ```
  pub fn tick(&mut self) -> Vec<T> {
    // Get the node at the current tick in the wheel
    let node = mem::replace(self.ring.index_mut(&self.current_tick), Vec::new());

    // Increment the timer
    self.current_tick = (self.current_tick + 1) % self.max_interval;

    // Reduce the size by the length of the removed node
    self.size = self.size - node.len();

    // Return the node that was in that spot
    return node
  }
}
<commit_msg>Updating for rustc 1.0.0-nightly (f1398d273 2015-01-31 20:21:02 +0000)<commit_after>//! Simple hashed wheel timer with bounded interval.
//!
//! Relevant:
//! http://www.cs.columbia.edu/~nahum/w6998/papers/sosp87-timing-wheels.pdf

#![unstable]
#![feature(core)]

use std::mem;
use std::ops::IndexMut;

/// A simple wheel timer implementation with a fixed ring size.
pub struct WheelTimer<T> {
  max_interval: usize,
  current_tick: usize,
  size: usize,

  ring: Vec<Vec<T>>
}

/// Iterator implementation allows for using the wheel timer in a for loop.
///
/// # Example
///
/// ```
/// use wheel_timer::WheelTimer;
///
/// let mut timer: WheelTimer<usize> = WheelTimer::new(20us);
/// for result in timer {
///   // result is a vector of the values at that step
/// }
/// ```
impl<T> Iterator for WheelTimer<T> {
  type Item = Vec<T>;

  fn next(&mut self) -> Option<Vec<T>> {
    let size = self.size();
    return if size > 0 {
      Some(self.tick())
    } else {
      None
    };
  }
}

impl<T> WheelTimer<T> {

  /// Creates a new timer with the specified max interval.
  ///
  /// # Example
  ///
  /// ```
  /// use wheel_timer::WheelTimer;
  ///
  /// let mut timer: WheelTimer<usize> = WheelTimer::new(20us);
  /// ```
  pub fn new(max_interval: usize) -> WheelTimer<T> {
    // Initialize the ring with Nil values
    let mut ring = Vec::with_capacity(max_interval);
    for _ in range(0us, max_interval) {
      ring.push(Vec::new())
    }

    return WheelTimer{
      max_interval: max_interval,
      current_tick: 0,
      ring: ring,
      size: 0,
    }
  }

  /// Returns the number of items currently scheduled.
  ///
  /// # Example
  ///
  /// ```
  /// use wheel_timer::WheelTimer;
  ///
  /// let mut timer: WheelTimer<usize> = WheelTimer::new(20us);
  /// timer.schedule(4, 1);
  /// timer.schedule(7, 1);
  /// timer.schedule(1, 1);
  /// assert_eq!(timer.size(), 3);
  /// ```
  pub fn size(&self) -> usize {
    self.size
  }

  /// Schedules a new value, available after `ticks` have passed.
  ///
  /// # Example
  ///
  /// ```
  /// use wheel_timer::WheelTimer;
  ///
  /// let mut timer: WheelTimer<usize> = WheelTimer::new(20us);
  /// timer.schedule(4, 7); // schedule value 7 for 4 ticks
  /// ```
  pub fn schedule(&mut self, ticks: usize, value: T) {
    // Compute the scheduled position in the wheel
    let index = (self.current_tick + ticks) % self.max_interval;

    // Get the current node at `index` in the wheel and append the new node
    self.ring.index_mut(&index).push(value);

    // Increment the size counter
    self.size = self.size + 1;
  }

  /// Tick the timer, returning the node at the current tick.
  ///
  /// # Example
  ///
  /// ```
  /// use wheel_timer::WheelTimer;
  ///
  /// let mut timer: WheelTimer<usize> = WheelTimer::new(20us);
  /// timer.schedule(3, 4); // schedule value 4 for 3 ticks
  /// timer.tick();
  /// timer.tick();
  /// timer.tick();
  /// let result = timer.tick(); // vec![4]
  /// assert_eq!(result.len(), 1);
  /// ```
  pub fn tick(&mut self) -> Vec<T> {
    // Get the node at the current tick in the wheel
    let node = mem::replace(self.ring.index_mut(&self.current_tick), Vec::new());

    // Increment the timer
    self.current_tick = (self.current_tick + 1) % self.max_interval;

    // Reduce the size by the length of the removed node
    self.size = self.size - node.len();

    // Return the node that was in that spot
    return node
  }
}
<|endoftext|>


<commit_before>use rusoto_core::signature;
use rusoto_core::signature::SignedRequest;
use rusoto_core::param::{Params, ServiceParams};
use rusoto_core::region::Region;
use rusoto_core::credential::AwsCredentials;
use generated::{GetObjectRequest, PutObjectRequest, DeleteObjectRequest};

/// URL encodes an S3 object key. This is necessary for `copy_object` and `upload_part_copy`,
/// which require the `copy_source` field to be URL encoded.
///
/// # Examples
///
/// ```
/// use rusoto_s3::CopyObjectRequest;
///
/// let request = CopyObjectRequest {
///     bucket: "my-bucket".to_owned(),
///     key: "my-key".to_owned(),
///     copy_source: rusoto_s3::util::encode_key("other-buckét/key-to-cöpy"),
///     ..Default::default()
/// };
/// ```
pub fn encode_key<T: AsRef<str>>(key: T) -> String {
    signature::encode_uri_path(key.as_ref())
}

pub enum PresignedRequestMethod {
    Get (GetObjectRequest),
    Put (PutObjectRequest),
    // Post (PostObjectRequest),
    Delete (DeleteObjectRequest),
}

/// Generate a presigned url given arguments.
///
pub fn generate_presigned_url(region: &Region, credentials: &AwsCredentials, input_request: &PresignedRequestMethod) -> String {

    macro_rules! add_headers {
        (
            $input:ident , $req:ident ; $p:ident , $e:expr ; $( $t:tt )*
        ) => (
            {
                if let Some(ref $p) = $input.$p {
                    $req.add_header($e, &$p.to_string());
                }
                add_headers! { $input, $req; $( $t )* }
            }
        );
        (
            $input:pat , $req:expr ;
        ) => ({
        });
    }

    macro_rules! add_params {
        (
            $input:ident , $params:ident ; $p:ident , $e:expr ; $( $t:tt )*
        ) => (
            {
                if let Some(ref $p) = $input.$p {
                    $params.put($e, &$p);
                }
                add_params! { $input, $params; $( $t )* }
            }
        );
        (
            $input:pat , $req:expr ;
        ) => ({
        });
    }

    match input_request {
        PresignedRequestMethod::Get(ref input) => {
            let request_uri = format!("/{bucket}/{key}", bucket = input.bucket, key = input.key);
            let mut request = SignedRequest::new("GET", "s3", &region, &request_uri);
            let mut params = Params::new();

            // https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectGET.html

            add_headers!(
                input, request;
                range, "Range";
                if_modified_since, "If-Modified-Since";
                if_unmodified_since, "If-Unmodified-Since";
                if_match, "If-Match";
                if_none_match, "If-None-Match";
                sse_customer_algorithm, "x-amz-server-side-encryption-customer-algorithm";
                sse_customer_key, "x-amz-server-side-encryption-customer-key";
                sse_customer_key_md5, "x-amz-server-side-encryption-customer-key-MD5";
            );

            add_params!(
                input, params;
                part_number, "partNumber";
                response_content_type, "response-content-type";
                response_content_language, "response-content-language";
                response_expires, "response-expires";
                response_cache_control, "response-cache-control";
                response_content_disposition, "response-content-disposition";
                response_content_encoding, "response-content-encoding";
                version_id, "versionId";
            );

            request.set_params(params);
            request.generate_presigned_url(&credentials)
        },
        // PresignedRequestMethod::Post(ref input) => {
        //     let request_uri = format!("/{bucket}/{key}", bucket = input.bucket, key = input.key);
        //     let mut request = SignedRequest::new("POST", "s3", &region, &request_uri);
        //     let mut params = Params::new();

        //     // https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html

        //     add_headers!(
        //         input, request;
        //     );
        //     add_params!(
        //         input, params;
        //     );

        //     request.set_params(params);
        //     request.generate_presigned_url(&credentials)
        // },
        PresignedRequestMethod::Put(ref input) => {
            let request_uri = format!("/{bucket}/{key}", bucket = input.bucket, key = input.key);
            let mut request = SignedRequest::new("PUT", "s3", &region, &request_uri);
            let mut params = Params::new();

            // https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPUT.html

            add_headers!(
                input, request;
                cache_control, "Cache-Control";
                content_disposition, "Content-Disposition";
                content_encoding, "Content-Encoding";
                content_length, "Content-Length";
                content_md5, "Content-MD5";
                content_type, "Content-Type";
                //expect, "Expect";
                expires, "Expires";
                storage_class, "x-amz-storage-class";
                tagging, "x-amz-tagging";
                website_redirect_location, "x-amz-website-redirect-location";
                acl, "x-amz-acl";
                grant_read, "x-amz-grant-read";
                //grant_write, "x-amz-grant-write";
                grant_read_acp, "x-amz-grant-read-acp";
                grant_write_acp, "x-amz-grant-write-acp";
                grant_full_control, "x-amz-grant-full-control";
                server_side_encryption, "x-amz-server-side-encryption";
                ssekms_key_id, "x-amz-server-side-encryption-aws-kms-key-id";
                //kms_context, "x-amz-server-side-encryption-context";
                sse_customer_algorithm, "x-amz-server-side-encryption-customer-algorithm";
                sse_customer_key, "x-amz-server-side-encryption-customer-key";
                sse_customer_key_md5, "x-amz-server-side-encryption-customer-key-MD5";
            );

            if let Some(ref metadata) = input.metadata {
                for (key, val) in metadata.iter() {
                    params.put(&format!("x-amz-meta-{}", key), val);
                }
            }

            add_params!(
                input, params;
            );

            request.set_params(params);
            request.generate_presigned_url(&credentials)
        },
        PresignedRequestMethod::Delete(ref input) => {
            let request_uri = format!("/{bucket}/{key}", bucket = input.bucket, key = input.key);
            let mut request = SignedRequest::new("DELETE", "s3", &region, &request_uri);
            let mut params = Params::new();

            // https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectDELETE.html

            add_headers!(
                input, request;
                mfa, "x-amz-mfa";
            );

            add_params!(
                input, params;
                version_id, "versionId";
            );

            request.set_params(params);
            request.generate_presigned_url(&credentials)
        },
    }
}
<commit_msg>fix build issue<commit_after>use rusoto_core::signature;
use rusoto_core::signature::SignedRequest;
use rusoto_core::param::{Params, ServiceParams};
use rusoto_core::region::Region;
use rusoto_core::credential::AwsCredentials;
use generated::{GetObjectRequest, PutObjectRequest, DeleteObjectRequest};

/// URL encodes an S3 object key. This is necessary for `copy_object` and `upload_part_copy`,
/// which require the `copy_source` field to be URL encoded.
///
/// # Examples
///
/// ```
/// use rusoto_s3::CopyObjectRequest;
///
/// let request = CopyObjectRequest {
///     bucket: "my-bucket".to_owned(),
///     key: "my-key".to_owned(),
///     copy_source: rusoto_s3::util::encode_key("other-buckét/key-to-cöpy"),
///     ..Default::default()
/// };
/// ```
pub fn encode_key<T: AsRef<str>>(key: T) -> String {
    signature::encode_uri_path(key.as_ref())
}

pub enum PresignedRequestMethod {
    Get (GetObjectRequest),
    Put (PutObjectRequest),
    // Post (PostObjectRequest),
    Delete (DeleteObjectRequest),
}

/// Generate a presigned url given arguments.
///
pub fn generate_presigned_url(region: &Region, credentials: &AwsCredentials, input_request: &PresignedRequestMethod) -> String {

    macro_rules! add_headers {
        (
            $input:ident , $req:ident ; $p:ident , $e:expr ; $( $t:tt )*
        ) => (
            {
                if let Some(ref $p) = $input.$p {
                    $req.add_header($e, &$p.to_string());
                }
                add_headers! { $input, $req; $( $t )* }
            }
        );
        (
            $input:pat , $req:expr ;
        ) => ({
        });
    }

    macro_rules! add_params {
        (
            $input:ident , $params:ident ; $p:ident , $e:expr ; $( $t:tt )*
        ) => (
            {
                if let Some(ref $p) = $input.$p {
                    $params.put($e, &$p);
                }
                add_params! { $input, $params; $( $t )* }
            }
        );
        (
            $input:pat , $req:expr ;
        ) => ({
        });
    }

    match input_request {
        &PresignedRequestMethod::Get(ref input) => {
            let request_uri = format!("/{bucket}/{key}", bucket = input.bucket, key = input.key);
            let mut request = SignedRequest::new("GET", "s3", &region, &request_uri);
            let mut params = Params::new();

            // https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectGET.html

            add_headers!(
                input, request;
                range, "Range";
                if_modified_since, "If-Modified-Since";
                if_unmodified_since, "If-Unmodified-Since";
                if_match, "If-Match";
                if_none_match, "If-None-Match";
                sse_customer_algorithm, "x-amz-server-side-encryption-customer-algorithm";
                sse_customer_key, "x-amz-server-side-encryption-customer-key";
                sse_customer_key_md5, "x-amz-server-side-encryption-customer-key-MD5";
            );

            add_params!(
                input, params;
                part_number, "partNumber";
                response_content_type, "response-content-type";
                response_content_language, "response-content-language";
                response_expires, "response-expires";
                response_cache_control, "response-cache-control";
                response_content_disposition, "response-content-disposition";
                response_content_encoding, "response-content-encoding";
                version_id, "versionId";
            );

            request.set_params(params);
            request.generate_presigned_url(&credentials)
        },
        // &PresignedRequestMethod::Post(ref input) => {
        //     let request_uri = format!("/{bucket}/{key}", bucket = input.bucket, key = input.key);
        //     let mut request = SignedRequest::new("POST", "s3", &region, &request_uri);
        //     let mut params = Params::new();

        //     // https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html

        //     add_headers!(
        //         input, request;
        //     );
        //     add_params!(
        //         input, params;
        //     );

        //     request.set_params(params);
        //     request.generate_presigned_url(&credentials)
        // },
        &PresignedRequestMethod::Put(ref input) => {
            let request_uri = format!("/{bucket}/{key}", bucket = input.bucket, key = input.key);
            let mut request = SignedRequest::new("PUT", "s3", &region, &request_uri);
            let mut params = Params::new();

            // https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPUT.html

            add_headers!(
                input, request;
                cache_control, "Cache-Control";
                content_disposition, "Content-Disposition";
                content_encoding, "Content-Encoding";
                content_length, "Content-Length";
                content_md5, "Content-MD5";
                content_type, "Content-Type";
                //expect, "Expect";
                expires, "Expires";
                storage_class, "x-amz-storage-class";
                tagging, "x-amz-tagging";
                website_redirect_location, "x-amz-website-redirect-location";
                acl, "x-amz-acl";
                grant_read, "x-amz-grant-read";
                //grant_write, "x-amz-grant-write";
                grant_read_acp, "x-amz-grant-read-acp";
                grant_write_acp, "x-amz-grant-write-acp";
                grant_full_control, "x-amz-grant-full-control";
                server_side_encryption, "x-amz-server-side-encryption";
                ssekms_key_id, "x-amz-server-side-encryption-aws-kms-key-id";
                //kms_context, "x-amz-server-side-encryption-context";
                sse_customer_algorithm, "x-amz-server-side-encryption-customer-algorithm";
                sse_customer_key, "x-amz-server-side-encryption-customer-key";
                sse_customer_key_md5, "x-amz-server-side-encryption-customer-key-MD5";
            );

            if let Some(ref metadata) = input.metadata {
                for (key, val) in metadata.iter() {
                    params.put(&format!("x-amz-meta-{}", key), val);
                }
            }

            add_params!(
                input, params;
            );

            request.set_params(params);
            request.generate_presigned_url(&credentials)
        },
        &PresignedRequestMethod::Delete(ref input) => {
            let request_uri = format!("/{bucket}/{key}", bucket = input.bucket, key = input.key);
            let mut request = SignedRequest::new("DELETE", "s3", &region, &request_uri);
            let mut params = Params::new();

            // https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectDELETE.html

            add_headers!(
                input, request;
                mfa, "x-amz-mfa";
            );

            add_params!(
                input, params;
                version_id, "versionId";
            );

            request.set_params(params);
            request.generate_presigned_url(&credentials)
        },
    }
}
<|endoftext|>


<commit_before>//! The public FFI functions for initializing, adding sinks to, and applying a logger.

use std::convert::TryFrom;
use std::ffi::{CStr, CString};
use std::ptr;
use std::str::from_utf8;

use fern::Dispatch;
use libc::{c_char, c_int};
use log::{error, LevelFilter as LogLevelFilter};

use crate::error::set_error_msg;
use crate::log::level_filter::LevelFilter;
use crate::log::logger::{add_sink, apply_logger, set_logger};
use crate::log::sink::Sink;
use crate::log::status::Status;
use crate::util::string::to_c;
use crate::log::inmem_buffer::fetch_buffer_contents;

/// Convenience function to direct all logging to stdout.
#[no_mangle]
pub extern "C" fn log_to_stdout(level_filter: LevelFilter) -> c_int {
    logger_init();

    let spec = match CString::new("stdout") {
        Ok(spec) => spec,
        Err(e) => {
            set_error_msg(e.to_string());
            return Status::CantConstructSink as c_int;
        }
    };

    let status = logger_attach_sink(spec.as_ptr(), level_filter);
    if status != 0 {
        return status;
    }

    let status = logger_apply();
    if status != 0 {
        return status;
    }

    Status::Success as c_int
}

/// Convenience function to direct all logging to stderr.
#[no_mangle]
pub extern "C" fn log_to_stderr(level_filter: LevelFilter) -> c_int {
    logger_init();

    let spec = match CString::new("stderr") {
        Ok(spec) => spec,
        Err(e) => {
            set_error_msg(e.to_string());
            return Status::CantConstructSink as c_int;
        }
    };

    let status = logger_attach_sink(spec.as_ptr(), level_filter);
    if status != 0 {
        return status;
    }

    let status = logger_apply();
    if status != 0 {
        return status;
    }

    Status::Success as c_int
}

/// Convenience function to direct all logging to a file.
#[no_mangle]
pub extern "C" fn log_to_file(
    file_name: *const c_char,
    level_filter: LevelFilter,
) -> c_int {
    logger_init();

    let spec = {
        if file_name.is_null() {
            return Status::CantConstructSink as c_int;
        }

        let file_name =
            match unsafe { CStr::from_ptr(file_name) }.to_str() {
                Ok(file_name) => file_name,
                Err(e) => {
                    set_error_msg(e.to_string());
                    return Status::CantConstructSink as c_int;
                }
            };

        let spec = format!("file {}", file_name);

        match CString::new(spec) {
            Ok(spec) => spec,
            Err(e) => {
                set_error_msg(e.to_string());
                return Status::CantConstructSink as c_int;
            }
        }
    };

    let status = logger_attach_sink(spec.as_ptr(), level_filter);
    if status != 0 {
        return status;
    }

    let status = logger_apply();
    if status != 0 {
        return status;
    }

    Status::Success as c_int
}

/// Convenience function to direct all logging to a thread local memory buffer.
#[no_mangle]
pub extern "C" fn log_to_buffer(level_filter: LevelFilter) -> c_int {
  logger_init();

  let spec = match CString::new("buffer") {
    Ok(spec) => spec,
    Err(e) => {
      set_error_msg(e.to_string());
      return Status::CantConstructSink as c_int;
    }
  };

  let status = logger_attach_sink(spec.as_ptr(), level_filter);
  if status != 0 {
    return status;
  }

  let status = logger_apply();
  if status != 0 {
    return status;
  }

  Status::Success as c_int
}

// C API uses something like the pledge API to select write locations, including:
//
// * stdout (`logger_attach_sink("stdout", LevelFilter_Info)`)
// * stderr (`logger_attach_sink("stderr", LevelFilter_Debug)`)
// * file w/ file path (`logger_attach_sink("file /some/file/path", LevelFilter_Trace)`)
//
// The general flow is:
//
// 1. Call `logger_init` to create a `Dispatch` struct.
// 2. Call `logger_attach_sink` to add an additional sink, using bitflags to set the metadata.
// 3. Call `logger_apply` to finalize the logger and enable logging to the configured sinks.
//
// Once `logger_apply` has been called, any additional calls to `logger_attach_sink` will fail
// with an error indicating the logger has been applied already.
//
// ```
// logger_init();
//
// int result = logger_attach_sink("stderr", FilterLevel_Debug);
// /* handle the error */
//
// int result = logger_attach_sink("file /some/file/path", FilterLevel_Info);
// /* handle the error */
//
// int result = logger_apply();
// /* handle the error */
// ```

/// Initialize the thread-local logger with no sinks.
///
/// This initialized logger does nothing until `logger_apply` has been called.
///
/// # Usage
///
/// ```c
/// logger_init();
/// ```
///
/// # Safety
///
/// This function is always safe to call.
#[no_mangle]
pub extern "C" fn logger_init() {
    set_logger(Dispatch::new());
}

/// Attach an additional sink to the thread-local logger.
///
/// This logger does nothing until `logger_apply` has been called.
///
/// Three types of sinks can be specified:
///
/// - stdout (`logger_attach_sink("stdout", LevelFilter_Info)`)
/// - stderr (`logger_attach_sink("stderr", LevelFilter_Debug)`)
/// - file w/ file path (`logger_attach_sink("file /some/file/path", LevelFilter_Trace)`)
/// - buffer (`logger_attach_sink("buffer", LevelFilter_Debug)`)
///
/// # Usage
///
/// ```
/// int result = logger_attach_sink("file /some/file/path", LogLevel_Filter);
/// ```
///
/// # Error Handling
///
/// The return error codes are as follows:
///
/// - `-1`: Can't set logger (applying the logger failed, perhaps because one is applied already).
/// - `-2`: No logger has been initialized (call `logger_init` before any other log function).
/// - `-3`: The sink specifier was not UTF-8 encoded.
/// - `-4`: The sink type specified is not a known type (known types: "stdout", "stderr", or "file /some/path").
/// - `-5`: No file path was specified in a file-type sink specification.
/// - `-6`: Opening a sink to the specified file path failed (check permissions).
///
/// # Safety
///
/// This function checks the validity of the passed-in sink specifier, and errors
/// out if the specifier isn't valid UTF-8.
#[allow(clippy::missing_safety_doc)]
#[allow(clippy::not_unsafe_ptr_arg_deref)]
#[no_mangle]
pub extern "C" fn logger_attach_sink(
    sink_specifier: *const c_char,
    level_filter: LevelFilter,
) -> c_int {
    // Get the specifier from the raw C string.
    let sink_specifier = unsafe { CStr::from_ptr(sink_specifier) };
    let sink_specifier = match sink_specifier.to_str() {
        Ok(sink_specifier) => sink_specifier,
        // TODO: Permit non-UTF8 strings, as some filesystems may have non-UTF8
        //       paths to which the user wants to direct the logging output.
        Err(_) => return Status::SpecifierNotUtf8 as c_int,
    };

    // Attempt to construct a sink from the specifier.
    let sink = match Sink::try_from(sink_specifier) {
        Ok(sink) => sink,
        Err(err) => return Status::from(err) as c_int,
    };

    // Convert from our `#[repr(C)]` LevelFilter to the one from the `log` crate.
    let level_filter: LogLevelFilter = level_filter.into();

    // Construct a dispatcher from the sink and level filter.
    let dispatch = Into::<Dispatch>::into(sink)
        .level(level_filter)
        .format(|out, message, record| {
            out.finish(format_args!(
                "[{}][{}] {}",
                record.level(),
                record.target(),
                message
            ))
        });

    // Take the existing logger, if there is one, add a new sink to it, and put it back.
    let status = match add_sink(dispatch) {
        Ok(_) => Status::Success,
        Err(err) => Status::from(err),
    };

    status as c_int
}

/// Apply the thread-local logger to the program.
///
/// Any attempts to modify the logger after the call to `logger_apply` will fail.
#[no_mangle]
pub extern "C" fn logger_apply() -> c_int {
    let status = match apply_logger() {
        Ok(_) => Status::Success,
        Err(err) => Status::from(err),
    };

    status as c_int
}

/// Fetch the in-memory logger buffer contents. This will only have any contents if the `buffer`
/// sink has been configured to log to. The contents will be allocated on the heap and will need
/// to be freed with `string_delete`.
///
/// Returns a NULL pointer if the buffer can't be fetched. This can occur is there is not
/// sufficient memory to make a copy of the contents or the buffer contains non-UTF-8 characters.
#[no_mangle]
pub extern "C" fn fetch_memory_buffer() -> *const c_char {
   match from_utf8(&fetch_buffer_contents()) {
     Ok(contents) => match to_c(contents) {
       Ok(c_str) => c_str,
       Err(err) => {
         error!("Failed to copy in-memory log buffer - {}", err);
         ptr::null()
       }
     }
     Err(err) => {
       error!("Failed to convert in-memory log buffer to UTF-8 = {}", err);
       ptr::null()
     }
   }
}
<commit_msg>chore: correct markdown doc example<commit_after>//! The public FFI functions for initializing, adding sinks to, and applying a logger.

use std::convert::TryFrom;
use std::ffi::{CStr, CString};
use std::ptr;
use std::str::from_utf8;

use fern::Dispatch;
use libc::{c_char, c_int};
use log::{error, LevelFilter as LogLevelFilter};

use crate::error::set_error_msg;
use crate::log::level_filter::LevelFilter;
use crate::log::logger::{add_sink, apply_logger, set_logger};
use crate::log::sink::Sink;
use crate::log::status::Status;
use crate::util::string::to_c;
use crate::log::inmem_buffer::fetch_buffer_contents;

/// Convenience function to direct all logging to stdout.
#[no_mangle]
pub extern "C" fn log_to_stdout(level_filter: LevelFilter) -> c_int {
    logger_init();

    let spec = match CString::new("stdout") {
        Ok(spec) => spec,
        Err(e) => {
            set_error_msg(e.to_string());
            return Status::CantConstructSink as c_int;
        }
    };

    let status = logger_attach_sink(spec.as_ptr(), level_filter);
    if status != 0 {
        return status;
    }

    let status = logger_apply();
    if status != 0 {
        return status;
    }

    Status::Success as c_int
}

/// Convenience function to direct all logging to stderr.
#[no_mangle]
pub extern "C" fn log_to_stderr(level_filter: LevelFilter) -> c_int {
    logger_init();

    let spec = match CString::new("stderr") {
        Ok(spec) => spec,
        Err(e) => {
            set_error_msg(e.to_string());
            return Status::CantConstructSink as c_int;
        }
    };

    let status = logger_attach_sink(spec.as_ptr(), level_filter);
    if status != 0 {
        return status;
    }

    let status = logger_apply();
    if status != 0 {
        return status;
    }

    Status::Success as c_int
}

/// Convenience function to direct all logging to a file.
#[no_mangle]
pub extern "C" fn log_to_file(
    file_name: *const c_char,
    level_filter: LevelFilter,
) -> c_int {
    logger_init();

    let spec = {
        if file_name.is_null() {
            return Status::CantConstructSink as c_int;
        }

        let file_name =
            match unsafe { CStr::from_ptr(file_name) }.to_str() {
                Ok(file_name) => file_name,
                Err(e) => {
                    set_error_msg(e.to_string());
                    return Status::CantConstructSink as c_int;
                }
            };

        let spec = format!("file {}", file_name);

        match CString::new(spec) {
            Ok(spec) => spec,
            Err(e) => {
                set_error_msg(e.to_string());
                return Status::CantConstructSink as c_int;
            }
        }
    };

    let status = logger_attach_sink(spec.as_ptr(), level_filter);
    if status != 0 {
        return status;
    }

    let status = logger_apply();
    if status != 0 {
        return status;
    }

    Status::Success as c_int
}

/// Convenience function to direct all logging to a thread local memory buffer.
#[no_mangle]
pub extern "C" fn log_to_buffer(level_filter: LevelFilter) -> c_int {
  logger_init();

  let spec = match CString::new("buffer") {
    Ok(spec) => spec,
    Err(e) => {
      set_error_msg(e.to_string());
      return Status::CantConstructSink as c_int;
    }
  };

  let status = logger_attach_sink(spec.as_ptr(), level_filter);
  if status != 0 {
    return status;
  }

  let status = logger_apply();
  if status != 0 {
    return status;
  }

  Status::Success as c_int
}

// C API uses something like the pledge API to select write locations, including:
//
// * stdout (`logger_attach_sink("stdout", LevelFilter_Info)`)
// * stderr (`logger_attach_sink("stderr", LevelFilter_Debug)`)
// * file w/ file path (`logger_attach_sink("file /some/file/path", LevelFilter_Trace)`)
//
// The general flow is:
//
// 1. Call `logger_init` to create a `Dispatch` struct.
// 2. Call `logger_attach_sink` to add an additional sink, using bitflags to set the metadata.
// 3. Call `logger_apply` to finalize the logger and enable logging to the configured sinks.
//
// Once `logger_apply` has been called, any additional calls to `logger_attach_sink` will fail
// with an error indicating the logger has been applied already.
//
// ```
// logger_init();
//
// int result = logger_attach_sink("stderr", FilterLevel_Debug);
// /* handle the error */
//
// int result = logger_attach_sink("file /some/file/path", FilterLevel_Info);
// /* handle the error */
//
// int result = logger_apply();
// /* handle the error */
// ```

/// Initialize the thread-local logger with no sinks.
///
/// This initialized logger does nothing until `logger_apply` has been called.
///
/// # Usage
///
/// ```c
/// logger_init();
/// ```
///
/// # Safety
///
/// This function is always safe to call.
#[no_mangle]
pub extern "C" fn logger_init() {
    set_logger(Dispatch::new());
}

/// Attach an additional sink to the thread-local logger.
///
/// This logger does nothing until `logger_apply` has been called.
///
/// Three types of sinks can be specified:
///
/// - stdout (`logger_attach_sink("stdout", LevelFilter_Info)`)
/// - stderr (`logger_attach_sink("stderr", LevelFilter_Debug)`)
/// - file w/ file path (`logger_attach_sink("file /some/file/path", LevelFilter_Trace)`)
/// - buffer (`logger_attach_sink("buffer", LevelFilter_Debug)`)
///
/// # Usage
///
/// ```c
/// int result = logger_attach_sink("file /some/file/path", LogLevel_Filter);
/// ```
///
/// # Error Handling
///
/// The return error codes are as follows:
///
/// - `-1`: Can't set logger (applying the logger failed, perhaps because one is applied already).
/// - `-2`: No logger has been initialized (call `logger_init` before any other log function).
/// - `-3`: The sink specifier was not UTF-8 encoded.
/// - `-4`: The sink type specified is not a known type (known types: "stdout", "stderr", or "file /some/path").
/// - `-5`: No file path was specified in a file-type sink specification.
/// - `-6`: Opening a sink to the specified file path failed (check permissions).
///
/// # Safety
///
/// This function checks the validity of the passed-in sink specifier, and errors
/// out if the specifier isn't valid UTF-8.
#[allow(clippy::missing_safety_doc)]
#[allow(clippy::not_unsafe_ptr_arg_deref)]
#[no_mangle]
pub extern "C" fn logger_attach_sink(
    sink_specifier: *const c_char,
    level_filter: LevelFilter,
) -> c_int {
    // Get the specifier from the raw C string.
    let sink_specifier = unsafe { CStr::from_ptr(sink_specifier) };
    let sink_specifier = match sink_specifier.to_str() {
        Ok(sink_specifier) => sink_specifier,
        // TODO: Permit non-UTF8 strings, as some filesystems may have non-UTF8
        //       paths to which the user wants to direct the logging output.
        Err(_) => return Status::SpecifierNotUtf8 as c_int,
    };

    // Attempt to construct a sink from the specifier.
    let sink = match Sink::try_from(sink_specifier) {
        Ok(sink) => sink,
        Err(err) => return Status::from(err) as c_int,
    };

    // Convert from our `#[repr(C)]` LevelFilter to the one from the `log` crate.
    let level_filter: LogLevelFilter = level_filter.into();

    // Construct a dispatcher from the sink and level filter.
    let dispatch = Into::<Dispatch>::into(sink)
        .level(level_filter)
        .format(|out, message, record| {
            out.finish(format_args!(
                "[{}][{}] {}",
                record.level(),
                record.target(),
                message
            ))
        });

    // Take the existing logger, if there is one, add a new sink to it, and put it back.
    let status = match add_sink(dispatch) {
        Ok(_) => Status::Success,
        Err(err) => Status::from(err),
    };

    status as c_int
}

/// Apply the thread-local logger to the program.
///
/// Any attempts to modify the logger after the call to `logger_apply` will fail.
#[no_mangle]
pub extern "C" fn logger_apply() -> c_int {
    let status = match apply_logger() {
        Ok(_) => Status::Success,
        Err(err) => Status::from(err),
    };

    status as c_int
}

/// Fetch the in-memory logger buffer contents. This will only have any contents if the `buffer`
/// sink has been configured to log to. The contents will be allocated on the heap and will need
/// to be freed with `string_delete`.
///
/// Returns a NULL pointer if the buffer can't be fetched. This can occur is there is not
/// sufficient memory to make a copy of the contents or the buffer contains non-UTF-8 characters.
#[no_mangle]
pub extern "C" fn fetch_memory_buffer() -> *const c_char {
   match from_utf8(&fetch_buffer_contents()) {
     Ok(contents) => match to_c(contents) {
       Ok(c_str) => c_str,
       Err(err) => {
         error!("Failed to copy in-memory log buffer - {}", err);
         ptr::null()
       }
     }
     Err(err) => {
       error!("Failed to convert in-memory log buffer to UTF-8 = {}", err);
       ptr::null()
     }
   }
}
<|endoftext|>


<commit_before>// TODO:
//      - Simplify using instruction iterators
//      - Make movement mode
//      - Record modifiers

mod editor;
pub use self::editor::*;

mod mode;
pub use self::mode::*;

mod movement;
pub use self::movement::*;

mod cursor;
pub use self::cursor::*;

mod insert;
pub use self::insert::*;

mod exec;
pub use self::exec::*;

use redox::*;

pub fn main() {
    let mut window = Window::new((rand() % 400 + 50) as isize,
								 (rand() % 300 + 50) as isize,
								 576,
								 400,
								 &"Sodium").unwrap();

    let mut editor = Editor::new();

    let mut inp = window.event_iter().map(|x| {
        x.to_option()
    }).inst_iter(&editor.cursor().mode);

    for i in inp {
        editor.exec(i, &mut inp);
    }
    window.set([255, 255, 255, 255]);

}

pub fn redraw() {
    /*
                    // Redraw window
                    window.set([255, 255, 255, 255]);

                    for (y, row) in editor.text.iter().enumerate() {
                        for (x, c) in row.iter().enumerate() {
                            window.char(8 * (y - editor.scroll_y) as isize, 16 * (x - editor.scroll_x) as isize, *c, [128, 128, 128, 255]);
                            if editor.cursor().x == x && editor.cursor().y == y {
                                window.char(8 * (y - editor.scroll_y) as isize, 16 * (x - editor.scroll_x) as isize, '_', [128, 128, 128, 255]);
                            }
                        }
                    }
    */
}
<commit_msg>Convert tabs to spaces and remove some tailing spaces<commit_after>// TODO:
//      - Simplify using instruction iterators
//      - Make movement mode
//      - Record modifiers

mod editor;
pub use self::editor::*;

mod mode;
pub use self::mode::*;

mod movement;
pub use self::movement::*;

mod cursor;
pub use self::cursor::*;

mod insert;
pub use self::insert::*;

mod exec;
pub use self::exec::*;

use redox::*;

pub fn main() {
    let mut window = Window::new((rand() % 400 + 50) as isize,
                                 (rand() % 300 + 50) as isize,
                                 576,
                                 400,
                                 &"Sodium").unwrap();

    let mut editor = Editor::new();

    let mut inp = window.event_iter().map(|x| {
        x.to_option()
    }).inst_iter(&editor.cursor().mode);

    for i in inp {
        editor.exec(i, &mut inp);
    }
    window.set([255, 255, 255, 255]);

}

pub fn redraw() {
    /*
                    // Redraw window
                    window.set([255, 255, 255, 255]);

                    for (y, row) in editor.text.iter().enumerate() {
                        for (x, c) in row.iter().enumerate() {
                            window.char(8 * (y - editor.scroll_y) as isize, 16 * (x - editor.scroll_x) as isize, *c, [128, 128, 128, 255]);
                            if editor.cursor().x == x && editor.cursor().y == y {
                                window.char(8 * (y - editor.scroll_y) as isize, 16 * (x - editor.scroll_x) as isize, '_', [128, 128, 128, 255]);
                            }
                        }
                    }
    */
}
<|endoftext|>


<commit_before><commit_msg>Make cached_size field public<commit_after><|endoftext|>


<commit_before><commit_msg>dx12: Fix compute descriptor tables<commit_after><|endoftext|>