<commit_before>use rustc::ty::{self, Ty, TypeAndMut};
use rustc::ty::layout::{self, TyLayout, Size};
use rustc::ty::adjustment::{PointerCast};
use syntax::ast::{FloatTy, IntTy, UintTy};
use syntax::symbol::sym;

use rustc_apfloat::ieee::{Single, Double};
use rustc::mir::interpret::{
    Scalar, EvalResult, Pointer, PointerArithmetic, InterpError,
};
use rustc::mir::CastKind;
use rustc_apfloat::Float;

use super::{InterpretCx, Machine, PlaceTy, OpTy, ImmTy, Immediate};

impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> {
    fn type_is_fat_ptr(&self, ty: Ty<'tcx>) -> bool {
        match ty.sty {
            ty::RawPtr(ty::TypeAndMut { ty, .. }) |
            ty::Ref(_, ty, _) => !self.type_is_sized(ty),
            ty::Adt(def, _) if def.is_box() => !self.type_is_sized(ty.boxed_ty()),
            _ => false,
        }
    }

    pub fn cast(
        &mut self,
        src: OpTy<'tcx, M::PointerTag>,
        kind: CastKind,
        dest: PlaceTy<'tcx, M::PointerTag>,
    ) -> EvalResult<'tcx> {
        use rustc::mir::CastKind::*;
        match kind {
            Pointer(PointerCast::Unsize) => {
                self.unsize_into(src, dest)?;
            }

            Misc | Pointer(PointerCast::MutToConstPointer) => {
                let src = self.read_immediate(src)?;

                if self.type_is_fat_ptr(src.layout.ty) {
                    match (*src, self.type_is_fat_ptr(dest.layout.ty)) {
                        // pointers to extern types
                        (Immediate::Scalar(_),_) |
                        // slices and trait objects to other slices/trait objects
                        (Immediate::ScalarPair(..), true) => {
                            // No change to immediate
                            self.write_immediate(*src, dest)?;
                        }
                        // slices and trait objects to thin pointers (dropping the metadata)
                        (Immediate::ScalarPair(data, _), false) => {
                            self.write_scalar(data, dest)?;
                        }
                    }
                } else {
                    match src.layout.variants {
                        layout::Variants::Single { index } => {
                            if let Some(discr) =
                                src.layout.ty.discriminant_for_variant(*self.tcx, index)
                            {
                                // Cast from a univariant enum
                                assert!(src.layout.is_zst());
                                return self.write_scalar(
                                    Scalar::from_uint(discr.val, dest.layout.size),
                                    dest);
                            }
                        }
                        layout::Variants::Multiple { .. } => {},
                    }

                    let dest_val = self.cast_scalar(src.to_scalar()?, src.layout, dest.layout)?;
                    self.write_scalar(dest_val, dest)?;
                }
            }

            Pointer(PointerCast::ReifyFnPointer) => {
                // The src operand does not matter, just its type
                match src.layout.ty.sty {
                    ty::FnDef(def_id, substs) => {
                        if self.tcx.has_attr(def_id, sym::rustc_args_required_const) {
                            bug!("reifying a fn ptr that requires const arguments");
                        }
                        let instance: EvalResult<'tcx, _> = ty::Instance::resolve(
                            *self.tcx,
                            self.param_env,
                            def_id,
                            substs,
                        ).ok_or_else(|| InterpError::TooGeneric.into());
                        let fn_ptr = self.memory.create_fn_alloc(instance?);
                        self.write_scalar(Scalar::Ptr(fn_ptr.into()), dest)?;
                    }
                    _ => bug!("reify fn pointer on {:?}", src.layout.ty),
                }
            }

            Pointer(PointerCast::UnsafeFnPointer) => {
                let src = self.read_immediate(src)?;
                match dest.layout.ty.sty {
                    ty::FnPtr(_) => {
                        // No change to value
                        self.write_immediate(*src, dest)?;
                    }
                    _ => bug!("fn to unsafe fn cast on {:?}", dest.layout.ty),
                }
            }

            Pointer(PointerCast::ClosureFnPointer(_)) => {
                // The src operand does not matter, just its type
                match src.layout.ty.sty {
                    ty::Closure(def_id, substs) => {
                        let substs = self.subst_and_normalize_erasing_regions(substs)?;
                        let instance = ty::Instance::resolve_closure(
                            *self.tcx,
                            def_id,
                            substs,
                            ty::ClosureKind::FnOnce,
                        );
                        let fn_ptr = self.memory.create_fn_alloc(instance);
                        let val = Immediate::Scalar(Scalar::Ptr(fn_ptr.into()).into());
                        self.write_immediate(val, dest)?;
                    }
                    _ => bug!("closure fn pointer on {:?}", src.layout.ty),
                }
            }
        }
        Ok(())
    }

    pub(super) fn cast_scalar(
        &self,
        val: Scalar<M::PointerTag>,
        src_layout: TyLayout<'tcx>,
        dest_layout: TyLayout<'tcx>,
    ) -> EvalResult<'tcx, Scalar<M::PointerTag>> {
        use rustc::ty::TyKind::*;
        trace!("Casting {:?}: {:?} to {:?}", val, src_layout.ty, dest_layout.ty);

        match val.to_bits_or_ptr(src_layout.size, self) {
            Err(ptr) => self.cast_from_ptr(ptr, dest_layout.ty),
            Ok(data) => {
                match src_layout.ty.sty {
                    Float(fty) => self.cast_from_float(data, fty, dest_layout.ty),
                    _ => self.cast_from_int(data, src_layout, dest_layout),
                }
            }
        }
    }

    fn cast_from_int(
        &self,
        v: u128,
        src_layout: TyLayout<'tcx>,
        dest_layout: TyLayout<'tcx>,
    ) -> EvalResult<'tcx, Scalar<M::PointerTag>> {
        let signed = src_layout.abi.is_signed();
        let v = if signed {
            self.sign_extend(v, src_layout)
        } else {
            v
        };
        trace!("cast_from_int: {}, {}, {}", v, src_layout.ty, dest_layout.ty);
        use rustc::ty::TyKind::*;
        match dest_layout.ty.sty {
            Int(_) | Uint(_) | RawPtr(_) => {
                let v = self.truncate(v, dest_layout);
                Ok(Scalar::from_uint(v, dest_layout.size))
            }

            Float(FloatTy::F32) if signed => Ok(Scalar::from_uint(
                Single::from_i128(v as i128).value.to_bits(),
                Size::from_bits(32)
            )),
            Float(FloatTy::F64) if signed => Ok(Scalar::from_uint(
                Double::from_i128(v as i128).value.to_bits(),
                Size::from_bits(64)
            )),
            Float(FloatTy::F32) => Ok(Scalar::from_uint(
                Single::from_u128(v).value.to_bits(),
                Size::from_bits(32)
            )),
            Float(FloatTy::F64) => Ok(Scalar::from_uint(
                Double::from_u128(v).value.to_bits(),
                Size::from_bits(64)
            )),

            Char => {
                // `u8` to `char` cast
                debug_assert_eq!(v as u8 as u128, v);
                Ok(Scalar::from_uint(v, Size::from_bytes(4)))
            },

            // Casts to bool are not permitted by rustc, no need to handle them here.
            _ => err!(Unimplemented(format!("int to {:?} cast", dest_layout.ty))),
        }
    }

    fn cast_from_float(
        &self,
        bits: u128,
        fty: FloatTy,
        dest_ty: Ty<'tcx>
    ) -> EvalResult<'tcx, Scalar<M::PointerTag>> {
        use rustc::ty::TyKind::*;
        use rustc_apfloat::FloatConvert;
        match dest_ty.sty {
            // float -> uint
            Uint(t) => {
                let width = t.bit_width().unwrap_or_else(|| self.pointer_size().bits() as usize);
                let v = match fty {
                    FloatTy::F32 => Single::from_bits(bits).to_u128(width).value,
                    FloatTy::F64 => Double::from_bits(bits).to_u128(width).value,
                };
                // This should already fit the bit width
                Ok(Scalar::from_uint(v, Size::from_bits(width as u64)))
            },
            // float -> int
            Int(t) => {
                let width = t.bit_width().unwrap_or_else(|| self.pointer_size().bits() as usize);
                let v = match fty {
                    FloatTy::F32 => Single::from_bits(bits).to_i128(width).value,
                    FloatTy::F64 => Double::from_bits(bits).to_i128(width).value,
                };
                Ok(Scalar::from_int(v, Size::from_bits(width as u64)))
            },
            // f64 -> f32
            Float(FloatTy::F32) if fty == FloatTy::F64 => {
                Ok(Scalar::from_uint(
                    Single::to_bits(Double::from_bits(bits).convert(&mut false).value),
                    Size::from_bits(32),
                ))
            },
            // f32 -> f64
            Float(FloatTy::F64) if fty == FloatTy::F32 => {
                Ok(Scalar::from_uint(
                    Double::to_bits(Single::from_bits(bits).convert(&mut false).value),
                    Size::from_bits(64),
                ))
            },
            // identity cast
            Float(FloatTy:: F64) => Ok(Scalar::from_uint(bits, Size::from_bits(64))),
            Float(FloatTy:: F32) => Ok(Scalar::from_uint(bits, Size::from_bits(32))),
            _ => err!(Unimplemented(format!("float to {:?} cast", dest_ty))),
        }
    }

    fn cast_from_ptr(
        &self,
        ptr: Pointer<M::PointerTag>,
        ty: Ty<'tcx>
    ) -> EvalResult<'tcx, Scalar<M::PointerTag>> {
        use rustc::ty::TyKind::*;
        match ty.sty {
            // Casting to a reference or fn pointer is not permitted by rustc,
            // no need to support it here.
            RawPtr(_) |
            Int(IntTy::Isize) |
            Uint(UintTy::Usize) => Ok(ptr.into()),
            Int(_) | Uint(_) => err!(ReadPointerAsBytes),
            _ => err!(Unimplemented(format!("ptr to {:?} cast", ty))),
        }
    }

    fn unsize_into_ptr(
        &mut self,
        src: OpTy<'tcx, M::PointerTag>,
        dest: PlaceTy<'tcx, M::PointerTag>,
        // The pointee types
        sty: Ty<'tcx>,
        dty: Ty<'tcx>,
    ) -> EvalResult<'tcx> {
        // A<Struct> -> A<Trait> conversion
        let (src_pointee_ty, dest_pointee_ty) = self.tcx.struct_lockstep_tails(sty, dty);

        match (&src_pointee_ty.sty, &dest_pointee_ty.sty) {
            (&ty::Array(_, length), &ty::Slice(_)) => {
                let ptr = self.read_immediate(src)?.to_scalar_ptr()?;
                // u64 cast is from usize to u64, which is always good
                let val = Immediate::new_slice(
                    ptr,
                    length.unwrap_usize(self.tcx.tcx),
                    self,
                );
                self.write_immediate(val, dest)
            }
            (&ty::Dynamic(..), &ty::Dynamic(..)) => {
                // For now, upcasts are limited to changes in marker
                // traits, and hence never actually require an actual
                // change to the vtable.
                let val = self.read_immediate(src)?;
                self.write_immediate(*val, dest)
            }
            (_, &ty::Dynamic(ref data, _)) => {
                // Initial cast from sized to dyn trait
                let vtable = self.get_vtable(src_pointee_ty, data.principal())?;
                let ptr = self.read_immediate(src)?.to_scalar_ptr()?;
                let val = Immediate::new_dyn_trait(ptr, vtable);
                self.write_immediate(val, dest)
            }

            _ => bug!("invalid unsizing {:?} -> {:?}", src.layout.ty, dest.layout.ty),
        }
    }

    fn unsize_into(
        &mut self,
        src: OpTy<'tcx, M::PointerTag>,
        dest: PlaceTy<'tcx, M::PointerTag>,
    ) -> EvalResult<'tcx> {
        match (&src.layout.ty.sty, &dest.layout.ty.sty) {
            (&ty::Ref(_, s, _), &ty::Ref(_, d, _)) |
            (&ty::Ref(_, s, _), &ty::RawPtr(TypeAndMut { ty: d, .. })) |
            (&ty::RawPtr(TypeAndMut { ty: s, .. }),
             &ty::RawPtr(TypeAndMut { ty: d, .. })) => {
                self.unsize_into_ptr(src, dest, s, d)
            }
            (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
                assert_eq!(def_a, def_b);
                if def_a.is_box() || def_b.is_box() {
                    if !def_a.is_box() || !def_b.is_box() {
                        bug!("invalid unsizing between {:?} -> {:?}", src.layout, dest.layout);
                    }
                    return self.unsize_into_ptr(
                        src,
                        dest,
                        src.layout.ty.boxed_ty(),
                        dest.layout.ty.boxed_ty(),
                    );
                }

                // unsizing of generic struct with pointer fields
                // Example: `Arc<T>` -> `Arc<Trait>`
                // here we need to increase the size of every &T thin ptr field to a fat ptr
                for i in 0..src.layout.fields.count() {
                    let dst_field = self.place_field(dest, i as u64)?;
                    if dst_field.layout.is_zst() {
                        continue;
                    }
                    let src_field = match src.try_as_mplace() {
                        Ok(mplace) => {
                            let src_field = self.mplace_field(mplace, i as u64)?;
                            src_field.into()
                        }
                        Err(..) => {
                            let src_field_layout = src.layout.field(self, i)?;
                            // this must be a field covering the entire thing
                            assert_eq!(src.layout.fields.offset(i).bytes(), 0);
                            assert_eq!(src_field_layout.size, src.layout.size);
                            // just sawp out the layout
                            OpTy::from(ImmTy { imm: src.to_immediate(), layout: src_field_layout })
                        }
                    };
                    if src_field.layout.ty == dst_field.layout.ty {
                        self.copy_op(src_field, dst_field)?;
                    } else {
                        self.unsize_into(src_field, dst_field)?;
                    }
                }
                Ok(())
            }
            _ => {
                bug!(
                    "unsize_into: invalid conversion: {:?} -> {:?}",
                    src.layout,
                    dest.layout
                )
            }
        }
    }
}
<commit_msg>Rollup merge of #61404 - RalfJung:miri-unsize, r=oli-obk<commit_after>use rustc::ty::{self, Ty, TypeAndMut};
use rustc::ty::layout::{self, TyLayout, Size};
use rustc::ty::adjustment::{PointerCast};
use syntax::ast::{FloatTy, IntTy, UintTy};
use syntax::symbol::sym;

