<commit_before>// Copyright (c) Carl-Erwin Griffith
//
// Permission is hereby granted, free of charge, to any
// person obtaining a copy of this software and associated
// documentation files (the "Software"), to deal in the
// Software without restriction, including without
// limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice
// shall be included in all copies or substantial portions
// of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER

pub mod line;

use core::codepointinfo::CodepointInfo;

use self::line::Line;
use self::line::LineCellIndex;

pub type LineIndex = usize;

/// A Screen is composed of Line(s).

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Screen {
    /// the underlying lines storage
    pub line: Vec<Line>,
    /// the index of the line filled with the puhs method
    pub current_line_index: LineCellIndex,
    /// maximum number of elements the screen line can hold
    pub width: usize,
    /// maximum number of lines the screen can hold
    pub height: usize,
    /// the number of elements pushed in the screen
    pub nb_push: usize,
    /// placeholder to record the offset of the first pushed CodepointInfo (used by View)
    pub first_offset: u64,
    /// placeholder to record the offset of the last pushed CodepointInfo (used by View)
    pub last_offset: u64,
    /// placeholder to record the maximum offset of the document (eof)
    pub doc_max_offset: u64,
}

impl Screen {
    pub fn new(width: usize, height: usize) -> Screen {
        let mut line: Vec<Line> = Vec::new();
        for _ in 0..height {
            line.push(Line::new(width));
        }

        Screen {
            line,
            current_line_index: 0,
            width,
            height,
            nb_push: 0,
            first_offset: 0,
            last_offset: 0,
            doc_max_offset: 0,
        }
    }

    pub fn resize(&mut self, width: usize, height: usize) {
        self.line.resize(height, Line::new(width));
        for i in 0..height {
            self.line[i].resize(width);
        }
        self.width = width;
        self.height = height;
        self.current_line_index = 0;
        self.nb_push = 0;
        self.first_offset = 0;
        self.last_offset = 0;
        self.doc_max_offset = 0;
    }

    /// append
    pub fn push(&mut self, cpi: CodepointInfo) -> (bool, usize) {
        if self.current_line_index == self.height {
            return (false, self.current_line_index);
        }

        if self.line[self.current_line_index].read_only {
            self.current_line_index += 1;
        }

        if self.current_line_index == self.height {
            return (false, self.current_line_index);
        }

        let cp = cpi.cp;
        let line = &mut self.line[self.current_line_index];
        let (ok, _) = line.push(cpi);

        if ok {
            self.nb_push += 1;
            if cp == '\n' || cp == '\r' {
                line.read_only = true;
            }
        }
        (ok, self.current_line_index)
    }

    pub fn clear(&mut self) {
        for h in 0..self.height {
            self.line[h].clear();
        }
        self.current_line_index = 0;
        self.nb_push = 0;
        self.first_offset = 0;
        self.last_offset = 0;
        self.doc_max_offset = 0;
    }

    pub fn get_mut_line(&mut self, index: usize) -> Option<&mut Line> {
        if index < self.height {
            Some(&mut self.line[index])
        } else {
            None
        }
    }

    pub fn get_line(&self, index: usize) -> Option<&Line> {
        if index < self.height {
            Some(&self.line[index])
        } else {
            None
        }
    }

    pub fn get_mut_used_line(&mut self, index: usize) -> Option<&mut Line> {
        if index < self.current_line_index {
            Some(&mut self.line[index])
        } else {
            None
        }
    }

    pub fn get_used_line_clipped(&mut self, index: usize) -> (Option<&Line>, LineIndex) {
        let index = ::std::cmp::min(index, self.current_line_index);
        (self.get_used_line(index), index)
    }

    pub fn get_used_line(&self, index: usize) -> Option<&Line> {
        if index < self.current_line_index {
            Some(&self.line[index])
        } else {
            None
        }
    }

    /// there must be 2 line a least
    pub fn get_first_used_line(&self) -> Option<&Line> {
        if 0 < self.current_line_index {
            Some(&self.line[0])
        } else {
            None
        }
    }

    /// there must be 2 line a least
    pub fn get_last_used_line(&self) -> Option<&Line> {
        if self.current_line_index > 0 {
            Some(&self.line[self.current_line_index - 1])
        } else {
            None
        }
    }

    pub fn get_cpinfo(&self, x: usize, y: usize) -> Option<&CodepointInfo> {
        match self.get_line(y) {
            None => None,
            Some(l) => l.get_cpi(x),
        }
    }

    pub fn get_mut_cpinfo(&mut self, x: usize, y: usize) -> Option<&mut CodepointInfo> {
        match self.get_mut_line(y) {
            None => None,
            Some(l) => l.get_mut_cpi(x),
        }
    }

    pub fn get_used_cpinfo(&self, x: usize, y: usize) -> Option<&CodepointInfo> {
        match self.get_used_line(y) {
            None => None,
            Some(l) => l.get_used_cpi(x),
        }
    }

    pub fn get_mut_used_cpinfo(&mut self, x: usize, y: usize) -> Option<&mut CodepointInfo> {
        match self.get_mut_used_line(y) {
            None => None,
            Some(l) => l.get_mut_used_cpi(x),
        }
    }

    pub fn get_mut_first_cpinfo(&mut self) -> (Option<&mut CodepointInfo>, usize, usize) {
        match self.get_mut_used_line(0) {
            None => (None, 0, 0),
            Some(l) => (l.get_mut_used_cpi(0), 0, 0),
        }
    }

    pub fn get_mut_last_cpinfo(&mut self) -> (Option<&mut CodepointInfo>, usize, usize) {
        let y = self.current_line_index;
        match self.get_mut_used_line(y) {
            None => (None, 0, 0),
            Some(l) => {
                let x = l.nb_cells;
                (l.get_mut_used_cpi(0), x, y)
            }
        }
    }

    pub fn get_first_cpinfo(&self) -> (Option<&CodepointInfo>, usize, usize) {
        match self.get_used_line(0) {
            None => (None, 0, 0),
            Some(l) => (l.get_used_cpi(0), 0, 0),
        }
    }

    pub fn get_last_cpinfo(&self) -> (Option<&CodepointInfo>, usize, usize) {
        let y = self.current_line_index;
        match self.get_used_line(y) {
            None => (None, 0, 0),
            Some(l) => {
                if l.nb_cells > 0 {
                    let x = l.nb_cells - 1;
                    (l.get_used_cpi(0), x, y)
                } else {
                    (None, 0, 0)
                }
            }
        }
    }

    pub fn get_used_cpinfo_clipped(
        &mut self,
        x: usize,
        y: usize,
    ) -> (Option<&CodepointInfo>, LineCellIndex, LineIndex) {
        match self.get_used_line_clipped(y) {
            (None, li) => (None, x, li),
            (Some(l), li) => match l.get_used_cpi_clipped(x) {
                (optcpi, lci) => (optcpi, lci, li),
            },
        }
    }

    pub fn find_cpi_by_offset(&self, offset: u64) -> (Option<&CodepointInfo>, usize, usize) {
        // TODO: use dichotomic search

        if offset < self.first_offset || offset > self.last_offset {
            return (None, 0, 0);
        }

        for y in 0..self.height {
            let l = self.get_line(y).unwrap();
            if l.nb_cells == 0 {
                continue;
            }

            for x in 0..l.width {
                let cpi = l.get_cpi(x).unwrap();
                if cpi.offset == offset {
                    return (Some(cpi), x, y);
                }
            }
        }
        (None, 0, 0)
    }

    pub fn contains_offset(&self, offset: u64) -> bool {
        if offset < self.first_offset || offset > self.last_offset {
            return false;
        }

        let (cpi, _, _) = self.find_cpi_by_offset(offset);
        match cpi {
            Some(_) => true,
            _ => false,
        }
    }
}

#[test]
fn test_screen() {
    let mut scr = Screen::new(640, 480);
    assert_eq!(640, scr.width);
    assert_eq!(480, scr.height);
    assert_eq!(scr.height, scr.line.len());
    assert_eq!(scr.width, scr.line[0].cells.len());

    scr.resize(800, 600);
    assert_eq!(800, scr.width);
    assert_eq!(600, scr.height);
    assert_eq!(scr.height, scr.line.len());
    assert_eq!(scr.width, scr.line[0].cells.len());

    scr.resize(1024, 768);
    assert_eq!(1024, scr.width);
    assert_eq!(768, scr.height);
    assert_eq!(scr.height, scr.line.len());
    assert_eq!(scr.width, scr.line[0].cells.len());

    scr.resize(640, 480);
    assert_eq!(640, scr.width);
    assert_eq!(480, scr.height);
    assert_eq!(scr.height, scr.line.len());
    assert_eq!(scr.width, scr.line[0].cells.len());
}
<commit_msg>fix typo<commit_after>// Copyright (c) Carl-Erwin Griffith
//
// Permission is hereby granted, free of charge, to any
// person obtaining a copy of this software and associated
// documentation files (the "Software"), to deal in the
// Software without restriction, including without
// limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice
// shall be included in all copies or substantial portions
// of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER

pub mod line;

use core::codepointinfo::CodepointInfo;

use self::line::Line;
use self::line::LineCellIndex;

pub type LineIndex = usize;

/// A Screen is composed of Line(s).

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Screen {
    /// the underlying lines storage
    pub line: Vec<Line>,
    /// the index of the line filled with the push method
    pub current_line_index: LineCellIndex,
    /// maximum number of elements the screen line can hold
    pub width: usize,
    /// maximum number of lines the screen can hold
    pub height: usize,
    /// the number of elements pushed in the screen
    pub nb_push: usize,
    /// placeholder to record the offset of the first pushed CodepointInfo (used by View)
    pub first_offset: u64,
    /// placeholder to record the offset of the last pushed CodepointInfo (used by View)
    pub last_offset: u64,
    /// placeholder to record the maximum offset of the document (eof)
    pub doc_max_offset: u64,
}

impl Screen {
    pub fn new(width: usize, height: usize) -> Screen {
        let mut line: Vec<Line> = Vec::new();
        for _ in 0..height {
            line.push(Line::new(width));
        }

        Screen {
            line,
            current_line_index: 0,
            width,
            height,
            nb_push: 0,
            first_offset: 0,
            last_offset: 0,
            doc_max_offset: 0,
        }
    }

    pub fn resize(&mut self, width: usize, height: usize) {
        self.line.resize(height, Line::new(width));
        for i in 0..height {
            self.line[i].resize(width);
        }
        self.width = width;
        self.height = height;
        self.current_line_index = 0;
        self.nb_push = 0;
        self.first_offset = 0;
        self.last_offset = 0;
        self.doc_max_offset = 0;
    }

