<commit_before>//! This sub module contains extra structs used as widget properties.

use std::{collections::HashSet, fmt::Debug};

use dces::prelude::{Component, Entity, StringComponentStore};

pub use self::layout::*;
pub use self::widget::*;
use crate::{into_property_source, render, theming, utils};

mod layout;
mod widget;

/// Get the property of a widget.
pub fn get_property<T>(key: &str, entity: Entity, store: &StringComponentStore) -> T
where
    T: Clone + Component,
{
    store.get::<T>(key, entity).map(|r| r.clone()).unwrap()
}

/// Returns the value of a property of a widget if it exists otherwise the given value.
pub fn get_property_or_value<T>(
    key: &str,
    entity: Entity,
    store: &StringComponentStore,
    value: T,
) -> T
where
    T: Clone + Component,
{
    if let Ok(property) = store.get::<T>(key, entity).map(|r| r.clone()) {
        return property;
    }
    value
}

/// Use to build a property or to share it.
#[derive(PartialEq, Debug)]
pub enum PropertySource
 {
    Source(Entity),
    KeySource(String, Entity),
    Value(P),
}

impl
 From<Entity> for PropertySource
 {
    fn from(entity: Entity) -> Self {
        PropertySource::Source(entity)
    }
}

/// Used to convert components / properties into a PropertySource object.
pub trait IntoPropertySource
 {
    fn into_source(self) -> PropertySource
;
}

/// Used ot generate attached properties.
pub struct AttachedProperty

where
    P: Component + Debug,
{
    pub key: String,
    pub property_source: PropertySource
,
}

impl
 AttachedProperty

where
    P: Component + Debug,
{
    /// Create a new attached property.
    pub fn new(key: impl Into<String>, property_source: impl IntoPropertySource
) -> Self {
        AttachedProperty {
            key: key.into(),
            property_source: property_source.into_source(),
        }
    }
}

// Implementation of PropertySource for default types
into_property_source!(bool);
into_property_source!(String: &str, utils::Value);
into_property_source!(usize);
into_property_source!(u32);
into_property_source!(f32: utils::Value);
into_property_source!(f64: i32, f32, utils::Value);
into_property_source!(i32);
into_property_source!(i64);

// Implementation of PropertySource for utils types
into_property_source!(utils::Alignment: &str);
into_property_source!(utils::Brush: &str, utils::Color, utils::Value);
into_property_source!(utils::Orientation: &str);
into_property_source!(utils::Point: f64, i32, (i32, i32), (f64, f64));
into_property_source!(utils::Size: f64, i32, (i32, i32), (f64, f64));
into_property_source!(
    utils::Rectangle: (i32, i32, i32, i32),
    (f64, f64, f64, f64),
    (utils::Point, utils::Size)
);
into_property_source!(
    utils::Thickness: i32,
    f64,
    (i32, i32),
    (f64, f64),
    (i32, i32, i32, i32),
    (f64, f64, f64, f64),
    utils::Value
);
into_property_source!(utils::String16: &str, String);
into_property_source!(utils::SelectionMode: &str);
into_property_source!(utils::Visibility: &str);
into_property_source!(Vec<String>);
into_property_source!(utils::Filter: &str, String, Vec<String>, Vec<&str>);

// Implementation of css types
into_property_source!(theming::Selector: &str, String);
into_property_source!(theming::Theme);

// Implementation of render property types
into_property_source!(render::Image: &str, String, (u32, u32, Vec<u32>));

// Implementation of custom property types
into_property_source!(Columns: ColumnsBuilder);
into_property_source!(Constraint: ConstraintBuilder);
into_property_source!(DefaultRenderPipeline);
into_property_source!(Rows: RowsBuilder);
into_property_source!(ScrollViewerMode: (&str, &str));
into_property_source!(SelectedEntities: HashSet<Entity>);
into_property_source!(SelectedIndices: HashSet<usize>);
into_property_source!(TextSelection: (usize, usize));
<commit_msg>Added char to impl of PropertySource<commit_after>//! This sub module contains extra structs used as widget properties.

use std::{collections::HashSet, fmt::Debug};

use dces::prelude::{Component, Entity, StringComponentStore};

pub use self::layout::*;
pub use self::widget::*;
use crate::{into_property_source, render, theming, utils};

mod layout;
mod widget;

/// Get the property of a widget.
pub fn get_property<T>(key: &str, entity: Entity, store: &StringComponentStore) -> T
where
    T: Clone + Component,
{
    store.get::<T>(key, entity).map(|r| r.clone()).unwrap()
}

/// Returns the value of a property of a widget if it exists otherwise the given value.
pub fn get_property_or_value<T>(
    key: &str,
    entity: Entity,
    store: &StringComponentStore,
    value: T,
) -> T
where
    T: Clone + Component,
{
    if let Ok(property) = store.get::<T>(key, entity).map(|r| r.clone()) {
        return property;
    }
    value
}

/// Use to build a property or to share it.
#[derive(PartialEq, Debug)]
pub enum PropertySource
 {
    Source(Entity),
    KeySource(String, Entity),
    Value(P),
}

impl
 From<Entity> for PropertySource
 {
    fn from(entity: Entity) -> Self {
        PropertySource::Source(entity)
    }
}

/// Used to convert components / properties into a PropertySource object.
pub trait IntoPropertySource
 {
    fn into_source(self) -> PropertySource
;
}

/// Used ot generate attached properties.
pub struct AttachedProperty

where
    P: Component + Debug,
{
    pub key: String,
    pub property_source: PropertySource
,
}

impl
 AttachedProperty

where
    P: Component + Debug,
{
    /// Create a new attached property.
    pub fn new(key: impl Into<String>, property_source: impl IntoPropertySource
) -> Self {
        AttachedProperty {
            key: key.into(),
            property_source: property_source.into_source(),
        }
    }
}

// Implementation of PropertySource for default types
into_property_source!(bool);
into_property_source!(char);
into_property_source!(String: &str, utils::Value);
into_property_source!(usize);
into_property_source!(u32);
into_property_source!(f32: utils::Value);
into_property_source!(f64: i32, f32, utils::Value);
into_property_source!(i32);
into_property_source!(i64);

// Implementation of PropertySource for utils types
into_property_source!(utils::Alignment: &str);
into_property_source!(utils::Brush: &str, utils::Color, utils::Value);
into_property_source!(utils::Orientation: &str);
into_property_source!(utils::Point: f64, i32, (i32, i32), (f64, f64));
into_property_source!(utils::Size: f64, i32, (i32, i32), (f64, f64));
into_property_source!(
    utils::Rectangle: (i32, i32, i32, i32),
    (f64, f64, f64, f64),
    (utils::Point, utils::Size)
);
into_property_source!(
    utils::Thickness: i32,
    f64,
    (i32, i32),
    (f64, f64),
    (i32, i32, i32, i32),
    (f64, f64, f64, f64),
    utils::Value
);
into_property_source!(utils::String16: &str, String);
into_property_source!(utils::SelectionMode: &str);
into_property_source!(utils::Visibility: &str);
into_property_source!(Vec<String>);
into_property_source!(utils::Filter: &str, String, Vec<String>, Vec<&str>);

// Implementation of css types
into_property_source!(theming::Selector: &str, String);
into_property_source!(theming::Theme);

// Implementation of render property types
into_property_source!(render::Image: &str, String, (u32, u32, Vec<u32>));

// Implementation of custom property types
into_property_source!(Columns: ColumnsBuilder);
into_property_source!(Constraint: ConstraintBuilder);
into_property_source!(DefaultRenderPipeline);
into_property_source!(Rows: RowsBuilder);
into_property_source!(ScrollViewerMode: (&str, &str));
into_property_source!(SelectedEntities: HashSet<Entity>);
into_property_source!(SelectedIndices: HashSet<usize>);
into_property_source!(TextSelection: (usize, usize));
<|endoftext|>


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

//! The implementations of `Rand` for the built-in types.

use char;
use int;
use option::{Option, Some, None};
use rand::{Rand,Rng};
use uint;

impl Rand for int {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> int {
        if int::bits == 32 {
            rng.gen::<i32>() as int
        } else {
            rng.gen::<i64>() as int
        }
    }
}

impl Rand for i8 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i8 {
        rng.next_u32() as i8
    }
}

impl Rand for i16 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i16 {
        rng.next_u32() as i16
    }
}

impl Rand for i32 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i32 {
        rng.next_u32() as i32
    }
}

impl Rand for i64 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i64 {
        rng.next_u64() as i64
    }
}

impl Rand for uint {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> uint {
        if uint::bits == 32 {
            rng.gen::<u32>() as uint
        } else {
            rng.gen::<u64>() as uint
        }
    }
}

impl Rand for u8 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u8 {
        rng.next_u32() as u8
    }
}

impl Rand for u16 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u16 {
        rng.next_u32() as u16
    }
}

impl Rand for u32 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u32 {
        rng.next_u32()
    }
}

impl Rand for u64 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u64 {
        rng.next_u64()
    }
}

impl Rand for f32 {
    /// A random `f32` in the range `[0, 1)`.
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> f32 {
        // weird, but this is the easiest way to get 2**32
        static SCALE: f32 = 2.0 * (1u32 << 31) as f32;
        rng.next_u32() as f32 / SCALE
    }
}

impl Rand for f64 {
    /// A random `f64` in the range `[0, 1)`.
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> f64 {
        // weird, but this is the easiest way to get 2**64
        static SCALE: f64 = 2.0 * (1u64 << 63) as f64;

        rng.next_u64() as f64 / SCALE
    }
}

impl Rand for char {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> char {
        // a char is 21 bits
        static CHAR_MASK: u32 = 0x001f_ffff;
        loop {
            // Rejection sampling. About 0.2% of numbers with at most
            // 21-bits are invalid codepoints (surrogates), so this
            // will succeed first go almost every time.
            match char::from_u32(rng.next_u32() & CHAR_MASK) {
                Some(c) => return c,
                None => {}
            }
        }
    }
}

impl Rand for bool {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> bool {
        rng.gen::<u8>() & 1 == 1
    }
}

macro_rules! tuple_impl {
    // use variables to indicate the arity of the tuple
    ($($tyvar:ident),* ) => {
        // the trailing commas are for the 1 tuple
        impl<
            $( $tyvar : Rand ),*
            > Rand for ( $( $tyvar ),* , ) {

            #[inline]
            fn rand<R: Rng>(_rng: &mut R) -> ( $( $tyvar ),* , ) {
                (
                    // use the $tyvar's to get the appropriate number of
                    // repeats (they're not actually needed)
                    $(
                        _rng.gen::<$tyvar>()
                    ),*
                    ,
                )
            }
        }
    }
}

impl Rand for () {
    #[inline]
    fn rand<R: Rng>(_: &mut R) -> () { () }
}
tuple_impl!{A}
tuple_impl!{A, B}
tuple_impl!{A, B, C}
tuple_impl!{A, B, C, D}
tuple_impl!{A, B, C, D, E}
tuple_impl!{A, B, C, D, E, F}
tuple_impl!{A, B, C, D, E, F, G}
tuple_impl!{A, B, C, D, E, F, G, H}
tuple_impl!{A, B, C, D, E, F, G, H, I}
tuple_impl!{A, B, C, D, E, F, G, H, I, J}