use rustc_apfloat::ieee::{Single, Double};
use rustc::mir::interpret::{
    Scalar, EvalResult, Pointer, PointerArithmetic, InterpError,
};
use rustc::mir::CastKind;
use rustc_apfloat::Float;

use super::{InterpretCx, Machine, PlaceTy, OpTy, Immediate};

impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> {
    fn type_is_fat_ptr(&self, ty: Ty<'tcx>) -> bool {
        match ty.sty {
            ty::RawPtr(ty::TypeAndMut { ty, .. }) |
            ty::Ref(_, ty, _) => !self.type_is_sized(ty),
            ty::Adt(def, _) if def.is_box() => !self.type_is_sized(ty.boxed_ty()),
            _ => false,
        }
    }

    pub fn cast(
        &mut self,
        src: OpTy<'tcx, M::PointerTag>,
        kind: CastKind,
        dest: PlaceTy<'tcx, M::PointerTag>,
    ) -> EvalResult<'tcx> {
        use rustc::mir::CastKind::*;
        match kind {
            Pointer(PointerCast::Unsize) => {
                self.unsize_into(src, dest)?;
            }

            Misc | Pointer(PointerCast::MutToConstPointer) => {
                let src = self.read_immediate(src)?;

                if self.type_is_fat_ptr(src.layout.ty) {
                    match (*src, self.type_is_fat_ptr(dest.layout.ty)) {
                        // pointers to extern types
                        (Immediate::Scalar(_),_) |
                        // slices and trait objects to other slices/trait objects
                        (Immediate::ScalarPair(..), true) => {
                            // No change to immediate
                            self.write_immediate(*src, dest)?;
                        }
                        // slices and trait objects to thin pointers (dropping the metadata)
                        (Immediate::ScalarPair(data, _), false) => {
                            self.write_scalar(data, dest)?;
                        }
                    }
                } else {
                    match src.layout.variants {
                        layout::Variants::Single { index } => {
                            if let Some(discr) =
                                src.layout.ty.discriminant_for_variant(*self.tcx, index)
                            {
                                // Cast from a univariant enum
                                assert!(src.layout.is_zst());
                                return self.write_scalar(
                                    Scalar::from_uint(discr.val, dest.layout.size),
                                    dest);
                            }
                        }
                        layout::Variants::Multiple { .. } => {},
                    }

                    let dest_val = self.cast_scalar(src.to_scalar()?, src.layout, dest.layout)?;
                    self.write_scalar(dest_val, dest)?;
                }
            }

            Pointer(PointerCast::ReifyFnPointer) => {
                // The src operand does not matter, just its type
                match src.layout.ty.sty {
                    ty::FnDef(def_id, substs) => {
                        if self.tcx.has_attr(def_id, sym::rustc_args_required_const) {
                            bug!("reifying a fn ptr that requires const arguments");
                        }
                        let instance: EvalResult<'tcx, _> = ty::Instance::resolve(
                            *self.tcx,
                            self.param_env,
                            def_id,
                            substs,
                        ).ok_or_else(|| InterpError::TooGeneric.into());
                        let fn_ptr = self.memory.create_fn_alloc(instance?);
                        self.write_scalar(Scalar::Ptr(fn_ptr.into()), dest)?;
                    }
                    _ => bug!("reify fn pointer on {:?}", src.layout.ty),
                }
            }

            Pointer(PointerCast::UnsafeFnPointer) => {
                let src = self.read_immediate(src)?;
                match dest.layout.ty.sty {
                    ty::FnPtr(_) => {
                        // No change to value
                        self.write_immediate(*src, dest)?;
                    }
                    _ => bug!("fn to unsafe fn cast on {:?}", dest.layout.ty),
                }
            }

            Pointer(PointerCast::ClosureFnPointer(_)) => {
                // The src operand does not matter, just its type
                match src.layout.ty.sty {
                    ty::Closure(def_id, substs) => {
                        let substs = self.subst_and_normalize_erasing_regions(substs)?;
                        let instance = ty::Instance::resolve_closure(
                            *self.tcx,
                            def_id,
                            substs,
                            ty::ClosureKind::FnOnce,
                        );
                        let fn_ptr = self.memory.create_fn_alloc(instance);
                        let val = Immediate::Scalar(Scalar::Ptr(fn_ptr.into()).into());
                        self.write_immediate(val, dest)?;
                    }
                    _ => bug!("closure fn pointer on {:?}", src.layout.ty),
                }
            }
        }
        Ok(())
    }

    pub(super) fn cast_scalar(
        &self,
        val: Scalar<M::PointerTag>,
        src_layout: TyLayout<'tcx>,
        dest_layout: TyLayout<'tcx>,
    ) -> EvalResult<'tcx, Scalar<M::PointerTag>> {
        use rustc::ty::TyKind::*;
        trace!("Casting {:?}: {:?} to {:?}", val, src_layout.ty, dest_layout.ty);

        match val.to_bits_or_ptr(src_layout.size, self) {
            Err(ptr) => self.cast_from_ptr(ptr, dest_layout.ty),
            Ok(data) => {
                match src_layout.ty.sty {
                    Float(fty) => self.cast_from_float(data, fty, dest_layout.ty),
                    _ => self.cast_from_int(data, src_layout, dest_layout),
                }
            }
        }
    }

    fn cast_from_int(
        &self,
        v: u128,
        src_layout: TyLayout<'tcx>,
        dest_layout: TyLayout<'tcx>,
    ) -> EvalResult<'tcx, Scalar<M::PointerTag>> {
        let signed = src_layout.abi.is_signed();
        let v = if signed {
            self.sign_extend(v, src_layout)
        } else {
            v
        };
        trace!("cast_from_int: {}, {}, {}", v, src_layout.ty, dest_layout.ty);
        use rustc::ty::TyKind::*;
        match dest_layout.ty.sty {
            Int(_) | Uint(_) | RawPtr(_) => {
                let v = self.truncate(v, dest_layout);
                Ok(Scalar::from_uint(v, dest_layout.size))
            }

            Float(FloatTy::F32) if signed => Ok(Scalar::from_uint(
                Single::from_i128(v as i128).value.to_bits(),
                Size::from_bits(32)
            )),
            Float(FloatTy::F64) if signed => Ok(Scalar::from_uint(
                Double::from_i128(v as i128).value.to_bits(),
                Size::from_bits(64)
            )),
            Float(FloatTy::F32) => Ok(Scalar::from_uint(
                Single::from_u128(v).value.to_bits(),
                Size::from_bits(32)
            )),
            Float(FloatTy::F64) => Ok(Scalar::from_uint(
                Double::from_u128(v).value.to_bits(),
                Size::from_bits(64)
            )),

            Char => {
                // `u8` to `char` cast
                debug_assert_eq!(v as u8 as u128, v);
                Ok(Scalar::from_uint(v, Size::from_bytes(4)))
            },

            // Casts to bool are not permitted by rustc, no need to handle them here.
            _ => err!(Unimplemented(format!("int to {:?} cast", dest_layout.ty))),
        }
    }

    fn cast_from_float(
        &self,
        bits: u128,
        fty: FloatTy,
        dest_ty: Ty<'tcx>
    ) -> EvalResult<'tcx, Scalar<M::PointerTag>> {
        use rustc::ty::TyKind::*;
        use rustc_apfloat::FloatConvert;
        match dest_ty.sty {
            // float -> uint
            Uint(t) => {
                let width = t.bit_width().unwrap_or_else(|| self.pointer_size().bits() as usize);
                let v = match fty {
                    FloatTy::F32 => Single::from_bits(bits).to_u128(width).value,
                    FloatTy::F64 => Double::from_bits(bits).to_u128(width).value,
                };
                // This should already fit the bit width
                Ok(Scalar::from_uint(v, Size::from_bits(width as u64)))
            },
            // float -> int
            Int(t) => {
                let width = t.bit_width().unwrap_or_else(|| self.pointer_size().bits() as usize);
                let v = match fty {
                    FloatTy::F32 => Single::from_bits(bits).to_i128(width).value,
                    FloatTy::F64 => Double::from_bits(bits).to_i128(width).value,
                };
                Ok(Scalar::from_int(v, Size::from_bits(width as u64)))
            },
            // f64 -> f32
            Float(FloatTy::F32) if fty == FloatTy::F64 => {
                Ok(Scalar::from_uint(
                    Single::to_bits(Double::from_bits(bits).convert(&mut false).value),
                    Size::from_bits(32),
                ))
            },
            // f32 -> f64
            Float(FloatTy::F64) if fty == FloatTy::F32 => {
                Ok(Scalar::from_uint(
                    Double::to_bits(Single::from_bits(bits).convert(&mut false).value),
                    Size::from_bits(64),
                ))
            },
            // identity cast
            Float(FloatTy:: F64) => Ok(Scalar::from_uint(bits, Size::from_bits(64))),
            Float(FloatTy:: F32) => Ok(Scalar::from_uint(bits, Size::from_bits(32))),
            _ => err!(Unimplemented(format!("float to {:?} cast", dest_ty))),
        }
    }

    fn cast_from_ptr(
        &self,
        ptr: Pointer<M::PointerTag>,
        ty: Ty<'tcx>
    ) -> EvalResult<'tcx, Scalar<M::PointerTag>> {
        use rustc::ty::TyKind::*;
        match ty.sty {
            // Casting to a reference or fn pointer is not permitted by rustc,
            // no need to support it here.
            RawPtr(_) |
            Int(IntTy::Isize) |
            Uint(UintTy::Usize) => Ok(ptr.into()),
            Int(_) | Uint(_) => err!(ReadPointerAsBytes),
            _ => err!(Unimplemented(format!("ptr to {:?} cast", ty))),
        }
    }

    fn unsize_into_ptr(
        &mut self,
        src: OpTy<'tcx, M::PointerTag>,
        dest: PlaceTy<'tcx, M::PointerTag>,
        // The pointee types
        sty: Ty<'tcx>,
        dty: Ty<'tcx>,
    ) -> EvalResult<'tcx> {
        // A<Struct> -> A<Trait> conversion
        let (src_pointee_ty, dest_pointee_ty) = self.tcx.struct_lockstep_tails(sty, dty);

        match (&src_pointee_ty.sty, &dest_pointee_ty.sty) {
            (&ty::Array(_, length), &ty::Slice(_)) => {
                let ptr = self.read_immediate(src)?.to_scalar_ptr()?;
                // u64 cast is from usize to u64, which is always good
                let val = Immediate::new_slice(
                    ptr,
                    length.unwrap_usize(self.tcx.tcx),
                    self,
                );
                self.write_immediate(val, dest)
            }
            (&ty::Dynamic(..), &ty::Dynamic(..)) => {
                // For now, upcasts are limited to changes in marker
                // traits, and hence never actually require an actual
                // change to the vtable.
                let val = self.read_immediate(src)?;
                self.write_immediate(*val, dest)
            }
            (_, &ty::Dynamic(ref data, _)) => {
                // Initial cast from sized to dyn trait
                let vtable = self.get_vtable(src_pointee_ty, data.principal())?;
                let ptr = self.read_immediate(src)?.to_scalar_ptr()?;
                let val = Immediate::new_dyn_trait(ptr, vtable);
                self.write_immediate(val, dest)
            }

            _ => bug!("invalid unsizing {:?} -> {:?}", src.layout.ty, dest.layout.ty),
        }
    }

    fn unsize_into(
        &mut self,
        src: OpTy<'tcx, M::PointerTag>,
        dest: PlaceTy<'tcx, M::PointerTag>,
    ) -> EvalResult<'tcx> {
        trace!("Unsizing {:?} into {:?}", src, dest);
        match (&src.layout.ty.sty, &dest.layout.ty.sty) {
            (&ty::Ref(_, s, _), &ty::Ref(_, d, _)) |
            (&ty::Ref(_, s, _), &ty::RawPtr(TypeAndMut { ty: d, .. })) |
            (&ty::RawPtr(TypeAndMut { ty: s, .. }),
             &ty::RawPtr(TypeAndMut { ty: d, .. })) => {
                self.unsize_into_ptr(src, dest, s, d)
            }
            (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
                assert_eq!(def_a, def_b);
                if def_a.is_box() || def_b.is_box() {
                    if !def_a.is_box() || !def_b.is_box() {
                        bug!("invalid unsizing between {:?} -> {:?}", src.layout, dest.layout);
                    }
                    return self.unsize_into_ptr(
                        src,
                        dest,
                        src.layout.ty.boxed_ty(),
                        dest.layout.ty.boxed_ty(),
                    );
                }

                // unsizing of generic struct with pointer fields
                // Example: `Arc<T>` -> `Arc<Trait>`
                // here we need to increase the size of every &T thin ptr field to a fat ptr
                for i in 0..src.layout.fields.count() {
                    let dst_field = self.place_field(dest, i as u64)?;
                    if dst_field.layout.is_zst() {
                        continue;
                    }
                    let src_field = self.operand_field(src, i as u64)?;
                    if src_field.layout.ty == dst_field.layout.ty {
                        self.copy_op(src_field, dst_field)?;
                    } else {
                        self.unsize_into(src_field, dst_field)?;
                    }
                }
                Ok(())
            }
            _ => {
                bug!(
                    "unsize_into: invalid conversion: {:?} -> {:?}",
                    src.layout,
                    dest.layout
                )
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::fs::{File, OpenOptions, metadata};
use std::path::{Path, PathBuf};

use bincode::SizeLimit;
use bincode::rustc_serialize::{encode, encode_into, decode_from};

use super::Error;
use super::database::Database;
use super::column::Column;
use super::rows::Rows;

use super::super::identifier::Identifier;

pub struct Table<'a> {
    database: &'a Database,
    name: Identifier,
    meta_data: TableMetadata
}

#[derive(Clone, RustcDecodable, RustcEncodable)]
struct TableMetadata {
    engine_id: u8,
    columns: Vec<Column>
}

/// Table representation
impl<'a> Table<'a> {
    /// Create table in database
    pub fn create<'b>(name: &str, engine_id: u8, columns: Vec<Column>, db: &'b Database) -> Result<Table<'b>, Error> {
        info!("creating table: {}", name);

        // TODO: verify if name is a valid identifier

        let metadata = TableMetadata {
            engine_id: engine_id,
            columns: columns
        };

        let mut buf = try!(File::create(db.get_path().clone().join(&name).with_extension("tbl")));

        encode_into(&metadata, &mut buf, SizeLimit::Infinite).unwrap();

        Ok(Table {
            database: &db,
            name: try!(Identifier::new(name)),
            meta_data: metadata.clone()
        })
    }

    /// Load table from database
    pub fn load<'b>(name: &str, db: &'b Database) -> Result<Table<'b>, Error> {
        info!("loading table: {}", &name);
        let path = db.get_path().clone().join(&name).with_extension("tbl");
        if !try!(metadata(&path)).is_dir()
        {
            let mut file = try!(OpenOptions::new()
                                .read(true)
                                .open(&path));

            let metadata: TableMetadata = try!(decode_from(&mut file, SizeLimit::Infinite));
            info!("loaded table: {}", &name);

            Ok(Table {
                database: db,
                name: try!(Identifier::new(name)),
                meta_data: metadata
            })
        }else {
            error!("could not load table: {} at {}", &name, &path.to_str().unwrap());
            Err(Error::LoadTable)
        }
    }

    // TODO: write table delete static function

    /// Returns a vector of the sizes of the columns
    pub fn get_cols_sizes(&self) -> Vec<u32> {
        let mut column_sizes = Vec::<u32>::new();

        for v in &self.meta_data.columns {
            column_sizes.push(v.size());
        }

        column_sizes
    }

    pub fn get_table_header_offset(&self) -> u32 {
        let bytes: Vec<u8> = encode(&self.meta_data, SizeLimit::Infinite).unwrap();
        bytes.len() as u32
    }

    pub fn get_cols_offset(&self) -> u32 {
        let mut size = 0;

        for v in &self.meta_data.columns {
            size += v.size();
        }

        size
    }

    /// Get full file path including filename and ext
    pub fn get_path(&self) -> PathBuf {
        self.database.get_path().clone().join(&self.name.get_name()).with_extension("tbl")
    }

    pub fn get_engine_id(&self) -> u8 {
        self.meta_data.engine_id
    }

}

