<commit_before>use crate::ast::{self, NodeId};
use crate::source_map::{DUMMY_SP, dummy_spanned};
use crate::ext::base::ExtCtxt;
use crate::ext::expand::{AstFragment, AstFragmentKind};
use crate::tokenstream::TokenStream;
use crate::mut_visit::*;
use crate::ptr::P;
use crate::ThinVec;

use smallvec::{smallvec, SmallVec};

use rustc_data_structures::fx::FxHashMap;

pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment {
    fn mac_placeholder() -> ast::Mac {
        ast::Mac {
            path: ast::Path { span: DUMMY_SP, segments: Vec::new() },
            tts: TokenStream::default().into(),
            delim: ast::MacDelimiter::Brace,
            span: DUMMY_SP,
            prior_type_ascription: None,
        }
    }

    let ident = ast::Ident::invalid();
    let attrs = Vec::new();
    let generics = ast::Generics::default();
    let vis = dummy_spanned(ast::VisibilityKind::Inherited);
    let span = DUMMY_SP;
    let expr_placeholder = || P(ast::Expr {
        id, span,
        attrs: ThinVec::new(),
        kind: ast::ExprKind::Mac(mac_placeholder()),
    });
    let ty = P(ast::Ty {
        id,
        kind: ast::TyKind::Mac(mac_placeholder()),
        span,
    });
    let pat = P(ast::Pat {
        id,
        kind: ast::PatKind::Mac(mac_placeholder()),
        span,
    });

    match kind {
        AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()),
        AstFragmentKind::OptExpr => AstFragment::OptExpr(Some(expr_placeholder())),
        AstFragmentKind::Items => AstFragment::Items(smallvec![P(ast::Item {
            id, span, ident, vis, attrs,
            kind: ast::ItemKind::Mac(mac_placeholder()),
            tokens: None,
        })]),
        AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![ast::TraitItem {
            id, span, ident, attrs, generics,
            kind: ast::TraitItemKind::Macro(mac_placeholder()),
            tokens: None,
        }]),
        AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![ast::ImplItem {
            id, span, ident, vis, attrs, generics,
            kind: ast::ImplItemKind::Macro(mac_placeholder()),
            defaultness: ast::Defaultness::Final,
            tokens: None,
        }]),
        AstFragmentKind::ForeignItems =>
            AstFragment::ForeignItems(smallvec![ast::ForeignItem {
                id, span, ident, vis, attrs,
                kind: ast::ForeignItemKind::Macro(mac_placeholder()),
            }]),
        AstFragmentKind::Pat => AstFragment::Pat(P(ast::Pat {
            id, span, kind: ast::PatKind::Mac(mac_placeholder()),
        })),
        AstFragmentKind::Ty => AstFragment::Ty(P(ast::Ty {
            id, span, kind: ast::TyKind::Mac(mac_placeholder()),
        })),
        AstFragmentKind::Stmts => AstFragment::Stmts(smallvec![{
            let mac = P((mac_placeholder(), ast::MacStmtStyle::Braces, ThinVec::new()));
            ast::Stmt { id, span, kind: ast::StmtKind::Mac(mac) }
        }]),
        AstFragmentKind::Arms => AstFragment::Arms(smallvec![
            ast::Arm {
                attrs: Default::default(),
                body: expr_placeholder(),
                guard: None,
                id,
                pat,
                span,
                is_placeholder: true,
            }
        ]),
        AstFragmentKind::Fields => AstFragment::Fields(smallvec![
            ast::Field {
                attrs: Default::default(),
                expr: expr_placeholder(),
                id,
                ident,
                is_shorthand: false,
                span,
                is_placeholder: true,
            }
        ]),
        AstFragmentKind::FieldPats => AstFragment::FieldPats(smallvec![
            ast::FieldPat {
                attrs: Default::default(),
                id,
                ident,
                is_shorthand: false,
                pat,
                span,
                is_placeholder: true,
            }
        ]),
        AstFragmentKind::GenericParams => AstFragment::GenericParams(smallvec![{
            ast::GenericParam {
                attrs: Default::default(),
                bounds: Default::default(),
                id,
                ident,
                is_placeholder: true,
                kind: ast::GenericParamKind::Lifetime,
            }
        }]),
        AstFragmentKind::Params => AstFragment::Params(smallvec![
            ast::Param {
                attrs: Default::default(),
                id,
                pat,
                span,
                ty,
                is_placeholder: true,
            }
        ]),
        AstFragmentKind::StructFields => AstFragment::StructFields(smallvec![
            ast::StructField {
                attrs: Default::default(),
                id,
                ident: None,
                span,
                ty,
                vis,
                is_placeholder: true,
            }
        ]),
        AstFragmentKind::Variants => AstFragment::Variants(smallvec![
            ast::Variant {
                attrs: Default::default(),
                data: ast::VariantData::Struct(Default::default(), false),
                disr_expr: None,
                id,
                ident,
                span,
                is_placeholder: true,
            }
        ])
    }
}

pub struct PlaceholderExpander<'a, 'b> {
    expanded_fragments: FxHashMap<ast::NodeId, AstFragment>,
    cx: &'a mut ExtCtxt<'b>,
    monotonic: bool,
}

impl<'a, 'b> PlaceholderExpander<'a, 'b> {
    pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
        PlaceholderExpander {
            cx,
            expanded_fragments: FxHashMap::default(),
            monotonic,
        }
    }

    pub fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment, placeholders: Vec<NodeId>) {
        fragment.mut_visit_with(self);
        if let AstFragment::Items(mut items) = fragment {
            for placeholder in placeholders {
                match self.remove(placeholder) {
                    AstFragment::Items(derived_items) => items.extend(derived_items),
                    _ => unreachable!(),
                }
            }
            fragment = AstFragment::Items(items);
        }
        self.expanded_fragments.insert(id, fragment);
    }

    fn remove(&mut self, id: ast::NodeId) -> AstFragment {
        self.expanded_fragments.remove(&id).unwrap()
    }
}

impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> {
    fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
        if arm.is_placeholder {
            self.remove(arm.id).make_arms()
        } else {
            noop_flat_map_arm(arm, self)
        }
    }

    fn flat_map_field(&mut self, field: ast::Field) -> SmallVec<[ast::Field; 1]> {
        if field.is_placeholder {
            self.remove(field.id).make_fields()
        } else {
            noop_flat_map_field(field, self)
        }
    }

    fn flat_map_field_pattern(&mut self, fp: ast::FieldPat) -> SmallVec<[ast::FieldPat; 1]> {
        if fp.is_placeholder {
            self.remove(fp.id).make_field_patterns()
        } else {
            noop_flat_map_field_pattern(fp, self)
        }
    }

    fn flat_map_generic_param(
        &mut self,
        param: ast::GenericParam
    ) -> SmallVec<[ast::GenericParam; 1]>
    {
        if param.is_placeholder {
            self.remove(param.id).make_generic_params()
        } else {
            noop_flat_map_generic_param(param, self)
        }
    }

    fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> {
        if p.is_placeholder {
            self.remove(p.id).make_params()
        } else {
            noop_flat_map_param(p, self)
        }
    }

    fn flat_map_struct_field(&mut self, sf: ast::StructField) -> SmallVec<[ast::StructField; 1]> {
        if sf.is_placeholder {
            self.remove(sf.id).make_struct_fields()
        } else {
            noop_flat_map_struct_field(sf, self)
        }
    }

    fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> {
        if variant.is_placeholder {
            self.remove(variant.id).make_variants()
        } else {
            noop_flat_map_variant(variant, self)
        }
    }

    fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
        match item.kind {
            ast::ItemKind::Mac(_) => return self.remove(item.id).make_items(),
            ast::ItemKind::MacroDef(_) => return smallvec![item],
            _ => {}
        }

        noop_flat_map_item(item, self)
    }

    fn flat_map_trait_item(&mut self, item: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> {
        match item.kind {
            ast::TraitItemKind::Macro(_) => self.remove(item.id).make_trait_items(),
            _ => noop_flat_map_trait_item(item, self),
        }
    }

    fn flat_map_impl_item(&mut self, item: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> {
        match item.kind {
            ast::ImplItemKind::Macro(_) => self.remove(item.id).make_impl_items(),
            _ => noop_flat_map_impl_item(item, self),
        }
    }

    fn flat_map_foreign_item(&mut self, item: ast::ForeignItem) -> SmallVec<[ast::ForeignItem; 1]> {
        match item.kind {
            ast::ForeignItemKind::Macro(_) => self.remove(item.id).make_foreign_items(),
            _ => noop_flat_map_foreign_item(item, self),
        }
    }

    fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
        match expr.kind {
            ast::ExprKind::Mac(_) => *expr = self.remove(expr.id).make_expr(),
            _ => noop_visit_expr(expr, self),
        }
    }

    fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
        match expr.kind {
            ast::ExprKind::Mac(_) => self.remove(expr.id).make_opt_expr(),
            _ => noop_filter_map_expr(expr, self),
        }
    }

    fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
        let (style, mut stmts) = match stmt.kind {
            ast::StmtKind::Mac(mac) => (mac.1, self.remove(stmt.id).make_stmts()),
            _ => return noop_flat_map_stmt(stmt, self),
        };

        if style == ast::MacStmtStyle::Semicolon {
            if let Some(stmt) = stmts.pop() {
                stmts.push(stmt.add_trailing_semicolon());
            }
        }

        stmts
    }

    fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
        match pat.kind {
            ast::PatKind::Mac(_) => *pat = self.remove(pat.id).make_pat(),
            _ => noop_visit_pat(pat, self),
        }
    }

    fn visit_ty(&mut self, ty: &mut P<ast::Ty>) {
        match ty.kind {
            ast::TyKind::Mac(_) => *ty = self.remove(ty.id).make_ty(),
            _ => noop_visit_ty(ty, self),
        }
    }

    fn visit_block(&mut self, block: &mut P<ast::Block>) {
        noop_visit_block(block, self);

        for stmt in block.stmts.iter_mut() {
            if self.monotonic {
                assert_eq!(stmt.id, ast::DUMMY_NODE_ID);
                stmt.id = self.cx.resolver.next_node_id();
            }
        }
    }

    fn visit_mod(&mut self, module: &mut ast::Mod) {
        noop_visit_mod(module, self);
        module.items.retain(|item| match item.kind {
            ast::ItemKind::Mac(_) if !self.cx.ecfg.keep_macs => false, // remove macro definitions
            _ => true,
        });
    }

    fn visit_mac(&mut self, _mac: &mut ast::Mac) {
        // Do nothing.
    }
}
<commit_msg>Lazify some `mac_placeholder()` calls.<commit_after>use crate::ast::{self, NodeId};
use crate::source_map::{DUMMY_SP, dummy_spanned};
use crate::ext::base::ExtCtxt;
use crate::ext::expand::{AstFragment, AstFragmentKind};
use crate::tokenstream::TokenStream;
use crate::mut_visit::*;
use crate::ptr::P;
use crate::ThinVec;

use smallvec::{smallvec, SmallVec};

use rustc_data_structures::fx::FxHashMap;

pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment {
    fn mac_placeholder() -> ast::Mac {
        ast::Mac {
            path: ast::Path { span: DUMMY_SP, segments: Vec::new() },
            tts: TokenStream::default().into(),
            delim: ast::MacDelimiter::Brace,
            span: DUMMY_SP,
            prior_type_ascription: None,
        }
    }

    let ident = ast::Ident::invalid();
    let attrs = Vec::new();
    let generics = ast::Generics::default();
    let vis = dummy_spanned(ast::VisibilityKind::Inherited);
    let span = DUMMY_SP;
    let expr_placeholder = || P(ast::Expr {
        id, span,
        attrs: ThinVec::new(),
        kind: ast::ExprKind::Mac(mac_placeholder()),
    });
    let ty = || P(ast::Ty {
        id,
        kind: ast::TyKind::Mac(mac_placeholder()),
        span,
    });
    let pat = || P(ast::Pat {
        id,
        kind: ast::PatKind::Mac(mac_placeholder()),
        span,
    });

    match kind {
        AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()),
        AstFragmentKind::OptExpr => AstFragment::OptExpr(Some(expr_placeholder())),
        AstFragmentKind::Items => AstFragment::Items(smallvec![P(ast::Item {
            id, span, ident, vis, attrs,
            kind: ast::ItemKind::Mac(mac_placeholder()),
            tokens: None,
        })]),
        AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![ast::TraitItem {
            id, span, ident, attrs, generics,
            kind: ast::TraitItemKind::Macro(mac_placeholder()),
            tokens: None,
        }]),
        AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![ast::ImplItem {
            id, span, ident, vis, attrs, generics,
            kind: ast::ImplItemKind::Macro(mac_placeholder()),
            defaultness: ast::Defaultness::Final,
            tokens: None,
        }]),
        AstFragmentKind::ForeignItems =>
            AstFragment::ForeignItems(smallvec![ast::ForeignItem {
                id, span, ident, vis, attrs,
                kind: ast::ForeignItemKind::Macro(mac_placeholder()),
            }]),
        AstFragmentKind::Pat => AstFragment::Pat(P(ast::Pat {
            id, span, kind: ast::PatKind::Mac(mac_placeholder()),
        })),
        AstFragmentKind::Ty => AstFragment::Ty(P(ast::Ty {
            id, span, kind: ast::TyKind::Mac(mac_placeholder()),
        })),
        AstFragmentKind::Stmts => AstFragment::Stmts(smallvec![{
            let mac = P((mac_placeholder(), ast::MacStmtStyle::Braces, ThinVec::new()));
            ast::Stmt { id, span, kind: ast::StmtKind::Mac(mac) }
        }]),
        AstFragmentKind::Arms => AstFragment::Arms(smallvec![
            ast::Arm {
                attrs: Default::default(),
                body: expr_placeholder(),
                guard: None,
                id,
                pat: pat(),
                span,
                is_placeholder: true,
            }
        ]),
        AstFragmentKind::Fields => AstFragment::Fields(smallvec![
            ast::Field {
                attrs: Default::default(),
                expr: expr_placeholder(),
                id,
                ident,
                is_shorthand: false,
                span,
                is_placeholder: true,
            }
        ]),
        AstFragmentKind::FieldPats => AstFragment::FieldPats(smallvec![
            ast::FieldPat {
                attrs: Default::default(),
                id,
                ident,
                is_shorthand: false,
                pat: pat(),
                span,
                is_placeholder: true,
            }
        ]),
        AstFragmentKind::GenericParams => AstFragment::GenericParams(smallvec![{
            ast::GenericParam {
                attrs: Default::default(),
                bounds: Default::default(),
                id,
                ident,
                is_placeholder: true,
                kind: ast::GenericParamKind::Lifetime,
            }
        }]),
        AstFragmentKind::Params => AstFragment::Params(smallvec![
            ast::Param {
                attrs: Default::default(),
                id,
                pat: pat(),
                span,
                ty: ty(),
                is_placeholder: true,
            }
        ]),
        AstFragmentKind::StructFields => AstFragment::StructFields(smallvec![
            ast::StructField {
                attrs: Default::default(),
                id,
                ident: None,
                span,
                ty: ty(),
                vis,
                is_placeholder: true,
            }
        ]),
        AstFragmentKind::Variants => AstFragment::Variants(smallvec![
            ast::Variant {
                attrs: Default::default(),
                data: ast::VariantData::Struct(Default::default(), false),
                disr_expr: None,
                id,
                ident,
                span,
                is_placeholder: true,
            }
        ])
    }
}

pub struct PlaceholderExpander<'a, 'b> {
    expanded_fragments: FxHashMap<ast::NodeId, AstFragment>,
    cx: &'a mut ExtCtxt<'b>,
    monotonic: bool,
}

impl<'a, 'b> PlaceholderExpander<'a, 'b> {
    pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
        PlaceholderExpander {
            cx,
            expanded_fragments: FxHashMap::default(),
            monotonic,
        }
    }

    pub fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment, placeholders: Vec<NodeId>) {
        fragment.mut_visit_with(self);
        if let AstFragment::Items(mut items) = fragment {
            for placeholder in placeholders {
                match self.remove(placeholder) {
                    AstFragment::Items(derived_items) => items.extend(derived_items),
                    _ => unreachable!(),
                }
            }
            fragment = AstFragment::Items(items);
        }
        self.expanded_fragments.insert(id, fragment);
    }

    fn remove(&mut self, id: ast::NodeId) -> AstFragment {
        self.expanded_fragments.remove(&id).unwrap()
    }
}

impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> {
    fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
        if arm.is_placeholder {
            self.remove(arm.id).make_arms()
        } else {
            noop_flat_map_arm(arm, self)
        }
    }

    fn flat_map_field(&mut self, field: ast::Field) -> SmallVec<[ast::Field; 1]> {
        if field.is_placeholder {
            self.remove(field.id).make_fields()
        } else {
            noop_flat_map_field(field, self)
        }
    }

    fn flat_map_field_pattern(&mut self, fp: ast::FieldPat) -> SmallVec<[ast::FieldPat; 1]> {
        if fp.is_placeholder {
            self.remove(fp.id).make_field_patterns()
        } else {
            noop_flat_map_field_pattern(fp, self)
        }
    }

    fn flat_map_generic_param(
        &mut self,
        param: ast::GenericParam
    ) -> SmallVec<[ast::GenericParam; 1]>
    {
        if param.is_placeholder {
            self.remove(param.id).make_generic_params()
        } else {
            noop_flat_map_generic_param(param, self)
        }
    }

    fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> {
        if p.is_placeholder {
            self.remove(p.id).make_params()
        } else {
            noop_flat_map_param(p, self)
        }
    }

    fn flat_map_struct_field(&mut self, sf: ast::StructField) -> SmallVec<[ast::StructField; 1]> {
        if sf.is_placeholder {
            self.remove(sf.id).make_struct_fields()
        } else {
            noop_flat_map_struct_field(sf, self)
        }
    }

    fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> {
        if variant.is_placeholder {
            self.remove(variant.id).make_variants()
        } else {
            noop_flat_map_variant(variant, self)
        }
    }

    fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
        match item.kind {
            ast::ItemKind::Mac(_) => return self.remove(item.id).make_items(),
            ast::ItemKind::MacroDef(_) => return smallvec![item],
            _ => {}
        }

        noop_flat_map_item(item, self)
    }

    fn flat_map_trait_item(&mut self, item: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> {
        match item.kind {
            ast::TraitItemKind::Macro(_) => self.remove(item.id).make_trait_items(),
            _ => noop_flat_map_trait_item(item, self),
        }
    }

    fn flat_map_impl_item(&mut self, item: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> {
        match item.kind {
            ast::ImplItemKind::Macro(_) => self.remove(item.id).make_impl_items(),
            _ => noop_flat_map_impl_item(item, self),
        }
    }

    fn flat_map_foreign_item(&mut self, item: ast::ForeignItem) -> SmallVec<[ast::ForeignItem; 1]> {
        match item.kind {
            ast::ForeignItemKind::Macro(_) => self.remove(item.id).make_foreign_items(),
            _ => noop_flat_map_foreign_item(item, self),
        }
    }

    fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
        match expr.kind {
            ast::ExprKind::Mac(_) => *expr = self.remove(expr.id).make_expr(),
            _ => noop_visit_expr(expr, self),
        }
    }

    fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
        match expr.kind {
            ast::ExprKind::Mac(_) => self.remove(expr.id).make_opt_expr(),
            _ => noop_filter_map_expr(expr, self),
        }
    }

    fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
        let (style, mut stmts) = match stmt.kind {
            ast::StmtKind::Mac(mac) => (mac.1, self.remove(stmt.id).make_stmts()),
            _ => return noop_flat_map_stmt(stmt, self),
        };

        if style == ast::MacStmtStyle::Semicolon {
            if let Some(stmt) = stmts.pop() {
                stmts.push(stmt.add_trailing_semicolon());
            }
        }

        stmts
    }

    fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
        match pat.kind {
            ast::PatKind::Mac(_) => *pat = self.remove(pat.id).make_pat(),
            _ => noop_visit_pat(pat, self),
        }
    }

    fn visit_ty(&mut self, ty: &mut P<ast::Ty>) {
        match ty.kind {
            ast::TyKind::Mac(_) => *ty = self.remove(ty.id).make_ty(),
            _ => noop_visit_ty(ty, self),
        }
    }

    fn visit_block(&mut self, block: &mut P<ast::Block>) {
        noop_visit_block(block, self);

        for stmt in block.stmts.iter_mut() {
            if self.monotonic {
                assert_eq!(stmt.id, ast::DUMMY_NODE_ID);
                stmt.id = self.cx.resolver.next_node_id();
            }
        }
    }

    fn visit_mod(&mut self, module: &mut ast::Mod) {
        noop_visit_mod(module, self);
        module.items.retain(|item| match item.kind {
            ast::ItemKind::Mac(_) if !self.cx.ecfg.keep_macs => false, // remove macro definitions
            _ => true,
        });
    }

    fn visit_mac(&mut self, _mac: &mut ast::Mac) {
        // Do nothing.
    }
}
<|endoftext|>


<commit_before>#[phase(plugin)]
extern crate gfx_macros;

use gfx;
use gfx::{Device, DeviceHelper, BufferHandle, VertexFormat};
use gfx::shade::{ShaderParam, TextureParam};
use device;
use device::draw::CommandBuffer;
use image;
use image::{GenericImage, ImageBuf, MutableRefImage, Pixel, Rgba, SubImage};

pub mod buffer;
pub mod program;

#[vertex_format]
pub struct Vertex {
    #[as_float]
    pub pos: [f32, ..3],
    #[as_float]
    pub uv: [f32, ..2],
    #[as_float]
    pub color: [f32, ..3]
}

#[shader_param(Program)]
pub struct Params {
    #[name = "projection"]
    pub projection: [[f32, ..4], ..4],
    #[name = "view"]
    pub view: [[f32, ..4], ..4],
    #[name = "s_texture"]
    pub texture: TextureParam
}

impl Vertex {
    pub fn new(pos: [f32, ..3], uv: [f32, ..2], color: [f32, ..3]) -> Vertex {
        Vertex {
            pos: pos,
            uv: uv,
            color: color
        }
    }
}

impl Clone for Vertex {
    fn clone(&self) -> Vertex {
        *self
    }
}

pub struct Texture {
    pub handle: gfx::TextureHandle,
    width: u32,
    height: u32
}

impl Texture {
    /// Loads image by relative file name to the asset root.
    pub fn from_file<D: Device<C>, C: CommandBuffer>(path: &Path, d: &mut D) -> Result<Texture, String> {
        Ok(Texture::from_rgba8(try!(load_rgba8(path)), d))
    }

