<commit_before>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use hir::def_id::DefId;
use ty::{self, Ty, TypeFoldable, Substs, TyCtxt};
use ty::subst::{Kind, Subst};
use traits;
use syntax::abi::Abi;
use syntax::codemap::DUMMY_SP;
use util::ppaux;

use std::fmt;

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

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub enum InstanceDef<'tcx> {
    Item(DefId),
    Intrinsic(DefId),

    /// <fn() as FnTrait>::call_*
    /// def-id is FnTrait::call_*
    FnPtrShim(DefId, Ty<'tcx>),

    /// <Trait as Trait>::fn
    Virtual(DefId, usize),

    /// <[mut closure] as FnOnce>::call_once
    ClosureOnceShim { call_once: DefId },

    /// drop_in_place::<T>; None for empty drop glue.
    DropGlue(DefId, Option<Ty<'tcx>>),

    ///`<T as Clone>::clone` shim.
    CloneShim(DefId, Ty<'tcx>),
}

impl<'tcx> InstanceDef<'tcx> {
    #[inline]
    pub fn def_id(&self) -> DefId {
        match *self {
            InstanceDef::Item(def_id) |
            InstanceDef::FnPtrShim(def_id, _) |
            InstanceDef::Virtual(def_id, _) |
            InstanceDef::Intrinsic(def_id, ) |
            InstanceDef::ClosureOnceShim { call_once: def_id } |
            InstanceDef::DropGlue(def_id, _) |
            InstanceDef::CloneShim(def_id, _) => def_id
        }
    }

    #[inline]
    pub fn def_ty<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
        tcx.type_of(self.def_id())
    }

    #[inline]
    pub fn attrs<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::Attributes<'tcx> {
        tcx.get_attrs(self.def_id())
    }
}

impl<'tcx> fmt::Display for Instance<'tcx> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        ppaux::parameterized(f, self.substs, self.def_id(), &[])?;
        match self.def {
            InstanceDef::Item(_) => Ok(()),
            InstanceDef::Intrinsic(_) => {
                write!(f, " - intrinsic")
            }
            InstanceDef::Virtual(_, num) => {
                write!(f, " - shim(#{})", num)
            }
            InstanceDef::FnPtrShim(_, ty) => {
                write!(f, " - shim({:?})", ty)
            }
            InstanceDef::ClosureOnceShim { .. } => {
                write!(f, " - shim")
            }
            InstanceDef::DropGlue(_, ty) => {
                write!(f, " - shim({:?})", ty)
            }
            InstanceDef::CloneShim(_, ty) => {
                write!(f, " - shim({:?})", ty)
            }
        }
    }
}

impl<'a, 'b, 'tcx> Instance<'tcx> {
    pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>)
               -> Instance<'tcx> {
        assert!(substs.is_normalized_for_trans() && !substs.has_escaping_regions(),
                "substs of instance {:?} not normalized for trans: {:?}",
                def_id, substs);
        Instance { def: InstanceDef::Item(def_id), substs: substs }
    }

    pub fn mono(tcx: TyCtxt<'a, 'tcx, 'b>, def_id: DefId) -> Instance<'tcx> {
        Instance::new(def_id, tcx.global_tcx().empty_substs_for_def_id(def_id))
    }

    #[inline]
    pub fn def_id(&self) -> DefId {
        self.def.def_id()
    }

    /// The point where linking happens. Resolve a (def_id, substs)
    /// pair to an instance.
    pub fn resolve(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                   param_env: ty::ParamEnv<'tcx>,
                   def_id: DefId,
                   substs: &'tcx Substs<'tcx>) -> Option<Instance<'tcx>> {
        debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
        let result = if let Some(trait_def_id) = tcx.trait_of_item(def_id) {
            debug!(" => associated item, attempting to find impl");
            let item = tcx.associated_item(def_id);
            resolve_associated_item(tcx, &item, param_env, trait_def_id, substs)
        } else {
            let ty = tcx.type_of(def_id);
            let item_type = tcx.trans_apply_param_substs(substs, &ty);

            let def = match item_type.sty {
                ty::TyFnDef(..) if {
                    let f = item_type.fn_sig(tcx);
                    f.abi() == Abi::RustIntrinsic ||
                        f.abi() == Abi::PlatformIntrinsic
                } =>
                {
                    debug!(" => intrinsic");
                    ty::InstanceDef::Intrinsic(def_id)
                }
                _ => {
                    if Some(def_id) == tcx.lang_items().drop_in_place_fn() {
                        let ty = substs.type_at(0);
                        if ty.needs_drop(tcx, ty::ParamEnv::empty(traits::Reveal::All)) {
                            debug!(" => nontrivial drop glue");
                            ty::InstanceDef::DropGlue(def_id, Some(ty))
                        } else {
                            debug!(" => trivial drop glue");
                            ty::InstanceDef::DropGlue(def_id, None)
                        }
                    } else {
                        debug!(" => free item");
                        ty::InstanceDef::Item(def_id)
                    }
                }
            };
            Some(Instance {
                def: def,
                substs: substs
            })
        };
        debug!("resolve(def_id={:?}, substs={:?}) = {:?}", def_id, substs, result);
        result
    }
}

fn resolve_closure<'a, 'tcx>(
                   tcx: TyCtxt<'a, 'tcx, 'tcx>,
                   def_id: DefId,
                   substs: ty::ClosureSubsts<'tcx>,
                   requested_kind: ty::ClosureKind)
-> Instance<'tcx>
{
    let actual_kind = tcx.closure_kind(def_id);

    match needs_fn_once_adapter_shim(actual_kind, requested_kind) {
        Ok(true) => fn_once_adapter_instance(tcx, def_id, substs),
        _ => Instance::new(def_id, substs.substs)
    }
}

fn resolve_associated_item<'a, 'tcx>(
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
    trait_item: &ty::AssociatedItem,
    param_env: ty::ParamEnv<'tcx>,
    trait_id: DefId,
    rcvr_substs: &'tcx Substs<'tcx>
    ) -> Option<Instance<'tcx>> {
    let def_id = trait_item.def_id;
    debug!("resolve_associated_item(trait_item={:?}, \
                                    trait_id={:?}, \
           rcvr_substs={:?})",
           def_id, trait_id, rcvr_substs);

    let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
    let vtbl = tcx.trans_fulfill_obligation(DUMMY_SP, param_env, ty::Binder(trait_ref));

    // Now that we know which impl is being used, we can dispatch to
    // the actual function:
    match vtbl {
        traits::VtableImpl(impl_data) => {
            let (def_id, substs) = traits::find_associated_item(
                tcx, trait_item, rcvr_substs, &impl_data);
            let substs = tcx.erase_regions(&substs);
            Some(ty::Instance::new(def_id, substs))
        }
        traits::VtableGenerator(closure_data) => {
            Some(Instance {
                def: ty::InstanceDef::Item(closure_data.closure_def_id),
                substs: closure_data.substs.substs
            })
        }
        traits::VtableClosure(closure_data) => {
            let trait_closure_kind = tcx.lang_items().fn_trait_kind(trait_id).unwrap();
            Some(resolve_closure(tcx, closure_data.closure_def_id, closure_data.substs,
                                 trait_closure_kind))
        }
        traits::VtableFnPointer(ref data) => {
            Some(Instance {
                def: ty::InstanceDef::FnPtrShim(trait_item.def_id, data.fn_ty),
                substs: rcvr_substs
            })
        }
        traits::VtableObject(ref data) => {
            let index = tcx.get_vtable_index_of_object_method(data, def_id);
            Some(Instance {
                def: ty::InstanceDef::Virtual(def_id, index),
                substs: rcvr_substs
            })
        }
        traits::VtableBuiltin(..) if Some(trait_id) == tcx.lang_items().clone_trait() => {
            Some(Instance {
                def: ty::InstanceDef::CloneShim(def_id, trait_ref.self_ty()),
                substs: rcvr_substs
            })
        }
        _ => {
            None
        }
    }
}

fn needs_fn_once_adapter_shim<'a, 'tcx>(actual_closure_kind: ty::ClosureKind,
                              trait_closure_kind: ty::ClosureKind)
    -> Result<bool, ()>
{
    match (actual_closure_kind, trait_closure_kind) {
        (ty::ClosureKind::Fn, ty::ClosureKind::Fn) |
            (ty::ClosureKind::FnMut, ty::ClosureKind::FnMut) |
            (ty::ClosureKind::FnOnce, ty::ClosureKind::FnOnce) => {
                // No adapter needed.
                Ok(false)
            }
        (ty::ClosureKind::Fn, ty::ClosureKind::FnMut) => {
            // The closure fn `llfn` is a `fn(&self, ...)`.  We want a
            // `fn(&mut self, ...)`. In fact, at trans time, these are
            // basically the same thing, so we can just return llfn.
            Ok(false)
        }
        (ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) |
            (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
                // The closure fn `llfn` is a `fn(&self, ...)` or `fn(&mut
                // self, ...)`.  We want a `fn(self, ...)`. We can produce
                // this by doing something like:
                //
                //     fn call_once(self, ...) { call_mut(&self, ...) }
                //     fn call_once(mut self, ...) { call_mut(&mut self, ...) }
                //
                // These are both the same at trans time.
                Ok(true)
            }
        _ => Err(()),
    }
}

