<commit_before>extern crate shootr;

extern crate specs;
extern crate chrono;
extern crate serde_json;
extern crate websocket_server;

use self::specs::{DispatcherBuilder, World, Entity};
use self::chrono::prelude::*;
use self::websocket_server::{start as start_server, EventHandler, SendChannel, OwnedMessage};

use shootr::util::{read_env_var, elapsed_ms};
use shootr::model::comp::{Vel, Pos, Bounciness, Connect, Disconnect, Player, Ping};
use shootr::model::client::KeyState;
use shootr::model::game::{Vector, Id};
use shootr::system::*;
use shootr::bootstrap;

use std::sync::{Arc, RwLock};
use std::thread::sleep;
use std::time::Duration;
use std::collections::{HashMap, HashSet};
use std::net::SocketAddr;

fn main() {
    let port = read_env_var("CORE_PORT").parse::<u32>().expect("Specified port is not a valid number");
    start_server::<Handler>("localhost", port);
}

struct Handler {
    id_entity: RwLock<HashMap<Id, Entity>>,
    to_spawn: RwLock<HashMap<Id, SendChannel>>,
    to_despawn: RwLock<HashSet<Id>>,
    inputs: Arc<RwLock<HashMap<Id, Vec<KeyState>>>>,
}

impl Handler {
    fn prepare_world(&self, world: &mut World) {
        bootstrap::prepare_world(world);
        world.add_resource(self.inputs.clone());

        // Ball
        world
            .create_entity()
            .with(Vel::from(Vector { x: 15, y: 10 }))
            .with(Pos::from(Vector { x: 500, y: 500 }))
            .with(Bounciness {})
            .build();
    }

    fn handle_text(&self, id: Id, msg: &str) {
        if let Ok(key_state) = serde_json::from_str::<KeyState>(&msg) {
            let mut inputs = self.inputs.write().unwrap();
            let has_already_inputs = inputs.get(&id).is_some();
            if has_already_inputs {
                inputs.get_mut(&id).unwrap().push(key_state);
            } else {
                inputs.insert(id, vec![key_state]);
            }
        } else {
            println!("Client {}: Sent invalid message: {}", id, msg);
        }
    }

    fn register_spawns(&self, world: &mut World) {
        let mut id_entity = self.id_entity.write().unwrap();
        let mut to_spawn = self.to_spawn.write().unwrap();
        for (id, send_channel) in to_spawn.drain() {
            let entity = world
                .create_entity()
                .with(Connect {})
                .with(Player::new(id, send_channel))
                .build();
            id_entity.insert(id, entity.clone());
        }

        let mut to_despawn = self.to_despawn.write().unwrap();
        for id in to_despawn.drain() {
            let entity = id_entity.remove(&id).expect(
                "Tried to remove id that was not there",
            );
            world.write::<Disconnect>().insert(entity, Disconnect {});
        }
    }

    fn register_pings(&self, world: &mut World) {
        for (_, entity) in self.id_entity.read().unwrap().iter() {
            world.write::<Ping>().insert(entity.clone(), Ping {});
        }
    }
}

impl EventHandler for Handler {
    type Id = Id;

    fn new() -> Self {
        Handler {
            id_entity: RwLock::new(HashMap::new()),
            to_spawn: RwLock::new(HashMap::new()),
            to_despawn: RwLock::new(HashSet::new()),
            inputs: Arc::new(RwLock::new(HashMap::new())),
        }
    }
    fn main_loop(&self) {
        let mut world = World::new();
        self.prepare_world(&mut world);

        let mut updater = DispatcherBuilder::new()
            .add(InputHandler, "input_handler", &[])
            .add(Physics, "physics", &["input_handler"])
            .add(Bounce, "bounce", &["physics"])
            .add(Spawn, "spawn", &["physics", "bounce"])
            .build();
        let mut sender = DispatcherBuilder::new()
            .add(Sending, "sending", &[])
            .build();

        let mut lag: u64 = 0;
        let mut previous = Utc::now();
        let updates_per_sec = read_env_var("CORE_UPDATES_PER_SEC").parse::<u64>().expect(
            "Failed to parse environmental variable as integer",
        );
        let ms_per_update = 1000 / updates_per_sec;
        let mut ping_timer = 0;
        let ping_interval = 500;
        loop {
            let current = Utc::now();
            let elapsed = elapsed_ms(previous, current).expect("Time went backwards");
            previous = current;
            lag += elapsed;
            ping_timer += elapsed;

            self.register_spawns(&mut world);
            if ping_timer > ping_interval {
                self.register_pings(&mut world);
                ping_timer = 0;
            }

            while lag >= ms_per_update {
                updater.dispatch(&mut world.res);
                lag -= ms_per_update;
            }
            sender.dispatch(&mut world.res);
            world.maintain();

            sleep(Duration::from_millis(ms_per_update - lag));
        }
    }

    fn on_message(&self, id: Self::Id, msg: OwnedMessage) {
        match msg {
            OwnedMessage::Text(ref txt) => self.handle_text(id, txt),
            _ => {}
        };
    }
    fn on_connect(&self, _: SocketAddr, send_channel: SendChannel) -> Option<Self::Id> {
        let id = Id::new_v4();
        self.to_spawn.write().unwrap().insert(id, send_channel);
        Some(id)
    }
    fn on_disconnect(&self, id: Self::Id) {
        self.to_despawn.write().unwrap().insert(id);
    }
}
<commit_msg>Core: Run rustfmt<commit_after>extern crate shootr;

extern crate specs;
extern crate chrono;
extern crate serde_json;
extern crate websocket_server;

use self::specs::{DispatcherBuilder, World, Entity};
use self::chrono::prelude::*;
use self::websocket_server::{start as start_server, EventHandler, SendChannel, OwnedMessage};

use shootr::util::{read_env_var, elapsed_ms};
use shootr::model::comp::{Vel, Pos, Bounciness, Connect, Disconnect, Player, Ping};
use shootr::model::client::KeyState;
use shootr::model::game::{Vector, Id};
use shootr::system::*;
use shootr::bootstrap;

use std::sync::{Arc, RwLock};
use std::thread::sleep;
use std::time::Duration;
use std::collections::{HashMap, HashSet};
use std::net::SocketAddr;

fn main() {
    let port = read_env_var("CORE_PORT").parse::<u32>().expect(
        "Specified port is not a valid number",
    );
    start_server::<Handler>("localhost", port);
}

struct Handler {
    id_entity: RwLock<HashMap<Id, Entity>>,
    to_spawn: RwLock<HashMap<Id, SendChannel>>,
    to_despawn: RwLock<HashSet<Id>>,
    inputs: Arc<RwLock<HashMap<Id, Vec<KeyState>>>>,
}

impl Handler {
    fn prepare_world(&self, world: &mut World) {
        bootstrap::prepare_world(world);
        world.add_resource(self.inputs.clone());

        // Ball
        world
            .create_entity()
            .with(Vel::from(Vector { x: 15, y: 10 }))
            .with(Pos::from(Vector { x: 500, y: 500 }))
            .with(Bounciness {})
            .build();
    }

    fn handle_text(&self, id: Id, msg: &str) {
        if let Ok(key_state) = serde_json::from_str::<KeyState>(&msg) {
            let mut inputs = self.inputs.write().unwrap();
            let has_already_inputs = inputs.get(&id).is_some();
            if has_already_inputs {
                inputs.get_mut(&id).unwrap().push(key_state);
            } else {
                inputs.insert(id, vec![key_state]);
            }
        } else {
            println!("Client {}: Sent invalid message: {}", id, msg);
        }
    }

    fn register_spawns(&self, world: &mut World) {
        let mut id_entity = self.id_entity.write().unwrap();
        let mut to_spawn = self.to_spawn.write().unwrap();
        for (id, send_channel) in to_spawn.drain() {
            let entity = world
                .create_entity()
                .with(Connect {})
                .with(Player::new(id, send_channel))
                .build();
            id_entity.insert(id, entity.clone());
        }

        let mut to_despawn = self.to_despawn.write().unwrap();
        for id in to_despawn.drain() {
            let entity = id_entity.remove(&id).expect(
                "Tried to remove id that was not there",
            );
            world.write::<Disconnect>().insert(entity, Disconnect {});
        }
    }

    fn register_pings(&self, world: &mut World) {
        for (_, entity) in self.id_entity.read().unwrap().iter() {
            world.write::<Ping>().insert(entity.clone(), Ping {});
        }
    }
}

impl EventHandler for Handler {
    type Id = Id;

    fn new() -> Self {
        Handler {
            id_entity: RwLock::new(HashMap::new()),
            to_spawn: RwLock::new(HashMap::new()),
            to_despawn: RwLock::new(HashSet::new()),
            inputs: Arc::new(RwLock::new(HashMap::new())),
        }
    }
    fn main_loop(&self) {
        let mut world = World::new();
        self.prepare_world(&mut world);

        let mut updater = DispatcherBuilder::new()
            .add(InputHandler, "input_handler", &[])
            .add(Physics, "physics", &["input_handler"])
            .add(Bounce, "bounce", &["physics"])
            .add(Spawn, "spawn", &["physics", "bounce"])
            .build();
        let mut sender = DispatcherBuilder::new()
            .add(Sending, "sending", &[])
            .build();

        let mut lag: u64 = 0;
        let mut previous = Utc::now();
        let updates_per_sec = read_env_var("CORE_UPDATES_PER_SEC").parse::<u64>().expect(
            "Failed to parse environmental variable as integer",
        );
        let ms_per_update = 1000 / updates_per_sec;
        let mut ping_timer = 0;
        let ping_interval = 500;
        loop {
            let current = Utc::now();
            let elapsed = elapsed_ms(previous, current).expect("Time went backwards");
            previous = current;
            lag += elapsed;
            ping_timer += elapsed;

            self.register_spawns(&mut world);
            if ping_timer > ping_interval {
                self.register_pings(&mut world);
                ping_timer = 0;
            }

            while lag >= ms_per_update {
                updater.dispatch(&mut world.res);
                lag -= ms_per_update;
            }
            sender.dispatch(&mut world.res);
            world.maintain();

            sleep(Duration::from_millis(ms_per_update - lag));
        }
    }