impl<T:Rand> Rand for Option<T> {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> Option<T> {
        if rng.gen() {
            Some(rng.gen())
        } else {
            None
        }
    }
}

impl<T: Rand> Rand for ~T {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> ~T { ~rng.gen() }
}

impl<T: Rand + 'static> Rand for @T {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> @T { @rng.gen() }
}
<commit_msg>std::rand: Correct the implementation of Rand for f32 & f64.<commit_after>// Copyright 2013 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.

//! The implementations of `Rand` for the built-in types.

use char;
use int;
use option::{Option, Some, None};
use rand::{Rand,Rng};
use uint;

impl Rand for int {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> int {
        if int::bits == 32 {
            rng.gen::<i32>() as int
        } else {
            rng.gen::<i64>() as int
        }
    }
}

impl Rand for i8 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i8 {
        rng.next_u32() as i8
    }
}

impl Rand for i16 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i16 {
        rng.next_u32() as i16
    }
}

impl Rand for i32 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i32 {
        rng.next_u32() as i32
    }
}

impl Rand for i64 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i64 {
        rng.next_u64() as i64
    }
}

impl Rand for uint {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> uint {
        if uint::bits == 32 {
            rng.gen::<u32>() as uint
        } else {
            rng.gen::<u64>() as uint
        }
    }
}

impl Rand for u8 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u8 {
        rng.next_u32() as u8
    }
}

impl Rand for u16 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u16 {
        rng.next_u32() as u16
    }
}

impl Rand for u32 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u32 {
        rng.next_u32()
    }
}

impl Rand for u64 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u64 {
        rng.next_u64()
    }
}

impl Rand for f32 {
    /// A random `f32` in the range `[0, 1)`, using 24 bits of
    /// precision.
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> f32 {
        // using any more than 24 bits will cause (e.g.) 0xffff_ffff
        // to correspond to 1 exactly, so we need to drop 8 to
        // guarantee the open end.

        static SCALE: f32 = (1u32 << 24) as f32;
        (rng.next_u32() >> 8) as f32 / SCALE
    }
}

impl Rand for f64 {
    /// A random `f64` in the range `[0, 1)`, using 53 bits of
    /// precision.
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> f64 {
        // as for f32, but using more bits.

        static SCALE: f64 = (1u64 << 53) as f64;
        (rng.next_u64() >> 11) as f64 / SCALE
    }
}

impl Rand for char {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> char {
        // a char is 21 bits
        static CHAR_MASK: u32 = 0x001f_ffff;
        loop {
            // Rejection sampling. About 0.2% of numbers with at most
            // 21-bits are invalid codepoints (surrogates), so this
            // will succeed first go almost every time.
            match char::from_u32(rng.next_u32() & CHAR_MASK) {
                Some(c) => return c,
                None => {}
            }
        }
    }
}

impl Rand for bool {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> bool {
        rng.gen::<u8>() & 1 == 1
    }
}

macro_rules! tuple_impl {
    // use variables to indicate the arity of the tuple
    ($($tyvar:ident),* ) => {
        // the trailing commas are for the 1 tuple
        impl<
            $( $tyvar : Rand ),*
            > Rand for ( $( $tyvar ),* , ) {

            #[inline]
            fn rand<R: Rng>(_rng: &mut R) -> ( $( $tyvar ),* , ) {
                (
                    // use the $tyvar's to get the appropriate number of
                    // repeats (they're not actually needed)
                    $(
                        _rng.gen::<$tyvar>()
                    ),*
                    ,
                )
            }
        }
    }
}

impl Rand for () {
    #[inline]
    fn rand<R: Rng>(_: &mut R) -> () { () }
}
tuple_impl!{A}
tuple_impl!{A, B}
tuple_impl!{A, B, C}
tuple_impl!{A, B, C, D}
tuple_impl!{A, B, C, D, E}
tuple_impl!{A, B, C, D, E, F}
tuple_impl!{A, B, C, D, E, F, G}
tuple_impl!{A, B, C, D, E, F, G, H}
tuple_impl!{A, B, C, D, E, F, G, H, I}
tuple_impl!{A, B, C, D, E, F, G, H, I, J}

impl<T:Rand> Rand for Option<T> {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> Option<T> {
        if rng.gen() {
            Some(rng.gen())
        } else {
            None
        }
    }
}

impl<T: Rand> Rand for ~T {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> ~T { ~rng.gen() }
}

impl<T: Rand + 'static> Rand for @T {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> @T { @rng.gen() }
}

#[cfg(test)]
mod tests {
    use rand::Rng;
    struct ConstantRng(u64);
    impl Rng for ConstantRng {
        fn next_u64(&mut self) -> u64 {
            **self
        }
    }
    fn floating_point_edge_cases() {
        // the test for exact equality is correct here.
        assert!(ConstantRng(0xffff_ffff).gen::<f32>() != 1.0)
        assert!(ConstantRng(0xffff_ffff_ffff_ffff).gen::<f64>() != 1.0)
    }
}
<|endoftext|>


<commit_before>use std::any::{Any, TypeId};
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use std::mem;
use std::ptr;

use ffi;
use libc;

use AsLua;
use AsMutLua;
use Push;
use PushGuard;
use LuaRead;

use InsideCallback;
use LuaTable;

#[inline]
extern "C" fn destructor_wrapper(lua: *mut ffi::lua_State) -> libc::c_int {
    let impl_raw = unsafe { ffi::lua_touserdata(lua, ffi::lua_upvalueindex(1)) };
    let imp: fn(*mut ffi::lua_State) -> ::libc::c_int = unsafe { mem::transmute(impl_raw) };

    imp(lua)
}

#[inline]
fn destructor_impl<T>(lua: *mut ffi::lua_State) -> libc::c_int {
    let obj = unsafe { ffi::lua_touserdata(lua, -1) };
    let obj: &mut T = unsafe { mem::transmute(obj) };
    mem::replace(obj, unsafe { mem::uninitialized() });

    0
}

/// Pushes an object as a user data.
///
/// In Lua, a user data is anything that is not recognized by Lua. When the script attempts to
/// copy a user data, instead only a reference to the data is copied.
///
/// The way a Lua script can use the user data depends on the content of the **metatable**, which
/// is a Lua table linked to the object.
///
/// [See this link for more infos.](http://www.lua.org/manual/5.2/manual.html#2.4)
///
/// # Arguments
///
///  - `metatable`: Function that fills the metatable of the object.
///
#[inline]
pub fn push_userdata<'lua, L, T, F>(data: T, mut lua: L, mut metatable: F) -> PushGuard<L>
    where F: FnMut(LuaTable<&mut PushGuard<&mut L>>),
          L: AsMutLua<'lua>,
          T: Send + 'static + Any
{
    let typeid = format!("{:?}", TypeId::of::<T>());

    let lua_data_raw = unsafe {
        ffi::lua_newuserdata(lua.as_mut_lua().0, mem::size_of_val(&data) as libc::size_t)
    };
    let lua_data: *mut T = unsafe { mem::transmute(lua_data_raw) };
    unsafe { ptr::write(lua_data, data) };

    let lua_raw = lua.as_mut_lua();

    // creating a metatable
    unsafe {
        ffi::lua_newtable(lua.as_mut_lua().0);

        // index "__typeid" corresponds to the hash of the TypeId of T
        match "__typeid".push_to_lua(&mut lua) {
            Ok(p) => p.forget(),
            Err(_) => unreachable!(),
        };
        match typeid.push_to_lua(&mut lua) {
            Ok(p) => p.forget(),
            Err(_) => unreachable!(),
        };
        ffi::lua_settable(lua.as_mut_lua().0, -3);

        // index "__gc" call the object's destructor
        {
            match "__gc".push_to_lua(&mut lua) {
                Ok(p) => p.forget(),
                Err(_) => unreachable!(),
            };

            // pushing destructor_impl as a lightuserdata
            let destructor_impl: fn(*mut ffi::lua_State) -> libc::c_int = destructor_impl::<T>;
            ffi::lua_pushlightuserdata(lua.as_mut_lua().0, mem::transmute(destructor_impl));

            // pushing destructor_wrapper as a closure
            ffi::lua_pushcclosure(lua.as_mut_lua().0, destructor_wrapper, 1);

            ffi::lua_settable(lua.as_mut_lua().0, -3);
        }

        // calling the metatable closure
        {
            let raw_lua = lua.as_lua();
            let mut guard = PushGuard {
                lua: &mut lua,
                size: 1,
                raw_lua: raw_lua,
            };
            metatable(LuaRead::lua_read(&mut guard).ok().unwrap());
            guard.forget();
        }

        ffi::lua_setmetatable(lua_raw.0, -2);
    }

    let raw_lua = lua.as_lua();
    PushGuard {
        lua: lua,
        size: 1,
        raw_lua: raw_lua,
    }
}

///
#[inline]
pub fn read_userdata<'t, 'c, T>(mut lua: &'c mut InsideCallback,
                                index: i32)
                                -> Result<&'t mut T, &'c mut InsideCallback>
    where T: 'static + Any
{
    unsafe {
        let expected_typeid = format!("{:?}", TypeId::of::<T>());

        let data_ptr = ffi::lua_touserdata(lua.as_lua().0, index);
        if data_ptr.is_null() {
            return Err(lua);
        }

        if ffi::lua_getmetatable(lua.as_lua().0, index) == 0 {
            return Err(lua);
        }

        match "__typeid".push_to_lua(&mut lua) {
            Ok(p) => p.forget(),
            Err(_) => unreachable!(),
        };
        ffi::lua_gettable(lua.as_lua().0, -2);
        match <String as LuaRead<_>>::lua_read(&mut lua) {
            Ok(ref val) if val == &expected_typeid => {}
            _ => {
                return Err(lua);
            }
        }
        ffi::lua_pop(lua.as_lua().0, 2);

        Ok(mem::transmute(data_ptr))
    }
}

/// Represents a user data located inside the Lua context.
pub struct UserdataOnStack<T, L> {
    variable: L,
    marker: PhantomData<T>,
}

impl<'lua, T, L> LuaRead<L> for UserdataOnStack<T, L>
    where L: AsMutLua<'lua> + AsLua<'lua>,
          T: 'static + Any
{
    #[inline]
    fn lua_read_at_position(mut lua: L, index: i32) -> Result<UserdataOnStack<T, L>, L> {
        unsafe {
            let expected_typeid = format!("{:?}", TypeId::of::<T>());

            let data_ptr = ffi::lua_touserdata(lua.as_lua().0, index);
            if data_ptr.is_null() {
                return Err(lua);
            }

            if ffi::lua_getmetatable(lua.as_lua().0, index) == 0 {
                return Err(lua);
            }

            match "__typeid".push_to_lua(&mut lua) {
                Ok(p) => p.forget(),
                Err(_) => unreachable!(),
            };
            ffi::lua_gettable(lua.as_lua().0, -2);
            match <String as LuaRead<_>>::lua_read(&mut lua) {
                Ok(ref val) if val == &expected_typeid => {}
                _ => {
                    return Err(lua);
                }
            }
            ffi::lua_pop(lua.as_lua().0, 2);

            Ok(UserdataOnStack {
                variable: lua,
                marker: PhantomData,
            })
        }
    }
}