fn fn_once_adapter_instance<'a, 'tcx>(
                            tcx: TyCtxt<'a, 'tcx, 'tcx>,
                            closure_did: DefId,
                            substs: ty::ClosureSubsts<'tcx>,
                            ) -> Instance<'tcx> {
    debug!("fn_once_adapter_shim({:?}, {:?})",
    closure_did,
    substs);
    let fn_once = tcx.lang_items().fn_once_trait().unwrap();
    let call_once = tcx.associated_items(fn_once)
        .find(|it| it.kind == ty::AssociatedKind::Method)
        .unwrap().def_id;
    let def = ty::InstanceDef::ClosureOnceShim { call_once };

    let self_ty = tcx.mk_closure_from_closure_substs(
        closure_did, substs);

    let sig = tcx.fn_sig(closure_did).subst(tcx, substs.substs);
    let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
    assert_eq!(sig.inputs().len(), 1);
    let substs = tcx.mk_substs([
                               Kind::from(self_ty),
                               Kind::from(sig.inputs()[0]),
    ].iter().cloned());

    debug!("fn_once_adapter_shim: self_ty={:?} sig={:?}", self_ty, sig);
    Instance { def, substs }
}
<commit_msg>improve documentation for resolve()<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use hir::def_id::DefId;
use ty::{self, Ty, TypeFoldable, Substs, TyCtxt};
use ty::subst::{Kind, Subst};
use traits;
use syntax::abi::Abi;
use syntax::codemap::DUMMY_SP;
use util::ppaux;

use std::fmt;

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

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub enum InstanceDef<'tcx> {
    Item(DefId),
    Intrinsic(DefId),

    /// <fn() as FnTrait>::call_*
    /// def-id is FnTrait::call_*
    FnPtrShim(DefId, Ty<'tcx>),

    /// <Trait as Trait>::fn
    Virtual(DefId, usize),

    /// <[mut closure] as FnOnce>::call_once
    ClosureOnceShim { call_once: DefId },

    /// drop_in_place::<T>; None for empty drop glue.
    DropGlue(DefId, Option<Ty<'tcx>>),

    ///`<T as Clone>::clone` shim.
    CloneShim(DefId, Ty<'tcx>),
}

impl<'tcx> InstanceDef<'tcx> {
    #[inline]
    pub fn def_id(&self) -> DefId {
        match *self {
            InstanceDef::Item(def_id) |
            InstanceDef::FnPtrShim(def_id, _) |
            InstanceDef::Virtual(def_id, _) |
            InstanceDef::Intrinsic(def_id, ) |
            InstanceDef::ClosureOnceShim { call_once: def_id } |
            InstanceDef::DropGlue(def_id, _) |
            InstanceDef::CloneShim(def_id, _) => def_id
        }
    }

    #[inline]
    pub fn def_ty<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
        tcx.type_of(self.def_id())
    }

    #[inline]
    pub fn attrs<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::Attributes<'tcx> {
        tcx.get_attrs(self.def_id())
    }
}

impl<'tcx> fmt::Display for Instance<'tcx> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        ppaux::parameterized(f, self.substs, self.def_id(), &[])?;
        match self.def {
            InstanceDef::Item(_) => Ok(()),
            InstanceDef::Intrinsic(_) => {
                write!(f, " - intrinsic")
            }
            InstanceDef::Virtual(_, num) => {
                write!(f, " - shim(#{})", num)
            }
            InstanceDef::FnPtrShim(_, ty) => {
                write!(f, " - shim({:?})", ty)
            }
            InstanceDef::ClosureOnceShim { .. } => {
                write!(f, " - shim")
            }
            InstanceDef::DropGlue(_, ty) => {
                write!(f, " - shim({:?})", ty)
            }
            InstanceDef::CloneShim(_, ty) => {
                write!(f, " - shim({:?})", ty)
            }
        }
    }
}

impl<'a, 'b, 'tcx> Instance<'tcx> {
    pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>)
               -> Instance<'tcx> {
        assert!(substs.is_normalized_for_trans() && !substs.has_escaping_regions(),
                "substs of instance {:?} not normalized for trans: {:?}",
                def_id, substs);
        Instance { def: InstanceDef::Item(def_id), substs: substs }
    }

    pub fn mono(tcx: TyCtxt<'a, 'tcx, 'b>, def_id: DefId) -> Instance<'tcx> {
        Instance::new(def_id, tcx.global_tcx().empty_substs_for_def_id(def_id))
    }

    #[inline]
    pub fn def_id(&self) -> DefId {
        self.def.def_id()
    }

    /// Resolve a (def_id, substs) pair to an (optional) instance -- most commonly,
    /// this is used to find the precise code that will run for a trait method invocation,
    /// if known.
    ///
    /// Returns `None` if we cannot resolve `Instance` to a specific instance.
    /// For example, in a context like this,
    ///
    /// ```
    /// fn foo<T: Debug>(t: T) { ... }
    /// ```
    ///
    /// trying to resolve `Debug::fmt` applied to `T` will yield `None`, because we do not
    /// know what code ought to run. (Note that this setting is also affected by the
    /// `RevealMode` in the parameter environment.)
    ///
    /// Presuming that coherence and type-check have succeeded, if this method is invoked
    /// in a monomorphic context (i.e., like during trans), then it is guaranteed to return
    /// `Some`.
    pub fn resolve(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                   param_env: ty::ParamEnv<'tcx>,
                   def_id: DefId,
                   substs: &'tcx Substs<'tcx>) -> Option<Instance<'tcx>> {
        debug!("resolve(def_id={:?}, substs={:?})", def_id, substs);
        let result = if let Some(trait_def_id) = tcx.trait_of_item(def_id) {
            debug!(" => associated item, attempting to find impl");
            let item = tcx.associated_item(def_id);
            resolve_associated_item(tcx, &item, param_env, trait_def_id, substs)
        } else {
            let ty = tcx.type_of(def_id);
            let item_type = tcx.trans_apply_param_substs(substs, &ty);

            let def = match item_type.sty {
                ty::TyFnDef(..) if {
                    let f = item_type.fn_sig(tcx);
                    f.abi() == Abi::RustIntrinsic ||
                        f.abi() == Abi::PlatformIntrinsic
                } =>
                {
                    debug!(" => intrinsic");
                    ty::InstanceDef::Intrinsic(def_id)
                }
                _ => {
                    if Some(def_id) == tcx.lang_items().drop_in_place_fn() {
                        let ty = substs.type_at(0);
                        if ty.needs_drop(tcx, ty::ParamEnv::empty(traits::Reveal::All)) {
                            debug!(" => nontrivial drop glue");
                            ty::InstanceDef::DropGlue(def_id, Some(ty))
                        } else {
                            debug!(" => trivial drop glue");
                            ty::InstanceDef::DropGlue(def_id, None)
                        }
                    } else {
                        debug!(" => free item");
                        ty::InstanceDef::Item(def_id)
                    }
                }
            };
            Some(Instance {
                def: def,
                substs: substs
            })
        };
        debug!("resolve(def_id={:?}, substs={:?}) = {:?}", def_id, substs, result);
        result
    }
}

fn resolve_closure<'a, 'tcx>(
                   tcx: TyCtxt<'a, 'tcx, 'tcx>,
                   def_id: DefId,
                   substs: ty::ClosureSubsts<'tcx>,
                   requested_kind: ty::ClosureKind)
-> Instance<'tcx>
{
    let actual_kind = tcx.closure_kind(def_id);

    match needs_fn_once_adapter_shim(actual_kind, requested_kind) {
        Ok(true) => fn_once_adapter_instance(tcx, def_id, substs),
        _ => Instance::new(def_id, substs.substs)
    }
}

fn resolve_associated_item<'a, 'tcx>(
    tcx: TyCtxt<'a, 'tcx, 'tcx>,
    trait_item: &ty::AssociatedItem,
    param_env: ty::ParamEnv<'tcx>,
    trait_id: DefId,
    rcvr_substs: &'tcx Substs<'tcx>
    ) -> Option<Instance<'tcx>> {
    let def_id = trait_item.def_id;
    debug!("resolve_associated_item(trait_item={:?}, \
                                    trait_id={:?}, \
           rcvr_substs={:?})",
           def_id, trait_id, rcvr_substs);

    let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
    let vtbl = tcx.trans_fulfill_obligation(DUMMY_SP, param_env, ty::Binder(trait_ref));

    // Now that we know which impl is being used, we can dispatch to
    // the actual function:
    match vtbl {
        traits::VtableImpl(impl_data) => {
            let (def_id, substs) = traits::find_associated_item(
                tcx, trait_item, rcvr_substs, &impl_data);
            let substs = tcx.erase_regions(&substs);
            Some(ty::Instance::new(def_id, substs))
        }
        traits::VtableGenerator(closure_data) => {
            Some(Instance {
                def: ty::InstanceDef::Item(closure_data.closure_def_id),
                substs: closure_data.substs.substs
            })
        }
        traits::VtableClosure(closure_data) => {
            let trait_closure_kind = tcx.lang_items().fn_trait_kind(trait_id).unwrap();
            Some(resolve_closure(tcx, closure_data.closure_def_id, closure_data.substs,
                                 trait_closure_kind))
        }
        traits::VtableFnPointer(ref data) => {
            Some(Instance {
                def: ty::InstanceDef::FnPtrShim(trait_item.def_id, data.fn_ty),
                substs: rcvr_substs
            })
        }
        traits::VtableObject(ref data) => {
            let index = tcx.get_vtable_index_of_object_method(data, def_id);
            Some(Instance {
                def: ty::InstanceDef::Virtual(def_id, index),
                substs: rcvr_substs
            })
        }
        traits::VtableBuiltin(..) if Some(trait_id) == tcx.lang_items().clone_trait() => {
            Some(Instance {
                def: ty::InstanceDef::CloneShim(def_id, trait_ref.self_ty()),
                substs: rcvr_substs
            })
        }
        _ => {
            None
        }
    }
}