    fn on_message(&self, id: Self::Id, msg: OwnedMessage) {
        match msg {
            OwnedMessage::Text(ref txt) => self.handle_text(id, txt),
            _ => {}
        };
    }
    fn on_connect(&self, _: SocketAddr, send_channel: SendChannel) -> Option<Self::Id> {
        let id = Id::new_v4();
        self.to_spawn.write().unwrap().insert(id, send_channel);
        Some(id)
    }
    fn on_disconnect(&self, id: Self::Id) {
        self.to_despawn.write().unwrap().insert(id);
    }
}
<|endoftext|>


<commit_before>fn main() {}
<commit_msg>signatures: Remove empty example<commit_after><|endoftext|>


<commit_before>//! Error Reporting for Anonymous Region Lifetime Errors
//! where one region is named and the other is anonymous.
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
use rustc_hir::intravisit::Visitor;
use rustc_hir::FnRetTy;
use rustc_middle::ty;

impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
    /// When given a `ConcreteFailure` for a function with parameters containing a named region and
    /// an anonymous region, emit an descriptive diagnostic error.
    pub(super) fn try_report_named_anon_conflict(&self) -> Option<DiagnosticBuilder<'a>> {
        let (span, sub, sup) = self.regions()?;

        debug!(
            "try_report_named_anon_conflict(sub={:?}, sup={:?}, error={:?})",
            sub, sup, self.error,
        );

        // Determine whether the sub and sup consist of one named region ('a)
        // and one anonymous (elided) region. If so, find the parameter arg
        // where the anonymous region appears (there must always be one; we
        // only introduced anonymous regions in parameters) as well as a
        // version new_ty of its type where the anonymous region is replaced
        // with the named one.
        let (named, anon, anon_param_info, region_info) = if sub.has_name()
            && self.tcx().is_suitable_region(sup).is_some()
            && self.find_param_with_region(sup, sub).is_some()
        {
            (
                sub,
                sup,
                self.find_param_with_region(sup, sub).unwrap(),
                self.tcx().is_suitable_region(sup).unwrap(),
            )
        } else if sup.has_name()
            && self.tcx().is_suitable_region(sub).is_some()
            && self.find_param_with_region(sub, sup).is_some()
        {
            (
                sup,
                sub,
                self.find_param_with_region(sub, sup).unwrap(),
                self.tcx().is_suitable_region(sub).unwrap(),
            )
        } else {
            return None; // inapplicable
        };

        debug!("try_report_named_anon_conflict: named = {:?}", named);
        debug!("try_report_named_anon_conflict: anon_param_info = {:?}", anon_param_info);
        debug!("try_report_named_anon_conflict: region_info = {:?}", region_info);

        let (param, new_ty, new_ty_span, br, is_first, scope_def_id, is_impl_item) = (
            anon_param_info.param,
            anon_param_info.param_ty,
            anon_param_info.param_ty_span,
            anon_param_info.bound_region,
            anon_param_info.is_first,
            region_info.def_id,
            region_info.is_impl_item,
        );
        match br {
            ty::BrAnon(_) => {}
            _ => {
                /* not an anonymous region */
                debug!("try_report_named_anon_conflict: not an anonymous region");
                return None;
            }
        }

        if is_impl_item {
            debug!("try_report_named_anon_conflict: impl item, bail out");
            return None;
        }

        if let Some((_, fndecl)) = self.find_anon_type(anon, &br) {
            if self.is_self_anon(is_first, scope_def_id) {
                return None;
            }

            if let FnRetTy::Return(ty) = &fndecl.output {
                let mut v = ty::TraitObjectVisitor(vec![], self.tcx().hir());
                v.visit_ty(ty);

                debug!("try_report_named_anon_conflict: ret ty {:?}", ty);
                if sub == &ty::ReStatic
                    && v.0
                        .into_iter()
                        .filter(|t| t.span.desugaring_kind().is_none())
                        .next()
                        .is_some()
                {
                    // If the failure is due to a `'static` requirement coming from a `dyn` or
                    // `impl` Trait that *isn't* caused by `async fn` desugaring, handle this case
                    // better in `static_impl_trait`.
                    debug!("try_report_named_anon_conflict: impl Trait + 'static");
                    return None;
                }
            }
        }

        let (error_var, span_label_var) = match param.pat.simple_ident() {
            Some(simple_ident) => (
                format!("the type of `{}`", simple_ident),
                format!("the type of `{}`", simple_ident),
            ),
            None => ("parameter type".to_owned(), "type".to_owned()),
        };

        let mut diag = struct_span_err!(
            self.tcx().sess,
            span,
            E0621,
            "explicit lifetime required in {}",
            error_var
        );

        diag.span_label(span, format!("lifetime `{}` required", named));
        diag.span_suggestion(
            new_ty_span,
            &format!("add explicit lifetime `{}` to {}", named, span_label_var),
            new_ty.to_string(),
            Applicability::Unspecified,
        );

        Some(diag)
    }
}
<commit_msg>fix clippy::filter_next: use .find(..) instead of .filter(..).next()<commit_after>//! Error Reporting for Anonymous Region Lifetime Errors
//! where one region is named and the other is anonymous.
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
use rustc_hir::intravisit::Visitor;
use rustc_hir::FnRetTy;
use rustc_middle::ty;

impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
    /// When given a `ConcreteFailure` for a function with parameters containing a named region and
    /// an anonymous region, emit an descriptive diagnostic error.
    pub(super) fn try_report_named_anon_conflict(&self) -> Option<DiagnosticBuilder<'a>> {
        let (span, sub, sup) = self.regions()?;

        debug!(
            "try_report_named_anon_conflict(sub={:?}, sup={:?}, error={:?})",
            sub, sup, self.error,
        );

        // Determine whether the sub and sup consist of one named region ('a)
        // and one anonymous (elided) region. If so, find the parameter arg
        // where the anonymous region appears (there must always be one; we
        // only introduced anonymous regions in parameters) as well as a
        // version new_ty of its type where the anonymous region is replaced
        // with the named one.
        let (named, anon, anon_param_info, region_info) = if sub.has_name()
            && self.tcx().is_suitable_region(sup).is_some()
            && self.find_param_with_region(sup, sub).is_some()
        {
            (
                sub,
                sup,
                self.find_param_with_region(sup, sub).unwrap(),
                self.tcx().is_suitable_region(sup).unwrap(),
            )
        } else if sup.has_name()
            && self.tcx().is_suitable_region(sub).is_some()
            && self.find_param_with_region(sub, sup).is_some()
        {
            (
                sup,
                sub,
                self.find_param_with_region(sub, sup).unwrap(),
                self.tcx().is_suitable_region(sub).unwrap(),
            )
        } else {
            return None; // inapplicable
        };

        debug!("try_report_named_anon_conflict: named = {:?}", named);
        debug!("try_report_named_anon_conflict: anon_param_info = {:?}", anon_param_info);
        debug!("try_report_named_anon_conflict: region_info = {:?}", region_info);

        let (param, new_ty, new_ty_span, br, is_first, scope_def_id, is_impl_item) = (
            anon_param_info.param,
            anon_param_info.param_ty,
            anon_param_info.param_ty_span,
            anon_param_info.bound_region,
            anon_param_info.is_first,
            region_info.def_id,
            region_info.is_impl_item,
        );
        match br {
            ty::BrAnon(_) => {}
            _ => {
                /* not an anonymous region */
                debug!("try_report_named_anon_conflict: not an anonymous region");
                return None;
            }
        }

        if is_impl_item {
            debug!("try_report_named_anon_conflict: impl item, bail out");
            return None;
        }

        if let Some((_, fndecl)) = self.find_anon_type(anon, &br) {
            if self.is_self_anon(is_first, scope_def_id) {
                return None;
            }

            if let FnRetTy::Return(ty) = &fndecl.output {
                let mut v = ty::TraitObjectVisitor(vec![], self.tcx().hir());
                v.visit_ty(ty);

                debug!("try_report_named_anon_conflict: ret ty {:?}", ty);
                if sub == &ty::ReStatic
                    && v.0.into_iter().find(|t| t.span.desugaring_kind().is_none()).is_some()
                {
                    // If the failure is due to a `'static` requirement coming from a `dyn` or
                    // `impl` Trait that *isn't* caused by `async fn` desugaring, handle this case
                    // better in `static_impl_trait`.
                    debug!("try_report_named_anon_conflict: impl Trait + 'static");
                    return None;
                }
            }
        }

        let (error_var, span_label_var) = match param.pat.simple_ident() {
            Some(simple_ident) => (
                format!("the type of `{}`", simple_ident),
                format!("the type of `{}`", simple_ident),
            ),
            None => ("parameter type".to_owned(), "type".to_owned()),
        };

        let mut diag = struct_span_err!(
            self.tcx().sess,
            span,
            E0621,
            "explicit lifetime required in {}",
            error_var
        );

        diag.span_label(span, format!("lifetime `{}` required", named));
        diag.span_suggestion(
            new_ty_span,
            &format!("add explicit lifetime `{}` to {}", named, span_label_var),
            new_ty.to_string(),
            Applicability::Unspecified,
        );

        Some(diag)
    }
}
<|endoftext|>


