<commit_before>use std::fmt::Write;

use syntax_pos::symbol::Symbol;
use rustc::ty::layout::{self, Size, Primitive};
use rustc::ty::{self, Ty};
use rustc_data_structures::fx::FxHashSet;
use rustc::mir::interpret::{
    Scalar, AllocType, EvalResult, ScalarMaybeUndef,
};

use super::{
    MPlaceTy, PlaceExtra, Machine, EvalContext
};

macro_rules! validation_failure{
    ($what:expr, $where:expr, $details:expr) => {{
        let where_ = path_format($where);
        let where_ = if where_.is_empty() {
            String::new()
        } else {
            format!(" at {}", where_)
        };
        err!(ValidationFailure(format!(
            "encountered {}{}, but expected {}",
            $what, where_, $details,
        )))
    }};
    ($what:expr, $where:expr) => {{
        let where_ = path_format($where);
        let where_ = if where_.is_empty() {
            String::new()
        } else {
            format!(" at {}", where_)
        };
        err!(ValidationFailure(format!(
            "encountered {}{}",
            $what, where_,
        )))
    }};
}

/// We want to show a nice path to the invalid field for diagnotsics,
/// but avoid string operations in the happy case where no error happens.
/// So we track a `Vec<PathElem>` where `PathElem` contains all the data we
/// need to later print something for the user.
#[derive(Copy, Clone, Debug)]
pub enum PathElem {
    Field(Symbol),
    ClosureVar(Symbol),
    ArrayElem(usize),
    TupleElem(usize),
    Deref,
    Tag,
}

// Adding a Deref and making a copy of the path to be put into the queue
// always go together.  This one does it with only new allocation.
fn path_clone_and_deref(path: &Vec<PathElem>) -> Vec<PathElem> {
    let mut new_path = Vec::with_capacity(path.len()+1);
    new_path.clone_from(path);
    new_path.push(PathElem::Deref);
    new_path
}

/// Format a path
fn path_format(path: &Vec<PathElem>) -> String {
    use self::PathElem::*;

    let mut out = String::new();
    for elem in path.iter() {
        match elem {
            Field(name) => write!(out, ".{}", name).unwrap(),
            ClosureVar(name) => write!(out, ".<closure-var({})>", name).unwrap(),
            TupleElem(idx) => write!(out, ".{}", idx).unwrap(),
            ArrayElem(idx) => write!(out, "[{}]", idx).unwrap(),
            Deref =>
                // This does not match Rust syntax, but it is more readable for long paths -- and
                // some of the other items here also are not Rust syntax.  Actually we can't
                // even use the usual syntax because we are just showing the projections,
                // not the root.
                write!(out, ".<deref>").unwrap(),
            Tag => write!(out, ".<enum-tag>").unwrap(),
        }
    }
    out
}

impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
    fn validate_scalar(
        &self,
        value: ScalarMaybeUndef,
        size: Size,
        scalar: &layout::Scalar,
        path: &Vec<PathElem>,
        ty: Ty,
    ) -> EvalResult<'tcx> {
        trace!("validate scalar: {:#?}, {:#?}, {:#?}, {}", value, size, scalar, ty);
        let (lo, hi) = scalar.valid_range.clone().into_inner();

        let value = match value {
            ScalarMaybeUndef::Scalar(scalar) => scalar,
            ScalarMaybeUndef::Undef => return validation_failure!("undefined bytes", path),
        };

        let bits = match value {
            Scalar::Bits { bits, size: value_size } => {
                assert_eq!(value_size as u64, size.bytes());
                bits
            },
            Scalar::Ptr(_) => {
                let ptr_size = self.memory.pointer_size();
                let ptr_max = u128::max_value() >> (128 - ptr_size.bits());
                return if lo > hi {
                    if lo - hi == 1 {
                        // no gap, all values are ok
                        Ok(())
                    } else if hi < ptr_max || lo > 1 {
                        let max = u128::max_value() >> (128 - size.bits());
                        validation_failure!(
                            "pointer",
                            path,
                            format!("something in the range {:?} or {:?}", 0..=lo, hi..=max)
                        )
                    } else {
                        Ok(())
                    }
                } else if hi < ptr_max || lo > 1 {
                    validation_failure!(
                        "pointer",
                        path,
                        format!("something in the range {:?}", scalar.valid_range)
                    )
                } else {
                    Ok(())
                };
            },
        };

        // char gets a special treatment, because its number space is not contiguous so `TyLayout`
        // has no special checks for chars
        match ty.sty {
            ty::TyChar => {
                debug_assert_eq!(size.bytes(), 4);
                if ::std::char::from_u32(bits as u32).is_none() {
                    return validation_failure!(
                        "character",
                        path,
                        "a valid unicode codepoint"
                    );
                }
            }
            _ => {},
        }

        use std::ops::RangeInclusive;
        let in_range = |bound: RangeInclusive<u128>| bound.contains(&bits);
        if lo > hi {
            if in_range(0..=hi) || in_range(lo..=u128::max_value()) {
                Ok(())
            } else {
                validation_failure!(
                    bits,
                    path,
                    format!("something in the range {:?} or {:?}", ..=hi, lo..)
                )
            }
        } else {
            if in_range(scalar.valid_range.clone()) {
                Ok(())
            } else {
                validation_failure!(
                    bits,
                    path,
                    format!("something in the range {:?}", scalar.valid_range)
                )
            }
        }
    }

    /// This function checks the memory where `dest` points to.  The place must be sized
    /// (i.e., dest.extra == PlaceExtra::None).
    /// It will error if the bits at the destination do not match the ones described by the layout.
    /// The `path` may be pushed to, but the part that is present when the function
    /// starts must not be changed!
    pub fn validate_mplace(
        &self,
        dest: MPlaceTy<'tcx>,
        path: &mut Vec<PathElem>,
        seen: &mut FxHashSet<(MPlaceTy<'tcx>)>,
        todo: &mut Vec<(MPlaceTy<'tcx>, Vec<PathElem>)>,
    ) -> EvalResult<'tcx> {
        self.memory.dump_alloc(dest.to_ptr()?.alloc_id);
        trace!("validate_mplace: {:?}, {:#?}", *dest, dest.layout);

        // Find the right variant.  We have to handle this as a prelude, not via
        // proper recursion with the new inner layout, to be able to later nicely
        // print the field names of the enum field that is being accessed.
        let (variant, dest) = match dest.layout.variants {
            layout::Variants::NicheFilling { niche: ref tag, .. } |
            layout::Variants::Tagged { ref tag, .. } => {
                let size = tag.value.size(self);
                // we first read the tag value as scalar, to be able to validate it
                let tag_mplace = self.mplace_field(dest, 0)?;
                let tag_value = self.read_scalar(tag_mplace.into())?;
                path.push(PathElem::Tag);
                self.validate_scalar(
                    tag_value, size, tag, &path, tag_mplace.layout.ty
                )?;
                path.pop(); // remove the element again
                // then we read it again to get the index, to continue
                let variant = self.read_discriminant_as_variant_index(dest.into())?;
                let inner_dest = self.mplace_downcast(dest, variant)?;
                // Put the variant projection onto the path, as a field
                path.push(PathElem::Field(dest.layout.ty.ty_adt_def().unwrap().variants[variant].name));
                trace!("variant layout: {:#?}", dest.layout);
                (variant, inner_dest)
            },
            layout::Variants::Single { index } => {
                (index, dest)
            }
        };

        // Remember the length, in case we need to truncate
        let path_len = path.len();

        // Validate all fields
        match dest.layout.fields {
            // primitives are unions with zero fields
            layout::FieldPlacement::Union(0) => {
                match dest.layout.abi {
                    // nothing to do, whatever the pointer points to, it is never going to be read
                    layout::Abi::Uninhabited =>
                        return validation_failure!("a value of an uninhabited type", path),
                    // check that the scalar is a valid pointer or that its bit range matches the
                    // expectation.
                    layout::Abi::Scalar(ref scalar_layout) => {
                        let size = scalar_layout.value.size(self);
                        let value = self.read_value(dest.into())?;
                        let scalar = value.to_scalar_or_undef();
                        self.validate_scalar(scalar, size, scalar_layout, &path, dest.layout.ty)?;
                        if scalar_layout.value == Primitive::Pointer {
                            // ignore integer pointers, we can't reason about the final hardware
                            if let Scalar::Ptr(ptr) = scalar.not_undef()? {
                                let alloc_kind = self.tcx.alloc_map.lock().get(ptr.alloc_id);
                                if let Some(AllocType::Static(did)) = alloc_kind {
                                    // statics from other crates are already checked.
                                    // extern statics should not be validated as they have no body.
                                    if !did.is_local() || self.tcx.is_foreign_item(did) {
                                        return Ok(());
                                    }
                                }
                                if value.layout.ty.builtin_deref(false).is_some() {
                                    trace!("Recursing below ptr {:#?}", value);
                                    let ptr_place = self.ref_to_mplace(value)?;
                                    // we have not encountered this pointer+layout combination before
                                    if seen.insert(ptr_place) {
                                        todo.push((ptr_place, path_clone_and_deref(path)));
                                    }
                                }
                            }
                        }
                    },
                    _ => bug!("bad abi for FieldPlacement::Union(0): {:#?}", dest.layout.abi),
                }
            }
            layout::FieldPlacement::Union(_) => {
                // We can't check unions, their bits are allowed to be anything.
                // The fields don't need to correspond to any bit pattern of the union's fields.
                // See https://github.com/rust-lang/rust/issues/32836#issuecomment-406875389
            },
            layout::FieldPlacement::Array { .. } => {
                for (i, field) in self.mplace_array_fields(dest)?.enumerate() {
                    let field = field?;
                    path.push(PathElem::ArrayElem(i));
                    self.validate_mplace(field, path, seen, todo)?;
                    path.truncate(path_len);
                }
            },
            layout::FieldPlacement::Arbitrary { ref offsets, .. } => {
                // fat pointers need special treatment
                match dest.layout.ty.builtin_deref(false).map(|tam| &tam.ty.sty) {
                    | Some(ty::TyStr)
                    | Some(ty::TySlice(_)) => {
                        // check the length (for nicer error messages)
                        let len_mplace = self.mplace_field(dest, 1)?;
                        let len = self.read_scalar(len_mplace.into())?;
                        let len = match len.to_bits(len_mplace.layout.size) {
                            Err(_) => return validation_failure!("length is not a valid integer", path),
                            Ok(len) => len as u64,
                        };
                        // get the fat ptr, and recursively check it
                        let ptr = self.ref_to_mplace(self.read_value(dest.into())?)?;
                        assert_eq!(ptr.extra, PlaceExtra::Length(len));
                        let unpacked_ptr = self.unpack_unsized_mplace(ptr)?;
                        if seen.insert(unpacked_ptr) {
                            todo.push((unpacked_ptr, path_clone_and_deref(path)));
                        }
                    },
                    Some(ty::TyDynamic(..)) => {
                        // check the vtable (for nicer error messages)
                        let vtable = self.read_scalar(self.mplace_field(dest, 1)?.into())?;
                        let vtable = match vtable.to_ptr() {
                            Err(_) => return validation_failure!("vtable address is not a pointer", path),
                            Ok(vtable) => vtable,
                        };
                        // get the fat ptr, and recursively check it
                        let ptr = self.ref_to_mplace(self.read_value(dest.into())?)?;
                        assert_eq!(ptr.extra, PlaceExtra::Vtable(vtable));
                        let unpacked_ptr = self.unpack_unsized_mplace(ptr)?;
                        if seen.insert(unpacked_ptr) {
                            todo.push((unpacked_ptr, path_clone_and_deref(path)));
                        }
                        // FIXME: More checks for the vtable... making sure it is exactly
                        // the one one would expect for this type.
                    },
                    Some(ty) =>
                        bug!("Unexpected fat pointer target type {:?}", ty),
                    None => {
                        // Not a pointer, perform regular aggregate handling below
                        for i in 0..offsets.len() {
                            let field = self.mplace_field(dest, i as u64)?;
                            path.push(self.aggregate_field_path_elem(dest.layout.ty, variant, i));
                            self.validate_mplace(field, path, seen, todo)?;
                            path.truncate(path_len);
                        }
                        // FIXME: For a TyStr, check that this is valid UTF-8.
                    },
                }
            }
        }
        Ok(())
    }

    fn aggregate_field_path_elem(&self, ty: Ty<'tcx>, variant: usize, field: usize) -> PathElem {
        match ty.sty {
            // generators and closures.
            ty::TyClosure(def_id, _) | ty::TyGenerator(def_id, _, _) => {
                let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap();
                let freevar = self.tcx.with_freevars(node_id, |fv| fv[field]);
                PathElem::ClosureVar(self.tcx.hir.name(freevar.var_id()))
            }

            // tuples
            ty::TyTuple(_) => PathElem::TupleElem(field),

            // enums
            ty::TyAdt(def, ..) if def.is_enum() => {
                let variant = &def.variants[variant];
                PathElem::Field(variant.fields[field].ident.name)
            }

            // other ADTs
            ty::TyAdt(def, _) => PathElem::Field(def.non_enum_variant().fields[field].ident.name),

            // nothing else has an aggregate layout
            _ => bug!("aggregate_field_path_elem: got non-aggregate type {:?}", ty),
        }
    }
}
<commit_msg>fix validating fat raw pointers<commit_after>use std::fmt::Write;