fn needs_fn_once_adapter_shim<'a, 'tcx>(actual_closure_kind: ty::ClosureKind,
                              trait_closure_kind: ty::ClosureKind)
    -> Result<bool, ()>
{
    match (actual_closure_kind, trait_closure_kind) {
        (ty::ClosureKind::Fn, ty::ClosureKind::Fn) |
            (ty::ClosureKind::FnMut, ty::ClosureKind::FnMut) |
            (ty::ClosureKind::FnOnce, ty::ClosureKind::FnOnce) => {
                // No adapter needed.
                Ok(false)
            }
        (ty::ClosureKind::Fn, ty::ClosureKind::FnMut) => {
            // The closure fn `llfn` is a `fn(&self, ...)`.  We want a
            // `fn(&mut self, ...)`. In fact, at trans time, these are
            // basically the same thing, so we can just return llfn.
            Ok(false)
        }
        (ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) |
            (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
                // The closure fn `llfn` is a `fn(&self, ...)` or `fn(&mut
                // self, ...)`.  We want a `fn(self, ...)`. We can produce
                // this by doing something like:
                //
                //     fn call_once(self, ...) { call_mut(&self, ...) }
                //     fn call_once(mut self, ...) { call_mut(&mut self, ...) }
                //
                // These are both the same at trans time.
                Ok(true)
            }
        _ => Err(()),
    }
}

fn fn_once_adapter_instance<'a, 'tcx>(
                            tcx: TyCtxt<'a, 'tcx, 'tcx>,
                            closure_did: DefId,
                            substs: ty::ClosureSubsts<'tcx>,
                            ) -> Instance<'tcx> {
    debug!("fn_once_adapter_shim({:?}, {:?})",
    closure_did,
    substs);
    let fn_once = tcx.lang_items().fn_once_trait().unwrap();
    let call_once = tcx.associated_items(fn_once)
        .find(|it| it.kind == ty::AssociatedKind::Method)
        .unwrap().def_id;
    let def = ty::InstanceDef::ClosureOnceShim { call_once };

    let self_ty = tcx.mk_closure_from_closure_substs(
        closure_did, substs);

    let sig = tcx.fn_sig(closure_did).subst(tcx, substs.substs);
    let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
    assert_eq!(sig.inputs().len(), 1);
    let substs = tcx.mk_substs([
                               Kind::from(self_ty),
                               Kind::from(sig.inputs()[0]),
    ].iter().cloned());

    debug!("fn_once_adapter_shim: self_ty={:?} sig={:?}", self_ty, sig);
    Instance { def, substs }
}
<|endoftext|>


<commit_before>//! Implements the game representation

use types::NumPlies;

use super::piece::Piece;
use super::color::{Color};
use super::square::{File,Square};
use super::board::{self,Board};
use super::castle::{self,CastlingData,Side};

/// A complete representation of a chess position.
#[derive(PartialEq, Eq, Clone, Show)]
pub struct Position {
    data: Board,
    side_to_move: Color,
    castling: CastlingData,
    en_passant: Option<File>,
    ply_count: NumPlies,
}
impl Position {
    pub fn new() -> Position {
        Position {
            data: Board::new(),
            side_to_move: Color::White,
            castling: CastlingData::new(),
            en_passant: None,
            ply_count: NumPlies(0),
        }
    }

    pub fn at(&self, s: Square) -> Option<Piece> {
        self.data.at(s)
    }
    pub fn is_piece_at(&self, p: Piece, s: Square) -> bool {
        self.data.is_piece_at(p,s)
    }
    pub fn is_empty_at(&self, s: Square) -> bool {
        self.data.is_empty_at(s)
    }
    pub fn is_color_at(&self, s: Square, c: Color) -> bool {
        self.data.is_color_at(s,c)
    }

    pub fn set_at(&mut self, s: Square, p: Piece) {
        self.data.set_at(s, p);
    }
    pub fn remove_at(&mut self, s: Square, p: Piece) {
        self.data.remove_at(s, p);
    }

    pub fn king_square(&self, c: Color) -> Square {
        self.data.king_square(c)
    }
    pub fn piece_iter(&self) -> board::Iter {
        self.data.iter()
    }

    pub fn side_to_move(&self) -> Color {
        self.side_to_move
    }
    pub fn set_side_to_move(&mut self, c: Color) {
        self.side_to_move = c;
    }
    pub fn swap_side_to_move(&mut self) {
        let c = self.side_to_move.invert();
        self.set_side_to_move(c);
    }

    pub fn can_castle(&self, side: Side, c: Color) -> bool {
        self.castling.get(side, c)
    }
    // Does not check for castling out of check, through check, or into check.
    pub fn can_castle_now(&self, side: Side, c: Color) -> bool {
        self.can_castle(side, c) &&
            castle::require_empty_squares(side, c).iter().all( |x| self.is_empty_at(*x) )
    }
    pub fn set_castle(&mut self, side:Side, c:Color, val: bool) {
        self.castling.set(side, c, val);
    }

    pub fn en_passant(&self) -> Option<File> {
        self.en_passant
    }
    pub fn set_en_passant(&mut self, val: Option<File>) {
        self.en_passant = val;
    }

    pub fn ply_count(&self) -> NumPlies {
        self.ply_count
    }
    pub fn set_ply_count(&mut self, val: NumPlies) {
        self.ply_count = val;
    }
}
<commit_msg>Split irreversible position data out of Position<commit_after>//! Implements the game representation

use types::NumPlies;

use super::piece::Piece;
use super::color::{Color};
use super::square::{File,Square};
use super::board::{self,Board};
use super::castle::{self,CastlingData,Side};

/// Data required to unmake moves
#[derive(PartialEq, Eq, Clone, Show)]
pub struct ExtraData {
    castling: CastlingData,
    en_passant: Option<File>,
    ply_count: NumPlies,
}

/// A complete representation of a chess position.
#[derive(PartialEq, Eq, Clone, Show)]
pub struct Position {
    data: Board,
    side_to_move: Color,
    extra_data: ExtraData,
}
impl Position {
    pub fn new() -> Position {
        Position {
            data: Board::new(),
            side_to_move: Color::White,
            extra_data: ExtraData {
                castling: CastlingData::new(),
                en_passant: None,
                ply_count: NumPlies(0),
            },
        }
    }

    pub fn at(&self, s: Square) -> Option<Piece> {
        self.data.at(s)
    }
    pub fn is_piece_at(&self, p: Piece, s: Square) -> bool {
        self.data.is_piece_at(p,s)
    }
    pub fn is_empty_at(&self, s: Square) -> bool {
        self.data.is_empty_at(s)
    }
    pub fn is_color_at(&self, s: Square, c: Color) -> bool {
        self.data.is_color_at(s,c)
    }

    pub fn set_at(&mut self, s: Square, p: Piece) {
        self.data.set_at(s, p);
    }
    pub fn remove_at(&mut self, s: Square, p: Piece) {
        self.data.remove_at(s, p);
    }

    pub fn king_square(&self, c: Color) -> Square {
        self.data.king_square(c)
    }
    pub fn piece_iter(&self) -> board::Iter {
        self.data.iter()
    }

    pub fn side_to_move(&self) -> Color {
        self.side_to_move
    }
    pub fn set_side_to_move(&mut self, c: Color) {
        self.side_to_move = c;
    }
    pub fn swap_side_to_move(&mut self) {
        let c = self.side_to_move.invert();
        self.set_side_to_move(c);
    }

    pub fn can_castle(&self, side: Side, c: Color) -> bool {
        self.extra_data.castling.get(side, c)
    }
    // Does not check for castling out of check, through check, or into check.
    pub fn can_castle_now(&self, side: Side, c: Color) -> bool {
        self.can_castle(side, c) &&
            castle::require_empty_squares(side, c).iter().all( |x| self.is_empty_at(*x) )
    }
    pub fn set_castle(&mut self, side:Side, c:Color, val: bool) {
        self.extra_data.castling.set(side, c, val);
    }

    pub fn en_passant(&self) -> Option<File> {
        self.extra_data.en_passant
    }
    pub fn set_en_passant(&mut self, val: Option<File>) {
        self.extra_data.en_passant = val;
    }

    pub fn ply_count(&self) -> NumPlies {
        self.extra_data.ply_count
    }
    pub fn set_ply_count(&mut self, val: NumPlies) {
        self.extra_data.ply_count = val;
    }

    pub fn extra_data(&self) -> &ExtraData {
        &self.extra_data
    }
    pub fn set_extra_data(&mut self, val: ExtraData) {
        self.extra_data = val;
    }
}

<|endoftext|>


<commit_before>use glob::glob;
use reqwest;
use reqwest::header::Authorization;
use serde_json;
use std;
use std::collections::HashMap;
use std::fs::File;
use std::io::prelude::*;
use structs::{CliError, Config, Member, PublicKey, Repo, Sector, SectorGroup, Team};

pub struct GithubClient {
    client: reqwest::Client,
    conf: Config,
}