    pub fn from_rgba8<D: Device<C>, C: CommandBuffer>(img: ImageBuf<Rgba<u8>>, d: &mut D) -> Texture {
        let (width, height) = img.dimensions();

        let mut ti = gfx::tex::TextureInfo::new();
        ti.width = width as u16;
        ti.height = height as u16;
        ti.kind = gfx::tex::Texture2D;
        ti.format = gfx::tex::RGBA8;

        let tex = d.create_texture(ti).unwrap();

        d.update_texture(&tex, &ti.to_image_info(), &img.into_vec()).unwrap();
        d.generate_mipmap(&tex);

        Texture {
            handle: tex,
            width: width,
            height: height
        }
    }
}

fn load_rgba8(path: &Path) -> Result<ImageBuf<Rgba<u8>>, String> {
    match image::open(path) {
        Ok(image::ImageRgba8(img)) => Ok(img),
        Ok(image::ImageRgb8(img)) => {
            let (w, h) = img.dimensions();
            Ok(ImageBuf::from_fn(w, h, |x, y| img.get_pixel(x, y).to_rgba()))
        }
        Ok(img) => return Err(format!("Unsupported color type {} in '{}'",
                                      img.color(), path.display())),
        Err(e) => return Err(format!("Could not load '{}': {}", path.display(), e))
    }
}

pub struct Renderer<D: Device<C>, C: CommandBuffer> {
    pub graphics: gfx::Graphics<D, C>,
    frame: gfx::Frame,
    clear_data: gfx::ClearData,
    drawstate: gfx::DrawState
}

impl<D: Device<C>, C: CommandBuffer> Renderer<D, C> {
    pub fn new(mut device: D, frame: gfx::Frame) -> Renderer<D, C> {
        let mut drawstate = gfx::DrawState::new().depth(gfx::state::LessEqual, true);
        drawstate.primitive.front_face = gfx::state::Clockwise;

        Renderer {
            graphics: gfx::Graphics::new(device),
            frame: frame,
            clear_data: gfx::ClearData {
                color: Some([0.05, 0.0, 0.06, 1.0]),
                depth: Some(1.0),
                stencil: None,
            },
            drawstate: drawstate,
        }
    }

    pub fn clear(&mut self) {
        self.graphics.clear(self.clear_data, &self.frame);
    }

    pub fn render<V: VertexFormat, P: ShaderParam<L>, L>(&mut self,
                                                         buffer: buffer::Buffer<V, P, L>,
                                                         params: P) {
        self.graphics.draw(&buffer.batch, &params, &self.frame);
    }

    pub fn end_frame(&mut self) {
        self.graphics.end_frame();
    }
}
<commit_msg>Removed unused imports.<commit_after>#[phase(plugin)]
extern crate gfx_macros;

use gfx;
use gfx::{Device, VertexFormat};
use gfx::shade::{ShaderParam, TextureParam};
use device;
use device::draw::CommandBuffer;
use image;
use image::{GenericImage, ImageBuf, MutableRefImage, Pixel, Rgba};

pub mod buffer;
pub mod program;

#[vertex_format]
pub struct Vertex {
    #[as_float]
    pub pos: [f32, ..3],
    #[as_float]
    pub uv: [f32, ..2],
    #[as_float]
    pub color: [f32, ..3]
}

#[shader_param(Program)]
pub struct Params {
    #[name = "projection"]
    pub projection: [[f32, ..4], ..4],
    #[name = "view"]
    pub view: [[f32, ..4], ..4],
    #[name = "s_texture"]
    pub texture: TextureParam
}

impl Vertex {
    pub fn new(pos: [f32, ..3], uv: [f32, ..2], color: [f32, ..3]) -> Vertex {
        Vertex {
            pos: pos,
            uv: uv,
            color: color
        }
    }
}

impl Clone for Vertex {
    fn clone(&self) -> Vertex {
        *self
    }
}

pub struct Texture {
    pub handle: gfx::TextureHandle,
    width: u32,
    height: u32
}

impl Texture {
    /// Loads image by relative file name to the asset root.
    pub fn from_file<D: Device<C>, C: CommandBuffer>(path: &Path, d: &mut D) -> Result<Texture, String> {
        Ok(Texture::from_rgba8(try!(load_rgba8(path)), d))
    }

    pub fn from_rgba8<D: Device<C>, C: CommandBuffer>(img: ImageBuf<Rgba<u8>>, d: &mut D) -> Texture {
        let (width, height) = img.dimensions();

        let mut ti = gfx::tex::TextureInfo::new();
        ti.width = width as u16;
        ti.height = height as u16;
        ti.kind = gfx::tex::Texture2D;
        ti.format = gfx::tex::RGBA8;

        let tex = d.create_texture(ti).unwrap();

        d.update_texture(&tex, &ti.to_image_info(), &img.into_vec()).unwrap();
        d.generate_mipmap(&tex);

        Texture {
            handle: tex,
            width: width,
            height: height
        }
    }
}

fn load_rgba8(path: &Path) -> Result<ImageBuf<Rgba<u8>>, String> {
    match image::open(path) {
        Ok(image::ImageRgba8(img)) => Ok(img),
        Ok(image::ImageRgb8(img)) => {
            let (w, h) = img.dimensions();
            Ok(ImageBuf::from_fn(w, h, |x, y| img.get_pixel(x, y).to_rgba()))
        }
        Ok(img) => return Err(format!("Unsupported color type {} in '{}'",
                                      img.color(), path.display())),
        Err(e) => return Err(format!("Could not load '{}': {}", path.display(), e))
    }
}

pub struct Renderer<D: Device<C>, C: CommandBuffer> {
    pub graphics: gfx::Graphics<D, C>,
    frame: gfx::Frame,
    clear_data: gfx::ClearData,
    drawstate: gfx::DrawState
}

impl<D: Device<C>, C: CommandBuffer> Renderer<D, C> {
    pub fn new(mut device: D, frame: gfx::Frame) -> Renderer<D, C> {
        let mut drawstate = gfx::DrawState::new().depth(gfx::state::LessEqual, true);
        drawstate.primitive.front_face = gfx::state::Clockwise;

        Renderer {
            graphics: gfx::Graphics::new(device),
            frame: frame,
            clear_data: gfx::ClearData {
                color: Some([0.05, 0.0, 0.06, 1.0]),
                depth: Some(1.0),
                stencil: None,
            },
            drawstate: drawstate,
        }
    }

    pub fn clear(&mut self) {
        self.graphics.clear(self.clear_data, &self.frame);
    }

    pub fn render<V: VertexFormat, P: ShaderParam<L>, L>(&mut self,
                                                         buffer: buffer::Buffer<V, P, L>,
                                                         params: P) {
        self.graphics.draw(&buffer.batch, &params, &self.frame);
    }

    pub fn end_frame(&mut self) {
        self.graphics.end_frame();
    }
}
<|endoftext|>


<commit_before>use std::path;
use std::env;
use ::powerline::*;
use ::color::Color;
use ::part::*;

pub struct Cwd {
    special: &'static str,
    max_length: i32,
    wanted_seg_num: i32,
}

impl Cwd {
    pub fn new(special: &'static str, max_length: i32, wanted_seg_num: i32) -> Cwd {
        Cwd { special, max_length, wanted_seg_num }
    }
}

fn pb_to_str(path: path::PathBuf) -> Result<String, Error> {
    Ok(path.to_str().ok_or(Error::from_str("Path is not valid UTF-8"))?.to_string())
}

impl Part for Cwd {
    fn get_segments(self) -> Result<Vec<Segment>, Error> {
        let cwd = pb_to_str(env::current_dir()?)?;
        let mut segments = Vec::new();
        let cwd_slice = if let Some(home_path) = env::home_dir() {
            let home = pb_to_str(home_path)?;
            if let Some(pos) = cwd.find(&home) {
                segments.push(Segment::simple(&format!(" {} ", self.special), Color::HOME_FG, Color::HOME_BG) );
                &cwd[pos+home.len()..]
            } else {
                cwd.as_str()
            }
        } else {
            cwd.as_str()
        };
        let dots = "\u{2026}";
        let depth: i32 = cwd_slice.matches("/").count() as i32- 1;
        let iter: Vec<&str> = if (cwd_slice.len() > self.max_length as usize) && (depth > self.wanted_seg_num) {
            let left = self.wanted_seg_num / 2;
            let right = self.wanted_seg_num - left;
            let start = cwd_slice.split("/").skip(1).take(left as usize);
            let end = cwd_slice.split("/").skip((depth - right + 2) as usize);
            start.chain(dots.split("/")).chain(end).collect()
        }
        else {
            cwd_slice.split("/").skip(1).collect()
        };

        for val in iter {
            segments.push(Segment::special(&format!(" {} ", val), Color::PATH_FG, Color::PATH_BG, '\u{E0B1}', Color::SEPARATOR_FG ) );
        }
        if let Some(last) = segments.last_mut() {
            if last.val == "  " { last.val = " / ".to_owned()}
            last.fg = Color::CWD_FG;
            last.sep = '\u{E0B0}';
            last.sep_col = last.bg;
        }

        Ok(segments)
    }
}
<commit_msg>Cleaned cwd shortening<commit_after>use std::path;
use std::env;
use ::powerline::*;
use ::color::Color;
use ::part::*;

pub struct Cwd {
    special: &'static str,
    max_length: i32,
    wanted_seg_num: i32,
}

impl Cwd {
    pub fn new(special: &'static str, max_length: i32, wanted_seg_num: i32) -> Cwd {
        Cwd { special, max_length, wanted_seg_num }
    }
}

fn pb_to_str(path: path::PathBuf) -> Result<String, Error> {
    Ok(path.to_str().ok_or(Error::from_str("Path is not valid UTF-8"))?.to_string())
}

fn append_cwd_segments<'a, I>(segments: &mut Vec<Segment>, iter: I)
where
    I: Iterator<Item = &'a str>
{
    for val in iter {
        segments.push(Segment::special(&format!(" {} ", val), Color::PATH_FG, Color::PATH_BG, '\u{E0B1}', Color::SEPARATOR_FG ) );
    }
}

impl Part for Cwd {
    fn get_segments(self) -> Result<Vec<Segment>, Error> {
        let cwd = pb_to_str(env::current_dir()?)?;
        let mut segments = Vec::new();
        let cwd_slice = if let Some(home_path) = env::home_dir() {
            let home = pb_to_str(home_path)?;
            if let Some(pos) = cwd.find(&home) {
                segments.push(Segment::simple(&format!(" {} ", self.special), Color::HOME_FG, Color::HOME_BG) );
                &cwd[pos+home.len()..]
            } else {
                cwd.as_str()
            }
        } else {
            cwd.as_str()
        };
        let depth: i32 = cwd_slice.matches("/").count() as i32- 1;
        if (cwd_slice.len() > self.max_length as usize) && (depth > self.wanted_seg_num) {
            let left = self.wanted_seg_num / 2;
            let right = self.wanted_seg_num - left;

            let start = cwd_slice.split("/").skip(1).take(left as usize);
            let end = cwd_slice.split("/").skip((depth - right + 2) as usize);

            append_cwd_segments(&mut segments, start);
            segments.push(Segment::special(" \u{2026} ", Color::PATH_FG, Color::PATH_BG, '\u{E0B1}', Color::SEPARATOR_FG ) );
            append_cwd_segments(&mut segments, end);
        }
        else {
            append_cwd_segments(&mut segments, cwd_slice.split("/").skip(1));
        };

        if let Some(last) = segments.last_mut() {
            if last.val == "  " { last.val = " / ".to_owned()}
            last.fg = Color::CWD_FG;
            last.sep = '\u{E0B0}';
            last.sep_col = last.bg;
        }

        Ok(segments)
    }
}
<|endoftext|>


<commit_before>use std;