use syntax_pos::symbol::Symbol;
use rustc::ty::layout::{self, Size, Primitive};
use rustc::ty::{self, Ty};
use rustc_data_structures::fx::FxHashSet;
use rustc::mir::interpret::{
    Scalar, AllocType, EvalResult, ScalarMaybeUndef,
};

use super::{
    MPlaceTy, PlaceExtra, Machine, EvalContext
};

macro_rules! validation_failure{
    ($what:expr, $where:expr, $details:expr) => {{
        let where_ = path_format($where);
        let where_ = if where_.is_empty() {
            String::new()
        } else {
            format!(" at {}", where_)
        };
        err!(ValidationFailure(format!(
            "encountered {}{}, but expected {}",
            $what, where_, $details,
        )))
    }};
    ($what:expr, $where:expr) => {{
        let where_ = path_format($where);
        let where_ = if where_.is_empty() {
            String::new()
        } else {
            format!(" at {}", where_)
        };
        err!(ValidationFailure(format!(
            "encountered {}{}",
            $what, where_,
        )))
    }};
}

/// We want to show a nice path to the invalid field for diagnotsics,
/// but avoid string operations in the happy case where no error happens.
/// So we track a `Vec<PathElem>` where `PathElem` contains all the data we
/// need to later print something for the user.
#[derive(Copy, Clone, Debug)]
pub enum PathElem {
    Field(Symbol),
    ClosureVar(Symbol),
    ArrayElem(usize),
    TupleElem(usize),
    Deref,
    Tag,
}

// Adding a Deref and making a copy of the path to be put into the queue
// always go together.  This one does it with only new allocation.
fn path_clone_and_deref(path: &Vec<PathElem>) -> Vec<PathElem> {
    let mut new_path = Vec::with_capacity(path.len()+1);
    new_path.clone_from(path);
    new_path.push(PathElem::Deref);
    new_path
}

/// Format a path
fn path_format(path: &Vec<PathElem>) -> String {
    use self::PathElem::*;

    let mut out = String::new();
    for elem in path.iter() {
        match elem {
            Field(name) => write!(out, ".{}", name).unwrap(),
            ClosureVar(name) => write!(out, ".<closure-var({})>", name).unwrap(),
            TupleElem(idx) => write!(out, ".{}", idx).unwrap(),
            ArrayElem(idx) => write!(out, "[{}]", idx).unwrap(),
            Deref =>
                // This does not match Rust syntax, but it is more readable for long paths -- and
                // some of the other items here also are not Rust syntax.  Actually we can't
                // even use the usual syntax because we are just showing the projections,
                // not the root.
                write!(out, ".<deref>").unwrap(),
            Tag => write!(out, ".<enum-tag>").unwrap(),
        }
    }
    out
}

impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
    fn validate_scalar(
        &self,
        value: ScalarMaybeUndef,
        size: Size,
        scalar: &layout::Scalar,
        path: &Vec<PathElem>,
        ty: Ty,
    ) -> EvalResult<'tcx> {
        trace!("validate scalar: {:#?}, {:#?}, {:#?}, {}", value, size, scalar, ty);
        let (lo, hi) = scalar.valid_range.clone().into_inner();

        let value = match value {
            ScalarMaybeUndef::Scalar(scalar) => scalar,
            ScalarMaybeUndef::Undef => return validation_failure!("undefined bytes", path),
        };

        let bits = match value {
            Scalar::Bits { bits, size: value_size } => {
                assert_eq!(value_size as u64, size.bytes());
                bits
            },
            Scalar::Ptr(_) => {
                let ptr_size = self.memory.pointer_size();
                let ptr_max = u128::max_value() >> (128 - ptr_size.bits());
                return if lo > hi {
                    if lo - hi == 1 {
                        // no gap, all values are ok
                        Ok(())
                    } else if hi < ptr_max || lo > 1 {
                        let max = u128::max_value() >> (128 - size.bits());
                        validation_failure!(
                            "pointer",
                            path,
                            format!("something in the range {:?} or {:?}", 0..=lo, hi..=max)
                        )
                    } else {
                        Ok(())
                    }
                } else if hi < ptr_max || lo > 1 {
                    validation_failure!(
                        "pointer",
                        path,
                        format!("something in the range {:?}", scalar.valid_range)
                    )
                } else {
                    Ok(())
                };
            },
        };

        // char gets a special treatment, because its number space is not contiguous so `TyLayout`
        // has no special checks for chars
        match ty.sty {
            ty::TyChar => {
                debug_assert_eq!(size.bytes(), 4);
                if ::std::char::from_u32(bits as u32).is_none() {
                    return validation_failure!(
                        "character",
                        path,
                        "a valid unicode codepoint"
                    );
                }
            }
            _ => {},
        }

        use std::ops::RangeInclusive;
        let in_range = |bound: RangeInclusive<u128>| bound.contains(&bits);
        if lo > hi {
            if in_range(0..=hi) || in_range(lo..=u128::max_value()) {
                Ok(())
            } else {
                validation_failure!(
                    bits,
                    path,
                    format!("something in the range {:?} or {:?}", ..=hi, lo..)
                )
            }
        } else {
            if in_range(scalar.valid_range.clone()) {
                Ok(())
            } else {
                validation_failure!(
                    bits,
                    path,
                    format!("something in the range {:?}", scalar.valid_range)
                )
            }
        }
    }

    /// This function checks the memory where `dest` points to.  The place must be sized
    /// (i.e., dest.extra == PlaceExtra::None).
    /// It will error if the bits at the destination do not match the ones described by the layout.
    /// The `path` may be pushed to, but the part that is present when the function
    /// starts must not be changed!
    pub fn validate_mplace(
        &self,
        dest: MPlaceTy<'tcx>,
        path: &mut Vec<PathElem>,
        seen: &mut FxHashSet<(MPlaceTy<'tcx>)>,
        todo: &mut Vec<(MPlaceTy<'tcx>, Vec<PathElem>)>,
    ) -> EvalResult<'tcx> {
        self.memory.dump_alloc(dest.to_ptr()?.alloc_id);
        trace!("validate_mplace: {:?}, {:#?}", *dest, dest.layout);

        // Find the right variant.  We have to handle this as a prelude, not via
        // proper recursion with the new inner layout, to be able to later nicely
        // print the field names of the enum field that is being accessed.
        let (variant, dest) = match dest.layout.variants {
            layout::Variants::NicheFilling { niche: ref tag, .. } |
            layout::Variants::Tagged { ref tag, .. } => {
                let size = tag.value.size(self);
                // we first read the tag value as scalar, to be able to validate it
                let tag_mplace = self.mplace_field(dest, 0)?;
                let tag_value = self.read_scalar(tag_mplace.into())?;
                path.push(PathElem::Tag);
                self.validate_scalar(
                    tag_value, size, tag, &path, tag_mplace.layout.ty
                )?;
                path.pop(); // remove the element again
                // then we read it again to get the index, to continue
                let variant = self.read_discriminant_as_variant_index(dest.into())?;
                let inner_dest = self.mplace_downcast(dest, variant)?;
                // Put the variant projection onto the path, as a field
                path.push(PathElem::Field(dest.layout.ty.ty_adt_def().unwrap().variants[variant].name));
                trace!("variant layout: {:#?}", dest.layout);
                (variant, inner_dest)
            },
            layout::Variants::Single { index } => {
                (index, dest)
            }
        };

        // Remember the length, in case we need to truncate
        let path_len = path.len();

        // Validate all fields
        match dest.layout.fields {
            // primitives are unions with zero fields
            // FIXME: Use some other indicator instead, like `layout.abi`.
            layout::FieldPlacement::Union(0) => {
                match dest.layout.abi {
                    // nothing to do, whatever the pointer points to, it is never going to be read
                    layout::Abi::Uninhabited =>
                        return validation_failure!("a value of an uninhabited type", path),
                    // check that the scalar is a valid pointer or that its bit range matches the
                    // expectation.
                    layout::Abi::Scalar(ref scalar_layout) => {
                        let size = scalar_layout.value.size(self);
                        let value = self.read_value(dest.into())?;
                        let scalar = value.to_scalar_or_undef();
                        self.validate_scalar(scalar, size, scalar_layout, &path, dest.layout.ty)?;
                        if scalar_layout.value == Primitive::Pointer {
                            // ignore integer pointers, we can't reason about the final hardware
                            if let Scalar::Ptr(ptr) = scalar.not_undef()? {
                                let alloc_kind = self.tcx.alloc_map.lock().get(ptr.alloc_id);
                                if let Some(AllocType::Static(did)) = alloc_kind {
                                    // statics from other crates are already checked.
                                    // extern statics should not be validated as they have no body.
                                    if !did.is_local() || self.tcx.is_foreign_item(did) {
                                        return Ok(());
                                    }
                                }
                                if value.layout.ty.builtin_deref(false).is_some() {
                                    trace!("Recursing below ptr {:#?}", value);
                                    let ptr_place = self.ref_to_mplace(value)?;
                                    // we have not encountered this pointer+layout combination before
                                    if seen.insert(ptr_place) {
                                        todo.push((ptr_place, path_clone_and_deref(path)));
                                    }
                                }
                            }
                        }
                    },
                    _ => bug!("bad abi for FieldPlacement::Union(0): {:#?}", dest.layout.abi),
                }
            }
            layout::FieldPlacement::Union(_) => {
                // We can't check unions, their bits are allowed to be anything.
                // The fields don't need to correspond to any bit pattern of the union's fields.
                // See https://github.com/rust-lang/rust/issues/32836#issuecomment-406875389
            },
            layout::FieldPlacement::Array { .. } => {
                for (i, field) in self.mplace_array_fields(dest)?.enumerate() {
                    let field = field?;
                    path.push(PathElem::ArrayElem(i));
                    self.validate_mplace(field, path, seen, todo)?;
                    path.truncate(path_len);
                }
            },
            layout::FieldPlacement::Arbitrary { ref offsets, .. } => {
                // Fat pointers need special treatment.
                match dest.layout.ty.builtin_deref(true).map(|tam| &tam.ty.sty) {
                    | Some(ty::TyStr)
                    | Some(ty::TySlice(_)) => {
                        // check the length (for nicer error messages); must be valid even
                        // for a raw pointer.
                        let len_mplace = self.mplace_field(dest, 1)?;
                        let len = self.read_scalar(len_mplace.into())?;
                        let len = match len.to_bits(len_mplace.layout.size) {
                            Err(_) => return validation_failure!("length is not a valid integer", path),
                            Ok(len) => len as u64,
                        };
                        // for safe ptrs, get the fat ptr, and recursively check it
                        if !dest.layout.ty.is_unsafe_ptr() {
                            let ptr = self.ref_to_mplace(self.read_value(dest.into())?)?;
                            assert_eq!(ptr.extra, PlaceExtra::Length(len));
                            let unpacked_ptr = self.unpack_unsized_mplace(ptr)?;
                            if seen.insert(unpacked_ptr) {
                                todo.push((unpacked_ptr, path_clone_and_deref(path)));
                            }
                        }
                    },
                    Some(ty::TyDynamic(..)) => {
                        // check the vtable (for nicer error messages); must be valid even for a
                        // raw ptr.
                        let vtable = self.read_scalar(self.mplace_field(dest, 1)?.into())?;
                        let vtable = match vtable.to_ptr() {
                            Err(_) => return validation_failure!("vtable address is not a pointer", path),
                            Ok(vtable) => vtable,
                        };
                        // for safe ptrs, get the fat ptr, and recursively check it
                        if !dest.layout.ty.is_unsafe_ptr() {
                            let ptr = self.ref_to_mplace(self.read_value(dest.into())?)?;
                            assert_eq!(ptr.extra, PlaceExtra::Vtable(vtable));
                            let unpacked_ptr = self.unpack_unsized_mplace(ptr)?;
                            if seen.insert(unpacked_ptr) {
                                todo.push((unpacked_ptr, path_clone_and_deref(path)));
                            }
                            // FIXME: More checks for the vtable... making sure it is exactly
                            // the one one would expect for this type.
                        }
                    },
                    Some(ty) =>
                        bug!("Unexpected fat pointer target type {:?}", ty),
                    None => {
                        // Not a pointer, perform regular aggregate handling below
                        for i in 0..offsets.len() {
                            let field = self.mplace_field(dest, i as u64)?;
                            path.push(self.aggregate_field_path_elem(dest.layout.ty, variant, i));
                            self.validate_mplace(field, path, seen, todo)?;
                            path.truncate(path_len);
                        }
                        // FIXME: For a TyStr, check that this is valid UTF-8.
                    },
                }
            }
        }
        Ok(())
    }

    fn aggregate_field_path_elem(&self, ty: Ty<'tcx>, variant: usize, field: usize) -> PathElem {
        match ty.sty {
            // generators and closures.
            ty::TyClosure(def_id, _) | ty::TyGenerator(def_id, _, _) => {
                let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap();
                let freevar = self.tcx.with_freevars(node_id, |fv| fv[field]);
                PathElem::ClosureVar(self.tcx.hir.name(freevar.var_id()))
            }

            // tuples
            ty::TyTuple(_) => PathElem::TupleElem(field),

            // enums
            ty::TyAdt(def, ..) if def.is_enum() => {
                let variant = &def.variants[variant];
                PathElem::Field(variant.fields[field].ident.name)
            }

            // other ADTs
            ty::TyAdt(def, _) => PathElem::Field(def.non_enum_variant().fields[field].ident.name),

            // nothing else has an aggregate layout
            _ => bug!("aggregate_field_path_elem: got non-aggregate type {:?}", ty),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 by SiegeLord
//
// All rights reserved. Distributed under ZLib. For full terms see the file LICENSE.

use libc::*;
use std::mem;
use std::c_str::CString;

use internal::bitmap::*;
use internal::bitmap_like::*;
use internal::color::*;
use internal::core::*;
use internal::events::*;
use rust_util::Flag;

use ffi::*;

pub use rust_util::c_bool;

flag_type!(
	DisplayFlags
	{
		WINDOWED                  = ALLEGRO_WINDOWED,
		FULLSCREEN                = ALLEGRO_FULLSCREEN,
		OPENGL                    = ALLEGRO_OPENGL,
		DIRECT3D                  = ALLEGRO_DIRECT3D_INTERNAL,
		RESIZABLE                 = ALLEGRO_RESIZABLE,
		FRAMELESS                 = ALLEGRO_FRAMELESS,
		GENERATE_EXPOSE_EVENTS    = ALLEGRO_GENERATE_EXPOSE_EVENTS,
		OPENGL_3_0                = ALLEGRO_OPENGL_3_0,
		OPENGL_FORWARD_COMPATIBLE = ALLEGRO_OPENGL_FORWARD_COMPATIBLE,
		FULLSCREEN_WINDOW         = ALLEGRO_FULLSCREEN_WINDOW,
		MINIMIZED                 = ALLEGRO_MINIMIZED
	}
)

#[repr(u32)]
pub enum DisplayOption
{
	RedSize = ALLEGRO_RED_SIZE,
	GreenSize = ALLEGRO_GREEN_SIZE,
	BlueSize = ALLEGRO_BLUE_SIZE,
	AlphaSize = ALLEGRO_ALPHA_SIZE,
	RedShift = ALLEGRO_RED_SHIFT,
	GreenShift = ALLEGRO_GREEN_SHIFT,
	BlueShift = ALLEGRO_BLUE_SHIFT,
	AlphaShift = ALLEGRO_ALPHA_SHIFT,
	AccRedSize = ALLEGRO_ACC_RED_SIZE,
	AccGreenSize = ALLEGRO_ACC_GREEN_SIZE,
	AccBlueSize = ALLEGRO_ACC_BLUE_SIZE,
	AccAlphaSize = ALLEGRO_ACC_ALPHA_SIZE,
	Stereo = ALLEGRO_STEREO,
	AuxBuffers = ALLEGRO_AUX_BUFFERS,
	ColorSize = ALLEGRO_COLOR_SIZE,
	DepthSize = ALLEGRO_DEPTH_SIZE,
	StencilSize = ALLEGRO_STENCIL_SIZE,
	SampleBuffers = ALLEGRO_SAMPLE_BUFFERS,
	Samples = ALLEGRO_SAMPLES,
	RenderMethod = ALLEGRO_RENDER_METHOD,
	FloatColor = ALLEGRO_FLOAT_COLOR,
	FloatDepth = ALLEGRO_FLOAT_DEPTH,
	SingleBuffer = ALLEGRO_SINGLE_BUFFER,
	SwapMethod = ALLEGRO_SWAP_METHOD,
	CompatibleDisplay = ALLEGRO_COMPATIBLE_DISPLAY,
	UpdateDisplayRegion = ALLEGRO_UPDATE_DISPLAY_REGION,
	Vsync = ALLEGRO_VSYNC,
	MaxBitmapSize = ALLEGRO_MAX_BITMAP_SIZE,
	SupportNpotBitmap = ALLEGRO_SUPPORT_NPOT_BITMAP,
	CanDrawIntoBitmap = ALLEGRO_CAN_DRAW_INTO_BITMAP,
	SupportSeparateAlpha = ALLEGRO_SUPPORT_SEPARATE_ALPHA,
}

#[repr(u32)]
pub enum DisplayOptionImportance
{
	DontCare = ALLEGRO_DONTCARE,
	Require = ALLEGRO_REQUIRE,
	Suggest = ALLEGRO_SUGGEST,
}

#[repr(u32)]
pub enum DisplayOrientation
{
	DisplayOrientation0Degrees = ALLEGRO_DISPLAY_ORIENTATION_0_DEGREES,
	DisplayOrientation90Degrees = ALLEGRO_DISPLAY_ORIENTATION_90_DEGREES,
	DisplayOrientation180Degrees = ALLEGRO_DISPLAY_ORIENTATION_180_DEGREES,
	DisplayOrientation270Degrees = ALLEGRO_DISPLAY_ORIENTATION_270_DEGREES,
	DisplayOrientationFaceUp = ALLEGRO_DISPLAY_ORIENTATION_FACE_UP,
	DisplayOrientationFaceDown = ALLEGRO_DISPLAY_ORIENTATION_FACE_DOWN,
}

pub struct Display
{
	allegro_display: *mut ALLEGRO_DISPLAY,
	backbuffer: Bitmap,
	event_source: EventSource,
}

impl Display
{
	fn new(w: i32, h: i32) -> Result<Display, String>
	{
		unsafe
		{
			if !al_get_current_display().is_null()
			{
				Err("Only one display is allowed per thread.".to_string())
			}
			else
			{
				let d = al_create_display(w as c_int, h as c_int);
				if d.is_null()
				{
					Err("Could not create the display".to_string())
				}
				else
				{
					Ok
					(
						Display
						{
							allegro_display: d,
							backbuffer: new_bitmap_ref(al_get_backbuffer(d)),
							event_source: new_event_source_ref(al_get_display_event_source(d)),
						}
					)
				}
			}
		}
	}

	pub fn get_width(&self) -> i32
	{
		unsafe
		{
			al_get_display_width(self.allegro_display) as i32
		}
	}

	pub fn get_height(&self) -> i32
	{
		unsafe
		{
			al_get_display_height(self.allegro_display) as i32
		}
	}

	pub fn get_format(&self) -> PixelFormat
	{
		unsafe
		{
			mem::transmute(al_get_display_format(self.allegro_display) as u32)
		}
	}

	pub fn get_refresh_rate(&self) -> i32
	{
		unsafe
		{
			al_get_display_refresh_rate(self.allegro_display) as i32
		}
	}

	pub fn get_flags(&self) -> DisplayFlags
	{
		unsafe
		{
			mem::transmute(al_get_display_flags(self.allegro_display))
		}
	}

	pub fn set_flag(&self, flag: DisplayFlags, onoff: bool) -> bool
	{
		unsafe
		{
			al_set_display_flag(self.allegro_display, flag.get(), onoff as u8) != 0
		}
	}

	pub fn get_backbuffer<'l>(&'l self) -> &'l Bitmap
	{
		&self.backbuffer
	}

	pub fn acknowledge_resize(&self) -> Result<(), ()>
	{
		unsafe
		{
			if al_acknowledge_resize(self.allegro_display) != 0
			{
				Ok(())
			}
			else
			{
				Err(())
			}
		}
	}

	pub fn resize(&self, w: i32, h: i32) -> Result<(), ()>
	{
		unsafe
		{
			if al_resize_display(self.allegro_display, w as c_int, h as c_int) != 0
			{
				Ok(())
			}
			else
			{
				Err(())
			}
		}
	}

	pub fn set_icon<T: BitmapLike>(&self, icon: &T)
	{
		unsafe
		{
			al_set_display_icon(self.allegro_display, icon.get_allegro_bitmap());
		}
	}

	pub fn set_icons<'l, U: Iterator<&'l BitmapLike>>(&self, icons: U)
	{
		let mut c_icons: Vec<_> = icons.map(|b| b.get_allegro_bitmap()).collect();
		unsafe
		{
			al_set_display_icons(self.allegro_display, c_icons.len() as c_int, c_icons.as_mut_ptr());
		}
	}

	pub fn set_window_position(&self, x: i32, y: i32)
	{
		unsafe
		{
			al_set_window_position(self.allegro_display, x as c_int, y as c_int);
		}
	}

	pub fn get_window_position(&self) -> (i32, i32)
	{
		unsafe
		{
			let mut x = 0 as c_int;
			let mut y = 0 as c_int;
			al_get_window_position(self.allegro_display, &mut x, &mut y);
			(x as i32, y as i32)
		}
	}

	pub fn set_window_title(&self, title: &CString)
	{
		unsafe
		{
			al_set_window_title(self.allegro_display, title.as_ptr());
		}
	}

	pub fn get_option(&self, option: DisplayOption) -> i32
	{
		unsafe
		{
			al_get_display_option(self.allegro_display, option as c_int) as i32
		}
	}

	pub fn convert_bitmap<T: BitmapLike>(&self, bmp: &T) -> Result<Bitmap, ()>
	{
		clone_bitmap(bmp.get_allegro_bitmap())
	}

	pub fn get_event_source<'l>(&'l self) -> &'l EventSource
	{
		&self.event_source
	}

	pub fn get_allegro_display(&self) -> *mut ALLEGRO_DISPLAY
	{
		self.allegro_display
	}

	pub fn flip(&self)
	{
		unsafe
		{
			al_flip_display();
		}
	}

	pub fn update_region(&self, x: i32, y: i32, width: i32, height: i32)
	{
		unsafe
		{
			al_update_display_region(x as c_int, y as c_int, width as c_int, height as c_int);
		}
	}

	pub fn is_compatible_bitmap<T: BitmapLike>(&self, bitmap: &T) -> bool
	{
		unsafe
		{
			al_is_compatible_bitmap(bitmap.get_allegro_bitmap()) != 0
		}
	}

	pub fn wait_for_vsync(&self) -> Result<(), ()>
	{
		unsafe
		{
			if al_wait_for_vsync() != 0
			{
				Ok(())
			}
			else
			{
				Err(())
			}
		}
	}

	pub fn hold_bitmap_drawing(&self, hold: bool)
	{
		unsafe
		{
			al_hold_bitmap_drawing(hold as c_bool);
		}
	}

	pub fn is_bitmap_drawing_held(&self) -> bool
	{
		unsafe
		{
			al_is_bitmap_drawing_held() != 0
		}
	}
}

// Not Send just because of the marker in the event source
#[unsafe_destructor]
impl Drop for Display
{
	fn drop(&mut self)
	{
		unsafe
		{
			/* If it's a video bitmap, it's about to be reset, so we fall back to the dummy target */
			if al_get_bitmap_flags(al_get_target_bitmap()) & (ALLEGRO_VIDEO_BITMAP as i32) != 0
			{
				al_set_target_bitmap(dummy_target);
			}
			al_destroy_display(self.allegro_display);
		}
	}
}

impl ::internal::core::Core
{
	pub fn set_new_display_flags(&self, flags: DisplayFlags)
	{
		unsafe
		{
			al_set_new_display_flags(flags.get() as c_int);
		}
	}

	pub fn get_new_display_flags(&self) -> DisplayFlags
	{
		unsafe
		{
			mem::transmute(al_get_new_display_flags())
		}
	}

	pub fn set_new_display_refresh_rate(&self, rate: i32)
	{
		unsafe
		{
			al_set_new_display_refresh_rate(rate as c_int);
		}
	}

	pub fn get_new_display_refresh_rate(&self) -> i32
	{
		unsafe
		{
			al_get_new_display_refresh_rate() as i32
		}
	}

	pub fn set_new_display_adapter(&self, adapter: i32)
	{
		unsafe
		{
			al_set_new_display_adapter(adapter as c_int);
		}
	}

	pub fn get_new_display_adapter(&self) -> i32
	{
		unsafe
		{
			al_get_new_display_adapter() as i32
		}
	}

	pub fn set_new_window_position(&self, x: i32, y: i32)
	{
		unsafe
		{
			al_set_new_window_position(x as c_int, y as c_int);
		}
	}

	pub fn get_new_window_position(&self) -> (i32, i32)
	{
		unsafe
		{
			use std::mem::uninitialized;

			let mut x: c_int = uninitialized();
			let mut y: c_int = uninitialized();
			al_get_new_window_position(&mut x, &mut y);
			(x as i32, y as i32)
		}
	}

	pub fn reset_new_display_options(&self)
	{
		unsafe
		{
			al_reset_new_display_options();
		}
	}

	pub fn set_new_display_option(&self, option: DisplayOption, value: i32, importance: DisplayOptionImportance)
	{
		unsafe
		{
			al_set_new_display_option(option as c_int, value as c_int, importance as c_int);
		}
	}

	pub fn get_new_display_option(&self, option: DisplayOption) -> (i32, DisplayOptionImportance)
	{
		unsafe
		{
			use std::mem::uninitialized;

			let mut imp: c_int = uninitialized();

			let val = al_get_new_display_option(option as c_int, &mut imp);
			(val as i32, mem::transmute(imp))
		}
	}

	pub fn create_display(&self, w: i32, h: i32) -> Result<Display, String>
	{
		Display::new(w, h)
	}
}
<commit_msg>Lifetime bound<commit_after>// Copyright (c) 2014 by SiegeLord
//
// All rights reserved. Distributed under ZLib. For full terms see the file LICENSE.

use libc::*;
use std::mem;
use std::c_str::CString;

use internal::bitmap::*;
use internal::bitmap_like::*;
use internal::color::*;
use internal::core::*;
use internal::events::*;
use rust_util::Flag;

use ffi::*;

pub use rust_util::c_bool;

flag_type!(
	DisplayFlags
	{
		WINDOWED                  = ALLEGRO_WINDOWED,
		FULLSCREEN                = ALLEGRO_FULLSCREEN,
		OPENGL                    = ALLEGRO_OPENGL,
		DIRECT3D                  = ALLEGRO_DIRECT3D_INTERNAL,
		RESIZABLE                 = ALLEGRO_RESIZABLE,
		FRAMELESS                 = ALLEGRO_FRAMELESS,
		GENERATE_EXPOSE_EVENTS    = ALLEGRO_GENERATE_EXPOSE_EVENTS,
		OPENGL_3_0                = ALLEGRO_OPENGL_3_0,
		OPENGL_FORWARD_COMPATIBLE = ALLEGRO_OPENGL_FORWARD_COMPATIBLE,
		FULLSCREEN_WINDOW         = ALLEGRO_FULLSCREEN_WINDOW,
		MINIMIZED                 = ALLEGRO_MINIMIZED
	}
)

#[repr(u32)]
pub enum DisplayOption
{
	RedSize = ALLEGRO_RED_SIZE,
	GreenSize = ALLEGRO_GREEN_SIZE,
	BlueSize = ALLEGRO_BLUE_SIZE,
	AlphaSize = ALLEGRO_ALPHA_SIZE,
	RedShift = ALLEGRO_RED_SHIFT,
	GreenShift = ALLEGRO_GREEN_SHIFT,
	BlueShift = ALLEGRO_BLUE_SHIFT,
	AlphaShift = ALLEGRO_ALPHA_SHIFT,
	AccRedSize = ALLEGRO_ACC_RED_SIZE,
	AccGreenSize = ALLEGRO_ACC_GREEN_SIZE,
	AccBlueSize = ALLEGRO_ACC_BLUE_SIZE,
	AccAlphaSize = ALLEGRO_ACC_ALPHA_SIZE,
	Stereo = ALLEGRO_STEREO,
	AuxBuffers = ALLEGRO_AUX_BUFFERS,
	ColorSize = ALLEGRO_COLOR_SIZE,
	DepthSize = ALLEGRO_DEPTH_SIZE,
	StencilSize = ALLEGRO_STENCIL_SIZE,
	SampleBuffers = ALLEGRO_SAMPLE_BUFFERS,
	Samples = ALLEGRO_SAMPLES,
	RenderMethod = ALLEGRO_RENDER_METHOD,
	FloatColor = ALLEGRO_FLOAT_COLOR,
	FloatDepth = ALLEGRO_FLOAT_DEPTH,
	SingleBuffer = ALLEGRO_SINGLE_BUFFER,
	SwapMethod = ALLEGRO_SWAP_METHOD,
	CompatibleDisplay = ALLEGRO_COMPATIBLE_DISPLAY,
	UpdateDisplayRegion = ALLEGRO_UPDATE_DISPLAY_REGION,
	Vsync = ALLEGRO_VSYNC,
	MaxBitmapSize = ALLEGRO_MAX_BITMAP_SIZE,
	SupportNpotBitmap = ALLEGRO_SUPPORT_NPOT_BITMAP,
	CanDrawIntoBitmap = ALLEGRO_CAN_DRAW_INTO_BITMAP,
	SupportSeparateAlpha = ALLEGRO_SUPPORT_SEPARATE_ALPHA,
}

#[repr(u32)]
pub enum DisplayOptionImportance
{
	DontCare = ALLEGRO_DONTCARE,
	Require = ALLEGRO_REQUIRE,
	Suggest = ALLEGRO_SUGGEST,
}

#[repr(u32)]
pub enum DisplayOrientation
{
	DisplayOrientation0Degrees = ALLEGRO_DISPLAY_ORIENTATION_0_DEGREES,
	DisplayOrientation90Degrees = ALLEGRO_DISPLAY_ORIENTATION_90_DEGREES,
	DisplayOrientation180Degrees = ALLEGRO_DISPLAY_ORIENTATION_180_DEGREES,
	DisplayOrientation270Degrees = ALLEGRO_DISPLAY_ORIENTATION_270_DEGREES,
	DisplayOrientationFaceUp = ALLEGRO_DISPLAY_ORIENTATION_FACE_UP,
	DisplayOrientationFaceDown = ALLEGRO_DISPLAY_ORIENTATION_FACE_DOWN,
}

pub struct Display
{
	allegro_display: *mut ALLEGRO_DISPLAY,
	backbuffer: Bitmap,
	event_source: EventSource,
}

impl Display
{
	fn new(w: i32, h: i32) -> Result<Display, String>
	{
		unsafe
		{
			if !al_get_current_display().is_null()
			{
				Err("Only one display is allowed per thread.".to_string())
			}
			else
			{
				let d = al_create_display(w as c_int, h as c_int);
				if d.is_null()
				{
					Err("Could not create the display".to_string())
				}
				else
				{
					Ok
					(
						Display
						{
							allegro_display: d,
							backbuffer: new_bitmap_ref(al_get_backbuffer(d)),
							event_source: new_event_source_ref(al_get_display_event_source(d)),
						}
					)
				}
			}
		}
	}

	pub fn get_width(&self) -> i32
	{
		unsafe
		{
			al_get_display_width(self.allegro_display) as i32
		}
	}

	pub fn get_height(&self) -> i32
	{
		unsafe
		{
			al_get_display_height(self.allegro_display) as i32
		}
	}

	pub fn get_format(&self) -> PixelFormat
	{
		unsafe
		{
			mem::transmute(al_get_display_format(self.allegro_display) as u32)
		}
	}

	pub fn get_refresh_rate(&self) -> i32
	{
		unsafe
		{
			al_get_display_refresh_rate(self.allegro_display) as i32
		}
	}

	pub fn get_flags(&self) -> DisplayFlags
	{
		unsafe
		{
			mem::transmute(al_get_display_flags(self.allegro_display))
		}
	}

	pub fn set_flag(&self, flag: DisplayFlags, onoff: bool) -> bool
	{
		unsafe
		{
			al_set_display_flag(self.allegro_display, flag.get(), onoff as u8) != 0
		}
	}

	pub fn get_backbuffer<'l>(&'l self) -> &'l Bitmap
	{
		&self.backbuffer
	}

	pub fn acknowledge_resize(&self) -> Result<(), ()>
	{
		unsafe
		{
			if al_acknowledge_resize(self.allegro_display) != 0
			{
				Ok(())
			}
			else
			{
				Err(())
			}
		}
	}

	pub fn resize(&self, w: i32, h: i32) -> Result<(), ()>
	{
		unsafe
		{
			if al_resize_display(self.allegro_display, w as c_int, h as c_int) != 0
			{
				Ok(())
			}
			else
			{
				Err(())
			}
		}
	}

	pub fn set_icon<T: BitmapLike>(&self, icon: &T)
	{
		unsafe
		{
			al_set_display_icon(self.allegro_display, icon.get_allegro_bitmap());
		}
	}

	pub fn set_icons<'l, U: Iterator<&'l BitmapLike + 'l>>(&self, icons: U)
	{
		let mut c_icons: Vec<_> = icons.map(|b| b.get_allegro_bitmap()).collect();
		unsafe
		{
			al_set_display_icons(self.allegro_display, c_icons.len() as c_int, c_icons.as_mut_ptr());
		}
	}

	pub fn set_window_position(&self, x: i32, y: i32)
	{
		unsafe
		{
			al_set_window_position(self.allegro_display, x as c_int, y as c_int);
		}
	}

	pub fn get_window_position(&self) -> (i32, i32)
	{
		unsafe
		{
			let mut x = 0 as c_int;
			let mut y = 0 as c_int;
			al_get_window_position(self.allegro_display, &mut x, &mut y);
			(x as i32, y as i32)
		}
	}

	pub fn set_window_title(&self, title: &CString)
	{
		unsafe
		{
			al_set_window_title(self.allegro_display, title.as_ptr());
		}
	}

	pub fn get_option(&self, option: DisplayOption) -> i32
	{
		unsafe
		{
			al_get_display_option(self.allegro_display, option as c_int) as i32
		}
	}

	pub fn convert_bitmap<T: BitmapLike>(&self, bmp: &T) -> Result<Bitmap, ()>
	{
		clone_bitmap(bmp.get_allegro_bitmap())
	}

	pub fn get_event_source<'l>(&'l self) -> &'l EventSource
	{
		&self.event_source
	}

	pub fn get_allegro_display(&self) -> *mut ALLEGRO_DISPLAY
	{
		self.allegro_display
	}

	pub fn flip(&self)
	{
		unsafe
		{
			al_flip_display();
		}
	}

	pub fn update_region(&self, x: i32, y: i32, width: i32, height: i32)
	{
		unsafe
		{
			al_update_display_region(x as c_int, y as c_int, width as c_int, height as c_int);
		}
	}

	pub fn is_compatible_bitmap<T: BitmapLike>(&self, bitmap: &T) -> bool
	{
		unsafe
		{
			al_is_compatible_bitmap(bitmap.get_allegro_bitmap()) != 0
		}
	}

	pub fn wait_for_vsync(&self) -> Result<(), ()>
	{
		unsafe
		{
			if al_wait_for_vsync() != 0
			{
				Ok(())
			}
			else
			{
				Err(())
			}
		}
	}

	pub fn hold_bitmap_drawing(&self, hold: bool)
	{
		unsafe
		{
			al_hold_bitmap_drawing(hold as c_bool);
		}
	}

	pub fn is_bitmap_drawing_held(&self) -> bool
	{
		unsafe
		{
			al_is_bitmap_drawing_held() != 0
		}
	}
}

