<commit_before>// run-rustfix

#![warn(clippy::or_fun_call)]
#![allow(dead_code)]

use std::collections::BTreeMap;
use std::collections::HashMap;
use std::time::Duration;

/// Checks implementation of the `OR_FUN_CALL` lint.
fn or_fun_call() {
    struct Foo;

    impl Foo {
        fn new() -> Foo {
            Foo
        }
    }

    enum Enum {
        A(i32),
    }

    fn make<T>() -> T {
        unimplemented!();
    }

    let with_enum = Some(Enum::A(1));
    with_enum.unwrap_or(Enum::A(5));

    let with_const_fn = Some(Duration::from_secs(1));
    with_const_fn.unwrap_or(Duration::from_secs(5));

    let with_constructor = Some(vec![1]);
    with_constructor.unwrap_or(make());

    let with_new = Some(vec![1]);
    with_new.unwrap_or(Vec::new());

    let with_const_args = Some(vec![1]);
    with_const_args.unwrap_or(Vec::with_capacity(12));

    let with_err: Result<_, ()> = Ok(vec![1]);
    with_err.unwrap_or(make());

    let with_err_args: Result<_, ()> = Ok(vec![1]);
    with_err_args.unwrap_or(Vec::with_capacity(12));

    let with_default_trait = Some(1);
    with_default_trait.unwrap_or(Default::default());

    let with_default_type = Some(1);
    with_default_type.unwrap_or(u64::default());

    let with_vec = Some(vec![1]);
    with_vec.unwrap_or(vec![]);

    let without_default = Some(Foo);
    without_default.unwrap_or(Foo::new());

    let mut map = HashMap::<u64, String>::new();
    map.entry(42).or_insert(String::new());

    let mut btree = BTreeMap::<u64, String>::new();
    btree.entry(42).or_insert(String::new());

    let stringy = Some(String::from(""));
    let _ = stringy.unwrap_or("".to_owned());

    let opt = Some(1);
    let hello = "Hello";
    let _ = opt.ok_or(format!("{} world.", hello));
}

struct Foo(u8);
struct Bar(String, Duration);
#[rustfmt::skip]
fn test_or_with_ctors() {
    let opt = Some(1);
    let opt_opt = Some(Some(1));
    // we also test for const promotion, this makes sure we don't hit that
    let two = 2;

    let _ = opt_opt.unwrap_or(Some(2));
    let _ = opt_opt.unwrap_or(Some(two));
    let _ = opt.ok_or(Some(2));
    let _ = opt.ok_or(Some(two));
    let _ = opt.ok_or(Foo(2));
    let _ = opt.ok_or(Foo(two));
    let _ = opt.or(Some(2));
    let _ = opt.or(Some(two));

    let _ = Some("a".to_string()).or(Some("b".to_string()));

    let b = "b".to_string();
    let _ = Some(Bar("a".to_string(), Duration::from_secs(1)))
        .or(Some(Bar(b, Duration::from_secs(2))));
}

// Issue 4514 - early return
fn f() -> Option<()> {
    let a = Some(1);
    let b = 1i32;

    let _ = a.unwrap_or(b.checked_mul(3)?.min(240));

    Some(())
}

fn main() {}
<commit_msg>Add tests<commit_after>// run-rustfix

#![warn(clippy::or_fun_call)]
#![allow(dead_code)]

use std::collections::BTreeMap;
use std::collections::HashMap;
use std::time::Duration;

/// Checks implementation of the `OR_FUN_CALL` lint.
fn or_fun_call() {
    struct Foo;

    impl Foo {
        fn new() -> Foo {
            Foo
        }
    }

    enum Enum {
        A(i32),
    }

    fn make<T>() -> T {
        unimplemented!();
    }

    let with_enum = Some(Enum::A(1));
    with_enum.unwrap_or(Enum::A(5));

    let with_const_fn = Some(Duration::from_secs(1));
    with_const_fn.unwrap_or(Duration::from_secs(5));

    let with_constructor = Some(vec![1]);
    with_constructor.unwrap_or(make());

    let with_new = Some(vec![1]);
    with_new.unwrap_or(Vec::new());

    let with_const_args = Some(vec![1]);
    with_const_args.unwrap_or(Vec::with_capacity(12));

    let with_err: Result<_, ()> = Ok(vec![1]);
    with_err.unwrap_or(make());

    let with_err_args: Result<_, ()> = Ok(vec![1]);
    with_err_args.unwrap_or(Vec::with_capacity(12));

    let with_default_trait = Some(1);
    with_default_trait.unwrap_or(Default::default());

    let with_default_type = Some(1);
    with_default_type.unwrap_or(u64::default());

    let with_vec = Some(vec![1]);
    with_vec.unwrap_or(vec![]);

    let without_default = Some(Foo);
    without_default.unwrap_or(Foo::new());

    let mut map = HashMap::<u64, String>::new();
    map.entry(42).or_insert(String::new());

    let mut btree = BTreeMap::<u64, String>::new();
    btree.entry(42).or_insert(String::new());

    let stringy = Some(String::from(""));
    let _ = stringy.unwrap_or("".to_owned());

    let opt = Some(1);
    let hello = "Hello";
    let _ = opt.ok_or(format!("{} world.", hello));
}

struct Foo(u8);
struct Bar(String, Duration);
#[rustfmt::skip]
fn test_or_with_ctors() {
    let opt = Some(1);
    let opt_opt = Some(Some(1));
    // we also test for const promotion, this makes sure we don't hit that
    let two = 2;

    let _ = opt_opt.unwrap_or(Some(2));
    let _ = opt_opt.unwrap_or(Some(two));
    let _ = opt.ok_or(Some(2));
    let _ = opt.ok_or(Some(two));
    let _ = opt.ok_or(Foo(2));
    let _ = opt.ok_or(Foo(two));
    let _ = opt.or(Some(2));
    let _ = opt.or(Some(two));

    let _ = Some("a".to_string()).or(Some("b".to_string()));

    let b = "b".to_string();
    let _ = Some(Bar("a".to_string(), Duration::from_secs(1)))
        .or(Some(Bar(b, Duration::from_secs(2))));

    let vec = vec!["foo"];
    let _ = opt.ok_or(vec.len());

    let array = ["foo"];
    let _ = opt.ok_or(array.len());

    let slice = &["foo"][..];
    let _ = opt.ok_or(slice.len());
}

// Issue 4514 - early return
fn f() -> Option<()> {
    let a = Some(1);
    let b = 1i32;

    let _ = a.unwrap_or(b.checked_mul(3)?.min(240));

    Some(())
}

fn main() {}
<|endoftext|>


<commit_before>use proc_macro2::{Span, TokenStream};
use quote::{format_ident, quote};
use syn::{
    parse_quote, AngleBracketedGenericArguments, Attribute, Data, DeriveInput, Field, Fields,
    GenericArgument, GenericParam, Generics, ImplGenerics, ParenthesizedGenericArguments,
    PathArguments, Type, TypeGenerics, TypePath, TypeReference, TypeSlice, Variant,
};

enum StructKind {
    Struct,
    Tuple,
}

enum DataKind {
    Struct(Vec<Field>, StructKind),
    Enum(Vec<Variant>),
    Unit,
}

