<commit_before>use crate::{LateContext, LateLintPass, LintContext};
use rustc_ast as ast;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_middle::ty;
use rustc_parse_format::{ParseMode, Parser, Piece};
use rustc_span::{sym, InnerSpan};

declare_lint! {
    /// The `panic_fmt` lint detects `panic!("..")` with `{` or `}` in the string literal.
    ///
    /// ### Example
    ///
    /// ```rust,no_run
    /// panic!("{}");
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// `panic!("{}")` panics with the message `"{}"`, as a `panic!()` invocation
    /// with a single argument does not use `format_args!()`.
    /// A future version of Rust will interpret this string as format string,
    /// which would break this.
    PANIC_FMT,
    Warn,
    "detect braces in single-argument panic!() invocations",
    report_in_external_macro
}

declare_lint_pass!(PanicFmt => [PANIC_FMT]);

impl<'tcx> LateLintPass<'tcx> for PanicFmt {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
        if let hir::ExprKind::Call(f, [arg]) = &expr.kind {
            if let &ty::FnDef(def_id, _) = cx.typeck_results().expr_ty(f).kind() {
                if Some(def_id) == cx.tcx.lang_items().begin_panic_fn()
                    || Some(def_id) == cx.tcx.lang_items().panic_fn()
                {
                    check_panic(cx, f, arg);
                }
            }
        }
    }
}

fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tcx hir::Expr<'tcx>) {
    if let hir::ExprKind::Lit(lit) = &arg.kind {
        if let ast::LitKind::Str(sym, _) = lit.node {
            let mut expn = f.span.ctxt().outer_expn_data();
            if let Some(id) = expn.macro_def_id {
                if cx.tcx.is_diagnostic_item(sym::std_panic_macro, id)
                    || cx.tcx.is_diagnostic_item(sym::core_panic_macro, id)
                {
                    let fmt = sym.as_str();
                    if !fmt.contains(&['{', '}'][..]) {
                        return;
                    }

                    let fmt_span = arg.span.source_callsite();

                    let (snippet, style) =
                        match cx.sess().parse_sess.source_map().span_to_snippet(fmt_span) {
                            Ok(snippet) => {
                                // Count the number of `#`s between the `r` and `"`.
                                let style = snippet.strip_prefix('r').and_then(|s| s.find('"'));
                                (Some(snippet), style)
                            }
                            Err(_) => (None, None),
                        };

                    let mut fmt_parser =
                        Parser::new(fmt.as_ref(), style, snippet.clone(), false, ParseMode::Format);
                    let n_arguments =
                        (&mut fmt_parser).filter(|a| matches!(a, Piece::NextArgument(_))).count();

                    // Unwrap another level of macro expansion if this panic!()
                    // was expanded from assert!() or debug_assert!().
                    for &assert in &[sym::assert_macro, sym::debug_assert_macro] {
                        let parent = expn.call_site.ctxt().outer_expn_data();
                        if parent
                            .macro_def_id
                            .map_or(false, |id| cx.tcx.is_diagnostic_item(assert, id))
                        {
                            expn = parent;
                        }
                    }

                    if n_arguments > 0 && fmt_parser.errors.is_empty() {
                        let arg_spans: Vec<_> = match &fmt_parser.arg_places[..] {
                            [] => vec![fmt_span],
                            v => v.iter().map(|span| fmt_span.from_inner(*span)).collect(),
                        };
                        cx.struct_span_lint(PANIC_FMT, arg_spans, |lint| {
                            let mut l = lint.build(match n_arguments {
                                1 => "panic message contains an unused formatting placeholder",
                                _ => "panic message contains unused formatting placeholders",
                            });
                            l.note("this message is not used as a format string when given without arguments, but will be in a future Rust version");
                            if expn.call_site.contains(arg.span) {
                                l.span_suggestion(
                                    arg.span.shrink_to_hi(),
                                    "add the missing argument(s)",
                                    ", ...".into(),
                                    Applicability::HasPlaceholders,
                                );
                                l.span_suggestion(
                                    arg.span.shrink_to_lo(),
                                    "or add a \"{}\" format string to use the message literally",
                                    "\"{}\", ".into(),
                                    Applicability::MaybeIncorrect,
                                );
                            }
                            l.emit();
                        });
                    } else {
                        let brace_spans: Option<Vec<_>> = snippet
                            .filter(|s| s.starts_with('"') || s.starts_with("r#"))
                            .map(|s| {
                                s.char_indices()
                                    .filter(|&(_, c)| c == '{' || c == '}')
                                    .map(|(i, _)| {
                                        fmt_span.from_inner(InnerSpan { start: i, end: i + 1 })
                                    })
                                    .collect()
                            });
                        let msg = match &brace_spans {
                            Some(v) if v.len() == 1 => "panic message contains a brace",
                            _ => "panic message contains braces",
                        };
                        cx.struct_span_lint(PANIC_FMT, brace_spans.unwrap_or(vec![expn.call_site]), |lint| {
                            let mut l = lint.build(msg);
                            l.note("this message is not used as a format string, but will be in a future Rust version");
                            if expn.call_site.contains(arg.span) {
                                l.span_suggestion(
                                    arg.span.shrink_to_lo(),
                                    "add a \"{}\" format string to use the message literally",
                                    "\"{}\", ".into(),
                                    Applicability::MachineApplicable,
                                );
                            }
                            l.emit();
                        });
                    }
                }
            }
        }
    }
}
<commit_msg>Mark panic_fmt suggestion as machine applicable.<commit_after>use crate::{LateContext, LateLintPass, LintContext};
use rustc_ast as ast;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_middle::ty;
use rustc_parse_format::{ParseMode, Parser, Piece};
use rustc_span::{sym, InnerSpan};

declare_lint! {
    /// The `panic_fmt` lint detects `panic!("..")` with `{` or `}` in the string literal.
    ///
    /// ### Example
    ///
    /// ```rust,no_run
    /// panic!("{}");
    /// ```
    ///
    /// {{produces}}
    ///
    /// ### Explanation
    ///
    /// `panic!("{}")` panics with the message `"{}"`, as a `panic!()` invocation
    /// with a single argument does not use `format_args!()`.
    /// A future version of Rust will interpret this string as format string,
    /// which would break this.
    PANIC_FMT,
    Warn,
    "detect braces in single-argument panic!() invocations",
    report_in_external_macro
}

declare_lint_pass!(PanicFmt => [PANIC_FMT]);

impl<'tcx> LateLintPass<'tcx> for PanicFmt {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
        if let hir::ExprKind::Call(f, [arg]) = &expr.kind {
            if let &ty::FnDef(def_id, _) = cx.typeck_results().expr_ty(f).kind() {
                if Some(def_id) == cx.tcx.lang_items().begin_panic_fn()
                    || Some(def_id) == cx.tcx.lang_items().panic_fn()
                {
                    check_panic(cx, f, arg);
                }
            }
        }
    }
}

fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tcx hir::Expr<'tcx>) {
    if let hir::ExprKind::Lit(lit) = &arg.kind {
        if let ast::LitKind::Str(sym, _) = lit.node {
            let mut expn = f.span.ctxt().outer_expn_data();
            if let Some(id) = expn.macro_def_id {
                if cx.tcx.is_diagnostic_item(sym::std_panic_macro, id)
                    || cx.tcx.is_diagnostic_item(sym::core_panic_macro, id)
                {
                    let fmt = sym.as_str();
                    if !fmt.contains(&['{', '}'][..]) {
                        return;
                    }

                    let fmt_span = arg.span.source_callsite();

                    let (snippet, style) =
                        match cx.sess().parse_sess.source_map().span_to_snippet(fmt_span) {
                            Ok(snippet) => {
                                // Count the number of `#`s between the `r` and `"`.
                                let style = snippet.strip_prefix('r').and_then(|s| s.find('"'));
                                (Some(snippet), style)
                            }
                            Err(_) => (None, None),
                        };

                    let mut fmt_parser =
                        Parser::new(fmt.as_ref(), style, snippet.clone(), false, ParseMode::Format);
                    let n_arguments =
                        (&mut fmt_parser).filter(|a| matches!(a, Piece::NextArgument(_))).count();

                    // Unwrap another level of macro expansion if this panic!()
                    // was expanded from assert!() or debug_assert!().
                    for &assert in &[sym::assert_macro, sym::debug_assert_macro] {
                        let parent = expn.call_site.ctxt().outer_expn_data();
                        if parent
                            .macro_def_id
                            .map_or(false, |id| cx.tcx.is_diagnostic_item(assert, id))
                        {
                            expn = parent;
                        }
                    }

                    if n_arguments > 0 && fmt_parser.errors.is_empty() {
                        let arg_spans: Vec<_> = match &fmt_parser.arg_places[..] {
                            [] => vec![fmt_span],
                            v => v.iter().map(|span| fmt_span.from_inner(*span)).collect(),
                        };
                        cx.struct_span_lint(PANIC_FMT, arg_spans, |lint| {
                            let mut l = lint.build(match n_arguments {
                                1 => "panic message contains an unused formatting placeholder",
                                _ => "panic message contains unused formatting placeholders",
                            });
                            l.note("this message is not used as a format string when given without arguments, but will be in a future Rust version");
                            if expn.call_site.contains(arg.span) {
                                l.span_suggestion(
                                    arg.span.shrink_to_hi(),
                                    "add the missing argument(s)",
                                    ", ...".into(),
                                    Applicability::HasPlaceholders,
                                );
                                l.span_suggestion(
                                    arg.span.shrink_to_lo(),
                                    "or add a \"{}\" format string to use the message literally",
                                    "\"{}\", ".into(),
                                    Applicability::MachineApplicable,
                                );
                            }
                            l.emit();
                        });
                    } else {
                        let brace_spans: Option<Vec<_>> = snippet
                            .filter(|s| s.starts_with('"') || s.starts_with("r#"))
                            .map(|s| {
                                s.char_indices()
                                    .filter(|&(_, c)| c == '{' || c == '}')
                                    .map(|(i, _)| {
                                        fmt_span.from_inner(InnerSpan { start: i, end: i + 1 })
                                    })
                                    .collect()
                            });
                        let msg = match &brace_spans {
                            Some(v) if v.len() == 1 => "panic message contains a brace",
                            _ => "panic message contains braces",
                        };
                        cx.struct_span_lint(PANIC_FMT, brace_spans.unwrap_or(vec![expn.call_site]), |lint| {
                            let mut l = lint.build(msg);
                            l.note("this message is not used as a format string, but will be in a future Rust version");
                            if expn.call_site.contains(arg.span) {
                                l.span_suggestion(
                                    arg.span.shrink_to_lo(),
                                    "add a \"{}\" format string to use the message literally",
                                    "\"{}\", ".into(),
                                    Applicability::MachineApplicable,
                                );
                            }
                            l.emit();
                        });
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>// Claxon -- A FLAC decoding library in Rust
// Copyright 2017 Ruud van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

// This file contains a minimal example of using Claxon and Hound to decode a
// flac file. This can be done more efficiently, but it is also more verbose.
// See the `decode` example for that.

extern crate claxon;
extern crate walkdir;
extern crate time;

use time::PreciseTime;
use std::io::{Seek, SeekFrom};

fn main() {
    use std::ffi::OsStr;
    let mut file_times_us = Vec::new();
    let mut bytes_per_sec = Vec::new();

    let wd = walkdir::WalkDir::new("testsamples/extra")
        .follow_links(true)
        .into_iter()
        .filter_map(|e| e.ok())
        .take(1024);

    for entry in wd {
        let path = entry.path();
        if path.is_file() && path.extension() == Some(OsStr::new("flac")) {
            let epoch = PreciseTime::now();
            let mut bytes = 0;

            // Read the file multiple times to amortize the walkdir cost.
            for _ in 0..10 {
                let reader = claxon::FlacReader::open(path).unwrap();

                // Note that these are not optimized away even though the results
                // are not used, because the expectation may fail.
                reader.get_tag("DATE").next().expect("DATE");
                reader.get_tag("ORIGINALDATE").next().expect("ORIGINALDATE");
                reader.get_tag("TITLE").next().expect("TITLE");
                reader.get_tag("ALBUM").next().expect("ALBUM");
                reader.get_tag("ALBUMARTIST").next().expect("ALBUMARTIST");
                reader.get_tag("MUSICBRAINZ_TRACKID").next().expect("MUSICBRAINZ_TRACKID");
                reader.get_tag("MUSICBRAINZ_ALBUMID").next().expect("MUSICBRAINZ_ALBUMID");
                reader.get_tag("MUSICBRAINZ_ARTISTID").next().expect("MUSICBRAINZ_ARTISTID");
                bytes += reader.into_inner().seek(SeekFrom::Current(0)).unwrap();
            }

            let duration_ns = epoch.to(PreciseTime::now()).num_nanoseconds().unwrap();
            file_times_us.push(duration_ns as f64 / 1000.0 / 10.0);
            bytes_per_sec.push(bytes as f64 / (duration_ns as f64 / 1.0e9) / 10.0);
        }
    }

    file_times_us.sort_by(|x, y| x.partial_cmp(y).unwrap());
    bytes_per_sec.sort_by(|x, y| x.partial_cmp(y).unwrap());

    let p10 = file_times_us[10 * file_times_us.len() / 100];
    let p50 = file_times_us[50 * file_times_us.len() / 100];
    let p90 = file_times_us[90 * file_times_us.len() / 100];
    let mean = file_times_us.iter().sum::<f64>() / (file_times_us.len() as f64);
    let p10_mibs = bytes_per_sec[10 * bytes_per_sec.len() / 100] / (1024.0 * 1024.0);

    // Output numbers compatible with tools/compare_benches.r.
    println!("{:>6.2} {:>6.2} {:>6.2} {:>6.2} {:>6.2}", p10, p50, p90, mean, p10_mibs);
}
<commit_msg>Read a few more tags in metadata benchmark<commit_after>// Claxon -- A FLAC decoding library in Rust
// Copyright 2017 Ruud van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

// This file contains a minimal example of using Claxon and Hound to decode a
// flac file. This can be done more efficiently, but it is also more verbose.
// See the `decode` example for that.

extern crate claxon;
extern crate walkdir;
extern crate time;

use time::PreciseTime;
use std::io::{Seek, SeekFrom};

fn main() {
    use std::ffi::OsStr;
    let mut file_times_us = Vec::new();
    let mut bytes_per_sec = Vec::new();

    let wd = walkdir::WalkDir::new("testsamples/extra")
        .follow_links(true)
        .into_iter()
        .filter_map(|e| e.ok())
        .take(1024);

    for entry in wd {
        let path = entry.path();
        if path.is_file() && path.extension() == Some(OsStr::new("flac")) {
            let epoch = PreciseTime::now();
            let mut bytes = 0;

            // Read the file multiple times to amortize the walkdir cost.
            for _ in 0..10 {
                let reader = claxon::FlacReader::open(path).unwrap();

                // Note that these are not optimized away even though the results
                // are not used, because the expectation may fail.
                reader.get_tag("date").next().expect("date");
                reader.get_tag("originaldate").next().expect("originaldate");
                reader.get_tag("tracknumber").next().expect("tracknumber");
                reader.get_tag("tracktotal").next().expect("tracktotal");
                reader.get_tag("discnumber").next().expect("discnumber");
                reader.get_tag("disctotal").next().expect("disctotal");

                reader.get_tag("title").next().expect("title");
                reader.get_tag("album").next().expect("album");
                reader.get_tag("artist").next().expect("artist");
                reader.get_tag("albumartist").next().expect("albumartist");
                reader.get_tag("artistsort").next().expect("artistsort");
                reader.get_tag("albumartistsort").next().expect("albumartistsort");

                reader.get_tag("musicbrainz_trackid").next().expect("musicbrainz_trackid");
                reader.get_tag("musicbrainz_albumid").next().expect("musicbrainz_albumid");
                reader.get_tag("musicbrainz_artistid").next().expect("musicbrainz_artistid");
                reader.get_tag("musicbrainz_albumartistid").next().expect("musicbrainz_albumartistid");

                bytes += reader.into_inner().seek(SeekFrom::Current(0)).unwrap();
            }

            let duration_ns = epoch.to(PreciseTime::now()).num_nanoseconds().unwrap();
            file_times_us.push(duration_ns as f64 / 1000.0 / 10.0);
            bytes_per_sec.push(bytes as f64 / (duration_ns as f64 / 1.0e9) / 10.0);
        }
    }

    file_times_us.sort_by(|x, y| x.partial_cmp(y).unwrap());
    bytes_per_sec.sort_by(|x, y| x.partial_cmp(y).unwrap());

    let p10 = file_times_us[10 * file_times_us.len() / 100];
    let p50 = file_times_us[50 * file_times_us.len() / 100];
    let p90 = file_times_us[90 * file_times_us.len() / 100];
    let mean = file_times_us.iter().sum::<f64>() / (file_times_us.len() as f64);
    let p10_mibs = bytes_per_sec[10 * bytes_per_sec.len() / 100] / (1024.0 * 1024.0);

    // Output numbers compatible with tools/compare_benches.r.
    println!("{:>6.2} {:>6.2} {:>6.2} {:>6.2} {:>6.2}", p10, p50, p90, mean, p10_mibs);
}
<|endoftext|>


<commit_before>//! It's a tree!

use std::ptr;
use std::ops::DerefMut;

#[derive(Debug, PartialEq, Eq)]
struct Node<T> {
    // We need a mut pointer so we can modify the parent
    parent: *mut Node<T>,
    val: T,
    children: Vec<Node<T>>
}

impl<T> Node<T> {
    pub fn new(val: T) -> Node<T> {
        Node {
            parent: ptr::null_mut(),
            val: val,
            children: Vec::new()
        }
    }

    pub fn new_child(&mut self, val: T) {
        let self_mut = self as *mut Node<T>;
        self.children.push(Node {
            parent: self_mut,
            val: val,
            children: Vec::new()
        })
    }

    pub fn adopt(&mut self, mut other: Node<T>) {
        let self_ptr = self as *mut Node<T>;
        other.parent = self_ptr;
        self.children.push(other);
    }

    pub fn has_parent(&self) -> bool {
        self.parent.is_null()
    }

    pub fn get_parent<'a>(&'a self) -> Option<&'a mut Node<T>> {
        if self.parent.is_null() {
            return None;
        }
        unsafe {
            return Some(&mut *self.parent);
        }
    }

    /// Sets the parent of the node.
    /// Does not update the parent of the old node
    pub fn set_parent(&mut self, new: &mut Node<T>) {
        unsafe { self.parent = new as *mut Node<T>; }
    }

    pub fn get_children<'a>(&'a self) -> &Vec<Node<T>> {
        &self.children
    }

    pub fn get_mut_children(&mut self) -> &mut Vec<Node<T>> {
        &mut self.children
    }

    pub fn remove_child_at(&mut self, index: usize) -> Node<T> {
        self.children.remove(index)
    }

    pub fn is_parent_of(&self, other: Node<T>) -> bool {
        true
    }
}

impl <T: PartialEq> Node<T> {
    pub fn remove_from_parent(&self) {
        if let Some(ref mut parent) = self.get_parent() {
            let children = parent.get_mut_children();
            if let Some(index) = children.iter().position(|c| c == self) {
                children.remove(index);
            }
        }
    }

    pub fn remove_child(&mut self, other: &Node<T>) -> Option<Node<T>> {
        if let Some(index) = self.children.iter().position(|c| c == other) {
            Some(self.children.remove(index))
        }
        else {
            None
        }
    }

    pub fn move_to(mut self, new_parent: &mut Node<T>) {
        self.remove_from_parent();
        self.parent = new_parent as *mut Node<T>;
        new_parent.children.push(self);
    }
}

impl<T> Drop for Node<T> {
    fn drop(&mut self) {
        trace!("Dropping a node!!!!");
    }
}

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

    fn test_add_child() {

    }
}
<commit_msg>Remove adopt+set_parent in favor of move_to<commit_after>//! It's a tree!

use std::ptr;
use std::ops::{Deref, DerefMut};
use std::fmt::Debug;

#[derive(Debug, PartialEq, Eq)]
struct Node<T> {
    // We need a mut pointer so we can modify the parent
    parent: *mut Node<T>,
    val: T,
    children: Vec<Node<T>>
}

impl<T> Node<T> {
    /// Create a new node with the existing value.
    /// For root-style constructors.
    pub fn new(val: T) -> Node<T> {
        Node {
            parent: ptr::null_mut(),
            val: val,
            children: Vec::new()
        }
    }

    /// Add a new child node to this node, using a value
    pub fn new_child(&mut self, val: T) {
        let self_mut = self as *mut Node<T>;
        self.children.push(Node {
            parent: self_mut,
            val: val,
            children: Vec::new()
        })
    }

    /// Whether this node has a (currently-reachable) parent
    pub fn has_parent(&self) -> bool {
        self.parent.is_null()
    }

    /// Gets the parent of this node (if it exists)
    pub fn get_parent<'a>(&'a self) -> Option<&'a mut Node<T>> {
        if self.parent.is_null() {
            return None;
        }
        unsafe {
            return Some(&mut *self.parent);
        }
    }

    /// Borrow the children of this node.
    pub fn get_children<'a>(&'a self) -> &Vec<Node<T>> {
        &self.children
    }

    /// Mutably borrow the children of this mutable node
    pub fn get_mut_children(&mut self) -> &mut Vec<Node<T>> {
        &mut self.children
    }

    /// Remove a child at the given index
    pub fn remove_child_at(&mut self, index: usize) -> Node<T> {
        self.children.remove(index)
    }

    /// Whether this node is a parent of another node
    pub fn is_parent_of(&self, other: Node<T>) -> bool {
        self.parent == other.parent
    }
}