#[allow(mutable_transmutes)]
impl<'lua, T, L> Deref for UserdataOnStack<T, L>
    where L: AsMutLua<'lua>,
          T: 'static + Any
{
    type Target = T;

    #[inline]
    fn deref(&self) -> &T {
        let me: &mut UserdataOnStack<T, L> = unsafe { mem::transmute(self) };       // FIXME:
        let data = unsafe { ffi::lua_touserdata(me.variable.as_mut_lua().0, -1) };
        let data: &T = unsafe { mem::transmute(data) };
        data
    }
}

impl<'lua, T, L> DerefMut for UserdataOnStack<T, L>
    where L: AsMutLua<'lua>,
          T: 'static + Any
{
    #[inline]
    fn deref_mut(&mut self) -> &mut T {
        let data = unsafe { ffi::lua_touserdata(self.variable.as_mut_lua().0, -1) };
        let data: &mut T = unsafe { mem::transmute(data) };
        data
    }
}
<commit_msg>Remove mutable transmutes from UserdataOnStack<commit_after>use std::any::{Any, TypeId};
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use std::mem;
use std::ptr;

use ffi;
use libc;

use AsLua;
use AsMutLua;
use Push;
use PushGuard;
use LuaRead;

use InsideCallback;
use LuaTable;

#[inline]
extern "C" fn destructor_wrapper(lua: *mut ffi::lua_State) -> libc::c_int {
    let impl_raw = unsafe { ffi::lua_touserdata(lua, ffi::lua_upvalueindex(1)) };
    let imp: fn(*mut ffi::lua_State) -> ::libc::c_int = unsafe { mem::transmute(impl_raw) };

    imp(lua)
}

#[inline]
fn destructor_impl<T>(lua: *mut ffi::lua_State) -> libc::c_int {
    let obj = unsafe { ffi::lua_touserdata(lua, -1) };
    let obj: &mut T = unsafe { mem::transmute(obj) };
    mem::replace(obj, unsafe { mem::uninitialized() });

    0
}

/// Pushes an object as a user data.
///
/// In Lua, a user data is anything that is not recognized by Lua. When the script attempts to
/// copy a user data, instead only a reference to the data is copied.
///
/// The way a Lua script can use the user data depends on the content of the **metatable**, which
/// is a Lua table linked to the object.
///
/// [See this link for more infos.](http://www.lua.org/manual/5.2/manual.html#2.4)
///
/// # Arguments
///
///  - `metatable`: Function that fills the metatable of the object.
///
#[inline]
pub fn push_userdata<'lua, L, T, F>(data: T, mut lua: L, mut metatable: F) -> PushGuard<L>
    where F: FnMut(LuaTable<&mut PushGuard<&mut L>>),
          L: AsMutLua<'lua>,
          T: Send + 'static + Any
{
    let typeid = format!("{:?}", TypeId::of::<T>());

    let lua_data_raw = unsafe {
        ffi::lua_newuserdata(lua.as_mut_lua().0, mem::size_of_val(&data) as libc::size_t)
    };
    let lua_data: *mut T = unsafe { mem::transmute(lua_data_raw) };
    unsafe { ptr::write(lua_data, data) };

    let lua_raw = lua.as_mut_lua();

    // creating a metatable
    unsafe {
        ffi::lua_newtable(lua.as_mut_lua().0);

        // index "__typeid" corresponds to the hash of the TypeId of T
        match "__typeid".push_to_lua(&mut lua) {
            Ok(p) => p.forget(),
            Err(_) => unreachable!(),
        };
        match typeid.push_to_lua(&mut lua) {
            Ok(p) => p.forget(),
            Err(_) => unreachable!(),
        };
        ffi::lua_settable(lua.as_mut_lua().0, -3);

        // index "__gc" call the object's destructor
        {
            match "__gc".push_to_lua(&mut lua) {
                Ok(p) => p.forget(),
                Err(_) => unreachable!(),
            };

            // pushing destructor_impl as a lightuserdata
            let destructor_impl: fn(*mut ffi::lua_State) -> libc::c_int = destructor_impl::<T>;
            ffi::lua_pushlightuserdata(lua.as_mut_lua().0, mem::transmute(destructor_impl));

            // pushing destructor_wrapper as a closure
            ffi::lua_pushcclosure(lua.as_mut_lua().0, destructor_wrapper, 1);

            ffi::lua_settable(lua.as_mut_lua().0, -3);
        }

        // calling the metatable closure
        {
            let raw_lua = lua.as_lua();
            let mut guard = PushGuard {
                lua: &mut lua,
                size: 1,
                raw_lua: raw_lua,
            };
            metatable(LuaRead::lua_read(&mut guard).ok().unwrap());
            guard.forget();
        }

        ffi::lua_setmetatable(lua_raw.0, -2);
    }

    let raw_lua = lua.as_lua();
    PushGuard {
        lua: lua,
        size: 1,
        raw_lua: raw_lua,
    }
}

///
#[inline]
pub fn read_userdata<'t, 'c, T>(mut lua: &'c mut InsideCallback,
                                index: i32)
                                -> Result<&'t mut T, &'c mut InsideCallback>
    where T: 'static + Any
{
    unsafe {
        let expected_typeid = format!("{:?}", TypeId::of::<T>());

        let data_ptr = ffi::lua_touserdata(lua.as_lua().0, index);
        if data_ptr.is_null() {
            return Err(lua);
        }

        if ffi::lua_getmetatable(lua.as_lua().0, index) == 0 {
            return Err(lua);
        }

        match "__typeid".push_to_lua(&mut lua) {
            Ok(p) => p.forget(),
            Err(_) => unreachable!(),
        };
        ffi::lua_gettable(lua.as_lua().0, -2);
        match <String as LuaRead<_>>::lua_read(&mut lua) {
            Ok(ref val) if val == &expected_typeid => {}
            _ => {
                return Err(lua);
            }
        }
        ffi::lua_pop(lua.as_lua().0, 2);

        Ok(mem::transmute(data_ptr))
    }
}

/// Represents a user data located inside the Lua context.
pub struct UserdataOnStack<T, L> {
    variable: L,
    marker: PhantomData<T>,
}

impl<'lua, T, L> LuaRead<L> for UserdataOnStack<T, L>
    where L: AsMutLua<'lua> + AsLua<'lua>,
          T: 'lua + Any
{
    #[inline]
    fn lua_read_at_position(mut lua: L, index: i32) -> Result<UserdataOnStack<T, L>, L> {
        unsafe {
            let expected_typeid = format!("{:?}", TypeId::of::<T>());

            let data_ptr = ffi::lua_touserdata(lua.as_lua().0, index);
            if data_ptr.is_null() {
                return Err(lua);
            }

            if ffi::lua_getmetatable(lua.as_lua().0, index) == 0 {
                return Err(lua);
            }

            match "__typeid".push_to_lua(&mut lua) {
                Ok(p) => p.forget(),
                Err(_) => unreachable!(),
            };
            ffi::lua_gettable(lua.as_lua().0, -2);
            match <String as LuaRead<_>>::lua_read(&mut lua) {
                Ok(ref val) if val == &expected_typeid => {}
                _ => {
                    return Err(lua);
                }
            }
            ffi::lua_pop(lua.as_lua().0, 2);

            Ok(UserdataOnStack {
                variable: lua,
                marker: PhantomData,
            })
        }
    }
}

impl<'lua, T, L> Deref for UserdataOnStack<T, L>
    where L: AsLua<'lua>,
          T: 'lua + Any
{
    type Target = T;

    #[inline]
    fn deref(&self) -> &T {
        unsafe {
            let data = ffi::lua_touserdata(self.variable.as_lua().0, -1);
            &*(data as *const T)
        }
    }
}

impl<'lua, T, L> DerefMut for UserdataOnStack<T, L>
    where L: AsMutLua<'lua>,
          T: 'lua + Any
{
    #[inline]
    fn deref_mut(&mut self) -> &mut T {
        unsafe {
            let data = ffi::lua_touserdata(self.variable.as_mut_lua().0, -1);
            &mut *(data as *mut T)
        }
    }
}
<|endoftext|>


<commit_before>use std::cell::RefCell;

use cairo::{self, ImageSurface};
use markup5ever::local_name;

use crate::drawing_ctx::DrawingCtx;
use crate::node::{NodeResult, NodeTrait, NodeType, RsvgNode};
use crate::property_bag::PropertyBag;
use crate::rect::IRect;
use crate::surface_utils::shared_surface::{SharedImageSurface, SurfaceType};

use super::context::{FilterContext, FilterOutput, FilterResult};
use super::input::Input;
use super::{Filter, FilterError, Primitive};

/// The `feMerge` filter primitive.
pub struct Merge {
    base: Primitive,
}

/// The `<feMergeNode>` element.
#[derive(Default)]
pub struct MergeNode {
    in_: RefCell<Option<Input>>,
}

impl Default for Merge {
    /// Constructs a new `Merge` with empty properties.
    #[inline]
    fn default() -> Merge {
        Merge {
            base: Primitive::new::<Self>(),
        }
    }
}

impl NodeTrait for Merge {
    impl_node_as_filter!();

    #[inline]
    fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
        self.base.set_atts(parent, pbag)
    }
}

impl NodeTrait for MergeNode {
    #[inline]
    fn set_atts(&mut self, _parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
        for (attr, value) in pbag.iter() {
            match attr {
                local_name!("in") => {
                    self.in_.replace(Some(Input::parse(attr, value)?));
                }
                _ => (),
            }
        }

        Ok(())
    }
}

impl MergeNode {
    fn render(
        &self,
        ctx: &FilterContext,
        draw_ctx: &mut DrawingCtx,
        bounds: IRect,
        output_surface: Option<SharedImageSurface>,
    ) -> Result<SharedImageSurface, FilterError> {
        let input = ctx.get_input(draw_ctx, self.in_.borrow().as_ref())?;

        if output_surface.is_none() {
            return Ok(input.surface().clone());
        }
        let output_surface = output_surface.unwrap();

        // If we're combining two alpha-only surfaces, the result is alpha-only. Otherwise the
        // result is whatever the non-alpha-only type we're working on (which can be either sRGB or
        // linear sRGB depending on color-interpolation-filters).
        let surface_type = if input.surface().is_alpha_only() {
            output_surface.surface_type()
        } else {
            if !output_surface.is_alpha_only() {
                // All surface types should match (this is enforced by get_input()).
                assert_eq!(
                    output_surface.surface_type(),
                    input.surface().surface_type()
                );
            }

            input.surface().surface_type()
        };

        let output_surface = output_surface.into_image_surface()?;

        {
            let cr = cairo::Context::new(&output_surface);
            cr.rectangle(
                bounds.x0 as f64,
                bounds.y0 as f64,
                (bounds.x1 - bounds.x0) as f64,
                (bounds.y1 - bounds.y0) as f64,
            );
            cr.clip();

            input.surface().set_as_source_surface(&cr, 0f64, 0f64);
            cr.set_operator(cairo::Operator::Over);
            cr.paint();
        }

        Ok(SharedImageSurface::new(output_surface, surface_type)?)
    }
}