pub fn expand_derive_outgoing(input: DeriveInput) -> syn::Result<TokenStream> {
    let derive_deserialize = if no_deserialize_in_attrs(&input.attrs) {
        TokenStream::new()
    } else {
        quote!(::ruma_api::exports::serde::Deserialize)
    };

    let data = match input.data.clone() {
        Data::Union(_) => panic!("#[derive(Outgoing)] does not support Union types"),
        Data::Enum(e) => DataKind::Enum(e.variants.into_iter().collect()),
        Data::Struct(s) => match s.fields {
            Fields::Named(fs) => {
                DataKind::Struct(fs.named.into_iter().collect(), StructKind::Struct)
            }
            Fields::Unnamed(fs) => {
                DataKind::Struct(fs.unnamed.into_iter().collect(), StructKind::Tuple)
            }
            Fields::Unit => DataKind::Unit,
        },
    };

    match data {
        DataKind::Unit => Ok(impl_outgoing_with_incoming_self(&input)),
        DataKind::Enum(mut vars) => {
            let mut found_lifetime = false;
            for var in &mut vars {
                for field in &mut var.fields {
                    if strip_lifetimes(&mut field.ty) {
                        found_lifetime = true;
                    }
                }
            }

            let original_ident = &input.ident;
            let (original_impl_gen, original_ty_gen, _) = input.generics.split_for_impl();

            if !found_lifetime {
                return Ok(impl_outgoing_with_incoming_self(&input));
            }

            let vis = input.vis;
            let doc = format!("'Incoming' variant of [{ty}](enum.{ty}.html).", ty = &input.ident);
            let incoming_ident =
                format_ident!("Incoming{}", original_ident, span = Span::call_site());
            let mut gen_copy = input.generics.clone();
            let (impl_gen, ty_gen) = split_for_impl_lifetime_less(&mut gen_copy);

            Ok(quote! {
                #[doc = #doc]
                #[derive(Debug, #derive_deserialize)]
                #vis enum #incoming_ident #ty_gen { #( #vars, )* }

                impl #original_impl_gen ::ruma_api::Outgoing for #original_ident #original_ty_gen {
                    type Incoming = #incoming_ident #impl_gen;
                }
            })
        }
        DataKind::Struct(mut fields, struct_kind) => {
            let mut found_lifetime = false;
            for field in &mut fields {
                if strip_lifetimes(&mut field.ty) {
                    found_lifetime = true;
                }
            }

            let original_ident = &input.ident;
            let (original_impl_gen, original_ty_gen, _) = input.generics.split_for_impl();

            if !found_lifetime {
                return Ok(impl_outgoing_with_incoming_self(&input));
            }

            let vis = input.vis;
            let doc = format!("'Incoming' variant of [{ty}](struct.{ty}.html).", ty = &input.ident);
            let incoming_ident =
                format_ident!("Incoming{}", original_ident, span = Span::call_site());
            let mut gen_copy = input.generics.clone();
            let (impl_gen, ty_gen) = split_for_impl_lifetime_less(&mut gen_copy);

            let struct_def = match struct_kind {
                StructKind::Struct => quote! { { #(#fields,)* } },
                StructKind::Tuple => quote! { ( #(#fields,)* ); },
            };

            Ok(quote! {
                #[doc = #doc]
                #[derive(Debug, #derive_deserialize)]
                #vis struct #incoming_ident #ty_gen #struct_def

                impl #original_impl_gen ::ruma_api::Outgoing for #original_ident #original_ty_gen {
                    type Incoming = #incoming_ident #impl_gen;
                }
            })
        }
    }
}

fn no_deserialize_in_attrs(attrs: &[Attribute]) -> bool {
    attrs.iter().any(|attr| attr.path.is_ident("incoming_no_deserialize"))
}

fn impl_outgoing_with_incoming_self(input: &DeriveInput) -> TokenStream {
    let ident = &input.ident;
    let (impl_gen, ty_gen, _) = input.generics.split_for_impl();

    quote! {
        impl #impl_gen ::ruma_api::Outgoing for #ident #ty_gen {
            type Incoming = Self;
        }
    }
}

fn split_for_impl_lifetime_less(generics: &mut Generics) -> (ImplGenerics, TypeGenerics) {
    generics.params = generics
        .params
        .clone()
        .into_iter()
        .filter(|param| !matches!(param, GenericParam::Lifetime(_)))
        .collect();

    let (impl_gen, ty_gen, _) = generics.split_for_impl();
    (impl_gen, ty_gen)
}

fn strip_lifetimes(field_type: &mut Type) -> bool {
    match field_type {
        // T<'a> -> IncomingT
        // The IncomingT has to be declared by the user of this derive macro.
        Type::Path(TypePath { path, .. }) => {
            let mut has_lifetimes = false;
            let mut generic_lifetime = false;

            for seg in &mut path.segments {
                // strip generic lifetimes
                match &mut seg.arguments {
                    PathArguments::AngleBracketed(AngleBracketedGenericArguments {
                        args, ..
                    }) => {
                        *args = args
                            .clone()
                            .into_iter()
                            .map(|mut ty| {
                                if let GenericArgument::Type(ty) = &mut ty {
                                    if strip_lifetimes(ty) {
                                        has_lifetimes = true;
                                    };
                                }
                                ty
                            })
                            .filter(|arg| {
                                if let GenericArgument::Lifetime(_) = arg {
                                    generic_lifetime = true;
                                    false
                                } else {
                                    true
                                }
                            })
                            .collect();
                    }
                    PathArguments::Parenthesized(ParenthesizedGenericArguments {
                        inputs, ..
                    }) => {
                        *inputs = inputs
                            .clone()
                            .into_iter()
                            .map(|mut ty| {
                                if strip_lifetimes(&mut ty) {
                                    has_lifetimes = true;
                                };
                                ty
                            })
                            .collect();
                    }
                    _ => {}
                }
            }

            // If a type has a generic lifetime parameter there must be an `Incoming` variant of that type.
            if generic_lifetime {
                if let Some(name) = path.segments.last_mut() {
                    let incoming_ty_ident = format_ident!("Incoming{}", name.ident);
                    name.ident = incoming_ty_ident;
                }
            }

            has_lifetimes || generic_lifetime
        }
        Type::Reference(TypeReference { elem, .. }) => match &mut **elem {
            Type::Path(ty_path) => {
                let TypePath { path, .. } = ty_path;
                let segs = path
                    .segments
                    .clone()
                    .into_iter()
                    .map(|seg| seg.ident.to_string())
                    .collect::<Vec<_>>();

                if path.is_ident("str") {
                    // &str -> String
                    *field_type = parse_quote! { ::std::string::String };
                } else if segs.contains(&"DeviceId".into()) || segs.contains(&"ServerName".into()) {
                    // The identifiers that need to be boxed `Box<T>` since they are DST's.
                    *field_type = parse_quote! { ::std::boxed::Box<#path> };
                } else {
                    // &T -> T
                    *field_type = Type::Path(ty_path.clone());
                }
                true
            }
            // &[T] -> Vec<T>
            Type::Slice(TypeSlice { elem, .. }) => {
                // Recursively strip the lifetimes of the slice's elements.
                strip_lifetimes(&mut *elem);
                *field_type = parse_quote! { Vec<#elem> };
                true
            }
            _ => false,
        },
        Type::Tuple(syn::TypeTuple { elems, .. }) => {
            let mut has_lifetime = false;
            for elem in elems {
                if strip_lifetimes(elem) {
                    has_lifetime = true;
                }
            }
            has_lifetime
        }
        _ => false,
    }
}
<commit_msg>Rename generic_lifetime -> is_lifetime_generic<commit_after>use proc_macro2::{Span, TokenStream};
use quote::{format_ident, quote};
use syn::{
    parse_quote, AngleBracketedGenericArguments, Attribute, Data, DeriveInput, Field, Fields,
    GenericArgument, GenericParam, Generics, ImplGenerics, ParenthesizedGenericArguments,
    PathArguments, Type, TypeGenerics, TypePath, TypeReference, TypeSlice, Variant,
};

enum StructKind {
    Struct,
    Tuple,
}

enum DataKind {
    Struct(Vec<Field>, StructKind),
    Enum(Vec<Variant>),
    Unit,
}

pub fn expand_derive_outgoing(input: DeriveInput) -> syn::Result<TokenStream> {
    let derive_deserialize = if no_deserialize_in_attrs(&input.attrs) {
        TokenStream::new()
    } else {
        quote!(::ruma_api::exports::serde::Deserialize)
    };

    let data = match input.data.clone() {
        Data::Union(_) => panic!("#[derive(Outgoing)] does not support Union types"),
        Data::Enum(e) => DataKind::Enum(e.variants.into_iter().collect()),
        Data::Struct(s) => match s.fields {
            Fields::Named(fs) => {
                DataKind::Struct(fs.named.into_iter().collect(), StructKind::Struct)
            }
            Fields::Unnamed(fs) => {
                DataKind::Struct(fs.unnamed.into_iter().collect(), StructKind::Tuple)
            }
            Fields::Unit => DataKind::Unit,
        },
    };

    match data {
        DataKind::Unit => Ok(impl_outgoing_with_incoming_self(&input)),
        DataKind::Enum(mut vars) => {
            let mut found_lifetime = false;
            for var in &mut vars {
                for field in &mut var.fields {
                    if strip_lifetimes(&mut field.ty) {
                        found_lifetime = true;
                    }
                }
            }

            let original_ident = &input.ident;
            let (original_impl_gen, original_ty_gen, _) = input.generics.split_for_impl();

            if !found_lifetime {
                return Ok(impl_outgoing_with_incoming_self(&input));
            }

            let vis = input.vis;
            let doc = format!("'Incoming' variant of [{ty}](enum.{ty}.html).", ty = &input.ident);
            let incoming_ident =
                format_ident!("Incoming{}", original_ident, span = Span::call_site());
            let mut gen_copy = input.generics.clone();
            let (impl_gen, ty_gen) = split_for_impl_lifetime_less(&mut gen_copy);

            Ok(quote! {
                #[doc = #doc]
                #[derive(Debug, #derive_deserialize)]
                #vis enum #incoming_ident #ty_gen { #( #vars, )* }

                impl #original_impl_gen ::ruma_api::Outgoing for #original_ident #original_ty_gen {
                    type Incoming = #incoming_ident #impl_gen;
                }
            })
        }
        DataKind::Struct(mut fields, struct_kind) => {
            let mut found_lifetime = false;
            for field in &mut fields {
                if strip_lifetimes(&mut field.ty) {
                    found_lifetime = true;
                }
            }

            let original_ident = &input.ident;
            let (original_impl_gen, original_ty_gen, _) = input.generics.split_for_impl();

            if !found_lifetime {
                return Ok(impl_outgoing_with_incoming_self(&input));
            }

            let vis = input.vis;
            let doc = format!("'Incoming' variant of [{ty}](struct.{ty}.html).", ty = &input.ident);
            let incoming_ident =
                format_ident!("Incoming{}", original_ident, span = Span::call_site());
            let mut gen_copy = input.generics.clone();
            let (impl_gen, ty_gen) = split_for_impl_lifetime_less(&mut gen_copy);

            let struct_def = match struct_kind {
                StructKind::Struct => quote! { { #(#fields,)* } },
                StructKind::Tuple => quote! { ( #(#fields,)* ); },
            };

            Ok(quote! {
                #[doc = #doc]
                #[derive(Debug, #derive_deserialize)]
                #vis struct #incoming_ident #ty_gen #struct_def

                impl #original_impl_gen ::ruma_api::Outgoing for #original_ident #original_ty_gen {
                    type Incoming = #incoming_ident #impl_gen;
                }
            })
        }
    }
}

fn no_deserialize_in_attrs(attrs: &[Attribute]) -> bool {
    attrs.iter().any(|attr| attr.path.is_ident("incoming_no_deserialize"))
}

fn impl_outgoing_with_incoming_self(input: &DeriveInput) -> TokenStream {
    let ident = &input.ident;
    let (impl_gen, ty_gen, _) = input.generics.split_for_impl();

    quote! {
        impl #impl_gen ::ruma_api::Outgoing for #ident #ty_gen {
            type Incoming = Self;
        }
    }
}

fn split_for_impl_lifetime_less(generics: &mut Generics) -> (ImplGenerics, TypeGenerics) {
    generics.params = generics
        .params
        .clone()
        .into_iter()
        .filter(|param| !matches!(param, GenericParam::Lifetime(_)))
        .collect();

    let (impl_gen, ty_gen, _) = generics.split_for_impl();
    (impl_gen, ty_gen)
}

fn strip_lifetimes(field_type: &mut Type) -> bool {
    match field_type {
        // T<'a> -> IncomingT
        // The IncomingT has to be declared by the user of this derive macro.
        Type::Path(TypePath { path, .. }) => {
            let mut has_lifetimes = false;
            let mut is_lifetime_generic = false;

            for seg in &mut path.segments {
                // strip generic lifetimes
                match &mut seg.arguments {
                    PathArguments::AngleBracketed(AngleBracketedGenericArguments {
                        args, ..
                    }) => {
                        *args = args
                            .clone()
                            .into_iter()
                            .map(|mut ty| {
                                if let GenericArgument::Type(ty) = &mut ty {
                                    if strip_lifetimes(ty) {
                                        has_lifetimes = true;
                                    };
                                }
                                ty
                            })
                            .filter(|arg| {
                                if let GenericArgument::Lifetime(_) = arg {
                                    is_lifetime_generic = true;
                                    false
                                } else {
                                    true
                                }
                            })
                            .collect();
                    }
                    PathArguments::Parenthesized(ParenthesizedGenericArguments {
                        inputs, ..
                    }) => {
                        *inputs = inputs
                            .clone()
                            .into_iter()
                            .map(|mut ty| {
                                if strip_lifetimes(&mut ty) {
                                    has_lifetimes = true;
                                };
                                ty
                            })
                            .collect();
                    }
                    _ => {}
                }
            }

            // If a type has a generic lifetime parameter there must be an `Incoming` variant of that type.
            if is_lifetime_generic {
                if let Some(name) = path.segments.last_mut() {
                    let incoming_ty_ident = format_ident!("Incoming{}", name.ident);
                    name.ident = incoming_ty_ident;
                }
            }

            has_lifetimes || is_lifetime_generic
        }
        Type::Reference(TypeReference { elem, .. }) => match &mut **elem {
            Type::Path(ty_path) => {
                let TypePath { path, .. } = ty_path;
                let segs = path
                    .segments
                    .clone()
                    .into_iter()
                    .map(|seg| seg.ident.to_string())
                    .collect::<Vec<_>>();

                if path.is_ident("str") {
                    // &str -> String
                    *field_type = parse_quote! { ::std::string::String };
                } else if segs.contains(&"DeviceId".into()) || segs.contains(&"ServerName".into()) {
                    // The identifiers that need to be boxed `Box<T>` since they are DST's.
                    *field_type = parse_quote! { ::std::boxed::Box<#path> };
                } else {
                    // &T -> T
                    *field_type = Type::Path(ty_path.clone());
                }
                true
            }
            // &[T] -> Vec<T>
            Type::Slice(TypeSlice { elem, .. }) => {
                // Recursively strip the lifetimes of the slice's elements.
                strip_lifetimes(&mut *elem);
                *field_type = parse_quote! { Vec<#elem> };
                true
            }
            _ => false,
        },
        Type::Tuple(syn::TypeTuple { elems, .. }) => {
            let mut has_lifetime = false;
            for elem in elems {
                if strip_lifetimes(elem) {
                    has_lifetime = true;
                }
            }
            has_lifetime
        }
        _ => false,
    }
}
<|endoftext|>


<commit_before>use libc;
use glib::translate::*;
use pango;
use pango_sys;

pub enum RsvgState {}

// Keep in sync with rsvg-styles.h:UnicodeBidi
#[repr(C)]
pub enum UnicodeBidi {
    Normal,
    Embed,
    Override,
}

extern "C" {
    fn rsvg_state_get_language     (state: *const RsvgState) -> *const libc::c_char;
    fn rsvg_state_get_unicode_bidi (state: *const RsvgState) -> UnicodeBidi;
    fn rsvg_state_get_text_dir     (state: *const RsvgState) -> pango_sys::PangoDirection;
    fn rsvg_state_get_text_gravity (state: *const RsvgState) -> pango_sys::PangoGravity;
    fn rsvg_state_get_font_family  (state: *const RsvgState) -> *const libc::c_char;
    fn rsvg_state_get_font_style   (state: *const RsvgState) -> pango_sys::PangoStyle;
    fn rsvg_state_get_font_variant (state: *const RsvgState) -> pango_sys::PangoVariant;
    fn rsvg_state_get_font_weight  (state: *const RsvgState) -> pango_sys::PangoWeight;
    fn rsvg_state_get_font_stretch (state: *const RsvgState) -> pango_sys::PangoStretch;
}

pub fn get_language(state: *const RsvgState) -> Option<String> {
    unsafe {
        from_glib_none(rsvg_state_get_language(state))
    }
}

pub fn get_unicode_bidi(state: *const RsvgState) -> UnicodeBidi {
    unsafe { rsvg_state_get_unicode_bidi(state) }
}

pub fn get_text_dir(state: *const RsvgState) -> pango::Direction {
    unsafe { from_glib(rsvg_state_get_text_dir(state)) }
}

pub fn get_text_gravity(state: *const RsvgState) -> pango::Gravity {
    unsafe { from_glib(rsvg_state_get_text_gravity(state)) }
}

pub fn get_font_family(state: *const RsvgState) -> String {
    unsafe { from_glib_none(rsvg_state_get_font_family(state)) }
}

pub fn get_font_style(state: *const RsvgState) -> pango::Style {
    unsafe { from_glib(rsvg_state_get_font_style(state)) }
}

pub fn get_font_variant(state: *const RsvgState) -> pango::Variant {
    unsafe { from_glib(rsvg_state_get_font_variant(state)) }
}

pub fn get_font_weight(state: *const RsvgState) -> pango::Weight {
    unsafe { from_glib(rsvg_state_get_font_weight(state)) }
}

pub fn get_font_stretch(state: *const RsvgState) -> pango::Stretch {
    unsafe { from_glib(rsvg_state_get_font_stretch(state)) }
}
<commit_msg>state::get_font_family() should return an Option<String><commit_after>use libc;
use glib::translate::*;
use pango;
use pango_sys;

pub enum RsvgState {}

// Keep in sync with rsvg-styles.h:UnicodeBidi
#[repr(C)]
pub enum UnicodeBidi {
    Normal,
    Embed,
    Override,
}

extern "C" {
    fn rsvg_state_get_language     (state: *const RsvgState) -> *const libc::c_char;
    fn rsvg_state_get_unicode_bidi (state: *const RsvgState) -> UnicodeBidi;
    fn rsvg_state_get_text_dir     (state: *const RsvgState) -> pango_sys::PangoDirection;
    fn rsvg_state_get_text_gravity (state: *const RsvgState) -> pango_sys::PangoGravity;
    fn rsvg_state_get_font_family  (state: *const RsvgState) -> *const libc::c_char;
    fn rsvg_state_get_font_style   (state: *const RsvgState) -> pango_sys::PangoStyle;
    fn rsvg_state_get_font_variant (state: *const RsvgState) -> pango_sys::PangoVariant;
    fn rsvg_state_get_font_weight  (state: *const RsvgState) -> pango_sys::PangoWeight;
    fn rsvg_state_get_font_stretch (state: *const RsvgState) -> pango_sys::PangoStretch;
}

pub fn get_language(state: *const RsvgState) -> Option<String> {
    unsafe {
        from_glib_none(rsvg_state_get_language(state))
    }
}

pub fn get_unicode_bidi(state: *const RsvgState) -> UnicodeBidi {
    unsafe { rsvg_state_get_unicode_bidi(state) }
}

pub fn get_text_dir(state: *const RsvgState) -> pango::Direction {
    unsafe { from_glib(rsvg_state_get_text_dir(state)) }
}

pub fn get_text_gravity(state: *const RsvgState) -> pango::Gravity {
    unsafe { from_glib(rsvg_state_get_text_gravity(state)) }
}

pub fn get_font_family(state: *const RsvgState) -> Option<String> {
    unsafe { from_glib_none(rsvg_state_get_font_family(state)) }
}

pub fn get_font_style(state: *const RsvgState) -> pango::Style {
    unsafe { from_glib(rsvg_state_get_font_style(state)) }
}

pub fn get_font_variant(state: *const RsvgState) -> pango::Variant {
    unsafe { from_glib(rsvg_state_get_font_variant(state)) }
}

pub fn get_font_weight(state: *const RsvgState) -> pango::Weight {
    unsafe { from_glib(rsvg_state_get_font_weight(state)) }
}

pub fn get_font_stretch(state: *const RsvgState) -> pango::Stretch {
    unsafe { from_glib(rsvg_state_get_font_stretch(state)) }
}
<|endoftext|>


<commit_before>//! For detailed description of the ptrace requests, consult `man ptrace`.

use std::{mem, ptr};
use {Error, Result};
use errno::Errno;
use libc::{self, c_void, c_long, siginfo_t};
use ::unistd::Pid;
use sys::signal::Signal;

cfg_if! {
    if #[cfg(any(all(target_os = "linux", arch = "s390x"),
                 all(target_os = "linux", target_env = "gnu")))] {
        #[doc(hidden)]
        pub type RequestType = ::libc::c_uint;
    } else {
        #[doc(hidden)]
        pub type RequestType = ::libc::c_int;
    }
}

libc_enum!{
    #[cfg_attr(not(any(target_env = "musl", target_os = "android")), repr(u32))]
    #[cfg_attr(any(target_env = "musl", target_os = "android"), repr(i32))]
    /// Ptrace Request enum defining the action to be taken.
    pub enum Request {
        PTRACE_TRACEME,
        PTRACE_PEEKTEXT,
        PTRACE_PEEKDATA,
        PTRACE_PEEKUSER,
        PTRACE_POKETEXT,
        PTRACE_POKEDATA,
        PTRACE_POKEUSER,
        PTRACE_CONT,
        PTRACE_KILL,
        PTRACE_SINGLESTEP,
        #[cfg(all(any(target_env = "musl", target_arch ="x86_64", target_arch = "s390x"), not(target_os = "android")))]
        PTRACE_GETREGS,
        #[cfg(all(any(target_env = "musl", target_arch ="x86_64", target_arch = "s390x"), not(target_os = "android")))]
        PTRACE_SETREGS,
        #[cfg(all(any(target_env = "musl", target_arch ="x86_64", target_arch = "s390x"), not(target_os = "android")))]
        PTRACE_GETFPREGS,
        #[cfg(all(any(target_env = "musl", target_arch ="x86_64", target_arch = "s390x"), not(target_os = "android")))]
        PTRACE_SETFPREGS,
        PTRACE_ATTACH,
        PTRACE_DETACH,
        #[cfg(all(any(target_env = "musl", target_arch ="x86_64"), not(target_os = "android")))]
        PTRACE_GETFPXREGS,
        #[cfg(all(any(target_env = "musl", target_arch ="x86_64"), not(target_os = "android")))]
        PTRACE_SETFPXREGS,
        PTRACE_SYSCALL,
        PTRACE_SETOPTIONS,
        PTRACE_GETEVENTMSG,
        PTRACE_GETSIGINFO,
        PTRACE_SETSIGINFO,
        #[cfg(all(any(target_env = "musl", target_arch ="x86_64", target_arch = "s390x"), not(target_os = "android")))]
        PTRACE_GETREGSET,
        #[cfg(all(any(target_env = "musl", target_arch ="x86_64", target_arch = "s390x"), not(target_os = "android")))]
        PTRACE_SETREGSET,
        #[cfg(not(any(target_os = "android", target_arch = "mips", target_arch = "mips64")))]
        PTRACE_SEIZE,
        #[cfg(not(any(target_os = "android", target_arch = "mips", target_arch = "mips64")))]
        PTRACE_INTERRUPT,
        #[cfg(not(any(target_os = "android", target_arch = "mips", target_arch = "mips64")))]
        PTRACE_LISTEN,
        #[cfg(not(any(target_os = "android", target_arch = "mips", target_arch = "mips64")))]
        PTRACE_PEEKSIGINFO,
    }
}

libc_enum!{
    #[repr(i32)]
    /// Using the ptrace options the tracer can configure the tracee to stop
    /// at certain events. This enum is used to define those events as defined
    /// in `man ptrace`.
    pub enum Event {
        /// Event that stops before a return from fork or clone.
        PTRACE_EVENT_FORK,
        /// Event that stops before a return from vfork or clone.
        PTRACE_EVENT_VFORK,
        /// Event that stops before a return from clone.
        PTRACE_EVENT_CLONE,
        /// Event that stops before a return from execve.
        PTRACE_EVENT_EXEC,
        /// Event for a return from vfork.
        PTRACE_EVENT_VFORK_DONE,
        /// Event for a stop before an exit. Unlike the waitpid Exit status program.
        /// registers can still be examined
        PTRACE_EVENT_EXIT,
        /// STop triggered by a seccomp rule on a tracee.
        PTRACE_EVENT_SECCOMP,
        // PTRACE_EVENT_STOP not provided by libc because it's defined in glibc 2.26
    }
}

libc_bitflags! {
    /// Ptrace options used in conjunction with the PTRACE_SETOPTIONS request.
    /// See `man ptrace` for more details.
    pub struct Options: libc::c_int {
        /// When delivering system call traps set a bit to allow tracer to
        /// distinguish between normal stops or syscall stops. May not work on
        /// all systems.
        PTRACE_O_TRACESYSGOOD;
        /// Stop tracee at next fork and start tracing the forked process.
        PTRACE_O_TRACEFORK;
        /// Stop tracee at next vfork call and trace the vforked process.
        PTRACE_O_TRACEVFORK;
        /// Stop tracee at next clone call and trace the cloned process.
        PTRACE_O_TRACECLONE;
        /// Stop tracee at next execve call.
        PTRACE_O_TRACEEXEC;
        /// Stop tracee at vfork completion.
        PTRACE_O_TRACEVFORKDONE;
        /// Stop tracee at next exit call. Stops before exit commences allowing
        /// tracer to see location of exit and register states.
        PTRACE_O_TRACEEXIT;
        /// Stop tracee when a SECCOMP_RET_TRACE rule is triggered. See `man seccomp` for more
        /// details.
        PTRACE_O_TRACESECCOMP;
        /// Send a SIGKILL to the tracee if the tracer exits.  This is useful
        /// for ptrace jailers to prevent tracees from escaping their control.
        #[cfg(any(target_os = "android", target_os = "linux"))]
        PTRACE_O_EXITKILL;
    }
}

/// Performs a ptrace request. If the request in question is provided by a specialised function
/// this function will return an unsupported operation error.
#[deprecated(
    since="0.10.0",
    note="usages of `ptrace()` should be replaced with the specialized helper functions instead"
)]
pub unsafe fn ptrace(request: Request, pid: Pid, addr: *mut c_void, data: *mut c_void) -> Result<c_long> {
    use self::Request::*;
    match request {
        PTRACE_PEEKTEXT | PTRACE_PEEKDATA | PTRACE_PEEKUSER => ptrace_peek(request, pid, addr, data),
        PTRACE_GETSIGINFO | PTRACE_GETEVENTMSG | PTRACE_SETSIGINFO | PTRACE_SETOPTIONS => Err(Error::UnsupportedOperation),
        _ => ptrace_other(request, pid, addr, data)
    }
}

fn ptrace_peek(request: Request, pid: Pid, addr: *mut c_void, data: *mut c_void) -> Result<c_long> {
    let ret = unsafe {
        Errno::clear();
        libc::ptrace(request as RequestType, libc::pid_t::from(pid), addr, data)
    };
    match Errno::result(ret) {
        Ok(..) | Err(Error::Sys(Errno::UnknownErrno)) => Ok(ret),
        err @ Err(..) => err,
    }
}

/// Function for ptrace requests that return values from the data field.
/// Some ptrace get requests populate structs or larger elements than `c_long`
/// and therefore use the data field to return values. This function handles these
/// requests.
fn ptrace_get_data<T>(request: Request, pid: Pid) -> Result<T> {
    // Creates an uninitialized pointer to store result in
    let data: T = unsafe { mem::uninitialized() };
    let res = unsafe {
        libc::ptrace(request as RequestType,
                     libc::pid_t::from(pid),
                     ptr::null_mut::<T>(),
                     &data as *const _ as *const c_void)
    };
    Errno::result(res)?;
    Ok(data)
}

unsafe fn ptrace_other(request: Request, pid: Pid, addr: *mut c_void, data: *mut c_void) -> Result<c_long> {
    Errno::result(libc::ptrace(request as RequestType, libc::pid_t::from(pid), addr, data)).map(|_| 0)
}

/// Set options, as with `ptrace(PTRACE_SETOPTIONS,...)`.
pub fn setoptions(pid: Pid, options: Options) -> Result<()> {
    use std::ptr;

    let res = unsafe {
        libc::ptrace(Request::PTRACE_SETOPTIONS as RequestType,
                     libc::pid_t::from(pid),
                     ptr::null_mut::<libc::c_void>(),
                     options.bits() as *mut c_void)
    };
    Errno::result(res).map(|_| ())
}

/// Gets a ptrace event as described by `ptrace(PTRACE_GETEVENTMSG,...)`
pub fn getevent(pid: Pid) -> Result<c_long> {
    ptrace_get_data::<c_long>(Request::PTRACE_GETEVENTMSG, pid)
}

/// Get siginfo as with `ptrace(PTRACE_GETSIGINFO,...)`
pub fn getsiginfo(pid: Pid) -> Result<siginfo_t> {
    ptrace_get_data::<siginfo_t>(Request::PTRACE_GETSIGINFO, pid)
}

/// Set siginfo as with `ptrace(PTRACE_SETSIGINFO,...)`
pub fn setsiginfo(pid: Pid, sig: &siginfo_t) -> Result<()> {
    let ret = unsafe{
        Errno::clear();
        libc::ptrace(Request::PTRACE_SETSIGINFO as RequestType,
                     libc::pid_t::from(pid),
                     ptr::null_mut::<libc::c_void>(),
                     sig as *const _ as *const c_void)
    };
    match Errno::result(ret) {
        Ok(_) => Ok(()),
        Err(e) => Err(e),
    }
}

/// Sets the process as traceable, as with `ptrace(PTRACE_TRACEME, ...)`
///
/// Indicates that this process is to be traced by its parent.
/// This is the only ptrace request to be issued by the tracee.
pub fn traceme() -> Result<()> {
    unsafe {
        ptrace_other(
            Request::PTRACE_TRACEME,
            Pid::from_raw(0),
            ptr::null_mut(),
            ptr::null_mut(),
        ).map(|_| ()) // ignore the useless return value
    }
}

/// Ask for next syscall, as with `ptrace(PTRACE_SYSCALL, ...)`
///
/// Arranges for the tracee to be stopped at the next entry to or exit from a system call.
pub fn syscall(pid: Pid) -> Result<()> {
    unsafe {
        ptrace_other(
            Request::PTRACE_SYSCALL,
            pid,
            ptr::null_mut(),
            ptr::null_mut(),
        ).map(|_| ()) // ignore the useless return value
    }
}

/// Attach to a running process, as with `ptrace(PTRACE_ATTACH, ...)`
///
/// Attaches to the process specified in pid, making it a tracee of the calling process.
pub fn attach(pid: Pid) -> Result<()> {
    unsafe {
        ptrace_other(
            Request::PTRACE_ATTACH,
            pid,
            ptr::null_mut(),
            ptr::null_mut(),
        ).map(|_| ()) // ignore the useless return value
    }
}

/// Detaches the current running process, as with `ptrace(PTRACE_DETACH, ...)`
///
/// Detaches from the process specified in pid allowing it to run freely
pub fn detach(pid: Pid) -> Result<()> {
    unsafe {
        ptrace_other(
            Request::PTRACE_DETACH,
            pid,
            ptr::null_mut(),
            ptr::null_mut()
        ).map(|_| ())
    }
}

/// Restart the stopped tracee process, as with `ptrace(PTRACE_CONT, ...)`
///
/// Continues the execution of the process with PID `pid`, optionally
/// delivering a signal specified by `sig`.
pub fn cont<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
    let data = match sig.into() {
        Some(s) => s as i32 as *mut c_void,
        None => ptr::null_mut(),
    };
    unsafe {
        ptrace_other(Request::PTRACE_CONT, pid, ptr::null_mut(), data).map(|_| ()) // ignore the useless return value
    }
}