use std::borrow::Borrow;
use std::iter::IntoIterator;
use std::ops::Deref;
use std::ptr;
use std::str;

use smallvec::{Array, SmallVec};

#[derive(Clone, Default)]
pub(crate) struct SmallString<B: Array<Item = u8>> {
    buffer: SmallVec<B>,
}

impl<B: Array<Item = u8>> SmallString<B> {
    /// Creates a new empty `SmallString`
    #[inline]
    pub fn new() -> Self {
        SmallString { buffer: SmallVec::new() }
    }

    /// Creates a new empty `SmallString` with at least `capacity` bytes
    /// of capacity.
    #[inline]
    pub fn with_capacity(capacity: usize) -> Self {
        SmallString { buffer: SmallVec::with_capacity(capacity) }
    }

    /// Creates a new `SmallString` with the same contents as the given `&str`.
    #[inline]
    pub fn from_str(string: &str) -> Self {
        SmallString { buffer: string.as_bytes().into_iter().cloned().collect() }
    }

    /// Inserts a `&str` at byte offset `idx`.
    ///
    /// Panics if `idx` is not a char boundary, as that would result in an
    /// invalid utf8 string.
    #[inline]
    pub fn insert_str(&mut self, idx: usize, string: &str) {
        assert!(self.is_char_boundary(idx));
        assert!(idx <= self.len());

        unsafe {
            self.insert_bytes(idx, string.as_bytes());
        }
    }

    /// Appends a `&str` to end the of the `SmallString`.
    #[inline]
    pub fn push_str(&mut self, string: &str) {
        let len = self.len();
        unsafe {
            self.insert_bytes(len, string.as_bytes());
        }
    }

    /// Drops the text after byte index `idx`.
    ///
    /// Panics if `idx` is not a char boundary, as that would result in an
    /// invalid utf8 string.
    #[inline]
    pub fn truncate(&mut self, idx: usize) {
        assert!(self.is_char_boundary(idx));
        assert!(idx <= self.len());
        self.buffer.truncate(idx);
    }

    /// Drops the text before byte index `idx`, shifting the
    /// rest of the text to fill in the space.
    ///
    /// Panics if `idx` is not a char boundary, as that would result in an
    /// invalid utf8 string.
    #[inline]
    pub fn truncate_front(&mut self, idx: usize) {
        assert!(self.is_char_boundary(idx));
        assert!(idx <= self.len());
        unsafe {
            self.remove_bytes(0, idx);
        }
    }

    /// Removes the text in the byte index interval `[start, end)`.
    ///
    /// Panics if either `start` or `end` are not char boundaries, as that
    /// would result in an invalid utf8 string.
    #[inline]
    pub fn remove_range(&mut self, start: usize, end: usize) {
        assert!(self.is_char_boundary(start));
        assert!(self.is_char_boundary(end));
        assert!(end < self.len());
        assert!(start <= end);
        unsafe {
            self.remove_bytes(start, end);
        }
    }

    /// Splits the `SmallString` at `idx`.
    ///
    /// The left part remains in the original, and the right part is
    /// returned in a new `SmallString`.
    ///
    /// Panics if `idx` is not a char boundary, as that would result in an
    /// invalid utf8 string.
    #[inline]
    pub fn split_off(&mut self, idx: usize) -> SmallString<B> {
        assert!(self.is_char_boundary(idx));
        assert!(idx <= self.len());
        let len = self.len();
        let mut other = SmallString::with_capacity(len - idx);
        unsafe {
            ptr::copy_nonoverlapping(
                self.buffer.as_ptr().offset(idx as isize),
                other.buffer.as_mut_ptr().offset(0),
                len - idx,
            );
            self.buffer.set_len(idx);
            other.buffer.set_len(len - idx);
        }
        other
    }

    #[inline]
    pub fn shrink_to_fit(&mut self) {
        self.buffer.shrink_to_fit();
    }

    #[inline]
    pub unsafe fn as_mut_smallvec(&mut self) -> &mut SmallVec<B> {
        &mut self.buffer
    }

    unsafe fn insert_bytes(&mut self, idx: usize, bytes: &[u8]) {
        debug_assert!(idx <= self.len());
        let len = self.len();
        let amt = bytes.len();
        self.buffer.reserve(amt);

        ptr::copy(
            self.buffer.as_ptr().offset(idx as isize),
            self.buffer.as_mut_ptr().offset((idx + amt) as isize),
            len - idx,
        );
        ptr::copy(
            bytes.as_ptr(),
            self.buffer.as_mut_ptr().offset(idx as isize),
            amt,
        );
        self.buffer.set_len(len + amt);
    }

    unsafe fn remove_bytes(&mut self, start: usize, end: usize) {
        debug_assert!(end >= start);
        debug_assert!(end <= self.len());
        let len = self.len();
        let amt = end - start;
        ptr::copy(
            self.buffer.as_ptr().offset(end as isize),
            self.buffer.as_mut_ptr().offset(start as isize),
            len - end,
        );
        self.buffer.set_len(len - amt);
    }
}

impl<B: Array<Item = u8>> std::cmp::PartialEq for SmallString<B> {
    fn eq(&self, other: &Self) -> bool {
        let (s1, s2): (&str, &str) = (self, other);
        s1 == s2
    }
}

impl<'a, B: Array<Item = u8>> PartialEq<SmallString<B>> for &'a str {
    fn eq(&self, other: &SmallString<B>) -> bool {
        *self == (other as &str)
    }
}

impl<B: Array<Item = u8>> std::fmt::Display for SmallString<B> {
    fn fmt(&self, fm: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        let s: &str = SmallString::deref(self);
        s.fmt(fm)
    }
}

impl<B: Array<Item = u8>> std::fmt::Debug for SmallString<B> {
    fn fmt(&self, fm: &mut std::fmt::Formatter) -> std::fmt::Result {
        let s: &str = SmallString::deref(self);
        s.fmt(fm)
    }
}

impl<'a, B: Array<Item = u8>> From<&'a str> for SmallString<B> {
    fn from(s: &str) -> Self {
        Self::from_str(s)
    }
}

impl<B: Array<Item = u8>> Deref for SmallString<B> {
    type Target = str;

    fn deref(&self) -> &str {
        // We only allow `buffer` to be created from an existing valid string,
        // so this is safe.
        unsafe { str::from_utf8_unchecked(self.buffer.as_ref()) }
    }
}

impl<B: Array<Item = u8>> AsRef<str> for SmallString<B> {
    fn as_ref(&self) -> &str {
        // We only allow `buffer` to be created from an existing valid string,
        // so this is safe.
        unsafe { str::from_utf8_unchecked(self.buffer.as_ref()) }
    }
}

impl<B: Array<Item = u8>> Borrow<str> for SmallString<B> {
    fn borrow(&self) -> &str {
        // We only allow `buffer` to be created from an existing valid string,
        // so this is safe.
        unsafe { str::from_utf8_unchecked(self.buffer.as_ref()) }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use node::BackingArray;
    type SS = SmallString<BackingArray>;

    #[test]
    fn remove_bytes_01() {
        let mut s = SS::new();
        s.push_str("Hello there, everyone!  How's it going?");
        unsafe {
            s.remove_bytes(11, 21);
        }
        assert_eq!("Hello there!  How's it going?", s);
    }
}
<commit_msg>Some better comments.<commit_after>use std;

use std::borrow::Borrow;
use std::iter::IntoIterator;
use std::ops::Deref;
use std::ptr;
use std::str;

use smallvec::{Array, SmallVec};

#[derive(Clone, Default)]
pub(crate) struct SmallString<B: Array<Item = u8>> {
    buffer: SmallVec<B>,
}

impl<B: Array<Item = u8>> SmallString<B> {
    /// Creates a new empty `SmallString`
    #[inline]
    pub fn new() -> Self {
        SmallString { buffer: SmallVec::new() }
    }

    /// Creates a new empty `SmallString` with at least `capacity` bytes
    /// of capacity.
    #[inline]
    pub fn with_capacity(capacity: usize) -> Self {
        SmallString { buffer: SmallVec::with_capacity(capacity) }
    }

    /// Creates a new `SmallString` with the same contents as the given `&str`.
    #[inline]
    pub fn from_str(string: &str) -> Self {
        SmallString { buffer: string.as_bytes().into_iter().cloned().collect() }
    }

    /// Inserts a `&str` at byte offset `idx`.
    ///
    /// Panics if `idx` is not a char boundary, as that would result in an
    /// invalid utf8 string.
    #[inline]
    pub fn insert_str(&mut self, idx: usize, string: &str) {
        assert!(self.is_char_boundary(idx));
        assert!(idx <= self.len());

        unsafe {
            self.insert_bytes(idx, string.as_bytes());
        }
    }

    /// Appends a `&str` to end the of the `SmallString`.
    #[inline]
    pub fn push_str(&mut self, string: &str) {
        let len = self.len();
        unsafe {
            self.insert_bytes(len, string.as_bytes());
        }
    }

    /// Drops the text after byte index `idx`.
    ///
    /// Panics if `idx` is not a char boundary, as that would result in an
    /// invalid utf8 string.
    #[inline]
    pub fn truncate(&mut self, idx: usize) {
        assert!(self.is_char_boundary(idx));
        assert!(idx <= self.len());
        self.buffer.truncate(idx);
    }

    /// Drops the text before byte index `idx`, shifting the
    /// rest of the text to fill in the space.
    ///
    /// Panics if `idx` is not a char boundary, as that would result in an
    /// invalid utf8 string.
    #[inline]
    pub fn truncate_front(&mut self, idx: usize) {
        assert!(self.is_char_boundary(idx));
        assert!(idx <= self.len());
        unsafe {
            self.remove_bytes(0, idx);
        }
    }

    /// Removes the text in the byte index interval `[start, end)`.
    ///
    /// Panics if either `start` or `end` are not char boundaries, as that
    /// would result in an invalid utf8 string.
    #[inline]
    pub fn remove_range(&mut self, start: usize, end: usize) {
        assert!(self.is_char_boundary(start));
        assert!(self.is_char_boundary(end));
        assert!(end < self.len());
        assert!(start <= end);
        unsafe {
            self.remove_bytes(start, end);
        }
    }

    /// Splits the `SmallString` at `idx`.
    ///
    /// The left part remains in the original, and the right part is
    /// returned in a new `SmallString`.
    ///
    /// Panics if `idx` is not a char boundary, as that would result in an
    /// invalid utf8 string.
    #[inline]
    pub fn split_off(&mut self, idx: usize) -> SmallString<B> {
        assert!(self.is_char_boundary(idx));
        assert!(idx <= self.len());
        let len = self.len();
        let mut other = SmallString::with_capacity(len - idx);
        unsafe {
            ptr::copy_nonoverlapping(
                self.buffer.as_ptr().offset(idx as isize),
                other.buffer.as_mut_ptr().offset(0),
                len - idx,
            );
            self.buffer.set_len(idx);
            other.buffer.set_len(len - idx);
        }
        other
    }

    #[inline]
    pub fn shrink_to_fit(&mut self) {
        self.buffer.shrink_to_fit();
    }

    #[inline]
    pub unsafe fn as_mut_smallvec(&mut self) -> &mut SmallVec<B> {
        &mut self.buffer
    }

    unsafe fn insert_bytes(&mut self, idx: usize, bytes: &[u8]) {
        debug_assert!(idx <= self.len());
        let len = self.len();
        let amt = bytes.len();
        self.buffer.reserve(amt);

        ptr::copy(
            self.buffer.as_ptr().offset(idx as isize),
            self.buffer.as_mut_ptr().offset((idx + amt) as isize),
            len - idx,
        );
        ptr::copy(
            bytes.as_ptr(),
            self.buffer.as_mut_ptr().offset(idx as isize),
            amt,
        );
        self.buffer.set_len(len + amt);
    }