impl <T: PartialEq> Node<T> {
    pub fn remove_from_parent(&self) {
        if let Some(ref mut parent) = self.get_parent() {
            let children = parent.get_mut_children();
            if let Some(index) = children.iter().position(|c| c == self) {
                children.remove(index);
            }
        }
    }

    pub fn remove_child(&mut self, other: &Node<T>) -> Option<Node<T>> {
        if let Some(index) = self.children.iter().position(|c| c == other) {
            Some(self.children.remove(index))
        }
        else {
            None
        }
    }

    pub fn move_to(mut self, new_parent: &mut Node<T>) {
        self.remove_from_parent();
        self.parent = new_parent as *mut Node<T>;
        new_parent.children.push(self);
    }
}

impl<T> Drop for Node<T> {
    fn drop(&mut self) {
        trace!("Dropping a node!!!!");
        self.parent = ptr::null_mut();
    }
}

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

    fn test_add_child() {

    }
}
<|endoftext|>


<commit_before>use rustc_serialize::json;
use hyper;
use hyper::{Client};
use url::form_urlencoded;

use std::io::Read;
use std::borrow::Cow;

use text_view::view_as_text;
use text_view::insert_annotation;
use token::Token;
use token::Data;
use error::{Error, Result, Source};

/// Represents a grammar error from language tool
///
/// Note: lots of fields are missing
#[derive(RustcDecodable, RustcEncodable, Debug)]
pub struct GrammarError {
    pub message: String,
    pub offset: usize,
    pub length: usize,
    pub short_message: Option<String>,
    pub issue_type: Option<String>,
}

/// Contains a list of matches to errors
///
/// Corresponds to the JSON that LanguageTool-server sends back
///
/// Note: lots of fields are missing
#[derive(RustcDecodable, RustcEncodable, Debug)]
pub struct GrammarCheck {
    pub matches: Vec<GrammarError>,
}

impl GrammarCheck {
    /// Send a query to LanguageTools server and get back a list of errors
    pub fn new(text: &str, port: usize, lang: &str) -> Result<GrammarCheck> {
        let query: String = form_urlencoded::Serializer::new(String::new())
            .append_pair("language", lang)
            .append_pair("text", text)
            .finish();

        let client = Client::new();

        let mut res = try!(client.post(&format!("http://localhost:{}/v2/check", port))
                           .body(&query)
                           .send()
                           .map_err(|e| Error::default(Source::empty(),
                                                       format!("could not send request to server: {}", e))));

        if res.status != hyper::Ok {
            return Err(Error::default(Source::empty(),
                                      format!("server didn't respond with a OK status code")));
        }

        let mut s = String::new();
        try!(res.read_to_string(&mut s)
             .map_err(|e| Error::default(Source::empty(),
                                         format!("could not read response: {}", e))));
        let reponse: GrammarCheck = try!(json::decode(&s).map_err(|e| Error::default(Source::empty(),
                                                                                format!("could not decode JSON: {}", e))));
        Ok(reponse)
    }
}

fn escape_query<'a>(s: &str) -> Cow<'a, str> {
    let mut res = String::with_capacity(s.len());
    for c in s.chars() {
        match c {
            '&' => res.push_str("%26"),
            _ => res.push(c),
        }
    }
    Cow::Owned(res)
}

/// Check the grammar in a chapter
///
/// This modifies the AST
pub fn check_grammar(tokens: &mut Vec<Token>, lang: &str) -> Result<()> {
    let input = view_as_text(tokens);
    let check = try!(GrammarCheck::new(&input, 8081, lang));

    for error in check.matches {
        insert_annotation(tokens, &Data::GrammarError(error.message.clone()), error.offset, error.length);
    }
    Ok(())
}

<commit_msg>Remove now useless escape_query function<commit_after>use rustc_serialize::json;
use hyper;
use hyper::{Client};
use url::form_urlencoded;

use std::io::Read;
use std::borrow::Cow;

use text_view::view_as_text;
use text_view::insert_annotation;
use token::Token;
use token::Data;
use error::{Error, Result, Source};

/// Represents a grammar error from language tool
///
/// Note: lots of fields are missing
#[derive(RustcDecodable, RustcEncodable, Debug)]
pub struct GrammarError {
    pub message: String,
    pub offset: usize,
    pub length: usize,
    pub short_message: Option<String>,
    pub issue_type: Option<String>,
}

/// Contains a list of matches to errors
///
/// Corresponds to the JSON that LanguageTool-server sends back
///
/// Note: lots of fields are missing
#[derive(RustcDecodable, RustcEncodable, Debug)]
pub struct GrammarCheck {
    pub matches: Vec<GrammarError>,
}

impl GrammarCheck {
    /// Send a query to LanguageTools server and get back a list of errors
    pub fn new(text: &str, port: usize, lang: &str) -> Result<GrammarCheck> {
        let query: String = form_urlencoded::Serializer::new(String::new())
            .append_pair("language", lang)
            .append_pair("text", text)
            .finish();

        let client = Client::new();

        let mut res = try!(client.post(&format!("http://localhost:{}/v2/check", port))
                           .body(&query)
                           .send()
                           .map_err(|e| Error::default(Source::empty(),
                                                       format!("could not send request to server: {}", e))));

        if res.status != hyper::Ok {
            return Err(Error::default(Source::empty(),
                                      format!("server didn't respond with a OK status code")));
        }

        let mut s = String::new();
        try!(res.read_to_string(&mut s)
             .map_err(|e| Error::default(Source::empty(),
                                         format!("could not read response: {}", e))));
        let reponse: GrammarCheck = try!(json::decode(&s).map_err(|e| Error::default(Source::empty(),
                                                                                format!("could not decode JSON: {}", e))));
        Ok(reponse)
    }
}

/// Check the grammar in a chapter
///
/// This modifies the AST
pub fn check_grammar(tokens: &mut Vec<Token>, lang: &str) -> Result<()> {
    let input = view_as_text(tokens);
    let check = try!(GrammarCheck::new(&input, 8081, lang));

    for error in check.matches {
        insert_annotation(tokens, &Data::GrammarError(error.message.clone()), error.offset, error.length);
    }
    Ok(())
}

<|endoftext|>


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

use hir::def_id::DefId;
use util::nodemap::{NodeMap, DefIdMap};
use syntax::ast;
use syntax::ext::base::MacroKind;
use syntax_pos::Span;
use hir;
use ty;

#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum CtorKind {
    /// Constructor function automatically created by a tuple struct/variant.
    Fn,
    /// Constructor constant automatically created by a unit struct/variant.
    Const,
    /// Unusable name in value namespace created by a struct variant.
    Fictive,
}

#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum Def {
    // Type namespace
    Mod(DefId),
    Struct(DefId), // DefId refers to NodeId of the struct itself
    Union(DefId),
    Enum(DefId),
    Variant(DefId),
    Trait(DefId),
    TyAlias(DefId),
    TyForeign(DefId),
    TraitAlias(DefId),
    AssociatedTy(DefId),
    PrimTy(hir::PrimTy),
    TyParam(DefId),
    SelfTy(Option<DefId> /* trait */, Option<DefId> /* impl */),

    // Value namespace
    Fn(DefId),
    Const(DefId),
    Static(DefId, bool /* is_mutbl */),
    StructCtor(DefId, CtorKind), // DefId refers to NodeId of the struct's constructor
    VariantCtor(DefId, CtorKind),
    Method(DefId),
    AssociatedConst(DefId),

    Local(ast::NodeId),
    Upvar(ast::NodeId,  // node id of closed over local
          usize,        // index in the freevars list of the closure
          ast::NodeId), // expr node that creates the closure
    Label(ast::NodeId),

    // Macro namespace
    Macro(DefId, MacroKind),

    GlobalAsm(DefId),

    // Both namespaces
    Err,
}

/// The result of resolving a path before lowering to HIR.
/// `base_def` is definition of resolved part of the
/// path, `unresolved_segments` is the number of unresolved
/// segments.
///     module::Type::AssocX::AssocY::MethodOrAssocType
///     ^~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
///     base_def      unresolved_segments = 3
///
///     <T as Trait>::AssocX::AssocY::MethodOrAssocType
///           ^~~~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~
///           base_def        unresolved_segments = 2
#[derive(Copy, Clone, Debug)]
pub struct PathResolution {
    base_def: Def,
    unresolved_segments: usize,
}

impl PathResolution {
    pub fn new(def: Def) -> Self {
        PathResolution { base_def: def, unresolved_segments: 0 }
    }

    pub fn with_unresolved_segments(def: Def, mut unresolved_segments: usize) -> Self {
        if def == Def::Err { unresolved_segments = 0 }
        PathResolution { base_def: def, unresolved_segments: unresolved_segments }
    }

    #[inline]
    pub fn base_def(&self) -> Def {
        self.base_def
    }

    #[inline]
    pub fn unresolved_segments(&self) -> usize {
        self.unresolved_segments
    }

    pub fn kind_name(&self) -> &'static str {
        if self.unresolved_segments != 0 {
            "associated item"
        } else {
            self.base_def.kind_name()
        }
    }
}

/// Definition mapping
pub type DefMap = NodeMap<PathResolution>;

/// This is the replacement export map. It maps a module to all of the exports
/// within.
pub type ExportMap = DefIdMap<Vec<Export>>;