#[cfg(test)]
mod test {
    use super::Table;
    use super::super::database::*;
    use std::fs::metadata;
    use super::super::column::Column;
    use super::super::types::Types;

    #[test]
    fn create_table() {
        let path = "/tmp/test1/";
        let name = "test_db3";
        let mut columns = Vec::<Column>::new();
        columns.push(Column::new("Name", Types::Char(10)));
        columns.push(Column::new("Age", Types::Int));

        let db = Database::create(&name, DatabaseConfig::new(&path)).unwrap();
        let table = Table::create("test_table1", 0, columns, &db).unwrap();

        assert!(!metadata("/tmp/test1/test_db3/test_table1.tbl").unwrap().is_dir());
    }

    #[test]
    fn load_table() {
        let path = "/tmp/test1/";
        let name = "test_db4";

        let mut columns = Vec::<Column>::new();
        columns.push(Column::new("Name", Types::Char(10)));
        columns.push(Column::new("Age", Types::Int));

        let db2 = Database::create(&name, DatabaseConfig::new(&path));
        assert!(db2.is_ok());
        let db = db2.unwrap();
        let table3 = Table::create("test_table2", 34, columns, &db);
        assert!(table3.is_ok());
        let table = table3.unwrap();

       // assert!(!metadata("/tmp/test1/test_db3/test_table2.tbl").unwrap().is_dir());

        let table2 = Table::load("test_table2", &db).unwrap();

        assert_eq!(table.get_engine_id(), table2.get_engine_id());
        assert_eq!(&table.meta_data.columns, &table2.meta_data.columns);
    }