<commit_before>use super::*;
use redox::*;

impl Editor {
    pub fn exec(&mut self, Inst(n, cmd): Inst) {
        use super::Mode::*;
        use super::PrimitiveMode::*;
        use super::CommandMode::*;
        match self.cursor().mode {
            Command(Normal) => match cmd {
                'i' => {
                    self.cursor_mut().mode = Mode::Primitive(PrimitiveMode::Insert(
                        InsertOptions {
                            mode: InsertMode::Insert,
                        }));

                },
                'h' => self.left(n as usize),
                'j' => self.down(n as usize),
                'k' => self.up(n as usize),
                'l' => self.right(n as usize),
                'J' => self.down(15),
                'K' => self.up(15),
                'x' => self.delete(),
                'X' => {
                    self.previous();
                    self.delete();
                },
                '$' => self.cursor_mut().x = self.text[self.y()].len(),
                '0' => self.cursor_mut().x = 0,
                ' ' => self.next(),
                _ => {},
            },
            Primitive(Insert(_)) => {
                self.insert(cmd);
            },
        }
    }
}
<commit_msg>Add r command<commit_after>use super::*;
use redox::*;

impl Editor {
    pub fn exec(&mut self, Inst(n, cmd): Inst) {
        use super::Mode::*;
        use super::PrimitiveMode::*;
        use super::CommandMode::*;
        match self.cursor().mode {
            Command(Normal) => match cmd {
                'i' => {
                    self.cursor_mut().mode = Mode::Primitive(PrimitiveMode::Insert(
                        InsertOptions {
                            mode: InsertMode::Insert,
                        }));

                },
                'h' => self.left(n as usize),
                'j' => self.down(n as usize),
                'k' => self.up(n as usize),
                'l' => self.right(n as usize),
                'J' => self.down(15),
                'K' => self.up(15),
                'x' => self.delete(),
                'X' => {
                    self.previous();
                    self.delete();
                },
                '$' => self.cursor_mut().x = self.text[self.y()].len(),
                '0' => self.cursor_mut().x = 0,
                'r' => {
                    if let EventOption::Key(k) = self.window.poll()
                                                 .unwrap_or(Event::new())
                                                 .to_option() {
                        let x = self.x();
                        let y = self.y();
                        self.text[y][x] = k.character;
                    }
                },
                ' ' => self.next(),
                _ => {},
            },
            Primitive(Insert(_)) => {
                self.insert(cmd);
            },
        }
    }
}
<|endoftext|>


<commit_before>use std::convert;
use std::io;
use std::result;
use std::num::{FromPrimitive, ToPrimitive};
use std::str::Utf8Error;

use byteorder;

const FIXSTR_SIZE   : u8 = 0x1f;
const FIXARRAY_SIZE : u8 = 0x0f;
const FIXMAP_SIZE   : u8 = 0x0f;

#[derive(Clone, Copy, PartialEq, Debug)]
pub enum Marker {
    PositiveFixnum(u8),
    NegativeFixnum(i8),
    Null,
    True,
    False,
    U8,
    U16,
    U32,
    U64,
    I8,
    I16,
    I32,
    I64,
    F32,
    F64,
    FixedString(u8),
    Str8,
    Str16,
    Str32,
    Bin8,
    Bin16,
    Bin32,
    FixedArray(u8),
    Array16,
    Array32,
    FixedMap(u8),
    Map16,
    Map32,
    FixExt1,
    FixExt2,
    FixExt4,
    FixExt8,
    FixExt16,
    Ext8,
    Ext16,
    Ext32,
    Reserved,
}

// TODO: Consider using own trait without Option packing/unpacking.
impl FromPrimitive for Marker {
    fn from_i64(n: i64) -> Option<Marker> {
        FromPrimitive::from_u64(n as u64)
    }

    fn from_u64(n: u64) -> Option<Marker> {
        match n {
            val @ 0x00 ... 0x7f => Some(Marker::PositiveFixnum(val as u8)),
            val @ 0xe0 ... 0xff => Some(Marker::NegativeFixnum(val as i8)),
            val @ 0x80 ... 0x8f => Some(Marker::FixedMap((val as u8) & FIXMAP_SIZE)),
            val @ 0x90 ... 0x9f => Some(Marker::FixedArray((val as u8) & FIXARRAY_SIZE)),
            val @ 0xa0 ... 0xbf => Some(Marker::FixedString((val as u8) & FIXSTR_SIZE)),
            0xc0 => Some(Marker::Null),
            0xc1 => None, // Marked in MessagePack spec as never used.
            0xc2 => Some(Marker::False),
            0xc3 => Some(Marker::True),
            0xc4 => Some(Marker::Bin8),
            0xc5 => Some(Marker::Bin16),
            0xc6 => Some(Marker::Bin32),
            0xc7 => Some(Marker::Ext8),
            0xc8 => Some(Marker::Ext16),
            0xc9 => Some(Marker::Ext32),
            0xca => Some(Marker::F32),
            0xcb => Some(Marker::F64),
            0xcc => Some(Marker::U8),
            0xcd => Some(Marker::U16),
            0xce => Some(Marker::U32),
            0xcf => Some(Marker::U64),
            0xd0 => Some(Marker::I8),
            0xd1 => Some(Marker::I16),
            0xd2 => Some(Marker::I32),
            0xd3 => Some(Marker::I64),
            0xd4 => Some(Marker::FixExt1),
            0xd5 => Some(Marker::FixExt2),
            0xd6 => Some(Marker::FixExt4),
            0xd7 => Some(Marker::FixExt8),
            0xd8 => Some(Marker::FixExt16),
            0xd9 => Some(Marker::Str8),
            0xda => Some(Marker::Str16),
            0xdb => Some(Marker::Str32),
            0xdc => Some(Marker::Array16),
            0xdd => Some(Marker::Array32),
            0xde => Some(Marker::Map16),
            0xdf => Some(Marker::Map32),
            _ => None,
        }
    }
}

// TODO: Consider using own trait without Option packing/unpacking.
impl ToPrimitive for Marker {
    fn to_i64(&self) -> Option<i64> {
        Some(ToPrimitive::to_u64(self).unwrap() as i64)
    }

    fn to_u64(&self) -> Option<u64> {
        let byte = match *self {
            Marker::PositiveFixnum(val) => val,
            Marker::NegativeFixnum(val) => val as u8,
            Marker::Null                => 0xc0,
            Marker::True                => 0xc3,
            Marker::False               => 0xc2,
            Marker::U8                  => 0xcc,
            Marker::U16                 => 0xcd,
            Marker::U32                 => 0xce,
            Marker::U64                 => 0xcf,
            Marker::I8                  => 0xd0,
            Marker::I16                 => 0xd1,
            Marker::I32                 => 0xd2,
            Marker::I64                 => 0xd3,
            Marker::F32                 => 0xca,
            Marker::F64                 => 0xcb,
            Marker::FixedString(..)     => unimplemented!(),
            Marker::Str8                => unimplemented!(),
            Marker::Str16               => unimplemented!(),
            Marker::Str32               => unimplemented!(),
            Marker::Bin8                => unimplemented!(),
            Marker::Bin16               => unimplemented!(),
            Marker::Bin32               => unimplemented!(),
            Marker::FixedArray(..)      => unimplemented!(),
            Marker::Array16             => unimplemented!(),
            Marker::Array32             => unimplemented!(),
            Marker::FixedMap(..)        => unimplemented!(),
            Marker::Map16               => unimplemented!(),
            Marker::Map32               => unimplemented!(),
            Marker::FixExt1             => unimplemented!(),
            Marker::FixExt2             => unimplemented!(),
            Marker::FixExt4             => unimplemented!(),
            Marker::FixExt8             => unimplemented!(),
            Marker::FixExt16            => unimplemented!(),
            Marker::Ext8                => unimplemented!(),
            Marker::Ext16               => unimplemented!(),
            Marker::Ext32               => unimplemented!(),
            Marker::Reserved            => 0xc1,
        };

        Some(byte as u64)
    }
}

/// An error type for reading bytes from the reader.
///
/// This is a thin wrapper over the standard `io::Error` type. Namely, it adds one additional error
/// case: an unexpected EOF.
#[unstable(reason = "remove Debug trait")]
#[derive(Debug)]
pub enum ReadError {
    UnexpectedEOF,
    IO(io::Error),
}

// TODO: This is a hack, because io::Error has PartialEq once.
impl PartialEq for ReadError {
    fn eq(&self, other: &ReadError) -> bool {
        match (self, other) {
            (&ReadError::UnexpectedEOF, &ReadError::UnexpectedEOF) => true,
            (&ReadError::IO(ref lhs),   &ReadError::IO(ref rhs)) => {
                lhs.kind() == rhs.kind()
            }
            _ => false
        }
    }

    fn ne(&self, other: &ReadError) -> bool {
        return !self.eq(other);
    }
}

impl convert::From<io::Error> for ReadError {
    fn from(err: io::Error) -> ReadError { ReadError::IO(err) }
}

impl convert::From<ReadError> for io::Error {
    fn from(err: ReadError) -> io::Error {
        match err {
            ReadError::IO(err) => err,
            ReadError::UnexpectedEOF => io::Error::new(io::ErrorKind::Other, "unexpected EOF")
        }
    }
}

impl convert::From<byteorder::Error> for ReadError {
    fn from(err: byteorder::Error) -> ReadError {
        match err {
            byteorder::Error::UnexpectedEOF => ReadError::UnexpectedEOF,
            byteorder::Error::Io(err) => ReadError::IO(err),
        }
    }
}