impl GithubClient {
    pub fn new(config: &Config) -> GithubClient {
        if std::env::var("SSL_CERT_FILE").is_err() {
            std::env::set_var("SSL_CERT_FILE", &config.cert_path);
        }
        GithubClient { client: match config.proxy_url {
                           Some(ref proxy_url) => {
                               let p = reqwest::Proxy::all(proxy_url).unwrap();
                               reqwest::Client::builder().proxy(p).build().unwrap()
                           }
                           None => reqwest::Client::new(),
                       },
                       conf: config.clone(), }
    }

    fn get_cache_path(url: &str) -> std::path::PathBuf {
        let mut path = std::env::temp_dir();
        path.push("sectora-cache");
        path.push(url);
        path
    }

    fn load_content_from_cache(&self, url: &str) -> Result<(std::fs::Metadata, String), CliError> {
        let path = Self::get_cache_path(url);
        let metadata = std::fs::metadata(path.to_str().unwrap())?;
        let mut f = File::open(path.to_str().unwrap())?;
        let mut content = String::new();
        f.read_to_string(&mut content)?;
        Ok((metadata, content))
    }

    fn store_content_to_cache(&self, url: &str, content: &str) -> Result<(), CliError> {
        let path = Self::get_cache_path(url);
        std::fs::create_dir_all(path.parent().unwrap())?;
        let mut f = File::create(path.to_str().unwrap())?;
        f.write(content.as_bytes())?;
        Ok(())
    }

    fn get_content_from_url(&self, url: &str) -> Result<String, CliError> {
        let mut all_contents: Vec<serde_json::value::Value> = Vec::new();
        let mut page = 1;
        loop {
            let mut new_array = self.get_content_from_url_page(url, page)?;
            if new_array.is_empty() {
                break;
            }
            all_contents.append(&mut new_array);
            page += 1;
        }
        let content = serde_json::ser::to_string(&all_contents)?;
        self.store_content_to_cache(url, &content)?;
        Ok(content)
    }

    fn get_content_from_url_page(&self, url: &str, page: u64) -> Result<Vec<serde_json::value::Value>, CliError> {
        let token = String::from("token ") + &self.conf.token;
        let sep = if url.contains("?") { "&" } else { "?" };
        let url_p = format!("{}{}page={}", url, sep, page);
        let res = self.client.get(&url_p).header(Authorization(token)).send();
        let mut content = String::new();
        res?.read_to_string(&mut content)?;
        Ok(serde_json::from_str::<Vec<serde_json::value::Value>>(&content)?)
    }

    fn get_content(&self, url: &str) -> Result<String, CliError> {
        match self.load_content_from_cache(url) {
            Ok((metadata, cache_content)) => match std::time::SystemTime::now().duration_since(metadata.modified()?) {
                Ok(caching_duration) => {
                    if caching_duration.as_secs() > self.conf.cache_duration {
                        match self.get_content_from_url(url) {
                            Ok(content_from_url) => Ok(content_from_url),
                            Err(_) => Ok(cache_content),
                        }
                    } else {
                        Ok(cache_content)
                    }
                }
                Err(_) => Ok(cache_content),
            },
            Err(_) => self.get_content_from_url(url),
        }
    }

    #[allow(dead_code)]
    pub fn print_user_public_key(&self, user: &str) -> Result<(), CliError> {
        let keys = self.get_user_public_key(user)?;
        println!("{}", keys);
        Ok(())
    }

    fn get_user_public_key(&self, user: &str) -> Result<String, CliError> {
        let url = format!("{}/users/{}/keys", self.conf.endpoint, user);
        let content = self.get_content(&url)?;
        let keys = serde_json::from_str::<Vec<PublicKey>>(&content)?;
        Ok(keys.iter().map(|k| k.key.clone())
               .collect::<Vec<String>>()
               .join("\n"))
    }

    #[allow(dead_code)]
    pub fn check_pam(&self, user: &str) -> Result<bool, CliError> {
        let sectors = self.get_sectors();
        Ok(sectors.iter().any(|team| team.members.contains_key(user)))
    }

    pub fn get_sectors(&self) -> Vec<SectorGroup> {
        let mut sectors: Vec<SectorGroup> = self.get_teams_result().unwrap_or(Vec::new());
        sectors.append(&mut self.get_repos_result().unwrap_or(Vec::new()));
        sectors
    }

    fn get_teams_result(&self) -> Result<Vec<SectorGroup>, CliError> {
        let gh_teams = self.get_team_map()?;
        let mut teams = Vec::new();
        for team_conf in &self.conf.team {
            if let &Some(gh_team) = &gh_teams.get(&team_conf.name) {
                teams.push(SectorGroup { sector: Sector::from(gh_team.clone()),
                                         gid: team_conf.gid.clone(),
                                         group: team_conf.group.clone(),
                                         members: self.get_team_members(gh_team.id)?, });
            }
        }
        Ok(teams)
    }

    fn get_team_map(&self) -> Result<HashMap<String, Team>, CliError> {
        let url = format!("{}/orgs/{}/teams", self.conf.endpoint, self.conf.org);
        let content = self.get_content(&url)?;
        let teams = serde_json::from_str::<Vec<Team>>(&content)?;
        Ok(teams.iter().map(|t| (t.name.clone(), t.clone())).collect())
    }

    fn get_team_members(&self, mid: u64) -> Result<HashMap<String, Member>, CliError> {
        let url = format!("{}/teams/{}/members", self.conf.endpoint, mid);
        let content = self.get_content(&url)?;
        let members = serde_json::from_str::<Vec<Member>>(&content)?;
        Ok(members.iter()
                  .map(|m| (m.login.clone(), m.clone()))
                  .collect())
    }

    fn get_repos_result(&self) -> Result<Vec<SectorGroup>, CliError> {
        let gh_repos = self.get_repo_map()?;
        let mut repos = Vec::new();
        for repo_conf in &self.conf.repo {
            if let &Some(gh_repo) = &gh_repos.get(&repo_conf.name) {
                repos.push(SectorGroup { sector: Sector::from(gh_repo.clone()),
                                         gid: repo_conf.gid.clone(),
                                         group: repo_conf.group.clone(),
                                         members: self.get_repo_collaborators(&gh_repo.name)?, });
            }
        }
        Ok(repos)
    }

    fn get_repo_map(&self) -> Result<HashMap<String, Repo>, CliError> {
        let url = format!("{}/orgs/{}/repos?per_page=100",
                          self.conf.endpoint, self.conf.org);
        let content = self.get_content(&url)?;
        let repos = serde_json::from_str::<Vec<Repo>>(&content)?;
        Ok(repos.iter().map(|t| (t.name.clone(), t.clone())).collect())
    }

    fn get_repo_collaborators(&self, repo_name: &str) -> Result<HashMap<String, Member>, CliError> {
        let url = format!("{}/repos/{}/{}/collaborators?affiliation=outside",
                          self.conf.endpoint, self.conf.org, repo_name);
        let content = self.get_content(&url)?;
        let members = serde_json::from_str::<Vec<Member>>(&content)?;
        Ok(members.iter()
                  .map(|m| (m.login.clone(), m.clone()))
                  .collect())
    }

    #[allow(dead_code)]
    pub fn clear_all_caches(&self) -> Result<(), CliError> {
        let mut path = std::env::temp_dir();
        path.push("sectora-cache/**/*");
        for entry in glob(&path.to_str().unwrap()).unwrap() {
            match entry {
                Ok(path) => {
                    if path.is_file() {
                        std::fs::remove_file(path)?
                    }
                }
                Err(e) => println!("{:?}", e),
            }
        }
        Ok(())
    }
}
<commit_msg>Remove per_page parameter<commit_after>use glob::glob;
use reqwest;
use reqwest::header::Authorization;
use serde_json;
use std;
use std::collections::HashMap;
use std::fs::File;
use std::io::prelude::*;
use structs::{CliError, Config, Member, PublicKey, Repo, Sector, SectorGroup, Team};

pub struct GithubClient {
    client: reqwest::Client,
    conf: Config,
}

impl GithubClient {
    pub fn new(config: &Config) -> GithubClient {
        if std::env::var("SSL_CERT_FILE").is_err() {
            std::env::set_var("SSL_CERT_FILE", &config.cert_path);
        }
        GithubClient { client: match config.proxy_url {
                           Some(ref proxy_url) => {
                               let p = reqwest::Proxy::all(proxy_url).unwrap();
                               reqwest::Client::builder().proxy(p).build().unwrap()
                           }
                           None => reqwest::Client::new(),
                       },
                       conf: config.clone(), }
    }

    fn get_cache_path(url: &str) -> std::path::PathBuf {
        let mut path = std::env::temp_dir();
        path.push("sectora-cache");
        path.push(url);
        path
    }

    fn load_content_from_cache(&self, url: &str) -> Result<(std::fs::Metadata, String), CliError> {
        let path = Self::get_cache_path(url);
        let metadata = std::fs::metadata(path.to_str().unwrap())?;
        let mut f = File::open(path.to_str().unwrap())?;
        let mut content = String::new();
        f.read_to_string(&mut content)?;
        Ok((metadata, content))
    }

    fn store_content_to_cache(&self, url: &str, content: &str) -> Result<(), CliError> {
        let path = Self::get_cache_path(url);
        std::fs::create_dir_all(path.parent().unwrap())?;
        let mut f = File::create(path.to_str().unwrap())?;
        f.write(content.as_bytes())?;
        Ok(())
    }