// Not Send just because of the marker in the event source
#[unsafe_destructor]
impl Drop for Display
{
	fn drop(&mut self)
	{
		unsafe
		{
			/* If it's a video bitmap, it's about to be reset, so we fall back to the dummy target */
			if al_get_bitmap_flags(al_get_target_bitmap()) & (ALLEGRO_VIDEO_BITMAP as i32) != 0
			{
				al_set_target_bitmap(dummy_target);
			}
			al_destroy_display(self.allegro_display);
		}
	}
}

impl ::internal::core::Core
{
	pub fn set_new_display_flags(&self, flags: DisplayFlags)
	{
		unsafe
		{
			al_set_new_display_flags(flags.get() as c_int);
		}
	}

	pub fn get_new_display_flags(&self) -> DisplayFlags
	{
		unsafe
		{
			mem::transmute(al_get_new_display_flags())
		}
	}

	pub fn set_new_display_refresh_rate(&self, rate: i32)
	{
		unsafe
		{
			al_set_new_display_refresh_rate(rate as c_int);
		}
	}

	pub fn get_new_display_refresh_rate(&self) -> i32
	{
		unsafe
		{
			al_get_new_display_refresh_rate() as i32
		}
	}

	pub fn set_new_display_adapter(&self, adapter: i32)
	{
		unsafe
		{
			al_set_new_display_adapter(adapter as c_int);
		}
	}