    unsafe fn remove_bytes(&mut self, start: usize, end: usize) {
        debug_assert!(end >= start);
        debug_assert!(end <= self.len());
        let len = self.len();
        let amt = end - start;
        ptr::copy(
            self.buffer.as_ptr().offset(end as isize),
            self.buffer.as_mut_ptr().offset(start as isize),
            len - end,
        );
        self.buffer.set_len(len - amt);
    }
}

impl<B: Array<Item = u8>> std::cmp::PartialEq for SmallString<B> {
    fn eq(&self, other: &Self) -> bool {
        let (s1, s2): (&str, &str) = (self, other);
        s1 == s2
    }
}

impl<'a, B: Array<Item = u8>> PartialEq<SmallString<B>> for &'a str {
    fn eq(&self, other: &SmallString<B>) -> bool {
        *self == (other as &str)
    }
}

impl<B: Array<Item = u8>> std::fmt::Display for SmallString<B> {
    fn fmt(&self, fm: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        let s: &str = SmallString::deref(self);
        s.fmt(fm)
    }
}

impl<B: Array<Item = u8>> std::fmt::Debug for SmallString<B> {
    fn fmt(&self, fm: &mut std::fmt::Formatter) -> std::fmt::Result {
        let s: &str = SmallString::deref(self);
        s.fmt(fm)
    }
}

impl<'a, B: Array<Item = u8>> From<&'a str> for SmallString<B> {
    fn from(s: &str) -> Self {
        Self::from_str(s)
    }
}

impl<B: Array<Item = u8>> Deref for SmallString<B> {
    type Target = str;

    fn deref(&self) -> &str {
        // SmallString's methods don't allow `buffer` to become invalid utf8,
        // so this is safe.
        unsafe { str::from_utf8_unchecked(self.buffer.as_ref()) }
    }
}

impl<B: Array<Item = u8>> AsRef<str> for SmallString<B> {
    fn as_ref(&self) -> &str {
        // SmallString's methods don't allow `buffer` to become invalid utf8,
        // so this is safe.
        unsafe { str::from_utf8_unchecked(self.buffer.as_ref()) }
    }
}

impl<B: Array<Item = u8>> Borrow<str> for SmallString<B> {
    fn borrow(&self) -> &str {
        // SmallString's methods don't allow `buffer` to become invalid utf8,
        // so this is safe.
        unsafe { str::from_utf8_unchecked(self.buffer.as_ref()) }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use node::BackingArray;
    type SS = SmallString<BackingArray>;

    #[test]
    fn remove_bytes_01() {
        let mut s = SS::new();
        s.push_str("Hello there, everyone!  How's it going?");
        unsafe {
            s.remove_bytes(11, 21);
        }
        assert_eq!("Hello there!  How's it going?", s);
    }
}
<|endoftext|>


<commit_before>// TODO: This will panic on certain opcodes. The ideas I have for cpu_lang
// will probably fix it; we'll see. For now tho, I'm gonna leave it as-is;
// I can imagine fixing it trivially might lead to performance problems.
// I'll deal with it after the port is finished.

// TODO: This is a placeholder before I start generalizing traits
// from the old code.
use super::apu::Apu;

pub struct Smp<'a> {
    emulator: &'a mut Apu,

    reg_pc: u16,
    reg_a: u8,
    reg_x: u8,
    reg_y: u8,
    reg_sp: u8,

    psw_c: bool,
    psw_z: bool,
    psw_h: bool,
    psw_p: bool,
    psw_v: bool,
    psw_n: bool,
    // TODO: Look up some more behavior for I and B. Can't seem to find much
    // but some instructions DO set them.
    psw_i: bool,
    psw_b: bool,