    fn get_content_from_url(&self, url: &str) -> Result<String, CliError> {
        let mut all_contents: Vec<serde_json::value::Value> = Vec::new();
        let mut page = 1;
        loop {
            let mut new_array = self.get_content_from_url_page(url, page)?;
            if new_array.is_empty() {
                break;
            }
            all_contents.append(&mut new_array);
            page += 1;
        }
        let content = serde_json::ser::to_string(&all_contents)?;
        self.store_content_to_cache(url, &content)?;
        Ok(content)
    }

    fn get_content_from_url_page(&self, url: &str, page: u64) -> Result<Vec<serde_json::value::Value>, CliError> {
        let token = String::from("token ") + &self.conf.token;
        let sep = if url.contains("?") { "&" } else { "?" };
        let url_p = format!("{}{}page={}", url, sep, page);
        let res = self.client.get(&url_p).header(Authorization(token)).send();
        let mut content = String::new();
        res?.read_to_string(&mut content)?;
        Ok(serde_json::from_str::<Vec<serde_json::value::Value>>(&content)?)
    }

    fn get_content(&self, url: &str) -> Result<String, CliError> {
        match self.load_content_from_cache(url) {
            Ok((metadata, cache_content)) => match std::time::SystemTime::now().duration_since(metadata.modified()?) {
                Ok(caching_duration) => {
                    if caching_duration.as_secs() > self.conf.cache_duration {
                        match self.get_content_from_url(url) {
                            Ok(content_from_url) => Ok(content_from_url),
                            Err(_) => Ok(cache_content),
                        }
                    } else {
                        Ok(cache_content)
                    }
                }
                Err(_) => Ok(cache_content),
            },
            Err(_) => self.get_content_from_url(url),
        }
    }

    #[allow(dead_code)]
    pub fn print_user_public_key(&self, user: &str) -> Result<(), CliError> {
        let keys = self.get_user_public_key(user)?;
        println!("{}", keys);
        Ok(())
    }

    fn get_user_public_key(&self, user: &str) -> Result<String, CliError> {
        let url = format!("{}/users/{}/keys", self.conf.endpoint, user);
        let content = self.get_content(&url)?;
        let keys = serde_json::from_str::<Vec<PublicKey>>(&content)?;
        Ok(keys.iter().map(|k| k.key.clone())
               .collect::<Vec<String>>()
               .join("\n"))
    }

    #[allow(dead_code)]
    pub fn check_pam(&self, user: &str) -> Result<bool, CliError> {
        let sectors = self.get_sectors();
        Ok(sectors.iter().any(|team| team.members.contains_key(user)))
    }

    pub fn get_sectors(&self) -> Vec<SectorGroup> {
        let mut sectors: Vec<SectorGroup> = self.get_teams_result().unwrap_or(Vec::new());
        sectors.append(&mut self.get_repos_result().unwrap_or(Vec::new()));
        sectors
    }

    fn get_teams_result(&self) -> Result<Vec<SectorGroup>, CliError> {
        let gh_teams = self.get_team_map()?;
        let mut teams = Vec::new();
        for team_conf in &self.conf.team {
            if let &Some(gh_team) = &gh_teams.get(&team_conf.name) {
                teams.push(SectorGroup { sector: Sector::from(gh_team.clone()),
                                         gid: team_conf.gid.clone(),
                                         group: team_conf.group.clone(),
                                         members: self.get_team_members(gh_team.id)?, });
            }
        }
        Ok(teams)
    }

    fn get_team_map(&self) -> Result<HashMap<String, Team>, CliError> {
        let url = format!("{}/orgs/{}/teams", self.conf.endpoint, self.conf.org);
        let content = self.get_content(&url)?;
        let teams = serde_json::from_str::<Vec<Team>>(&content)?;
        Ok(teams.iter().map(|t| (t.name.clone(), t.clone())).collect())
    }

    fn get_team_members(&self, mid: u64) -> Result<HashMap<String, Member>, CliError> {
        let url = format!("{}/teams/{}/members", self.conf.endpoint, mid);
        let content = self.get_content(&url)?;
        let members = serde_json::from_str::<Vec<Member>>(&content)?;
        Ok(members.iter()
                  .map(|m| (m.login.clone(), m.clone()))
                  .collect())
    }

    fn get_repos_result(&self) -> Result<Vec<SectorGroup>, CliError> {
        let gh_repos = self.get_repo_map()?;
        let mut repos = Vec::new();
        for repo_conf in &self.conf.repo {
            if let &Some(gh_repo) = &gh_repos.get(&repo_conf.name) {
                repos.push(SectorGroup { sector: Sector::from(gh_repo.clone()),
                                         gid: repo_conf.gid.clone(),
                                         group: repo_conf.group.clone(),
                                         members: self.get_repo_collaborators(&gh_repo.name)?, });
            }
        }
        Ok(repos)
    }

    fn get_repo_map(&self) -> Result<HashMap<String, Repo>, CliError> {
        let url = format!("{}/orgs/{}/repos", self.conf.endpoint, self.conf.org);
        let content = self.get_content(&url)?;
        let repos = serde_json::from_str::<Vec<Repo>>(&content)?;
        Ok(repos.iter().map(|t| (t.name.clone(), t.clone())).collect())
    }

    fn get_repo_collaborators(&self, repo_name: &str) -> Result<HashMap<String, Member>, CliError> {
        let url = format!("{}/repos/{}/{}/collaborators?affiliation=outside",
                          self.conf.endpoint, self.conf.org, repo_name);
        let content = self.get_content(&url)?;
        let members = serde_json::from_str::<Vec<Member>>(&content)?;
        Ok(members.iter()
                  .map(|m| (m.login.clone(), m.clone()))
                  .collect())
    }

    #[allow(dead_code)]
    pub fn clear_all_caches(&self) -> Result<(), CliError> {
        let mut path = std::env::temp_dir();
        path.push("sectora-cache/**/*");
        for entry in glob(&path.to_str().unwrap()).unwrap() {
            match entry {
                Ok(path) => {
                    if path.is_file() {
                        std::fs::remove_file(path)?
                    }
                }
                Err(e) => println!("{:?}", e),
            }
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>
use std::collections::HashMap;
use super::super::*;

#[test]
fn test_trait() {
    let mut vars: HashMap<String, String> = HashMap::new();
    vars.insert("x".to_string(), "X".to_string());

    assert_eq!("hi {x}".format(&vars), "hi X");
    assert_eq!("hi {x}".to_string().format(&vars), "hi X");
}
<commit_msg>trait tests were broken somehow<commit_after>
use std::collections::HashMap;
use super::super::*;

#[test]
fn test_trait() {
    let mut vars: HashMap<String, String> = HashMap::new();
    vars.insert("x".to_string(), "X".to_string());

    assert_eq!("hi {x}".format(&vars).unwrap(), "hi X");
    assert_eq!("hi {x}".to_string().format(&vars).unwrap(), "hi X");
}
<|endoftext|>


<commit_before>use std::mem;
use std::ptr;
use std::fs::File;
use std::net::Ipv4Addr;
use std::ffi::{CStr, CString};
use std::io::{self, Read, Write};
use std::os::unix::io::{AsRawFd, FromRawFd};

use libc::{socket, close, SOCK_DGRAM, AF_INET, c_char, O_RDWR, open};

use tun::Tun;
use common::error::*;
use common::sockaddr::SockAddr;
use tun::configuration::{Configurable, Configuration};

use super::sys::*;

pub fn create(configuration: &Configuration) -> Result<Device> {
    Device::from_configuration(&configuration)
}

pub struct Device {
    name: String,
    tun: File,
    ctl: File,
}

impl Device {
    pub unsafe fn request(&self) -> ifreq {
        let mut req: ifreq = mem::zeroed();
        ptr::copy_nonoverlapping(self.name.as_ptr() as *const c_char,
                                 req.ifr_ifrn.ifrn_name.as_mut_ptr(),
                                 self.name.len());

        req
    }
}

impl Read for Device {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.tun.read(buf)
    }
}

impl Write for Device {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.tun.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.tun.flush()
    }
}

impl Tun for Device {
    fn name(&self) -> &str {
        &self.name
    }

    fn address(&self) -> Result<Ipv4Addr> {
        unsafe {
            let mut req = self.request();

            if siocgifaddr(self.ctl.as_raw_fd(), &mut req) < 0 {
                return Err(io::Error::last_os_error().into());
            }

            SockAddr::new(&req.ifr_ifru.ifru_addr).map(Into::into)
        }
    }
    fn set_address(&mut self, value: Ipv4Addr) -> Result<()> {
        unsafe {
            let mut req = self.request();
            req.ifr_ifru.ifru_addr = SockAddr::from(value).into();

            if siocsifaddr(self.ctl.as_raw_fd(), &req) < 0 {
                return Err(io::Error::last_os_error().into());
            }

            Ok(())
        }
    }

    fn broadcast(&self) -> Result<Ipv4Addr> {
        unsafe {
            let mut req = self.request();

            if siocgifbrdaddr(self.ctl.as_raw_fd(), &mut req) < 0 {
                return Err(io::Error::last_os_error().into());
            }

            SockAddr::new(&req.ifr_ifru.ifru_broadaddr).map(Into::into)
        }
    }
    fn set_broadcast(&mut self, value: Ipv4Addr) -> Result<()> {
        unsafe {
            let mut req = self.request();
            req.ifr_ifru.ifru_broadaddr = SockAddr::from(value).into();

            if siocsifbrdaddr(self.ctl.as_raw_fd(), &req) < 0 {
                return Err(io::Error::last_os_error().into());
            }

            Ok(())
        }
    }