    /// append
    pub fn push(&mut self, cpi: CodepointInfo) -> (bool, usize) {
        if self.current_line_index == self.height {
            return (false, self.current_line_index);
        }

        if self.line[self.current_line_index].read_only {
            self.current_line_index += 1;
        }

        if self.current_line_index == self.height {
            return (false, self.current_line_index);
        }

        let cp = cpi.cp;
        let line = &mut self.line[self.current_line_index];
        let (ok, _) = line.push(cpi);

        if ok {
            self.nb_push += 1;
            if cp == '\n' || cp == '\r' {
                line.read_only = true;
            }
        }
        (ok, self.current_line_index)
    }

    pub fn clear(&mut self) {
        for h in 0..self.height {
            self.line[h].clear();
        }
        self.current_line_index = 0;
        self.nb_push = 0;
        self.first_offset = 0;
        self.last_offset = 0;
        self.doc_max_offset = 0;
    }

    pub fn get_mut_line(&mut self, index: usize) -> Option<&mut Line> {
        if index < self.height {
            Some(&mut self.line[index])
        } else {
            None
        }
    }

    pub fn get_line(&self, index: usize) -> Option<&Line> {
        if index < self.height {
            Some(&self.line[index])
        } else {
            None
        }
    }

    pub fn get_mut_used_line(&mut self, index: usize) -> Option<&mut Line> {
        if index < self.current_line_index {
            Some(&mut self.line[index])
        } else {
            None
        }
    }

    pub fn get_used_line_clipped(&mut self, index: usize) -> (Option<&Line>, LineIndex) {
        let index = ::std::cmp::min(index, self.current_line_index);
        (self.get_used_line(index), index)
    }

    pub fn get_used_line(&self, index: usize) -> Option<&Line> {
        if index < self.current_line_index {
            Some(&self.line[index])
        } else {
            None
        }
    }

    /// there must be 2 line a least
    pub fn get_first_used_line(&self) -> Option<&Line> {
        if 0 < self.current_line_index {
            Some(&self.line[0])
        } else {
            None
        }
    }

    /// there must be 2 line a least
    pub fn get_last_used_line(&self) -> Option<&Line> {
        if self.current_line_index > 0 {
            Some(&self.line[self.current_line_index - 1])
        } else {
            None
        }
    }

    pub fn get_cpinfo(&self, x: usize, y: usize) -> Option<&CodepointInfo> {
        match self.get_line(y) {
            None => None,
            Some(l) => l.get_cpi(x),
        }
    }

    pub fn get_mut_cpinfo(&mut self, x: usize, y: usize) -> Option<&mut CodepointInfo> {
        match self.get_mut_line(y) {
            None => None,
            Some(l) => l.get_mut_cpi(x),
        }
    }

    pub fn get_used_cpinfo(&self, x: usize, y: usize) -> Option<&CodepointInfo> {
        match self.get_used_line(y) {
            None => None,
            Some(l) => l.get_used_cpi(x),
        }
    }

    pub fn get_mut_used_cpinfo(&mut self, x: usize, y: usize) -> Option<&mut CodepointInfo> {
        match self.get_mut_used_line(y) {
            None => None,
            Some(l) => l.get_mut_used_cpi(x),
        }
    }

    pub fn get_mut_first_cpinfo(&mut self) -> (Option<&mut CodepointInfo>, usize, usize) {
        match self.get_mut_used_line(0) {
            None => (None, 0, 0),
            Some(l) => (l.get_mut_used_cpi(0), 0, 0),
        }
    }

    pub fn get_mut_last_cpinfo(&mut self) -> (Option<&mut CodepointInfo>, usize, usize) {
        let y = self.current_line_index;
        match self.get_mut_used_line(y) {
            None => (None, 0, 0),
            Some(l) => {
                let x = l.nb_cells;
                (l.get_mut_used_cpi(0), x, y)
            }
        }
    }

    pub fn get_first_cpinfo(&self) -> (Option<&CodepointInfo>, usize, usize) {
        match self.get_used_line(0) {
            None => (None, 0, 0),
            Some(l) => (l.get_used_cpi(0), 0, 0),
        }
    }

    pub fn get_last_cpinfo(&self) -> (Option<&CodepointInfo>, usize, usize) {
        let y = self.current_line_index;
        match self.get_used_line(y) {
            None => (None, 0, 0),
            Some(l) => {
                if l.nb_cells > 0 {
                    let x = l.nb_cells - 1;
                    (l.get_used_cpi(0), x, y)
                } else {
                    (None, 0, 0)
                }
            }
        }
    }

    pub fn get_used_cpinfo_clipped(
        &mut self,
        x: usize,
        y: usize,
    ) -> (Option<&CodepointInfo>, LineCellIndex, LineIndex) {
        match self.get_used_line_clipped(y) {
            (None, li) => (None, x, li),
            (Some(l), li) => match l.get_used_cpi_clipped(x) {
                (optcpi, lci) => (optcpi, lci, li),
            },
        }
    }

    pub fn find_cpi_by_offset(&self, offset: u64) -> (Option<&CodepointInfo>, usize, usize) {
        // TODO: use dichotomic search

        if offset < self.first_offset || offset > self.last_offset {
            return (None, 0, 0);
        }

        for y in 0..self.height {
            let l = self.get_line(y).unwrap();
            if l.nb_cells == 0 {
                continue;
            }

            for x in 0..l.width {
                let cpi = l.get_cpi(x).unwrap();
                if cpi.offset == offset {
                    return (Some(cpi), x, y);
                }
            }
        }
        (None, 0, 0)
    }

    pub fn contains_offset(&self, offset: u64) -> bool {
        if offset < self.first_offset || offset > self.last_offset {
            return false;
        }

        let (cpi, _, _) = self.find_cpi_by_offset(offset);
        match cpi {
            Some(_) => true,
            _ => false,
        }
    }
}

#[test]
fn test_screen() {
    let mut scr = Screen::new(640, 480);
    assert_eq!(640, scr.width);
    assert_eq!(480, scr.height);
    assert_eq!(scr.height, scr.line.len());
    assert_eq!(scr.width, scr.line[0].cells.len());

    scr.resize(800, 600);
    assert_eq!(800, scr.width);
    assert_eq!(600, scr.height);
    assert_eq!(scr.height, scr.line.len());
    assert_eq!(scr.width, scr.line[0].cells.len());

    scr.resize(1024, 768);
    assert_eq!(1024, scr.width);
    assert_eq!(768, scr.height);
    assert_eq!(scr.height, scr.line.len());
    assert_eq!(scr.width, scr.line[0].cells.len());

    scr.resize(640, 480);
    assert_eq!(640, scr.width);
    assert_eq!(480, scr.height);
    assert_eq!(scr.height, scr.line.len());
    assert_eq!(scr.width, scr.line[0].cells.len());
}
<|endoftext|>


<commit_before>use crate::utils::span_lint;
use rustc_ast::ast;
use rustc_hir as hir;
use rustc_lint::{self, LateContext, LateLintPass, LintContext};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;

declare_clippy_lint! {
    /// **What it does:** it lints if an exported function, method, trait method with default impl,
    /// or trait method impl is not `#[inline]`.
    ///
    /// **Why is this bad?** In general, it is not. Functions can be inlined across
    /// crates when that's profitable as long as any form of LTO is used. When LTO is disabled,
    /// functions that are not `#[inline]` cannot be inlined across crates. Certain types of crates
    /// might intend for most of the methods in their public API to be able to be inlined across
    /// crates even when LTO is disabled. For these types of crates, enabling this lint might make
    /// sense. It allows the crate to require all exported methods to be `#[inline]` by default, and
    /// then opt out for specific methods where this might not make sense.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// pub fn foo() {} // missing #[inline]
    /// fn ok() {} // ok
    /// #[inline] pub fn bar() {} // ok
    /// #[inline(always)] pub fn baz() {} // ok
    ///
    /// pub trait Bar {
    ///   fn bar(); // ok
    ///   fn def_bar() {} // missing #[inline]
    /// }
    ///
    /// struct Baz;
    /// impl Baz {
    ///    fn private() {} // ok
    /// }
    ///
    /// impl Bar for Baz {
    ///   fn bar() {} // ok - Baz is not exported
    /// }
    ///
    /// pub struct PubBaz;
    /// impl PubBaz {
    ///    fn private() {} // ok
    ///    pub fn not_ptrivate() {} // missing #[inline]
    /// }
    ///
    /// impl Bar for PubBaz {
    ///    fn bar() {} // missing #[inline]
    ///    fn def_bar() {} // missing #[inline]
    /// }
    /// ```
    pub MISSING_INLINE_IN_PUBLIC_ITEMS,
    restriction,
    "detects missing `#[inline]` attribute for public callables (functions, trait methods, methods...)"
}

fn check_missing_inline_attrs(cx: &LateContext<'_, '_>, attrs: &[ast::Attribute], sp: Span, desc: &'static str) {
    let has_inline = attrs.iter().any(|a| a.check_name(sym!(inline)));
    if !has_inline {
        span_lint(
            cx,
            MISSING_INLINE_IN_PUBLIC_ITEMS,
            sp,
            &format!("missing `#[inline]` for {}", desc),
        );
    }
}

fn is_executable(cx: &LateContext<'_, '_>) -> bool {
    use rustc_session::config::CrateType;

    cx.tcx.sess.crate_types.get().iter().any(|t: &CrateType| match t {
        CrateType::Executable => true,
        _ => false,
    })
}