	pub fn get_new_display_adapter(&self) -> i32
	{
		unsafe
		{
			al_get_new_display_adapter() as i32
		}
	}

	pub fn set_new_window_position(&self, x: i32, y: i32)
	{
		unsafe
		{
			al_set_new_window_position(x as c_int, y as c_int);
		}
	}

	pub fn get_new_window_position(&self) -> (i32, i32)
	{
		unsafe
		{
			use std::mem::uninitialized;

			let mut x: c_int = uninitialized();
			let mut y: c_int = uninitialized();
			al_get_new_window_position(&mut x, &mut y);
			(x as i32, y as i32)
		}
	}

	pub fn reset_new_display_options(&self)
	{
		unsafe
		{
			al_reset_new_display_options();
		}
	}

	pub fn set_new_display_option(&self, option: DisplayOption, value: i32, importance: DisplayOptionImportance)
	{
		unsafe
		{
			al_set_new_display_option(option as c_int, value as c_int, importance as c_int);
		}
	}

	pub fn get_new_display_option(&self, option: DisplayOption) -> (i32, DisplayOptionImportance)
	{
		unsafe
		{
			use std::mem::uninitialized;

			let mut imp: c_int = uninitialized();

			let val = al_get_new_display_option(option as c_int, &mut imp);
			(val as i32, mem::transmute(imp))
		}
	}

	pub fn create_display(&self, w: i32, h: i32) -> Result<Display, String>
	{
		Display::new(w, h)
	}
}
<|endoftext|>


<commit_before>// Third Party
#[cfg(feature = "suggestions")]
use strsim;

// Internal
use crate::build::App;
use crate::output::fmt::Format;

/// Produces a string from a given list of possible values which is similar to
/// the passed in value `v` with a certain confidence.
/// Thus in a list of possible values like ["foo", "bar"], the value "fop" will yield
/// `Some("foo")`, whereas "blark" would yield `None`.
#[cfg(feature = "suggestions")]
#[cfg_attr(feature = "lints", allow(needless_lifetimes))]
pub fn did_you_mean<T, I>(v: &str, possible_values: I) -> Option<String>
where
    T: AsRef<str>,
    I: IntoIterator<Item = T>,
{
    let mut candidate: Option<(f64, String)> = None;
    for pv in possible_values {
        let confidence = strsim::jaro_winkler(v, pv.as_ref());
        if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence))
        {
            candidate = Some((confidence, pv.as_ref().to_owned()));
        }
    }
    match candidate {
        None => None,
        Some((_, candidate)) => Some(candidate.to_owned()),
    }
}

#[cfg(not(feature = "suggestions"))]
pub fn did_you_mean<T, I>(_: &str, _: I) -> Option<String>
where
    T: AsRef<str>,
    I: IntoIterator<Item = T>,
{
    None
}

/// Returns a suffix that can be empty, or is the standard 'did you mean' phrase
#[cfg_attr(feature = "lints", allow(needless_lifetimes))]
pub fn did_you_mean_flag_suffix<I, T>(
    arg: &str,
    longs: I,
    subcommands: &mut [App],
) -> (String, Option<String>)
where
    T: AsRef<str>,
    I: IntoIterator<Item = T>,
{
    match did_you_mean(arg, longs) {
        Some(ref candidate) => {
            let suffix = format!(
                "\n\tDid you mean {}{}?",
                Format::Good("--"),
                Format::Good(candidate)
            );
            return (suffix, Some(candidate.to_owned()));
        }
        None => {
            for subcommand in subcommands {
                subcommand._build();
                if let Some(ref candidate) = did_you_mean(
                    arg,
                    longs!(subcommand).map(|x| x.to_string_lossy().into_owned()),
                ) {
                    let suffix = format!(
                        "\n\tDid you mean to put '{}{}' after the subcommand '{}'?",
                        Format::Good("--"),
                        Format::Good(candidate),
                        Format::Good(subcommand.get_name())
                    );
                    return (suffix, Some(candidate.clone()));
                }
            }
        }
    }
    (String::new(), None)
}

/// Returns a suffix that can be empty, or is the standard 'did you mean' phrase
pub fn did_you_mean_value_suffix<T, I>(arg: &str, values: I) -> (String, Option<String>)
where
    T: AsRef<str>,
    I: IntoIterator<Item = T>,
{
    match did_you_mean(arg, values) {
        Some(ref candidate) => {
            let suffix = format!("\n\tDid you mean '{}'?", Format::Good(candidate));
            (suffix, Some(candidate.to_owned()))
        }
        None => (String::new(), None),
    }
}

#[cfg(all(test, features = "suggestions"))]
mod test {
    use super::*;

    #[test]
    fn possible_values_match() {
        let p_vals = ["test", "possible", "values"];
        assert_eq!(did_you_mean("tst", p_vals.iter()), Some("test"));
    }

    #[test]
    fn possible_values_nomatch() {
        let p_vals = ["test", "possible", "values"];
        assert!(did_you_mean("hahaahahah", p_vals.iter()).is_none());
    }

    #[test]
    fn suffix_long() {
        let p_vals = ["test", "possible", "values"];
        let suffix = "\n\tDid you mean \'--test\'?";
        assert_eq!(
            did_you_mean_flag_suffix("tst", p_vals.iter(), []),
            (suffix, Some("test"))
        );
    }

    #[test]
    fn suffix_enum() {
        let p_vals = ["test", "possible", "values"];
        let suffix = "\n\tDid you mean \'test\'?";
        assert_eq!(
            did_you_mean_value_suffix("tst", p_vals.iter()),
            (suffix, Some("test"))
        );
    }
}
<commit_msg>Use map instead of match on Option<commit_after>// Third Party
#[cfg(feature = "suggestions")]
use strsim;

// Internal
use crate::build::App;
use crate::output::fmt::Format;

/// Produces a string from a given list of possible values which is similar to
/// the passed in value `v` with a certain confidence.
/// Thus in a list of possible values like ["foo", "bar"], the value "fop" will yield
/// `Some("foo")`, whereas "blark" would yield `None`.
#[cfg(feature = "suggestions")]
#[cfg_attr(feature = "lints", allow(needless_lifetimes))]
pub fn did_you_mean<T, I>(v: &str, possible_values: I) -> Option<String>
where
    T: AsRef<str>,
    I: IntoIterator<Item = T>,
{
    let mut candidate: Option<(f64, String)> = None;
    for pv in possible_values {
        let confidence = strsim::jaro_winkler(v, pv.as_ref());
        if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence))
        {
            candidate = Some((confidence, pv.as_ref().to_owned()));
        }
    }

    candidate.map(|(_, candidate)| candidate)
}

#[cfg(not(feature = "suggestions"))]
pub fn did_you_mean<T, I>(_: &str, _: I) -> Option<String>
where
    T: AsRef<str>,
    I: IntoIterator<Item = T>,
{
    None
}