    fn destination(&self) -> Result<Ipv4Addr> {
        unsafe {
            let mut req = self.request();

            if siocgifdstaddr(self.ctl.as_raw_fd(), &mut req) < 0 {
                return Err(io::Error::last_os_error().into());
            }

            SockAddr::new(&req.ifr_ifru.ifru_dstaddr).map(Into::into)
        }
    }
    fn set_destination(&mut self, value: Ipv4Addr) -> Result<()> {
        unsafe {
            let mut req = self.request();
            req.ifr_ifru.ifru_dstaddr = SockAddr::from(value).into();

            if siocsifdstaddr(self.ctl.as_raw_fd(), &req) < 0 {
                return Err(io::Error::last_os_error().into());
            }

            Ok(())
        }
    }

    fn netmask(&self) -> Result<Ipv4Addr> {
        unsafe {
            let mut req = self.request();

            if siocgifnetmask(self.ctl.as_raw_fd(), &mut req) < 0 {
                return Err(io::Error::last_os_error().into());
            }

            SockAddr::unchecked(&req.ifr_ifru.ifru_netmask).map(Into::into)
        }
    }
    fn set_netmask(&mut self, value: Ipv4Addr) -> Result<()> {
        unsafe {
            let mut req = self.request();
            req.ifr_ifru.ifru_netmask = SockAddr::from(value).into();

            if siocsifnetmask(self.ctl.as_raw_fd(), &req) < 0 {
                return Err(io::Error::last_os_error().into());
            }

            Ok(())
        }
    }

    fn mtu(&self) -> Result<i32> {
        unsafe {
            let mut req = self.request();

            if siocgifmtu(self.ctl.as_raw_fd(), &mut req) < 0 {
                return Err(io::Error::last_os_error().into());
            }

            Ok(req.ifr_ifru.ifru_mtu)
        }
    }
    fn set_mtu(&mut self, value: i32) -> Result<()> {
        unsafe {
            let mut req = self.request();
            req.ifr_ifru.ifru_mtu = value;

            if siocsifmtu(self.ctl.as_raw_fd(), &req) < 0 {
                return Err(io::Error::last_os_error().into());
            }

            Ok(())
        }
    }

    fn flags(&self) -> Result<i16> {
        unsafe {
            let mut req = self.request();

            if siocgifflags(self.ctl.as_raw_fd(), &mut req) < 0 {
                return Err(io::Error::last_os_error().into());
            }

            Ok(req.ifr_ifru.ifru_flags)
        }
    }
    fn set_flags(&mut self, value: i16) -> Result<()> {
        let origin_flags = self.flags()?;
        let mut value = value;

        unsafe {
            let mut req = self.request();

            req.ifr_ifru.ifru_flags = if value < 0 {
                value = -value;
                origin_flags & !value
            } else {
                origin_flags | value
            };

            if siocsifflags(self.ctl.as_raw_fd(), &req) < 0 {
                return Err(io::Error::last_os_error().into());
            }

            Ok(())
        }
    }

    fn set_enabled(&mut self, value: bool) -> Result<()> {
        let origin_flags = self.flags()?;

        if value {
            return self.set_flags(IFF_UP | IFF_RUNNING);
        }

        self.set_flags(-IFF_UP)
    }
}

impl Configurable for Device {
    fn from_configuration(configuration: &Configuration) -> Result<Self> {
        let device_name = match configuration.name.as_ref() {
            Some(name) => {
                let name = CString::new(name.clone())?;

                if name.as_bytes_with_nul().len() > IFNAMSIZ {
                    return Err(ErrorKind::NameTooLong.into());
                }

                Some(name)
            }

            None => None,
        };

        let mut device;
        unsafe {
            let tun = open(b"/dev/net/tun\0".as_ptr() as *const _, O_RDWR);
            if tun < 0 {
                return Err(io::Error::last_os_error().into());
            }

            let mut req: ifreq = mem::zeroed();

            if let Some(device_name) = device_name.as_ref() {
                ptr::copy_nonoverlapping(device_name.as_ptr() as *const c_char,
                                         req.ifr_ifrn.ifrn_name.as_mut_ptr(),
                                         device_name.as_bytes().len());
            }

            // TODO: add IFF_NO_PI flag?
            req.ifr_ifru.ifru_flags = IFF_TUN;

            if tunsetiff(tun, &mut req as *mut _ as *mut _) < 0 {
                close(tun);
                return Err(io::Error::last_os_error().into());
            }

            let ctl = socket(AF_INET, SOCK_DGRAM, 0);
            if ctl < 0 {
                return Err(io::Error::last_os_error().into());
            }

            device = Device {
                name: CStr::from_ptr(req.ifr_ifrn.ifrn_name.as_ptr()).to_string_lossy().into(),
                tun: File::from_raw_fd(tun),
                ctl: File::from_raw_fd(ctl),
            };
        }

        device.configure(configuration)?;
        Ok(device)
    }
    fn configure(&mut self, configuration: &Configuration) -> Result<()> {
        if let Some(ip) = configuration.address {
            self.set_address(ip)?;
        }

        if let Some(ip) = configuration.destination {
            self.set_destination(ip)?;
        }

        if let Some(ip) = configuration.broadcast {
            self.set_broadcast(ip)?;
        }

        if let Some(ip) = configuration.netmask {
            self.set_netmask(ip)?;
        }

        if let Some(mtu) = configuration.mtu {
            self.set_mtu(mtu)?;
        }

        self.set_enabled(configuration.enabled)?;

        Ok(())
    }
}
<commit_msg>remove unused variable<commit_after>use std::mem;
use std::ptr;
use std::fs::File;
use std::net::Ipv4Addr;
use std::ffi::{CStr, CString};
use std::io::{self, Read, Write};
use std::os::unix::io::{AsRawFd, FromRawFd};

use libc::{socket, close, SOCK_DGRAM, AF_INET, c_char, O_RDWR, open};

use tun::Tun;
use common::error::*;
use common::sockaddr::SockAddr;
use tun::configuration::{Configurable, Configuration};

use super::sys::*;

pub fn create(configuration: &Configuration) -> Result<Device> {
    Device::from_configuration(&configuration)
}

pub struct Device {
    name: String,
    tun: File,
    ctl: File,
}

impl Device {
    pub unsafe fn request(&self) -> ifreq {
        let mut req: ifreq = mem::zeroed();
        ptr::copy_nonoverlapping(self.name.as_ptr() as *const c_char,
                                 req.ifr_ifrn.ifrn_name.as_mut_ptr(),
                                 self.name.len());

        req
    }
}

impl Read for Device {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.tun.read(buf)
    }
}

impl Write for Device {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.tun.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.tun.flush()
    }
}

impl Tun for Device {
    fn name(&self) -> &str {
        &self.name
    }

    fn address(&self) -> Result<Ipv4Addr> {
        unsafe {
            let mut req = self.request();

            if siocgifaddr(self.ctl.as_raw_fd(), &mut req) < 0 {
                return Err(io::Error::last_os_error().into());
            }

            SockAddr::new(&req.ifr_ifru.ifru_addr).map(Into::into)
        }
    }
    fn set_address(&mut self, value: Ipv4Addr) -> Result<()> {
        unsafe {
            let mut req = self.request();
            req.ifr_ifru.ifru_addr = SockAddr::from(value).into();

            if siocsifaddr(self.ctl.as_raw_fd(), &req) < 0 {
                return Err(io::Error::last_os_error().into());
            }

            Ok(())
        }
    }

    fn broadcast(&self) -> Result<Ipv4Addr> {
        unsafe {
            let mut req = self.request();

            if siocgifbrdaddr(self.ctl.as_raw_fd(), &mut req) < 0 {
                return Err(io::Error::last_os_error().into());
            }

            SockAddr::new(&req.ifr_ifru.ifru_broadaddr).map(Into::into)
        }
    }
    fn set_broadcast(&mut self, value: Ipv4Addr) -> Result<()> {
        unsafe {
            let mut req = self.request();
            req.ifr_ifru.ifru_broadaddr = SockAddr::from(value).into();

            if siocsifbrdaddr(self.ctl.as_raw_fd(), &req) < 0 {
                return Err(io::Error::last_os_error().into());
            }

            Ok(())
        }
    }

    fn destination(&self) -> Result<Ipv4Addr> {
        unsafe {
            let mut req = self.request();

            if siocgifdstaddr(self.ctl.as_raw_fd(), &mut req) < 0 {
                return Err(io::Error::last_os_error().into());
            }

            SockAddr::new(&req.ifr_ifru.ifru_dstaddr).map(Into::into)
        }
    }
    fn set_destination(&mut self, value: Ipv4Addr) -> Result<()> {
        unsafe {
            let mut req = self.request();
            req.ifr_ifru.ifru_dstaddr = SockAddr::from(value).into();

            if siocsifdstaddr(self.ctl.as_raw_fd(), &req) < 0 {
                return Err(io::Error::last_os_error().into());
            }

            Ok(())
        }
    }