/// Move the stopped tracee process forward by a single step as with
/// `ptrace(PTRACE_SINGLESTEP, ...)`
///
/// Advances the execution of the process with PID `pid` by a single step optionally delivering a
/// single specified by `sig`.
///
/// # Example
/// ```rust
/// extern crate nix;
/// use nix::sys::ptrace::step;
/// use nix::unistd::Pid;
/// use nix::sys::signal::Signal;
/// fn main() {
///     let dummy_pid = Pid::from_raw(0);
///
///     let _ = step(dummy_pid, Some(Signal::SIGSTOP));
/// }
/// ```
pub fn step<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
    let data = match sig.into() {
        Some(s) => s as i32 as *mut c_void,
        None => ptr::null_mut(),
    };
    unsafe {
        ptrace_other(Request::PTRACE_SINGLESTEP, pid, ptr::null_mut(), data).map(|_| ())
    }
}
<commit_msg>Corrected typo<commit_after>//! For detailed description of the ptrace requests, consult `man ptrace`.

use std::{mem, ptr};
use {Error, Result};
use errno::Errno;
use libc::{self, c_void, c_long, siginfo_t};
use ::unistd::Pid;
use sys::signal::Signal;

cfg_if! {
    if #[cfg(any(all(target_os = "linux", arch = "s390x"),
                 all(target_os = "linux", target_env = "gnu")))] {
        #[doc(hidden)]
        pub type RequestType = ::libc::c_uint;
    } else {
        #[doc(hidden)]
        pub type RequestType = ::libc::c_int;
    }
}