declare_lint_pass!(MissingInline => [MISSING_INLINE_IN_PUBLIC_ITEMS]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline {
    fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, it: &'tcx hir::Item<'_>) {
        if rustc_middle::lint::in_external_macro(cx.sess(), it.span) || is_executable(cx) {
            return;
        }

        if !cx.access_levels.is_exported(it.hir_id) {
            return;
        }
        match it.kind {
            hir::ItemKind::Fn(..) => {
                let desc = "a function";
                check_missing_inline_attrs(cx, &it.attrs, it.span, desc);
            },
            hir::ItemKind::Trait(ref _is_auto, ref _unsafe, ref _generics, ref _bounds, trait_items) => {
                // note: we need to check if the trait is exported so we can't use
                // `LateLintPass::check_trait_item` here.
                for tit in trait_items {
                    let tit_ = cx.tcx.hir().trait_item(tit.id);
                    match tit_.kind {
                        hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(..) => {},
                        hir::TraitItemKind::Fn(..) => {
                            if tit.defaultness.has_value() {
                                // trait method with default body needs inline in case
                                // an impl is not provided
                                let desc = "a default trait method";
                                let item = cx.tcx.hir().expect_trait_item(tit.id.hir_id);
                                check_missing_inline_attrs(cx, &item.attrs, item.span, desc);
                            }
                        },
                    }
                }
            },
            hir::ItemKind::Const(..)
            | hir::ItemKind::Enum(..)
            | hir::ItemKind::Mod(..)
            | hir::ItemKind::Static(..)
            | hir::ItemKind::Struct(..)
            | hir::ItemKind::TraitAlias(..)
            | hir::ItemKind::GlobalAsm(..)
            | hir::ItemKind::TyAlias(..)
            | hir::ItemKind::Union(..)
            | hir::ItemKind::OpaqueTy(..)
            | hir::ItemKind::ExternCrate(..)
            | hir::ItemKind::ForeignMod(..)
            | hir::ItemKind::Impl { .. }
            | hir::ItemKind::Use(..) => {},
        };
    }

    fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &'tcx hir::ImplItem<'_>) {
        use rustc_middle::ty::{ImplContainer, TraitContainer};
        if rustc_middle::lint::in_external_macro(cx.sess(), impl_item.span) || is_executable(cx) {
            return;
        }

        // If the item being implemented is not exported, then we don't need #[inline]
        if !cx.access_levels.is_exported(impl_item.hir_id) {
            return;
        }

        let desc = match impl_item.kind {
            hir::ImplItemKind::Fn(..) => "a method",
            hir::ImplItemKind::Const(..) | hir::ImplItemKind::TyAlias(_) | hir::ImplItemKind::OpaqueTy(_) => return,
        };

        let def_id = cx.tcx.hir().local_def_id(impl_item.hir_id);
        let trait_def_id = match cx.tcx.associated_item(def_id).container {
            TraitContainer(cid) => Some(cid),
            ImplContainer(cid) => cx.tcx.impl_trait_ref(cid).map(|t| t.def_id),
        };

        if let Some(trait_def_id) = trait_def_id {
            if trait_def_id.is_local() && !cx.access_levels.is_exported(impl_item.hir_id) {
                // If a trait is being implemented for an item, and the
                // trait is not exported, we don't need #[inline]
                return;
            }
        }

        check_missing_inline_attrs(cx, &impl_item.attrs, impl_item.span, desc);
    }
}
<commit_msg>Auto merge of #5646 - flip1995:rustup, r=matthiaskrgr<commit_after>use crate::utils::span_lint;
use rustc_ast::ast;
use rustc_hir as hir;
use rustc_lint::{self, LateContext, LateLintPass, LintContext};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;

declare_clippy_lint! {
    /// **What it does:** it lints if an exported function, method, trait method with default impl,
    /// or trait method impl is not `#[inline]`.
    ///
    /// **Why is this bad?** In general, it is not. Functions can be inlined across
    /// crates when that's profitable as long as any form of LTO is used. When LTO is disabled,
    /// functions that are not `#[inline]` cannot be inlined across crates. Certain types of crates
    /// might intend for most of the methods in their public API to be able to be inlined across
    /// crates even when LTO is disabled. For these types of crates, enabling this lint might make
    /// sense. It allows the crate to require all exported methods to be `#[inline]` by default, and
    /// then opt out for specific methods where this might not make sense.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// pub fn foo() {} // missing #[inline]
    /// fn ok() {} // ok
    /// #[inline] pub fn bar() {} // ok
    /// #[inline(always)] pub fn baz() {} // ok
    ///
    /// pub trait Bar {
    ///   fn bar(); // ok
    ///   fn def_bar() {} // missing #[inline]
    /// }
    ///
    /// struct Baz;
    /// impl Baz {
    ///    fn private() {} // ok
    /// }
    ///
    /// impl Bar for Baz {
    ///   fn bar() {} // ok - Baz is not exported
    /// }
    ///
    /// pub struct PubBaz;
    /// impl PubBaz {
    ///    fn private() {} // ok
    ///    pub fn not_ptrivate() {} // missing #[inline]
    /// }
    ///
    /// impl Bar for PubBaz {
    ///    fn bar() {} // missing #[inline]
    ///    fn def_bar() {} // missing #[inline]
    /// }
    /// ```
    pub MISSING_INLINE_IN_PUBLIC_ITEMS,
    restriction,
    "detects missing `#[inline]` attribute for public callables (functions, trait methods, methods...)"
}

fn check_missing_inline_attrs(cx: &LateContext<'_, '_>, attrs: &[ast::Attribute], sp: Span, desc: &'static str) {
    let has_inline = attrs.iter().any(|a| a.check_name(sym!(inline)));
    if !has_inline {
        span_lint(
            cx,
            MISSING_INLINE_IN_PUBLIC_ITEMS,
            sp,
            &format!("missing `#[inline]` for {}", desc),
        );
    }
}

fn is_executable(cx: &LateContext<'_, '_>) -> bool {
    use rustc_session::config::CrateType;

    cx.tcx.sess.crate_types().iter().any(|t: &CrateType| match t {
        CrateType::Executable => true,
        _ => false,
    })
}

declare_lint_pass!(MissingInline => [MISSING_INLINE_IN_PUBLIC_ITEMS]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline {
    fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, it: &'tcx hir::Item<'_>) {
        if rustc_middle::lint::in_external_macro(cx.sess(), it.span) || is_executable(cx) {
            return;
        }

        if !cx.access_levels.is_exported(it.hir_id) {
            return;
        }
        match it.kind {
            hir::ItemKind::Fn(..) => {
                let desc = "a function";
                check_missing_inline_attrs(cx, &it.attrs, it.span, desc);
            },
            hir::ItemKind::Trait(ref _is_auto, ref _unsafe, ref _generics, ref _bounds, trait_items) => {
                // note: we need to check if the trait is exported so we can't use
                // `LateLintPass::check_trait_item` here.
                for tit in trait_items {
                    let tit_ = cx.tcx.hir().trait_item(tit.id);
                    match tit_.kind {
                        hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(..) => {},
                        hir::TraitItemKind::Fn(..) => {
                            if tit.defaultness.has_value() {
                                // trait method with default body needs inline in case
                                // an impl is not provided
                                let desc = "a default trait method";
                                let item = cx.tcx.hir().expect_trait_item(tit.id.hir_id);
                                check_missing_inline_attrs(cx, &item.attrs, item.span, desc);
                            }
                        },
                    }
                }
            },
            hir::ItemKind::Const(..)
            | hir::ItemKind::Enum(..)
            | hir::ItemKind::Mod(..)
            | hir::ItemKind::Static(..)
            | hir::ItemKind::Struct(..)
            | hir::ItemKind::TraitAlias(..)
            | hir::ItemKind::GlobalAsm(..)
            | hir::ItemKind::TyAlias(..)
            | hir::ItemKind::Union(..)
            | hir::ItemKind::OpaqueTy(..)
            | hir::ItemKind::ExternCrate(..)
            | hir::ItemKind::ForeignMod(..)
            | hir::ItemKind::Impl { .. }
            | hir::ItemKind::Use(..) => {},
        };
    }

    fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &'tcx hir::ImplItem<'_>) {
        use rustc_middle::ty::{ImplContainer, TraitContainer};
        if rustc_middle::lint::in_external_macro(cx.sess(), impl_item.span) || is_executable(cx) {
            return;
        }

        // If the item being implemented is not exported, then we don't need #[inline]
        if !cx.access_levels.is_exported(impl_item.hir_id) {
            return;
        }

        let desc = match impl_item.kind {
            hir::ImplItemKind::Fn(..) => "a method",
            hir::ImplItemKind::Const(..) | hir::ImplItemKind::TyAlias(_) | hir::ImplItemKind::OpaqueTy(_) => return,
        };

        let def_id = cx.tcx.hir().local_def_id(impl_item.hir_id);
        let trait_def_id = match cx.tcx.associated_item(def_id).container {
            TraitContainer(cid) => Some(cid),
            ImplContainer(cid) => cx.tcx.impl_trait_ref(cid).map(|t| t.def_id),
        };

        if let Some(trait_def_id) = trait_def_id {
            if trait_def_id.is_local() && !cx.access_levels.is_exported(impl_item.hir_id) {
                // If a trait is being implemented for an item, and the
                // trait is not exported, we don't need #[inline]
                return;
            }
        }

        check_missing_inline_attrs(cx, &impl_item.attrs, impl_item.span, desc);
    }
}
<|endoftext|>


<commit_before>use std::fmt::Display;
use std::fmt::{Formatter, Result};

pub struct GapBuffer {
    pub buffer: Vec<char>,
    pub cursor: usize,
    pub gap_start: usize,
    pub gap_end: usize,
}