#[unstable(reason = "remove Debug trait; incomplete")]
#[derive(Debug, PartialEq)]
pub enum Error {
    /// Marker type error.
    TypeMismatch(Marker),
    /// IO error while reading marker.
    InvalidMarkerRead(ReadError),
    /// IO error while reading data.
    InvalidDataRead(ReadError),
}

#[unstable(reason = "Core? Shit name!")]
#[derive(Debug, PartialEq)]
pub enum DecodeStringError<'a> {
    Core(Error),
    /// The given buffer is too small to accumulate specified amount of bytes.
    BufferSizeTooSmall(u32),
    InvalidDataCopy(&'a [u8], ReadError),
    InvalidUtf8(&'a [u8], Utf8Error),
}

impl<'a> convert::From<Error> for DecodeStringError<'a> {
    fn from(err: Error) -> DecodeStringError<'a> {
        DecodeStringError::Core(err)
    }
}

pub type Result<T> = result::Result<T, Error>;

#[derive(Clone, Debug, PartialEq)]
pub enum Integer {
    /// Every non-negative integer is treated as u64, even if it fits in i64.
    U64(u64),
    /// Every negative integer is treated as i64.
    I64(i64),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    Null,
    Integer(Integer),
    String(String),
    Array(Vec<Value>),
}

pub mod decode;
pub mod encode;
<commit_msg>[Misc] Some minor preparations for refactoring.<commit_after>use std::convert;
use std::io;
use std::result;
use std::num::{FromPrimitive, ToPrimitive};
use std::str::Utf8Error;

use byteorder;

const FIXSTR_SIZE   : u8 = 0x1f;
const FIXARRAY_SIZE : u8 = 0x0f;
const FIXMAP_SIZE   : u8 = 0x0f;

#[derive(Clone, Copy, PartialEq, Debug)]
pub enum Marker {
    PositiveFixnum(u8),
    NegativeFixnum(i8),
    Null,
    True,
    False,
    U8,
    U16,
    U32,
    U64,
    I8,
    I16,
    I32,
    I64,
    F32,
    F64,
    FixedString(u8),
    Str8,
    Str16,
    Str32,
    Bin8,
    Bin16,
    Bin32,
    FixedArray(u8),
    Array16,
    Array32,
    FixedMap(u8),
    Map16,
    Map32,
    FixExt1,
    FixExt2,
    FixExt4,
    FixExt8,
    FixExt16,
    Ext8,
    Ext16,
    Ext32,
    Reserved,
}

// TODO: Consider using own trait without Option packing/unpacking.
impl FromPrimitive for Marker {
    fn from_i64(n: i64) -> Option<Marker> {
        FromPrimitive::from_u64(n as u64)
    }

    fn from_u64(n: u64) -> Option<Marker> {
        match n {
            val @ 0x00 ... 0x7f => Some(Marker::PositiveFixnum(val as u8)),
            val @ 0xe0 ... 0xff => Some(Marker::NegativeFixnum(val as i8)),
            val @ 0x80 ... 0x8f => Some(Marker::FixedMap((val as u8) & FIXMAP_SIZE)),
            val @ 0x90 ... 0x9f => Some(Marker::FixedArray((val as u8) & FIXARRAY_SIZE)),
            val @ 0xa0 ... 0xbf => Some(Marker::FixedString((val as u8) & FIXSTR_SIZE)),
            0xc0 => Some(Marker::Null),
            0xc1 => None, // Marked in MessagePack spec as never used.
            0xc2 => Some(Marker::False),
            0xc3 => Some(Marker::True),
            0xc4 => Some(Marker::Bin8),
            0xc5 => Some(Marker::Bin16),
            0xc6 => Some(Marker::Bin32),
            0xc7 => Some(Marker::Ext8),
            0xc8 => Some(Marker::Ext16),
            0xc9 => Some(Marker::Ext32),
            0xca => Some(Marker::F32),
            0xcb => Some(Marker::F64),
            0xcc => Some(Marker::U8),
            0xcd => Some(Marker::U16),
            0xce => Some(Marker::U32),
            0xcf => Some(Marker::U64),
            0xd0 => Some(Marker::I8),
            0xd1 => Some(Marker::I16),
            0xd2 => Some(Marker::I32),
            0xd3 => Some(Marker::I64),
            0xd4 => Some(Marker::FixExt1),
            0xd5 => Some(Marker::FixExt2),
            0xd6 => Some(Marker::FixExt4),
            0xd7 => Some(Marker::FixExt8),
            0xd8 => Some(Marker::FixExt16),
            0xd9 => Some(Marker::Str8),
            0xda => Some(Marker::Str16),
            0xdb => Some(Marker::Str32),
            0xdc => Some(Marker::Array16),
            0xdd => Some(Marker::Array32),
            0xde => Some(Marker::Map16),
            0xdf => Some(Marker::Map32),
            _ => None,
        }
    }
}

// TODO: Consider using own trait without Option packing/unpacking.
impl ToPrimitive for Marker {
    fn to_i64(&self) -> Option<i64> {
        Some(ToPrimitive::to_u64(self).unwrap() as i64)
    }

    fn to_u64(&self) -> Option<u64> {
        let byte = match *self {
            Marker::PositiveFixnum(val) => val,
            Marker::NegativeFixnum(val) => val as u8,
            Marker::Null                => 0xc0,
            Marker::True                => 0xc3,
            Marker::False               => 0xc2,
            Marker::U8                  => 0xcc,
            Marker::U16                 => 0xcd,
            Marker::U32                 => 0xce,
            Marker::U64                 => 0xcf,
            Marker::I8                  => 0xd0,
            Marker::I16                 => 0xd1,
            Marker::I32                 => 0xd2,
            Marker::I64                 => 0xd3,
            Marker::F32                 => 0xca,
            Marker::F64                 => 0xcb,

            Marker::FixedString(..)     => unimplemented!(),
            Marker::Str8                => unimplemented!(),
            Marker::Str16               => unimplemented!(),
            Marker::Str32               => unimplemented!(),

            Marker::Bin8                => unimplemented!(),
            Marker::Bin16               => unimplemented!(),
            Marker::Bin32               => unimplemented!(),

            Marker::FixedArray(..)      => unimplemented!(),
            Marker::Array16             => unimplemented!(),
            Marker::Array32             => unimplemented!(),

            Marker::FixedMap(..)        => unimplemented!(),
            Marker::Map16               => unimplemented!(),
            Marker::Map32               => unimplemented!(),

            Marker::FixExt1             => unimplemented!(),
            Marker::FixExt2             => unimplemented!(),
            Marker::FixExt4             => unimplemented!(),
            Marker::FixExt8             => unimplemented!(),
            Marker::FixExt16            => unimplemented!(),
            Marker::Ext8                => unimplemented!(),
            Marker::Ext16               => unimplemented!(),
            Marker::Ext32               => unimplemented!(),

            Marker::Reserved            => 0xc1,
        };

        Some(byte as u64)
    }
}

/// An error type for reading bytes from the reader.
///
/// This is a thin wrapper over the standard `io::Error` type. Namely, it adds one additional error
/// case: an unexpected EOF.
#[unstable(reason = "remove Debug trait; maybe rename IO variant to Io")]
#[derive(Debug)]
pub enum ReadError {
    UnexpectedEOF,
    IO(io::Error),
}

#[unstable(reason = "this is a hack, because io::Error has PartialEq once; will be removed")]
impl PartialEq for ReadError {
    fn eq(&self, other: &ReadError) -> bool {
        match (self, other) {
            (&ReadError::UnexpectedEOF, &ReadError::UnexpectedEOF) => true,
            (&ReadError::IO(ref lhs),   &ReadError::IO(ref rhs)) => {
                lhs.kind() == rhs.kind()
            }
            _ => false
        }
    }

    fn ne(&self, other: &ReadError) -> bool {
        return !self.eq(other);
    }
}

impl convert::From<io::Error> for ReadError {
    fn from(err: io::Error) -> ReadError { ReadError::IO(err) }
}

impl convert::From<ReadError> for io::Error {
    fn from(err: ReadError) -> io::Error {
        match err {
            ReadError::IO(err) => err,
            ReadError::UnexpectedEOF => io::Error::new(io::ErrorKind::Other, "unexpected EOF")
        }
    }
}

impl convert::From<byteorder::Error> for ReadError {
    fn from(err: byteorder::Error) -> ReadError {
        match err {
            byteorder::Error::UnexpectedEOF => ReadError::UnexpectedEOF,
            byteorder::Error::Io(err) => ReadError::IO(err),
        }
    }
}

#[unstable(reason = "remove Debug trait; incomplete")]
#[derive(Debug, PartialEq)]
pub enum Error {
    /// Marker type error.
    TypeMismatch(Marker),
    /// IO error while reading marker.
    InvalidMarkerRead(ReadError),
    /// IO error while reading data.
    InvalidDataRead(ReadError),
}

#[unstable(reason = "Core? Shit name!")]
#[derive(Debug, PartialEq)]
pub enum DecodeStringError<'a> {
    Core(Error),
    /// The given buffer is too small to accumulate specified amount of bytes.
    BufferSizeTooSmall(u32),
    InvalidDataCopy(&'a [u8], ReadError),
    InvalidUtf8(&'a [u8], Utf8Error),
}

impl<'a> convert::From<Error> for DecodeStringError<'a> {
    fn from(err: Error) -> DecodeStringError<'a> {
        DecodeStringError::Core(err)
    }
}

pub type Result<T> = result::Result<T, Error>;