impl Filter for Merge {
    fn render(
        &self,
        node: &RsvgNode,
        ctx: &FilterContext,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        // Compute the filter bounds, taking each child node's input into account.
        let mut bounds = self.base.get_bounds(ctx);
        for child in node
            .children()
            .filter(|c| c.borrow().get_type() == NodeType::FeMergeNode)
        {
            if child.borrow().is_in_error() {
                return Err(FilterError::ChildNodeInError);
            }

            let input = ctx.get_input(
                draw_ctx,
                child.borrow().get_impl::<MergeNode>().in_.borrow().as_ref(),
            )?;
            bounds = bounds.add_input(&input);
        }
        let bounds = bounds.into_irect(draw_ctx);

        // Now merge them all.
        let mut output_surface = None;
        for child in node
            .children()
            .filter(|c| c.borrow().get_type() == NodeType::FeMergeNode)
        {
            output_surface = Some(child.borrow().get_impl::<MergeNode>().render(
                ctx,
                draw_ctx,
                bounds,
                output_surface,
            )?);
        }

        let output_surface = match output_surface {
            Some(surface) => surface,
            None => SharedImageSurface::new(
                ImageSurface::create(
                    cairo::Format::ARgb32,
                    ctx.source_graphic().width(),
                    ctx.source_graphic().height(),
                )?,
                SurfaceType::AlphaOnly,
            )?,
        };

        Ok(FilterResult {
            name: self.base.result.borrow().clone(),
            output: FilterOutput {
                surface: output_surface,
                bounds,
            },
        })
    }

    #[inline]
    fn is_affected_by_color_interpolation_filters(&self) -> bool {
        true
    }
}
<commit_msg>filters/merge: remove interior mutability<commit_after>use cairo::{self, ImageSurface};
use markup5ever::local_name;

use crate::drawing_ctx::DrawingCtx;
use crate::node::{NodeResult, NodeTrait, NodeType, RsvgNode};
use crate::property_bag::PropertyBag;
use crate::rect::IRect;
use crate::surface_utils::shared_surface::{SharedImageSurface, SurfaceType};

use super::context::{FilterContext, FilterOutput, FilterResult};
use super::input::Input;
use super::{Filter, FilterError, Primitive};

/// The `feMerge` filter primitive.
pub struct Merge {
    base: Primitive,
}

/// The `<feMergeNode>` element.
#[derive(Default)]
pub struct MergeNode {
    in_: Option<Input>,
}

impl Default for Merge {
    /// Constructs a new `Merge` with empty properties.
    #[inline]
    fn default() -> Merge {
        Merge {
            base: Primitive::new::<Self>(),
        }
    }
}

impl NodeTrait for Merge {
    impl_node_as_filter!();

    #[inline]
    fn set_atts(&mut self, parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
        self.base.set_atts(parent, pbag)
    }
}

impl NodeTrait for MergeNode {
    #[inline]
    fn set_atts(&mut self, _parent: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
        for (attr, value) in pbag.iter() {
            match attr {
                local_name!("in") => self.in_ = Some(Input::parse(attr, value)?),
                _ => (),
            }
        }

        Ok(())
    }
}

impl MergeNode {
    fn render(
        &self,
        ctx: &FilterContext,
        draw_ctx: &mut DrawingCtx,
        bounds: IRect,
        output_surface: Option<SharedImageSurface>,
    ) -> Result<SharedImageSurface, FilterError> {
        let input = ctx.get_input(draw_ctx, self.in_.as_ref())?;

        if output_surface.is_none() {
            return Ok(input.surface().clone());
        }
        let output_surface = output_surface.unwrap();

        // If we're combining two alpha-only surfaces, the result is alpha-only. Otherwise the
        // result is whatever the non-alpha-only type we're working on (which can be either sRGB or
        // linear sRGB depending on color-interpolation-filters).
        let surface_type = if input.surface().is_alpha_only() {
            output_surface.surface_type()
        } else {
            if !output_surface.is_alpha_only() {
                // All surface types should match (this is enforced by get_input()).
                assert_eq!(
                    output_surface.surface_type(),
                    input.surface().surface_type()
                );
            }

            input.surface().surface_type()
        };

        let output_surface = output_surface.into_image_surface()?;

        {
            let cr = cairo::Context::new(&output_surface);
            cr.rectangle(
                bounds.x0 as f64,
                bounds.y0 as f64,
                (bounds.x1 - bounds.x0) as f64,
                (bounds.y1 - bounds.y0) as f64,
            );
            cr.clip();

            input.surface().set_as_source_surface(&cr, 0f64, 0f64);
            cr.set_operator(cairo::Operator::Over);
            cr.paint();
        }

        Ok(SharedImageSurface::new(output_surface, surface_type)?)
    }
}

impl Filter for Merge {
    fn render(
        &self,
        node: &RsvgNode,
        ctx: &FilterContext,
        draw_ctx: &mut DrawingCtx,
    ) -> Result<FilterResult, FilterError> {
        // Compute the filter bounds, taking each child node's input into account.
        let mut bounds = self.base.get_bounds(ctx);
        for child in node
            .children()
            .filter(|c| c.borrow().get_type() == NodeType::FeMergeNode)
        {
            if child.borrow().is_in_error() {
                return Err(FilterError::ChildNodeInError);
            }

            let input = ctx.get_input(
                draw_ctx,
                child.borrow().get_impl::<MergeNode>().in_.as_ref(),
            )?;
            bounds = bounds.add_input(&input);
        }
        let bounds = bounds.into_irect(draw_ctx);

        // Now merge them all.
        let mut output_surface = None;
        for child in node
            .children()
            .filter(|c| c.borrow().get_type() == NodeType::FeMergeNode)
        {
            output_surface = Some(child.borrow().get_impl::<MergeNode>().render(
                ctx,
                draw_ctx,
                bounds,
                output_surface,
            )?);
        }

        let output_surface = match output_surface {
            Some(surface) => surface,
            None => SharedImageSurface::new(
                ImageSurface::create(
                    cairo::Format::ARgb32,
                    ctx.source_graphic().width(),
                    ctx.source_graphic().height(),
                )?,
                SurfaceType::AlphaOnly,
            )?,
        };

        Ok(FilterResult {
            name: self.base.result.borrow().clone(),
            output: FilterOutput {
                surface: output_surface,
                bounds,
            },
        })
    }

    #[inline]
    fn is_affected_by_color_interpolation_filters(&self) -> bool {
        true
    }
}
<|endoftext|>


<commit_before>use ui;
use ui::ncurses::*;
use ui::{CMD_ENTRY_HEIGHT, Window, Size};
use std::cmp;

pub struct CommandEntry {
    parent: Window,
    child:  Window,
}

impl CommandEntry {
    pub fn new(size: Size) -> CommandEntry {
        let parent = newwin(CMD_ENTRY_HEIGHT,
                            size.width,
                            size.height - CMD_ENTRY_HEIGHT,
                            0);
        box_(parent, 0, 0);
        wrefresh(parent);

        let child = derwin(parent,
                           CMD_ENTRY_HEIGHT - 2,
                           size.width - 2,
                           1,
                           1);
        scrollok(child, true);
        keypad(child, true);

        CommandEntry {
            parent: Window::new(parent),
            child:  Window::new(child),
        }
    }

    pub fn read_input_char(&self) -> Option<char> {
        match wgetch(self.child.id) {
            -1 => None,
            i  => ::std::char::from_u32(i as u32),
        }
    }

    pub fn process_char(&self, ch: char) {
        match ch as i32 {
            KEY_BACKSPACE => self.backspace_key(),
            KEY_HOME      => { wmove(self.child.id, 0, 0); },
            KEY_DC        => self.delete_key(),
            KEY_UP | KEY_DOWN => (),
            _ => { wechochar(self.child.id, ch as u32); },
        }
    }

    fn delete_char_at(&self, index: i32) {
        let old_pos = ui::get_cursor_pos(self.child.id);

        wmove(self.child.id, 0, cmp::max(index, 0));
        wdelch(self.child.id);
        wmove(self.child.id, 0, old_pos.x - 1);
        wrefresh(self.child.id);
    }

    fn backspace_key(&self) {
        let pos = ui::get_cursor_pos(self.child.id);

        if pos.x > 0 {
            self.delete_char_at(pos.x - 1);
        }
    }

    fn delete_key(&self) {
        let pos = ui::get_cursor_pos(self.child.id);
        self.delete_char_at(pos.x);
    }
}<commit_msg>Make backspace / delete key handling more stable<commit_after>use ui;
use ui::ncurses::*;
use ui::{CMD_ENTRY_HEIGHT, Window, Size, Position};
use std::cmp;

pub struct CommandEntry {
    parent: Window,
    child:  Window,
}

impl CommandEntry {
    pub fn new(size: Size) -> CommandEntry {
        let parent = newwin(CMD_ENTRY_HEIGHT,
                            size.width,
                            size.height - CMD_ENTRY_HEIGHT,
                            0);
        box_(parent, 0, 0);
        wrefresh(parent);

        let child = derwin(parent,
                           CMD_ENTRY_HEIGHT - 2,
                           size.width - 2,
                           1,
                           1);
        scrollok(child, true);
        keypad(child, true);

        CommandEntry {
            parent: Window::new(parent),
            child:  Window::new(child),
        }
    }

    pub fn read_input_char(&self) -> Option<char> {
        match wgetch(self.child.id) {
            -1 => None,
            i  => ::std::char::from_u32(i as u32),
        }
    }

    fn move_cursor(&self, x_pos: i32) {
        wmove(self.child.id, 0, cmp::max(x_pos, 0));
        wrefresh(self.child.id);
    }

    pub fn process_char(&self, ch: char) {
        match ch as i32 {
            KEY_BACKSPACE => self.backspace_key(),
            KEY_HOME      => self.move_cursor(0),
            KEY_DC        => self.delete_key(),
            KEY_UP | KEY_DOWN => (),
            _ => { wechochar(self.child.id, ch as u32); },
        }
    }

    fn delete_char_at(&self, index: i32) {
        self.move_cursor(index);

        wdelch(self.child.id);
        wrefresh(self.child.id);
    }

    fn backspace_key(&self) {
        let Position { x, .. } = ui::get_cursor_pos(self.child.id);
        self.delete_char_at(x - 1);
    }