impl GapBuffer {
    fn place_gap(&mut self) {
        if self.cursor == self.gap_start {
            return;
        }
        if self.cursor < self.gap_start {
            let count = self.gap_end - self.gap_start;
            let amt = self.gap_start - self.cursor;

            for i in self.cursor..self.gap_start {
                self.buffer[i + count] = self.buffer[i];
            }
            self.gap_start -= amt;
            self.gap_end -= amt;

            for i in self.gap_start..self.gap_end {
                self.buffer[i] = '\0';
            }
        } else {
            let count = self.gap_end - self.gap_start;
            let amt = self.cursor - self.gap_start;

            for i in self.gap_end..self.buffer.len() {
                self.buffer[i - count] = self.buffer[i];
            }
            self.gap_start += amt;
            self.gap_end += amt;

            for i in self.gap_start..self.gap_end {
                self.buffer[i] = '\0';
            }

        }
    }
    fn check_capacity(&mut self) {
        if self.gap_end == self.gap_start {
            self.extend_buffer();
        }
    }
    fn extend_buffer(&mut self) {
        let len = self.buffer.clone().len();
        self.buffer.resize(len * 2, '\0');
        // still buggy :(
        // for i in self.gap_end..self.buffer.len() - len {
        //     self.buffer[i + len] = self.buffer[i];
        // }
        // self.gap_end += len;

        // for i in self.gap_start..self.gap_end {
        //     self.buffer[i] = '\0';
        // }
    }
    pub fn insert(&mut self, ch: char) {
        self.check_capacity();
        self.place_gap();
        self.buffer[self.cursor] = ch;
        self.cursor += 1;
        self.gap_start += 1;
    }
    pub fn delete(&mut self) {
        if self.gap_start > 0 && self.cursor > 0 {
            self.cursor -= 1;
            self.gap_start -= 1;
        }
        for i in self.gap_start..self.gap_end {
            self.buffer[i] = '\0';
        }
    }
    pub fn new(size: usize) -> GapBuffer {
        GapBuffer {
            buffer: vec!['\0'; size],
            gap_start: 0,
            gap_end: size,
            cursor: 0,
        }
    }
}
impl Display for GapBuffer {
    fn fmt(&self, f: &mut Formatter) -> Result {
        let mut string = String::new();
        for i in self.buffer.clone() {
            string.push(i);
        }
        write!(f, "{}", string)
    }
}
#[cfg(test)]
mod tests {
    #[test]
    fn test_gap_check() {
        use gapbuffer::GapBuffer;
        let mut buffer = GapBuffer::new(5);
        buffer.insert('a');
        buffer.insert('c');

        assert_eq!('a', buffer.buffer[0]);
        assert_eq!('c', buffer.buffer[1]);
        buffer.cursor = 0;
        buffer.insert('d');
        assert_eq!('d', buffer.buffer[0]);
        assert_eq!('a', buffer.buffer[3]);
        assert_eq!('c', buffer.buffer[4]);
    }
    //#[test]
    fn test_gap_check_1() {
        use gapbuffer::GapBuffer;
        let mut buffer = GapBuffer::new(5);
        assert_eq!(4, buffer.gap_end - buffer.gap_start);
        buffer.insert('a');
        assert_eq!(3, buffer.gap_end - buffer.gap_start);
        buffer.cursor = 0;
        buffer.insert('b');
        assert_eq!(2, buffer.gap_end - buffer.gap_start);
        buffer.insert('b');
        assert_eq!(1, buffer.gap_end - buffer.gap_start);
        buffer.insert('b');
        assert_eq!(0, buffer.gap_end - buffer.gap_start);
        buffer.insert('b');

        assert_eq!(4, buffer.gap_end - buffer.gap_start);
    }
    #[test]
    fn test_gap_check_2() {
        use gapbuffer::GapBuffer;
        let mut buffer = GapBuffer::new(5);
        buffer.insert('a');
        buffer.cursor = 3;
        buffer.insert('b');
        assert_eq!('a', buffer.buffer[0]);
        assert_eq!('b', buffer.buffer[3]);
    }
    #[test]
    fn test_gap_check_3() {
        use gapbuffer::GapBuffer;
        let mut buffer = GapBuffer::new(5);
        buffer.insert('a');
        buffer.insert('b');
        buffer.insert('c');
        buffer.insert('d');
        assert_eq!('a', buffer.buffer[0]);
        assert_eq!('b', buffer.buffer[1]);
        assert_eq!('c', buffer.buffer[2]);
        assert_eq!('d', buffer.buffer[3]);

        buffer.cursor = 2;
        buffer.insert(' ');
        assert_eq!(' ', buffer.buffer[2]);
        assert_eq!('c', buffer.buffer[3]);
    }
    #[test]
    fn test_gap_check_4() {
        use gapbuffer::GapBuffer;
        let mut buffer = GapBuffer::new(5);
        buffer.insert('a');
        buffer.insert('b');
        assert_eq!('a', buffer.buffer[0]);
        assert_eq!('b', buffer.buffer[1]);
        buffer.cursor = 0;
        buffer.insert(' ');
        assert_eq!(' ', buffer.buffer[0]);
        assert_eq!('a', buffer.buffer[3]);
        assert_eq!('b', buffer.buffer[4]);
        assert_eq!(1, buffer.gap_start);
        assert_eq!(4, buffer.gap_end);
    }

}
<commit_msg>Gap buffer is working<commit_after>use std::fmt::Display;
use std::fmt::{Formatter, Result};

pub struct GapBuffer {
    pub buffer: Vec<char>,
    pub cursor: usize,
    pub gap_start: usize,
    pub gap_end: usize,
}

impl GapBuffer {
    fn place_gap(&mut self) {
        if self.cursor == self.gap_start {
            return;
        }
        if self.cursor < self.gap_start {
            let count = self.gap_end - self.gap_start;
            let amt = self.gap_start - self.cursor;

            let temp_buffer = self.buffer.clone();
            for i in self.cursor..self.gap_start {
                self.buffer[i + count] = temp_buffer[i];
            }
            self.gap_start -= amt;
            self.gap_end -= amt;

            for i in self.gap_start..self.gap_end {
                self.buffer[i] = '\0';
            }
        } else {
            let count = self.gap_end - self.gap_start;
            let amt = self.cursor - self.gap_start;

            let temp_buffer = self.buffer.clone();
            for i in self.gap_end..self.buffer.len() {
                self.buffer[i - count] = temp_buffer[i];
            }
            self.gap_start += amt;
            self.gap_end += amt;

            for i in self.gap_start..self.gap_end {
                self.buffer[i] = '\0';
            }
        }
    }
    fn check_capacity(&mut self) {
        if self.gap_end == self.gap_start {
            self.extend_buffer();
        }
    }
    fn extend_buffer(&mut self) {
        let len = self.buffer.clone().len();
        self.buffer.resize(len * 2, '\0');
        self.gap_start += len - self.cursor;
        self.gap_end = self.buffer.len();
        self.place_gap();
    }
    pub fn insert(&mut self, ch: char) {
        self.place_gap();
        self.check_capacity();
        self.buffer[self.cursor] = ch;
        self.cursor += 1;
        self.gap_start += 1;
    }
    pub fn delete(&mut self) {
        if self.gap_start > 0 && self.cursor > 0 {
            self.cursor -= 1;
            self.gap_start -= 1;
        }
        for i in self.gap_start..self.gap_end {
            self.buffer[i] = '\0';
        }
    }
    pub fn new(size: usize) -> GapBuffer {
        GapBuffer {
            buffer: vec!['\0'; size],
            gap_start: 0,
            gap_end: size,
            cursor: 0,
        }
    }
}
impl Display for GapBuffer {
    fn fmt(&self, f: &mut Formatter) -> Result {
        let mut string = String::new();
        for i in self.buffer.clone() {
            string.push(i);
        }
        write!(f, "{}", string)
    }
}
#[cfg(test)]
mod tests {
    #[test]
    fn test_gap_check() {
        use gapbuffer::GapBuffer;
        let mut buffer = GapBuffer::new(5);
        buffer.insert('a');
        buffer.insert('c');

        assert_eq!('a', buffer.buffer[0]);
        assert_eq!('c', buffer.buffer[1]);
        buffer.cursor = 0;
        buffer.insert('d');
        assert_eq!('d', buffer.buffer[0]);
        assert_eq!('a', buffer.buffer[3]);
        assert_eq!('c', buffer.buffer[4]);
    }
    //#[test]
    fn test_gap_check_1() {
        use gapbuffer::GapBuffer;
        let mut buffer = GapBuffer::new(5);
        assert_eq!(4, buffer.gap_end - buffer.gap_start);
        buffer.insert('a');
        assert_eq!(3, buffer.gap_end - buffer.gap_start);
        buffer.cursor = 0;
        buffer.insert('b');
        assert_eq!(2, buffer.gap_end - buffer.gap_start);
        buffer.insert('b');
        assert_eq!(1, buffer.gap_end - buffer.gap_start);
        buffer.insert('b');
        assert_eq!(0, buffer.gap_end - buffer.gap_start);
        buffer.insert('b');

        assert_eq!(4, buffer.gap_end - buffer.gap_start);
    }
    #[test]
    fn test_gap_check_2() {
        use gapbuffer::GapBuffer;
        let mut buffer = GapBuffer::new(5);
        buffer.insert('a');
        buffer.cursor = 3;
        buffer.insert('b');
        assert_eq!('a', buffer.buffer[0]);
        assert_eq!('b', buffer.buffer[3]);
    }
    #[test]
    fn test_gap_check_3() {
        use gapbuffer::GapBuffer;
        let mut buffer = GapBuffer::new(5);
        buffer.insert('a');
        buffer.insert('b');
        buffer.insert('c');
        buffer.insert('d');
        assert_eq!('a', buffer.buffer[0]);
        assert_eq!('b', buffer.buffer[1]);
        assert_eq!('c', buffer.buffer[2]);
        assert_eq!('d', buffer.buffer[3]);

        buffer.cursor = 2;
        buffer.insert(' ');
        assert_eq!(' ', buffer.buffer[2]);
        assert_eq!('c', buffer.buffer[3]);
    }
    #[test]
    fn test_gap_check_4() {
        use gapbuffer::GapBuffer;
        let mut buffer = GapBuffer::new(5);
        buffer.insert('a');
        buffer.insert('b');
        assert_eq!('a', buffer.buffer[0]);
        assert_eq!('b', buffer.buffer[1]);
        buffer.cursor = 0;
        buffer.insert(' ');
        assert_eq!(' ', buffer.buffer[0]);
        assert_eq!('a', buffer.buffer[3]);
        assert_eq!('b', buffer.buffer[4]);
        assert_eq!(1, buffer.gap_start);
        assert_eq!(4, buffer.gap_end);
    }

}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! SOS memory allocation library
//!
//! This is in its own crate so it can be used by kernel-space and user-space
//! OS components.

#![crate_name = "sos_alloc"]
#![crate_type = "lib"]

// The compiler needs to be instructed that this crate is an allocator in order
// to realize that when this is linked in another allocator like jemalloc
// should not be linked in
#![feature(allocator)]
#![allocator]

// Allocators are not allowed to depend on the standard library which in turn
// requires an allocator in order to avoid circular dependencies. This crate,
// however, can use all of libcore.
#![feature(no_std)]
#![no_std]

#![feature( ptr_as_ref
          , const_fn
          , core_slice_ext
          , iter_cmp )]

#![cfg(feature = "multiboot")]
extern crate sos_multiboot2 as multiboot;
use core::ptr;
use core::cmp::min;

pub const PAGE_SIZE: usize = 4096;

/// Trait for something that is like a frame.
///
/// Various allocation strategies use different data structures for
/// representing frames. For example, frames may be stored as frame numbers or
/// as nodes in a linked list. To be `Framesque`, an object need only provide
/// a function to convert the frame data to a pointer to the frame in memory.
pub trait Framesque {
    /// Return a pointer to the frame in memory.
    fn as_ptr(&self) - *mut u8;
}

/// An `Allocator` implements a particular memory allocation strategy.
///
/// `Allocator`s are generally `struct`s that contain any additional
/// information necessary to enact that allocation strategy. Since
/// different `Allocator`s may use different methods of tracking frames,
/// each `Allocator` implementation can provide its own frame type, as long as
/// that frame type is `frameesque` (i.e., it provides some method to resolve
/// it into a pointer to its memory area).
pub trait Allocator {
    // type Frame: Framesque;

    unsafe fn allocate(&mut self, size: usize, align: usize)
                      -> Option<*mut u8>;

    unsafe fn deallocate(&mut self, frame: *mut u8, size: usize, align: usize);

    /// Reallocate the memory
    // TODO: Optimization: check if the reallocation request fits in
    // the old frame and return immediately if it does
    unsafe fn reallocate( &mut self, old_frame: *mut u8, old_size: usize
                        , new_size: usize, align: usize )
                        -> Option<*mut u8>
    {
        // First, attempt to allocate a new frame...
        self.allocate(new_size, align)
            .map(|new_frame| {
                // If a new frame was allocated, copy all the data from the
                // old frame into the new frame.
                ptr::copy(new_frame, old_frame, min(old_size, new_size));
                // Then we can deallocate the old frame
                self.deallocate(old_frame, old_size, align);
                new_frame
            })
    }