    #[test]
    fn table_offset() {
        let path = "/tmp/test1/";
        let name = "test_db5";

        let mut columns = Vec::<Column>::new();
        columns.push(Column::new("Name", Types::Char(10)));
        columns.push(Column::new("Age", Types::Int));

        let db = Database::create(&name, DatabaseConfig::new(&path)).unwrap();
        let table = Table::create("test_table1", 34, columns, &db).unwrap();

        assert_eq!(table.get_table_header_offset(), 42u32);

    }

}
<commit_msg>changed table create to OpenOption<commit_after>use std::fs::{File, OpenOptions, metadata};
use std::path::{Path, PathBuf};

use bincode::SizeLimit;
use bincode::rustc_serialize::{encode, encode_into, decode_from};

use super::Error;
use super::database::Database;
use super::column::Column;
use super::rows::Rows;

use super::super::identifier::Identifier;

pub struct Table<'a> {
    database: &'a Database,
    name: Identifier,
    meta_data: TableMetadata
}

#[derive(Clone, RustcDecodable, RustcEncodable)]
struct TableMetadata {
    engine_id: u8,
    columns: Vec<Column>
}

/// Table representation
impl<'a> Table<'a> {
    /// Create table in database
    pub fn create<'b>(name: &str, engine_id: u8, columns: Vec<Column>, db: &'b Database) -> Result<Table<'b>, Error> {
        info!("creating table: {}", name);

        // TODO: verify if name is a valid identifier

        let metadata = TableMetadata {
            engine_id: engine_id,
            columns: columns
        };

        let path = db.get_path().clone().join(&name).with_extension("tbl");
        println!("{}", &path.to_str().unwrap());
        let mut buf = try!(OpenOptions::new()
                           .read(true)
                           .write(true)
                           .create(true)
                           .open(path));

        encode_into(&metadata, &mut buf, SizeLimit::Infinite).unwrap();

        Ok(Table {
            database: &db,
            name: try!(Identifier::new(name)),
            meta_data: metadata.clone()
        })
    }

    /// Load table from database
    pub fn load<'b>(name: &str, db: &'b Database) -> Result<Table<'b>, Error> {
        info!("loading table: {}", &name);
        let path = db.get_path().clone().join(&name).with_extension("tbl");
        if !try!(metadata(&path)).is_dir()
        {
            let mut file = try!(OpenOptions::new()
                                .read(true)
                                .open(&path));

            let metadata: TableMetadata = try!(decode_from(&mut file, SizeLimit::Infinite));
            info!("loaded table: {}", &name);

            Ok(Table {
                database: db,
                name: try!(Identifier::new(name)),
                meta_data: metadata
            })
        }else {
            error!("could not load table: {} at {}", &name, &path.to_str().unwrap());
            Err(Error::LoadTable)
        }
    }

    // TODO: write table delete static function

    /// Returns a vector of the sizes of the columns
    pub fn get_cols_sizes(&self) -> Vec<u32> {
        let mut column_sizes = Vec::<u32>::new();

        for v in &self.meta_data.columns {
            column_sizes.push(v.size());
        }

        column_sizes
    }

    pub fn get_table_header_offset(&self) -> u32 {
        let bytes: Vec<u8> = encode(&self.meta_data, SizeLimit::Infinite).unwrap();
        bytes.len() as u32
    }

    pub fn get_cols_offset(&self) -> u32 {
        let mut size = 0;

        for v in &self.meta_data.columns {
            size += v.size();
        }

        size
    }

    /// Get full file path including filename and ext
    pub fn get_path(&self) -> PathBuf {
        self.database.get_path().clone().join(&self.name.get_name()).with_extension("tbl")
    }

    pub fn get_engine_id(&self) -> u8 {
        self.meta_data.engine_id
    }

}

#[cfg(test)]
mod test {
    use super::Table;
    use super::super::database::*;
    use std::fs::metadata;
    use super::super::column::Column;
    use super::super::types::Types;

    #[test]
    fn create_table() {
        let path = "/tmp/test1/";
        let name = "test_db3";
        let mut columns = Vec::<Column>::new();
        columns.push(Column::new("Name", Types::Char(10)));
        columns.push(Column::new("Age", Types::Int));

        let db = Database::create(&name, DatabaseConfig::new(&path)).unwrap();
        let table = Table::create("test_table1", 0, columns, &db).unwrap();

        assert!(!metadata("/tmp/test1/test_db3/test_table1.tbl").unwrap().is_dir());
    }

    #[test]
    fn load_table() {
        let path = "/tmp/test1/";
        let name = "test_db4";

        let mut columns = Vec::<Column>::new();
        columns.push(Column::new("Name", Types::Char(10)));
        columns.push(Column::new("Age", Types::Int));

        let db2 = Database::create(&name, DatabaseConfig::new(&path));
        assert!(db2.is_ok());
        let db = db2.unwrap();
        let table3 = Table::create("test_table2", 34, columns, &db);
        assert!(table3.is_ok());
        let table = table3.unwrap();

       // assert!(!metadata("/tmp/test1/test_db3/test_table2.tbl").unwrap().is_dir());

        let table2 = Table::load("test_table2", &db).unwrap();

        assert_eq!(table.get_engine_id(), table2.get_engine_id());
        assert_eq!(&table.meta_data.columns, &table2.meta_data.columns);
    }

    #[test]
    fn table_offset() {
        let path = "/tmp/test1/";
        let name = "test_db5";

        let mut columns = Vec::<Column>::new();
        columns.push(Column::new("Name", Types::Char(10)));
        columns.push(Column::new("Age", Types::Int));

        let db = Database::create(&name, DatabaseConfig::new(&path)).unwrap();
        let table = Table::create("test_table1", 34, columns, &db).unwrap();

        assert_eq!(table.get_table_header_offset(), 42u32);

    }
}
<|endoftext|>


<commit_before>use std::io;
use std::net::{self, SocketAddr};

pub fn connect(_: SocketAddr) -> io::Result<net::TcpStream> {
    os_required!();
}

pub fn bind(_: SocketAddr) -> io::Result<net::TcpListener> {
    os_required!();
}
<commit_msg>Add sys::shell::tcp::accept<commit_after>use std::io;
use std::net::{self, SocketAddr};

pub fn connect(_: SocketAddr) -> io::Result<net::TcpStream> {
    os_required!();
}

pub fn bind(_: SocketAddr) -> io::Result<net::TcpListener> {
    os_required!();
}

pub fn accept(_: &net::TcpListener) -> io::Result<(net::TcpStream, SocketAddr)> {
    os_required!();
}
<|endoftext|>


<commit_before>use std::fmt;

use {Value, String, Integer, Float, Boolean, Datetime, Array, Table};