/// Returns a suffix that can be empty, or is the standard 'did you mean' phrase
#[cfg_attr(feature = "lints", allow(needless_lifetimes))]
pub fn did_you_mean_flag_suffix<I, T>(
    arg: &str,
    longs: I,
    subcommands: &mut [App],
) -> (String, Option<String>)
where
    T: AsRef<str>,
    I: IntoIterator<Item = T>,
{
    match did_you_mean(arg, longs) {
        Some(ref candidate) => {
            let suffix = format!(
                "\n\tDid you mean {}{}?",
                Format::Good("--"),
                Format::Good(candidate)
            );
            return (suffix, Some(candidate.to_owned()));
        }
        None => {
            for subcommand in subcommands {
                subcommand._build();
                if let Some(ref candidate) = did_you_mean(
                    arg,
                    longs!(subcommand).map(|x| x.to_string_lossy().into_owned()),
                ) {
                    let suffix = format!(
                        "\n\tDid you mean to put '{}{}' after the subcommand '{}'?",
                        Format::Good("--"),
                        Format::Good(candidate),
                        Format::Good(subcommand.get_name())
                    );
                    return (suffix, Some(candidate.clone()));
                }
            }
        }
    }
    (String::new(), None)
}

/// Returns a suffix that can be empty, or is the standard 'did you mean' phrase
pub fn did_you_mean_value_suffix<T, I>(arg: &str, values: I) -> (String, Option<String>)
where
    T: AsRef<str>,
    I: IntoIterator<Item = T>,
{
    match did_you_mean(arg, values) {
        Some(ref candidate) => {
            let suffix = format!("\n\tDid you mean '{}'?", Format::Good(candidate));
            (suffix, Some(candidate.to_owned()))
        }
        None => (String::new(), None),
    }
}

#[cfg(all(test, features = "suggestions"))]
mod test {
    use super::*;

    #[test]
    fn possible_values_match() {
        let p_vals = ["test", "possible", "values"];
        assert_eq!(did_you_mean("tst", p_vals.iter()), Some("test"));
    }

    #[test]
    fn possible_values_nomatch() {
        let p_vals = ["test", "possible", "values"];
        assert!(did_you_mean("hahaahahah", p_vals.iter()).is_none());
    }

    #[test]
    fn suffix_long() {
        let p_vals = ["test", "possible", "values"];
        let suffix = "\n\tDid you mean \'--test\'?";
        assert_eq!(
            did_you_mean_flag_suffix("tst", p_vals.iter(), []),
            (suffix, Some("test"))
        );
    }

    #[test]
    fn suffix_enum() {
        let p_vals = ["test", "possible", "values"];
        let suffix = "\n\tDid you mean \'test\'?";
        assert_eq!(
            did_you_mean_value_suffix("tst", p_vals.iter()),
            (suffix, Some("test"))
        );
    }
}
<|endoftext|>


<commit_before>//! Translation skeletton that traverses the whole WebAssembly module and call helper functions
//! to deal with each part of it.
use wasmparser::{ParserState, SectionCode, ParserInput, Parser, WasmDecoder, BinaryReaderError};
use sections_translator::{SectionParsingError, parse_function_signatures, parse_import_section,
                          parse_function_section, parse_export_section, parse_memory_section,
                          parse_global_section, parse_table_section, parse_elements_section,
                          parse_data_section};
use translation_utils::{type_to_type, Import, SignatureIndex, FunctionIndex};
use cretonne::ir::{Function, Type};
use code_translator::translate_function_body;
use cton_frontend::ILBuilder;
use std::collections::HashMap;
use runtime::WasmRuntime;

/// Output of the [`translate_module`](fn.translate_module.html) function.
pub struct TranslationResult {
    /// The translated functions.
    pub functions: Vec<Function>,
    /// When present, the index of the function defined as `start` of the module.
    ///
    /// Note that this is a WebAssembly function index and not an index into the `functions` vector
    /// above. The imported functions are numbered before the local functions.
    pub start_index: Option<FunctionIndex>,
}

/// Translate a sequence of bytes forming a valid Wasm binary into a list of valid Cretonne IL
/// [`Function`](../cretonne/ir/function/struct.Function.html).
/// Returns the functions and also the mappings for imported functions and signature between the
/// indexes in the wasm module and the indexes inside each functions.
pub fn translate_module(
    data: &[u8],
    runtime: &mut WasmRuntime,
) -> Result<TranslationResult, String> {
    let mut parser = Parser::new(data);
    match *parser.read() {
        ParserState::BeginWasm { .. } => {}
        ParserState::Error(BinaryReaderError { message, offset }) => {
            return Err(format!("at offset {}: {}", offset, message));
        }
        ref s => panic!("modules should begin properly: {:?}", s),
    }
    let mut signatures = None;
    let mut functions: Option<Vec<SignatureIndex>> = None;
    let mut globals = Vec::new();
    let mut exports: Option<HashMap<FunctionIndex, String>> = None;
    let mut next_input = ParserInput::Default;
    let mut function_index: FunctionIndex = 0;
    let mut start_index: Option<FunctionIndex> = None;
    loop {
        match *parser.read_with_input(next_input) {
            ParserState::BeginSection { code: SectionCode::Type, .. } => {
                match parse_function_signatures(&mut parser, runtime) {
                    Ok(sigs) => signatures = Some(sigs),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the type section: {}", s))
                    }
                };
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Import, .. } => {
                match parse_import_section(&mut parser, runtime) {
                    Ok(imps) => {
                        for import in imps {
                            match import {
                                Import::Function { sig_index } => {
                                    functions = match functions {
                                        None => Some(vec![sig_index as SignatureIndex]),
                                        Some(mut funcs) => {
                                            funcs.push(sig_index as SignatureIndex);
                                            Some(funcs)
                                        }
                                    };
                                    function_index += 1;
                                }
                                Import::Memory(mem) => {
                                    runtime.declare_memory(mem);
                                }
                                Import::Global(glob) => {
                                    runtime.declare_global(glob);
                                    globals.push(glob);
                                }
                                Import::Table(tab) => {
                                    runtime.declare_table(tab);
                                }
                            }
                        }
                    }
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the import section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Function, .. } => {
                match parse_function_section(&mut parser, runtime) {
                    Ok(funcs) => {
                        match functions {
                            None => functions = Some(funcs),
                            Some(ref mut imps) => imps.extend(funcs),
                        }
                    }
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the function section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Table, .. } => {
                match parse_table_section(&mut parser, runtime) {
                    Ok(()) => (),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the table section: {}", s))
                    }
                }
            }
            ParserState::BeginSection { code: SectionCode::Memory, .. } => {
                match parse_memory_section(&mut parser) {
                    Ok(mems) => {
                        for mem in mems {
                            runtime.declare_memory(mem);
                        }
                    }
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the memory section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Global, .. } => {
                match parse_global_section(&mut parser, runtime) {
                    Ok(mut globs) => globals.append(&mut globs),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the global section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Export, .. } => {
                match parse_export_section(&mut parser) {
                    Ok(exps) => exports = Some(exps),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the export section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Start, .. } => {
                match *parser.read() {
                    ParserState::StartSectionEntry(index) => {
                        start_index = Some(index as FunctionIndex)
                    }
                    _ => return Err(String::from("wrong content in the start section")),
                }
                match *parser.read() {
                    ParserState::EndSection => {}
                    _ => return Err(String::from("wrong content in the start section")),
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Element, .. } => {
                match parse_elements_section(&mut parser, runtime, &globals) {
                    Ok(()) => (),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the element section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Code, .. } => {
                // The code section begins
                break;
            }
            ParserState::EndSection => {
                next_input = ParserInput::Default;
            }
            ParserState::EndWasm => {
                return Ok(TranslationResult {
                    functions: Vec::new(),
                    start_index: None,
                })
            }
            ParserState::BeginSection { code: SectionCode::Data, .. } => {
                match parse_data_section(&mut parser, runtime, &globals) {
                    Ok(()) => (),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the data section: {}", s))
                    }
                }
            }
            _ => return Err(String::from("wrong content in the preamble")),
        };
    }
    // At this point we've entered the code section
    // First we check that we have all that is necessary to translate a function.
    let signatures = signatures.unwrap_or_default();
    let functions = match functions {
        None => return Err(String::from("missing a function section")),
        Some(functions) => functions,
    };
    let mut il_functions: Vec<Function> = Vec::new();
    let mut il_builder = ILBuilder::new();
    runtime.begin_translation();
    loop {
        let locals: Vec<(usize, Type)> = match *parser.read() {
            ParserState::BeginFunctionBody { ref locals, .. } => {
                locals
                    .iter()
                    .map(|&(index, ref ty)| {
                        (
                            index as usize,
                            match type_to_type(ty) {
                                Ok(ty) => ty,
                                Err(()) => panic!("unsupported type for local variable"),
                            },
                        )
                    })
                    .collect()
            }
            ParserState::EndSection => break,
            _ => return Err(String::from("wrong content in code section")),
        };
        let signature = signatures[functions[function_index]].clone();
        match translate_function_body(
            &mut parser,
            function_index,
            &signature,
            &locals,
            &exports,
            &mut il_builder,
            runtime,
        ) {
            Ok(il_func) => il_functions.push(il_func),
            Err(s) => return Err(s),
        }
        function_index += 1;
    }
    loop {
        match *parser.read() {
            ParserState::BeginSection { code: SectionCode::Data, .. } => {
                match parse_data_section(&mut parser, runtime, &globals) {
                    Ok(()) => (),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the data section: {}", s))
                    }
                }
            }
            ParserState::EndWasm => {
                return Ok(TranslationResult {
                    functions: il_functions,
                    start_index,
                })
            }
            _ => (),
        }
    }
}
<commit_msg>Replace a match with a `?`.<commit_after>//! Translation skeletton that traverses the whole WebAssembly module and call helper functions
//! to deal with each part of it.
use wasmparser::{ParserState, SectionCode, ParserInput, Parser, WasmDecoder, BinaryReaderError};
use sections_translator::{SectionParsingError, parse_function_signatures, parse_import_section,
                          parse_function_section, parse_export_section, parse_memory_section,
                          parse_global_section, parse_table_section, parse_elements_section,
                          parse_data_section};
use translation_utils::{type_to_type, Import, SignatureIndex, FunctionIndex};
use cretonne::ir::{Function, Type};
use code_translator::translate_function_body;
use cton_frontend::ILBuilder;
use std::collections::HashMap;
use runtime::WasmRuntime;

/// Output of the [`translate_module`](fn.translate_module.html) function.
pub struct TranslationResult {
    /// The translated functions.
    pub functions: Vec<Function>,
    /// When present, the index of the function defined as `start` of the module.
    ///
    /// Note that this is a WebAssembly function index and not an index into the `functions` vector
    /// above. The imported functions are numbered before the local functions.
    pub start_index: Option<FunctionIndex>,
}

/// Translate a sequence of bytes forming a valid Wasm binary into a list of valid Cretonne IL
/// [`Function`](../cretonne/ir/function/struct.Function.html).
/// Returns the functions and also the mappings for imported functions and signature between the
/// indexes in the wasm module and the indexes inside each functions.
pub fn translate_module(
    data: &[u8],
    runtime: &mut WasmRuntime,
) -> Result<TranslationResult, String> {
    let mut parser = Parser::new(data);
    match *parser.read() {
        ParserState::BeginWasm { .. } => {}
        ParserState::Error(BinaryReaderError { message, offset }) => {
            return Err(format!("at offset {}: {}", offset, message));
        }
        ref s => panic!("modules should begin properly: {:?}", s),
    }
    let mut signatures = None;
    let mut functions: Option<Vec<SignatureIndex>> = None;
    let mut globals = Vec::new();
    let mut exports: Option<HashMap<FunctionIndex, String>> = None;
    let mut next_input = ParserInput::Default;
    let mut function_index: FunctionIndex = 0;
    let mut start_index: Option<FunctionIndex> = None;
    loop {
        match *parser.read_with_input(next_input) {
            ParserState::BeginSection { code: SectionCode::Type, .. } => {
                match parse_function_signatures(&mut parser, runtime) {
                    Ok(sigs) => signatures = Some(sigs),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the type section: {}", s))
                    }
                };
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Import, .. } => {
                match parse_import_section(&mut parser, runtime) {
                    Ok(imps) => {
                        for import in imps {
                            match import {
                                Import::Function { sig_index } => {
                                    functions = match functions {
                                        None => Some(vec![sig_index as SignatureIndex]),
                                        Some(mut funcs) => {
                                            funcs.push(sig_index as SignatureIndex);
                                            Some(funcs)
                                        }
                                    };
                                    function_index += 1;
                                }
                                Import::Memory(mem) => {
                                    runtime.declare_memory(mem);
                                }
                                Import::Global(glob) => {
                                    runtime.declare_global(glob);
                                    globals.push(glob);
                                }
                                Import::Table(tab) => {
                                    runtime.declare_table(tab);
                                }
                            }
                        }
                    }
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the import section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Function, .. } => {
                match parse_function_section(&mut parser, runtime) {
                    Ok(funcs) => {
                        match functions {
                            None => functions = Some(funcs),
                            Some(ref mut imps) => imps.extend(funcs),
                        }
                    }
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the function section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Table, .. } => {
                match parse_table_section(&mut parser, runtime) {
                    Ok(()) => (),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the table section: {}", s))
                    }
                }
            }
            ParserState::BeginSection { code: SectionCode::Memory, .. } => {
                match parse_memory_section(&mut parser) {
                    Ok(mems) => {
                        for mem in mems {
                            runtime.declare_memory(mem);
                        }
                    }
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the memory section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Global, .. } => {
                match parse_global_section(&mut parser, runtime) {
                    Ok(mut globs) => globals.append(&mut globs),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the global section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Export, .. } => {
                match parse_export_section(&mut parser) {
                    Ok(exps) => exports = Some(exps),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the export section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Start, .. } => {
                match *parser.read() {
                    ParserState::StartSectionEntry(index) => {
                        start_index = Some(index as FunctionIndex)
                    }
                    _ => return Err(String::from("wrong content in the start section")),
                }
                match *parser.read() {
                    ParserState::EndSection => {}
                    _ => return Err(String::from("wrong content in the start section")),
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Element, .. } => {
                match parse_elements_section(&mut parser, runtime, &globals) {
                    Ok(()) => (),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the element section: {}", s))
                    }
                }
                next_input = ParserInput::Default;
            }
            ParserState::BeginSection { code: SectionCode::Code, .. } => {
                // The code section begins
                break;
            }
            ParserState::EndSection => {
                next_input = ParserInput::Default;
            }
            ParserState::EndWasm => {
                return Ok(TranslationResult {
                    functions: Vec::new(),
                    start_index: None,
                })
            }
            ParserState::BeginSection { code: SectionCode::Data, .. } => {
                match parse_data_section(&mut parser, runtime, &globals) {
                    Ok(()) => (),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the data section: {}", s))
                    }
                }
            }
            _ => return Err(String::from("wrong content in the preamble")),
        };
    }
    // At this point we've entered the code section
    // First we check that we have all that is necessary to translate a function.
    let signatures = signatures.unwrap_or_default();
    let functions = match functions {
        None => return Err(String::from("missing a function section")),
        Some(functions) => functions,
    };
    let mut il_functions: Vec<Function> = Vec::new();
    let mut il_builder = ILBuilder::new();
    runtime.begin_translation();
    loop {
        let locals: Vec<(usize, Type)> = match *parser.read() {
            ParserState::BeginFunctionBody { ref locals, .. } => {
                locals
                    .iter()
                    .map(|&(index, ref ty)| {
                        (
                            index as usize,
                            match type_to_type(ty) {
                                Ok(ty) => ty,
                                Err(()) => panic!("unsupported type for local variable"),
                            },
                        )
                    })
                    .collect()
            }
            ParserState::EndSection => break,
            _ => return Err(String::from("wrong content in code section")),
        };
        let signature = signatures[functions[function_index]].clone();
        let il_func = translate_function_body(
            &mut parser,
            function_index,
            &signature,
            &locals,
            &exports,
            &mut il_builder,
            runtime,
        )?;
        il_functions.push(il_func);
        function_index += 1;
    }
    loop {
        match *parser.read() {
            ParserState::BeginSection { code: SectionCode::Data, .. } => {
                match parse_data_section(&mut parser, runtime, &globals) {
                    Ok(()) => (),
                    Err(SectionParsingError::WrongSectionContent(s)) => {
                        return Err(format!("wrong content in the data section: {}", s))
                    }
                }
            }
            ParserState::EndWasm => {
                return Ok(TranslationResult {
                    functions: il_functions,
                    start_index,
                })
            }
            _ => (),
        }
    }
}
<|endoftext|>


<commit_before>/*!
 * Hello World server in Rust
 * Binds REP socket to tcp://*:5555
 * Expects "Hello" from client, replies with "World"
 */

extern mod zmq;

use std::libc;

fn main() {
#[fixed_stack_segment];

    let context = zmq::Context::new();
    let responder = context.socket(zmq::REP).unwrap();

    assert!(responder.bind("tcp://*:5555").is_ok());

    let mut msg = zmq::Message::new();
    loop {
        responder.recv(&mut msg, 0);
        do msg.with_str |s| {
            printfln!("Received %s", s);
        }
        responder.send_str("World", 0);
        unsafe { libc::sleep(1); }
    }
}
<commit_msg>Use std::rt::io::Timer instead of an unsafe sleep()<commit_after>/*!
 * Hello World server in Rust
 * Binds REP socket to tcp://*:5555
 * Expects "Hello" from client, replies with "World"
 */

extern mod zmq;

use std::rt;

fn main() {
#[fixed_stack_segment];

    let context = zmq::Context::new();
    let responder = context.socket(zmq::REP).unwrap();

    assert!(responder.bind("tcp://*:5555").is_ok());

    let mut msg = zmq::Message::new();
    loop {
        responder.recv(&mut msg, 0);
        do msg.with_str |s| {
            printfln!("Received %s", s);
        }
        responder.send_str("World", 0);
        let timer = ~rt::io::Timer::new();
        do timer.map_move |mut t| { t.sleep(1) };
    }
}
<|endoftext|>


<commit_before>use cocoa::base::id;

pub trait MTLRenderCommandEncoder {

}

impl MTLRenderCommandEncoder for id {}

#[repr(usize)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum MTLPrimitiveType {
    MTLPrimitiveTypePoint = 0,
    MTLPrimitiveTypeLine = 1,
    MTLPrimitiveTypeLineStrip = 2,
    MTLPrimitiveTypeTriangle = 3,
    MTLPrimitiveTypeTriangleStrip = 4
}

#[repr(usize)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum MTLIndexType {
    MTLIndexTypeUInt16 = 0,
    MTLIndexTypeUInt32 = 1
}

#[repr(usize)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum MTLVisibilityResultMode {
    MTLVisibilityResultModeDisabled = 0,
    MTLVisibilityResultModeBoolean = 1,
    MTLVisibilityResultModeCounting = 2
}

#[repr(usize)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum MTLCullMode {
    MTLCullModeNone = 0,
    MTLCullModeFront = 1,
    MTLCullModeBack = 2
}

#[repr(usize)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum MTLDepthClipMode {
    MTLDepthClipModeClip = 0,
    MTLDepthClipModeClamp = 1
}