    fn netmask(&self) -> Result<Ipv4Addr> {
        unsafe {
            let mut req = self.request();

            if siocgifnetmask(self.ctl.as_raw_fd(), &mut req) < 0 {
                return Err(io::Error::last_os_error().into());
            }

            SockAddr::unchecked(&req.ifr_ifru.ifru_netmask).map(Into::into)
        }
    }
    fn set_netmask(&mut self, value: Ipv4Addr) -> Result<()> {
        unsafe {
            let mut req = self.request();
            req.ifr_ifru.ifru_netmask = SockAddr::from(value).into();

            if siocsifnetmask(self.ctl.as_raw_fd(), &req) < 0 {
                return Err(io::Error::last_os_error().into());
            }

            Ok(())
        }
    }

    fn mtu(&self) -> Result<i32> {
        unsafe {
            let mut req = self.request();

            if siocgifmtu(self.ctl.as_raw_fd(), &mut req) < 0 {
                return Err(io::Error::last_os_error().into());
            }

            Ok(req.ifr_ifru.ifru_mtu)
        }
    }
    fn set_mtu(&mut self, value: i32) -> Result<()> {
        unsafe {
            let mut req = self.request();
            req.ifr_ifru.ifru_mtu = value;

            if siocsifmtu(self.ctl.as_raw_fd(), &req) < 0 {
                return Err(io::Error::last_os_error().into());
            }

            Ok(())
        }
    }

    fn flags(&self) -> Result<i16> {
        unsafe {
            let mut req = self.request();

            if siocgifflags(self.ctl.as_raw_fd(), &mut req) < 0 {
                return Err(io::Error::last_os_error().into());
            }

            Ok(req.ifr_ifru.ifru_flags)
        }
    }
    fn set_flags(&mut self, value: i16) -> Result<()> {
        let origin_flags = self.flags()?;
        let mut value = value;

        unsafe {
            let mut req = self.request();

            req.ifr_ifru.ifru_flags = if value < 0 {
                value = -value;
                origin_flags & !value
            } else {
                origin_flags | value
            };

            if siocsifflags(self.ctl.as_raw_fd(), &req) < 0 {
                return Err(io::Error::last_os_error().into());
            }

            Ok(())
        }
    }

    fn set_enabled(&mut self, value: bool) -> Result<()> {
        if value {
            return self.set_flags(IFF_UP | IFF_RUNNING);
        }

        self.set_flags(-IFF_UP)
    }
}

impl Configurable for Device {
    fn from_configuration(configuration: &Configuration) -> Result<Self> {
        let device_name = match configuration.name.as_ref() {
            Some(name) => {
                let name = CString::new(name.clone())?;

                if name.as_bytes_with_nul().len() > IFNAMSIZ {
                    return Err(ErrorKind::NameTooLong.into());
                }

                Some(name)
            }

            None => None,
        };

        let mut device;
        unsafe {
            let tun = open(b"/dev/net/tun\0".as_ptr() as *const _, O_RDWR);
            if tun < 0 {
                return Err(io::Error::last_os_error().into());
            }

            let mut req: ifreq = mem::zeroed();

            if let Some(device_name) = device_name.as_ref() {
                ptr::copy_nonoverlapping(device_name.as_ptr() as *const c_char,
                                         req.ifr_ifrn.ifrn_name.as_mut_ptr(),
                                         device_name.as_bytes().len());
            }

            // TODO: add IFF_NO_PI flag?
            req.ifr_ifru.ifru_flags = IFF_TUN;

            if tunsetiff(tun, &mut req as *mut _ as *mut _) < 0 {
                close(tun);
                return Err(io::Error::last_os_error().into());
            }

            let ctl = socket(AF_INET, SOCK_DGRAM, 0);
            if ctl < 0 {
                return Err(io::Error::last_os_error().into());
            }

            device = Device {
                name: CStr::from_ptr(req.ifr_ifrn.ifrn_name.as_ptr()).to_string_lossy().into(),
                tun: File::from_raw_fd(tun),
                ctl: File::from_raw_fd(ctl),
            };
        }

        device.configure(configuration)?;
        Ok(device)
    }
    fn configure(&mut self, configuration: &Configuration) -> Result<()> {
        if let Some(ip) = configuration.address {
            self.set_address(ip)?;
        }

        if let Some(ip) = configuration.destination {
            self.set_destination(ip)?;
        }

        if let Some(ip) = configuration.broadcast {
            self.set_broadcast(ip)?;
        }

        if let Some(ip) = configuration.netmask {
            self.set_netmask(ip)?;
        }

        if let Some(mtu) = configuration.mtu {
            self.set_mtu(mtu)?;
        }

        self.set_enabled(configuration.enabled)?;

        Ok(())
    }
}
<|endoftext|>


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

use http::server::{Server, Config};
use http::server;

use super::ingot::Ingot;
use super::furnace::Furnace;
use super::response::Response;
use super::request::Request;

pub struct Iron<Rq, Rs, F> {
    pub furnace: F,
    ip: IpAddr,
    port: u16
}

impl<Rq, Rs, F: Clone> Clone for Iron<Rq, Rs, F> {
    fn clone(&self) -> Iron<Rq, Rs, F> {
        Iron {
            furnace: self.furnace.clone(),
            ip: self.ip.clone(),
            port: self.port
        }
    }
}

impl<'a, Rq: Request, Rs: Response<'a>, F: Furnace<'a, Rq, Rs>>
        Iron<Rq, Rs, F> {
    pub fn smelt<I: Ingot<'a, Rq, Rs>>(&mut self, ingot: I) {
        self.furnace.smelt(ingot);
    }

    pub fn listen(self) {
        self.serve_forever();
    }

    pub fn from_furnace<Rq, Rs, F>(furnace: F, ip: IpAddr, port: u16) -> Iron<Rq, Rs, F> {
        Iron {
            furnace: furnace,
            ip: ip,
            port: port
        }
    }
}

impl<'a,
     Rq: Request,
     Rs: Response<'a>,
     F: Furnace<'a, Rq, Rs>>
        Server for Iron<Rq, Rs, F> {
    fn get_config(&self) -> Config {
        Config { bind_address: SocketAddr { ip: self.ip, port: self.port } }
    }

    fn handle_request(&self, _req: &server::Request, _res: &mut server::ResponseWriter) {
        // coerce allllllll that
    }
}

<commit_msg>(feat) Added iron.new.<commit_after>use std::io::net::ip::{SocketAddr, IpAddr};

use http::server::{Server, Config};
use http::server;

use super::ingot::Ingot;
use super::furnace::Furnace;
use super::response::Response;
use super::request::Request;

pub struct Iron<Rq, Rs, F> {
    pub furnace: F,
    ip: IpAddr,
    port: u16
}

impl<Rq, Rs, F: Clone> Clone for Iron<Rq, Rs, F> {
    fn clone(&self) -> Iron<Rq, Rs, F> {
        Iron {
            furnace: self.furnace.clone(),
            ip: self.ip.clone(),
            port: self.port
        }
    }
}

impl<'a, Rq: Request, Rs: Response<'a>, F: Furnace<'a, Rq, Rs>>
        Iron<Rq, Rs, F> {
    pub fn smelt<I: Ingot<'a, Rq, Rs>>(&mut self, ingot: I) {
        self.furnace.smelt(ingot);
    }

    pub fn listen(self) {
        self.serve_forever();
    }

    pub fn new<'a, Rq, Rs>(ip: IpAddr, port: u16) -> Iron<Rq, Rs, F> {
        let furnace = Furnace::new();
        Iron {
            furnace: furnace,
            ip: ip,
            port: port
        }
    }

    pub fn from_furnace<Rq, Rs, F>(furnace: F, ip: IpAddr, port: u16) -> Iron<Rq, Rs, F> {
        Iron {
            furnace: furnace,
            ip: ip,
            port: port
        }
    }
}

impl<'a,
     Rq: Request,
     Rs: Response<'a>,
     F: Furnace<'a, Rq, Rs>>
        Server for Iron<Rq, Rs, F> {
    fn get_config(&self) -> Config {
        Config { bind_address: SocketAddr { ip: self.ip, port: self.port } }
    }

    fn handle_request(&self, _req: &server::Request, _res: &mut server::ResponseWriter) {
        // coerce allllllll that
    }
}

<|endoftext|>


<commit_before>// This file is part of the uutils coreutils package.
//
// (c) Derek Chiang <derekchiang93@gmail.com>
// (c) Christopher Brown <ccbrown112@gmail.com>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.

#[macro_use]
extern crate uucore;

use clap::{crate_version, App, Arg};
use std::io::{self, Write};
use std::iter::Peekable;
use std::str::Chars;

static NAME: &str = "echo";
static USAGE: &str = "[OPTIONS]... [STRING]...";
static SUMMARY: &str = "display a line of text";
static AFTER_HELP: &str = r#"
 Echo the STRING(s) to standard output.

 If -e is in effect, the following sequences are recognized:

 \\\\      backslash
 \\a      alert (BEL)
 \\b      backspace
 \\c      produce no further output
 \\e      escape
 \\f      form feed
 \\n      new line
 \\r      carriage return
 \\t      horizontal tab
 \\v      vertical tab
 \\0NNN   byte with octal value NNN (1 to 3 digits)
 \\xHH    byte with hexadecimal value HH (1 to 2 digits)
"#;

mod options {
    pub static STRING: &str = "STRING";
    pub static NO_NEWLINE: &str = "no_newline";
    pub static ENABLE_BACKSLASH_ESCAPE: &str = "enable_backslash_escape";
    pub static DISABLE_BACKSLASH_ESCAPE: &str = "disable_backslash_escape";
}