struct Printer<'a, 'b:'a> {
    output: &'a mut fmt::Formatter<'b>,
    stack: Vec<&'a str>,
}

impl fmt::Show for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            String(ref s) => {
                try!(write!(f, "\""));
                for ch in s.as_slice().chars() {
                    match ch {
                        '\u0008' => try!(write!(f, "\\b")),
                        '\u0009' => try!(write!(f, "\\t")),
                        '\u000a' => try!(write!(f, "\\n")),
                        '\u000c' => try!(write!(f, "\\f")),
                        '\u000d' => try!(write!(f, "\\r")),
                        '\u0022' => try!(write!(f, "\\\"")),
                        '\u005c' => try!(write!(f, "\\\\")),
                        ch => try!(write!(f, "{}", ch)),
                    }
                }
                write!(f, "\"")
            }
            Integer(i) => write!(f, "{}", i),
            Float(fp) => {
                try!(write!(f, "{}", fp));
                if fp % 1.0 == 0.0 { try!(write!(f, ".0")) }
                Ok(())
            }
            Boolean(b) => write!(f, "{}", b),
            Datetime(ref s) => write!(f, "{}", s),
            Array(ref a) => {
                match a.as_slice().head() {
                    Some(&Table(..)) => fail!("invalid toml array of tables"),
                    _ => {}
                }
                write!(f, "{}", a)
            }
            Table(ref t) => {
                let mut p = Printer { output: f, stack: Vec::new() };
                p.print(t)
            }
        }
    }
}

impl<'a, 'b> Printer<'a, 'b> {
    fn print(&mut self, table: &'a Table) -> fmt::Result {
        for (k, v) in table.iter() {
            match *v {
                Table(..) => continue,
                Array(ref a) => {
                    match a.as_slice().head() {
                        Some(&Table(..)) => continue,
                        _ => {}
                    }
                }
                _ => {}
            }
            try!(writeln!(self.output, "{} = {}", k, v));
        }
        for (k, v) in table.iter() {
            match *v {
                Table(ref inner) => {
                    self.stack.push(k.as_slice());
                    try!(writeln!(self.output, "\n[{}]",
                                  self.stack.connect(".")));
                    try!(self.print(inner));
                    self.stack.pop();
                }
                Array(ref inner) => {
                    match inner.as_slice().head() {
                        Some(&Table(..)) => {}
                        _ => continue
                    }
                    self.stack.push(k.as_slice());
                    for inner in inner.iter() {
                        try!(writeln!(self.output, "\n[[{}]]",
                                      self.stack.connect(".")));
                        match *inner {
                            Table(ref inner) => try!(self.print(inner)),
                            _ => fail!("non-heterogeneous toml array"),
                        }
                    }
                    self.stack.pop();
                }
                _ => {},
            }
        }
        Ok(())
    }
}

#[cfg(test)]
#[allow(warnings)]
mod tests {
    use {Value, String, Integer, Float, Boolean, Datetime, Array, Table};
    use std::collections::TreeMap;

    macro_rules! map( ($($k:expr: $v:expr),*) => ({
        let mut _m = TreeMap::new();
        $(_m.insert($k.to_string(), $v);)*
        _m
    }) )

    #[test]
    fn simple_show() {
        assert_eq!(String("foo".to_string()).to_string().as_slice(),
                   "\"foo\"")
        assert_eq!(Integer(10).to_string().as_slice(),
                   "10")
        assert_eq!(Float(10.0).to_string().as_slice(),
                   "10.0")
        assert_eq!(Float(2.4).to_string().as_slice(),
                   "2.4")
        assert_eq!(Boolean(true).to_string().as_slice(),
                   "true")
        assert_eq!(Datetime("test".to_string()).to_string().as_slice(),
                   "test")
        assert_eq!(Array(vec![]).to_string().as_slice(),
                   "[]")
        assert_eq!(Array(vec![Integer(1), Integer(2)]).to_string().as_slice(),
                   "[1, 2]")
    }

    #[test]
    fn table() {
        assert_eq!(Table(map! { }).to_string().as_slice(),
                   "")
        assert_eq!(Table(map! { "test": Integer(2) }).to_string().as_slice(),
                   "test = 2\n")
        assert_eq!(Table(map! {
                        "test": Integer(2),
                        "test2": Table(map! {
                            "test": String("wut".to_string())
                        })
                   }).to_string().as_slice(),
                   "test = 2\n\
                    \n\
                    [test2]\n\
                    test = \"wut\"\n")
        assert_eq!(Table(map! {
                        "test": Integer(2),
                        "test2": Table(map! {
                            "test": String("wut".to_string())
                        })
                   }).to_string().as_slice(),
                   "test = 2\n\
                    \n\
                    [test2]\n\
                    test = \"wut\"\n")
        assert_eq!(Table(map! {
                        "test": Integer(2),
                        "test2": Array(vec![Table(map! {
                            "test": String("wut".to_string())
                        })])
                   }).to_string().as_slice(),
                   "test = 2\n\
                    \n\
                    [[test2]]\n\
                    test = \"wut\"\n")
    }
}

<commit_msg>Update show to print an error instead of failing<commit_after>use std::fmt;

use {Value, String, Integer, Float, Boolean, Datetime, Array, Table};

struct Printer<'a, 'b:'a> {
    output: &'a mut fmt::Formatter<'b>,
    stack: Vec<&'a str>,
}

impl fmt::Show for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            String(ref s) => {
                try!(write!(f, "\""));
                for ch in s.as_slice().chars() {
                    match ch {
                        '\u0008' => try!(write!(f, "\\b")),
                        '\u0009' => try!(write!(f, "\\t")),
                        '\u000a' => try!(write!(f, "\\n")),
                        '\u000c' => try!(write!(f, "\\f")),
                        '\u000d' => try!(write!(f, "\\r")),
                        '\u0022' => try!(write!(f, "\\\"")),
                        '\u005c' => try!(write!(f, "\\\\")),
                        ch => try!(write!(f, "{}", ch)),
                    }
                }
                write!(f, "\"")
            }
            Integer(i) => write!(f, "{}", i),
            Float(fp) => {
                try!(write!(f, "{}", fp));
                if fp % 1.0 == 0.0 { try!(write!(f, ".0")) }
                Ok(())
            }
            Boolean(b) => write!(f, "{}", b),
            Datetime(ref s) => write!(f, "{}", s),
            Array(ref a) => {
                match a.as_slice().head() {
                   Some(&Table(..)) =>
                       try!(write!(f, "invalid toml array of tables")),
                   _ => {}
                }
                write!(f, "{}", a)
            }
            Table(ref t) => {
                let mut p = Printer { output: f, stack: Vec::new() };
                p.print(t)
            }
        }
    }
}

impl<'a, 'b> Printer<'a, 'b> {
    fn print(&mut self, table: &'a Table) -> fmt::Result {
        for (k, v) in table.iter() {
            match *v {
                Table(..) => continue,
                Array(ref a) => {
                    match a.as_slice().head() {
                        Some(&Table(..)) => continue,
                        _ => {}
                    }
                }
                _ => {}
            }
            try!(writeln!(self.output, "{} = {}", k, v));
        }
        for (k, v) in table.iter() {
            match *v {
                Table(ref inner) => {
                    self.stack.push(k.as_slice());
                    try!(writeln!(self.output, "\n[{}]",
                                  self.stack.connect(".")));
                    try!(self.print(inner));
                    self.stack.pop();
                }
                Array(ref inner) => {
                    match inner.as_slice().head() {
                        Some(&Table(..)) => {}
                        _ => continue
                    }
                    self.stack.push(k.as_slice());
                    for inner in inner.iter() {
                        try!(writeln!(self.output, "\n[[{}]]",
                                      self.stack.connect(".")));
                        match *inner {
                            Table(ref inner) => try!(self.print(inner)),
                            _ => fail!("non-heterogeneous toml array"),
                        }
                    }
                    self.stack.pop();
                }
                _ => {},
            }
        }
        Ok(())
    }
}

#[cfg(test)]
#[allow(warnings)]
mod tests {
    use {Value, String, Integer, Float, Boolean, Datetime, Array, Table};
    use std::collections::TreeMap;

    macro_rules! map( ($($k:expr: $v:expr),*) => ({
        let mut _m = TreeMap::new();
        $(_m.insert($k.to_string(), $v);)*
        _m
    }) )

    #[test]
    fn simple_show() {
        assert_eq!(String("foo".to_string()).to_string().as_slice(),
                   "\"foo\"")
        assert_eq!(Integer(10).to_string().as_slice(),
                   "10")
        assert_eq!(Float(10.0).to_string().as_slice(),
                   "10.0")
        assert_eq!(Float(2.4).to_string().as_slice(),
                   "2.4")
        assert_eq!(Boolean(true).to_string().as_slice(),
                   "true")
        assert_eq!(Datetime("test".to_string()).to_string().as_slice(),
                   "test")
        assert_eq!(Array(vec![]).to_string().as_slice(),
                   "[]")
        assert_eq!(Array(vec![Integer(1), Integer(2)]).to_string().as_slice(),
                   "[1, 2]")
    }

    #[test]
    fn table() {
        assert_eq!(Table(map! { }).to_string().as_slice(),
                   "")
        assert_eq!(Table(map! { "test": Integer(2) }).to_string().as_slice(),
                   "test = 2\n")
        assert_eq!(Table(map! {
                        "test": Integer(2),
                        "test2": Table(map! {
                            "test": String("wut".to_string())
                        })
                   }).to_string().as_slice(),
                   "test = 2\n\
                    \n\
                    [test2]\n\
                    test = \"wut\"\n")
        assert_eq!(Table(map! {
                        "test": Integer(2),
                        "test2": Table(map! {
                            "test": String("wut".to_string())
                        })
                   }).to_string().as_slice(),
                   "test = 2\n\
                    \n\
                    [test2]\n\
                    test = \"wut\"\n")
        assert_eq!(Table(map! {
                        "test": Integer(2),
                        "test2": Array(vec![Table(map! {
                            "test": String("wut".to_string())
                        })])
                   }).to_string().as_slice(),
                   "test = 2\n\
                    \n\
                    [[test2]]\n\
                    test = \"wut\"\n")
    }
}
<|endoftext|>