    fn delete_key(&self) {
        let Position { x, .. } = ui::get_cursor_pos(self.child.id);
        self.delete_char_at(x);
    }
}<|endoftext|>


<commit_before>#![crate_id(name="hostname", vers="1.0.0", author="Alan Andrade")]
/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Alan Andrade <alan.andradec@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * Synced with:
 *
 * https://www.opensource.apple.com/source/shell_cmds/shell_cmds-170/hostname/hostname.c?txt
 */

extern crate getopts;
extern crate libc;

use std::{os,str};
use getopts::{optflag, getopts, usage};

extern {
    fn gethostname(name: *libc::c_char, namelen: libc::size_t) -> libc::c_int;
    fn sethostname(name: *libc::c_char, namelen: libc::c_int) -> libc::c_int;
}

#[allow(dead_code)]
fn main () { os::set_exit_status(uumain(os::args())); }

pub fn uumain(args: Vec<String>) -> int {
    let program = args.get(0);

    let options = [
        optflag("f", "full", "Default option to show full name"),
        optflag("s", "slice subdomain", "Cuts the subdomain off if any"),
        optflag("h", "help", "Show help"),
        optflag("V", "version", "Show program's version")
    ];

    let matches = match getopts(args.tail(), options) {
        Ok(m) => { m }
        _ => { help_menu(program.as_slice(), options); return 0; }
    };

    if matches.opt_present("h") {
        help_menu(program.as_slice(), options);
        return 0
    }
    if matches.opt_present("V") { version(); return 0 }

    match matches.free.len() {
        0 => {
            let hostname = xgethostname();

            if matches.opt_present("s") {
                let pos = hostname.as_slice().find_str(".");
                if pos.is_some() {
                    println!("{:s}", hostname.as_slice().slice_to(pos.unwrap()));
                    return 0;
                }
            }

            println!("{:s}", hostname.as_slice());
        }
        1 => { xsethostname( matches.free.last().unwrap().as_slice() ) }
        _ => { help_menu(program.as_slice(), options); }
    };

    0
}

fn version() {
    println!("hostname 1.0.0");
}

fn help_menu(program: &str, options: &[getopts::OptGroup]) {
    version();
    println!("");
    println!("Usage:");
    println!("  {:s} [OPTION]... [HOSTNAME]", program);
    println!("");
    print!("{:s}", usage("Print or set the system's host name.", options));
}

fn xgethostname() -> String {
    let namelen = 256u;
    let mut name = Vec::from_elem(namelen, 0u8);

    let err = unsafe {
        gethostname (name.as_mut_ptr() as *libc::c_char,
                                        namelen as libc::size_t)
    };

    if err != 0 {
        fail!("Cannot determine hostname");
    }

    let last_char = name.iter().position(|byte| *byte == 0).unwrap_or(namelen);

    str::from_utf8(name.slice_to(last_char)).unwrap().to_string()
}

fn xsethostname(name: &str) {
    let vec_name: Vec<libc::c_char> = name.bytes().map(|c| c as i8).collect();

    let err = unsafe {
        sethostname (vec_name.as_ptr(), vec_name.len() as i32)
    };

    if err != 0 {
        println!("Cannot set hostname to {:s}", name);
    }
}
<commit_msg>hostname: fix sethostname prototype on linux<commit_after>#![crate_id(name="hostname", vers="1.0.0", author="Alan Andrade")]
/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Alan Andrade <alan.andradec@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * Synced with:
 *
 * https://www.opensource.apple.com/source/shell_cmds/shell_cmds-170/hostname/hostname.c?txt
 */

extern crate getopts;
extern crate libc;

use std::{os,str};
use getopts::{optflag, getopts, usage};

extern {
    fn gethostname(name: *libc::c_char, namelen: libc::size_t) -> libc::c_int;
}

#[cfg(target_os = "macos")]
extern {
    fn sethostname(name: *libc::c_char, namelen: libc::c_int) -> libc::c_int;
}

#[cfg(target_os = "linux")]
extern {
    fn sethostname(name: *libc::c_char, namelen: libc::size_t) -> libc::c_int;
}

#[allow(dead_code)]
fn main () { os::set_exit_status(uumain(os::args())); }

pub fn uumain(args: Vec<String>) -> int {
    let program = args.get(0);

    let options = [
        optflag("f", "full", "Default option to show full name"),
        optflag("s", "slice subdomain", "Cuts the subdomain off if any"),
        optflag("h", "help", "Show help"),
        optflag("V", "version", "Show program's version")
    ];

    let matches = match getopts(args.tail(), options) {
        Ok(m) => { m }
        _ => { help_menu(program.as_slice(), options); return 0; }
    };

    if matches.opt_present("h") {
        help_menu(program.as_slice(), options);
        return 0
    }
    if matches.opt_present("V") { version(); return 0 }

    match matches.free.len() {
        0 => {
            let hostname = xgethostname();

            if matches.opt_present("s") {
                let pos = hostname.as_slice().find_str(".");
                if pos.is_some() {
                    println!("{:s}", hostname.as_slice().slice_to(pos.unwrap()));
                    return 0;
                }
            }

            println!("{:s}", hostname.as_slice());
        }
        1 => { xsethostname( matches.free.last().unwrap().as_slice() ) }
        _ => { help_menu(program.as_slice(), options); }
    };

    0
}

fn version() {
    println!("hostname 1.0.0");
}

fn help_menu(program: &str, options: &[getopts::OptGroup]) {
    version();
    println!("");
    println!("Usage:");
    println!("  {:s} [OPTION]... [HOSTNAME]", program);
    println!("");
    print!("{:s}", usage("Print or set the system's host name.", options));
}

fn xgethostname() -> String {
    let namelen = 256u;
    let mut name = Vec::from_elem(namelen, 0u8);

    let err = unsafe {
        gethostname (name.as_mut_ptr() as *libc::c_char,
                                        namelen as libc::size_t)
    };

    if err != 0 {
        fail!("Cannot determine hostname");
    }

    let last_char = name.iter().position(|byte| *byte == 0).unwrap_or(namelen);

    str::from_utf8(name.slice_to(last_char)).unwrap().to_string()
}

#[cfg(target_os = "macos")]
fn xsethostname(name: &str) {
    let vec_name: Vec<libc::c_char> = name.bytes().map(|c| c as libc::c_char).collect();

    let err = unsafe {
        sethostname (vec_name.as_ptr(), vec_name.len() as libc::c_int)
    };

    if err != 0 {
        println!("Cannot set hostname to {:s}", name);
    }
}

#[cfg(target_os = "linux")]
fn xsethostname(name: &str) {
    let vec_name: Vec<libc::c_char> = name.bytes().map(|c| c as libc::c_char).collect();

    let err = unsafe {
        sethostname (vec_name.as_ptr(), vec_name.len() as libc::size_t)
    };

    if err != 0 {
        println!("Cannot set hostname to {:s}", name);
    }
}
<|endoftext|>


<commit_before>use std::process::exit;
use std::{io, thread, time};

use cpal::traits::{DeviceTrait, HostTrait};
use thiserror::Error;

use super::Sink;
use crate::audio::{convert, AudioPacket};
use crate::config::AudioFormat;
use crate::player::{NUM_CHANNELS, SAMPLE_RATE};

#[cfg(all(
    feature = "rodiojack-backend",
    not(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd"))
))]
compile_error!("Rodio JACK backend is currently only supported on linux.");

#[cfg(feature = "rodio-backend")]
pub fn mk_rodio(device: Option<String>, format: AudioFormat) -> Box<dyn Sink> {
    Box::new(open(cpal::default_host(), device, format))
}

#[cfg(feature = "rodiojack-backend")]
pub fn mk_rodiojack(device: Option<String>, format: AudioFormat) -> Box<dyn Sink> {
    Box::new(open(
        cpal::host_from_id(cpal::HostId::Jack).unwrap(),
        device,
        format,
    ))
}