#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct Export {
    /// The name of the target.
    pub ident: ast::Ident,
    /// The definition of the target.
    pub def: Def,
    /// The span of the target definition.
    pub span: Span,
    /// The visibility of the export.
    /// We include non-`pub` exports for hygienic macros that get used from extern crates.
    pub vis: ty::Visibility,
    /// True if from a `use` or and `extern crate`.
    pub is_import: bool,
}

impl CtorKind {
    pub fn from_ast(vdata: &ast::VariantData) -> CtorKind {
        match *vdata {
            ast::VariantData::Tuple(..) => CtorKind::Fn,
            ast::VariantData::Unit(..) => CtorKind::Const,
            ast::VariantData::Struct(..) => CtorKind::Fictive,
        }
    }
    pub fn from_hir(vdata: &hir::VariantData) -> CtorKind {
        match *vdata {
            hir::VariantData::Tuple(..) => CtorKind::Fn,
            hir::VariantData::Unit(..) => CtorKind::Const,
            hir::VariantData::Struct(..) => CtorKind::Fictive,
        }
    }
}

impl Def {
    pub fn def_id(&self) -> DefId {
        match *self {
            Def::Fn(id) | Def::Mod(id) | Def::Static(id, _) |
            Def::Variant(id) | Def::VariantCtor(id, ..) | Def::Enum(id) |
            Def::TyAlias(id) | Def::TraitAlias(id) |
            Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) |
            Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
            Def::AssociatedConst(id) | Def::Macro(id, ..) |
            Def::GlobalAsm(id) | Def::TyForeign(id) => {
                id
            }

            Def::Local(..) |
            Def::Upvar(..) |
            Def::Label(..)  |
            Def::PrimTy(..) |
            Def::SelfTy(..) |
            Def::Err => {
                bug!("attempted .def_id() on invalid def: {:?}", self)
            }
        }
    }

    /// A human readable kind name
    pub fn kind_name(&self) -> &'static str {
        match *self {
            Def::Fn(..) => "function",
            Def::Mod(..) => "module",
            Def::Static(..) => "static",
            Def::Variant(..) => "variant",
            Def::VariantCtor(.., CtorKind::Fn) => "tuple variant",
            Def::VariantCtor(.., CtorKind::Const) => "unit variant",
            Def::VariantCtor(.., CtorKind::Fictive) => "struct variant",
            Def::Enum(..) => "enum",
            Def::TyAlias(..) => "type alias",
            Def::TraitAlias(..) => "trait alias",
            Def::AssociatedTy(..) => "associated type",
            Def::Struct(..) => "struct",
            Def::StructCtor(.., CtorKind::Fn) => "tuple struct",
            Def::StructCtor(.., CtorKind::Const) => "unit struct",
            Def::StructCtor(.., CtorKind::Fictive) => bug!("impossible struct constructor"),
            Def::Union(..) => "union",
            Def::Trait(..) => "trait",
            Def::TyForeign(..) => "foreign type",
            Def::Method(..) => "method",
            Def::Const(..) => "constant",
            Def::AssociatedConst(..) => "associated constant",
            Def::TyParam(..) => "type parameter",
            Def::PrimTy(..) => "builtin type",
            Def::Local(..) => "local variable",
            Def::Upvar(..) => "closure capture",
            Def::Label(..) => "label",
            Def::SelfTy(..) => "self type",
            Def::Macro(..) => "macro",
            Def::GlobalAsm(..) => "global asm",
            Def::Err => "unresolved item",
        }
    }
}
<commit_msg>Auto merge of #47095 - leodasvacas:clarify-is-import, r=jseyfried<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use hir::def_id::DefId;
use util::nodemap::{NodeMap, DefIdMap};
use syntax::ast;
use syntax::ext::base::MacroKind;
use syntax_pos::Span;
use hir;
use ty;

#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum CtorKind {
    /// Constructor function automatically created by a tuple struct/variant.
    Fn,
    /// Constructor constant automatically created by a unit struct/variant.
    Const,
    /// Unusable name in value namespace created by a struct variant.
    Fictive,
}

#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum Def {
    // Type namespace
    Mod(DefId),
    Struct(DefId), // DefId refers to NodeId of the struct itself
    Union(DefId),
    Enum(DefId),
    Variant(DefId),
    Trait(DefId),
    TyAlias(DefId),
    TyForeign(DefId),
    TraitAlias(DefId),
    AssociatedTy(DefId),
    PrimTy(hir::PrimTy),
    TyParam(DefId),
    SelfTy(Option<DefId> /* trait */, Option<DefId> /* impl */),

    // Value namespace
    Fn(DefId),
    Const(DefId),
    Static(DefId, bool /* is_mutbl */),
    StructCtor(DefId, CtorKind), // DefId refers to NodeId of the struct's constructor
    VariantCtor(DefId, CtorKind),
    Method(DefId),
    AssociatedConst(DefId),

    Local(ast::NodeId),
    Upvar(ast::NodeId,  // node id of closed over local
          usize,        // index in the freevars list of the closure
          ast::NodeId), // expr node that creates the closure
    Label(ast::NodeId),

    // Macro namespace
    Macro(DefId, MacroKind),

    GlobalAsm(DefId),

    // Both namespaces
    Err,
}

/// The result of resolving a path before lowering to HIR.
/// `base_def` is definition of resolved part of the
/// path, `unresolved_segments` is the number of unresolved
/// segments.
///     module::Type::AssocX::AssocY::MethodOrAssocType
///     ^~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
///     base_def      unresolved_segments = 3
///
///     <T as Trait>::AssocX::AssocY::MethodOrAssocType
///           ^~~~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~
///           base_def        unresolved_segments = 2
#[derive(Copy, Clone, Debug)]
pub struct PathResolution {
    base_def: Def,
    unresolved_segments: usize,
}

impl PathResolution {
    pub fn new(def: Def) -> Self {
        PathResolution { base_def: def, unresolved_segments: 0 }
    }

    pub fn with_unresolved_segments(def: Def, mut unresolved_segments: usize) -> Self {
        if def == Def::Err { unresolved_segments = 0 }
        PathResolution { base_def: def, unresolved_segments: unresolved_segments }
    }

    #[inline]
    pub fn base_def(&self) -> Def {
        self.base_def
    }

    #[inline]
    pub fn unresolved_segments(&self) -> usize {
        self.unresolved_segments
    }

    pub fn kind_name(&self) -> &'static str {
        if self.unresolved_segments != 0 {
            "associated item"
        } else {
            self.base_def.kind_name()
        }
    }
}

/// Definition mapping
pub type DefMap = NodeMap<PathResolution>;

/// This is the replacement export map. It maps a module to all of the exports
/// within.
pub type ExportMap = DefIdMap<Vec<Export>>;

#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct Export {
    /// The name of the target.
    pub ident: ast::Ident,
    /// The definition of the target.
    pub def: Def,
    /// The span of the target definition.
    pub span: Span,
    /// The visibility of the export.
    /// We include non-`pub` exports for hygienic macros that get used from extern crates.
    pub vis: ty::Visibility,
    /// True if from a `use` or and `extern crate`.
    /// Used in rustdoc.
    pub is_import: bool,
}

impl CtorKind {
    pub fn from_ast(vdata: &ast::VariantData) -> CtorKind {
        match *vdata {
            ast::VariantData::Tuple(..) => CtorKind::Fn,
            ast::VariantData::Unit(..) => CtorKind::Const,
            ast::VariantData::Struct(..) => CtorKind::Fictive,
        }
    }
    pub fn from_hir(vdata: &hir::VariantData) -> CtorKind {
        match *vdata {
            hir::VariantData::Tuple(..) => CtorKind::Fn,
            hir::VariantData::Unit(..) => CtorKind::Const,
            hir::VariantData::Struct(..) => CtorKind::Fictive,
        }
    }
}

impl Def {
    pub fn def_id(&self) -> DefId {
        match *self {
            Def::Fn(id) | Def::Mod(id) | Def::Static(id, _) |
            Def::Variant(id) | Def::VariantCtor(id, ..) | Def::Enum(id) |
            Def::TyAlias(id) | Def::TraitAlias(id) |
            Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) |
            Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
            Def::AssociatedConst(id) | Def::Macro(id, ..) |
            Def::GlobalAsm(id) | Def::TyForeign(id) => {
                id
            }

            Def::Local(..) |
            Def::Upvar(..) |
            Def::Label(..)  |
            Def::PrimTy(..) |
            Def::SelfTy(..) |
            Def::Err => {
                bug!("attempted .def_id() on invalid def: {:?}", self)
            }
        }
    }

    /// A human readable kind name
    pub fn kind_name(&self) -> &'static str {
        match *self {
            Def::Fn(..) => "function",
            Def::Mod(..) => "module",
            Def::Static(..) => "static",
            Def::Variant(..) => "variant",
            Def::VariantCtor(.., CtorKind::Fn) => "tuple variant",
            Def::VariantCtor(.., CtorKind::Const) => "unit variant",
            Def::VariantCtor(.., CtorKind::Fictive) => "struct variant",
            Def::Enum(..) => "enum",
            Def::TyAlias(..) => "type alias",
            Def::TraitAlias(..) => "trait alias",
            Def::AssociatedTy(..) => "associated type",
            Def::Struct(..) => "struct",
            Def::StructCtor(.., CtorKind::Fn) => "tuple struct",
            Def::StructCtor(.., CtorKind::Const) => "unit struct",
            Def::StructCtor(.., CtorKind::Fictive) => bug!("impossible struct constructor"),
            Def::Union(..) => "union",
            Def::Trait(..) => "trait",
            Def::TyForeign(..) => "foreign type",
            Def::Method(..) => "method",
            Def::Const(..) => "constant",
            Def::AssociatedConst(..) => "associated constant",
            Def::TyParam(..) => "type parameter",
            Def::PrimTy(..) => "builtin type",
            Def::Local(..) => "local variable",
            Def::Upvar(..) => "closure capture",
            Def::Label(..) => "label",
            Def::SelfTy(..) => "self type",
            Def::Macro(..) => "macro",
            Def::GlobalAsm(..) => "global asm",
            Def::Err => "unresolved item",
        }
    }
}
<|endoftext|>


<commit_before>use log::{LogLevel, LogLevelFilter};

#[derive(Debug, Clone, Copy)]
pub enum Level {
    Emergency = 0,
    Alert = 1,
    Critical = 2,
    Error = 3,
    Warning = 4,
    Notice = 5,
    Informational = 6,
    Debug = 7,
}