<commit_before>// while a WIP
#![allow(unused_variables)]
use rutorch::*;
use std::ops::{Index, IndexMut};
use std::convert::From;
use std::cmp::max;
use std::hash::{Hash, Hasher};
use serde::{Serialize, Deserialize, Serializer, Deserializer};

use storage::*;
use ::*;
pub use tensor::tensor_ops::*;
use rand;
use {Ixs, RcMut};

pub enum TensorType {
    Float,
    Double,
    Byte,
    Char,
    Short,
    Int,
    Long,
}

#[derive(Hash, Serialize, Deserialize)]
pub enum TensorKind {
    FloatTensor(Tensor<f32>),
    LongTensor(Tensor<i64>),
}
pub enum NumKind {
    Float(f32),
    Double(f64),
    Long(i64),
}

impl NumKind {
    pub fn intof32(&self) -> f32 {
        use self::NumKind::{Float, Double, Long};
        match *self {
            Float(v) => v,
            Double(v) => unimplemented!(),
            Long(v) => unimplemented!(),
        }
    }
    pub fn intoi64(&self) -> i64 {
        use self::NumKind::{Float, Double, Long};
        match *self {
            Float(v) => unimplemented!(),
            Double(v) => unimplemented!(),
            Long(v) => v,
        }
    }
}

impl<T: Copy> From<T> for NumKind {
    #[allow(unused_variables)]
    default fn from(input: T) -> Self {
        unreachable!()
    }
}
impl From<f32> for NumKind {
    fn from(input: f32) -> Self {
        NumKind::Float(input)
    }
}
impl From<f64> for NumKind {
    fn from(input: f64) -> Self {
        NumKind::Double(input)
    }
}
impl From<i64> for NumKind {
    fn from(input: i64) -> Self {
        NumKind::Long(input)
    }
}

pub type TensorList<T> = Vec<Tensor<T>>;
pub type TensorKindList = Vec<TensorKind>;
pub type OptTensorKindList = Vec<Option<TensorKind>>;
pub type RefTensorList<'a, T> = Vec<&'a mut Tensor<T>>;
pub type RefTensorKindList<'a> = Vec<&'a TensorKind>;
pub type TensorId = usize;

impl TensorKind {
    pub fn backend(&self) -> Box<nn::BackendIntf> {
        unimplemented!()
    }
    pub fn inner(&self) -> *mut ::std::os::raw::c_void {
        unimplemented!()
    }
}

impl Index<usize> for TensorKind {
    type Output = NumKind;
    fn index(&self, idx: usize) -> &Self::Output {
        unimplemented!()
    }
}
impl PartialEq for TensorKind {
    fn eq(&self, other: &Self) -> bool {
        use self::TensorKind::{FloatTensor, LongTensor};
        match (self, other) {
            (&FloatTensor(ref t1), &FloatTensor(ref t2)) => t1.id() == t2.id(),
            (&LongTensor(ref t1), &LongTensor(ref t2)) => t1.id() == t2.id(),
            _ => false,
        }
    }
}
impl Eq for TensorKind {}
impl Clone for TensorKind {
    fn clone(&self) -> Self {
        use self::TensorKind::{FloatTensor, LongTensor};
        match *self {
            FloatTensor(ref t) => FloatTensor(t.clone()),
            LongTensor(ref t) => LongTensor(t.clone()),
        }
    }
}

impl<T> From<Tensor<T>> for TensorKind {
    #[allow(unused_variables)]
    default fn from(input: Tensor<T>) -> Self {
        unreachable!()
    }
}

impl From<Tensor<f32>> for TensorKind {
    fn from(input: Tensor<f32>) -> Self {
        TensorKind::FloatTensor(input)
    }
}

impl From<Tensor<i64>> for TensorKind {
    fn from(input: Tensor<i64>) -> Self {
        TensorKind::LongTensor(input)
    }
}

impl<T> From<TensorKind> for Tensor<T> {
    #[allow(unused_variables)]
    default fn from(input: TensorKind) -> Self {
        panic!("bad cast")
    }
}

impl<'a, T> From<&'a TensorKind> for &'a Tensor<T> {
    #[allow(unused_variables)]
    default fn from(input: &'a TensorKind) -> Self {
        panic!("bad cast")
    }
}

impl<'a> From<&'a TensorKind> for &'a Tensor<f32> {
    fn from(input: &'a TensorKind) -> Self {
        match *input {
            TensorKind::FloatTensor(ref t) => t,
            _ => unreachable!(),
        }
    }
}

impl<'a> From<&'a TensorKind> for &'a Tensor<i64> {
    fn from(input: &'a TensorKind) -> Self {
        match *input {
            TensorKind::LongTensor(ref t) => t,
            _ => unreachable!(),
        }
    }
}

impl From<TensorKind> for Tensor<f32> {
    fn from(input: TensorKind) -> Self {
        match input {
            TensorKind::FloatTensor(v) => v,
            _ => unimplemented!(),
        }
    }
}

impl From<TensorKind> for Tensor<i64> {
    fn from(input: TensorKind) -> Self {
        match input {
            TensorKind::LongTensor(v) => v,
            _ => unimplemented!(),
        }
    }
}

pub struct Tensor<T> {
    pub value: RcMut<TensorImpl<T, Output = T>>,
}

impl<T> Serialize for Tensor<T> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        unimplemented!()
    }
}
impl<'de, T> Deserialize<'de> for Tensor<T> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer<'de>
    {
        unimplemented!()
    }
}

impl<T: Copy> Hash for Tensor<T> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.id().hash(state)
    }
}

impl<T: Copy> Index<usize> for Tensor<T> {
    type Output = T;
    fn index(&self, idx: usize) -> &Self::Output {

        //        self.value.borrow_mut().index(idx as isize)
        unimplemented!()
    }
}

impl<T: Copy> Index<i32> for Tensor<T> {
    type Output = T;
    fn index(&self, idx: i32) -> &Self::Output {

        //        self.value.borrow_mut().index(idx as isize)
        unimplemented!()
    }
}

pub trait New<D, T> {
    fn new(args: D) -> T;
}
pub trait NewSelf<D, T> {
    fn new(&self, args: D) -> T;
}

impl<T> NewSelf<usize, Tensor<T>> for Tensor<T> {
    fn new(&self, args: usize) -> Self {
        unimplemented!()
    }
}
impl<T> NewSelf<(), Tensor<T>> for Tensor<T> {
    fn new(&self, args: ()) -> Self {
        unimplemented!()
    }
}
impl<T> NewSelf<Vec<usize>, Tensor<T>> for Tensor<T> {
    fn new(&self, args: Vec<usize>) -> Self {
        unimplemented!()
    }
}
impl NewSelf<usize, TensorKind> for TensorKind {
    fn new(&self, args: usize) -> Self {
        unimplemented!()
    }
}
impl NewSelf<(), TensorKind> for TensorKind {
    fn new(&self, args: ()) -> Self {
        unimplemented!()
    }
}
impl NewSelf<Vec<usize>, TensorKind> for TensorKind {
    fn new(&self, args: Vec<usize>) -> Self {
        unimplemented!()
    }
}
impl NewSelf<[usize; 2], TensorKind> for TensorKind {
    fn new(&self, args: [usize; 2]) -> Self {
        unimplemented!()
    }
}

impl<T> Tensor<T> {
    pub fn len(&self) -> usize {
        unimplemented!()
    }
    pub fn s(&self, dim: usize) -> Self {
        unimplemented!()
    }
}

impl<T> Default for Tensor<T> {
    fn default() -> Self {
        unimplemented!()
    }
}

impl<T> Clone for Tensor<T> {
    fn clone(&self) -> Self {
        Tensor { value: self.value.clone() }
    }
}

impl<T: Copy> Index<isize> for Tensor<T> {
    type Output = T;

    fn index(&self, idx: isize) -> &Self::Output {
        unimplemented!()
    }
}

type RefTI<T> = RcMut<TensorImpl<T, Output = T>>;
pub type TIArg<T> = TensorImpl<T, Output = T>;
pub trait TensorImpl<T>: Index<Ixs, Output = T> {
    //fn view<'a>(&self, dims: &[i32]) -> Tensor<'a>;
    fn new(&self) -> RefTI<T>;
    fn add(&self, value: T, output: &TIArg<T>);
    fn addt(&self, value: T, rhs: &TIArg<T>, output: &TIArg<T>);
    fn inner(&self) -> *mut ::std::os::raw::c_void;
}

impl TensorImpl<f32> for FloatTensor {
    fn new(&self) -> RefTI<f32> {
        // XXX place holder implementation
        RcMutNew(FloatTensor::new())
    }
    fn add(&self, value: f32, output: &TIArg<f32>) {
        let out = typecast!(output.inner(), THFloatTensor);
        unsafe {
            THFloatTensor_add(out, self.t, value);
        };
    }
    fn inner(&self) -> *mut ::std::os::raw::c_void {
        self.t as *mut ::std::os::raw::c_void
    }
    fn addt(&self, value: f32, rhs: &TIArg<f32>, output: &TIArg<f32>) {
        let rhsp = typecast!(rhs.inner(), THFloatTensor);
    }
}

impl Index<isize> for FloatTensor {
    type Output = f32;
    fn index(&self, idx: isize) -> &Self::Output {
        unimplemented!()
    }
}