#[derive(Debug, Error)]
pub enum RodioError {
    #[error("Rodio: no device available")]
    NoDeviceAvailable,
    #[error("Rodio: device \"{0}\" is not available")]
    DeviceNotAvailable(String),
    #[error("Rodio play error: {0}")]
    PlayError(#[from] rodio::PlayError),
    #[error("Rodio stream error: {0}")]
    StreamError(#[from] rodio::StreamError),
    #[error("Cannot get audio devices: {0}")]
    DevicesError(#[from] cpal::DevicesError),
}

pub struct RodioSink {
    rodio_sink: rodio::Sink,
    format: AudioFormat,
    _stream: rodio::OutputStream,
}

fn list_formats(device: &rodio::Device) {
    match device.default_output_config() {
        Ok(cfg) => {
            debug!("  Default config:");
            debug!("    {:?}", cfg);
        }
        Err(e) => {
            // Use loglevel debug, since even the output is only debug
            debug!("Error getting default rodio::Sink config: {}", e);
        }
    };

    match device.supported_output_configs() {
        Ok(mut cfgs) => {
            if let Some(first) = cfgs.next() {
                debug!("  Available configs:");
                debug!("    {:?}", first);
            } else {
                return;
            }

            for cfg in cfgs {
                debug!("    {:?}", cfg);
            }
        }
        Err(e) => {
            debug!("Error getting supported rodio::Sink configs: {}", e);
        }
    }
}

fn list_outputs(host: &cpal::Host) -> Result<(), cpal::DevicesError> {
    let mut default_device_name = None;

    if let Some(default_device) = host.default_output_device() {
        default_device_name = default_device.name().ok();
        println!(
            "Default Audio Device:\n  {}",
            default_device_name.as_deref().unwrap_or("[unknown name]")
        );

        list_formats(&default_device);

        println!("Other Available Audio Devices:");
    } else {
        warn!("No default device was found");
    }

    for device in host.output_devices()? {
        match device.name() {
            Ok(name) if Some(&name) == default_device_name.as_ref() => (),
            Ok(name) => {
                println!("  {}", name);
                list_formats(&device);
            }
            Err(e) => {
                warn!("Cannot get device name: {}", e);
                println!("   [unknown name]");
                list_formats(&device);
            }
        }
    }

    Ok(())
}

fn create_sink(
    host: &cpal::Host,
    device: Option<String>,
) -> Result<(rodio::Sink, rodio::OutputStream), RodioError> {
    let rodio_device = match device {
        Some(ask) if &ask == "?" => {
            let exit_code = match list_outputs(host) {
                Ok(()) => 0,
                Err(e) => {
                    error!("{}", e);
                    1
                }
            };
            exit(exit_code)
        }
        Some(device_name) => {
            host.output_devices()?
                .find(|d| d.name().ok().map_or(false, |name| name == device_name)) // Ignore devices for which getting name fails
                .ok_or(RodioError::DeviceNotAvailable(device_name))?
        }
        None => host
            .default_output_device()
            .ok_or(RodioError::NoDeviceAvailable)?,
    };

    let name = rodio_device.name().ok();
    info!(
        "Using audio device: {}",
        name.as_deref().unwrap_or("[unknown name]")
    );

    let (stream, handle) = rodio::OutputStream::try_from_device(&rodio_device)?;
    let sink = rodio::Sink::try_new(&handle)?;
    Ok((sink, stream))
}

pub fn open(host: cpal::Host, device: Option<String>, format: AudioFormat) -> RodioSink {
    debug!(
        "Using rodio sink with format {:?} and cpal host: {}",
        format,
        host.id().name()
    );

    match format {
        AudioFormat::F32 => {
            #[cfg(target_os = "linux")]
            warn!("Rodio output to Alsa is known to cause garbled sound, consider using `--backend alsa`")
        }
        AudioFormat::S16 => (),
        _ => unimplemented!("Rodio currently only supports F32 and S16 formats"),
    }

    let (sink, stream) = create_sink(&host, device).unwrap();

    debug!("Rodio sink was created");
    RodioSink {
        rodio_sink: sink,
        format,
        _stream: stream,
    }
}

impl Sink for RodioSink {
    start_stop_noop!();

    fn write(&mut self, packet: &AudioPacket) -> io::Result<()> {
        let samples = packet.samples();
        match self.format {
            AudioFormat::F32 => {
                let source =
                    rodio::buffer::SamplesBuffer::new(NUM_CHANNELS as u16, SAMPLE_RATE, samples);
                self.rodio_sink.append(source);
            }
            AudioFormat::S16 => {
                let samples_s16: &[i16] = &convert::to_s16(samples);
                let source = rodio::buffer::SamplesBuffer::new(
                    NUM_CHANNELS as u16,
                    SAMPLE_RATE,
                    samples_s16,
                );
                self.rodio_sink.append(source);
            }
            _ => unreachable!(),
        };

        // Chunk sizes seem to be about 256 to 3000 ish items long.
        // Assuming they're on average 1628 then a half second buffer is:
        // 44100 elements --> about 27 chunks
        while self.rodio_sink.len() > 26 {
            // sleep and wait for rodio to drain a bit
            thread::sleep(time::Duration::from_millis(10));
        }
        Ok(())
    }
}
<commit_msg>Remove warning for Rodio on Alsa (fixed upstream) (#696)<commit_after>use std::process::exit;
use std::{io, thread, time};

use cpal::traits::{DeviceTrait, HostTrait};
use thiserror::Error;

use super::Sink;
use crate::audio::{convert, AudioPacket};
use crate::config::AudioFormat;
use crate::player::{NUM_CHANNELS, SAMPLE_RATE};

#[cfg(all(
    feature = "rodiojack-backend",
    not(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd"))
))]
compile_error!("Rodio JACK backend is currently only supported on linux.");

#[cfg(feature = "rodio-backend")]
pub fn mk_rodio(device: Option<String>, format: AudioFormat) -> Box<dyn Sink> {
    Box::new(open(cpal::default_host(), device, format))
}

#[cfg(feature = "rodiojack-backend")]
pub fn mk_rodiojack(device: Option<String>, format: AudioFormat) -> Box<dyn Sink> {
    Box::new(open(
        cpal::host_from_id(cpal::HostId::Jack).unwrap(),
        device,
        format,
    ))
}

#[derive(Debug, Error)]
pub enum RodioError {
    #[error("Rodio: no device available")]
    NoDeviceAvailable,
    #[error("Rodio: device \"{0}\" is not available")]
    DeviceNotAvailable(String),
    #[error("Rodio play error: {0}")]
    PlayError(#[from] rodio::PlayError),
    #[error("Rodio stream error: {0}")]
    StreamError(#[from] rodio::StreamError),
    #[error("Cannot get audio devices: {0}")]
    DevicesError(#[from] cpal::DevicesError),
}

pub struct RodioSink {
    rodio_sink: rodio::Sink,
    format: AudioFormat,
    _stream: rodio::OutputStream,
}

fn list_formats(device: &rodio::Device) {
    match device.default_output_config() {
        Ok(cfg) => {
            debug!("  Default config:");
            debug!("    {:?}", cfg);
        }
        Err(e) => {
            // Use loglevel debug, since even the output is only debug
            debug!("Error getting default rodio::Sink config: {}", e);
        }
    };

    match device.supported_output_configs() {
        Ok(mut cfgs) => {
            if let Some(first) = cfgs.next() {
                debug!("  Available configs:");
                debug!("    {:?}", first);
            } else {
                return;
            }

            for cfg in cfgs {
                debug!("    {:?}", cfg);
            }
        }
        Err(e) => {
            debug!("Error getting supported rodio::Sink configs: {}", e);
        }
    }
}

fn list_outputs(host: &cpal::Host) -> Result<(), cpal::DevicesError> {
    let mut default_device_name = None;

    if let Some(default_device) = host.default_output_device() {
        default_device_name = default_device.name().ok();
        println!(
            "Default Audio Device:\n  {}",
            default_device_name.as_deref().unwrap_or("[unknown name]")
        );

        list_formats(&default_device);

        println!("Other Available Audio Devices:");
    } else {
        warn!("No default device was found");
    }

    for device in host.output_devices()? {
        match device.name() {
            Ok(name) if Some(&name) == default_device_name.as_ref() => (),
            Ok(name) => {
                println!("  {}", name);
                list_formats(&device);
            }
            Err(e) => {
                warn!("Cannot get device name: {}", e);
                println!("   [unknown name]");
                list_formats(&device);
            }
        }
    }

    Ok(())
}

fn create_sink(
    host: &cpal::Host,
    device: Option<String>,
) -> Result<(rodio::Sink, rodio::OutputStream), RodioError> {
    let rodio_device = match device {
        Some(ask) if &ask == "?" => {
            let exit_code = match list_outputs(host) {
                Ok(()) => 0,
                Err(e) => {
                    error!("{}", e);
                    1
                }
            };
            exit(exit_code)
        }
        Some(device_name) => {
            host.output_devices()?
                .find(|d| d.name().ok().map_or(false, |name| name == device_name)) // Ignore devices for which getting name fails
                .ok_or(RodioError::DeviceNotAvailable(device_name))?
        }
        None => host
            .default_output_device()
            .ok_or(RodioError::NoDeviceAvailable)?,
    };

    let name = rodio_device.name().ok();
    info!(
        "Using audio device: {}",
        name.as_deref().unwrap_or("[unknown name]")
    );

    let (stream, handle) = rodio::OutputStream::try_from_device(&rodio_device)?;
    let sink = rodio::Sink::try_new(&handle)?;
    Ok((sink, stream))
}

pub fn open(host: cpal::Host, device: Option<String>, format: AudioFormat) -> RodioSink {
    info!(
        "Using Rodio sink with format {:?} and cpal host: {}",
        format,
        host.id().name()
    );

    if format != AudioFormat::S16 && format != AudioFormat::F32 {
        unimplemented!("Rodio currently only supports F32 and S16 formats");
    }

    let (sink, stream) = create_sink(&host, device).unwrap();

    debug!("Rodio sink was created");
    RodioSink {
        rodio_sink: sink,
        format,
        _stream: stream,
    }
}

impl Sink for RodioSink {
    start_stop_noop!();

    fn write(&mut self, packet: &AudioPacket) -> io::Result<()> {
        let samples = packet.samples();
        match self.format {
            AudioFormat::F32 => {
                let source =
                    rodio::buffer::SamplesBuffer::new(NUM_CHANNELS as u16, SAMPLE_RATE, samples);
                self.rodio_sink.append(source);
            }
            AudioFormat::S16 => {
                let samples_s16: &[i16] = &convert::to_s16(samples);
                let source = rodio::buffer::SamplesBuffer::new(
                    NUM_CHANNELS as u16,
                    SAMPLE_RATE,
                    samples_s16,
                );
                self.rodio_sink.append(source);
            }
            _ => unreachable!(),
        };

        // Chunk sizes seem to be about 256 to 3000 ish items long.
        // Assuming they're on average 1628 then a half second buffer is:
        // 44100 elements --> about 27 chunks
        while self.rodio_sink.len() > 26 {
            // sleep and wait for rodio to drain a bit
            thread::sleep(time::Duration::from_millis(10));
        }
        Ok(())
    }
}
<|endoftext|>


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

use rustc::hir::def_id::DefId;
use rustc::infer::TransNormalize;
use rustc::ty::subst::{Subst, Substs};
use rustc::ty::{self, Ty, TyCtxt};
use common::*;
use rustc::util::ppaux;

use std::fmt;

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct Instance<'tcx> {
    pub def: DefId,
    pub substs: &'tcx Substs<'tcx>,
}

impl<'tcx> fmt::Display for Instance<'tcx> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        ppaux::parameterized(f, &self.substs, self.def, ppaux::Ns::Value, &[])
    }
}

impl<'tcx> Instance<'tcx> {
    pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>)
               -> Instance<'tcx> {
        assert!(substs.regions().all(|&r| r == ty::ReErased));
        Instance { def: def_id, substs: substs }
    }
    pub fn mono<'a>(scx: &SharedCrateContext<'a, 'tcx>, def_id: DefId) -> Instance<'tcx> {
        Instance::new(def_id, scx.empty_substs_for_def_id(def_id))
    }
}

/// Monomorphizes a type from the AST by first applying the in-scope
/// substitutions and then normalizing any associated types.
pub fn apply_param_substs<'a, 'tcx, T>(scx: &SharedCrateContext<'a, 'tcx>,
                                       param_substs: &Substs<'tcx>,
                                       value: &T)
                                       -> T
    where T: TransNormalize<'tcx>
{
    let tcx = scx.tcx();
    debug!("apply_param_substs(param_substs={:?}, value={:?})", param_substs, value);
    let substituted = value.subst(tcx, param_substs);
    debug!("apply_param_substs: substituted={:?}{}",
           substituted,
           if substituted.has_projection_types() { " [needs projection]" } else { "" });
    tcx.normalize_associated_type(&substituted)
}

/// Returns the normalized type of a struct field
pub fn field_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                          param_substs: &Substs<'tcx>,
                          f: ty::FieldDef<'tcx>)
                          -> Ty<'tcx>
{
    tcx.normalize_associated_type(&f.ty(tcx, param_substs))
}

<commit_msg>cache projections in trans<commit_after>// Copyright 2012-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.

use common::*;
use rustc::hir::def_id::DefId;
use rustc::infer::TransNormalize;
use rustc::ty::fold::{TypeFolder, TypeFoldable};
use rustc::ty::subst::{Subst, Substs};
use rustc::ty::{self, Ty, TyCtxt};
use rustc::util::ppaux;
use rustc::util::common::MemoizationMap;
use std::fmt;

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct Instance<'tcx> {
    pub def: DefId,
    pub substs: &'tcx Substs<'tcx>,
}

impl<'tcx> fmt::Display for Instance<'tcx> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        ppaux::parameterized(f, &self.substs, self.def, ppaux::Ns::Value, &[])
    }
}