fn parse_code(
    input: &mut Peekable<Chars>,
    base: u32,
    max_digits: u32,
    bits_per_digit: u32,
) -> Option<char> {
    let mut ret = 0x8000_0000;
    for _ in 0..max_digits {
        match input.peek().and_then(|c| c.to_digit(base)) {
            Some(n) => ret = (ret << bits_per_digit) | n,
            None => break,
        }
        input.next();
    }
    std::char::from_u32(ret)
}

fn print_escaped(input: &str, mut output: impl Write) -> io::Result<bool> {
    let mut should_stop = false;

    let mut buffer = ['\\'; 2];

    let mut iter = input.chars().peekable();
    while let Some(mut c) = iter.next() {
        let mut start = 1;

        if c == '\\' {
            if let Some(next) = iter.next() {
                c = match next {
                    '\\' => '\\',
                    'a' => '\x07',
                    'b' => '\x08',
                    'c' => {
                        should_stop = true;
                        break;
                    }
                    'e' => '\x1b',
                    'f' => '\x0c',
                    'n' => '\n',
                    'r' => '\r',
                    't' => '\t',
                    'v' => '\x0b',
                    'x' => parse_code(&mut iter, 16, 2, 4).unwrap_or_else(|| {
                        start = 0;
                        next
                    }),
                    '0' => parse_code(&mut iter, 8, 3, 3).unwrap_or_else(|| {
                        start = 0;
                        next
                    }),
                    _ => {
                        start = 0;
                        next
                    }
                };
            }
        }

        buffer[1] = c;

        // because printing char slices is apparently not available in the standard library
        for ch in &buffer[start..] {
            write!(output, "{}", ch)?;
        }
    }

    Ok(should_stop)
}

pub fn uumain(args: impl uucore::Args) -> i32 {
    let args = args.collect_str();

    let matches = App::new(executable!())
        .name(NAME)
        // TrailingVarArg specifies the final positional argument is a VarArg
        // and it doesn't attempts the parse any further args.
        // Final argument must have multiple(true) or the usage string equivalent.
        .setting(clap::AppSettings::TrailingVarArg)
        .setting(clap::AppSettings::AllowLeadingHyphen)
        .version(crate_version!())
        .usage(USAGE)
        .about(SUMMARY)
        .after_help(AFTER_HELP)
        .arg(
            Arg::with_name(options::NO_NEWLINE)
                .short("n")
                .help("do not output the trailing newline")
                .takes_value(false)
                .display_order(1),
        )
        .arg(
            Arg::with_name(options::ENABLE_BACKSLASH_ESCAPE)
                .short("e")
                .help("enable interpretation of backslash escapes")
                .takes_value(false)
                .display_order(2),
        )
        .arg(
            Arg::with_name(options::DISABLE_BACKSLASH_ESCAPE)
                .short("E")
                .help("disable interpretation of backslash escapes (default)")
                .takes_value(false)
                .display_order(3),
        )
        .arg(
            Arg::with_name(options::STRING)
                .hidden(true)
                .multiple(true)
                .allow_hyphen_values(true),
        )
        .get_matches_from(args);

    let no_newline = matches.is_present(options::NO_NEWLINE);
    let escaped = matches.is_present(options::ENABLE_BACKSLASH_ESCAPE);
    let values: Vec<String> = match matches.values_of(options::STRING) {
        Some(s) => s.map(|s| s.to_string()).collect(),
        None => vec!["".to_string()],
    };

    match execute(no_newline, escaped, values) {
        Ok(_) => 0,
        Err(f) => {
            show_error!("{}", f);
            1
        }
    }
}

fn execute(no_newline: bool, escaped: bool, free: Vec<String>) -> io::Result<()> {
    let stdout = io::stdout();
    let mut output = stdout.lock();

    for (i, input) in free.iter().enumerate() {
        if i > 0 {
            write!(output, " ")?;
        }
        if escaped {
            let should_stop = print_escaped(&input, &mut output)?;
            if should_stop {
                break;
            }
        } else {
            write!(output, "{}", input)?;
        }
    }

    if !no_newline {
        writeln!(output)?;
    }

    Ok(())
}
<commit_msg>echo: Some minor changes to options (#1960)<commit_after>// This file is part of the uutils coreutils package.
//
// (c) Derek Chiang <derekchiang93@gmail.com>
// (c) Christopher Brown <ccbrown112@gmail.com>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.

#[macro_use]
extern crate uucore;

use clap::{crate_version, App, Arg};
use std::io::{self, Write};
use std::iter::Peekable;
use std::str::Chars;

const NAME: &str = "echo";
const SUMMARY: &str = "display a line of text";
const USAGE: &str = "[OPTIONS]... [STRING]...";
const AFTER_HELP: &str = r#"
 Echo the STRING(s) to standard output.

 If -e is in effect, the following sequences are recognized:

 \\\\      backslash
 \\a      alert (BEL)
 \\b      backspace
 \\c      produce no further output
 \\e      escape
 \\f      form feed
 \\n      new line
 \\r      carriage return
 \\t      horizontal tab
 \\v      vertical tab
 \\0NNN   byte with octal value NNN (1 to 3 digits)
 \\xHH    byte with hexadecimal value HH (1 to 2 digits)
"#;

mod options {
    pub const STRING: &str = "STRING";
    pub const NO_NEWLINE: &str = "no_newline";
    pub const ENABLE_BACKSLASH_ESCAPE: &str = "enable_backslash_escape";
    pub const DISABLE_BACKSLASH_ESCAPE: &str = "disable_backslash_escape";
}

fn parse_code(
    input: &mut Peekable<Chars>,
    base: u32,
    max_digits: u32,
    bits_per_digit: u32,
) -> Option<char> {
    let mut ret = 0x8000_0000;
    for _ in 0..max_digits {
        match input.peek().and_then(|c| c.to_digit(base)) {
            Some(n) => ret = (ret << bits_per_digit) | n,
            None => break,
        }
        input.next();
    }
    std::char::from_u32(ret)
}

fn print_escaped(input: &str, mut output: impl Write) -> io::Result<bool> {
    let mut should_stop = false;

    let mut buffer = ['\\'; 2];

    let mut iter = input.chars().peekable();
    while let Some(mut c) = iter.next() {
        let mut start = 1;

        if c == '\\' {
            if let Some(next) = iter.next() {
                c = match next {
                    '\\' => '\\',
                    'a' => '\x07',
                    'b' => '\x08',
                    'c' => {
                        should_stop = true;
                        break;
                    }
                    'e' => '\x1b',
                    'f' => '\x0c',
                    'n' => '\n',
                    'r' => '\r',
                    't' => '\t',
                    'v' => '\x0b',
                    'x' => parse_code(&mut iter, 16, 2, 4).unwrap_or_else(|| {
                        start = 0;
                        next
                    }),
                    '0' => parse_code(&mut iter, 8, 3, 3).unwrap_or_else(|| {
                        start = 0;
                        next
                    }),
                    _ => {
                        start = 0;
                        next
                    }
                };
            }
        }

        buffer[1] = c;

        // because printing char slices is apparently not available in the standard library
        for ch in &buffer[start..] {
            write!(output, "{}", ch)?;
        }
    }

    Ok(should_stop)
}

pub fn uumain(args: impl uucore::Args) -> i32 {
    let matches = App::new(executable!())
        .name(NAME)
        // TrailingVarArg specifies the final positional argument is a VarArg
        // and it doesn't attempts the parse any further args.
        // Final argument must have multiple(true) or the usage string equivalent.
        .setting(clap::AppSettings::TrailingVarArg)
        .setting(clap::AppSettings::AllowLeadingHyphen)
        .version(crate_version!())
        .about(SUMMARY)
        .after_help(AFTER_HELP)
        .usage(USAGE)
        .arg(
            Arg::with_name(options::NO_NEWLINE)
                .short("n")
                .help("do not output the trailing newline")
                .takes_value(false)
                .display_order(1),
        )
        .arg(
            Arg::with_name(options::ENABLE_BACKSLASH_ESCAPE)
                .short("e")
                .help("enable interpretation of backslash escapes")
                .takes_value(false)
                .display_order(2),
        )
        .arg(
            Arg::with_name(options::DISABLE_BACKSLASH_ESCAPE)
                .short("E")
                .help("disable interpretation of backslash escapes (default)")
                .takes_value(false)
                .display_order(3),
        )
        .arg(
            Arg::with_name(options::STRING)
                .multiple(true)
                .allow_hyphen_values(true),
        )
        .get_matches_from(args);

    let no_newline = matches.is_present(options::NO_NEWLINE);
    let escaped = matches.is_present(options::ENABLE_BACKSLASH_ESCAPE);
    let values: Vec<String> = match matches.values_of(options::STRING) {
        Some(s) => s.map(|s| s.to_string()).collect(),
        None => vec!["".to_string()],
    };

    match execute(no_newline, escaped, values) {
        Ok(_) => 0,
        Err(f) => {
            show_error!("{}", f);
            1
        }
    }
}

fn execute(no_newline: bool, escaped: bool, free: Vec<String>) -> io::Result<()> {
    let stdout = io::stdout();
    let mut output = stdout.lock();

    for (i, input) in free.iter().enumerate() {
        if i > 0 {
            write!(output, " ")?;
        }
        if escaped {
            let should_stop = print_escaped(&input, &mut output)?;
            if should_stop {
                break;
            }
        } else {
            write!(output, "{}", input)?;
        }
    }

    if !no_newline {
        writeln!(output)?;
    }

    Ok(())
}
<|endoftext|>