impl Level {
    pub fn from_rust(level: &LogLevel) -> Level {
        match *level {
            LogLevel::Error => Level::Error,
            LogLevel::Warn => Level::Warning,
            LogLevel::Info => Level::Informational,
            LogLevel::Debug | LogLevel::Trace => Level::Debug,
        }
    }

    pub fn to_rust(&self) -> LogLevel {
        match *self {
            Level::Emergency | Level::Alert | Level::Critical | Level::Error => LogLevel::Error,
            Level::Warning => LogLevel::Warn,
            Level::Notice | Level::Informational => LogLevel::Info,
            Level::Debug => LogLevel::Debug,
        }
    }
}

impl Into<LogLevel> for Level {
    fn into(self) -> LogLevel {
        self.to_rust()
    }
}

impl From<LogLevel> for Level {
    fn from(level: LogLevel) -> Level {
        Level::from_rust(&level)
    }
}

impl Into<LogLevelFilter> for Level {
    fn into(self) -> LogLevelFilter {
        self.to_rust().to_log_level_filter()
    }
}<commit_msg>Add documentation for gelf::Level<commit_after>use log::{LogLevel, LogLevelFilter};

/// GELF's representation of an error level
///
/// GELF's error levels are equivalent to syslog's severity
/// information (specified in [RFC 5424](https://tools.ietf.org/html/rfc5424))
///
/// The levels dont match `log`s levels, but (lossy) conversion methods
/// are provided. These methods follow this conversion table:
///
/// | GELF / Syslog     | Rust      |
/// |-------------------|-----------|
/// | Emergency (0)     | Error (1) |
/// | Alert (1)         | Error (1) |
/// | Critical (2)      | Error (1) |
/// | Error (3)         | Error (1) |
/// | Warning (4)       | Warn (2)  |
/// | Notice (5)        | Info (3)  |
/// | Informational (6) | Info (3)  |
/// | Debug (7)         | Debug (4) |
/// | Debug (7)         | Trace (5) |
#[derive(Debug, Clone, Copy)]
pub enum Level {
    Emergency = 0,
    Alert = 1,
    Critical = 2,
    Error = 3,
    Warning = 4,
    Notice = 5,
    Informational = 6,
    Debug = 7,
}

impl Level {
    /// Get the GELF error level from given Rust error level
    pub fn from_rust(level: &LogLevel) -> Level {
        match *level {
            LogLevel::Error => Level::Error,
            LogLevel::Warn => Level::Warning,
            LogLevel::Info => Level::Informational,
            LogLevel::Debug | LogLevel::Trace => Level::Debug,
        }
    }

    /// Get the Rust error level from this GELF error level
    pub fn to_rust(&self) -> LogLevel {
        match *self {
            Level::Emergency | Level::Alert | Level::Critical | Level::Error => LogLevel::Error,
            Level::Warning => LogLevel::Warn,
            Level::Notice | Level::Informational => LogLevel::Info,
            Level::Debug => LogLevel::Debug,
        }
    }
}

impl Into<LogLevel> for Level {
    /// Allow for Into conversion to Rust's LogLevel
    fn into(self) -> LogLevel {
        self.to_rust()
    }
}

impl From<LogLevel> for Level {
    /// Allow for Into conversion from Rust's LogLevel
    fn from(level: LogLevel) -> Level {
        Level::from_rust(&level)
    }
}

impl Into<LogLevelFilter> for Level {
    /// Allow for Into conversion from Rust's LogLevelFilter
    fn into(self) -> LogLevelFilter {
        self.to_rust().to_log_level_filter()
    }
}<|endoftext|>


<commit_before>extern crate cc;

use std::env;
use std::path::Path;

fn main() {
    let root_path = Path::new("vendor/tree-sitter");

    let mut config = cc::Build::new();
    config.flag_if_supported("-std=c99");
    config.flag_if_supported("-Wno-unused-parameter");
    config.include(root_path.join(Path::new("src")));
    config.include(root_path.join(Path::new("include")));
    config.include(root_path.join(Path::new("externals/utf8proc")));

    let source_filenames = [
      "get_changed_ranges.c",
      "language.c",
      "lexer.c",
      "node.c",
      "parser.c",
      "stack.c",
      "subtree.c",
      "tree_cursor.c",
      "tree.c",
      "utf16.c",
    ];

    config.files(source_filenames.iter().map(|source_filename| {
        root_path
            .join(Path::new(&"src/runtime"))
            .join(Path::new(&source_filename))
    }));

    config.file(root_path.join(Path::new("externals/utf8proc/utf8proc.c")));

    if env::var("RUST_TREE_SITTER_TEST").is_ok() {
        let parser_dir = Path::new("fixtures/tree-sitter-rust/src");
        config.file(parser_dir.join("parser.c"));
        config.file(parser_dir.join("scanner.c"));
    }

    config.compile("libruntime.a")
}
<commit_msg>Use a more unique library name when building C sources<commit_after>extern crate cc;

use std::env;
use std::path::Path;

fn main() {
    let root_path = Path::new("vendor/tree-sitter");

    let mut config = cc::Build::new();
    config.flag_if_supported("-std=c99");
    config.flag_if_supported("-Wno-unused-parameter");
    config.include(root_path.join(Path::new("src")));
    config.include(root_path.join(Path::new("include")));
    config.include(root_path.join(Path::new("externals/utf8proc")));

    let source_filenames = [
      "get_changed_ranges.c",
      "language.c",
      "lexer.c",
      "node.c",
      "parser.c",
      "stack.c",
      "subtree.c",
      "tree_cursor.c",
      "tree.c",
      "utf16.c",
    ];

    config.files(source_filenames.iter().map(|source_filename| {
        root_path
            .join(Path::new(&"src/runtime"))
            .join(Path::new(&source_filename))
    }));

    config.file(root_path.join(Path::new("externals/utf8proc/utf8proc.c")));

    if env::var("RUST_TREE_SITTER_TEST").is_ok() {
        let parser_dir = Path::new("fixtures/tree-sitter-rust/src");
        config.file(parser_dir.join("parser.c"));
        config.file(parser_dir.join("scanner.c"));
    }

    config.compile("treesitter")
}
<|endoftext|>


<commit_before>#![feature(path, env)]
extern crate gcc;

use std::path::PathBuf;
use std::env;

const LIB_NAME: &'static str = "libctxswtch.a";

fn main() {
    let arch =
        if cfg!(target_arch = "x86_64") {
            "x86_64"
        } else if cfg!(target_arch = "i686") {
            "i686"
        } else if cfg!(target_arch = "arm") {
            "arm"
        } else if cfg!(target_arch = "mips") {
            "mips"
        } else if cfg!(target_arch = "mipsel") {
            "mipsel"
        } else {
            panic!("Unsupported architecture: {}", env::var("TARGET").unwrap());
        };
    let src_path = &["src", "asm", arch, "_context.S"].iter().collect::<PathBuf>();
    gcc::compile_library(LIB_NAME, &[src_path.to_str().unwrap()]);

// seems like this line is no need actually
//    println!("cargo:rustc-flags=-l ctxswtch:static");
}
<commit_msg>remove env feature in build.rs<commit_after>#![feature(path)]
extern crate gcc;

use std::path::PathBuf;
use std::env;

const LIB_NAME: &'static str = "libctxswtch.a";

fn main() {
    let arch =
        if cfg!(target_arch = "x86_64") {
            "x86_64"
        } else if cfg!(target_arch = "i686") {
            "i686"
        } else if cfg!(target_arch = "arm") {
            "arm"
        } else if cfg!(target_arch = "mips") {
            "mips"
        } else if cfg!(target_arch = "mipsel") {
            "mipsel"
        } else {
            panic!("Unsupported architecture: {}", env::var("TARGET").unwrap());
        };
    let src_path = &["src", "asm", arch, "_context.S"].iter().collect::<PathBuf>();
    gcc::compile_library(LIB_NAME, &[src_path.to_str().unwrap()]);

// seems like this line is no need actually
//    println!("cargo:rustc-flags=-l ctxswtch:static");
}
<|endoftext|>


<commit_before>//! Memory allocation APIs

#![stable(feature = "alloc_module", since = "1.28.0")]

mod global;
mod layout;

#[stable(feature = "global_alloc", since = "1.28.0")]
pub use self::global::GlobalAlloc;
#[stable(feature = "alloc_layout", since = "1.28.0")]
pub use self::layout::{Layout, LayoutErr};

use crate::fmt;
use crate::ptr::{self, NonNull};

/// The `AllocErr` error indicates an allocation failure
/// that may be due to resource exhaustion or to
/// something wrong when combining the given input arguments with this
/// allocator.
#[unstable(feature = "allocator_api", issue = "32838")]
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct AllocErr;

// (we need this for downstream impl of trait Error)
#[unstable(feature = "allocator_api", issue = "32838")]
impl fmt::Display for AllocErr {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str("memory allocation failed")
    }
}

/// A desired initial state for allocated memory.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[unstable(feature = "allocator_api", issue = "32838")]
pub enum AllocInit {
    /// The contents of the new memory are undefined.
    ///
    /// Reading uninitialized memory is Undefined Behavior; it must be initialized before use.
    Uninitialized,
    /// The new memory is guaranteed to be zeroed.
    Zeroed,
}

impl AllocInit {
    /// Initialize the specified memory block.
    ///
    /// This behaves like calling [`AllocInit::init_offset(memory, 0)`][off].
    ///
    /// [off]: AllocInit::init_offset
    ///
    /// # Safety
    ///
    /// * `memory.ptr` must be [valid] for writes of `memory.size` bytes.
    ///
    /// [valid]: ../ptr/index.html#safety
    #[inline]
    #[unstable(feature = "allocator_api", issue = "32838")]
    pub unsafe fn init(self, memory: MemoryBlock) {
        self.init_offset(memory, 0)
    }