impl<'tcx> Instance<'tcx> {
    pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>)
               -> Instance<'tcx> {
        assert!(substs.regions().all(|&r| r == ty::ReErased));
        Instance { def: def_id, substs: substs }
    }
    pub fn mono<'a>(scx: &SharedCrateContext<'a, 'tcx>, def_id: DefId) -> Instance<'tcx> {
        Instance::new(def_id, scx.empty_substs_for_def_id(def_id))
    }
}

/// Monomorphizes a type from the AST by first applying the in-scope
/// substitutions and then normalizing any associated types.
pub fn apply_param_substs<'a, 'tcx, T>(scx: &SharedCrateContext<'a, 'tcx>,
                                       param_substs: &Substs<'tcx>,
                                       value: &T)
                                       -> T
    where T: TransNormalize<'tcx>
{
    let tcx = scx.tcx();
    debug!("apply_param_substs(param_substs={:?}, value={:?})", param_substs, value);
    let substituted = value.subst(tcx, param_substs);
    let substituted = scx.tcx().erase_regions(&substituted);
    AssociatedTypeNormalizer::new(scx).fold(&substituted)
}

/// Returns the normalized type of a struct field
pub fn field_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                          param_substs: &Substs<'tcx>,
                          f: ty::FieldDef<'tcx>)
                          -> Ty<'tcx>
{
    tcx.normalize_associated_type(&f.ty(tcx, param_substs))
}

struct AssociatedTypeNormalizer<'a, 'b: 'a, 'gcx: 'b> {
    shared: &'a SharedCrateContext<'b, 'gcx>,
}

impl<'a, 'b, 'gcx> AssociatedTypeNormalizer<'a, 'b, 'gcx> {
    fn new(shared: &'a SharedCrateContext<'b, 'gcx>) -> Self {
        AssociatedTypeNormalizer {
            shared: shared,
        }
    }

    fn fold<T:TypeFoldable<'gcx>>(&mut self, value: &T) -> T {
        if !value.has_projection_types() {
            value.clone()
        } else {
            value.fold_with(self)
        }
    }
}

impl<'a, 'b, 'gcx> TypeFolder<'gcx, 'gcx> for AssociatedTypeNormalizer<'a, 'b, 'gcx> {
    fn tcx<'c>(&'c self) -> TyCtxt<'c, 'gcx, 'gcx> {
        self.shared.tcx()
    }

    fn fold_ty(&mut self, ty: Ty<'gcx>) -> Ty<'gcx> {
        if !ty.has_projection_types() {
            ty
        } else {
            self.shared.project_cache().memoize(ty, || {
                debug!("AssociatedTypeNormalizer: ty={:?}", ty);
                self.shared.tcx().normalize_associated_type(&ty)
            })
        }
    }
}
<|endoftext|>


<commit_before>use super::{span_of_attrs, Pass};
use crate::clean::*;
use crate::core::DocContext;
use crate::fold::DocFolder;
use crate::html::markdown::opts;
use core::ops::Range;
use pulldown_cmark::{Event, Parser, Tag};
use regex::Regex;
use rustc_errors::Applicability;
use std::lazy::SyncLazy;
use std::mem;

crate const CHECK_BARE_URLS: Pass = Pass {
    name: "check-bare-urls",
    run: check_bare_urls,
    description: "detects URLs that are not hyperlinks",
};

const URL_REGEX: SyncLazy<Regex> = SyncLazy::new(|| {
    Regex::new(concat!(
        r"https?://",                          // url scheme
        r"([-a-zA-Z0-9@:%._\+~#=]{2,256}\.)+", // one or more subdomains
        r"[a-zA-Z]{2,63}",                     // root domain
        r"\b([-a-zA-Z0-9@:%_\+.~#?&/=]*)"      // optional query or url fragments
    ))
    .expect("failed to build regex")
});

struct BareUrlsLinter<'a, 'tcx> {
    cx: &'a mut DocContext<'tcx>,
}

impl<'a, 'tcx> BareUrlsLinter<'a, 'tcx> {
    fn find_raw_urls(
        &self,
        text: &str,
        range: Range<usize>,
        f: &impl Fn(&DocContext<'_>, &str, &str, Range<usize>),
    ) {
        trace!("looking for raw urls in {}", text);
        // For now, we only check "full" URLs (meaning, starting with "http://" or "https://").
        for match_ in URL_REGEX.find_iter(&text) {
            let url = match_.as_str();
            let url_range = match_.range();
            f(
                self.cx,
                "this URL is not a hyperlink",
                url,
                Range { start: range.start + url_range.start, end: range.start + url_range.end },
            );
        }
    }
}

crate fn check_bare_urls(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
    BareUrlsLinter { cx }.fold_crate(krate)
}

impl<'a, 'tcx> DocFolder for BareUrlsLinter<'a, 'tcx> {
    fn fold_item(&mut self, item: Item) -> Option<Item> {
        let hir_id = match DocContext::as_local_hir_id(self.cx.tcx, item.def_id) {
            Some(hir_id) => hir_id,
            None => {
                // If non-local, no need to check anything.
                return Some(self.fold_item_recur(item));
            }
        };
        let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
        if !dox.is_empty() {
            let report_diag = |cx: &DocContext<'_>, msg: &str, url: &str, range: Range<usize>| {
                let sp = super::source_span_for_markdown_range(cx.tcx, &dox, &range, &item.attrs)
                    .or_else(|| span_of_attrs(&item.attrs))
                    .unwrap_or(item.span.inner());
                cx.tcx.struct_span_lint_hir(crate::lint::BARE_URLS, hir_id, sp, |lint| {
                    lint.build(msg)
                        .span_suggestion(
                            sp,
                            "use an automatic link instead",
                            format!("<{}>", url),
                            Applicability::MachineApplicable,
                        )
                        .emit()
                });
            };

            let mut p = Parser::new_ext(&dox, opts()).into_offset_iter();

            while let Some((event, range)) = p.next() {
                match event {
                    Event::Text(s) => self.find_raw_urls(&s, range, &report_diag),
                    // We don't want to check the text inside code blocks or links.
                    Event::Start(tag @ (Tag::CodeBlock(_) | Tag::Link(..))) => {
                        while let Some((event, _)) = p.next() {
                            match event {
                                Event::End(end)
                                    if mem::discriminant(&end) == mem::discriminant(&tag) =>
                                {
                                    break;
                                }
                                _ => {}
                            }
                        }
                    }
                    _ => {}
                }
            }
        }

        Some(self.fold_item_recur(item))
    }
}
<commit_msg>Auto merge of #84034 - jyn514:regex-in-loop, r=Mark-Simulacrum<commit_after>use super::{span_of_attrs, Pass};
use crate::clean::*;
use crate::core::DocContext;
use crate::fold::DocFolder;
use crate::html::markdown::opts;
use core::ops::Range;
use pulldown_cmark::{Event, Parser, Tag};
use regex::Regex;
use rustc_errors::Applicability;
use std::lazy::SyncLazy;
use std::mem;

crate const CHECK_BARE_URLS: Pass = Pass {
    name: "check-bare-urls",
    run: check_bare_urls,
    description: "detects URLs that are not hyperlinks",
};

static URL_REGEX: SyncLazy<Regex> = SyncLazy::new(|| {
    Regex::new(concat!(
        r"https?://",                          // url scheme
        r"([-a-zA-Z0-9@:%._\+~#=]{2,256}\.)+", // one or more subdomains
        r"[a-zA-Z]{2,63}",                     // root domain
        r"\b([-a-zA-Z0-9@:%_\+.~#?&/=]*)"      // optional query or url fragments
    ))
    .expect("failed to build regex")
});

struct BareUrlsLinter<'a, 'tcx> {
    cx: &'a mut DocContext<'tcx>,
}

impl<'a, 'tcx> BareUrlsLinter<'a, 'tcx> {
    fn find_raw_urls(
        &self,
        text: &str,
        range: Range<usize>,
        f: &impl Fn(&DocContext<'_>, &str, &str, Range<usize>),
    ) {
        trace!("looking for raw urls in {}", text);
        // For now, we only check "full" URLs (meaning, starting with "http://" or "https://").
        for match_ in URL_REGEX.find_iter(&text) {
            let url = match_.as_str();
            let url_range = match_.range();
            f(
                self.cx,
                "this URL is not a hyperlink",
                url,
                Range { start: range.start + url_range.start, end: range.start + url_range.end },
            );
        }
    }
}

crate fn check_bare_urls(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
    BareUrlsLinter { cx }.fold_crate(krate)
}

impl<'a, 'tcx> DocFolder for BareUrlsLinter<'a, 'tcx> {
    fn fold_item(&mut self, item: Item) -> Option<Item> {
        let hir_id = match DocContext::as_local_hir_id(self.cx.tcx, item.def_id) {
            Some(hir_id) => hir_id,
            None => {
                // If non-local, no need to check anything.
                return Some(self.fold_item_recur(item));
            }
        };
        let dox = item.attrs.collapsed_doc_value().unwrap_or_default();
        if !dox.is_empty() {
            let report_diag = |cx: &DocContext<'_>, msg: &str, url: &str, range: Range<usize>| {
                let sp = super::source_span_for_markdown_range(cx.tcx, &dox, &range, &item.attrs)
                    .or_else(|| span_of_attrs(&item.attrs))
                    .unwrap_or(item.span.inner());
                cx.tcx.struct_span_lint_hir(crate::lint::BARE_URLS, hir_id, sp, |lint| {
                    lint.build(msg)
                        .span_suggestion(
                            sp,
                            "use an automatic link instead",
                            format!("<{}>", url),
                            Applicability::MachineApplicable,
                        )
                        .emit()
                });
            };

            let mut p = Parser::new_ext(&dox, opts()).into_offset_iter();

            while let Some((event, range)) = p.next() {
                match event {
                    Event::Text(s) => self.find_raw_urls(&s, range, &report_diag),
                    // We don't want to check the text inside code blocks or links.
                    Event::Start(tag @ (Tag::CodeBlock(_) | Tag::Link(..))) => {
                        while let Some((event, _)) = p.next() {
                            match event {
                                Event::End(end)
                                    if mem::discriminant(&end) == mem::discriminant(&tag) =>
                                {
                                    break;
                                }
                                _ => {}
                            }
                        }
                    }
                    _ => {}
                }
            }
        }

        Some(self.fold_item_recur(item))
    }
}
<|endoftext|>


<commit_before>#![feature(phase)]
#![feature(tuple_indexing)]

#[phase(plugin)]
extern crate gl_generator;
extern crate glutin;
extern crate libc;

mod gl {
    generate_gl_bindings! {
        api: "gl",
        profile: "core",
        version: "1.1",
        generator: "struct"
    }
}

#[cfg(feature = "headless")]
#[test]
fn main() {
    let window = glutin::HeadlessRendererBuilder::new(1024, 768).build().unwrap();

    unsafe { window.make_current() };

    let gl = gl::Gl::load_with(|symbol| window.get_proc_address(symbol));

    gl.ClearColor(0.0, 1.0, 0.0, 1.0);
    gl.Clear(gl::COLOR_BUFFER_BIT);

    let mut value: (u8, u8, u8, u8) = unsafe { std::mem::uninitialized() };
    unsafe { gl.ReadPixels(0, 0, 1, 1, gl::RGBA, gl::UNSIGNED_BYTE, std::mem::transmute(&mut value)) };

    assert_eq!(value, (0, 255, 0, 255));
}
<commit_msg>Test now less restrictive<commit_after>#![feature(phase)]
#![feature(tuple_indexing)]