    unsafe fn zero_alloc(&mut self, size: usize, align: usize)
                        -> Option<*mut u8>
    {
        unimplemented!()
    }
}

mod rawlink;
pub use self::rawlink::RawLink;

#[cfg(feature = "buddy")]
pub mod buddy;

#[cfg(feature = "simple")]
pub mod simple;
<commit_msg>Fix a typo<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! SOS memory allocation library
//!
//! This is in its own crate so it can be used by kernel-space and user-space
//! OS components.

#![crate_name = "sos_alloc"]
#![crate_type = "lib"]

// The compiler needs to be instructed that this crate is an allocator in order
// to realize that when this is linked in another allocator like jemalloc
// should not be linked in
#![feature(allocator)]
#![allocator]

// Allocators are not allowed to depend on the standard library which in turn
// requires an allocator in order to avoid circular dependencies. This crate,
// however, can use all of libcore.
#![feature(no_std)]
#![no_std]

#![feature( ptr_as_ref
          , const_fn
          , core_slice_ext
          , iter_cmp )]

#![cfg(feature = "multiboot")]
extern crate sos_multiboot2 as multiboot;
use core::ptr;
use core::cmp::min;

pub const PAGE_SIZE: usize = 4096;

/// Trait for something that is like a frame.
///
/// Various allocation strategies use different data structures for
/// representing frames. For example, frames may be stored as frame numbers or
/// as nodes in a linked list. To be `Framesque`, an object need only provide
/// a function to convert the frame data to a pointer to the frame in memory.
pub trait Framesque {
    /// Return a pointer to the frame in memory.
    fn as_ptr(&self) -> *mut u8;
}

/// An `Allocator` implements a particular memory allocation strategy.
///
/// `Allocator`s are generally `struct`s that contain any additional
/// information necessary to enact that allocation strategy. Since
/// different `Allocator`s may use different methods of tracking frames,
/// each `Allocator` implementation can provide its own frame type, as long as
/// that frame type is `frameesque` (i.e., it provides some method to resolve
/// it into a pointer to its memory area).
pub trait Allocator {
    // type Frame: Framesque;

    unsafe fn allocate(&mut self, size: usize, align: usize)
                      -> Option<*mut u8>;

    unsafe fn deallocate(&mut self, frame: *mut u8, size: usize, align: usize);

    /// Reallocate the memory
    // TODO: Optimization: check if the reallocation request fits in
    // the old frame and return immediately if it does
    unsafe fn reallocate( &mut self, old_frame: *mut u8, old_size: usize
                        , new_size: usize, align: usize )
                        -> Option<*mut u8>
    {
        // First, attempt to allocate a new frame...
        self.allocate(new_size, align)
            .map(|new_frame| {
                // If a new frame was allocated, copy all the data from the
                // old frame into the new frame.
                ptr::copy(new_frame, old_frame, min(old_size, new_size));
                // Then we can deallocate the old frame
                self.deallocate(old_frame, old_size, align);
                new_frame
            })
    }

    unsafe fn zero_alloc(&mut self, size: usize, align: usize)
                        -> Option<*mut u8>
    {
        unimplemented!()
    }
}

mod rawlink;
pub use self::rawlink::RawLink;

#[cfg(feature = "buddy")]
pub mod buddy;

#[cfg(feature = "simple")]
pub mod simple;
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! SOS memory allocation library
//!
//! This is in its own crate so it can be used by kernel-space and user-space
//! OS components.

#![crate_name = "sos_alloc"]
#![crate_type = "lib"]

// The compiler needs to be instructed that this crate is an allocator in order
// to realize that when this is linked in another allocator like jemalloc
// should not be linked in
#![cfg_attr( feature = "buddy_as_system"
           , feature(allocator) )]
#![cfg_attr( feature = "buddy_as_system"
           , allocator )]

// Allocators are not allowed to depend on the standard library which in turn
// requires an allocator in order to avoid circular dependencies. This crate,
// however, can use all of libcore.
#![feature(no_std)]
#![no_std]

#![feature( ptr_as_ref
          , const_fn
          , core_slice_ext
          , iter_cmp )]

#[cfg(feature = "multiboot")] extern crate sos_multiboot2 as multiboot;
#[cfg(feature = "buddy_as_system")] extern crate spin;

use core::ptr;
use core::cmp::min;

pub const PAGE_SIZE: usize = 4096;

/// Trait for something that is like a frame.
///
/// Various allocation strategies use different data structures for
/// representing frames. For example, frames may be stored as frame numbers or
/// as nodes in a linked list. To be `Framesque`, an object need only provide
/// a function to convert the frame data to a pointer to the frame in memory.
pub trait Framesque {
    /// Return a pointer to the frame in memory.
    fn as_ptr(&self) -> *mut u8;
}

/// An `Allocator` implements a particular memory allocation strategy.

pub trait Allocator {
    // type Frame: Framesque;

    /// Allocate a new block of size `size` on alignment `align`.
    ///
    /// # Arguments:
    ///   - `size`: the amount of memory to allocate (in bytes)
    ///   - `align`: the alignment for the allocation request
    ///
    /// # Returns:
    ///   - `Some(*mut u8)` if the request was allocated successfully
    ///   - `None` if the allocator is out of memory or if the request was
    ///     invalid.
    unsafe fn allocate(&mut self, size: usize, align: usize)
                      -> Option<*mut u8>;

    /// Release an allocated block of memory.
    ///
    /// The `size` and `align` parameters _must_ be the same as the original
    /// size and alignment of the frame being deallocated, otherwise our
    /// heap will become corrupted.
    ///
    /// # Arguments:
    ///   - `frame`: a pointer to the block of memory to deallocate
    ///   - `size`: the size of the block being deallocated
    ///   - `align`: the alignment of the block being deallocated
    unsafe fn deallocate(&mut self, frame: *mut u8, size: usize, align: usize);

    /// Reallocate `old_frame` from `old_size` bytes to `new_size` bytes
    ///
    /// The `old_size` and `align` parameters _must_ be the same as the
    /// original size and alignment of the frame being reallocated, otherwise
    /// our heap will become corrupted.
    ///
    /// # Arguments:
    ///   - `old_frame`: a pointer to the frame to be reallocated
    ///   - `old_size`: the size (in bytes) of the frame being reallocated
    ///   - `new_size`: the size to reallocate the frame to.
    ///   - `align`: the alignment for the allocation request
    ///
    /// # Returns:
    ///   - `Some(*mut u8)` if the frame was reallocated successfully
    ///   - `None` if the allocator is out of memory or if the request was
    ///     invalid.
    // TODO: Optimization: check if the reallocation request fits in
    // the old frame and return immediately if it does
    unsafe fn reallocate( &mut self, old_frame: *mut u8, old_size: usize
                        , new_size: usize, align: usize )
                        -> Option<*mut u8>
    {
        // First, attempt to allocate a new frame...
        self.allocate(new_size, align)
            .map(|new_frame| {
                // If a new frame was allocated, copy all the data from the
                // old frame into the new frame.
                ptr::copy(new_frame, old_frame, min(old_size, new_size));
                // Then we can deallocate the old frame
                self.deallocate(old_frame, old_size, align);
                new_frame
            })
    }

    unsafe fn zero_alloc(&mut self, size: usize, align: usize)
                        -> Option<*mut u8>
    {
        unimplemented!()
    }
}

mod rawlink;
pub use self::rawlink::RawLink;

#[cfg(feature = "buddy")]
pub mod buddy;

#[cfg(feature = "simple")]
pub mod simple;
<commit_msg>Added additional features if there are other allocators<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! SOS memory allocation library
//!
//! This is in its own crate so it can be used by kernel-space and user-space
//! OS components.

#![crate_name = "sos_alloc"]
#![crate_type = "lib"]

// The compiler needs to be instructed that this crate is an allocator in order
// to realize that when this is linked in another allocator like jemalloc
// should not be linked in
#![cfg_attr( feature = "as_system"
           , feature(allocator) )]
#![cfg_attr( feature = "as_system"
           , allocator )]

// Allocators are not allowed to depend on the standard library which in turn
// requires an allocator in order to avoid circular dependencies. This crate,
// however, can use all of libcore.
#![feature(no_std)]
#![no_std]

#![feature( ptr_as_ref
          , const_fn
          , core_slice_ext
          , iter_cmp )]

#[cfg(feature = "multiboot")] extern crate sos_multiboot2 as multiboot;
#[cfg(feature = "buddy_as_system")] extern crate spin;

use core::ptr;
use core::cmp::min;

pub const PAGE_SIZE: usize = 4096;

/// Trait for something that is like a frame.
///
/// Various allocation strategies use different data structures for
/// representing frames. For example, frames may be stored as frame numbers or
/// as nodes in a linked list. To be `Framesque`, an object need only provide
/// a function to convert the frame data to a pointer to the frame in memory.
pub trait Framesque {
    /// Return a pointer to the frame in memory.
    fn as_ptr(&self) -> *mut u8;
}

/// An `Allocator` implements a particular memory allocation strategy.

pub trait Allocator {
    // type Frame: Framesque;

    /// Allocate a new block of size `size` on alignment `align`.
    ///
    /// # Arguments:
    ///   - `size`: the amount of memory to allocate (in bytes)
    ///   - `align`: the alignment for the allocation request
    ///
    /// # Returns:
    ///   - `Some(*mut u8)` if the request was allocated successfully
    ///   - `None` if the allocator is out of memory or if the request was
    ///     invalid.
    unsafe fn allocate(&mut self, size: usize, align: usize)
                      -> Option<*mut u8>;

    /// Release an allocated block of memory.
    ///
    /// The `size` and `align` parameters _must_ be the same as the original
    /// size and alignment of the frame being deallocated, otherwise our
    /// heap will become corrupted.
    ///
    /// # Arguments:
    ///   - `frame`: a pointer to the block of memory to deallocate
    ///   - `size`: the size of the block being deallocated
    ///   - `align`: the alignment of the block being deallocated
    unsafe fn deallocate(&mut self, frame: *mut u8, size: usize, align: usize);