libc_enum!{
    #[cfg_attr(not(any(target_env = "musl", target_os = "android")), repr(u32))]
    #[cfg_attr(any(target_env = "musl", target_os = "android"), repr(i32))]
    /// Ptrace Request enum defining the action to be taken.
    pub enum Request {
        PTRACE_TRACEME,
        PTRACE_PEEKTEXT,
        PTRACE_PEEKDATA,
        PTRACE_PEEKUSER,
        PTRACE_POKETEXT,
        PTRACE_POKEDATA,
        PTRACE_POKEUSER,
        PTRACE_CONT,
        PTRACE_KILL,
        PTRACE_SINGLESTEP,
        #[cfg(all(any(target_env = "musl", target_arch ="x86_64", target_arch = "s390x"), not(target_os = "android")))]
        PTRACE_GETREGS,
        #[cfg(all(any(target_env = "musl", target_arch ="x86_64", target_arch = "s390x"), not(target_os = "android")))]
        PTRACE_SETREGS,
        #[cfg(all(any(target_env = "musl", target_arch ="x86_64", target_arch = "s390x"), not(target_os = "android")))]
        PTRACE_GETFPREGS,
        #[cfg(all(any(target_env = "musl", target_arch ="x86_64", target_arch = "s390x"), not(target_os = "android")))]
        PTRACE_SETFPREGS,
        PTRACE_ATTACH,
        PTRACE_DETACH,
        #[cfg(all(any(target_env = "musl", target_arch ="x86_64"), not(target_os = "android")))]
        PTRACE_GETFPXREGS,
        #[cfg(all(any(target_env = "musl", target_arch ="x86_64"), not(target_os = "android")))]
        PTRACE_SETFPXREGS,
        PTRACE_SYSCALL,
        PTRACE_SETOPTIONS,
        PTRACE_GETEVENTMSG,
        PTRACE_GETSIGINFO,
        PTRACE_SETSIGINFO,
        #[cfg(all(any(target_env = "musl", target_arch ="x86_64", target_arch = "s390x"), not(target_os = "android")))]
        PTRACE_GETREGSET,
        #[cfg(all(any(target_env = "musl", target_arch ="x86_64", target_arch = "s390x"), not(target_os = "android")))]
        PTRACE_SETREGSET,
        #[cfg(not(any(target_os = "android", target_arch = "mips", target_arch = "mips64")))]
        PTRACE_SEIZE,
        #[cfg(not(any(target_os = "android", target_arch = "mips", target_arch = "mips64")))]
        PTRACE_INTERRUPT,
        #[cfg(not(any(target_os = "android", target_arch = "mips", target_arch = "mips64")))]
        PTRACE_LISTEN,
        #[cfg(not(any(target_os = "android", target_arch = "mips", target_arch = "mips64")))]
        PTRACE_PEEKSIGINFO,
    }
}

libc_enum!{
    #[repr(i32)]
    /// Using the ptrace options the tracer can configure the tracee to stop
    /// at certain events. This enum is used to define those events as defined
    /// in `man ptrace`.
    pub enum Event {
        /// Event that stops before a return from fork or clone.
        PTRACE_EVENT_FORK,
        /// Event that stops before a return from vfork or clone.
        PTRACE_EVENT_VFORK,
        /// Event that stops before a return from clone.
        PTRACE_EVENT_CLONE,
        /// Event that stops before a return from execve.
        PTRACE_EVENT_EXEC,
        /// Event for a return from vfork.
        PTRACE_EVENT_VFORK_DONE,
        /// Event for a stop before an exit. Unlike the waitpid Exit status program.
        /// registers can still be examined
        PTRACE_EVENT_EXIT,
        /// STop triggered by a seccomp rule on a tracee.
        PTRACE_EVENT_SECCOMP,
        // PTRACE_EVENT_STOP not provided by libc because it's defined in glibc 2.26
    }
}

libc_bitflags! {
    /// Ptrace options used in conjunction with the PTRACE_SETOPTIONS request.
    /// See `man ptrace` for more details.
    pub struct Options: libc::c_int {
        /// When delivering system call traps set a bit to allow tracer to
        /// distinguish between normal stops or syscall stops. May not work on
        /// all systems.
        PTRACE_O_TRACESYSGOOD;
        /// Stop tracee at next fork and start tracing the forked process.
        PTRACE_O_TRACEFORK;
        /// Stop tracee at next vfork call and trace the vforked process.
        PTRACE_O_TRACEVFORK;
        /// Stop tracee at next clone call and trace the cloned process.
        PTRACE_O_TRACECLONE;
        /// Stop tracee at next execve call.
        PTRACE_O_TRACEEXEC;
        /// Stop tracee at vfork completion.
        PTRACE_O_TRACEVFORKDONE;
        /// Stop tracee at next exit call. Stops before exit commences allowing
        /// tracer to see location of exit and register states.
        PTRACE_O_TRACEEXIT;
        /// Stop tracee when a SECCOMP_RET_TRACE rule is triggered. See `man seccomp` for more
        /// details.
        PTRACE_O_TRACESECCOMP;
        /// Send a SIGKILL to the tracee if the tracer exits.  This is useful
        /// for ptrace jailers to prevent tracees from escaping their control.
        #[cfg(any(target_os = "android", target_os = "linux"))]
        PTRACE_O_EXITKILL;
    }
}

/// Performs a ptrace request. If the request in question is provided by a specialised function
/// this function will return an unsupported operation error.
#[deprecated(
    since="0.10.0",
    note="usages of `ptrace()` should be replaced with the specialized helper functions instead"
)]
pub unsafe fn ptrace(request: Request, pid: Pid, addr: *mut c_void, data: *mut c_void) -> Result<c_long> {
    use self::Request::*;
    match request {
        PTRACE_PEEKTEXT | PTRACE_PEEKDATA | PTRACE_PEEKUSER => ptrace_peek(request, pid, addr, data),
        PTRACE_GETSIGINFO | PTRACE_GETEVENTMSG | PTRACE_SETSIGINFO | PTRACE_SETOPTIONS => Err(Error::UnsupportedOperation),
        _ => ptrace_other(request, pid, addr, data)
    }
}

fn ptrace_peek(request: Request, pid: Pid, addr: *mut c_void, data: *mut c_void) -> Result<c_long> {
    let ret = unsafe {
        Errno::clear();
        libc::ptrace(request as RequestType, libc::pid_t::from(pid), addr, data)
    };
    match Errno::result(ret) {
        Ok(..) | Err(Error::Sys(Errno::UnknownErrno)) => Ok(ret),
        err @ Err(..) => err,
    }
}

/// Function for ptrace requests that return values from the data field.
/// Some ptrace get requests populate structs or larger elements than `c_long`
/// and therefore use the data field to return values. This function handles these
/// requests.
fn ptrace_get_data<T>(request: Request, pid: Pid) -> Result<T> {
    // Creates an uninitialized pointer to store result in
    let data: T = unsafe { mem::uninitialized() };
    let res = unsafe {
        libc::ptrace(request as RequestType,
                     libc::pid_t::from(pid),
                     ptr::null_mut::<T>(),
                     &data as *const _ as *const c_void)
    };
    Errno::result(res)?;
    Ok(data)
}

unsafe fn ptrace_other(request: Request, pid: Pid, addr: *mut c_void, data: *mut c_void) -> Result<c_long> {
    Errno::result(libc::ptrace(request as RequestType, libc::pid_t::from(pid), addr, data)).map(|_| 0)
}

/// Set options, as with `ptrace(PTRACE_SETOPTIONS,...)`.
pub fn setoptions(pid: Pid, options: Options) -> Result<()> {
    use std::ptr;

    let res = unsafe {
        libc::ptrace(Request::PTRACE_SETOPTIONS as RequestType,
                     libc::pid_t::from(pid),
                     ptr::null_mut::<libc::c_void>(),
                     options.bits() as *mut c_void)
    };
    Errno::result(res).map(|_| ())
}

/// Gets a ptrace event as described by `ptrace(PTRACE_GETEVENTMSG,...)`
pub fn getevent(pid: Pid) -> Result<c_long> {
    ptrace_get_data::<c_long>(Request::PTRACE_GETEVENTMSG, pid)
}

/// Get siginfo as with `ptrace(PTRACE_GETSIGINFO,...)`
pub fn getsiginfo(pid: Pid) -> Result<siginfo_t> {
    ptrace_get_data::<siginfo_t>(Request::PTRACE_GETSIGINFO, pid)
}

/// Set siginfo as with `ptrace(PTRACE_SETSIGINFO,...)`
pub fn setsiginfo(pid: Pid, sig: &siginfo_t) -> Result<()> {
    let ret = unsafe{
        Errno::clear();
        libc::ptrace(Request::PTRACE_SETSIGINFO as RequestType,
                     libc::pid_t::from(pid),
                     ptr::null_mut::<libc::c_void>(),
                     sig as *const _ as *const c_void)
    };
    match Errno::result(ret) {
        Ok(_) => Ok(()),
        Err(e) => Err(e),
    }
}

/// Sets the process as traceable, as with `ptrace(PTRACE_TRACEME, ...)`
///
/// Indicates that this process is to be traced by its parent.
/// This is the only ptrace request to be issued by the tracee.
pub fn traceme() -> Result<()> {
    unsafe {
        ptrace_other(
            Request::PTRACE_TRACEME,
            Pid::from_raw(0),
            ptr::null_mut(),
            ptr::null_mut(),
        ).map(|_| ()) // ignore the useless return value
    }
}

/// Ask for next syscall, as with `ptrace(PTRACE_SYSCALL, ...)`
///
/// Arranges for the tracee to be stopped at the next entry to or exit from a system call.
pub fn syscall(pid: Pid) -> Result<()> {
    unsafe {
        ptrace_other(
            Request::PTRACE_SYSCALL,
            pid,
            ptr::null_mut(),
            ptr::null_mut(),
        ).map(|_| ()) // ignore the useless return value
    }
}

/// Attach to a running process, as with `ptrace(PTRACE_ATTACH, ...)`
///
/// Attaches to the process specified in pid, making it a tracee of the calling process.
pub fn attach(pid: Pid) -> Result<()> {
    unsafe {
        ptrace_other(
            Request::PTRACE_ATTACH,
            pid,
            ptr::null_mut(),
            ptr::null_mut(),
        ).map(|_| ()) // ignore the useless return value
    }
}