#[repr(usize)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum MTLWinding {
    MTLWindingClockwise = 0,
    MTLWindingCounterClockwise = 1
}

#[repr(usize)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum MTLTriangleFillMode {
    MTLTriangleFillModeFill = 0,
    MTLTriangleFillModeLines = 1
}
<commit_msg>Add stubs for MTLRenderCommandEncoder<commit_after>use cocoa::base::id;
use cocoa::foundation::{NSInteger, NSRange, NSUInteger};
use libc::{uint32_t, c_void};
use types::{MTLScissorRect, MTLViewport};

pub trait MTLRenderCommandEncoder {
    unsafe fn setBlendColorRed_green_blue_alpha(self, red: f32, green: f32, blue: f32, alpha: f32);
    unsafe fn setCullMode(self, cullMode: MTLCullMode);
    unsafe fn setDepthBias_slopeScale_clamp(self, depthBias: f32, slopeScale: f32, clamp: f32);
    unsafe fn setDepthClipMode(self, depthClipMode: MTLDepthClipMode);
    unsafe fn setDepthStencilState(self, depthStencilState: id);
    unsafe fn setFrontFacingWinding(self, frontFacingWinding: MTLWinding);
    unsafe fn setRenderPipelineState(self, renderPipelineState: id);
    unsafe fn setScissorRect(self, scissorRect: MTLScissorRect);
    unsafe fn setStencilFrontReferenceValue_backReferenceValue(self, frontReferenceValue: uint32_t,
                                                               backReferenceValue: uint32_t);
    unsafe fn setStencilReferenceValue(self, referenceValue: uint32_t);
    unsafe fn setTriangleFillMode(self, fillMode: MTLTriangleFillMode);
    unsafe fn setViewport(self, viewport: MTLViewport);
    unsafe fn setVisibilityResultMode_offset(self, visibilityResultMode: MTLVisibilityResultMode,
                                             offset: NSUInteger);

    unsafe fn setVertexBuffer_offset_atIndex(self, buffer: id, offset: NSUInteger, index: NSUInteger);
    unsafe fn setVertexBuffers_offsets_withRange(self, buffers: *const id, offsets: *const NSUInteger, range: NSRange);
    unsafe fn setVertexBufferOffset_atIndex(self, offset: NSUInteger, index: NSUInteger);
    unsafe fn setVertexBytes_length_atIndex(self, bytes: *const c_void, length: NSUInteger, index: NSUInteger);
    unsafe fn setVertexSamplerState_atIndex(self, sampler: id, index: NSUInteger);
    unsafe fn setVertexSamplerStates_withRange(self, samplers: *const id, range: NSRange);
    unsafe fn setVertexSamplerState_lodMinClamp_lodMaxClamp_atIndex(self, samplers: id, lodMinClamp: f32,
                                                                    lodMaxClamp: f32, index: NSUInteger);
    unsafe fn setVertexSamplerStates_lodMinClamps_lodMaxClamps_withRange(self, samplers: *const id,
                                                                         lodMinClamps: *const f32,
                                                                         lodMaxClamps: *const f32,
                                                                         range: NSRange);
    unsafe fn setVertexTexture_atIndex(self, texture: id, index: NSUInteger);
    unsafe fn setVertexTextures_withRange(self, textures: *const id, range: NSRange);

    unsafe fn setFragmentBuffer_offset_atIndex(self, buffer: id, offset: NSUInteger, index: NSUInteger);
    unsafe fn setFragmentBuffers_offsets_withRange(self, buffers: *const id, offsets: *const NSUInteger,
                                                   range: NSRange);
    unsafe fn setFragmentBufferOffset_atIndex(self, offset: NSUInteger, index: NSUInteger);
    unsafe fn setFragmentBytes_length_atIndex(self, bytes: *const c_void, length: NSUInteger, index: NSUInteger);
    unsafe fn setFragmentSamplerState_atIndex(self, sampler: id, index: NSUInteger);
    unsafe fn setFragmentSamplerStates_withRange(self, samplers: *const id, range: NSRange);
    unsafe fn setFragmentSamplerState_lodMinClamp_lodMaxClamp_atIndex(self, samplers: id, lodMinClamp: f32,
                                                                      lodMaxClamp: f32, index: NSUInteger);
    unsafe fn setFragmentSamplerStates_lodMinClamps_lodMaxClamps_withRange(self, samplers: *const id,
                                                                           lodMinClamps: f32,
                                                                           lodMaxClamps: f32,
                                                                           range: NSRange);
    unsafe fn setFragmentTexture_atIndex(self, texture: id, index: NSUInteger);
    unsafe fn setFragmentTextures_withRange(self, textures: *const id, range: NSRange);