    /// Reallocate `old_frame` from `old_size` bytes to `new_size` bytes
    ///
    /// The `old_size` and `align` parameters _must_ be the same as the
    /// original size and alignment of the frame being reallocated, otherwise
    /// our heap will become corrupted.
    ///
    /// # Arguments:
    ///   - `old_frame`: a pointer to the frame to be reallocated
    ///   - `old_size`: the size (in bytes) of the frame being reallocated
    ///   - `new_size`: the size to reallocate the frame to.
    ///   - `align`: the alignment for the allocation request
    ///
    /// # Returns:
    ///   - `Some(*mut u8)` if the frame was reallocated successfully
    ///   - `None` if the allocator is out of memory or if the request was
    ///     invalid.
    // TODO: Optimization: check if the reallocation request fits in
    // the old frame and return immediately if it does
    unsafe fn reallocate( &mut self, old_frame: *mut u8, old_size: usize
                        , new_size: usize, align: usize )
                        -> Option<*mut u8>
    {
        // First, attempt to allocate a new frame...
        self.allocate(new_size, align)
            .map(|new_frame| {
                // If a new frame was allocated, copy all the data from the
                // old frame into the new frame.
                ptr::copy(new_frame, old_frame, min(old_size, new_size));
                // Then we can deallocate the old frame
                self.deallocate(old_frame, old_size, align);
                new_frame
            })
    }

    unsafe fn zero_alloc(&mut self, size: usize, align: usize)
                        -> Option<*mut u8>
    {
        unimplemented!()
    }
}

mod rawlink;
pub use self::rawlink::RawLink;

#[cfg(feature = "buddy")]
pub mod buddy;

#[cfg(feature = "simple")]
pub mod simple;
<|endoftext|>


<commit_before>extern crate libloading as lib;
extern crate rand;
extern crate rouille;

#[macro_use]
mod macros;

use std::fs;
use std::path::Path;

#[cfg(target_os = "windows")]
const LOG_FILE_PATH: &str = "ctehxk2.log";
#[cfg(not(target_os = "windows"))]
const LOG_FILE_PATH: &str = "libctehxk2.log";

#[cfg(target_os = "windows")]
const LIB_PATH: &str = "../../target/debug/ctehxk2.dll";
#[cfg(target_os = "linux")]
const LIB_PATH: &str = "../../target/debug/ctehxk2.so";
#[cfg(target_os = "macos")]
const LIB_PATH: &str = "../../target/debug/libctehxk2.dylib";

#[test]
fn base_url_from_config_file() {
    let shutdown = test_server!(("127.0.0.1:65432", request: &Request) {
        if request.url() == "/yaml/ct_init/17/321" {
            ::rouille::Response::text("0")
        } else {
            ::rouille::Response::empty_404()
        }
    });

    match lib::Library::new(LIB_PATH) {
        Ok(lib) => unsafe {
            let init: lib::Symbol<unsafe extern "C" fn(u16, u16) -> i8> =
                lib.get(b"CT_init").unwrap();

            let ctn = rand::random::<u16>();
            let pn = rand::random::<u16>();

            assert_eq!(0, init(ctn, pn));
        },
        _ => assert!(false, format!("loading library from {}", LIB_PATH)),
    }

    // kill server thread
    let _ = shutdown.send(());

    assert!(Path::new(LOG_FILE_PATH).exists());

    let metadata = fs::metadata(LOG_FILE_PATH).unwrap();
    assert!(metadata.len() > 0);
}
<commit_msg>fix library name for linux<commit_after>extern crate libloading as lib;
extern crate rand;
extern crate rouille;

#[macro_use]
mod macros;

use std::fs;
use std::path::Path;

#[cfg(target_os = "windows")]
const LOG_FILE_PATH: &str = "ctehxk2.log";
#[cfg(not(target_os = "windows"))]
const LOG_FILE_PATH: &str = "libctehxk2.log";

#[cfg(target_os = "windows")]
const LIB_PATH: &str = "../../target/debug/ctehxk2.dll";
#[cfg(target_os = "linux")]
const LIB_PATH: &str = "../../target/debug/libctehxk2.so";
#[cfg(target_os = "macos")]
const LIB_PATH: &str = "../../target/debug/libctehxk2.dylib";

#[test]
fn base_url_from_config_file() {
    let shutdown = test_server!(("127.0.0.1:65432", request: &Request) {
        if request.url() == "/yaml/ct_init/17/321" {
            ::rouille::Response::text("0")
        } else {
            ::rouille::Response::empty_404()
        }
    });

    match lib::Library::new(LIB_PATH) {
        Ok(lib) => unsafe {
            let init: lib::Symbol<unsafe extern "C" fn(u16, u16) -> i8> =
                lib.get(b"CT_init").unwrap();

            let ctn = rand::random::<u16>();
            let pn = rand::random::<u16>();

            assert_eq!(0, init(ctn, pn));
        },
        _ => assert!(false, format!("loading library from {}", LIB_PATH)),
    }

    // kill server thread
    let _ = shutdown.send(());

    assert!(Path::new(LOG_FILE_PATH).exists());

    let metadata = fs::metadata(LOG_FILE_PATH).unwrap();
    assert!(metadata.len() > 0);
}
<|endoftext|>


<commit_before>// Kevin Cantu
// Boyer-Moore string searching

use std;

// Function: findn_bytes
//
// Boyer-Moore string search, which returns
// up to `nn` byte positions of matched substrings
fn findn_bytes (needle: str, haystack: str, nn: uint) -> [uint] {
   let results = [];
   let ct = char_table(needle);
   let pt = prefix_table(needle);

   log(error, ct);
   log(error, pt);

   let ii = 0u;
   let jj = 0u;

   while ii < str::len_bytes(haystack) {

      jj = str::len_bytes(needle) - 1u;

      // reverse through needle
      while 0u <= jj {

         // if still matching
         if needle[jj] == haystack[ii] {
            // if full match
            if jj == 0u {
               vec::push(results, jj);
               if vec::len(results) >= nn { ret results; }
            }

         // if partial match
         } else {
            let sufn = str::len_bytes(needle) - jj;

            let ctx;
            let ptx;

            alt ct.find(needle[sufn] as uint) {
               option::none { ctx = str::len_bytes(needle);}
               option::some(x) { ctx = x;}
            }

            alt pt.find(sufn) {
               option::none { fail "something is out of range" }
               option::some(x) { ptx = x;}
            }

            ii += greaterOf(ctx, ptx) - jj;
            jj = 0u;
         }

         jj -= 1u;
      }

      ii += 1u;
   }

   ret results;
}

fn char_table (needle: str) -> std::map::map<uint, uint> {
   let mm: std::map::map<uint, uint> = std::map::new_uint_hash();
   let len = str::len_bytes(needle);

   let jj = len - 1u; // drop the last byte

   // from last-1 to first
   while jj > 0u {
      jj -= 1u;
      if ! mm.contains_key(needle[jj] as uint) {
         // store reverse indexes
         mm.insert(needle[jj] as uint, len - 1u - jj);
      }
   }

   ret mm;
}

#[test]
fn test_char_table () {
   let ct = char_table("ANPANMAN");
   assert 1u == ct.get('A' as uint);
   assert 2u == ct.get('M' as uint);
   assert 3u == ct.get('N' as uint);
   assert 5u == ct.get('P' as uint);
   assert option::none == ct.find('z' as uint);
}

fn prefix_table (needle: str) -> std::map::map<uint, uint> {
   let mm: std::map::map<uint, uint> = std::map::new_uint_hash();

   let prefs = vec::reversed(prefixes(needle)); // largest first
   let sufs  = vec::reversed(suffixes(needle)); // smallest first
   let jj    = 0u;
   let kk    = 0u;
   let lim   = str::len(needle);

   while jj < lim {    // sufixes
      std::io::println("^");
      kk = 0u;

      while kk < lim { // prefixes
         let suf = sufs[jj];
         let pref = prefs[kk];

         std::io::println("[" + pref + ", " + suf + "]");

         if str::len_bytes(pref) > str::len_bytes(suf) &&
            str::ends_with(pref, suf) &&
           !str::ends_with(pref, sufs[jj+1u])
         {
            std::io::print("-");

            if ! mm.contains_key(jj)
            {
               std::io::print("*");
               mm.insert(jj, kk);
            }
         }

         kk += 1u;
      }
      jj += 1u;
   }

   ret mm
}

#[test]
fn test_prefix_table() {
   let pt = prefix_table("ANPANMAN");
   std::io::print("+");
   log(error, pt);
   assert 8u == pt.get(2u);
}

////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////

// prefixes, smallest first
fn prefixes(ss: str) -> [str] unsafe {
   let vv = [];
   let sz = 0u;
   str::bytes_iter(ss) {|_bb|
      sz += 1u;
      vec::push(vv, str::unsafe::slice_bytes(ss, 0u, sz));
   }
   ret vv;
}

#[test]
fn test_prefs() {
   assert ["a", "ab", "abc", "abcd"] == prefixes("abcd");
}

// suffixes, largest first
fn suffixes(ss: str) -> [str] unsafe {
   let vv = [];
   let sz = 0u;
   let lim = str::len_bytes(ss);
   str::bytes_iter(ss) {|_bb|
      vec::push(vv, str::unsafe::slice_bytes(ss, sz, lim));
      sz += 1u;
   }
   ret vv;
}

#[test]
fn test_sufs() {
   assert ["abcd", "bcd", "cd", "d"] == suffixes("abcd");
}

fn greaterOf(a: uint, b: uint) -> uint {
   if a > b { ret a; } else { ret b; }
}

#[test]
fn test_greaterOf() {
   assert greaterOf(15u, 17u) == 17u;
   assert greaterOf(17u, 15u) == 17u;
}

fn find_bytes_(needle: str, haystack: str) -> option<uint> {
   ret option::some(findn_bytes(needle, haystack, 1u)[0u]);
}

//#[test]
fn test_find_bytes() {
  // byte positions
  assert (find_bytes_("banana", "apple pie") == option::none);
  assert (find_bytes_("", "") == option::some(0u));

  let data = "ประเทศไทย中华Việt Nam";
  assert (find_bytes_(data, "")     == option::some(0u));
  assert (find_bytes_(data, "ประเ") == option::some( 0u));
  assert (find_bytes_(data, "ะเ")   == option::some( 6u));
  assert (find_bytes_(data, "中华") == option::some(27u));
  assert (find_bytes_(data, "ไท华") == option::none);
}

<commit_msg>(boyer-moore) prefixes broken for now...<commit_after>// Kevin Cantu
// Boyer-Moore string searching

use std;

// Function: findn_bytes
//
// Boyer-Moore string search, which returns
// up to `nn` byte positions of matched substrings
fn findn_bytes (needle: str, haystack: str, nn: uint) -> [uint] {
   let results = [];
   let ct = char_table(needle);
   let pt = prefix_table(needle);

   log(error, ct);
   log(error, pt);

   let ii = 0u;
   let jj = 0u;

   while ii < str::len_bytes(haystack) {

      jj = str::len_bytes(needle) - 1u;

      // reverse through needle
      while 0u <= jj {

         // if still matching
         if needle[jj] == haystack[ii] {
            // if full match
            if jj == 0u {
               vec::push(results, jj);
               if vec::len(results) >= nn { ret results; }
            }

         // if partial match
         } else {
            let sufn = str::len_bytes(needle) - jj;

            let ctx;
            let ptx;

            alt ct.find(needle[sufn] as uint) {
               option::none { ctx = str::len_bytes(needle);}
               option::some(x) { ctx = x;}
            }

            alt pt.find(sufn) {
               option::none { fail "something is out of range" }
               option::some(x) { ptx = x;}
            }

            ii += greaterOf(ctx, ptx) - jj;
            jj = 0u;
         }

         jj -= 1u;
      }

      ii += 1u;
   }

   ret results;
}