/// Detaches the current running process, as with `ptrace(PTRACE_DETACH, ...)`
///
/// Detaches from the process specified in pid allowing it to run freely
pub fn detach(pid: Pid) -> Result<()> {
    unsafe {
        ptrace_other(
            Request::PTRACE_DETACH,
            pid,
            ptr::null_mut(),
            ptr::null_mut()
        ).map(|_| ())
    }
}

/// Restart the stopped tracee process, as with `ptrace(PTRACE_CONT, ...)`
///
/// Continues the execution of the process with PID `pid`, optionally
/// delivering a signal specified by `sig`.
pub fn cont<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
    let data = match sig.into() {
        Some(s) => s as i32 as *mut c_void,
        None => ptr::null_mut(),
    };
    unsafe {
        ptrace_other(Request::PTRACE_CONT, pid, ptr::null_mut(), data).map(|_| ()) // ignore the useless return value
    }
}

/// Move the stopped tracee process forward by a single step as with
/// `ptrace(PTRACE_SINGLESTEP, ...)`
///
/// Advances the execution of the process with PID `pid` by a single step optionally delivering a
/// signal specified by `sig`.
///
/// # Example
/// ```rust
/// extern crate nix;
/// use nix::sys::ptrace::step;
/// use nix::unistd::Pid;
/// use nix::sys::signal::Signal;
/// fn main() {
///     let dummy_pid = Pid::from_raw(0);
///
///     let _ = step(dummy_pid, Some(Signal::SIGSTOP));
/// }
/// ```
pub fn step<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
    let data = match sig.into() {
        Some(s) => s as i32 as *mut c_void,
        None => ptr::null_mut(),
    };
    unsafe {
        ptrace_other(Request::PTRACE_SINGLESTEP, pid, ptr::null_mut(), data).map(|_| ())
    }
}
<|endoftext|>


<commit_before>#![feature(libc,question_mark)]
extern crate libc;

use std::any::Any;
use std::fs;
use std::io;
use std::io::Read;
use std::path::Path;
use std::process::{Command, Stdio};
use std::str::from_utf8_unchecked;

/// Shortcut to path->filename conversion.
///
/// Returns the unchanged `path` if there is a character encoding error or something.
pub fn filename<'a> (path: &'a str) -> &'a str {
  match Path::new (path) .file_name() {
    Some (filename) => match filename.to_str() {
      Some (fstr) => if fstr.ends_with (".rs") {&fstr[0 .. fstr.len() - 3]} else {fstr},
      None => path},
    None => path}}

mod gstuff {pub fn filename<'a> (path: &'a str) -> &'a str {super::filename (path)}}

// A trick to use the `try_s` macro from both the outside and inside of the crate.
//mod gstuff {pub fn filename<'a> (path: &'a str) -> &'a str {::filename (path)}}

/// Returns on error, converting the `Err` value to `String` and prepending the current location.
///
/// cf. http://www.reddit.com/r/rust/comments/29wwzw/error_handling_and_result_types/cipcm9a
#[macro_export] macro_rules! try_s {
  ($e: expr) => {match $e {Ok (ok) => ok, Err (err) => {return Err (format! ("{}:{}] {}", ::gstuff::filename (file!()), line!(), err));}}}}

// Like `try_s`, but takes a reference.
#[macro_export] macro_rules! try_sp {
  ($e: expr) => {match $e {&Ok (ref ok) => ok,
    &Err (ref err) => {return Err (format! ("{}:{}] {:?}", ::gstuff::filename (file!()), line!(), err));}}}}

/// Returns a `Err(String)`, prepending the current location (file name and line number) to the string.
///
/// Examples: `ERR! ("too bad")`; `ERR! ("{}", foo)`;
#[macro_export] macro_rules! ERR {
  ($format: expr, $($args: tt)+) => {Err (format! (concat! ("{}:{}] ", $format), ::gstuff::filename (file!()), line!(), $($args)+))};
  ($format: expr) => {Err (format! (concat! ("{}:{}] ", $format), ::gstuff::filename (file!()), line!()))}}

/// A helper to build a string on the stack.
///
/// Given an array it makes a writeable cursor available to the passed code block.
///
/// Returns a &str slice pointing at memory between the array start and the cursor.
///
/// Example:
///
///     use std::io::Write;
///     let mut foobar: [u8; 128] = unsafe {std::mem::uninitialized()};
///     let foobar = gstring! (foobar, {
///         write! (foobar, "foo") .expect ("!write");
///         write! (foobar, "bar") .expect ("!write");
///     });
///
/// Alternatives: https://crates.io/crates/stack.
#[macro_export] macro_rules! gstring {($array: ident, $code: block) => {{
  let end = {
    let mut $array = ::std::io::Cursor::new (&mut $array[..]);
    let $array = &mut $array;
    $code;
    $array.position() as usize};
  unsafe {::std::str::from_utf8_unchecked (&$array[0..end])}}}}

/// Takes a netstring from the front of the slice.
///
/// Returns the unpacked netstring and the remainder of the slice.
pub fn netstring (at: &[u8]) -> Result<(&[u8], &[u8]), String> {
  let length_end = match at.iter().position (|&ch| ch < b'0' || ch > b'9') {Some (l) if l > 0 => l, _ => return ERR! ("No len.")};
  match at.get (length_end) {Some (&ch) if ch == b':' => (), _ => return ERR! ("No colon.")};
  let length = unsafe {from_utf8_unchecked (&at[0 .. length_end])};
  let length: usize = try_s! (length.parse());
  let bulk_pos = 0 + length_end + 1;
  let bulk_end = bulk_pos + length;
  match at.get (bulk_end) {Some (&ch) if ch == b',' => (), _ => return ERR! ("No comma.")}
  Ok ((&at[bulk_pos .. bulk_end], &at[bulk_end + 1 ..]))}

/// Wraps `gethostname` to fetch the current hostname into a temporary buffer.
#[cfg(unix)]
pub fn with_hostname (visitor: &mut FnMut (&[u8])) -> Result<(), std::io::Error> {
  use libc::{size_t, gethostname};  // http://man7.org/linux/man-pages/man2/gethostname.2.html
  use std::ffi::CStr;
  use std::io;

  let mut buf = [0; 128];
  let rc = unsafe {gethostname (buf.as_mut_ptr(), (buf.len() - 1) as size_t)};
  if rc == 0 {
    let cs = unsafe {CStr::from_ptr (buf.as_ptr())};
    Ok (visitor (cs.to_bytes()))
  } else {
    Err (io::Error::last_os_error())}}

#[cfg(unix)] #[test] fn test_hostname() {
  let mut hostname = String::new();
  with_hostname (&mut |bytes| hostname = String::from_utf8_lossy (bytes) .into_owned()) .unwrap();}

/// Read contents of the file into a String.
///
/// Returns an empty string if the file is not present under the given path.
pub fn slurp (path: &AsRef<Path>) -> String {
  let mut file = match fs::File::open (path) {
    Ok (f) => f,
    Err (ref err) if err.kind() == io::ErrorKind::NotFound => return String::new(),
    Err (err) => panic! ("Can't open {:?}: {}", path.as_ref(), err)};
  let mut buf = String::new();
  file.read_to_string (&mut buf) .expect ("!read");
  buf}

/// Runs a command in a shell, returning stderr+stdout on success.
///
/// Sometimes we need something simpler than constructing a Command.
///
/// If the command failed then returns it's stderr
pub fn slurp_prog (command: &str) -> Result<String, String> {
  let output = match Command::new ("bash") .arg ("-c") .arg (command) .output() {
    Ok (output) => output,
    Err (ref err) if err.kind() == io::ErrorKind::NotFound => {  // "sh" was not found, try a different name.
      try_s! (Command::new ("sh") .arg ("-c") .arg (command) .output())},
    Err (err) => return ERR! ("{}", err)};

  let combined_output: String = if output.stderr.is_empty() {
    try_s! (String::from_utf8 (output.stdout))
  } else if output.stdout.is_empty() {
    try_s! (String::from_utf8 (output.stderr))
  } else {
    let mut buf = String::with_capacity (output.stderr.len() + output.stdout.len());
    buf.push_str (try_s! (std::str::from_utf8 (&output.stderr[..])));
    buf.push_str (try_s! (std::str::from_utf8 (&output.stdout[..])));
    buf};

  if output.status.success() {Ok (combined_output)} else {Err (combined_output)}}

#[test] fn test_slurp_prog() {
  let foo = match slurp_prog ("echo foo") {Ok (foo) => foo, Err (err) => panic! ("{}", err)};
  assert_eq! (foo.trim(), "foo");}

/// Run a command, printing it first. Stdout and stderr are forwarded through (`inherit`).
pub fn cmd (cmd: &str) -> Result<(), String> {
  println! ("$ {}", cmd);
  let status = try_s! (Command::new ("bash") .arg ("-c") .arg (cmd) .stdout (Stdio::inherit()) .stderr (Stdio::inherit()) .status());
  if !status.success() {Err (format! ("Command returned an error status: {}", status))} else {Ok(())}}

/// Useful with panic handlers.
pub fn any_to_str<'a> (message: &'a Box<Any + Send + 'static>) -> Option<&'a str> {
  if let Some (message) = message.downcast_ref::<&str>() {return Some (message)}
  if let Some (message) = message.downcast_ref::<String>() {return Some (&message[..])}
  return None}

// --- nom extensions ---

/// Implements the `/(?x) (.*?) (remainder)/` pattern:
/// looks for remainder first, then returns a tuple with the prefix and the remainder.
///
/// Discussion: https://www.reddit.com/r/rust/comments/4yokxd/crash_course_into_nom_kind_of_question/
#[macro_export]
macro_rules! take_until_parse_s (
  ($i: expr, $remainder: ident! ($($args:tt)*)) => ({
    let input = $i as &str;
    let mut ret = IResult::Error (nom::Err::Position (nom::ErrorKind::Custom (0), input));
    for (pos, _) in $i.char_indices() {
      match $remainder! (&input[pos..], $($args)*) {
        IResult::Done (i,o)    => {ret = IResult::Done (i, (&input[0..pos], o)); break},  // Found the remainder!
        IResult::Error(_)      => continue,  // Keep looking.
        IResult::Incomplete(_) => continue}}  // Keep looking.

    if !ret.is_done() {
      // Last chance. See if subparser accepts an empty string.
      if let IResult::Done (i,o) = $remainder! ("", $($args)*) {
        ret = IResult::Done (i, (input, o))}}  // Empty remainder was accepted.

    ret});

  ($i: expr, $f: expr) => (take_until_parse_s! ($i, call! ($f));););

/// Uses nom to find all matches of the given `$submac` parser and replace them with the `$submac` results.
///
/// For exaple, replacing "foo" with "bar" might look like this:
///
///     let bar_bar = parse_replace_s! ("foo bar", map! (tag_s! ("foo"), |_| "bar"));
#[macro_export]
macro_rules! parse_replace_s {
  ($i: expr, $submac: ident! ($($args:tt)*)) => ({
    let input = $i as &str;
    let mut output = String::with_capacity (input.len() * 2 + 32);
    let mut pos = input;
    while let IResult::Done (tail, (head, evaluation)) = take_until_parse_s! (pos, $submac! ($($args)*)) {
      output.push_str (head);
      output.push_str (&evaluation);
      pos = tail;}
    output.push_str (pos);
    output});

  ($i: expr, $f: expr) => (parse_replace! ($i, call! ($f)););}

/// `$starts` is an optional `Pattern` used to optimize the `$remainder` search.
///
/// For example, with jetscii: `take_until_find_parse_s! ("foo bar", ascii_chars! ('b'), tag_s! ("bar"))`.
#[macro_export]
macro_rules! take_until_find_parse_s (
  ($i: expr, $starts: expr, $remainder: ident! ($($args:tt)*)) => ({
    let input = $i as &str;
    let mut ret = IResult::Error (nom::Err::Position (nom::ErrorKind::Custom (0), input));
    for (pos, _) in $i.match_indices ($starts) {
      match $remainder! (&input[pos..], $($args)*) {
        IResult::Done (i,o)    => {ret = IResult::Done (i, (&input[0..pos], o)); break},  // Found the remainder!
        IResult::Error(_)      => continue,  // Keep looking.
        IResult::Incomplete(_) => continue}}  // Keep looking.
    ret});

  ($i: expr, $starts: expr, $f: expr) => (take_until_find_parse_s! ($i, $starts, call! ($f));););