impl Serialize for FloatTensor {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        unimplemented!()
    }
}
impl<'de> Deserialize<'de> for FloatTensor {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer<'de>
    {
        unimplemented!()
    }
}

pub struct FloatTensor {
    t: *mut THFloatTensor,
    storage: FloatStorage,
    dims: Vec<isize>,
}

impl Default for FloatTensor {
    fn default() -> Self {
        FloatTensor::new()
    }
}

impl FloatTensor {
    pub fn new() -> Self {
        unsafe {
            FloatTensor {
                t: THFloatTensor_new(),
                storage: FloatStorage::new(),
                dims: Vec::new(),
            }
        }
    }
    pub fn with_capacity(dims: &[isize]) -> Self {
        let size = dims.iter().product();
        let storage = FloatStorage::with_capacity(size);
        let strides = vec![1; dims.len()];
        let mut t = THFloatTensor {
            size: dims.clone().as_ptr() as *mut ::std::os::raw::c_long,
            stride: strides.as_ptr() as *mut ::std::os::raw::c_long,
            nDimension: dims.len() as i32,
            storage: storage.t,
            storageOffset: 0,
            refcount: 1,
            flag: TH_TENSOR_REFCOUNTED as i8,
        };
        FloatTensor {
            t: &mut t,
            storage: storage,
            dims: Vec::from(dims),
        }
    }
    pub fn randn(dims: &[isize]) -> Self {
        /* XXX */
        let mut t = FloatTensor::with_capacity(dims);
        for x in t.storage.iter_mut() {
            *x = rand::random::<f32>()
        }
        t
    }
}

impl<'a> Index<&'a [isize]> for FloatTensor {
    type Output = f32;

    fn index(&self, idx: &'a [isize]) -> &Self::Output {
        let mut index: isize = 0;
        let lastidx = max(0, idx.len() as isize - 1) as usize;
        if idx.len() != self.dims.len() {
            panic!("bad dimlen")
        }
        for i in 0..lastidx {
            if idx[i] >= self.dims[i] {
                panic!("bad dimlen")
            }
            index += idx[i] * self.dims[i]
        }
        if idx[lastidx] >= self.dims[lastidx] {
            panic!("bad dimlen")
        }
        index += idx[lastidx];
        &self.storage[index]
    }
}

impl<'a> IndexMut<&'a [isize]> for FloatTensor {
    fn index_mut(&mut self, idx: &'a [isize]) -> &mut Self::Output {
        let mut index: isize = 0;
        let lastidx = max(0, idx.len() as isize - 1) as usize;
        if idx.len() != self.dims.len() {
            panic!("bad dimlen")
        }
        for i in 0..lastidx {
            if idx[i] >= self.dims[i] {
                panic!("bad dimlen")
            }
            index += idx[i] * self.dims[i]
        }
        if idx[lastidx] >= self.dims[lastidx] {
            panic!("bad dimlen")
        }
        index += idx[lastidx];
        &mut self.storage[index]
    }
}

pub fn make_vec(val: usize, count: usize) -> Vec<usize> {
    let mut vec = Vec::new();
    for _ in 0..count {
        vec.push(val)
    }
    vec
}
<commit_msg>add len() and s() to TensorKind<commit_after>// while a WIP
#![allow(unused_variables)]
use rutorch::*;
use std::ops::{Index, IndexMut};
use std::convert::From;
use std::cmp::max;
use std::hash::{Hash, Hasher};
use serde::{Serialize, Deserialize, Serializer, Deserializer};

use storage::*;
use ::*;
pub use tensor::tensor_ops::*;
use rand;
use {Ixs, RcMut};

pub enum TensorType {
    Float,
    Double,
    Byte,
    Char,
    Short,
    Int,
    Long,
}

#[derive(Hash, Serialize, Deserialize)]
pub enum TensorKind {
    FloatTensor(Tensor<f32>),
    LongTensor(Tensor<i64>),
}
pub enum NumKind {
    Float(f32),
    Double(f64),
    Long(i64),
}

impl NumKind {
    pub fn intof32(&self) -> f32 {
        use self::NumKind::{Float, Double, Long};
        match *self {
            Float(v) => v,
            Double(v) => unimplemented!(),
            Long(v) => unimplemented!(),
        }
    }
    pub fn intoi64(&self) -> i64 {
        use self::NumKind::{Float, Double, Long};
        match *self {
            Float(v) => unimplemented!(),
            Double(v) => unimplemented!(),
            Long(v) => v,
        }
    }
}

impl<T: Copy> From<T> for NumKind {
    #[allow(unused_variables)]
    default fn from(input: T) -> Self {
        unreachable!()
    }
}
impl From<f32> for NumKind {
    fn from(input: f32) -> Self {
        NumKind::Float(input)
    }
}
impl From<f64> for NumKind {
    fn from(input: f64) -> Self {
        NumKind::Double(input)
    }
}
impl From<i64> for NumKind {
    fn from(input: i64) -> Self {
        NumKind::Long(input)
    }
}

pub type TensorList<T> = Vec<Tensor<T>>;
pub type TensorKindList = Vec<TensorKind>;
pub type OptTensorKindList = Vec<Option<TensorKind>>;
pub type RefTensorList<'a, T> = Vec<&'a mut Tensor<T>>;
pub type RefTensorKindList<'a> = Vec<&'a TensorKind>;
pub type TensorId = usize;

impl TensorKind {
    pub fn backend(&self) -> Box<nn::BackendIntf> {
        unimplemented!()
    }
    pub fn inner(&self) -> *mut ::std::os::raw::c_void {
        unimplemented!()
    }
    pub fn len(&self) -> usize {
        unimplemented!()
    }
    pub fn s(&self, dim: usize) -> Self {
        unimplemented!()
    }
}

impl Index<usize> for TensorKind {
    type Output = NumKind;
    fn index(&self, idx: usize) -> &Self::Output {
        unimplemented!()
    }
}
impl PartialEq for TensorKind {
    fn eq(&self, other: &Self) -> bool {
        use self::TensorKind::{FloatTensor, LongTensor};
        match (self, other) {
            (&FloatTensor(ref t1), &FloatTensor(ref t2)) => t1.id() == t2.id(),
            (&LongTensor(ref t1), &LongTensor(ref t2)) => t1.id() == t2.id(),
            _ => false,
        }
    }
}
impl Eq for TensorKind {}
impl Clone for TensorKind {
    fn clone(&self) -> Self {
        use self::TensorKind::{FloatTensor, LongTensor};
        match *self {
            FloatTensor(ref t) => FloatTensor(t.clone()),
            LongTensor(ref t) => LongTensor(t.clone()),
        }
    }
}

impl<T> From<Tensor<T>> for TensorKind {
    #[allow(unused_variables)]
    default fn from(input: Tensor<T>) -> Self {
        unreachable!()
    }
}

impl From<Tensor<f32>> for TensorKind {
    fn from(input: Tensor<f32>) -> Self {
        TensorKind::FloatTensor(input)
    }
}

impl From<Tensor<i64>> for TensorKind {
    fn from(input: Tensor<i64>) -> Self {
        TensorKind::LongTensor(input)
    }
}

impl<T> From<TensorKind> for Tensor<T> {
    #[allow(unused_variables)]
    default fn from(input: TensorKind) -> Self {
        panic!("bad cast")
    }
}

impl<'a, T> From<&'a TensorKind> for &'a Tensor<T> {
    #[allow(unused_variables)]
    default fn from(input: &'a TensorKind) -> Self {
        panic!("bad cast")
    }
}

impl<'a> From<&'a TensorKind> for &'a Tensor<f32> {
    fn from(input: &'a TensorKind) -> Self {
        match *input {
            TensorKind::FloatTensor(ref t) => t,
            _ => unreachable!(),
        }
    }
}

impl<'a> From<&'a TensorKind> for &'a Tensor<i64> {
    fn from(input: &'a TensorKind) -> Self {
        match *input {
            TensorKind::LongTensor(ref t) => t,
            _ => unreachable!(),
        }
    }
}

impl From<TensorKind> for Tensor<f32> {
    fn from(input: TensorKind) -> Self {
        match input {
            TensorKind::FloatTensor(v) => v,
            _ => unimplemented!(),
        }
    }
}

impl From<TensorKind> for Tensor<i64> {
    fn from(input: TensorKind) -> Self {
        match input {
            TensorKind::LongTensor(v) => v,
            _ => unimplemented!(),
        }
    }
}

pub struct Tensor<T> {
    pub value: RcMut<TensorImpl<T, Output = T>>,
}

impl<T> Serialize for Tensor<T> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        unimplemented!()
    }
}
impl<'de, T> Deserialize<'de> for Tensor<T> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer<'de>
    {
        unimplemented!()
    }
}

impl<T: Copy> Hash for Tensor<T> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.id().hash(state)
    }
}

impl<T: Copy> Index<usize> for Tensor<T> {
    type Output = T;
    fn index(&self, idx: usize) -> &Self::Output {

        //        self.value.borrow_mut().index(idx as isize)
        unimplemented!()
    }
}

impl<T: Copy> Index<i32> for Tensor<T> {
    type Output = T;
    fn index(&self, idx: i32) -> &Self::Output {

        //        self.value.borrow_mut().index(idx as isize)
        unimplemented!()
    }
}

pub trait New<D, T> {
    fn new(args: D) -> T;
}
pub trait NewSelf<D, T> {
    fn new(&self, args: D) -> T;
}