fn char_table (needle: str) -> std::map::map<uint, uint> {
   let mm: std::map::map<uint, uint> = std::map::new_uint_hash();
   let len = str::len_bytes(needle);

   let jj = len - 1u; // drop the last byte

   // from last-1 to first
   while jj > 0u {
      jj -= 1u;
      if ! mm.contains_key(needle[jj] as uint) {
         // store reverse indexes
         mm.insert(needle[jj] as uint, len - 1u - jj);
      }
   }

   ret mm;
}

#[test]
fn test_char_table () {
   let ct = char_table("ANPANMAN");
   assert 1u == ct.get('A' as uint);
   assert 2u == ct.get('M' as uint);
   assert 3u == ct.get('N' as uint);
   assert 5u == ct.get('P' as uint);
   assert option::none == ct.find('z' as uint);
}

fn prefix_table (needle: str) -> std::map::map<uint, uint> {
   let mm: std::map::map<uint, uint> = std::map::new_uint_hash();

   let prefs = vec::reversed(prefixes(needle)); // largest first
   let sufs  = vec::reversed(suffixes(needle)); // smallest first
   let jj    = 0u;
   let kk    = 0u;
   let lim   = str::len(needle);

   while jj < lim {    // sufixes
      kk = 0u;

      while kk < lim { // prefixes
         let suf = sufs[jj];
         let pref = prefs[kk];

         if str::len_bytes(pref) > str::len_bytes(suf) {
            std::io::println("[" + pref + ", " + suf + "]");
            std::io::println(">");
            if str::ends_with(pref, suf) {
               std::io::println("(suf)");
               if !str::ends_with(pref, sufs[jj+1u]) {
                  std::io::println("(suf+1)");
               }
            }
         }

         if str::len_bytes(pref) > str::len_bytes(suf) &&
            str::ends_with(pref, suf) &&
           !str::ends_with(pref, sufs[jj+1u])
         {
            std::io::print("-");

            if ! mm.contains_key(jj)
            {
               std::io::println("*");
               mm.insert(jj, kk);
            }
         }

         kk += 1u;
      }
      jj += 1u;
   }

   ret mm
}

#[test]
fn test_prefix_table() {
   let pt = prefix_table("ANPANMAN");
   std::io::print("+");
   log(error, pt);
   assert 8u == pt.get(2u);
}

////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////

// prefixes, smallest first
fn prefixes(ss: str) -> [str] unsafe {
   let vv = [];
   let sz = 0u;
   str::bytes_iter(ss) {|_bb|
      sz += 1u;
      vec::push(vv, str::unsafe::slice_bytes(ss, 0u, sz));
   }
   ret vv;
}

#[test]
fn test_prefs() {
   assert ["a", "ab", "abc", "abcd"] == prefixes("abcd");
}

// suffixes, largest first
fn suffixes(ss: str) -> [str] unsafe {
   let vv = [];
   let sz = 0u;
   let lim = str::len_bytes(ss);
   str::bytes_iter(ss) {|_bb|
      vec::push(vv, str::unsafe::slice_bytes(ss, sz, lim));
      sz += 1u;
   }
   ret vv;
}

#[test]
fn test_sufs() {
   assert ["abcd", "bcd", "cd", "d"] == suffixes("abcd");
}

fn greaterOf(a: uint, b: uint) -> uint {
   if a > b { ret a; } else { ret b; }
}

#[test]
fn test_greaterOf() {
   assert greaterOf(15u, 17u) == 17u;
   assert greaterOf(17u, 15u) == 17u;
}

fn find_bytes_(needle: str, haystack: str) -> option<uint> {
   ret option::some(findn_bytes(needle, haystack, 1u)[0u]);
}

//#[test]
fn test_find_bytes() {
  // byte positions
  assert (find_bytes_("banana", "apple pie") == option::none);
  assert (find_bytes_("", "") == option::some(0u));

  let data = "ประเทศไทย中华Việt Nam";
  assert (find_bytes_(data, "")     == option::some(0u));
  assert (find_bytes_(data, "ประเ") == option::some( 0u));
  assert (find_bytes_(data, "ะเ")   == option::some( 6u));
  assert (find_bytes_(data, "中华") == option::some(27u));
  assert (find_bytes_(data, "ไท华") == option::none);
}

<|endoftext|>


<commit_before>#![feature(plugin_registrar, rustc_private)]

extern crate rustc;
extern crate rustc_plugin;
extern crate syntax;
extern crate bifrost_hasher;

use syntax::tokenstream::TokenTree;
use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager};
use syntax::ext::build::AstBuilder;  // trait for expr_usize
use syntax::ext::quote::rt::Span;
use syntax::parse::token;
use rustc_plugin::Registry;
use bifrost_hasher::hash_str;

fn hash_ident (cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) -> Box<MacResult + 'static> {
    if args.len() != 1 {
        cx.span_err(
            sp,
            &format!("argument should be a single identifier, but got {} arguments", args.len()));
        return DummyResult::any(sp);
    }

    let text = match args[0] {
        TokenTree::Token(_, token::Ident(s)) => s.to_string(),
        _ => {
            cx.span_err(sp, "argument should be a single identifier");
            return DummyResult::any(sp);
        }
    };
    let text = &*text;
    let str = String::from(text);
    MacEager::expr(cx.expr_usize(sp, hash_str(&str) as usize))
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("hash_ident", hash_ident);
}<commit_msg>display args content for hash_ident plugin<commit_after>#![feature(plugin_registrar, rustc_private)]

extern crate rustc;
extern crate rustc_plugin;
extern crate syntax;
extern crate bifrost_hasher;

use syntax::tokenstream::TokenTree;
use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager};
use syntax::ext::build::AstBuilder;  // trait for expr_usize
use syntax::ext::quote::rt::Span;
use syntax::parse::token;
use rustc_plugin::Registry;
use bifrost_hasher::hash_str;

fn hash_ident (cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) -> Box<MacResult + 'static> {
    if args.len() != 1 {
        cx.span_err(
            sp,
            &format!("argument should be a single identifier, but got {} arguments {:?}",
                     args.len(), args));
        return DummyResult::any(sp);
    }

    let text = match args[0] {
        TokenTree::Token(_, token::Ident(s)) => s.to_string(),
        _ => {
            cx.span_err(sp, "argument should be a single identifier");
            return DummyResult::any(sp);
        }
    };
    let text = &*text;
    let str = String::from(text);
    MacEager::expr(cx.expr_usize(sp, hash_str(&str) as usize))
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("hash_ident", hash_ident);
}<|endoftext|>


<commit_before>//! lint when there are large variants on an enum

use rustc::lint::*;
use rustc::hir::*;
use utils::{span_lint_and_then, snippet_opt};
use rustc::ty::layout::TargetDataLayout;
use rustc::ty::TypeFoldable;
use rustc::traits::Reveal;

/// **What it does:** Checks for large variants on `enum`s.
///
/// **Why is this bad?** Enum size is bounded by the largest variant. Having a large variant
/// can penalize the memory layout of that enum.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// enum Test {
///    A(i32),
///    B([i32; 8000]),
/// }
/// ```
declare_lint! {
    pub LARGE_ENUM_VARIANT,
    Warn,
    "large variants on an enum"
}

#[derive(Copy,Clone)]
pub struct LargeEnumVariant {
    maximum_variant_size_allowed: u64,
}

impl LargeEnumVariant {
    pub fn new(maximum_variant_size_allowed: u64) -> Self {
        LargeEnumVariant { maximum_variant_size_allowed: maximum_variant_size_allowed }
    }
}