/// Uses nom to find all matches of the given `$submac` parser and replace them with the parser's evaluations.
///
/// `$starts` is a `Pattern` that is used to speed up the search. It must match the beginning of any `$submac`-compatible substrings.
///
/// For exaple, replacing "foo" with "bar" might look like this:
///
///     let bar_bar = find_parse_replace_s! ("foo bar", ascii_chars! ('f'), map! (tag_s! ("foo"), |_| "bar"));
#[macro_export]
macro_rules! find_parse_replace_s {
  ($i: expr, $starts: expr, $submac: ident! ($($args:tt)*)) => ({
    let input = $i as &str;
    let mut output = String::with_capacity (input.len() * 2 + 32);
    let mut pos = input;
    while let IResult::Done (tail, (head, evaluation)) =
      take_until_find_parse_s! (pos, $starts, $submac! ($($args)*)) {
        output.push_str (head);
        output.push_str (&evaluation);
        pos = tail;}
    output.push_str (pos);
    output});

  ($i: expr, $starts: expr, $f: expr) => (find_parse_replace! ($i, $starts, call! ($f)););}
<commit_msg>Use "dash" instead of "bash" because on Windows 10 "bash" means Ubuntu.<commit_after>#![feature(libc,question_mark)]
extern crate libc;

use std::any::Any;
use std::fs;
use std::io;
use std::io::Read;
use std::path::Path;
use std::process::{Command, Stdio};
use std::str::from_utf8_unchecked;

/// Shortcut to path->filename conversion.
///
/// Returns the unchanged `path` if there is a character encoding error or something.
pub fn filename<'a> (path: &'a str) -> &'a str {
  match Path::new (path) .file_name() {
    Some (filename) => match filename.to_str() {
      Some (fstr) => if fstr.ends_with (".rs") {&fstr[0 .. fstr.len() - 3]} else {fstr},
      None => path},
    None => path}}

mod gstuff {pub fn filename<'a> (path: &'a str) -> &'a str {super::filename (path)}}

// A trick to use the `try_s` macro from both the outside and inside of the crate.
//mod gstuff {pub fn filename<'a> (path: &'a str) -> &'a str {::filename (path)}}

/// Returns on error, converting the `Err` value to `String` and prepending the current location.
///
/// cf. http://www.reddit.com/r/rust/comments/29wwzw/error_handling_and_result_types/cipcm9a
#[macro_export] macro_rules! try_s {
  ($e: expr) => {match $e {Ok (ok) => ok, Err (err) => {return Err (format! ("{}:{}] {}", ::gstuff::filename (file!()), line!(), err));}}}}

// Like `try_s`, but takes a reference.
#[macro_export] macro_rules! try_sp {
  ($e: expr) => {match $e {&Ok (ref ok) => ok,
    &Err (ref err) => {return Err (format! ("{}:{}] {:?}", ::gstuff::filename (file!()), line!(), err));}}}}

/// Returns a `Err(String)`, prepending the current location (file name and line number) to the string.
///
/// Examples: `ERR! ("too bad")`; `ERR! ("{}", foo)`;
#[macro_export] macro_rules! ERR {
  ($format: expr, $($args: tt)+) => {Err (format! (concat! ("{}:{}] ", $format), ::gstuff::filename (file!()), line!(), $($args)+))};
  ($format: expr) => {Err (format! (concat! ("{}:{}] ", $format), ::gstuff::filename (file!()), line!()))}}

/// A helper to build a string on the stack.
///
/// Given an array it makes a writeable cursor available to the passed code block.
///
/// Returns a &str slice pointing at memory between the array start and the cursor.
///
/// Example:
///
///     use std::io::Write;
///     let mut foobar: [u8; 128] = unsafe {std::mem::uninitialized()};
///     let foobar = gstring! (foobar, {
///         write! (foobar, "foo") .expect ("!write");
///         write! (foobar, "bar") .expect ("!write");
///     });
///
/// Alternatives: https://crates.io/crates/stack.
#[macro_export] macro_rules! gstring {($array: ident, $code: block) => {{
  let end = {
    let mut $array = ::std::io::Cursor::new (&mut $array[..]);
    let $array = &mut $array;
    $code;
    $array.position() as usize};
  unsafe {::std::str::from_utf8_unchecked (&$array[0..end])}}}}

/// Takes a netstring from the front of the slice.
///
/// Returns the unpacked netstring and the remainder of the slice.
pub fn netstring (at: &[u8]) -> Result<(&[u8], &[u8]), String> {
  let length_end = match at.iter().position (|&ch| ch < b'0' || ch > b'9') {Some (l) if l > 0 => l, _ => return ERR! ("No len.")};
  match at.get (length_end) {Some (&ch) if ch == b':' => (), _ => return ERR! ("No colon.")};
  let length = unsafe {from_utf8_unchecked (&at[0 .. length_end])};
  let length: usize = try_s! (length.parse());
  let bulk_pos = 0 + length_end + 1;
  let bulk_end = bulk_pos + length;
  match at.get (bulk_end) {Some (&ch) if ch == b',' => (), _ => return ERR! ("No comma.")}
  Ok ((&at[bulk_pos .. bulk_end], &at[bulk_end + 1 ..]))}

/// Wraps `gethostname` to fetch the current hostname into a temporary buffer.
#[cfg(unix)]
pub fn with_hostname (visitor: &mut FnMut (&[u8])) -> Result<(), std::io::Error> {
  use libc::{size_t, gethostname};  // http://man7.org/linux/man-pages/man2/gethostname.2.html
  use std::ffi::CStr;
  use std::io;

  let mut buf = [0; 128];
  let rc = unsafe {gethostname (buf.as_mut_ptr(), (buf.len() - 1) as size_t)};
  if rc == 0 {
    let cs = unsafe {CStr::from_ptr (buf.as_ptr())};
    Ok (visitor (cs.to_bytes()))
  } else {
    Err (io::Error::last_os_error())}}

#[cfg(unix)] #[test] fn test_hostname() {
  let mut hostname = String::new();
  with_hostname (&mut |bytes| hostname = String::from_utf8_lossy (bytes) .into_owned()) .unwrap();}

/// Read contents of the file into a String.
///
/// Returns an empty string if the file is not present under the given path.
pub fn slurp (path: &AsRef<Path>) -> String {
  let mut file = match fs::File::open (path) {
    Ok (f) => f,
    Err (ref err) if err.kind() == io::ErrorKind::NotFound => return String::new(),
    Err (err) => panic! ("Can't open {:?}: {}", path.as_ref(), err)};
  let mut buf = String::new();
  file.read_to_string (&mut buf) .expect ("!read");
  buf}

/// Runs a command in a shell, returning stderr+stdout on success.
///
/// Sometimes we need something simpler than constructing a Command.
///
/// If the command failed then returns it's stderr
pub fn slurp_prog (command: &str) -> Result<String, String> {
  let output = match Command::new ("dash") .arg ("-c") .arg (command) .output() {
    Ok (output) => output,
    Err (ref err) if err.kind() == io::ErrorKind::NotFound => {  // "sh" was not found, try a different name.
      try_s! (Command::new ("sh") .arg ("-c") .arg (command) .output())},
    Err (err) => return ERR! ("{}", err)};

  let combined_output: String = if output.stderr.is_empty() {
    try_s! (String::from_utf8 (output.stdout))
  } else if output.stdout.is_empty() {
    try_s! (String::from_utf8 (output.stderr))
  } else {
    let mut buf = String::with_capacity (output.stderr.len() + output.stdout.len());
    buf.push_str (try_s! (std::str::from_utf8 (&output.stderr[..])));
    buf.push_str (try_s! (std::str::from_utf8 (&output.stdout[..])));
    buf};

  if output.status.success() {Ok (combined_output)} else {Err (combined_output)}}

#[test] fn test_slurp_prog() {
  let foo = match slurp_prog ("echo foo") {Ok (foo) => foo, Err (err) => panic! ("{}", err)};
  assert_eq! (foo.trim(), "foo");}

/// Run a command, printing it first. Stdout and stderr are forwarded through (`inherit`).
pub fn cmd (cmd: &str) -> Result<(), String> {
  println! ("$ {}", cmd);
  let status = try_s! (Command::new ("dash") .arg ("-c") .arg (cmd) .stdout (Stdio::inherit()) .stderr (Stdio::inherit()) .status());
  if !status.success() {Err (format! ("Command returned an error status: {}", status))} else {Ok(())}}

/// Useful with panic handlers.
pub fn any_to_str<'a> (message: &'a Box<Any + Send + 'static>) -> Option<&'a str> {
  if let Some (message) = message.downcast_ref::<&str>() {return Some (message)}
  if let Some (message) = message.downcast_ref::<String>() {return Some (&message[..])}
  return None}

// --- nom extensions ---

/// Implements the `/(?x) (.*?) (remainder)/` pattern:
/// looks for remainder first, then returns a tuple with the prefix and the remainder.
///
/// Discussion: https://www.reddit.com/r/rust/comments/4yokxd/crash_course_into_nom_kind_of_question/
#[macro_export]
macro_rules! take_until_parse_s (
  ($i: expr, $remainder: ident! ($($args:tt)*)) => ({
    let input = $i as &str;
    let mut ret = IResult::Error (nom::Err::Position (nom::ErrorKind::Custom (0), input));
    for (pos, _) in $i.char_indices() {
      match $remainder! (&input[pos..], $($args)*) {
        IResult::Done (i,o)    => {ret = IResult::Done (i, (&input[0..pos], o)); break},  // Found the remainder!
        IResult::Error(_)      => continue,  // Keep looking.
        IResult::Incomplete(_) => continue}}  // Keep looking.

    if !ret.is_done() {
      // Last chance. See if subparser accepts an empty string.
      if let IResult::Done (i,o) = $remainder! ("", $($args)*) {
        ret = IResult::Done (i, (input, o))}}  // Empty remainder was accepted.

    ret});

  ($i: expr, $f: expr) => (take_until_parse_s! ($i, call! ($f));););

/// Uses nom to find all matches of the given `$submac` parser and replace them with the `$submac` results.
///
/// For exaple, replacing "foo" with "bar" might look like this:
///
///     let bar_bar = parse_replace_s! ("foo bar", map! (tag_s! ("foo"), |_| "bar"));
#[macro_export]
macro_rules! parse_replace_s {
  ($i: expr, $submac: ident! ($($args:tt)*)) => ({
    let input = $i as &str;
    let mut output = String::with_capacity (input.len() * 2 + 32);
    let mut pos = input;
    while let IResult::Done (tail, (head, evaluation)) = take_until_parse_s! (pos, $submac! ($($args)*)) {
      output.push_str (head);
      output.push_str (&evaluation);
      pos = tail;}
    output.push_str (pos);
    output});

  ($i: expr, $f: expr) => (parse_replace! ($i, call! ($f)););}

/// `$starts` is an optional `Pattern` used to optimize the `$remainder` search.
///
/// For example, with jetscii: `take_until_find_parse_s! ("foo bar", ascii_chars! ('b'), tag_s! ("bar"))`.
#[macro_export]
macro_rules! take_until_find_parse_s (
  ($i: expr, $starts: expr, $remainder: ident! ($($args:tt)*)) => ({
    let input = $i as &str;
    let mut ret = IResult::Error (nom::Err::Position (nom::ErrorKind::Custom (0), input));
    for (pos, _) in $i.match_indices ($starts) {
      match $remainder! (&input[pos..], $($args)*) {
        IResult::Done (i,o)    => {ret = IResult::Done (i, (&input[0..pos], o)); break},  // Found the remainder!
        IResult::Error(_)      => continue,  // Keep looking.
        IResult::Incomplete(_) => continue}}  // Keep looking.
    ret});

  ($i: expr, $starts: expr, $f: expr) => (take_until_find_parse_s! ($i, $starts, call! ($f));););

/// Uses nom to find all matches of the given `$submac` parser and replace them with the parser's evaluations.
///
/// `$starts` is a `Pattern` that is used to speed up the search. It must match the beginning of any `$submac`-compatible substrings.
///
/// For exaple, replacing "foo" with "bar" might look like this:
///
///     let bar_bar = find_parse_replace_s! ("foo bar", ascii_chars! ('f'), map! (tag_s! ("foo"), |_| "bar"));
#[macro_export]
macro_rules! find_parse_replace_s {
  ($i: expr, $starts: expr, $submac: ident! ($($args:tt)*)) => ({
    let input = $i as &str;
    let mut output = String::with_capacity (input.len() * 2 + 32);
    let mut pos = input;
    while let IResult::Done (tail, (head, evaluation)) =
      take_until_find_parse_s! (pos, $starts, $submac! ($($args)*)) {
        output.push_str (head);
        output.push_str (&evaluation);
        pos = tail;}
    output.push_str (pos);
    output});

  ($i: expr, $starts: expr, $f: expr) => (find_parse_replace! ($i, $starts, call! ($f)););}
<|endoftext|>


<commit_before>use scene::{BoxedScene, Scene, SceneChangeEvent, SceneName};
use engine::EngineData;
use text_renderer::TextRenderer;
use sdl2::pixels::Color;
use std::io::Result;
use std::path::Path;
use uorustlibs::art::ArtReader;

use sdl2::render::{Renderer, Texture, TextureQuery};
use sdl2::rect::Rect;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;