impl<T> NewSelf<usize, Tensor<T>> for Tensor<T> {
    fn new(&self, args: usize) -> Self {
        unimplemented!()
    }
}
impl<T> NewSelf<(), Tensor<T>> for Tensor<T> {
    fn new(&self, args: ()) -> Self {
        unimplemented!()
    }
}
impl<T> NewSelf<Vec<usize>, Tensor<T>> for Tensor<T> {
    fn new(&self, args: Vec<usize>) -> Self {
        unimplemented!()
    }
}
impl NewSelf<usize, TensorKind> for TensorKind {
    fn new(&self, args: usize) -> Self {
        unimplemented!()
    }
}
impl NewSelf<(), TensorKind> for TensorKind {
    fn new(&self, args: ()) -> Self {
        unimplemented!()
    }
}
impl NewSelf<Vec<usize>, TensorKind> for TensorKind {
    fn new(&self, args: Vec<usize>) -> Self {
        unimplemented!()
    }
}
impl NewSelf<[usize; 2], TensorKind> for TensorKind {
    fn new(&self, args: [usize; 2]) -> Self {
        unimplemented!()
    }
}

impl<T> Tensor<T> {
    pub fn len(&self) -> usize {
        unimplemented!()
    }
    pub fn s(&self, dim: usize) -> Self {
        unimplemented!()
    }
}

impl<T> Default for Tensor<T> {
    fn default() -> Self {
        unimplemented!()
    }
}

impl<T> Clone for Tensor<T> {
    fn clone(&self) -> Self {
        Tensor { value: self.value.clone() }
    }
}

impl<T: Copy> Index<isize> for Tensor<T> {
    type Output = T;

    fn index(&self, idx: isize) -> &Self::Output {
        unimplemented!()
    }
}

type RefTI<T> = RcMut<TensorImpl<T, Output = T>>;
pub type TIArg<T> = TensorImpl<T, Output = T>;
pub trait TensorImpl<T>: Index<Ixs, Output = T> {
    //fn view<'a>(&self, dims: &[i32]) -> Tensor<'a>;
    fn new(&self) -> RefTI<T>;
    fn add(&self, value: T, output: &TIArg<T>);
    fn addt(&self, value: T, rhs: &TIArg<T>, output: &TIArg<T>);
    fn inner(&self) -> *mut ::std::os::raw::c_void;
}

impl TensorImpl<f32> for FloatTensor {
    fn new(&self) -> RefTI<f32> {
        // XXX place holder implementation
        RcMutNew(FloatTensor::new())
    }
    fn add(&self, value: f32, output: &TIArg<f32>) {
        let out = typecast!(output.inner(), THFloatTensor);
        unsafe {
            THFloatTensor_add(out, self.t, value);
        };
    }
    fn inner(&self) -> *mut ::std::os::raw::c_void {
        self.t as *mut ::std::os::raw::c_void
    }
    fn addt(&self, value: f32, rhs: &TIArg<f32>, output: &TIArg<f32>) {
        let rhsp = typecast!(rhs.inner(), THFloatTensor);
    }
}

impl Index<isize> for FloatTensor {
    type Output = f32;
    fn index(&self, idx: isize) -> &Self::Output {
        unimplemented!()
    }
}

impl Serialize for FloatTensor {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        unimplemented!()
    }
}
impl<'de> Deserialize<'de> for FloatTensor {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer<'de>
    {
        unimplemented!()
    }
}

pub struct FloatTensor {
    t: *mut THFloatTensor,
    storage: FloatStorage,
    dims: Vec<isize>,
}

impl Default for FloatTensor {
    fn default() -> Self {
        FloatTensor::new()
    }
}

impl FloatTensor {
    pub fn new() -> Self {
        unsafe {
            FloatTensor {
                t: THFloatTensor_new(),
                storage: FloatStorage::new(),
                dims: Vec::new(),
            }
        }
    }
    pub fn with_capacity(dims: &[isize]) -> Self {
        let size = dims.iter().product();
        let storage = FloatStorage::with_capacity(size);
        let strides = vec![1; dims.len()];
        let mut t = THFloatTensor {
            size: dims.clone().as_ptr() as *mut ::std::os::raw::c_long,
            stride: strides.as_ptr() as *mut ::std::os::raw::c_long,
            nDimension: dims.len() as i32,
            storage: storage.t,
            storageOffset: 0,
            refcount: 1,
            flag: TH_TENSOR_REFCOUNTED as i8,
        };
        FloatTensor {
            t: &mut t,
            storage: storage,
            dims: Vec::from(dims),
        }
    }
    pub fn randn(dims: &[isize]) -> Self {
        /* XXX */
        let mut t = FloatTensor::with_capacity(dims);
        for x in t.storage.iter_mut() {
            *x = rand::random::<f32>()
        }
        t
    }
}

impl<'a> Index<&'a [isize]> for FloatTensor {
    type Output = f32;

    fn index(&self, idx: &'a [isize]) -> &Self::Output {
        let mut index: isize = 0;
        let lastidx = max(0, idx.len() as isize - 1) as usize;
        if idx.len() != self.dims.len() {
            panic!("bad dimlen")
        }
        for i in 0..lastidx {
            if idx[i] >= self.dims[i] {
                panic!("bad dimlen")
            }
            index += idx[i] * self.dims[i]
        }
        if idx[lastidx] >= self.dims[lastidx] {
            panic!("bad dimlen")
        }
        index += idx[lastidx];
        &self.storage[index]
    }
}

impl<'a> IndexMut<&'a [isize]> for FloatTensor {
    fn index_mut(&mut self, idx: &'a [isize]) -> &mut Self::Output {
        let mut index: isize = 0;
        let lastidx = max(0, idx.len() as isize - 1) as usize;
        if idx.len() != self.dims.len() {
            panic!("bad dimlen")
        }
        for i in 0..lastidx {
            if idx[i] >= self.dims[i] {
                panic!("bad dimlen")
            }
            index += idx[i] * self.dims[i]
        }
        if idx[lastidx] >= self.dims[lastidx] {
            panic!("bad dimlen")
        }
        index += idx[lastidx];
        &mut self.storage[index]
    }
}

pub fn make_vec(val: usize, count: usize) -> Vec<isize> {
    let mut vec = Vec::new();
    for _ in 0..count {
        vec.push(val as isize)
    }
    vec
}
<|endoftext|>


<commit_before>use std::io;

#[cfg(not(target_os = "redox"))]
use libc::c_ushort;

#[cfg(not(target_os = "redox"))]
#[repr(C)]
struct TermSize {
    row: c_ushort,
    col: c_ushort,
    _x: c_ushort,
    _y: c_ushort,
}

// Since attributes on non-item statements is not stable yet, we use a function.
#[cfg(not(target_os = "redox"))]
#[cfg(target_pointer_width = "64")]
fn tiocgwinsz() -> u64 {
    use termios::TIOCGWINSZ;
    TIOCGWINSZ as u64
}
#[cfg(not(target_os = "redox"))]
#[cfg(target_pointer_width = "32")]
fn tiocgwinsz() -> u32 {
    use termios::TIOCGWINSZ;
    TIOCGWINSZ as u32
}

/// Get the size of the terminal.
#[cfg(not(target_os = "redox"))]
pub fn terminal_size() -> io::Result<(usize, usize)> {
    use libc::ioctl;
    use libc::STDOUT_FILENO;

    use std::mem;
    unsafe {
        let mut size: TermSize = mem::zeroed();

        if ioctl(STDOUT_FILENO, tiocgwinsz(), &mut size as *mut _) == 0 {
            Ok((size.col as usize, size.row as usize))
        } else {
            Err(io::Error::new(io::ErrorKind::Other, "Unable to get the terminal size."))
        }
    }
}

/// Get the size of the terminal.
#[cfg(target_os = "redox")]
pub fn terminal_size() -> io::Result<(usize, usize)> {
    use std::env;

    let width = env::var("COLUMNS").unwrap_or(String::new()).parse::<usize>().unwrap_or(0);
    let height = env::var("LINES").unwrap_or(String::new()).parse::<usize>().unwrap_or(0);

    Ok((width, height))
}

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

    #[test]
    fn test_size() {
        assert!(terminal_size().is_ok());
    }
}
<commit_msg>Amend #15<commit_after>use std::io;

#[cfg(not(target_os = "redox"))]
use libc::c_ushort;

#[cfg(not(target_os = "redox"))]
#[repr(C)]
struct TermSize {
    row: c_ushort,
    col: c_ushort,
    _x: c_ushort,
    _y: c_ushort,
}

// Since attributes on non-item statements is not stable yet, we use a function.
#[cfg(not(target_os = "redox"))]
#[cfg(target_pointer_width = "64")]
fn tiocgwinsz() -> u64 {
    use termios::TIOCGWINSZ;
    TIOCGWINSZ as u64
}
#[cfg(not(target_os = "redox"))]
#[cfg(target_pointer_width = "32")]
fn tiocgwinsz() -> u32 {
    use termios::TIOCGWINSZ;
    TIOCGWINSZ as u32
}

/// Get the size of the terminal.
#[cfg(not(target_os = "redox"))]
pub fn terminal_size() -> io::Result<(usize, usize)> {
    use libc::ioctl;
    use libc::STDOUT_FILENO;

    use std::mem;
    unsafe {
        let mut size: TermSize = mem::zeroed();

        if ioctl(STDOUT_FILENO, tiocgwinsz(), &mut size as *mut _) == 0 {
            Ok((size.col as usize, size.row as usize))
        } else {
            Err(io::Error::new(io::ErrorKind::Other, "Unable to get the terminal size."))
        }
    }
}

/// Get the size of the terminal.
#[cfg(target_os = "redox")]
pub fn terminal_size() -> io::Result<(usize, usize)> {
    use std::env;

    let width = try!(env::var("COLUMNS").map_err(|x| io::Error::new(io::ErrorKind::NotFound, x))).parse().unwrap_or(0);
    let height = try!(env::var("LINES").map_err(|x| io::Error::new(io::ErrorKind::NotFound, x))).parse().unwrap_or(0);

    Ok((width, height))
}

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

    #[test]
    fn test_size() {
        assert!(terminal_size().is_ok());
    }
}
<|endoftext|>