    /// Initialize the memory block like specified by `init` at the specified `offset`.
    ///
    /// This is a no-op for [`AllocInit::Uninitialized`][] and writes zeroes for
    /// [`AllocInit::Zeroed`][] at `ptr + offset` until `ptr + layout.size()`.
    ///
    /// # Safety
    ///
    /// * `memory.ptr` must be [valid] for writes of `memory.size` bytes.
    /// * `offset` must be smaller than or equal to `memory.size`
    ///
    /// [valid]: ../ptr/index.html#safety
    #[inline]
    #[unstable(feature = "allocator_api", issue = "32838")]
    pub unsafe fn init_offset(self, memory: MemoryBlock, offset: usize) {
        debug_assert!(
            offset <= memory.size,
            "`offset` must be smaller than or equal to `memory.size`"
        );
        match self {
            AllocInit::Uninitialized => (),
            AllocInit::Zeroed => {
                memory.ptr.as_ptr().add(offset).write_bytes(0, memory.size - offset)
            }
        }
    }
}

/// Represents a block of allocated memory returned by an allocator.
#[derive(Debug, Copy, Clone)]
#[unstable(feature = "allocator_api", issue = "32838")]
pub struct MemoryBlock {
    pub ptr: NonNull<u8>,
    pub size: usize,
}

/// A placement constraint when growing or shrinking an existing allocation.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[unstable(feature = "allocator_api", issue = "32838")]
pub enum ReallocPlacement {
    /// The allocator is allowed to move the allocation to a different memory address.
    // FIXME(wg-allocators#46): Add a section to the module documentation "What is a legal
    //                          allocator" and link it at "valid location".
    ///
    /// If the allocation _does_ move, it's the responsibility of the allocator
    /// to also move the data from the previous location to the new location.
    MayMove,
    /// The address of the new memory must not change.
    ///
    /// If the allocation would have to be moved to a new location to fit, the
    /// reallocation request will fail.
    InPlace,
}

/// An implementation of `AllocRef` can allocate, grow, shrink, and deallocate arbitrary blocks of
/// data described via [`Layout`][].
///
/// `AllocRef` is designed to be implemented on ZSTs, references, or smart pointers because having
/// an allocator like `MyAlloc([u8; N])` cannot be moved, without updating the pointers to the
/// allocated memory.
///
/// Unlike [`GlobalAlloc`][], zero-sized allocations are allowed in `AllocRef`. If an underlying
/// allocator does not support this (like jemalloc) or return a null pointer (such as
/// `libc::malloc`), this case must be caught.
///
/// ### Currently allocated memory
///
/// Some of the methods require that a memory block be *currently allocated* via an allocator. This
/// means that:
///
/// * the starting address for that memory block was previously returned by [`alloc`], [`grow`], or
///   [`shrink`], and
///
/// * the memory block has not been subsequently deallocated, where blocks are either deallocated
///   directly by being passed to [`dealloc`] or were changed by being passed to [`grow`] or
///   [`shrink`] that returns `Ok`. If `grow` or `shrink` have returned `Err`, the passed pointer
///   remains valid.
///
/// [`alloc`]: AllocRef::alloc
/// [`grow`]: AllocRef::grow
/// [`shrink`]: AllocRef::shrink
/// [`dealloc`]: AllocRef::dealloc
///
/// ### Memory fitting
///
/// Some of the methods require that a layout *fit* a memory block. What it means for a layout to
/// "fit" a memory block means (or equivalently, for a memory block to "fit" a layout) is that the
/// following conditions must hold:
///
/// * The block must be allocated with the same alignment as [`layout.align()`], and
///
/// * The provided [`layout.size()`] must fall in the range `min ..= max`, where:
///   - `min` is the size of the layout most recently used to allocate the block, and
///   - `max` is the latest actual size returned from [`alloc`], [`grow`], or [`shrink`].
///
/// [`layout.align()`]: Layout::align
/// [`layout.size()`]: Layout::size
///
/// # Safety
///
/// * Memory blocks returned from an allocator must point to valid memory and retain their validity
///   until the instance and all of its clones are dropped, and
///
/// * cloning or moving the allocator must not invalidate memory blocks returned from this
///   allocator. A cloned allocator must behave like the same allocator.
///
/// * any pointer to a memory block which is [*currently allocated*] may be passed to any other
///   method of the allocator.
///
/// [*currently allocated*]: #currently-allocated-memory
#[unstable(feature = "allocator_api", issue = "32838")]
pub unsafe trait AllocRef {
    /// On success, returns a memory block meeting the size and alignment guarantees of `layout`.
    ///
    /// The returned block may have a larger size than specified by `layout.size()` and is
    /// initialized as specified by [`init`], all the way up to the returned size of the block.
    ///
    /// [`init`]: AllocInit
    ///
    /// # Errors
    ///
    /// Returning `Err` indicates that either memory is exhausted or `layout` does not meet
    /// allocator's size or alignment constraints.
    ///
    /// Implementations are encouraged to return `Err` on memory exhaustion rather than panicking or
    /// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement
    /// this trait atop an underlying native allocation library that aborts on memory exhaustion.)
    ///
    /// Clients wishing to abort computation in response to an allocation error are encouraged to
    /// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar.
    ///
    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
    fn alloc(&mut self, layout: Layout, init: AllocInit) -> Result<MemoryBlock, AllocErr>;

    /// Deallocates the memory denoted by `memory`.
    ///
    /// # Safety
    ///
    /// `memory` must be a memory block returned by this allocator.
    unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout);

    /// Attempts to extend the memory block.
    ///
    /// Returns a new memory block containing a pointer and the actual size of the allocated
    /// block. The pointer is suitable for holding data described by a new layout with `layout`’s
    /// alignment and a size given by `new_size`. To accomplish this, the allocator may extend the
    /// allocation referenced by `ptr` to fit the new layout. If the [`placement`] is
    /// [`InPlace`], the returned pointer is guaranteed to be the same as the passed `ptr`.
    ///
    /// If `ReallocPlacement::MayMove` is used then ownership of the memory block referenced by `ptr`
    /// is transferred to this allocator. The memory may or may not be freed, and should be
    /// considered unusable (unless of course it is transferred back to the caller again via the
    /// return value of this method).
    ///
    /// If this method returns `Err`, then ownership of the memory block has not been transferred to
    /// this allocator, and the contents of the memory block are unaltered.
    ///
    /// The memory block will contain the following contents after a successful call to `grow`:
    ///   * Bytes `0..layout.size()` are preserved from the original allocation.
    ///   * Bytes `layout.size()..old_size` will either be preserved or initialized according to
    ///     [`init`], depending on the allocator implementation. `old_size` refers to the size of
    ///     the `MemoryBlock` prior to the `grow` call, which may be larger than the size
    ///     that was originally requested when it was allocated.
    ///   * Bytes `old_size..new_size` are initialized according to [`init`]. `new_size` refers to
    ///     the size of the `MemoryBlock` returned by the `grow` call.
    ///
    /// [`InPlace`]: ReallocPlacement::InPlace
    /// [`placement`]: ReallocPlacement
    /// [`init`]: AllocInit
    ///
    /// # Safety
    ///
    /// * `ptr` must be [*currently allocated*] via this allocator,
    /// * `layout` must [*fit*] the `ptr`. (The `new_size` argument need not fit it.)
    // We can't require that `new_size` is strictly greater than `memory.size` because of ZSTs.
    // An alternative would be
    // * `new_size must be strictly greater than `memory.size` or both are zero
    /// * `new_size` must be greater than or equal to `layout.size()`
    /// * `new_size`, when rounded up to the nearest multiple of `layout.align()`, must not overflow
    ///   (i.e., the rounded value must be less than `usize::MAX`).
    ///
    /// [*currently allocated*]: #currently-allocated-memory
    /// [*fit*]: #memory-fitting
    ///
    /// # Errors
    ///
    /// Returns `Err` if the new layout does not meet the allocator's size and alignment
    /// constraints of the allocator, or if growing otherwise fails.
    ///
    /// Implementations are encouraged to return `Err` on memory exhaustion rather than panicking or
    /// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement
    /// this trait atop an underlying native allocation library that aborts on memory exhaustion.)
    ///
    /// Clients wishing to abort computation in response to an allocation error are encouraged to
    /// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar.
    ///
    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
    unsafe fn grow(
        &mut self,
        ptr: NonNull<u8>,
        layout: Layout,
        new_size: usize,
        placement: ReallocPlacement,
        init: AllocInit,
    ) -> Result<MemoryBlock, AllocErr> {
        match placement {
            ReallocPlacement::InPlace => Err(AllocErr),
            ReallocPlacement::MayMove => {
                let size = layout.size();
                debug_assert!(
                    new_size >= size,
                    "`new_size` must be greater than or equal to `layout.size()`"
                );

                if new_size == size {
                    return Ok(MemoryBlock { ptr, size });
                }

                let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
                let new_memory = self.alloc(new_layout, init)?;
                ptr::copy_nonoverlapping(ptr.as_ptr(), new_memory.ptr.as_ptr(), size);
                self.dealloc(ptr, layout);
                Ok(new_memory)
            }
        }
    }

    /// Attempts to shrink the memory block.
    ///
    /// Returns a new memory block containing a pointer and the actual size of the allocated
    /// block. The pointer is suitable for holding data described by a new layout with `layout`’s
    /// alignment and a size given by `new_size`. To accomplish this, the allocator may shrink the
    /// allocation referenced by `ptr` to fit the new layout. If the [`placement`] is
    /// [`InPlace`], the returned pointer is guaranteed to be the same as the passed `ptr`.
    ///
    /// If this returns `Ok`, then ownership of the memory block referenced by `ptr` has been
    /// transferred to this allocator. The memory may or may not have been freed, and should be
    /// considered unusable unless it was transferred back to the caller again via the
    /// return value of this method.
    ///
    /// If this method returns `Err`, then ownership of the memory block has not been transferred to
    /// this allocator, and the contents of the memory block are unaltered.
    ///
    /// The behavior of how the allocator tries to shrink the memory is specified by [`placement`].
    ///
    /// [`InPlace`]: ReallocPlacement::InPlace
    /// [`placement`]: ReallocPlacement
    ///
    /// # Safety
    ///
    /// * `ptr` must be [*currently allocated*] via this allocator,
    /// * `layout` must [*fit*] the `ptr`. (The `new_size` argument need not fit it.)
    // We can't require that `new_size` is strictly smaller than `memory.size` because of ZSTs.
    // An alternative would be
    // * `new_size must be strictly smaller than `memory.size` or both are zero
    /// * `new_size` must be smaller than or equal to `layout.size()`
    ///
    /// [*currently allocated*]: #currently-allocated-memory
    /// [*fit*]: #memory-fitting
    ///
    /// # Errors
    ///
    /// Returns `Err` if the new layout does not meet the allocator's size and alignment
    /// constraints of the allocator, or if growing otherwise fails.
    ///
    /// Implementations are encouraged to return `Err` on memory exhaustion rather than panicking or
    /// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement
    /// this trait atop an underlying native allocation library that aborts on memory exhaustion.)
    ///
    /// Clients wishing to abort computation in response to an allocation error are encouraged to
    /// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar.
    ///
    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
    unsafe fn shrink(
        &mut self,
        ptr: NonNull<u8>,
        layout: Layout,
        new_size: usize,
        placement: ReallocPlacement,
    ) -> Result<MemoryBlock, AllocErr> {
        match placement {
            ReallocPlacement::InPlace => Err(AllocErr),
            ReallocPlacement::MayMove => {
                let size = layout.size();
                debug_assert!(
                    new_size <= size,
                    "`new_size` must be smaller than or equal to `layout.size()`"
                );

                if new_size == size {
                    return Ok(MemoryBlock { ptr, size });
                }

                let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
                let new_memory = self.alloc(new_layout, AllocInit::Uninitialized)?;
                ptr::copy_nonoverlapping(ptr.as_ptr(), new_memory.ptr.as_ptr(), new_size);
                self.dealloc(ptr, layout);
                Ok(new_memory)
            }
        }
    }
}
<commit_msg>Fix links for `AllocInit` methods<commit_after>//! Memory allocation APIs