#[derive(Clone, Debug, PartialEq)]
pub enum Integer {
    /// Every non-negative integer is treated as u64, even if it fits in i64.
    U64(u64),
    /// Every negative integer is treated as i64.
    I64(i64),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    Null,
    Integer(Integer),
    String(String),
    Array(Vec<Value>),
}

pub mod decode;
pub mod encode;
<|endoftext|>


<commit_before><commit_msg>Fix a bug in the last chunk<commit_after><|endoftext|>


<commit_before><commit_msg>fix(dbg): Fix --help for debug tool<commit_after><|endoftext|>


<commit_before><commit_msg>tools/runfiles: use $TEST_SRCDIR when available (#1035)<commit_after><|endoftext|>


<commit_before>use std::{env,
          ffi::OsString,
          fs as stdfs,
          path::PathBuf};

use crate::{common::ui::UI,
            hcore::{crypto::CACHE_KEY_PATH_ENV_VAR,
                    env as henv,
                    fs}};

use crate::{config,
            error::Result};

pub const ARTIFACT_PATH_ENVVAR: &str = "ARTIFACT_PATH";

const AUTH_TOKEN_ENVVAR: &str = "HAB_AUTH_TOKEN";
const BLDR_URL_ENVVAR: &str = "HAB_BLDR_URL";
const CTL_SECRET_ENVVAR: &str = "HAB_CTL_SECRET";
const ORIGIN_ENVVAR: &str = "HAB_ORIGIN";
const STUDIO_CMD: &str = "hab-studio";
const STUDIO_CMD_ENVVAR: &str = "HAB_STUDIO_BINARY";
const STUDIO_PACKAGE_IDENT: &str = "core/hab-studio";

// fn set_env_var_from_config<T: Into<Option<bool>>>(env_var: &str, config_val: Option<String>, sensitive: T) {
fn set_env_var_from_config(env_var: &str, config_val: Option<String>, sensitive: bool) {
    if henv::var(env_var).is_err() {
        if let Some(val) = config_val {
            if sensitive {
              debug!("Setting Sensitive value {} via config file", env_var)
            }
            else {
              debug!("Setting {}={} via config file", env_var, val)
            }
            env::set_var(env_var, val);
        }
    }
}

pub fn start(ui: &mut UI, args: &[OsString]) -> Result<()> {
    let config = config::load()?;

    set_env_var_from_config(AUTH_TOKEN_ENVVAR, config.auth_token, true);
    set_env_var_from_config(BLDR_URL_ENVVAR, config.bldr_url, false);
    set_env_var_from_config(CTL_SECRET_ENVVAR, config.ctl_secret, true);
    set_env_var_from_config(ORIGIN_ENVVAR, config.origin, false);

    if henv::var(CACHE_KEY_PATH_ENV_VAR).is_err() {
        let path = fs::cache_key_path(None::<&str>);
        debug!("Setting {}={}", CACHE_KEY_PATH_ENV_VAR, path.display());
        env::set_var(CACHE_KEY_PATH_ENV_VAR, &path);
    };

    let artifact_path = match henv::var(ARTIFACT_PATH_ENVVAR) {
        Ok(p) => PathBuf::from(p),
        Err(_) => {
            let path = fs::cache_artifact_path(None::<&str>);
            debug!("Setting {}={}", ARTIFACT_PATH_ENVVAR, path.display());
            env::set_var(ARTIFACT_PATH_ENVVAR, &path);
            path
        }
    };
    if !artifact_path.is_dir() {
        debug!("Creating artifact_path at: {}", artifact_path.display());
        stdfs::create_dir_all(&artifact_path)?;
    }

    inner::start(ui, args)
}

#[cfg(target_os = "linux")]
mod inner {
    use crate::{command::studio::docker,
                common::ui::{UIWriter,
                             UI},
                error::{Error,
                        Result},
                exec,
                hcore::{crypto::init,
                        env as henv,
                        fs::{am_i_root,
                             find_command},
                        os::process,
                        package::{PackageIdent,
                                  PackageInstall},
                        users::linux as group},
                VERSION};
    use std::{env,
              ffi::OsString,
              path::PathBuf,
              str::FromStr};

    const SUDO_CMD: &str = "sudo";

    pub fn start(ui: &mut UI, args: &[OsString]) -> Result<()> {
        rerun_with_sudo_if_needed(ui, &args)?;
        if is_docker_studio(&args) {
            docker::start_docker_studio(ui, args)
        } else {
            let command = match henv::var(super::STUDIO_CMD_ENVVAR) {
                Ok(command) => PathBuf::from(command),
                Err(_) => {
                    init();
                    let version: Vec<&str> = VERSION.split('/').collect();
                    let ident = PackageIdent::from_str(&format!("{}/{}",
                                                                super::STUDIO_PACKAGE_IDENT,
                                                                version[0]))?;
                    // This is a duplicate of the code in `hab pkg exec` and
                    // should be refactored as part of or after:
                    // https://github.com/habitat-sh/habitat/issues/6633
                    // https://github.com/habitat-sh/habitat/issues/6634
                    let pkg_install = PackageInstall::load(&ident, None)?;
                    let cmd_env = pkg_install.environment_for_command()?;
                    for (key, value) in cmd_env.into_iter() {
                        debug!("Setting: {}='{}'", key, value);
                        env::set_var(key, value);
                    }

                    let mut display_args = super::STUDIO_CMD.to_string();
                    for arg in args {
                        display_args.push(' ');
                        display_args.push_str(arg.to_string_lossy().as_ref());
                    }
                    debug!("Running: {}", display_args);

                    exec::command_from_min_pkg(ui, super::STUDIO_CMD, &ident)?
                }
            };

            if let Some(cmd) = find_command(command.to_string_lossy().as_ref()) {
                process::become_command(cmd, args)?;
                Ok(())
            } else {
                Err(Error::ExecCommandNotFound(command))
            }
        }
    }

    fn is_docker_studio(args: &[OsString]) -> bool {
        if cfg!(not(target_os = "linux")) {
            return false;
        }

        for arg in args.iter() {
            let str_arg = arg.to_string_lossy();
            if str_arg == "-D" {
                return true;
            }
        }

        false
    }

    fn has_docker_group() -> bool {
        let current_user = group::get_current_username().unwrap();
        let docker_members = group::get_members_by_groupname("docker");
        docker_members.map_or(false, |d| d.contains(&current_user))
    }

    fn rerun_with_sudo_if_needed(ui: &mut UI, args: &[OsString]) -> Result<()> {
        // If I have root permissions or if I am executing a docker studio
        // and have the appropriate group - early return, we are done.
        if am_i_root() || (is_docker_studio(args) && has_docker_group()) {
            return Ok(());
        }

        // Otherwise we will try to re-run this program using `sudo`
        match find_command(SUDO_CMD) {
            Some(sudo_prog) => {
                let mut args: Vec<OsString> = vec!["-p".into(),
                                                   "[sudo hab-studio] password for %u: ".into(),
                                                   "-E".into(),];
                args.append(&mut env::args_os().collect());
                process::become_command(sudo_prog, &args)?;
                Ok(())
            }
            None => {
                ui.warn(format!("Could not find the `{}' command, is it in your PATH?",
                                SUDO_CMD))?;
                ui.warn("Running Habitat Studio requires root or administrator privileges. \
                         Please retry this command as a super user or use a privilege-granting \
                         facility such as sudo.")?;
                ui.br()?;
                Err(Error::RootRequired)
            }
        }
    }
}

#[cfg(not(target_os = "linux"))]
mod inner {
    use crate::{command::studio::docker,
                common::ui::UI,
                error::{Error,
                        Result},
                exec,
                hcore::{crypto::init,
                        env as henv,
                        fs::find_command,
                        os::process,
                        package::PackageIdent},
                VERSION};
    use std::{ffi::OsString,
              path::PathBuf,
              str::FromStr};

    pub fn start(_ui: &mut UI, args: &[OsString]) -> Result<()> {
        if is_windows_studio(&args) {
            start_windows_studio(_ui, args)
        } else {
            docker::start_docker_studio(_ui, args)
        }
    }

    pub fn start_windows_studio(ui: &mut UI, args: &[OsString]) -> Result<()> {
        let command = match henv::var(super::STUDIO_CMD_ENVVAR) {
            Ok(command) => PathBuf::from(command),
            Err(_) => {
                init();
                let version: Vec<&str> = VERSION.split('/').collect();
                let ident = PackageIdent::from_str(&format!("{}/{}",
                                                            super::STUDIO_PACKAGE_IDENT,
                                                            version[0]))?;
                exec::command_from_min_pkg(ui, super::STUDIO_CMD, &ident)?
            }
        };

        if let Some(cmd) = find_command(command.to_string_lossy().as_ref()) {
            process::become_command(cmd, args)?;
        } else {
            return Err(Error::ExecCommandNotFound(command));
        }
        Ok(())
    }

    fn is_windows_studio(args: &[OsString]) -> bool {
        if cfg!(not(target_os = "windows")) {
            return false;
        }

        for arg in args.iter() {
            let str_arg = arg.to_string_lossy();
            if str_arg == "-D" {
                return false;
            }
        }

        // -w/--windows is deprecated and should be removed in a post 0.64.0 release
        for arg in args.iter() {
            let str_arg = arg.to_string_lossy().to_lowercase();
            if str_arg == "--windows" || str_arg == "-w" {
                return true;
            }
        }

        true
    }
}
<commit_msg>Import consts from where they are defined instead of defining locally<commit_after>use std::{env,
          ffi::OsString,
          fs as stdfs,
          path::PathBuf};

use crate::{common::ui::UI,
            hcore::{crypto::CACHE_KEY_PATH_ENV_VAR,
                    env as henv,
                    fs}};

use crate::{config,
            error::Result,
            BLDR_URL_ENVVAR,
            CTL_SECRET_ENVVAR,
            ORIGIN_ENVVAR};

use habitat_core::AUTH_TOKEN_ENVVAR;

pub const ARTIFACT_PATH_ENVVAR: &str = "ARTIFACT_PATH";

const STUDIO_CMD: &str = "hab-studio";
const STUDIO_CMD_ENVVAR: &str = "HAB_STUDIO_BINARY";
const STUDIO_PACKAGE_IDENT: &str = "core/hab-studio";

// fn set_env_var_from_config<T: Into<Option<bool>>>(env_var: &str, config_val: Option<String>, sensitive: T) {
fn set_env_var_from_config(env_var: &str, config_val: Option<String>, sensitive: bool) {
    if henv::var(env_var).is_err() {
        if let Some(val) = config_val {
            if sensitive {
              debug!("Setting {}=REDACTED (sensitive) via config file", env_var)
            }
            else {
              debug!("Setting {}={} via config file", env_var, val)
            }
            env::set_var(env_var, val);
        }
    }
}

pub fn start(ui: &mut UI, args: &[OsString]) -> Result<()> {
    let config = config::load()?;

    set_env_var_from_config(AUTH_TOKEN_ENVVAR, config.auth_token, true);
    set_env_var_from_config(BLDR_URL_ENVVAR, config.bldr_url, false);
    set_env_var_from_config(CTL_SECRET_ENVVAR, config.ctl_secret, true);
    set_env_var_from_config(ORIGIN_ENVVAR, config.origin, false);

    if henv::var(CACHE_KEY_PATH_ENV_VAR).is_err() {
        let path = fs::cache_key_path(None::<&str>);
        debug!("Setting {}={}", CACHE_KEY_PATH_ENV_VAR, path.display());
        env::set_var(CACHE_KEY_PATH_ENV_VAR, &path);
    };

    let artifact_path = match henv::var(ARTIFACT_PATH_ENVVAR) {
        Ok(p) => PathBuf::from(p),
        Err(_) => {
            let path = fs::cache_artifact_path(None::<&str>);
            debug!("Setting {}={}", ARTIFACT_PATH_ENVVAR, path.display());
            env::set_var(ARTIFACT_PATH_ENVVAR, &path);
            path
        }
    };
    if !artifact_path.is_dir() {
        debug!("Creating artifact_path at: {}", artifact_path.display());
        stdfs::create_dir_all(&artifact_path)?;
    }

    inner::start(ui, args)
}

#[cfg(target_os = "linux")]
mod inner {
    use crate::{command::studio::docker,
                common::ui::{UIWriter,
                             UI},
                error::{Error,
                        Result},
                exec,
                hcore::{crypto::init,
                        env as henv,
                        fs::{am_i_root,
                             find_command},
                        os::process,
                        package::{PackageIdent,
                                  PackageInstall},
                        users::linux as group},
                VERSION};
    use std::{env,
              ffi::OsString,
              path::PathBuf,
              str::FromStr};

    const SUDO_CMD: &str = "sudo";

    pub fn start(ui: &mut UI, args: &[OsString]) -> Result<()> {
        rerun_with_sudo_if_needed(ui, &args)?;
        if is_docker_studio(&args) {
            docker::start_docker_studio(ui, args)
        } else {
            let command = match henv::var(super::STUDIO_CMD_ENVVAR) {
                Ok(command) => PathBuf::from(command),
                Err(_) => {
                    init();
                    let version: Vec<&str> = VERSION.split('/').collect();
                    let ident = PackageIdent::from_str(&format!("{}/{}",
                                                                super::STUDIO_PACKAGE_IDENT,
                                                                version[0]))?;
                    // This is a duplicate of the code in `hab pkg exec` and
                    // should be refactored as part of or after:
                    // https://github.com/habitat-sh/habitat/issues/6633
                    // https://github.com/habitat-sh/habitat/issues/6634
                    let pkg_install = PackageInstall::load(&ident, None)?;
                    let cmd_env = pkg_install.environment_for_command()?;
                    for (key, value) in cmd_env.into_iter() {
                        debug!("Setting: {}='{}'", key, value);
                        env::set_var(key, value);
                    }

                    let mut display_args = super::STUDIO_CMD.to_string();
                    for arg in args {
                        display_args.push(' ');
                        display_args.push_str(arg.to_string_lossy().as_ref());
                    }
                    debug!("Running: {}", display_args);

                    exec::command_from_min_pkg(ui, super::STUDIO_CMD, &ident)?
                }
            };

            if let Some(cmd) = find_command(command.to_string_lossy().as_ref()) {
                process::become_command(cmd, args)?;
                Ok(())
            } else {
                Err(Error::ExecCommandNotFound(command))
            }
        }
    }

    fn is_docker_studio(args: &[OsString]) -> bool {
        if cfg!(not(target_os = "linux")) {
            return false;
        }

        for arg in args.iter() {
            let str_arg = arg.to_string_lossy();
            if str_arg == "-D" {
                return true;
            }
        }

        false
    }

    fn has_docker_group() -> bool {
        let current_user = group::get_current_username().unwrap();
        let docker_members = group::get_members_by_groupname("docker");
        docker_members.map_or(false, |d| d.contains(&current_user))
    }

    fn rerun_with_sudo_if_needed(ui: &mut UI, args: &[OsString]) -> Result<()> {
        // If I have root permissions or if I am executing a docker studio
        // and have the appropriate group - early return, we are done.
        if am_i_root() || (is_docker_studio(args) && has_docker_group()) {
            return Ok(());
        }

        // Otherwise we will try to re-run this program using `sudo`
        match find_command(SUDO_CMD) {
            Some(sudo_prog) => {
                let mut args: Vec<OsString> = vec!["-p".into(),
                                                   "[sudo hab-studio] password for %u: ".into(),
                                                   "-E".into(),];
                args.append(&mut env::args_os().collect());
                process::become_command(sudo_prog, &args)?;
                Ok(())
            }
            None => {
                ui.warn(format!("Could not find the `{}' command, is it in your PATH?",
                                SUDO_CMD))?;
                ui.warn("Running Habitat Studio requires root or administrator privileges. \
                         Please retry this command as a super user or use a privilege-granting \
                         facility such as sudo.")?;
                ui.br()?;
                Err(Error::RootRequired)
            }
        }
    }
}

#[cfg(not(target_os = "linux"))]
mod inner {
    use crate::{command::studio::docker,
                common::ui::UI,
                error::{Error,
                        Result},
                exec,
                hcore::{crypto::init,
                        env as henv,
                        fs::find_command,
                        os::process,
                        package::PackageIdent},
                VERSION};
    use std::{ffi::OsString,
              path::PathBuf,
              str::FromStr};

    pub fn start(_ui: &mut UI, args: &[OsString]) -> Result<()> {
        if is_windows_studio(&args) {
            start_windows_studio(_ui, args)
        } else {
            docker::start_docker_studio(_ui, args)
        }
    }

    pub fn start_windows_studio(ui: &mut UI, args: &[OsString]) -> Result<()> {
        let command = match henv::var(super::STUDIO_CMD_ENVVAR) {
            Ok(command) => PathBuf::from(command),
            Err(_) => {
                init();
                let version: Vec<&str> = VERSION.split('/').collect();
                let ident = PackageIdent::from_str(&format!("{}/{}",
                                                            super::STUDIO_PACKAGE_IDENT,
                                                            version[0]))?;
                exec::command_from_min_pkg(ui, super::STUDIO_CMD, &ident)?
            }
        };

        if let Some(cmd) = find_command(command.to_string_lossy().as_ref()) {
            process::become_command(cmd, args)?;
        } else {
            return Err(Error::ExecCommandNotFound(command));
        }
        Ok(())
    }

    fn is_windows_studio(args: &[OsString]) -> bool {
        if cfg!(not(target_os = "windows")) {
            return false;
        }

        for arg in args.iter() {
            let str_arg = arg.to_string_lossy();
            if str_arg == "-D" {
                return false;
            }
        }

        // -w/--windows is deprecated and should be removed in a post 0.64.0 release
        for arg in args.iter() {
            let str_arg = arg.to_string_lossy().to_lowercase();
            if str_arg == "--windows" || str_arg == "-w" {
                return true;
            }
        }

        true
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Base classes to work with IDL callbacks.

use dom::bindings::global::global_object_for_js_object;
use dom::bindings::js::JSRef;
use dom::bindings::utils::Reflectable;
use js::jsapi::{JSContext, JSObject, JS_WrapObject, JS_ObjectIsCallable};
use js::jsapi::JS_GetProperty;
use js::jsval::{JSVal, UndefinedValue};

use std::ptr;

/// The exception handling used for a call.
pub enum ExceptionHandling {
    /// Report any exception and don't throw it to the caller code.
    ReportExceptions,
    /// Throw an exception to the caller code if the thrown exception is a
    /// binding object for a DOMError from the caller's scope, otherwise report
    /// it.
    RethrowContentExceptions,
    /// Throw any exception to the caller code.
    RethrowExceptions
}

/// A common base class for representing IDL callback function types.
#[deriving(Clone,PartialEq)]
#[jstraceable]
pub struct CallbackFunction {
    object: CallbackObject
}

impl CallbackFunction {
    pub fn new(callback: *mut JSObject) -> CallbackFunction {
        CallbackFunction {
            object: CallbackObject {
                callback: callback
            }
        }
    }
}

/// A common base class for representing IDL callback interface types.
#[deriving(Clone,PartialEq)]
#[jstraceable]
pub struct CallbackInterface {
    object: CallbackObject
}

/// A common base class for representing IDL callback function and
/// callback interface types.
#[allow(raw_pointer_deriving)]
#[deriving(Clone,PartialEq)]
#[jstraceable]
struct CallbackObject {
    /// The underlying `JSObject`.
    callback: *mut JSObject,
}

/// A trait to be implemented by concrete IDL callback function and
/// callback interface types.
pub trait CallbackContainer {
    /// Create a new CallbackContainer object for the given `JSObject`.
    fn new(callback: *mut JSObject) -> Self;
    /// Returns the underlying `JSObject`.
    fn callback(&self) -> *mut JSObject;
}

impl CallbackInterface {
    /// Returns the underlying `JSObject`.
    pub fn callback(&self) -> *mut JSObject {
        self.object.callback
    }
}

impl CallbackFunction {
    /// Returns the underlying `JSObject`.
    pub fn callback(&self) -> *mut JSObject {
        self.object.callback
    }
}

impl CallbackInterface {
    /// Create a new CallbackInterface object for the given `JSObject`.
    pub fn new(callback: *mut JSObject) -> CallbackInterface {
        CallbackInterface {
            object: CallbackObject {
                callback: callback
            }
        }
    }

    /// Returns the property with the given `name`, if it is a callable object,
    /// or `Err(())` otherwise. If it returns `Err(())`, a JSAPI exception is
    /// pending.
    pub fn GetCallableProperty(&self, cx: *mut JSContext, name: &str) -> Result<JSVal, ()> {
        let mut callable = UndefinedValue();
        unsafe {
            let name = name.to_c_str();
            if JS_GetProperty(cx, self.callback(), name.as_ptr(), &mut callable) == 0 {
                return Err(());
            }

            if !callable.is_object() ||
               JS_ObjectIsCallable(cx, callable.to_object()) == 0 {
                // FIXME(#347)
                //ThrowErrorMessage(cx, MSG_NOT_CALLABLE, description.get());
                return Err(());
            }
        }
        Ok(callable)
    }
}

/// Wraps the reflector for `p` into the compartment of `cx`.
pub fn WrapCallThisObject<T: Reflectable>(cx: *mut JSContext,
                                          p: JSRef<T>) -> *mut JSObject {
    let mut obj = p.reflector().get_jsobject();
    assert!(obj.is_not_null());

    unsafe {
        if JS_WrapObject(cx, &mut obj) == 0 {
            return ptr::null_mut();
        }
    }

    return obj;
}

/// A class that performs whatever setup we need to safely make a call while
/// this class is on the stack. After `new` returns, the call is safe to make.
pub struct CallSetup {
    /// The `JSContext` used for the call.
    cx: *mut JSContext,
    /// The exception handling used for the call.
    _handling: ExceptionHandling
}

impl CallSetup {
    /// Performs the setup needed to make a call.
    #[allow(unrooted_must_root)]
    pub fn new<T: CallbackContainer>(callback: T, handling: ExceptionHandling) -> CallSetup {
        let global = global_object_for_js_object(callback.callback());
        let global = global.root();
        let cx = global.root_ref().get_cx();
        CallSetup {
            cx: cx,
            _handling: handling
        }
    }

    /// Returns the `JSContext` used for the call.
    pub fn GetContext(&self) -> *mut JSContext {
        self.cx
    }
}
<commit_msg>Document bindings/callback.rs.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![deny(missing_doc)]

//! Base classes to work with IDL callbacks.

use dom::bindings::global::global_object_for_js_object;
use dom::bindings::js::JSRef;
use dom::bindings::utils::Reflectable;
use js::jsapi::{JSContext, JSObject, JS_WrapObject, JS_ObjectIsCallable};
use js::jsapi::JS_GetProperty;
use js::jsval::{JSVal, UndefinedValue};

use std::ptr;

/// The exception handling used for a call.
pub enum ExceptionHandling {
    /// Report any exception and don't throw it to the caller code.
    ReportExceptions,
    /// Throw an exception to the caller code if the thrown exception is a
    /// binding object for a DOMError from the caller's scope, otherwise report
    /// it.
    RethrowContentExceptions,
    /// Throw any exception to the caller code.
    RethrowExceptions
}

/// A common base class for representing IDL callback function types.
#[deriving(Clone,PartialEq)]
#[jstraceable]
pub struct CallbackFunction {
    object: CallbackObject
}

impl CallbackFunction {
    /// Create a new `CallbackFunction` for this object.
    pub fn new(callback: *mut JSObject) -> CallbackFunction {
        CallbackFunction {
            object: CallbackObject {
                callback: callback
            }
        }
    }
}

/// A common base class for representing IDL callback interface types.
#[deriving(Clone,PartialEq)]
#[jstraceable]
pub struct CallbackInterface {
    object: CallbackObject
}

/// A common base class for representing IDL callback function and
/// callback interface types.
#[allow(raw_pointer_deriving)]
#[deriving(Clone,PartialEq)]
#[jstraceable]
struct CallbackObject {
    /// The underlying `JSObject`.
    callback: *mut JSObject,
}

/// A trait to be implemented by concrete IDL callback function and
/// callback interface types.
pub trait CallbackContainer {
    /// Create a new CallbackContainer object for the given `JSObject`.
    fn new(callback: *mut JSObject) -> Self;
    /// Returns the underlying `JSObject`.
    fn callback(&self) -> *mut JSObject;
}

impl CallbackInterface {
    /// Returns the underlying `JSObject`.
    pub fn callback(&self) -> *mut JSObject {
        self.object.callback
    }
}

impl CallbackFunction {
    /// Returns the underlying `JSObject`.
    pub fn callback(&self) -> *mut JSObject {
        self.object.callback
    }
}

impl CallbackInterface {
    /// Create a new CallbackInterface object for the given `JSObject`.
    pub fn new(callback: *mut JSObject) -> CallbackInterface {
        CallbackInterface {
            object: CallbackObject {
                callback: callback
            }
        }
    }

    /// Returns the property with the given `name`, if it is a callable object,
    /// or `Err(())` otherwise. If it returns `Err(())`, a JSAPI exception is
    /// pending.
    pub fn GetCallableProperty(&self, cx: *mut JSContext, name: &str) -> Result<JSVal, ()> {
        let mut callable = UndefinedValue();
        unsafe {
            let name = name.to_c_str();
            if JS_GetProperty(cx, self.callback(), name.as_ptr(), &mut callable) == 0 {
                return Err(());
            }

            if !callable.is_object() ||
               JS_ObjectIsCallable(cx, callable.to_object()) == 0 {
                // FIXME(#347)
                //ThrowErrorMessage(cx, MSG_NOT_CALLABLE, description.get());
                return Err(());
            }
        }
        Ok(callable)
    }
}

/// Wraps the reflector for `p` into the compartment of `cx`.
pub fn WrapCallThisObject<T: Reflectable>(cx: *mut JSContext,
                                          p: JSRef<T>) -> *mut JSObject {
    let mut obj = p.reflector().get_jsobject();
    assert!(obj.is_not_null());

    unsafe {
        if JS_WrapObject(cx, &mut obj) == 0 {
            return ptr::null_mut();
        }
    }

    return obj;
}

/// A class that performs whatever setup we need to safely make a call while
/// this class is on the stack. After `new` returns, the call is safe to make.
pub struct CallSetup {
    /// The `JSContext` used for the call.
    cx: *mut JSContext,
    /// The exception handling used for the call.
    _handling: ExceptionHandling
}

impl CallSetup {
    /// Performs the setup needed to make a call.
    #[allow(unrooted_must_root)]
    pub fn new<T: CallbackContainer>(callback: T, handling: ExceptionHandling) -> CallSetup {
        let global = global_object_for_js_object(callback.callback());
        let global = global.root();
        let cx = global.root_ref().get_cx();
        CallSetup {
            cx: cx,
            _handling: handling
        }
    }

    /// Returns the `JSContext` used for the call.
    pub fn GetContext(&self) -> *mut JSContext {
        self.cx
    }
}
<|endoftext|>


<commit_before>// Generated from pipe compiler
mod stream {
    fn init<T: send>() -> (client::stream<T>, server::stream<T>) {
        pipes::entangle()
    }
    enum stream<T: send> { send(T, server::stream<T>), }
    mod client {
        fn send<T: send>(+pipe: stream<T>, +x_0: T) -> stream<T> {
            {
                let (c, s) = pipes::entangle();
                let message = stream::send(x_0, s);
                pipes::send(pipe, message);
                c
            }
        }
        type stream<T: send> = pipes::send_packet<stream::stream<T>>;
    }
    mod server {
        type stream<T: send> = pipes::recv_packet<stream::stream<T>>;
    }
}

fn main() {
    let (bc, _bp) = stream::init();

    stream::client::send(bc, ~"abc");
}
<commit_msg>Use a proper protocol definition instead of the already-expanded code.<commit_after>proto! stream {
    stream:send<T:send> {
        send(T) -> stream<T>
    }
}

fn main() {
    let (bc, _bp) = stream::init();

    stream::client::send(bc, ~"abc");
}
<|endoftext|>


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

#![allow(experimental)]

use std::unstable::simd::{i32x4, f32x4, u32x4};

fn test_int(e: i32) -> i32 {
    let v = i32x4(e, 0i32, 0i32, 0i32);
    let i32x4(e2, _, _, _) = v * v + v - v;
    e2
}

fn test_float(e: f32) -> f32 {
    let v = f32x4(e, 0f32, 0f32, 0f32);
    let f32x4(e2, _, _, _) = v * v + v - v;
    e2
}

pub fn test_shift(e: u32) -> u32 {
    let v = u32x4(e, 0u32, 0u32, 0u32);
    let one = u32x4(1u32, 0u32, 0u32, 0u32);
    let u32x4(e2, _, _, _) = v << one >> one;
    e2
}

pub fn main() {
    assert_eq!(test_int(3i32), 9i32);
    assert_eq!(test_float(3f32), 9f32);
    assert_eq!(test_shift(3u32), 3u32);
}
<commit_msg>Add more comprehensive unit tests for SIMD binops<commit_after>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(experimental)]

use std::unstable::simd::{i32x4, f32x4, u32x4};

fn eq_u32x4(u32x4(x0, x1, x2, x3): u32x4, u32x4(y0, y1, y2, y3): u32x4) -> bool {
    (x0 == y0) && (x1 == y1) && (x2 == y2) && (x3 == y3)
}

fn eq_f32x4(f32x4(x0, x1, x2, x3): f32x4, f32x4(y0, y1, y2, y3): f32x4) -> bool {
    (x0 == y0) && (x1 == y1) && (x2 == y2) && (x3 == y3)
}

fn eq_i32x4(i32x4(x0, x1, x2, x3): i32x4, i32x4(y0, y1, y2, y3): i32x4) -> bool {
    (x0 == y0) && (x1 == y1) && (x2 == y2) && (x3 == y3)
}

pub fn main() {
    assert!(eq_u32x4(u32x4(1, 2, 3, 4) + u32x4(4, 3, 2, 1), u32x4(5, 5, 5, 5)));
    assert!(eq_u32x4(u32x4(4, 5, 6, 7) - u32x4(4, 3, 2, 1), u32x4(0, 2, 4, 6)));
    assert!(eq_u32x4(u32x4(1, 2, 3, 4) * u32x4(4, 3, 2, 1), u32x4(4, 6, 6, 4)));
    assert!(eq_u32x4(u32x4(1, 2, 3, 4) & u32x4(4, 3, 2, 1), u32x4(0, 2, 2, 0)));
    assert!(eq_u32x4(u32x4(1, 2, 3, 4) | u32x4(4, 3, 2, 1), u32x4(5, 3, 3, 5)));
    assert!(eq_u32x4(u32x4(1, 2, 3, 4) ^ u32x4(4, 3, 2, 1), u32x4(5, 1, 1, 5)));
    assert!(eq_u32x4(u32x4(1, 2, 3, 4) << u32x4(4, 3, 2, 1), u32x4(16, 16, 12, 8)));
    assert!(eq_u32x4(u32x4(1, 2, 3, 4) >> u32x4(4, 3, 2, 1), u32x4(0, 0, 0, 2)));

    assert!(eq_i32x4(i32x4(1, 2, 3, 4) + i32x4(4, 3, 2, 1), i32x4(5, 5, 5, 5)));
    assert!(eq_i32x4(i32x4(1, 2, 3, 4) - i32x4(4, 3, 2, 1), i32x4(-3, -1, 1, 3)));
    assert!(eq_i32x4(i32x4(1, 2, 3, 4) * i32x4(4, 3, 2, 1), i32x4(4, 6, 6, 4)));
    assert!(eq_i32x4(i32x4(1, 2, 3, 4) & i32x4(4, 3, 2, 1), i32x4(0, 2, 2, 0)));
    assert!(eq_i32x4(i32x4(1, 2, 3, 4) | i32x4(4, 3, 2, 1), i32x4(5, 3, 3, 5)));
    assert!(eq_i32x4(i32x4(1, 2, 3, 4) ^ i32x4(4, 3, 2, 1), i32x4(5, 1, 1, 5)));
    assert!(eq_i32x4(i32x4(1, 2, 3, 4) << i32x4(4, 3, 2, 1), i32x4(16, 16, 12, 8)));
    assert!(eq_i32x4(i32x4(1, 2, 3, 4) >> i32x4(4, 3, 2, 1), i32x4(0, 0, 0, 2)));

    assert!(eq_f32x4(f32x4(1.0, 2.0, 3.0, 4.0) + f32x4(4.0, 3.0, 2.0, 1.0), f32x4(5.0, 5.0, 5.0, 5.0)));
    assert!(eq_f32x4(f32x4(1.0, 2.0, 3.0, 4.0) - f32x4(4.0, 3.0, 2.0, 1.0), f32x4(-3.0, -1.0, 1.0, 3.0)));
    assert!(eq_f32x4(f32x4(1.0, 2.0, 3.0, 4.0) * f32x4(4.0, 3.0, 2.0, 1.0), f32x4(4.0, 6.0, 6.0, 4.0)));
    assert!(eq_f32x4(f32x4(1.0, 2.0, 3.0, 4.0) / f32x4(4.0, 4.0, 2.0, 1.0), f32x4(0.25, 0.5, 1.5, 4.0)));
}
<|endoftext|>


<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.

/// Blah blah blah
/// ``` ignore
/// bad_assert!();
/// ```
pub fn foo() {}
<commit_msg>Remove whitespace<commit_after>// Copyright 2018 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.

/// Blah blah blah
/// ```ignore
/// bad_assert!();
/// ```
pub fn foo() {}
<|endoftext|>


<commit_before>// We share an instance of this type among all the destructor-order
// checkers.  It tracks how many destructors have run so far and
// 'fail's when one runs out of order.
// FIXME: Make it easier to collect a failure message.
state obj order_tracker(mutable int init) {
  fn assert_order(int expected, str fail_message) {
    if (expected != init) {
      log expected;
      log " != ";
      log init;
      log fail_message;
      fail;
    }
    init += 1;
  }
}

obj dorder(@order_tracker tracker, int order, str message) {
  drop {
    (*tracker).assert_order(order, message);
  }
}

fn test_simple() {
  auto tracker = @order_tracker(0);
  dorder(tracker, 1, "Reverse decl order");
  dorder(tracker, 0, "Reverse decl order");
}

fn test_block() {
  auto tracker = @order_tracker(0);
  dorder(tracker, 2, "Before block");
  {
    dorder(tracker, 0, "Inside block");
  }
  dorder(tracker, 1, "After block");
}

fn test_decl_v_init() {
  auto tracker = @order_tracker(0);
  auto var1;
  auto var2;
  var2 = dorder(tracker, 0, "decl, not init");
  var1 = dorder(tracker, 1, "decl, not init");
}

fn test_overwritten_obj() {
  auto tracker = @order_tracker(0);
  auto var1 = dorder(tracker, 0, "overwritten object destroyed first");
  auto var2 = dorder(tracker, 2, "destroyed at end of scope");
  var1 = dorder(tracker, 3, "overwriter deleted in rev decl order");
  {
    dorder(tracker, 1, "overwritten object destroyed before end of scope");
  }
}

// Used to embed dorder objects into an expression.  Note that the
// parameters don't get destroyed.
fn combine_dorders(dorder d1, dorder d2) -> int {
  ret 1;
}
fn test_expression_destroyed_right_to_left() {
  auto tracker = @order_tracker(0);
  combine_dorders(dorder(tracker, 4, ""), dorder(tracker, 3, ""))
    / combine_dorders(dorder(tracker, 2, ""), dorder(tracker, 1, ""));
  {
    dorder(tracker, 0,
           "expression objects live to end of block, not statement");
  }
}

fn main() {
  test_simple();
  test_block();
  test_decl_v_init();
  test_overwritten_obj();
  test_expression_destroyed_right_to_left();
}
<commit_msg>Remove explicit deref workaround in dtor-order test.  No longer necessary.<commit_after>// We share an instance of this type among all the destructor-order
// checkers.  It tracks how many destructors have run so far and
// 'fail's when one runs out of order.
// FIXME: Make it easier to collect a failure message.
state obj order_tracker(mutable int init) {
  fn assert_order(int expected, str fail_message) {
    if (expected != init) {
      log expected;
      log " != ";
      log init;
      log fail_message;
      fail;
    }
    init += 1;
  }
}

obj dorder(@order_tracker tracker, int order, str message) {
  drop {
    tracker.assert_order(order, message);
  }
}

fn test_simple() {
  auto tracker = @order_tracker(0);
  dorder(tracker, 1, "Reverse decl order");
  dorder(tracker, 0, "Reverse decl order");
}

fn test_block() {
  auto tracker = @order_tracker(0);
  dorder(tracker, 2, "Before block");
  {
    dorder(tracker, 0, "Inside block");
  }
  dorder(tracker, 1, "After block");
}

fn test_decl_v_init() {
  auto tracker = @order_tracker(0);
  auto var1;
  auto var2;
  var2 = dorder(tracker, 0, "decl, not init");
  var1 = dorder(tracker, 1, "decl, not init");
}

fn test_overwritten_obj() {
  auto tracker = @order_tracker(0);
  auto var1 = dorder(tracker, 0, "overwritten object destroyed first");
  auto var2 = dorder(tracker, 2, "destroyed at end of scope");
  var1 = dorder(tracker, 3, "overwriter deleted in rev decl order");
  {
    dorder(tracker, 1, "overwritten object destroyed before end of scope");
  }
}

// Used to embed dorder objects into an expression.  Note that the
// parameters don't get destroyed.
fn combine_dorders(dorder d1, dorder d2) -> int {
  ret 1;
}
fn test_expression_destroyed_right_to_left() {
  auto tracker = @order_tracker(0);
  combine_dorders(dorder(tracker, 4, ""), dorder(tracker, 3, ""))
    / combine_dorders(dorder(tracker, 2, ""), dorder(tracker, 1, ""));
  {
    dorder(tracker, 0,
           "expression objects live to end of block, not statement");
  }
}

fn main() {
  test_simple();
  test_block();
  test_decl_v_init();
  test_overwritten_obj();
  test_expression_destroyed_right_to_left();
}
<|endoftext|>