    cycle_count: i32
}

impl<'a> Smp<'a> {
    pub fn new(emulator: &'a mut Apu) -> Smp<'a> {
        let mut ret = Smp {
            emulator: emulator,

            reg_pc: 0,
            reg_a: 0,
            reg_x: 0,
            reg_y: 0,
            reg_sp: 0,

            psw_c: false,
            psw_z: false,
            psw_h: false,
            psw_p: false,
            psw_v: false,
            psw_n: false,
            psw_i: false,
            psw_b: false,

            cycle_count: 0
        };
        ret.reset();
        ret
    }

    pub fn reset(&mut self) {
        self.reg_pc = 0xffc0;
        self.reg_a = 0;
        self.reg_x = 0;
        self.reg_y = 0;
        self.reg_sp = 0xef;
        self.set_psw(0x02);
    }

    pub fn set_reg_ya(&mut self, value: u16) {
        self.reg_a = (value & 0xff) as u8;
        self.reg_y = ((value >> 8) & 0xff) as u8;
    }

    pub fn get_reg_ya(&self) -> u16 {
        ((self.reg_y as u16) << 8) | (self.reg_a as u16)
    }

    pub fn set_psw(&mut self, value: u8) {
        self.psw_c = (value & 0x01) != 0;
        self.psw_z = (value & 0x02) != 0;
        self.psw_h = (value & 0x08) != 0;
        self.psw_p = (value & 0x20) != 0;
        self.psw_v = (value & 0x40) != 0;
        self.psw_n = (value & 0x80) != 0;
    }

    pub fn get_psw(&self) -> u8 {
        ((if self.psw_n { 1 } else { 0 }) << 7) |
        ((if self.psw_v { 1 } else { 0 }) << 6) |
        ((if self.psw_p { 1 } else { 0 }) << 5) |
        ((if self.psw_h { 1 } else { 0 }) << 3) |
        ((if self.psw_z { 1 } else { 0 }) << 1) |
        (if self.psw_c { 1 } else { 0 })
    }

    fn is_negative(value: u32) -> bool {
        (value & 0x80) != 0
    }

    fn cycles(&mut self, num_cycles: i32) {
        self.emulator.cpu_cycles_callback(num_cycles);
        self.cycle_count += num_cycles;
    }

    fn read_op(&mut self, addr: u16) -> u8 {
        self.cycles(1);
        self.emulator.read_byte(addr as u32)
    }

    fn write_op(&mut self, addr: u16, value: u8) {
        self.cycles(1);
        self.emulator.write_byte(addr as u32, value);
    }

    fn read_pc_op(&mut self) -> u8 {
        let addr = self.reg_pc;
        self.reg_pc += 1;
        let ret = self.read_op(addr);
        ret
    }

    fn read_sp_op(&mut self) -> u8 {
        self.reg_sp += 1;
        let addr = 0x0100 | (self.reg_sp as u16);
        self.read_op(addr)
    }

    fn write_sp_op(&mut self, value: u8) {
        let addr = 0x0100 | (self.reg_sp as u16);
        self.reg_sp -= 1;
        self.write_op(addr, value);
    }

    fn read_dp_op(&mut self, addr: u8) -> u8 {
        let addr = (if self.psw_p { 0x0100 } else { 0 }) | (addr as u16);
        self.read_op(addr)
    }

    fn write_dp_op(&mut self, addr: u8, value: u8) {
        let addr = (if self.psw_p { 0x0100 } else { 0 }) | (addr as u16);
        self.write_op(addr, value);
    }

    fn set_psw_n_z_op(&mut self, x: u32) {
        self.psw_n = Smp::is_negative(x);
        self.psw_z = x == 0;
    }

    fn adc_op(&mut self, x: u8, y: u8) -> u8 {
        let x = x as u32;
        let y = y as u32;
        let r = x + y + (if self.psw_c { 1 } else { 0 });
        self.psw_n = Smp::is_negative(r);
        self.psw_v = (!(x ^ y) & (x ^ r) & 0x80) != 0;
        self.psw_h = ((x ^ y ^ r) & 0x10) != 0;
        self.psw_z = (r & 0xff) == 0;
        self.psw_c = r > 0xff;
        (r & 0xff) as u8
    }

    fn and_op(&mut self, x: u8, y: u8) -> u8 {
        let ret = x & y;
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn asl_op(&mut self, x: u8) -> u8 {
        self.psw_c = Smp::is_negative(x as u32);
        let ret = x << 1;
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn cmp_op(&mut self, x: u8, y: u8) -> u8 {
        let r = (x as i32) - (y as i32);
        self.psw_n = (r & 0x80) != 0;
        self.psw_z = (r & 0xff) == 0;
        self.psw_c = r >= 0;
        x
    }

    fn dec_op(&mut self, x: u8) -> u8 {
        let ret = x - 1;
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn eor_op(&mut self, x: u8, y: u8) -> u8 {
        let ret = x ^ y;
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn inc_op(&mut self, x: u8) -> u8 {
        let ret = x + 1;
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn ld_op(&mut self, _: u8, y: u8) -> u8 {
        self.set_psw_n_z_op(y as u32);
        y
    }

    fn lsr_op(&mut self, x: u8) -> u8 {
        self.psw_c = (x & 0x01) != 0;
        let ret = x >> 1;
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn run(&mut self, target_cycles: i32) -> i32 {
        0 // TODO
    }
}
<commit_msg>ops ops and more ops<commit_after>// TODO: This will panic on certain opcodes. The ideas I have for cpu_lang
// will probably fix it; we'll see. For now tho, I'm gonna leave it as-is;
// I can imagine fixing it trivially might lead to performance problems.
// I'll deal with it after the port is finished.

// TODO: This is a placeholder before I start generalizing traits
// from the old code.
use super::apu::Apu;

pub struct Smp<'a> {
    emulator: &'a mut Apu,

    reg_pc: u16,
    reg_a: u8,
    reg_x: u8,
    reg_y: u8,
    reg_sp: u8,

    psw_c: bool,
    psw_z: bool,
    psw_h: bool,
    psw_p: bool,
    psw_v: bool,
    psw_n: bool,
    // TODO: Look up some more behavior for I and B. Can't seem to find much
    // but some instructions DO set them.
    psw_i: bool,
    psw_b: bool,

    cycle_count: i32
}

impl<'a> Smp<'a> {
    pub fn new(emulator: &'a mut Apu) -> Smp<'a> {
        let mut ret = Smp {
            emulator: emulator,

            reg_pc: 0,
            reg_a: 0,
            reg_x: 0,
            reg_y: 0,
            reg_sp: 0,

            psw_c: false,
            psw_z: false,
            psw_h: false,
            psw_p: false,
            psw_v: false,
            psw_n: false,
            psw_i: false,
            psw_b: false,

            cycle_count: 0
        };
        ret.reset();
        ret
    }

    pub fn reset(&mut self) {
        self.reg_pc = 0xffc0;
        self.reg_a = 0;
        self.reg_x = 0;
        self.reg_y = 0;
        self.reg_sp = 0xef;
        self.set_psw(0x02);
    }

    pub fn set_reg_ya(&mut self, value: u16) {
        self.reg_a = (value & 0xff) as u8;
        self.reg_y = ((value >> 8) & 0xff) as u8;
    }

    pub fn get_reg_ya(&self) -> u16 {
        ((self.reg_y as u16) << 8) | (self.reg_a as u16)
    }

    pub fn set_psw(&mut self, value: u8) {
        self.psw_c = (value & 0x01) != 0;
        self.psw_z = (value & 0x02) != 0;
        self.psw_h = (value & 0x08) != 0;
        self.psw_p = (value & 0x20) != 0;
        self.psw_v = (value & 0x40) != 0;
        self.psw_n = (value & 0x80) != 0;
    }

    pub fn get_psw(&self) -> u8 {
        ((if self.psw_n { 1 } else { 0 }) << 7) |
        ((if self.psw_v { 1 } else { 0 }) << 6) |
        ((if self.psw_p { 1 } else { 0 }) << 5) |
        ((if self.psw_h { 1 } else { 0 }) << 3) |
        ((if self.psw_z { 1 } else { 0 }) << 1) |
        (if self.psw_c { 1 } else { 0 })
    }

    fn is_negative(value: u32) -> bool {
        (value & 0x80) != 0
    }

    fn cycles(&mut self, num_cycles: i32) {
        self.emulator.cpu_cycles_callback(num_cycles);
        self.cycle_count += num_cycles;
    }

    fn read_op(&mut self, addr: u16) -> u8 {
        self.cycles(1);
        self.emulator.read_byte(addr as u32)
    }

    fn write_op(&mut self, addr: u16, value: u8) {
        self.cycles(1);
        self.emulator.write_byte(addr as u32, value);
    }

    fn read_pc_op(&mut self) -> u8 {
        let addr = self.reg_pc;
        self.reg_pc += 1;
        let ret = self.read_op(addr);
        ret
    }

    fn read_sp_op(&mut self) -> u8 {
        self.reg_sp += 1;
        let addr = 0x0100 | (self.reg_sp as u16);
        self.read_op(addr)
    }

    fn write_sp_op(&mut self, value: u8) {
        let addr = 0x0100 | (self.reg_sp as u16);
        self.reg_sp -= 1;
        self.write_op(addr, value);
    }

    fn read_dp_op(&mut self, addr: u8) -> u8 {
        let addr = (if self.psw_p { 0x0100 } else { 0 }) | (addr as u16);
        self.read_op(addr)
    }

    fn write_dp_op(&mut self, addr: u8, value: u8) {
        let addr = (if self.psw_p { 0x0100 } else { 0 }) | (addr as u16);
        self.write_op(addr, value);
    }

    fn set_psw_n_z_op(&mut self, x: u32) {
        self.psw_n = Smp::is_negative(x);
        self.psw_z = x == 0;
    }

    fn adc_op(&mut self, x: u8, y: u8) -> u8 {
        let x = x as u32;
        let y = y as u32;
        let r = x + y + (if self.psw_c { 1 } else { 0 });
        self.psw_n = Smp::is_negative(r);
        self.psw_v = (!(x ^ y) & (x ^ r) & 0x80) != 0;
        self.psw_h = ((x ^ y ^ r) & 0x10) != 0;
        self.psw_z = (r & 0xff) == 0;
        self.psw_c = r > 0xff;
        (r & 0xff) as u8
    }

    fn and_op(&mut self, x: u8, y: u8) -> u8 {
        let ret = x & y;
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn asl_op(&mut self, x: u8) -> u8 {
        self.psw_c = Smp::is_negative(x as u32);
        let ret = x << 1;
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn cmp_op(&mut self, x: u8, y: u8) -> u8 {
        let r = (x as i32) - (y as i32);
        self.psw_n = (r & 0x80) != 0;
        self.psw_z = (r & 0xff) == 0;
        self.psw_c = r >= 0;
        x
    }

    fn dec_op(&mut self, x: u8) -> u8 {
        let ret = x - 1;
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn eor_op(&mut self, x: u8, y: u8) -> u8 {
        let ret = x ^ y;
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn inc_op(&mut self, x: u8) -> u8 {
        let ret = x + 1;
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn ld_op(&mut self, _: u8, y: u8) -> u8 {
        self.set_psw_n_z_op(y as u32);
        y
    }

    fn lsr_op(&mut self, x: u8) -> u8 {
        self.psw_c = (x & 0x01) != 0;
        let ret = x >> 1;
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn or_op(&mut self, x: u8, y: u8) -> u8 {
        let ret = x | y;
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn rol_op(&mut self, x: u8) -> u8 {
        let carry = if self.psw_c { 1 } else { 0 };
        self.psw_c = (x & 0x80) != 0;
        let ret = (x << 1) | carry;
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn ror_op(&mut self, x: u8) -> u8 {
        let carry = if self.psw_c { 0x80 } else { 0 };
        self.psw_c = (x & 0x01) != 0;
        let ret = carry | (x >> 1);
        self.set_psw_n_z_op(ret as u32);
        ret
    }

    fn sbc_op(&mut self, x: u8, y: u8) -> u8 {
        self.adc_op(x, !y)
    }

    fn st_op(&mut self, _: u8, y: u8) -> u8 {
        y
    }

    fn run(&mut self, target_cycles: i32) -> i32 {
        0 // TODO
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::error;
use std::fmt;
use std::fs::File;
use std::io;
use std::io::Read;
use std::path::PathBuf;
use std::slice;
use std::str;

pub mod cap;

pub struct Desc {
    pub names: Vec<String>,
    pub bools: Vec<bool>,
    pub nums: Vec<u16>,
    pub strings: Vec<String>,
}

impl Desc {
    pub fn file(name: &str) -> Option<File> {
        if name.is_empty() {
            return None;
        }

        let first_char = name.chars().next().unwrap();
        let first_hex = format!("{:x}", first_char as usize);
        let first_char = first_char.to_string();

        let d1 = to_path(env::var("TERMINFO").ok());
        let d2 = to_path(env::home_dir()).map(|d| d.join(".terminfo"));
        let d3 = to_paths(env::var("TERMINFO_DIRS").ok());
        let d3 = d3.into_iter().map(|d| if d.as_os_str().is_empty() {
                                        PathBuf::from("/usr/share/terminfo")
                                    } else {
                                        d
                                    });
        let d4 = vec![PathBuf::from("/etc/terminfo"),
                      PathBuf::from("/lib/terminfo"),
                      PathBuf::from("/usr/share/terminfo")];
        let ds = d1.into_iter()
            .chain(d2.into_iter())
            .chain(d3)
            .chain(d4.into_iter());

        for d in ds {
            if let Ok(f) = File::open(d.join(&first_char).join(name)) {
                return Some(f);
            }
            if let Ok(f) = File::open(d.join(&first_hex).join(name)) {
                return Some(f);
            }
        }
        return None;
    }

    pub fn parse(r: &mut Read) -> Result<Desc, ParseError> {
        let header = read_words(r, 6)?;
        if header[0] != 282 {
            return Err(parse_error("wrong magic number"));
        }

        let name_sz = header[1] as usize;
        if name_sz == 0 {
            return Err(parse_error("zero-length name section"));
        }
        let name_buf = read_bytes(r, name_sz)?;
        if name_buf[name_sz - 1] != 0 {
            return Err(parse_error("name section is not null-terminated"));
        }
        let names = str::from_utf8(&name_buf[0..name_sz - 1])?;
        let names: Vec<_> = names.split('|').map(str::to_owned).collect();
        if names.len() < 2 {
            return Err(parse_error("too few items in name section"));
        }

        let bools_num = header[2] as usize;
        if bools_num > cap::NUM_BOOLS {
            return Err(parse_error("too many boolean flags"));
        }
        let bool_buf = read_bytes(r, bools_num)?;
        let bools = bool_buf.into_iter()
            .map(|b| if b == 0 { false } else { true })
            .collect();

        if (name_sz + bools_num) % 2 != 0 {
            read_bytes(r, 1)?;
        }

        let ints_num = header[3] as usize;
        if ints_num > cap::NUM_INTS {
            return Err(parse_error("too many numbers"));
        }
        let nums = read_words(r, ints_num)?;

        let strings_num = header[4] as usize;
        let string_sz = header[5] as usize;
        if strings_num > cap::NUM_STRINGS {
            return Err(parse_error("too many strings"));
        }
        let offsets = read_words(r, strings_num)?;
        let str_table = read_bytes(r, string_sz)?;
        let mut strings = Vec::new();
        for pos in offsets {
            let pos = pos as usize;
            if pos == 0xffff {
                strings.push(String::new());
            } else if pos >= string_sz {
                return Err(parse_error("invalid string offset"));
            } else {
                match str_table[pos..].iter().position(|&b| b == 0) {
                    None => return Err(parse_error("unterminated string")),
                    Some(end) => {
                        let s = str::from_utf8(&str_table[pos..pos + end])?;
                        strings.push(s.to_owned());
                    }
                }
            }
        }

        Ok(Desc {
               names: names,
               bools: bools,
               nums: nums,
               strings: strings,
           })
    }
}

#[derive(Debug)]
pub struct ParseError {
    inner: ParseErrorImpl,
}

fn parse_error(msg: &str) -> ParseError {
    ParseError { inner: ParseErrorImpl::Other(msg.to_owned()) }
}

#[derive(Debug)]
enum ParseErrorImpl {
    Io(io::Error),
    Other(String),
}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.inner {
            ParseErrorImpl::Io(ref err) => err.fmt(f),
            ParseErrorImpl::Other(ref msg) => write!(f, "{}", msg),
        }
    }
}

impl error::Error for ParseError {
    fn description(&self) -> &str {
        match self.inner {
            ParseErrorImpl::Io(ref err) => err.description(),
            _ => "invalid terminfo description",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match self.inner {
            ParseErrorImpl::Io(ref err) => err.cause(),
            _ => None,
        }
    }
}

impl From<io::Error> for ParseError {
    fn from(err: io::Error) -> ParseError {
        ParseError { inner: ParseErrorImpl::Io(err) }
    }
}

impl From<str::Utf8Error> for ParseError {
    fn from(err: str::Utf8Error) -> ParseError {
        parse_error(&err.to_string())
    }
}

fn to_path<T: Into<PathBuf>>(var: Option<T>) -> Option<PathBuf> {
    match var {
        Some(d) => {
            let d = d.into();
            if d.as_os_str().is_empty() {
                None
            } else {
                Some(d)
            }
        }
        None => None,
    }
}

fn to_paths(var: Option<String>) -> Vec<PathBuf> {
    match var {
        None => Vec::new(),
        Some(ref d) if d.is_empty() => Vec::new(),
        Some(d) => env::split_paths(&d).collect(),
    }
}

fn read_bytes(r: &mut Read, n: usize) -> io::Result<Vec<u8>> {
    let mut buf = Vec::with_capacity(n);
    if r.take(n as u64).read_to_end(&mut buf)? < n {
        return Err(io::Error::new(io::ErrorKind::UnexpectedEof,
                                  "failed to fill whole buffer"));
    }
    Ok(buf)
}

fn read_words(r: &mut Read, n: usize) -> io::Result<Vec<u16>> {
    let mut buf_16: Vec<u16> = vec![0; n];
    let mut buf_8 = unsafe {
        slice::from_raw_parts_mut(buf_16.as_mut_ptr() as *mut u8, n * 2)
    };
    r.read_exact(&mut buf_8)?;
    if cfg!(target_endian = "big") {
        for w in &mut buf_16 {
            *w = w.swap_bytes();
        }
    }
    Ok(buf_16)
}
<commit_msg>Desc::file returns None on invalid terminal name<commit_after>use std::env;
use std::error;
use std::fmt;
use std::fs::File;
use std::io;
use std::io::Read;
use std::path::{Path, PathBuf};
use std::slice;
use std::str;

pub mod cap;

pub struct Desc {
    pub names: Vec<String>,
    pub bools: Vec<bool>,
    pub nums: Vec<u16>,
    pub strings: Vec<String>,
}

impl Desc {
    pub fn file(term_name: &str) -> Option<File> {
        if term_name.is_empty() {
            return None;
        }
        match Path::new(term_name).file_name() {
            Some(fname) if fname == Path::new(term_name).as_os_str() => (),
            _ => return None,
        }

        let first_char = term_name.chars().next().unwrap();
        let first_hex = format!("{:x}", first_char as usize);
        let first_char = first_char.to_string();

        let d1 = to_path(env::var("TERMINFO").ok());
        let d2 = to_path(env::home_dir()).map(|d| d.join(".terminfo"));
        let d3 = to_paths(env::var("TERMINFO_DIRS").ok());
        let d3 = d3.into_iter().map(|d| if d.as_os_str().is_empty() {
                                        PathBuf::from("/usr/share/terminfo")
                                    } else {
                                        d
                                    });
        let d4 = vec![PathBuf::from("/etc/terminfo"),
                      PathBuf::from("/lib/terminfo"),
                      PathBuf::from("/usr/share/terminfo")];
        let ds = d1.into_iter()
            .chain(d2.into_iter())
            .chain(d3)
            .chain(d4.into_iter());

        for d in ds {
            if let Ok(f) = File::open(d.join(&first_char).join(term_name)) {
                return Some(f);
            }
            if let Ok(f) = File::open(d.join(&first_hex).join(term_name)) {
                return Some(f);
            }
        }
        return None;
    }

    pub fn parse(r: &mut Read) -> Result<Desc, ParseError> {
        let header = read_words(r, 6)?;
        if header[0] != 282 {
            return Err(parse_error("wrong magic number"));
        }

        let name_sz = header[1] as usize;
        if name_sz == 0 {
            return Err(parse_error("zero-length name section"));
        }
        let name_buf = read_bytes(r, name_sz)?;
        if name_buf[name_sz - 1] != 0 {
            return Err(parse_error("name section is not null-terminated"));
        }
        let names = str::from_utf8(&name_buf[0..name_sz - 1])?;
        let names: Vec<_> = names.split('|').map(str::to_owned).collect();
        if names.len() < 2 {
            return Err(parse_error("too few items in name section"));
        }

        let bools_num = header[2] as usize;
        if bools_num > cap::NUM_BOOLS {
            return Err(parse_error("too many boolean flags"));
        }
        let bool_buf = read_bytes(r, bools_num)?;
        let bools = bool_buf.into_iter()
            .map(|b| if b == 0 { false } else { true })
            .collect();

        if (name_sz + bools_num) % 2 != 0 {
            read_bytes(r, 1)?;
        }

        let ints_num = header[3] as usize;
        if ints_num > cap::NUM_INTS {
            return Err(parse_error("too many numbers"));
        }
        let nums = read_words(r, ints_num)?;

        let strings_num = header[4] as usize;
        let string_sz = header[5] as usize;
        if strings_num > cap::NUM_STRINGS {
            return Err(parse_error("too many strings"));
        }
        let offsets = read_words(r, strings_num)?;
        let str_table = read_bytes(r, string_sz)?;
        let mut strings = Vec::new();
        for pos in offsets {
            let pos = pos as usize;
            if pos == 0xffff {
                strings.push(String::new());
            } else if pos >= string_sz {
                return Err(parse_error("invalid string offset"));
            } else {
                match str_table[pos..].iter().position(|&b| b == 0) {
                    None => return Err(parse_error("unterminated string")),
                    Some(end) => {
                        let s = str::from_utf8(&str_table[pos..pos + end])?;
                        strings.push(s.to_owned());
                    }
                }
            }
        }

        Ok(Desc {
               names: names,
               bools: bools,
               nums: nums,
               strings: strings,
           })
    }
}

#[derive(Debug)]
pub struct ParseError {
    inner: ParseErrorImpl,
}

fn parse_error(msg: &str) -> ParseError {
    ParseError { inner: ParseErrorImpl::Other(msg.to_owned()) }
}

#[derive(Debug)]
enum ParseErrorImpl {
    Io(io::Error),
    Other(String),
}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.inner {
            ParseErrorImpl::Io(ref err) => err.fmt(f),
            ParseErrorImpl::Other(ref msg) => write!(f, "{}", msg),
        }
    }
}

impl error::Error for ParseError {
    fn description(&self) -> &str {
        match self.inner {
            ParseErrorImpl::Io(ref err) => err.description(),
            _ => "invalid terminfo description",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match self.inner {
            ParseErrorImpl::Io(ref err) => err.cause(),
            _ => None,
        }
    }
}

impl From<io::Error> for ParseError {
    fn from(err: io::Error) -> ParseError {
        ParseError { inner: ParseErrorImpl::Io(err) }
    }
}

impl From<str::Utf8Error> for ParseError {
    fn from(err: str::Utf8Error) -> ParseError {
        parse_error(&err.to_string())
    }
}

fn to_path<T: Into<PathBuf>>(var: Option<T>) -> Option<PathBuf> {
    match var {
        Some(d) => {
            let d = d.into();
            if d.as_os_str().is_empty() {
                None
            } else {
                Some(d)
            }
        }
        None => None,
    }
}

fn to_paths(var: Option<String>) -> Vec<PathBuf> {
    match var {
        None => Vec::new(),
        Some(ref d) if d.is_empty() => Vec::new(),
        Some(d) => env::split_paths(&d).collect(),
    }
}

fn read_bytes(r: &mut Read, n: usize) -> io::Result<Vec<u8>> {
    let mut buf = Vec::with_capacity(n);
    if r.take(n as u64).read_to_end(&mut buf)? < n {
        return Err(io::Error::new(io::ErrorKind::UnexpectedEof,
                                  "failed to fill whole buffer"));
    }
    Ok(buf)
}

fn read_words(r: &mut Read, n: usize) -> io::Result<Vec<u16>> {
    let mut buf_16: Vec<u16> = vec![0; n];
    let mut buf_8 = unsafe {
        slice::from_raw_parts_mut(buf_16.as_mut_ptr() as *mut u8, n * 2)
    };
    r.read_exact(&mut buf_8)?;
    if cfg!(target_endian = "big") {
        for w in &mut buf_16 {
            *w = w.swap_bytes();
        }
    }
    Ok(buf_16)
}
<|endoftext|>


<commit_before>macro_rules! implement_sender {
  (name => $name:ident,
   wrap => $wrap_type:ident,
   with => $with_type:ident,
   variant => $variant:ident) =>  {
    pub struct $name {
      wrapped_sender: ::std::sync::mpsc::Sender<$with_type>,
    }

    impl $name {
      pub fn create(sender: ::std::sync::mpsc::Sender<$with_type>) -> $name {
        $name {
          wrapped_sender: sender
        }
      }
      pub fn send(&self, t: $wrap_type) -> Result<(), ::std::sync::mpsc::SendError<$wrap_type>> {
        let wrapped = self.wrap(t);
            let result = self.wrapped_sender.send(wrapped);
            result.map_err(|senderror| {
                let ::std::sync::mpsc::SendError(z) = senderror;
                ::std::sync::mpsc::SendError(self.unwrap(z))
            })
      }
      fn wrap(&self, d: $wrap_type) -> $with_type {
        $with_type::$variant(d)
      }
      fn unwrap(&self, msg: $with_type) -> $wrap_type {
        let d = match msg {
                $with_type::$variant(d) => d,
                _ => unreachable!()
        };
        d
      }
    }

    impl Clone for $name {
        fn clone(&self) -> $name {
            $name {
                wrapped_sender: self.wrapped_sender.clone()
            }
        }
    }
  }
}<commit_msg>Add documentation for channel macro<commit_after>/// Creates an implentation of sender which can be used to share an async channel for multiple message types.
///
/// # Examples
///
/// ```
/// struct D;
/// struct A;
///
/// enum Msg {
///   FirstType(D),
///   SecondType(A)
/// }
///
/// fn main() {
///   let (tx, rx) = channel::<Msg>();
///
///   let d_sender = DSender::create(tx.clone());
///   let a_sender = ASender::create(tx.clone());
///   subscribe(d_sender.clone());
///   subscribe2(d_sender.clone());
///   subscribe3(a_sender.clone());
 //
///   let mut i = 0;
 //
///   for m in rx {
///     i += 1;
///     match m {
///       Msg::FirstType(_) => println!("m: D {}", i),
///       Msg::SecondType(_) => println!("m: A {}", i)
///     };
///   }
/// }
///
/// fn subscribe(sender: DSender) {
///   thread::spawn(move|| {
///       sender.send(D).unwrap();
///   });
/// }
/// fn subscribe2(sender: DSender) {
///   thread::spawn(move|| {
///       thread::sleep(time::Duration::from_millis(10));
///       sender.send(D).unwrap();
///   });
/// }
/// fn subscribe3(sender: ASender) {
///   thread::spawn(move|| {
///       sender.send(A).unwrap();
///   });
/// }
/// implement_sender!(name => DSender,
///                   wrap => D,
///                   with => Msg,
///                   variant => FirstType)
/// implement_sender!(name => ASender,
///                   wrap => A,
///                   with => Msg,
///                   variant => SecondType)
/// ```
macro_rules! implement_sender {
  (name => $name:ident,
   wrap => $wrap_type:ident,
   with => $with_type:ident,
   variant => $variant:ident) =>  {
    pub struct $name {
      wrapped_sender: ::std::sync::mpsc::Sender<$with_type>,
    }

    impl $name {
      pub fn create(sender: ::std::sync::mpsc::Sender<$with_type>) -> $name {
        $name {
          wrapped_sender: sender
        }
      }
      pub fn send(&self, t: $wrap_type) -> Result<(), ::std::sync::mpsc::SendError<$wrap_type>> {
        let wrapped = self.wrap(t);
            let result = self.wrapped_sender.send(wrapped);
            result.map_err(|senderror| {
                let ::std::sync::mpsc::SendError(z) = senderror;
                ::std::sync::mpsc::SendError(self.unwrap(z))
            })
      }
      fn wrap(&self, d: $wrap_type) -> $with_type {
        $with_type::$variant(d)
      }
      fn unwrap(&self, msg: $with_type) -> $wrap_type {
        let d = match msg {
                $with_type::$variant(d) => d,
                _ => unreachable!()
        };
        d
      }
    }

    impl Clone for $name {
        fn clone(&self) -> $name {
            $name {
                wrapped_sender: self.wrapped_sender.clone()
            }
        }
    }
  }
}<|endoftext|>


<commit_before>extern crate build_utils;
extern crate cc;

/*

N.B. This build script is invoked by `cargo` by way of this configuration
in our Cargo.toml:

    [project]
    ...
    build = "src/cffi_build.rs"

Within, we use the `gcc` crate to compile the CFFI C sources (`native_engine.c`)
generated by `bootstrap.sh` into a (private) static lib (`libnative_engine_ffi.a`),
which then gets linked into the final `cargo build` product (the native engine binary).
This process mixes the Python module initialization function and other symbols into the
native engine binary, allowing us to address it both as an importable python module
(`from _native_engine import X`) as well as a C library (`ffi.dlopen(native_engine.so)`).

*/

use std::fs;
use std::io::{Read, Result};
use std::path::{Path, PathBuf};
use std::process::{exit, Command};

use build_utils::BuildRoot;

fn main() {
  // We depend on grpcio, which uses C++.
  // On Linux, with g++, some part of that compilation depends on
  // __gxx_personality_v0 which is present in the C++ standard library.
  // I don't know why. It shouldn't, and before grpcio 0.2.0, it didn't.
  //
  // So we need to link against the C++ standard library. Nothing under us
  // in the dependency tree appears to export this fact.
  // Ideally, we would be linking dynamically, because statically linking
  // against libstdc++ is kind of scary. But we're only doing it to pull in a
  // bogus symbol anyway, so what's the worst that can happen?
  //
  // The only way I can find to dynamically link against libstdc++ is to pass
  // `-C link-args=lstdc++` to rustc, but we can only do this from a
  // .cargo/config file, which applies that argument to every compile/link which
  // happens in a subdirectory of that directory, which isn't what we want to do.
  // So we'll statically link. Because what's the worst that can happen?
  //
  // The following do not work:
  //  * Using the link argument in Cargo.toml to specify stdc++.
  //  * Specifying `rustc-flags=-lstdc++`
  //    (which is equivalent to `-ldylib=stdc++`).
  //  * Specifying `rustc-link-lib=stdc++`
  //    (which is equivalent to `rustc-link-lib=dylib=stdc++).
  if cfg!(target_os = "linux") {
    println!("cargo:rustc-link-lib=static=stdc++");
  }

  // Generate the cffi c sources.
  let build_root = BuildRoot::find().unwrap();
  let cffi_bootstrapper = build_root.join("build-support/bin/native/bootstrap_cffi.sh");

  // N.B. The filename of this source code - at generation time - must line up 1:1 with the
  // python import name, as python keys the initialization function name off of the import name.
  let cffi_dir = Path::new("src/cffi");
  let c_path = mark_for_change_detection(cffi_dir.join("native_engine.c"));
  let env_script_path = mark_for_change_detection(cffi_dir.join("native_engine.cflags"));

  let result = Command::new(&cffi_bootstrapper)
    .arg(cffi_dir)
    .status()
    .expect(&format!("Failed to execute {:?}", &cffi_bootstrapper));
  if !result.success() {
    let exit_code = result.code();
    eprintln!(
      "Execution of {:?} failed with exit code {:?}",
      cffi_bootstrapper, exit_code
    );
    exit(exit_code.unwrap_or(1));
  }

  // Now compile the cffi c sources.
  let mut config = cc::Build::new();

  config.file(c_path.to_str().unwrap());
  for flag in make_flags(&env_script_path).unwrap() {
    config.flag(flag.as_str());
  }

  // cffi generates missing field initializers :(
  config.flag("-Wno-missing-field-initializers");

  config.compile("libnative_engine_ffi.a");
}

fn mark_for_change_detection(path: PathBuf) -> PathBuf {
  // Restrict re-compilation check to just our input files.
  // See: http://doc.crates.io/build-script.html#outputs-of-the-build-script
  println!("cargo:rerun-if-changed={}", path.to_str().unwrap());
  path
}

fn make_flags(env_script_path: &Path) -> Result<Vec<String>> {
  let mut contents = String::new();
  fs::File::open(env_script_path)?.read_to_string(&mut contents)?;
  // It would be a shame if someone were to include a space in an actual quoted value.
  // If they did that, I guess we'd need to implement shell tokenization or something.
  return Ok(
    contents
      .trim()
      .split_whitespace()
      .map(str::to_owned)
      .collect(),
  );
}
<commit_msg>Mark things which generate cffi for change detection (#5883)<commit_after>extern crate build_utils;
extern crate cc;

/*

N.B. This build script is invoked by `cargo` by way of this configuration
in our Cargo.toml:

    [project]
    ...
    build = "src/cffi_build.rs"

Within, we use the `gcc` crate to compile the CFFI C sources (`native_engine.c`)
generated by `bootstrap.sh` into a (private) static lib (`libnative_engine_ffi.a`),
which then gets linked into the final `cargo build` product (the native engine binary).
This process mixes the Python module initialization function and other symbols into the
native engine binary, allowing us to address it both as an importable python module
(`from _native_engine import X`) as well as a C library (`ffi.dlopen(native_engine.so)`).

*/

use std::fs;
use std::io::{Read, Result};
use std::path::Path;
use std::process::{exit, Command};

use build_utils::BuildRoot;

fn main() {
  // We depend on grpcio, which uses C++.
  // On Linux, with g++, some part of that compilation depends on
  // __gxx_personality_v0 which is present in the C++ standard library.
  // I don't know why. It shouldn't, and before grpcio 0.2.0, it didn't.
  //
  // So we need to link against the C++ standard library. Nothing under us
  // in the dependency tree appears to export this fact.
  // Ideally, we would be linking dynamically, because statically linking
  // against libstdc++ is kind of scary. But we're only doing it to pull in a
  // bogus symbol anyway, so what's the worst that can happen?
  //
  // The only way I can find to dynamically link against libstdc++ is to pass
  // `-C link-args=lstdc++` to rustc, but we can only do this from a
  // .cargo/config file, which applies that argument to every compile/link which
  // happens in a subdirectory of that directory, which isn't what we want to do.
  // So we'll statically link. Because what's the worst that can happen?
  //
  // The following do not work:
  //  * Using the link argument in Cargo.toml to specify stdc++.
  //  * Specifying `rustc-flags=-lstdc++`
  //    (which is equivalent to `-ldylib=stdc++`).
  //  * Specifying `rustc-link-lib=stdc++`
  //    (which is equivalent to `rustc-link-lib=dylib=stdc++).
  if cfg!(target_os = "linux") {
    println!("cargo:rustc-link-lib=static=stdc++");
  }

  // Generate the cffi c sources.
  let build_root = BuildRoot::find().unwrap();
  let cffi_bootstrapper = build_root.join("build-support/bin/native/bootstrap_cffi.sh");
  mark_for_change_detection(&cffi_bootstrapper);

  mark_for_change_detection(&build_root.join("src/python/pants/engine/native.py"));

  // N.B. The filename of this source code - at generation time - must line up 1:1 with the
  // python import name, as python keys the initialization function name off of the import name.
  let cffi_dir = Path::new("src/cffi");
  let c_path = cffi_dir.join("native_engine.c");
  mark_for_change_detection(&c_path);
  let env_script_path = cffi_dir.join("native_engine.cflags");
  mark_for_change_detection(&env_script_path);

  let result = Command::new(&cffi_bootstrapper)
    .arg(cffi_dir)
    .status()
    .expect(&format!("Failed to execute {:?}", &cffi_bootstrapper));
  if !result.success() {
    let exit_code = result.code();
    eprintln!(
      "Execution of {:?} failed with exit code {:?}",
      cffi_bootstrapper, exit_code
    );
    exit(exit_code.unwrap_or(1));
  }

  // Now compile the cffi c sources.
  let mut config = cc::Build::new();

  config.file(c_path.to_str().unwrap());
  for flag in make_flags(&env_script_path).unwrap() {
    config.flag(flag.as_str());
  }

  // cffi generates missing field initializers :(
  config.flag("-Wno-missing-field-initializers");

  config.compile("libnative_engine_ffi.a");
}

fn mark_for_change_detection(path: &Path) {
  // Restrict re-compilation check to just our input files.
  // See: http://doc.crates.io/build-script.html#outputs-of-the-build-script
  println!("cargo:rerun-if-changed={}", path.to_str().unwrap());
}

fn make_flags(env_script_path: &Path) -> Result<Vec<String>> {
  let mut contents = String::new();
  fs::File::open(env_script_path)?.read_to_string(&mut contents)?;
  // It would be a shame if someone were to include a space in an actual quoted value.
  // If they did that, I guess we'd need to implement shell tokenization or something.
  return Ok(
    contents
      .trim()
      .split_whitespace()
      .map(str::to_owned)
      .collect(),
  );
}
<|endoftext|>


<commit_before>use super::*;
use crate::test;

#[test]
fn execute_valid() {
    if test::should_test(false) {
        execute(
            &vec!["fn main() {println!(\"test\");}".to_string()],
            &vec![],
            true,
        );
    }
}

#[test]
#[should_panic]
fn execute_not_compile() {
    if test::should_test(true) {
        execute(
            &vec!["fn main() {donotcompile();}".to_string()],
            &vec![],
            true,
        );
    }
}

#[test]
#[should_panic]
fn execute_runtime_panic() {
    if test::should_test(true) {
        execute(
            &vec!["fn main() {panic!(\"error\");}".to_string()],
            &vec![],
            true,
        );
    }
}

#[test]
fn execute_runtime_panic_no_validate() {
    if test::should_test(true) {
        execute(
            &vec!["fn main() {panic!(\"error\");}".to_string()],
            &vec![],
            false,
        );
    }
}
<commit_msg>Fix tests #173<commit_after>use super::*;
use crate::test;

#[test]
fn execute_valid() {
    if test::should_test(false) {
        execute(
            &vec!["fn main() {println!(\"test\");}".to_string()],
            &vec![],
            true,
        );
    }
}

#[test]
#[should_panic]
fn execute_not_compile() {
    if test::should_test(true) {
        execute(
            &vec!["fn main() {donotcompile();}".to_string()],
            &vec![],
            true,
        );
    }
}

#[test]
#[should_panic]
fn execute_runtime_panic() {
    if test::should_test(true) {
        execute(
            &vec!["fn main() {panic!(\"error\");}".to_string()],
            &vec![],
            true,
        );
    }
}

#[test]
fn execute_runtime_panic_no_validate() {
    if test::should_test(false) {
        execute(
            &vec!["fn main() {panic!(\"error\");}".to_string()],
            &vec![],
            false,
        );
    }
}
<|endoftext|>


<commit_before>extern crate env_logger;
extern crate log;

use std::sync::{Once, ONCE_INIT};

pub struct LoggerUtils {}

struct SimpleLogger;

use self::log::{LogMetadata, LogRecord, LogLevelFilter};

impl log::Log for SimpleLogger {
    fn enabled(&self, metadata: &LogMetadata) -> bool {
        true
    }
    fn log(&self, record: &LogRecord) {
        if self.enabled(record.metadata()) {
            println!("{:>5}|{:<25}|{:>30}:{:<4}| {}", record.level(), record.target(), record.location().file(), record.location().line(), record.args());
        }
    }
}

impl LoggerUtils {
    pub fn init() {
        lazy_static! {
            static ref LOGGER_INIT: Once = ONCE_INIT;
        }

        LOGGER_INIT.call_once(|| {
            log::set_logger(|max_log_level| {
                max_log_level.set(LogLevelFilter::Info);
                Box::new(SimpleLogger)
            }).unwrap();
        });
    }
}

#[macro_export]
macro_rules! try_log {
    ($expr:expr) => (match $expr {
        Ok(val) => val,
        Err(err) => {
            error!("try_log! | {}", err);
            return Err(From::from(err))
        }
    })
}
<commit_msg>Update trace format<commit_after>extern crate env_logger;
extern crate log;

use std::sync::{Once, ONCE_INIT};

pub struct LoggerUtils {}

struct SimpleLogger;

use self::log::{LogMetadata, LogRecord, LogLevelFilter};

impl log::Log for SimpleLogger {
    fn enabled(&self, metadata: &LogMetadata) -> bool {
        true
    }
    fn log(&self, record: &LogRecord) {
        if self.enabled(record.metadata()) {
            println!("{:>5}|{:<27}|{:>30}:{:<4}| {}", record.level(), record.target(), record.location().file(), record.location().line(), record.args());
        }
    }
}

impl LoggerUtils {
    pub fn init() {
        lazy_static! {
            static ref LOGGER_INIT: Once = ONCE_INIT;
        }

        LOGGER_INIT.call_once(|| {
            log::set_logger(|max_log_level| {
                max_log_level.set(LogLevelFilter::Info);
                Box::new(SimpleLogger)
            }).unwrap();
        });
    }
}

#[macro_export]
macro_rules! try_log {
    ($expr:expr) => (match $expr {
        Ok(val) => val,
        Err(err) => {
            error!("try_log! | {}", err);
            return Err(From::from(err))
        }
    })
}
<|endoftext|>