static MAX_X:u32 = 18;
static MAX_Y:u32 = 10;

pub struct TileScene {
    reader: Result<ArtReader>,
    index: u32,
    texture: Option<Texture>,
}

impl TileScene {
    pub fn new<'a>(renderer: &mut Renderer, engine_data: &mut EngineData<'a>) -> BoxedScene<SceneName, EngineData<'a>> {
        let reader = ArtReader::new(&Path::new("./assets/artidx.mul"), &Path::new("./assets/art.mul"));
        let mut scene = Box::new(TileScene {
            reader: reader,
            index: 0,
            texture: None,
        });
        scene.create_slice(renderer, engine_data);

        scene
    }

    fn create_slice(&mut self, renderer: &mut Renderer, engine_data: &mut EngineData) {
        /*match self.reader {
            Ok(ref mut reader) => {
                let limit = MAX_X * MAX_Y;
                let start = limit * self.index;
                let mut dest = ImageBuf::new(1024, 768);

                for x in range(0, MAX_X) {
                    for y in range(0, MAX_Y) {
                        let maybe_tile = reader.read_tile(start + x + (y * MAX_X));
                        match maybe_tile {
                            Ok(tile) => {
                                let (width, height, data) = tile.to_32bit();
                                let buf = ImageBuf::from_fn(width, height, |x, y| {
                                    let (r, g, b, a) = data[((x % height) + (y * width)) as uint].to_rgba();
                                    Rgba(r, g, b, a)
                                });
                                overlay(&mut dest, &buf, 44 * x, (44 + 16) * y)
                            },
                            _ => ()
                        }
                    }
                }

                self.texture = Some(Texture::from_image(&dest))
            },
            Err(_) => {
                self.texture = None
            }
        }*/
    }

    /*fn render(&self, args: RenderArgs, uic: &mut UiContext, gl: &mut Gl) {
        gl.draw([0, 0, args.width as i32, args.height as i32], |c, gl| {
            let limit = MAX_X * MAX_Y;
            let start = limit * self.index;
            uic.background().color(Color::black()).draw(gl);
            match self.texture {
                Some(ref texture) => {
                    image(texture, &c, gl);
                    for x in range(0, MAX_X) {
                        for y in range(0, MAX_Y) {
                            let index = start + x + (y * MAX_X);
                            self.draw_label(uic, gl, format!("{}", index).as_slice(), (44 * x) as f64, (((44 + 16) * y) + 44) as f64)
                        }
                    }
                },
                None => ()
            }
        });
    }*/
}

impl<'a> Scene<SceneName, EngineData<'a>> for TileScene {
    fn render(&self, renderer: &mut Renderer, engine_data: &mut EngineData) {
        /*let TextureQuery {width, height, .. } = self.text.query();
        let target = Rect::new(0, 0, width, height);
        */
        renderer.clear();
        //renderer.copy(&self.text, None, Some(target)).unwrap();
        renderer.present();
    }

    fn handle_event(&mut self, event: &Event, renderer: &mut Renderer, engine_data: &mut EngineData) -> Option<SceneChangeEvent<SceneName>> {
        match *event {
            Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                Some(SceneChangeEvent::PopScene)
            },
            Event::KeyDown { keycode: Some(Keycode::Left), .. } => {
                if self.index > 0 {
                    self.index -= 1;
                    self.create_slice(renderer, engine_data);
                }
                None
            },
            Event::KeyDown { keycode: Some(Keycode::Right), .. } => {
                self.index += 1;
                self.create_slice(renderer, engine_data);
                None
            },
             _ => None
        }
    }
    /*fn handle_event(&mut self, e: &Event, ui_context: &mut UiContext, gl: &mut Gl) -> Option<BoxedScene> {
        match *e {
            Event::Render(args) => {
                self.render(args, ui_context, gl);
            },
            Event::Input(InputEvent::Release(Button::Keyboard(key))) => {
                match key {
                    Key::Left => {
                        if self.index > 0 {
                            self.index -= 1;
                            self.create_slice();
                        }
                    },
                    Key::Right => {
                        self.index += 1;
                        self.create_slice();
                    },
                    _ => ()
                }
            },
            _ => ()
        };
        None
    }*/
}
<commit_msg>Working towards tiles rendering again<commit_after>use scene::{BoxedScene, Scene, SceneChangeEvent, SceneName};
use engine::EngineData;
use text_renderer::TextRenderer;
use sdl2::pixels::{Color, PixelFormatEnum};
use sdl2::surface::Surface;
use std::io::Result;
use std::path::Path;
use uorustlibs::art::{ArtReader, Art};
use uorustlibs::color::Color as UOColor;

use sdl2::render::{Renderer, Texture, TextureQuery};
use sdl2::rect::Rect;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;

static MAX_X:u32 = 20;
static MAX_Y:u32 = 10;

pub struct TileScene {
    reader: Result<ArtReader>,
    index: u32,
    texture: Option<Texture>,
}

impl TileScene {
    pub fn new<'a>(renderer: &mut Renderer, engine_data: &mut EngineData<'a>) -> BoxedScene<SceneName, EngineData<'a>> {
        let reader = ArtReader::new(&Path::new("./assets/artidx.mul"), &Path::new("./assets/art.mul"));
        let mut scene = Box::new(TileScene {
            reader: reader,
            index: 0,
            texture: None,
        });
        scene.create_slice(renderer, engine_data);

        scene
    }

    fn create_slice(&mut self, renderer: &mut Renderer, engine_data: &mut EngineData) {
        match self.reader {
            Ok(ref mut reader) => {
                let limit = MAX_X * MAX_Y;
                let start = limit * self.index;
                let mut dest = Surface::new(1024, 768, PixelFormatEnum::RGBA8888).unwrap();
                dest.fill_rect(None, Color::RGB(0, 0, 0)).unwrap();

                for x in 0..MAX_X {
                    for y in 0..MAX_Y {
                        let maybe_tile = reader.read_tile(start + x + (y * MAX_X));
                        match maybe_tile {
                            Ok(tile) => {
                                let (width, height, data) = tile.to_32bit();
                                let mut surface = Surface::new(width, height, PixelFormatEnum::RGBA8888).unwrap();
                                surface.with_lock_mut(|bitmap| {
                                    for (i, cell) in data.iter().enumerate() {
                                        let (r, g, b, a) = cell.to_rgba();
                                        let offset = i * 4;
                                        bitmap[offset] = 255;
                                        bitmap[offset + 1] = 255;
                                        bitmap[offset + 2] = 255;
                                        bitmap[offset + 3] = 255;
                                    }
                                });
                                surface.blit(None, &mut dest, Some(Rect::new(44 * x as i32, (44 + 16) * y as i32, width, height)));
                            },
                            _ => ()
                        }
                    }
                }

                self.texture = Some(renderer.create_texture_from_surface(&dest).unwrap());
            },
            Err(_) => {
                self.texture = None
            }
        }
    }

    /*fn render(&self, args: RenderArgs, uic: &mut UiContext, gl: &mut Gl) {
        gl.draw([0, 0, args.width as i32, args.height as i32], |c, gl| {
            let limit = MAX_X * MAX_Y;
            let start = limit * self.index;
            uic.background().color(Color::black()).draw(gl);
            match self.texture {
                Some(ref texture) => {
                    image(texture, &c, gl);
                    for x in range(0, MAX_X) {
                        for y in range(0, MAX_Y) {
                            let index = start + x + (y * MAX_X);
                            self.draw_label(uic, gl, format!("{}", index).as_slice(), (44 * x) as f64, (((44 + 16) * y) + 44) as f64)
                        }
                    }
                },
                None => ()
            }
        });
    }*/
}

impl<'a> Scene<SceneName, EngineData<'a>> for TileScene {
    fn render(&self, renderer: &mut Renderer, engine_data: &mut EngineData) {
        /*let TextureQuery {width, height, .. } = self.text.query();
        let target = Rect::new(0, 0, width, height);
        */
        renderer.clear();
        match self.texture {
            Some(ref texture) => {
                renderer.copy(texture, None, None).unwrap();
            },
            None => ()
        };
        renderer.present();
    }

    fn handle_event(&mut self, event: &Event, renderer: &mut Renderer, engine_data: &mut EngineData) -> Option<SceneChangeEvent<SceneName>> {
        match *event {
            Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                Some(SceneChangeEvent::PopScene)
            },
            Event::KeyDown { keycode: Some(Keycode::Left), .. } => {
                if self.index > 0 {
                    self.index -= 1;
                    self.create_slice(renderer, engine_data);
                }
                None
            },
            Event::KeyDown { keycode: Some(Keycode::Right), .. } => {
                self.index += 1;
                self.create_slice(renderer, engine_data);
                None
            },
             _ => None
        }
    }
    /*fn handle_event(&mut self, e: &Event, ui_context: &mut UiContext, gl: &mut Gl) -> Option<BoxedScene> {
        match *e {
            Event::Render(args) => {
                self.render(args, ui_context, gl);
            },
            Event::Input(InputEvent::Release(Button::Keyboard(key))) => {
                match key {
                    Key::Left => {
                        if self.index > 0 {
                            self.index -= 1;
                            self.create_slice();
                        }
                    },
                    Key::Right => {
                        self.index += 1;
                        self.create_slice();
                    },
                    _ => ()
                }
            },
            _ => ()
        };
        None
    }*/
}
<|endoftext|>


<commit_before>use ::{Pattern, PatternHaystack, Searcher, ReverseSearcher, DoubleEndedSearcher};
use iterators::{Split, RSplit};
use iterators::{SplitTerminator, RSplitTerminator};
use iterators::{SplitN, RSplitN};
use iterators::{Matches, RMatches};
use iterators::{MatchIndices, RMatchIndices};
use ::InverseMatchesAreValid;

pub trait IteratorConstructors: PatternHaystack {
    #[inline]
    fn contains<P: Pattern<Self>>(self, pat: P) -> bool {
        pat.is_contained_in(self)
    }

    #[inline]
    fn split<P: Pattern<Self>>(self, pat: P) -> Split<Self, P>
        where Self: InverseMatchesAreValid
    {
        Split::new(self, pat)
    }

    #[inline]
    fn rsplit<P: Pattern<Self>>(self, pat: P) -> RSplit<Self, P>
        where P::Searcher: ReverseSearcher<Self>,
              Self: InverseMatchesAreValid
    {
        RSplit::new(self, pat)
    }

    #[inline]
    fn splitn<P: Pattern<Self>>(self, count: usize, pat: P) -> SplitN<Self, P>
        where Self: InverseMatchesAreValid
    {
        SplitN::new(self, pat, count)
    }

    #[inline]
    fn rsplitn<P: Pattern<Self>>(self, count: usize, pat: P) -> RSplitN<Self, P>
        where P::Searcher: ReverseSearcher<Self>,
              Self: InverseMatchesAreValid
    {
        RSplitN::new(self, pat, count)
    }

    #[inline]
    fn split_terminator<P: Pattern<Self>>(self, pat: P) -> SplitTerminator<Self, P>
        where Self: InverseMatchesAreValid
    {
        SplitTerminator::new(self, pat)
    }

    #[inline]
    fn rsplit_terminator<P: Pattern<Self>>(self, pat: P) -> RSplitTerminator<Self, P>
        where P::Searcher: ReverseSearcher<Self>,
              Self: InverseMatchesAreValid
    {
        RSplitTerminator::new(self, pat)
    }

    #[inline]
    fn matches<P: Pattern<Self>>(self, pat: P) -> Matches<Self, P> {
        Matches::new(self, pat)
    }

    #[inline]
    fn rmatches<P: Pattern<Self>>(self, pat: P) -> RMatches<Self, P>
        where P::Searcher: ReverseSearcher<Self>
    {
        RMatches::new(self, pat)
    }

    #[inline]
    fn match_indices<P: Pattern<Self>>(self, pat: P) -> MatchIndices<Self, P> {
        MatchIndices::new(self, pat)
    }

    #[inline]
    fn rmatch_indices<P: Pattern<Self>>(self, pat: P) -> RMatchIndices<Self, P>
        where P::Searcher: ReverseSearcher<Self>
    {
        RMatchIndices::new(self, pat)
    }

    #[inline]
    fn starts_with<P: Pattern<Self>>(self, pat: P) -> bool {
        pat.is_prefix_of(self)
    }

    #[inline]
    fn ends_with<P: Pattern<Self>>(self, pat: P) -> bool
        where P::Searcher: ReverseSearcher<Self>
    {
        pat.is_suffix_of(self)
    }

    #[inline]
    fn trim_matches<P: Pattern<Self>>(self, pat: P) -> Self::MatchType
        where P::Searcher: DoubleEndedSearcher<Self>
    {
        let mut matcher = pat.into_searcher(self);
        let mut i = Self::cursor_at_front(matcher.haystack());
        let mut j = Self::cursor_at_front(matcher.haystack());
        if let Some((a, b)) = matcher.next_reject() {
            i = a;
            j = b; // Remember earliest known match, correct it below if
                   // last match is different
        }
        if let Some((_, b)) = matcher.next_reject_back() {
            j = b;
        }
        unsafe {
            // Searcher is known to return valid indices
            Self::range_to_self(matcher.haystack(), i, j)
        }
    }