#[phase(plugin)]
extern crate gl_generator;
extern crate glutin;
extern crate libc;

mod gl {
    generate_gl_bindings! {
        api: "gl",
        profile: "core",
        version: "1.1",
        generator: "struct"
    }
}

#[cfg(feature = "headless")]
#[test]
fn main() {
    let window = glutin::HeadlessRendererBuilder::new(1024, 768).build().unwrap();

    unsafe { window.make_current() };

    let gl = gl::Gl::load_with(|symbol| window.get_proc_address(symbol));

    gl.ClearColor(0.0, 1.0, 0.0, 1.0);
    gl.Clear(gl::COLOR_BUFFER_BIT);

    let mut value: (u8, u8, u8, u8) = unsafe { std::mem::uninitialized() };
    unsafe { gl.ReadPixels(0, 0, 1, 1, gl::RGBA, gl::UNSIGNED_BYTE, std::mem::transmute(&mut value)) };

    assert!(value == (0, 255, 0, 255) || value == (0, 64, 0, 255) ||
        value == (0, 64, 0, 255) || value == (0, 64, 0, 0));
}
<|endoftext|>


<commit_before>extern crate lp_modeler;

use std::collections::HashMap;

use lp_modeler::variables::*;
use lp_modeler::variables::LpExpression::*;
use lp_modeler::operations::LpOperations;
use lp_modeler::problem::{LpObjective, LpProblem, LpFileFormat};
use lp_modeler::solvers::{SolverTrait, CbcSolver};

#[test]
fn test_readme_example_1() {
    let ref a = LpInteger::new("a");
    let ref b = LpInteger::new("b");
    let ref c = LpInteger::new("c");

    let mut problem = LpProblem::new("One Problem", LpObjective::Maximize);
    problem += 10.0 * a + 20.0 * b;

    problem += (500*a + 1200*b + 1500*c).le(10000);
    problem += (a).le(b);

    let solver = CbcSolver::new().temp_solution_file(format!("{}.sol", problem.name));

    match solver.run(&problem) {
        Ok((status, res)) => {
            println!("Status {:?}", status);
            for (name, value) in res.iter() {
                println!("value of {} = {}", name, value);
            }
        },
        Err(msg) => println!("{}", msg),
    }

    let output1 = "\\ One Problem

Maximize
  obj: 10 a + 20 b

Subject To
  c1: 500 a + 1200 b + 1500 c <= 10000
  c2: a - b <= 0

".to_string();
    let output2 = problem.to_lp_file_format();
    let output2 = output2.split("Generals").collect::<Vec<&str>>();
    let output2 = output2[0];
    assert_eq!(output1, output2);
}

#[test]
fn test_readme_example_2() {
    // Problem Data
    let men = vec!["A", "B", "C"];
    let women = vec!["D", "E", "F"];
    let scores: HashMap<(&'static str, &'static str), f32> = [
        (("A", "D"), 50.0),
        (("A", "E"), 75.0),
        (("A", "F"), 75.0),
        (("B", "D"), 60.0),
        (("B", "E"), 95.0),
        (("B", "F"), 80.0),
        (("C", "D"), 60.0),
        (("C", "E"), 70.0),
        (("C", "F"), 80.0),
        ].iter().cloned().collect();

    // Define Problem
    let mut problem = LpProblem::new("Matchmaking", LpObjective::Maximize);

    // Define Variables
    let mut vars = HashMap::new();
    for m in &men{
        for w in &women{
            vars.insert((m, w), LpBinary::new(&format!("{}_{}", m, w)));
        }
    }

    // Define Objective Function
    let mut obj_vec: Vec<LpExpression> = Vec::new();
    for (&(&m, &w), var) in &vars{
        let obj_coef = scores.get(&(m, w)).unwrap();
        obj_vec.push(*obj_coef * var);
    }
    problem += lp_sum(&obj_vec);

    // Define Constraints
    // Constraint 1: Each man must be assigned to exactly one woman
    for m in &men{
        let mut constr_vec = Vec::new();

        for w in &women{
            constr_vec.push(1.0 * vars.get(&(m, w)).unwrap());
        }

        problem += lp_sum(&constr_vec).equal(1);
    }

    // Constraint 2: Each woman must be assigned to exactly one man
    for w in &women{
        let mut constr_vec = Vec::new();

        for m in &men{
            constr_vec.push(1.0 * vars.get(&(m, w)).unwrap());
        }

        problem += lp_sum(&constr_vec).equal(1);
    }

    // Optionally write to file
    // let result = problem.write_lp("problem.lp");
    // match result{
    //     Ok(_) => println!("Written to file"),
    //     Err(msg) => println!("{}", msg)
    // }

    // Run Solver
    let solver = CbcSolver::new().temp_solution_file(format!("{}.sol", problem.name));
    let result = solver.run(&problem);

    // Terminate if error, or assign status & variable values
    assert!(result.is_ok(), result.unwrap_err());
    let (solver_status, var_values) = result.unwrap();

    // Compute final objective function value
    let mut obj_value = 0f32;
    for (&(&m, &w), var) in &vars{
        let obj_coef = scores.get(&(m, w)).unwrap();
        let var_value = var_values.get(&var.name).unwrap();

        obj_value += obj_coef * var_value;
    }

    // Print output
    println!("Status: {:?}", solver_status);
    println!("Objective Value: {}", obj_value);
    // println!("{:?}", var_values);
    for (var_name, var_value) in &var_values{
        let int_var_value = *var_value as u32;
        if int_var_value == 1{
            println!("{} = {}", var_name, int_var_value);
        }
    }

    assert_eq!(solver_status, lp_modeler::solvers::Status::Optimal);
    assert_eq!(obj_value, 230f32);
    assert_eq!(*var_values.get("A_F").unwrap(), 1f32);
    assert_eq!(*var_values.get("B_E").unwrap(), 1f32);
    assert_eq!(*var_values.get("C_D").unwrap(), 1f32);
}<commit_msg>Removed hack to set solution filenames<commit_after>extern crate lp_modeler;

use std::collections::HashMap;

use lp_modeler::variables::*;
use lp_modeler::variables::LpExpression::*;
use lp_modeler::operations::LpOperations;
use lp_modeler::problem::{LpObjective, LpProblem, LpFileFormat};
use lp_modeler::solvers::{SolverTrait, CbcSolver};

#[test]
fn test_readme_example_1() {
    let ref a = LpInteger::new("a");
    let ref b = LpInteger::new("b");
    let ref c = LpInteger::new("c");

    let mut problem = LpProblem::new("One Problem", LpObjective::Maximize);
    problem += 10.0 * a + 20.0 * b;

    problem += (500*a + 1200*b + 1500*c).le(10000);
    problem += (a).le(b);

    let solver = CbcSolver::new();

    match solver.run(&problem) {
        Ok((status, res)) => {
            println!("Status {:?}", status);
            for (name, value) in res.iter() {
                println!("value of {} = {}", name, value);
            }
        },
        Err(msg) => println!("{}", msg),
    }

    let output1 = "\\ One Problem

Maximize
  obj: 10 a + 20 b

Subject To
  c1: 500 a + 1200 b + 1500 c <= 10000
  c2: a - b <= 0

".to_string();
    let output2 = problem.to_lp_file_format();
    let output2 = output2.split("Generals").collect::<Vec<&str>>();
    let output2 = output2[0];
    assert_eq!(output1, output2);
}

#[test]
fn test_readme_example_2() {
    // Problem Data
    let men = vec!["A", "B", "C"];
    let women = vec!["D", "E", "F"];
    let scores: HashMap<(&'static str, &'static str), f32> = [
        (("A", "D"), 50.0),
        (("A", "E"), 75.0),
        (("A", "F"), 75.0),
        (("B", "D"), 60.0),
        (("B", "E"), 95.0),
        (("B", "F"), 80.0),
        (("C", "D"), 60.0),
        (("C", "E"), 70.0),
        (("C", "F"), 80.0),
        ].iter().cloned().collect();

    // Define Problem
    let mut problem = LpProblem::new("Matchmaking", LpObjective::Maximize);

    // Define Variables
    let mut vars = HashMap::new();
    for m in &men{
        for w in &women{
            vars.insert((m, w), LpBinary::new(&format!("{}_{}", m, w)));
        }
    }

    // Define Objective Function
    let mut obj_vec: Vec<LpExpression> = Vec::new();
    for (&(&m, &w), var) in &vars{
        let obj_coef = scores.get(&(m, w)).unwrap();
        obj_vec.push(*obj_coef * var);
    }
    problem += lp_sum(&obj_vec);

    // Define Constraints
    // Constraint 1: Each man must be assigned to exactly one woman
    for m in &men{
        let mut constr_vec = Vec::new();

        for w in &women{
            constr_vec.push(1.0 * vars.get(&(m, w)).unwrap());
        }

        problem += lp_sum(&constr_vec).equal(1);
    }

    // Constraint 2: Each woman must be assigned to exactly one man
    for w in &women{
        let mut constr_vec = Vec::new();

        for m in &men{
            constr_vec.push(1.0 * vars.get(&(m, w)).unwrap());
        }

        problem += lp_sum(&constr_vec).equal(1);
    }

    // Optionally write to file
    // let result = problem.write_lp("problem.lp");
    // match result{
    //     Ok(_) => println!("Written to file"),
    //     Err(msg) => println!("{}", msg)
    // }

    // Run Solver
    let solver = CbcSolver::new();
    let result = solver.run(&problem);

    // Terminate if error, or assign status & variable values
    assert!(result.is_ok(), result.unwrap_err());
    let (solver_status, var_values) = result.unwrap();

    // Compute final objective function value
    let mut obj_value = 0f32;
    for (&(&m, &w), var) in &vars{
        let obj_coef = scores.get(&(m, w)).unwrap();
        let var_value = var_values.get(&var.name).unwrap();

        obj_value += obj_coef * var_value;
    }

    // Print output
    println!("Status: {:?}", solver_status);
    println!("Objective Value: {}", obj_value);
    // println!("{:?}", var_values);
    for (var_name, var_value) in &var_values{
        let int_var_value = *var_value as u32;
        if int_var_value == 1{
            println!("{} = {}", var_name, int_var_value);
        }
    }

    assert_eq!(solver_status, lp_modeler::solvers::Status::Optimal);
    assert_eq!(obj_value, 230f32);
    assert_eq!(*var_values.get("A_F").unwrap(), 1f32);
    assert_eq!(*var_values.get("B_E").unwrap(), 1f32);
    assert_eq!(*var_values.get("C_D").unwrap(), 1f32);
}<|endoftext|>