#![stable(feature = "alloc_module", since = "1.28.0")]

mod global;
mod layout;

#[stable(feature = "global_alloc", since = "1.28.0")]
pub use self::global::GlobalAlloc;
#[stable(feature = "alloc_layout", since = "1.28.0")]
pub use self::layout::{Layout, LayoutErr};

use crate::fmt;
use crate::ptr::{self, NonNull};

/// The `AllocErr` error indicates an allocation failure
/// that may be due to resource exhaustion or to
/// something wrong when combining the given input arguments with this
/// allocator.
#[unstable(feature = "allocator_api", issue = "32838")]
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct AllocErr;

// (we need this for downstream impl of trait Error)
#[unstable(feature = "allocator_api", issue = "32838")]
impl fmt::Display for AllocErr {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str("memory allocation failed")
    }
}

/// A desired initial state for allocated memory.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[unstable(feature = "allocator_api", issue = "32838")]
pub enum AllocInit {
    /// The contents of the new memory are undefined.
    ///
    /// Reading uninitialized memory is Undefined Behavior; it must be initialized before use.
    Uninitialized,
    /// The new memory is guaranteed to be zeroed.
    Zeroed,
}

impl AllocInit {
    /// Initialize the specified memory block.
    ///
    /// This behaves like calling [`AllocInit::init_offset(memory, 0)`][off].
    ///
    /// [off]: AllocInit::init_offset
    ///
    /// # Safety
    ///
    /// * `memory.ptr` must be [valid] for writes of `memory.size` bytes.
    ///
    /// [valid]: ../../ptr/index.html#safety
    #[inline]
    #[unstable(feature = "allocator_api", issue = "32838")]
    pub unsafe fn init(self, memory: MemoryBlock) {
        self.init_offset(memory, 0)
    }

    /// Initialize the memory block like specified by `init` at the specified `offset`.
    ///
    /// This is a no-op for [`AllocInit::Uninitialized`][] and writes zeroes for
    /// [`AllocInit::Zeroed`][] at `ptr + offset` until `ptr + layout.size()`.
    ///
    /// # Safety
    ///
    /// * `memory.ptr` must be [valid] for writes of `memory.size` bytes.
    /// * `offset` must be smaller than or equal to `memory.size`
    ///
    /// [valid]: ../../ptr/index.html#safety
    #[inline]
    #[unstable(feature = "allocator_api", issue = "32838")]
    pub unsafe fn init_offset(self, memory: MemoryBlock, offset: usize) {
        debug_assert!(
            offset <= memory.size,
            "`offset` must be smaller than or equal to `memory.size`"
        );
        match self {
            AllocInit::Uninitialized => (),
            AllocInit::Zeroed => {
                memory.ptr.as_ptr().add(offset).write_bytes(0, memory.size - offset)
            }
        }
    }
}

/// Represents a block of allocated memory returned by an allocator.
#[derive(Debug, Copy, Clone)]
#[unstable(feature = "allocator_api", issue = "32838")]
pub struct MemoryBlock {
    pub ptr: NonNull<u8>,
    pub size: usize,
}

/// A placement constraint when growing or shrinking an existing allocation.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[unstable(feature = "allocator_api", issue = "32838")]
pub enum ReallocPlacement {
    /// The allocator is allowed to move the allocation to a different memory address.
    // FIXME(wg-allocators#46): Add a section to the module documentation "What is a legal
    //                          allocator" and link it at "valid location".
    ///
    /// If the allocation _does_ move, it's the responsibility of the allocator
    /// to also move the data from the previous location to the new location.
    MayMove,
    /// The address of the new memory must not change.
    ///
    /// If the allocation would have to be moved to a new location to fit, the
    /// reallocation request will fail.
    InPlace,
}

/// An implementation of `AllocRef` can allocate, grow, shrink, and deallocate arbitrary blocks of
/// data described via [`Layout`][].
///
/// `AllocRef` is designed to be implemented on ZSTs, references, or smart pointers because having
/// an allocator like `MyAlloc([u8; N])` cannot be moved, without updating the pointers to the
/// allocated memory.
///
/// Unlike [`GlobalAlloc`][], zero-sized allocations are allowed in `AllocRef`. If an underlying
/// allocator does not support this (like jemalloc) or return a null pointer (such as
/// `libc::malloc`), this case must be caught.
///
/// ### Currently allocated memory
///
/// Some of the methods require that a memory block be *currently allocated* via an allocator. This
/// means that:
///
/// * the starting address for that memory block was previously returned by [`alloc`], [`grow`], or
///   [`shrink`], and
///
/// * the memory block has not been subsequently deallocated, where blocks are either deallocated
///   directly by being passed to [`dealloc`] or were changed by being passed to [`grow`] or
///   [`shrink`] that returns `Ok`. If `grow` or `shrink` have returned `Err`, the passed pointer
///   remains valid.
///
/// [`alloc`]: AllocRef::alloc
/// [`grow`]: AllocRef::grow
/// [`shrink`]: AllocRef::shrink
/// [`dealloc`]: AllocRef::dealloc
///
/// ### Memory fitting
///
/// Some of the methods require that a layout *fit* a memory block. What it means for a layout to
/// "fit" a memory block means (or equivalently, for a memory block to "fit" a layout) is that the
/// following conditions must hold:
///
/// * The block must be allocated with the same alignment as [`layout.align()`], and
///
/// * The provided [`layout.size()`] must fall in the range `min ..= max`, where:
///   - `min` is the size of the layout most recently used to allocate the block, and
///   - `max` is the latest actual size returned from [`alloc`], [`grow`], or [`shrink`].
///
/// [`layout.align()`]: Layout::align
/// [`layout.size()`]: Layout::size
///
/// # Safety
///
/// * Memory blocks returned from an allocator must point to valid memory and retain their validity
///   until the instance and all of its clones are dropped, and
///
/// * cloning or moving the allocator must not invalidate memory blocks returned from this
///   allocator. A cloned allocator must behave like the same allocator.
///
/// * any pointer to a memory block which is [*currently allocated*] may be passed to any other
///   method of the allocator.
///
/// [*currently allocated*]: #currently-allocated-memory
#[unstable(feature = "allocator_api", issue = "32838")]
pub unsafe trait AllocRef {
    /// On success, returns a memory block meeting the size and alignment guarantees of `layout`.
    ///
    /// The returned block may have a larger size than specified by `layout.size()` and is
    /// initialized as specified by [`init`], all the way up to the returned size of the block.
    ///
    /// [`init`]: AllocInit
    ///
    /// # Errors
    ///
    /// Returning `Err` indicates that either memory is exhausted or `layout` does not meet
    /// allocator's size or alignment constraints.
    ///
    /// Implementations are encouraged to return `Err` on memory exhaustion rather than panicking or
    /// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement
    /// this trait atop an underlying native allocation library that aborts on memory exhaustion.)
    ///
    /// Clients wishing to abort computation in response to an allocation error are encouraged to
    /// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar.
    ///
    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
    fn alloc(&mut self, layout: Layout, init: AllocInit) -> Result<MemoryBlock, AllocErr>;