    #[inline]
    fn trim_left_matches<P: Pattern<Self>>(self, pat: P) -> Self::MatchType {
        let mut matcher = pat.into_searcher(self);
        let mut i = Self::cursor_at_back(matcher.haystack());
        let j = Self::cursor_at_back(matcher.haystack());
        if let Some((a, _)) = matcher.next_reject() {
            i = a;
        }
        unsafe {
            // Searcher is known to return valid indices
            Self::range_to_self(matcher.haystack(), i, j)
        }
    }

    #[inline]
    fn trim_right_matches<P: Pattern<Self>>(self, pat: P) -> Self::MatchType
        where P::Searcher: ReverseSearcher<Self>
    {
        let mut matcher = pat.into_searcher(self);
        let i = Self::cursor_at_front(matcher.haystack());
        let mut j = Self::cursor_at_front(matcher.haystack());
        if let Some((_, b)) = matcher.next_reject_back() {
            j = b;
        }
        unsafe {
            // Searcher is known to return valid indices
            Self::range_to_self(matcher.haystack(), i, j)
        }
    }

    fn find<P: Pattern<Self>>(self, pat: P) -> Option<usize> {
        let mut searcher = pat.into_searcher(self);
        let h = searcher.haystack();
        searcher.next_match().map(|(i, _)| Self::offset_from_front(h, i))
    }

    fn rfind<P: Pattern<Self>>(self, pat: P) -> Option<usize>
        where P::Searcher: ReverseSearcher<Self>
    {
        let mut searcher = pat.into_searcher(self);
        let h = searcher.haystack();
        searcher.next_match_back().map(|(i, _)| Self::offset_from_front(h, i))
    }
}

impl<T: PatternHaystack> IteratorConstructors for T {}

use os_string::shared::PartialUnicode as OsStrPartialUnicode;
use os_string::mutable::PartialUnicode as MutOsStrPartialUnicode;
use std::ffi::OsStr;
use std::ffi::OsString;
use std::char;
//use std::os::unix::ffi::OsStrExt;

pub trait OsStrExtension {
    fn for_unicode(&self) -> OsStrPartialUnicode;
    fn for_unicode_mut(&mut self) -> MutOsStrPartialUnicode;

    fn starts_with_os<S: AsRef<OsStr>>(&self, s: S) -> bool;
    fn ends_with_os<S: AsRef<OsStr>>(&self, s: S) -> bool;
    fn contains_os<S: AsRef<OsStr>>(&self, s: S) -> bool;
}

pub trait OsStringExtension {
    fn from_wide(s: &[u16]) -> Self;
    fn push_str(&mut self, &str);
    fn push_codepoint_unadjusted(&mut self, u32);
}

impl OsStrExtension for OsStr {
    fn for_unicode(&self) -> OsStrPartialUnicode {
        OsStrPartialUnicode { os_str: self }
    }
    fn for_unicode_mut(&mut self) -> MutOsStrPartialUnicode {
        MutOsStrPartialUnicode { os_str: self }
    }
    fn starts_with_os<S: AsRef<OsStr>>(&self, s: S) -> bool {
        self.starts_with(s.as_ref())
    }
    fn ends_with_os<S: AsRef<OsStr>>(&self, s: S) -> bool {
        self.ends_with(s.as_ref())
    }
    fn contains_os<S: AsRef<OsStr>>(&self, s: S) -> bool {
        self.contains(s.as_ref())
    }
}

impl OsStringExtension for OsString {
    fn from_wide(v: &[u16]) -> OsString {
        let mut string = OsString::with_capacity(v.len());
        for item in char::decode_utf16(v.iter().cloned()) {
            match item {
                Ok(ch) => {
                    string.push_codepoint_unadjusted(ch as u32);
                }
                Err(surrogate) => {
                    string.push_codepoint_unadjusted(surrogate as u32);
                }
            }
        }
        string
    }
    fn push_str(&mut self, s: &str) {
        unsafe {
            ::std::mem::transmute::<&mut OsString, &mut Vec<u8>>(self)
                .extend(s.bytes());
        }
    }
    fn push_codepoint_unadjusted(&mut self, cp: u32) {
        unsafe {
            let ch = char::from_u32_unchecked(cp as u32);
            for byte in ch.encode_utf8() {
                ::std::mem::transmute::<&mut OsString, &mut Vec<u8>>(self)
                    .push(byte);
            }
        }
    }
}
<commit_msg>quick fix for nightly build<commit_after>use ::{Pattern, PatternHaystack, Searcher, ReverseSearcher, DoubleEndedSearcher};
use iterators::{Split, RSplit};
use iterators::{SplitTerminator, RSplitTerminator};
use iterators::{SplitN, RSplitN};
use iterators::{Matches, RMatches};
use iterators::{MatchIndices, RMatchIndices};
use ::InverseMatchesAreValid;

pub trait IteratorConstructors: PatternHaystack {
    #[inline]
    fn contains<P: Pattern<Self>>(self, pat: P) -> bool {
        pat.is_contained_in(self)
    }

    #[inline]
    fn split<P: Pattern<Self>>(self, pat: P) -> Split<Self, P>
        where Self: InverseMatchesAreValid
    {
        Split::new(self, pat)
    }

    #[inline]
    fn rsplit<P: Pattern<Self>>(self, pat: P) -> RSplit<Self, P>
        where P::Searcher: ReverseSearcher<Self>,
              Self: InverseMatchesAreValid
    {
        RSplit::new(self, pat)
    }

    #[inline]
    fn splitn<P: Pattern<Self>>(self, count: usize, pat: P) -> SplitN<Self, P>
        where Self: InverseMatchesAreValid
    {
        SplitN::new(self, pat, count)
    }

    #[inline]
    fn rsplitn<P: Pattern<Self>>(self, count: usize, pat: P) -> RSplitN<Self, P>
        where P::Searcher: ReverseSearcher<Self>,
              Self: InverseMatchesAreValid
    {
        RSplitN::new(self, pat, count)
    }

    #[inline]
    fn split_terminator<P: Pattern<Self>>(self, pat: P) -> SplitTerminator<Self, P>
        where Self: InverseMatchesAreValid
    {
        SplitTerminator::new(self, pat)
    }

    #[inline]
    fn rsplit_terminator<P: Pattern<Self>>(self, pat: P) -> RSplitTerminator<Self, P>
        where P::Searcher: ReverseSearcher<Self>,
              Self: InverseMatchesAreValid
    {
        RSplitTerminator::new(self, pat)
    }

    #[inline]
    fn matches<P: Pattern<Self>>(self, pat: P) -> Matches<Self, P> {
        Matches::new(self, pat)
    }

    #[inline]
    fn rmatches<P: Pattern<Self>>(self, pat: P) -> RMatches<Self, P>
        where P::Searcher: ReverseSearcher<Self>
    {
        RMatches::new(self, pat)
    }

    #[inline]
    fn match_indices<P: Pattern<Self>>(self, pat: P) -> MatchIndices<Self, P> {
        MatchIndices::new(self, pat)
    }

    #[inline]
    fn rmatch_indices<P: Pattern<Self>>(self, pat: P) -> RMatchIndices<Self, P>
        where P::Searcher: ReverseSearcher<Self>
    {
        RMatchIndices::new(self, pat)
    }

    #[inline]
    fn starts_with<P: Pattern<Self>>(self, pat: P) -> bool {
        pat.is_prefix_of(self)
    }

    #[inline]
    fn ends_with<P: Pattern<Self>>(self, pat: P) -> bool
        where P::Searcher: ReverseSearcher<Self>
    {
        pat.is_suffix_of(self)
    }

    #[inline]
    fn trim_matches<P: Pattern<Self>>(self, pat: P) -> Self::MatchType
        where P::Searcher: DoubleEndedSearcher<Self>
    {
        let mut matcher = pat.into_searcher(self);
        let mut i = Self::cursor_at_front(matcher.haystack());
        let mut j = Self::cursor_at_front(matcher.haystack());
        if let Some((a, b)) = matcher.next_reject() {
            i = a;
            j = b; // Remember earliest known match, correct it below if
                   // last match is different
        }
        if let Some((_, b)) = matcher.next_reject_back() {
            j = b;
        }
        unsafe {
            // Searcher is known to return valid indices
            Self::range_to_self(matcher.haystack(), i, j)
        }
    }

    #[inline]
    fn trim_left_matches<P: Pattern<Self>>(self, pat: P) -> Self::MatchType {
        let mut matcher = pat.into_searcher(self);
        let mut i = Self::cursor_at_back(matcher.haystack());
        let j = Self::cursor_at_back(matcher.haystack());
        if let Some((a, _)) = matcher.next_reject() {
            i = a;
        }
        unsafe {
            // Searcher is known to return valid indices
            Self::range_to_self(matcher.haystack(), i, j)
        }
    }

    #[inline]
    fn trim_right_matches<P: Pattern<Self>>(self, pat: P) -> Self::MatchType
        where P::Searcher: ReverseSearcher<Self>
    {
        let mut matcher = pat.into_searcher(self);
        let i = Self::cursor_at_front(matcher.haystack());
        let mut j = Self::cursor_at_front(matcher.haystack());
        if let Some((_, b)) = matcher.next_reject_back() {
            j = b;
        }
        unsafe {
            // Searcher is known to return valid indices
            Self::range_to_self(matcher.haystack(), i, j)
        }
    }

    fn find<P: Pattern<Self>>(self, pat: P) -> Option<usize> {
        let mut searcher = pat.into_searcher(self);
        let h = searcher.haystack();
        searcher.next_match().map(|(i, _)| Self::offset_from_front(h, i))
    }

    fn rfind<P: Pattern<Self>>(self, pat: P) -> Option<usize>
        where P::Searcher: ReverseSearcher<Self>
    {
        let mut searcher = pat.into_searcher(self);
        let h = searcher.haystack();
        searcher.next_match_back().map(|(i, _)| Self::offset_from_front(h, i))
    }
}

impl<T: PatternHaystack> IteratorConstructors for T {}

use os_string::shared::PartialUnicode as OsStrPartialUnicode;
use os_string::mutable::PartialUnicode as MutOsStrPartialUnicode;
use std::ffi::OsStr;
use std::ffi::OsString;
use std::char;
//use std::os::unix::ffi::OsStrExt;

pub trait OsStrExtension {
    fn for_unicode(&self) -> OsStrPartialUnicode;
    fn for_unicode_mut(&mut self) -> MutOsStrPartialUnicode;

    fn starts_with_os<S: AsRef<OsStr>>(&self, s: S) -> bool;
    fn ends_with_os<S: AsRef<OsStr>>(&self, s: S) -> bool;
    fn contains_os<S: AsRef<OsStr>>(&self, s: S) -> bool;
}

pub trait OsStringExtension {
    fn from_wide(s: &[u16]) -> Self;
    fn push_str(&mut self, &str);
    fn push_codepoint_unadjusted(&mut self, u32);
}

impl OsStrExtension for OsStr {
    fn for_unicode(&self) -> OsStrPartialUnicode {
        OsStrPartialUnicode { os_str: self }
    }
    fn for_unicode_mut(&mut self) -> MutOsStrPartialUnicode {
        MutOsStrPartialUnicode { os_str: self }
    }
    fn starts_with_os<S: AsRef<OsStr>>(&self, s: S) -> bool {
        self.starts_with(s.as_ref())
    }
    fn ends_with_os<S: AsRef<OsStr>>(&self, s: S) -> bool {
        self.ends_with(s.as_ref())
    }
    fn contains_os<S: AsRef<OsStr>>(&self, s: S) -> bool {
        self.contains(s.as_ref())
    }
}

impl OsStringExtension for OsString {
    fn from_wide(v: &[u16]) -> OsString {
        let mut string = OsString::with_capacity(v.len());
        for item in char::decode_utf16(v.iter().cloned()) {
            match item {
                Ok(ch) => {
                    string.push_codepoint_unadjusted(ch as u32);
                }
                Err(surrogate) => {
                    string.push_codepoint_unadjusted(
                        surrogate.unpaired_surrogate() as u32);
                }
            }
        }
        string
    }
    fn push_str(&mut self, s: &str) {
        unsafe {
            ::std::mem::transmute::<&mut OsString, &mut Vec<u8>>(self)
                .extend(s.bytes());
        }
    }
    fn push_codepoint_unadjusted(&mut self, cp: u32) {
        unsafe {
            let ch = char::from_u32_unchecked(cp as u32);
            for byte in ch.encode_utf8() {
                ::std::mem::transmute::<&mut OsString, &mut Vec<u8>>(self)
                    .push(byte);
            }
        }
    }
}
<|endoftext|>