    unsafe fn drawPrimitives_vertexStart_vertexCount_instanceCount_baseInstance(self,
        primitiveType: MTLPrimitiveType, vertexStart: NSUInteger, vertexCount: NSUInteger,
        instanceCount: NSUInteger, baseInstance: NSUInteger);
    unsafe fn drawPrimitives_vertexStart_vertexCount_instanceCount(self, primitiveType: MTLPrimitiveType,
                                                                   vertexStart: NSUInteger, vertexCount: NSUInteger,
                                                                   instanceCount: NSUInteger);
    unsafe fn drawPrimitives_vertexStart_vertexCount(self, vertexStart: NSUInteger, vertexCount: NSUInteger);
    unsafe fn drawPrimitives_indirectBuffer_indirectBufferOffset(self, primitiveType: MTLPrimitiveType,
                                                                 indirectBuffer: id, indirectBufferOffset: NSUInteger);
    unsafe fn drawIndexedPrimitives_indexCount_indexType_indexBuffer_indexBufferOffset_instanceCount_baseVertex_baseInstance(
        self, primitiveType: MTLPrimitiveType, indexCount: NSUInteger, indexType: MTLIndexType, indexBuffer: id,
        indexBufferOffset: NSUInteger, instanceCount: NSUInteger, baseVertex: NSInteger, baseInstance: NSUInteger);
    unsafe fn drawIndexedPrimitives_indexCount_indexType_indexBuffer_indexBufferOffset_instanceCount(
        self, primitiveType: MTLPrimitiveType, indexCount: NSUInteger, indexType: MTLIndexType, indexBuffer: id,
        indexBufferOffset: NSUInteger, instanceCount: NSUInteger);
    unsafe fn drawIndexedPrimitives_indexCount_indexType_indexBuffer_indexBufferOffset(
        self, primitiveType: MTLPrimitiveType, indexCount: NSUInteger, indexType: MTLIndexType, indexBuffer: id,
        indexBufferOffset: NSUInteger);
    unsafe fn drawIndexedPrimitives_indexType_indexBuffer_indexBufferOffset_indirectBuffer_indirectBufferOffset(self,
        primitiveType: MTLPrimitiveType, indexType: MTLIndexType, indexBuffer: id, indexBufferOffset: NSUInteger,
        indirectBuffer: id, indirectBufferOffset: NSUInteger);
}

impl MTLRenderCommandEncoder for id {
    unsafe fn setBlendColorRed_green_blue_alpha(self, red: f32, green: f32, blue: f32, alpha: f32) {
        unimplemented!();
    }
    unsafe fn setCullMode(self, cullMode: MTLCullMode) {
        unimplemented!();
    }
    unsafe fn setDepthBias_slopeScale_clamp(self, depthBias: f32, slopeScale: f32, clamp: f32) {
        unimplemented!();
    }
    unsafe fn setDepthClipMode(self, depthClipMode: MTLDepthClipMode) {
        unimplemented!();
    }
    unsafe fn setDepthStencilState(self, depthStencilState: id) {
        unimplemented!();
    }
    unsafe fn setFrontFacingWinding(self, frontFacingWinding: MTLWinding) {
        unimplemented!();
    }
    unsafe fn setRenderPipelineState(self, renderPipelineState: id) {
        unimplemented!();
    }
    unsafe fn setScissorRect(self, scissorRect: MTLScissorRect) {
        unimplemented!();
    }
    unsafe fn setStencilFrontReferenceValue_backReferenceValue(self, frontReferenceValue: uint32_t,
                                                               backReferenceValue: uint32_t) {
        unimplemented!();
    }
    unsafe fn setStencilReferenceValue(self, referenceValue: uint32_t) {
        unimplemented!();
    }
    unsafe fn setTriangleFillMode(self, fillMode: MTLTriangleFillMode) {
        unimplemented!();
    }
    unsafe fn setViewport(self, viewport: MTLViewport) {
        unimplemented!();
    }
    unsafe fn setVisibilityResultMode_offset(self, visibilityResultMode: MTLVisibilityResultMode,
                                             offset: NSUInteger) {
        unimplemented!();
    }

    unsafe fn setVertexBuffer_offset_atIndex(self, buffer: id, offset: NSUInteger, index: NSUInteger) {
        unimplemented!();
    }
    unsafe fn setVertexBuffers_offsets_withRange(self, buffers: *const id, offsets: *const NSUInteger, range: NSRange) {
        unimplemented!();
    }
    unsafe fn setVertexBufferOffset_atIndex(self, offset: NSUInteger, index: NSUInteger) {
        unimplemented!();
    }
    unsafe fn setVertexBytes_length_atIndex(self, bytes: *const c_void, length: NSUInteger, index: NSUInteger) {
        unimplemented!();
    }
    unsafe fn setVertexSamplerState_atIndex(self, sampler: id, index: NSUInteger) {
        unimplemented!();
    }
    unsafe fn setVertexSamplerStates_withRange(self, samplers: *const id, range: NSRange) {
        unimplemented!();
    }
    unsafe fn setVertexSamplerState_lodMinClamp_lodMaxClamp_atIndex(self, samplers: id, lodMinClamp: f32,
                                                                    lodMaxClamp: f32, index: NSUInteger) {
        unimplemented!();
    }
    unsafe fn setVertexSamplerStates_lodMinClamps_lodMaxClamps_withRange(self, samplers: *const id,
                                                                         lodMinClamps: *const f32,
                                                                         lodMaxClamps: *const f32,
                                                                         range: NSRange) {
        unimplemented!();
    }
    unsafe fn setVertexTexture_atIndex(self, texture: id, index: NSUInteger) {
        unimplemented!();
    }
    unsafe fn setVertexTextures_withRange(self, textures: *const id, range: NSRange) {
        unimplemented!();
    }

    unsafe fn setFragmentBuffer_offset_atIndex(self, buffer: id, offset: NSUInteger, index: NSUInteger) {
        unimplemented!();
    }
    unsafe fn setFragmentBuffers_offsets_withRange(self, buffers: *const id, offsets: *const NSUInteger,
                                                   range: NSRange) {
        unimplemented!();
    }
    unsafe fn setFragmentBufferOffset_atIndex(self, offset: NSUInteger, index: NSUInteger) {
        unimplemented!();
    }
    unsafe fn setFragmentBytes_length_atIndex(self, bytes: *const c_void, length: NSUInteger, index: NSUInteger) {
        unimplemented!();
    }
    unsafe fn setFragmentSamplerState_atIndex(self, sampler: id, index: NSUInteger) {
        unimplemented!();
    }
    unsafe fn setFragmentSamplerStates_withRange(self, samplers: *const id, range: NSRange) {
        unimplemented!();
    }
    unsafe fn setFragmentSamplerState_lodMinClamp_lodMaxClamp_atIndex(self, samplers: id, lodMinClamp: f32,
                                                                      lodMaxClamp: f32, index: NSUInteger) {
        unimplemented!();
    }
    unsafe fn setFragmentSamplerStates_lodMinClamps_lodMaxClamps_withRange(self, samplers: *const id,
                                                                           lodMinClamps: f32,
                                                                           lodMaxClamps: f32,
                                                                           range: NSRange) {
        unimplemented!();
    }
    unsafe fn setFragmentTexture_atIndex(self, texture: id, index: NSUInteger) {
        unimplemented!();
    }
    unsafe fn setFragmentTextures_withRange(self, textures: *const id, range: NSRange) {
        unimplemented!();
    }

    unsafe fn drawPrimitives_vertexStart_vertexCount_instanceCount_baseInstance(self,
        primitiveType: MTLPrimitiveType, vertexStart: NSUInteger, vertexCount: NSUInteger,
        instanceCount: NSUInteger, baseInstance: NSUInteger) {
        unimplemented!();
    }
    unsafe fn drawPrimitives_vertexStart_vertexCount_instanceCount(self, primitiveType: MTLPrimitiveType,
                                                                   vertexStart: NSUInteger, vertexCount: NSUInteger,
                                                                   instanceCount: NSUInteger) {
        unimplemented!();
    }
    unsafe fn drawPrimitives_vertexStart_vertexCount(self, vertexStart: NSUInteger, vertexCount: NSUInteger) {
        unimplemented!();
    }
    unsafe fn drawPrimitives_indirectBuffer_indirectBufferOffset(self, primitiveType: MTLPrimitiveType,
                                                                 indirectBuffer: id, indirectBufferOffset: NSUInteger) {
        unimplemented!();
    }
    unsafe fn drawIndexedPrimitives_indexCount_indexType_indexBuffer_indexBufferOffset_instanceCount_baseVertex_baseInstance(
        self, primitiveType: MTLPrimitiveType, indexCount: NSUInteger, indexType: MTLIndexType, indexBuffer: id,
        indexBufferOffset: NSUInteger, instanceCount: NSUInteger, baseVertex: NSInteger, baseInstance: NSUInteger) {
        unimplemented!();
    }
    unsafe fn drawIndexedPrimitives_indexCount_indexType_indexBuffer_indexBufferOffset_instanceCount(
        self, primitiveType: MTLPrimitiveType, indexCount: NSUInteger, indexType: MTLIndexType, indexBuffer: id,
        indexBufferOffset: NSUInteger, instanceCount: NSUInteger) {
        unimplemented!();
    }
    unsafe fn drawIndexedPrimitives_indexCount_indexType_indexBuffer_indexBufferOffset(
        self, primitiveType: MTLPrimitiveType, indexCount: NSUInteger, indexType: MTLIndexType, indexBuffer: id,
        indexBufferOffset: NSUInteger) {
        unimplemented!();
    }
    unsafe fn drawIndexedPrimitives_indexType_indexBuffer_indexBufferOffset_indirectBuffer_indirectBufferOffset(self,
        primitiveType: MTLPrimitiveType, indexType: MTLIndexType, indexBuffer: id, indexBufferOffset: NSUInteger,
        indirectBuffer: id, indirectBufferOffset: NSUInteger) {
        unimplemented!();
    }
}

#[repr(usize)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum MTLPrimitiveType {
    MTLPrimitiveTypePoint = 0,
    MTLPrimitiveTypeLine = 1,
    MTLPrimitiveTypeLineStrip = 2,
    MTLPrimitiveTypeTriangle = 3,
    MTLPrimitiveTypeTriangleStrip = 4
}

#[repr(usize)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum MTLIndexType {
    MTLIndexTypeUInt16 = 0,
    MTLIndexTypeUInt32 = 1
}

#[repr(usize)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum MTLVisibilityResultMode {
    MTLVisibilityResultModeDisabled = 0,
    MTLVisibilityResultModeBoolean = 1,
    MTLVisibilityResultModeCounting = 2
}

#[repr(usize)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum MTLCullMode {
    MTLCullModeNone = 0,
    MTLCullModeFront = 1,
    MTLCullModeBack = 2
}

#[repr(usize)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum MTLDepthClipMode {
    MTLDepthClipModeClip = 0,
    MTLDepthClipModeClamp = 1
}

#[repr(usize)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum MTLWinding {
    MTLWindingClockwise = 0,
    MTLWindingCounterClockwise = 1
}

#[repr(usize)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum MTLTriangleFillMode {
    MTLTriangleFillModeFill = 0,
    MTLTriangleFillModeLines = 1
}
<|endoftext|>