impl LintPass for LargeEnumVariant {
    fn get_lints(&self) -> LintArray {
        lint_array!(LARGE_ENUM_VARIANT)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant {
    fn check_item(&mut self, cx: &LateContext, item: &Item) {
        let did = cx.tcx.map.local_def_id(item.id);
        if let ItemEnum(ref def, _) = item.node {
            let ty = cx.tcx.item_type(did);
            let adt = ty.ty_adt_def().expect("already checked whether this is an enum");
            for (i, variant) in adt.variants.iter().enumerate() {
                let data_layout = TargetDataLayout::parse(cx.sess());
                cx.tcx.infer_ctxt((), Reveal::All).enter(|infcx| {
                    let size: u64 = variant.fields
                        .iter()
                        .map(|f| {
                            let ty = cx.tcx.item_type(f.did);
                            if ty.needs_subst() {
                                0 // we can't reason about generics, so we treat them as zero sized
                            } else {
                                ty.layout(&infcx)
                                    .expect("layout should be computable for concrete type")
                                    .size(&data_layout)
                                    .bytes()
                            }
                        })
                        .sum();
                    if size > self.maximum_variant_size_allowed {
                        span_lint_and_then(cx,
                                           LARGE_ENUM_VARIANT,
                                           def.variants[i].span,
                                           "large enum variant found",
                                           |db| {
                            if variant.fields.len() == 1 {
                                let span = match def.variants[i].node.data {
                                    VariantData::Struct(ref fields, _) |
                                    VariantData::Tuple(ref fields, _) => fields[0].ty.span,
                                    VariantData::Unit(_) => unreachable!(),
                                };
                                if let Some(snip) = snippet_opt(cx, span) {
                                    db.span_suggestion(
                                        span,
                                        "consider boxing the large fields to reduce the total size of the enum",
                                        format!("Box<{}>", snip),
                                    );
                                    return;
                                }
                            }
                            db.span_help(
                                def.variants[i].span,
                                "consider boxing the large fields to reduce the total size of the enum",
                            );
                        });
                    }
                });
            }
        }
    }
}
<commit_msg>rustfmt<commit_after>//! lint when there are large variants on an enum

use rustc::lint::*;
use rustc::hir::*;
use utils::{span_lint_and_then, snippet_opt};
use rustc::ty::layout::TargetDataLayout;
use rustc::ty::TypeFoldable;
use rustc::traits::Reveal;

/// **What it does:** Checks for large variants on `enum`s.
///
/// **Why is this bad?** Enum size is bounded by the largest variant. Having a large variant
/// can penalize the memory layout of that enum.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// enum Test {
///    A(i32),
///    B([i32; 8000]),
/// }
/// ```
declare_lint! {
    pub LARGE_ENUM_VARIANT,
    Warn,
    "large variants on an enum"
}

#[derive(Copy,Clone)]
pub struct LargeEnumVariant {
    maximum_variant_size_allowed: u64,
}

impl LargeEnumVariant {
    pub fn new(maximum_variant_size_allowed: u64) -> Self {
        LargeEnumVariant { maximum_variant_size_allowed: maximum_variant_size_allowed }
    }
}

impl LintPass for LargeEnumVariant {
    fn get_lints(&self) -> LintArray {
        lint_array!(LARGE_ENUM_VARIANT)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant {
    fn check_item(&mut self, cx: &LateContext, item: &Item) {
        let did = cx.tcx.map.local_def_id(item.id);
        if let ItemEnum(ref def, _) = item.node {
            let ty = cx.tcx.item_type(did);
            let adt = ty.ty_adt_def().expect("already checked whether this is an enum");
            for (i, variant) in adt.variants.iter().enumerate() {
                let data_layout = TargetDataLayout::parse(cx.sess());
                cx.tcx.infer_ctxt((), Reveal::All).enter(|infcx| {
                    let size: u64 = variant.fields
                        .iter()
                        .map(|f| {
                            let ty = cx.tcx.item_type(f.did);
                            if ty.needs_subst() {
                                0 // we can't reason about generics, so we treat them as zero sized
                            } else {
                                ty.layout(&infcx)
                                    .expect("layout should be computable for concrete type")
                                    .size(&data_layout)
                                    .bytes()
                            }
                        })
                        .sum();
                    if size > self.maximum_variant_size_allowed {
                        span_lint_and_then(cx,
                                           LARGE_ENUM_VARIANT,
                                           def.variants[i].span,
                                           "large enum variant found",
                                           |db| {
                            if variant.fields.len() == 1 {
                                let span = match def.variants[i].node.data {
                                    VariantData::Struct(ref fields, _) |
                                    VariantData::Tuple(ref fields, _) => fields[0].ty.span,
                                    VariantData::Unit(_) => unreachable!(),
                                };
                                if let Some(snip) = snippet_opt(cx, span) {
                                    db.span_suggestion(span,
                                                       "consider boxing the large fields to reduce the total size of \
                                                        the enum",
                                                       format!("Box<{}>", snip));
                                    return;
                                }
                            }
                            db.span_help(def.variants[i].span,
                                         "consider boxing the large fields to reduce the total size of the enum");
                        });
                    }
                });
            }
        }
    }
}
<|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/.

use svgdom::{
    Document,
    Node,
};

use svgdom::types::{
    FuzzyEq,
};

use short::{
    AId,
    EId,
};

use traits::{
    GetValue,
};

// TODO: images should not be grouped
pub fn regroup_elements(doc: &mut Document, parent: &Node) {
    let g_attrs = [AId::Mask, AId::ClipPath, AId::Filter, AId::Opacity];

    let mut ids = Vec::new();
    let mut curr_node = parent.first_child();
    while let Some(mut node) = curr_node {
        curr_node = node.next_sibling();
        ids.clear();

        if node.has_children() {
            regroup_elements(doc, &node);
        }

        if node.is_tag_name(EId::G) || node.is_tag_name(EId::Defs) {
            continue;
        }

        let opacity = node.attributes().get_number(AId::Opacity).unwrap_or(1.0);
        if opacity.fuzzy_eq(&1.0) && !node.has_attributes(&g_attrs) {
            continue;
        }

        // TODO: check only for defs after we implement ref elems groupping
        if node.parents_with_self().any(|n| n.is_tag_name(EId::ClipPath)) {
            continue;
        }

        let mut g_node = doc.create_element(EId::G);

        {
            let attrs = node.attributes();
            for aid in &g_attrs {
                if let Some(attr) = attrs.get(*aid) {
                    g_node.set_attribute(attr.clone());
                    ids.push(*aid);
                }
            }

            if let Some(ts) = attrs.get(AId::Transform) {
                g_node.set_attribute(ts.clone());
                ids.push(AId::Transform);
            }
        }
        node.remove_attributes(&ids);

        node.insert_before(&g_node);
        node.detach();
        g_node.append(&node);
    }
}
<commit_msg>Fixed element groupping in the preprocessor.<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/.

use svgdom::{
    Document,
    Node,
};

use svgdom::types::{
    FuzzyEq,
};

use short::{
    AId,
    EId,
};

use traits::{
    GetValue,
};

// TODO: images should not be grouped
pub fn regroup_elements(doc: &mut Document, parent: &Node) {
    let g_attrs = [AId::ClipPath, AId::Opacity];

    let mut ids = Vec::new();
    let mut curr_node = parent.first_child();
    while let Some(mut node) = curr_node {
        curr_node = node.next_sibling();
        ids.clear();

        if node.has_children() {
            regroup_elements(doc, &node);
        }

        if node.is_tag_name(EId::G) || node.is_tag_name(EId::Defs) {
            continue;
        }

        let opacity = node.attributes().get_number(AId::Opacity).unwrap_or(1.0);
        if opacity.fuzzy_eq(&1.0) && !node.has_attributes(&g_attrs) {
            continue;
        }

        // TODO: check only for defs after we implement ref elems groupping
        if node.parents_with_self().any(|n| n.is_tag_name(EId::ClipPath)) {
            continue;
        }

        let mut g_node = doc.create_element(EId::G);

        {
            let attrs = node.attributes();
            for aid in &g_attrs {
                if let Some(attr) = attrs.get(*aid) {
                    g_node.set_attribute(attr.clone());
                    ids.push(*aid);
                }
            }

            if let Some(ts) = attrs.get(AId::Transform) {
                g_node.set_attribute(ts.clone());
                ids.push(AId::Transform);
            }
        }
        node.remove_attributes(&ids);

        node.insert_before(&g_node);
        node.detach();
        g_node.append(&node);
    }
}
<|endoftext|>


<commit_before>macro_rules! skip_bytes (
  ($input: expr, $length: expr, $offset: expr) => (
    {
      match take!($input, $length) {
        $crate::nom::IResult::Done(i, bytes)   => {
          let head        = bytes[0] << $offset;
          let tail        = &bytes[1..];
          let is_all_zero = tail.iter().all(|byte| *byte == 0);

          if head == 0 && is_all_zero {
            $crate::nom::IResult::Done(i, bytes)
          } else {
            $crate::nom::IResult::Error($crate::nom::Err::Position(
              $crate::nom::ErrorCode::Digit as u32, $input))
          }
        }
        $crate::nom::IResult::Error(error)     =>
          $crate::nom::IResult::Error(error),
        $crate::nom::IResult::Incomplete(need) =>
          $crate::nom::IResult::Incomplete(need),
      }
    }
  );
);

macro_rules! count_bits (
  ($input: expr, $submac: ident!( $($args:tt)* ), $count: expr) => (
    {
      let mut input    = $input;
      let mut count    = 0;
      let mut is_error = false;
      let mut result   = Vec::with_capacity($count);

      loop {
        if count == $count {
          break;
        }

        match $submac!(input, $($args)*) {
          $crate::nom::IResult::Done(i, o)    => {
            result.push(o);

            input  = i;
            count += 1;
          }
          $crate::nom::IResult::Error(_)      => {
            is_error = true;
            break;
          }
          $crate::nom::IResult::Incomplete(_) => break,
        }
      }

      if is_error {
        $crate::nom::IResult::Error($crate::nom::Err::Position(
          $crate::nom::ErrorCode::Count as u32, $input.0))
      } else if count == $count {
        $crate::nom::IResult::Done(input, result)
      } else {
        $crate::nom::IResult::Incomplete($crate::nom::Needed::Unknown)
      }
    }
  );
  ($i: expr, $f: expr, $count: expr) => (
    count_bits!($i, call!($f), $count);
  );
);
<commit_msg>Add `count_slice!` macro<commit_after>macro_rules! skip_bytes (
  ($input: expr, $length: expr, $offset: expr) => (
    {
      match take!($input, $length) {
        $crate::nom::IResult::Done(i, bytes)   => {
          let head        = bytes[0] << $offset;
          let tail        = &bytes[1..];
          let is_all_zero = tail.iter().all(|byte| *byte == 0);

          if head == 0 && is_all_zero {
            $crate::nom::IResult::Done(i, bytes)
          } else {
            $crate::nom::IResult::Error($crate::nom::Err::Position(
              $crate::nom::ErrorCode::Digit as u32, $input))
          }
        }
        $crate::nom::IResult::Error(error)     =>
          $crate::nom::IResult::Error(error),
        $crate::nom::IResult::Incomplete(need) =>
          $crate::nom::IResult::Incomplete(need),
      }
    }
  );
);

macro_rules! count_slice (
  ($input: expr, $submac: ident!( $($args:tt)* ), $result: expr) => (
    {
      let mut input    = $input;
      let mut count    = 0;
      let mut is_error = false;

      for result in $result {
        match $submac!(input, $($args)*) {
          $crate::nom::IResult::Done(i, o)    => {
            *result = o;

            input   = i;
            count  += 1;
          }
          $crate::nom::IResult::Error(_)      => {
            is_error = true;
            break;
          }
          $crate::nom::IResult::Incomplete(_) => break,
        }
      }

      if is_error {
        $crate::nom::IResult::Error($crate::nom::Err::Position(
          $crate::nom::ErrorCode::Count as u32, $input.0))
      } else if count == $result.len() {
        $crate::nom::IResult::Done(input, ())
      } else {
        $crate::nom::IResult::Incomplete($crate::nom::Needed::Unknown)
      }
    }
  );
  ($i: expr, $f: expr, $count: expr) => (
    count_slice!($i, call!($f), $count);
  );
);

macro_rules! count_bits (
  ($input: expr, $submac: ident!( $($args:tt)* ), $count: expr) => (
    {
      let mut input    = $input;
      let mut count    = 0;
      let mut is_error = false;
      let mut result   = Vec::with_capacity($count);

      loop {
        if count == $count {
          break;
        }

        match $submac!(input, $($args)*) {
          $crate::nom::IResult::Done(i, o)    => {
            result.push(o);

            input  = i;
            count += 1;
          }
          $crate::nom::IResult::Error(_)      => {
            is_error = true;
            break;
          }
          $crate::nom::IResult::Incomplete(_) => break,
        }
      }

      if is_error {
        $crate::nom::IResult::Error($crate::nom::Err::Position(
          $crate::nom::ErrorCode::Count as u32, $input.0))
      } else if count == $count {
        $crate::nom::IResult::Done(input, result)
      } else {
        $crate::nom::IResult::Incomplete($crate::nom::Needed::Unknown)
      }
    }
  );
  ($i: expr, $f: expr, $count: expr) => (
    count_bits!($i, call!($f), $count);
  );
);
<|endoftext|>