    /// Deallocates the memory denoted by `memory`.
    ///
    /// # Safety
    ///
    /// `memory` must be a memory block returned by this allocator.
    unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout);

    /// Attempts to extend the memory block.
    ///
    /// Returns a new memory block containing a pointer and the actual size of the allocated
    /// block. The pointer is suitable for holding data described by a new layout with `layout`’s
    /// alignment and a size given by `new_size`. To accomplish this, the allocator may extend the
    /// allocation referenced by `ptr` to fit the new layout. If the [`placement`] is
    /// [`InPlace`], the returned pointer is guaranteed to be the same as the passed `ptr`.
    ///
    /// If `ReallocPlacement::MayMove` is used then ownership of the memory block referenced by `ptr`
    /// is transferred to this allocator. The memory may or may not be freed, and should be
    /// considered unusable (unless of course it is transferred back to the caller again via the
    /// return value of this method).
    ///
    /// If this method returns `Err`, then ownership of the memory block has not been transferred to
    /// this allocator, and the contents of the memory block are unaltered.
    ///
    /// The memory block will contain the following contents after a successful call to `grow`:
    ///   * Bytes `0..layout.size()` are preserved from the original allocation.
    ///   * Bytes `layout.size()..old_size` will either be preserved or initialized according to
    ///     [`init`], depending on the allocator implementation. `old_size` refers to the size of
    ///     the `MemoryBlock` prior to the `grow` call, which may be larger than the size
    ///     that was originally requested when it was allocated.
    ///   * Bytes `old_size..new_size` are initialized according to [`init`]. `new_size` refers to
    ///     the size of the `MemoryBlock` returned by the `grow` call.
    ///
    /// [`InPlace`]: ReallocPlacement::InPlace
    /// [`placement`]: ReallocPlacement
    /// [`init`]: AllocInit
    ///
    /// # Safety
    ///
    /// * `ptr` must be [*currently allocated*] via this allocator,
    /// * `layout` must [*fit*] the `ptr`. (The `new_size` argument need not fit it.)
    // We can't require that `new_size` is strictly greater than `memory.size` because of ZSTs.
    // An alternative would be
    // * `new_size must be strictly greater than `memory.size` or both are zero
    /// * `new_size` must be greater than or equal to `layout.size()`
    /// * `new_size`, when rounded up to the nearest multiple of `layout.align()`, must not overflow
    ///   (i.e., the rounded value must be less than `usize::MAX`).
    ///
    /// [*currently allocated*]: #currently-allocated-memory
    /// [*fit*]: #memory-fitting
    ///
    /// # Errors
    ///
    /// Returns `Err` if the new layout does not meet the allocator's size and alignment
    /// constraints of the allocator, or if growing otherwise fails.
    ///
    /// Implementations are encouraged to return `Err` on memory exhaustion rather than panicking or
    /// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement
    /// this trait atop an underlying native allocation library that aborts on memory exhaustion.)
    ///
    /// Clients wishing to abort computation in response to an allocation error are encouraged to
    /// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar.
    ///
    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
    unsafe fn grow(
        &mut self,
        ptr: NonNull<u8>,
        layout: Layout,
        new_size: usize,
        placement: ReallocPlacement,
        init: AllocInit,
    ) -> Result<MemoryBlock, AllocErr> {
        match placement {
            ReallocPlacement::InPlace => Err(AllocErr),
            ReallocPlacement::MayMove => {
                let size = layout.size();
                debug_assert!(
                    new_size >= size,
                    "`new_size` must be greater than or equal to `layout.size()`"
                );

                if new_size == size {
                    return Ok(MemoryBlock { ptr, size });
                }

                let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
                let new_memory = self.alloc(new_layout, init)?;
                ptr::copy_nonoverlapping(ptr.as_ptr(), new_memory.ptr.as_ptr(), size);
                self.dealloc(ptr, layout);
                Ok(new_memory)
            }
        }
    }

    /// Attempts to shrink the memory block.
    ///
    /// Returns a new memory block containing a pointer and the actual size of the allocated
    /// block. The pointer is suitable for holding data described by a new layout with `layout`’s
    /// alignment and a size given by `new_size`. To accomplish this, the allocator may shrink the
    /// allocation referenced by `ptr` to fit the new layout. If the [`placement`] is
    /// [`InPlace`], the returned pointer is guaranteed to be the same as the passed `ptr`.
    ///
    /// If this returns `Ok`, then ownership of the memory block referenced by `ptr` has been
    /// transferred to this allocator. The memory may or may not have been freed, and should be
    /// considered unusable unless it was transferred back to the caller again via the
    /// return value of this method.
    ///
    /// If this method returns `Err`, then ownership of the memory block has not been transferred to
    /// this allocator, and the contents of the memory block are unaltered.
    ///
    /// The behavior of how the allocator tries to shrink the memory is specified by [`placement`].
    ///
    /// [`InPlace`]: ReallocPlacement::InPlace
    /// [`placement`]: ReallocPlacement
    ///
    /// # Safety
    ///
    /// * `ptr` must be [*currently allocated*] via this allocator,
    /// * `layout` must [*fit*] the `ptr`. (The `new_size` argument need not fit it.)
    // We can't require that `new_size` is strictly smaller than `memory.size` because of ZSTs.
    // An alternative would be
    // * `new_size must be strictly smaller than `memory.size` or both are zero
    /// * `new_size` must be smaller than or equal to `layout.size()`
    ///
    /// [*currently allocated*]: #currently-allocated-memory
    /// [*fit*]: #memory-fitting
    ///
    /// # Errors
    ///
    /// Returns `Err` if the new layout does not meet the allocator's size and alignment
    /// constraints of the allocator, or if growing otherwise fails.
    ///
    /// Implementations are encouraged to return `Err` on memory exhaustion rather than panicking or
    /// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement
    /// this trait atop an underlying native allocation library that aborts on memory exhaustion.)
    ///
    /// Clients wishing to abort computation in response to an allocation error are encouraged to
    /// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar.
    ///
    /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
    unsafe fn shrink(
        &mut self,
        ptr: NonNull<u8>,
        layout: Layout,
        new_size: usize,
        placement: ReallocPlacement,
    ) -> Result<MemoryBlock, AllocErr> {
        match placement {
            ReallocPlacement::InPlace => Err(AllocErr),
            ReallocPlacement::MayMove => {
                let size = layout.size();
                debug_assert!(
                    new_size <= size,
                    "`new_size` must be smaller than or equal to `layout.size()`"
                );

                if new_size == size {
                    return Ok(MemoryBlock { ptr, size });
                }

                let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
                let new_memory = self.alloc(new_layout, AllocInit::Uninitialized)?;
                ptr::copy_nonoverlapping(ptr.as_ptr(), new_memory.ptr.as_ptr(), new_size);
                self.dealloc(ptr, layout);
                Ok(new_memory)
            }
        }
    }
}
<|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/.

extern crate pkg_config;

use std::process::Command;
use std::env;
use std::fs;
use std::fs::File;

// Needs the libev-dev package

// Return true if file1 doesn't exist or is older than file2.
fn doesnt_exists_or_older(file1: &str, file2: &str) -> bool {
    let f1 = File::open(file1);
    if f1.is_err() {
        return true;
    }

    let f2 = File::open(file2);
    if f2.is_err() {
        panic!(format!("The file {} should exist!", file2));
    }

    let time1 = f1.unwrap().metadata().unwrap().modified().unwrap();
    let time2 = f2.unwrap().metadata().unwrap().modified().unwrap();
    time1 < time2
}

macro_rules! doesnt_exists_or_older (
    ($f1:expr, $f2:expr) => (
        doesnt_exists_or_older(&format!("libpagekite/{}", $f1), &format!("libpagekite/{}", $f2))
    )
);

fn build(output: &str) {
    // If configure doesn't exist or is older than configure.ac run autogen.sh
    if doesnt_exists_or_older!("configure", "configure.ac") {
        let exit_code = Command::new("./autogen.sh")
            .current_dir("libpagekite")
            .status()
            .unwrap();

        if !exit_code.success() {
            panic!("Failed to run libpagekite/autogen.sh");
        }
    }

    // If Makefile doesn't exist or is older than configure run configure
    if doesnt_exists_or_older!("Makefile", "configure") {
        let exit_code = Command::new("./configure")
            .env("CFLAGS", "-fPIC") // Needed to build the static library as PIC.
            .arg(format!("--prefix={}", output))
            .arg(format!("--without-java"))
            .arg(format!("--host={}", env::var("TARGET_TRIPLE").unwrap_or(env::var("TARGET").unwrap())))
            .current_dir("libpagekite")
            .status().unwrap();

        if !exit_code.success() {
            panic!("Failed to run libpagekite/configure");
        }
    }

    // We don't pass -j parameter to `make` because the build fails with this option.
    let exit_code = Command::new("make")
        .arg("install")
        .current_dir("libpagekite")
        .status()
        .unwrap();

    if !exit_code.success() {
        panic!(format!("Failure running `make -C libpagekite`"));
    }
}

#[allow(unused_must_use)]
fn main() {
    let libpagekite_build_dir = format!("{}/{}", env::var("OUT_DIR").unwrap(), "libpagekite");

    fs::create_dir(libpagekite_build_dir.clone());

    build(&libpagekite_build_dir);

    pkg_config::probe_library("libssl").unwrap();

    // No pkg-config support for libev unfortunately.
    println!("cargo:rustc-link-lib=ev");

    println!("cargo:rustc-link-search=native={}/lib", libpagekite_build_dir);
    println!("cargo:rustc-link-lib=dylib=pagekite");
}
<commit_msg>Always run configure to pick up Rust target change.<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/.

extern crate pkg_config;

use std::process::Command;
use std::env;
use std::fs;
use std::fs::File;

// Needs the libev-dev package

// Return true if file1 doesn't exist or is older than file2.
fn doesnt_exists_or_older(file1: &str, file2: &str) -> bool {
    let f1 = File::open(file1);
    if f1.is_err() {
        return true;
    }

    let f2 = File::open(file2);
    if f2.is_err() {
        panic!(format!("The file {} should exist!", file2));
    }

    let time1 = f1.unwrap().metadata().unwrap().modified().unwrap();
    let time2 = f2.unwrap().metadata().unwrap().modified().unwrap();
    time1 < time2
}

macro_rules! doesnt_exists_or_older (
    ($f1:expr, $f2:expr) => (
        doesnt_exists_or_older(&format!("libpagekite/{}", $f1), &format!("libpagekite/{}", $f2))
    )
);

fn build(output: &str) {
    // If configure doesn't exist or is older than configure.ac run autogen.sh
    if doesnt_exists_or_older!("configure", "configure.ac") {
        let exit_code = Command::new("./autogen.sh")
            .current_dir("libpagekite")
            .status()
            .unwrap();

        if !exit_code.success() {
            panic!("Failed to run libpagekite/autogen.sh");
        }
    }

    // We always run configure to setup a new installation prefix if needed
    // when switching from debug and release Rust targets.
    let exit_code = Command::new("./configure")
            .env("CFLAGS", "-fPIC") // Needed to build the static library as PIC.
            .arg(format!("--prefix={}", output))
            .arg(format!("--without-java"))
            .arg(format!("--host={}", env::var("TARGET_TRIPLE").unwrap_or(env::var("TARGET").unwrap())))
            .current_dir("libpagekite")
            .status().unwrap();

    if !exit_code.success() {
        panic!("Failed to run libpagekite/configure");
    }

    // We don't pass -j parameter to `make` because the build fails with this option.
    // See https://github.com/pagekite/libpagekite/pull/28
    let exit_code = Command::new("make")
        .arg("install")
        .current_dir("libpagekite")
        .status()
        .unwrap();

    if !exit_code.success() {
        panic!(format!("Failure running `make -C libpagekite`"));
    }
}

#[allow(unused_must_use)]
fn main() {
    let libpagekite_build_dir = format!("{}/{}", env::var("OUT_DIR").unwrap(), "libpagekite");

    fs::create_dir(libpagekite_build_dir.clone());

    build(&libpagekite_build_dir);

    pkg_config::probe_library("libssl").unwrap();

    // No pkg-config support for libev unfortunately.
    println!("cargo:rustc-link-lib=ev");

    println!("cargo:rustc-link-search=native={}/lib", libpagekite_build_dir);
    println!("cargo:rustc-link-lib=dylib=pagekite");
}
<|endoftext|>