<commit_before>import dvec::{dvec, extensions};

export filename;
export filemap;
export span;
export file_substr;
export codemap;
export expn_info;
export expn_info_;
export expanded_from;
export new_filemap;
export new_filemap_w_substr;
export mk_substr_filename;
export lookup_char_pos;
export lookup_char_pos_adj;
export adjust_span;
export span_to_str;
export span_to_filename;
export span_to_lines;
export file_lines;
export get_line;
export next_line;
export span_to_snippet;
export loc;
export get_filemap;
export new_codemap;

type filename = str;

type file_pos = {ch: uint, byte: uint};

/* A codemap is a thing that maps uints to file/line/column positions
 * in a crate. This to make it possible to represent the positions
 * with single-word things, rather than passing records all over the
 * compiler.
 */

enum file_substr {
    fss_none,
    fss_internal(span),
    fss_external({filename: str, line: uint, col: uint})
}

type filemap =
    @{name: filename, substr: file_substr, src: @str,
      start_pos: file_pos, mut lines: [file_pos]};

type codemap = @{files: dvec<filemap>};

type loc = {file: filemap, line: uint, col: uint};

fn new_codemap() -> codemap { @{files: dvec()} }

fn new_filemap_w_substr(filename: filename, substr: file_substr,
                        src: @str,
                        start_pos_ch: uint, start_pos_byte: uint)
   -> filemap {
    ret @{name: filename, substr: substr, src: src,
          start_pos: {ch: start_pos_ch, byte: start_pos_byte},
          mut lines: [{ch: start_pos_ch, byte: start_pos_byte}]};
}

fn new_filemap(filename: filename, src: @str,
               start_pos_ch: uint, start_pos_byte: uint)
    -> filemap {
    ret new_filemap_w_substr(filename, fss_none, src,
                             start_pos_ch, start_pos_byte);
}

fn mk_substr_filename(cm: codemap, sp: span) -> str
{
    let pos = lookup_char_pos(cm, sp.lo);
    ret #fmt("<%s:%u:%u>", pos.file.name, pos.line, pos.col);
}

fn next_line(file: filemap, chpos: uint, byte_pos: uint) {
    file.lines += [{ch: chpos, byte: byte_pos + file.start_pos.byte}];
}

type lookup_fn = fn@(file_pos) -> uint;

fn lookup_line(map: codemap, pos: uint, lookup: lookup_fn)
    -> {fm: filemap, line: uint}
{
    let len = map.files.len();
    let mut a = 0u;
    let mut b = len;
    while b - a > 1u {
        let m = (a + b) / 2u;
        if lookup(map.files[m].start_pos) > pos { b = m; } else { a = m; }
    }
    if (a >= len) {
        fail #fmt("position %u does not resolve to a source location", pos)
    }
    let f = map.files[a];
    a = 0u;
    b = vec::len(f.lines);
    while b - a > 1u {
        let m = (a + b) / 2u;
        if lookup(f.lines[m]) > pos { b = m; } else { a = m; }
    }
    ret {fm: f, line: a};
}

fn lookup_pos(map: codemap, pos: uint, lookup: lookup_fn) -> loc {
    let {fm: f, line: a} = lookup_line(map, pos, lookup);
    ret {file: f, line: a + 1u, col: pos - lookup(f.lines[a])};
}

fn lookup_char_pos(map: codemap, pos: uint) -> loc {
    fn lookup(pos: file_pos) -> uint { ret pos.ch; }
    ret lookup_pos(map, pos, lookup);
}

fn lookup_byte_pos(map: codemap, pos: uint) -> loc {
    fn lookup(pos: file_pos) -> uint { ret pos.byte; }
    ret lookup_pos(map, pos, lookup);
}

fn lookup_char_pos_adj(map: codemap, pos: uint)
    -> {filename: str, line: uint, col: uint, file: option<filemap>}
{
    let loc = lookup_char_pos(map, pos);
    alt (loc.file.substr) {
      fss_none {
        {filename: loc.file.name, line: loc.line, col: loc.col,
         file: some(loc.file)}
      }
      fss_internal(sp) {
        lookup_char_pos_adj(map, sp.lo + (pos - loc.file.start_pos.ch))
      }
      fss_external(eloc) {
        {filename: eloc.filename,
         line: eloc.line + loc.line - 1u,
         col: if loc.line == 1u {eloc.col + loc.col} else {loc.col},
         file: none}
      }
    }
}

fn adjust_span(map: codemap, sp: span) -> span {
    fn lookup(pos: file_pos) -> uint { ret pos.ch; }
    let line = lookup_line(map, sp.lo, lookup);
    alt (line.fm.substr) {
      fss_none {sp}
      fss_internal(s) {
        adjust_span(map, {lo: s.lo + (sp.lo - line.fm.start_pos.ch),
                          hi: s.lo + (sp.hi - line.fm.start_pos.ch),
                          expn_info: sp.expn_info})}
      fss_external(_) {sp}
    }
}

enum expn_info_ {
    expanded_from({call_site: span,
                   callie: {name: str, span: option<span>}})
}
type expn_info = option<@expn_info_>;
type span = {lo: uint, hi: uint, expn_info: expn_info};

fn span_to_str_no_adj(sp: span, cm: codemap) -> str {
    let lo = lookup_char_pos(cm, sp.lo);
    let hi = lookup_char_pos(cm, sp.hi);
    ret #fmt("%s:%u:%u: %u:%u", lo.file.name,
             lo.line, lo.col, hi.line, hi.col)
}

fn span_to_str(sp: span, cm: codemap) -> str {
    let lo = lookup_char_pos_adj(cm, sp.lo);
    let hi = lookup_char_pos_adj(cm, sp.hi);
    ret #fmt("%s:%u:%u: %u:%u", lo.filename,
             lo.line, lo.col, hi.line, hi.col)
}

type file_lines = {file: filemap, lines: [uint]};

fn span_to_filename(sp: span, cm: codemap::codemap) -> filename {
    let lo = lookup_char_pos(cm, sp.lo);
    ret lo.file.name;
}

fn span_to_lines(sp: span, cm: codemap::codemap) -> @file_lines {
    let lo = lookup_char_pos(cm, sp.lo);
    let hi = lookup_char_pos(cm, sp.hi);
    let mut lines = [];
    for uint::range(lo.line - 1u, hi.line as uint) {|i| lines += [i]; };
    ret @{file: lo.file, lines: lines};
}

fn get_line(fm: filemap, line: int) -> str unsafe {
    let begin: uint = fm.lines[line].byte - fm.start_pos.byte;
    let end = alt str::find_char_from(*fm.src, '\n', begin) {
      some(e) { e }
      none { str::len(*fm.src) }
    };
    str::slice(*fm.src, begin, end)
}

fn lookup_byte_offset(cm: codemap::codemap, chpos: uint)
    -> {fm: filemap, pos: uint} {
    let {fm, line} = lookup_line(cm, chpos, {|pos| pos.ch});
    let line_offset = fm.lines[line].byte - fm.start_pos.byte;
    let col = chpos - fm.lines[line].ch;
    let col_offset = str::count_bytes(*fm.src, line_offset, col);
    {fm: fm, pos: line_offset + col_offset}
}

fn span_to_snippet(sp: span, cm: codemap::codemap) -> str {
    let begin = lookup_byte_offset(cm, sp.lo);
    let end = lookup_byte_offset(cm, sp.hi);
    assert begin.fm == end.fm;
    ret str::slice(*begin.fm.src, begin.pos, end.pos);
}

fn get_snippet(cm: codemap::codemap, fidx: uint, lo: uint, hi: uint) -> str
{
    let fm = cm.files[fidx];
    ret str::slice(*fm.src, lo, hi)
}

fn get_filemap(cm: codemap, filename: str) -> filemap {
    for cm.files.each {|fm| if fm.name == filename { ret fm; } }
    //XXjdm the following triggers a mismatched type bug
    //      (or expected function, found _|_)
    fail; // ("asking for " + filename + " which we don't know about");
}

//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//
<commit_msg>make lookup fn pure in codemap<commit_after>import dvec::{dvec, extensions};

export filename;
export filemap;
export span;
export file_substr;
export codemap;
export expn_info;
export expn_info_;
export expanded_from;
export new_filemap;
export new_filemap_w_substr;
export mk_substr_filename;
export lookup_char_pos;
export lookup_char_pos_adj;
export adjust_span;
export span_to_str;
export span_to_filename;
export span_to_lines;
export file_lines;
export get_line;
export next_line;
export span_to_snippet;
export loc;
export get_filemap;
export new_codemap;

type filename = str;

type file_pos = {ch: uint, byte: uint};

/* A codemap is a thing that maps uints to file/line/column positions
 * in a crate. This to make it possible to represent the positions
 * with single-word things, rather than passing records all over the
 * compiler.
 */

enum file_substr {
    fss_none,
    fss_internal(span),
    fss_external({filename: str, line: uint, col: uint})
}

type filemap =
    @{name: filename, substr: file_substr, src: @str,
      start_pos: file_pos, mut lines: [file_pos]};

type codemap = @{files: dvec<filemap>};

type loc = {file: filemap, line: uint, col: uint};

fn new_codemap() -> codemap { @{files: dvec()} }

fn new_filemap_w_substr(filename: filename, substr: file_substr,
                        src: @str,
                        start_pos_ch: uint, start_pos_byte: uint)
   -> filemap {
    ret @{name: filename, substr: substr, src: src,
          start_pos: {ch: start_pos_ch, byte: start_pos_byte},
          mut lines: [{ch: start_pos_ch, byte: start_pos_byte}]};
}

fn new_filemap(filename: filename, src: @str,
               start_pos_ch: uint, start_pos_byte: uint)
    -> filemap {
    ret new_filemap_w_substr(filename, fss_none, src,
                             start_pos_ch, start_pos_byte);
}

fn mk_substr_filename(cm: codemap, sp: span) -> str
{
    let pos = lookup_char_pos(cm, sp.lo);
    ret #fmt("<%s:%u:%u>", pos.file.name, pos.line, pos.col);
}

fn next_line(file: filemap, chpos: uint, byte_pos: uint) {
    file.lines += [{ch: chpos, byte: byte_pos + file.start_pos.byte}];
}

type lookup_fn = pure fn(file_pos) -> uint;

fn lookup_line(map: codemap, pos: uint, lookup: lookup_fn)
    -> {fm: filemap, line: uint}
{
    let len = map.files.len();
    let mut a = 0u;
    let mut b = len;
    while b - a > 1u {
        let m = (a + b) / 2u;
        if lookup(map.files[m].start_pos) > pos { b = m; } else { a = m; }
    }
    if (a >= len) {
        fail #fmt("position %u does not resolve to a source location", pos)
    }
    let f = map.files[a];
    a = 0u;
    b = vec::len(f.lines);
    while b - a > 1u {
        let m = (a + b) / 2u;
        if lookup(f.lines[m]) > pos { b = m; } else { a = m; }
    }
    ret {fm: f, line: a};
}

fn lookup_pos(map: codemap, pos: uint, lookup: lookup_fn) -> loc {
    let {fm: f, line: a} = lookup_line(map, pos, lookup);
    ret {file: f, line: a + 1u, col: pos - lookup(f.lines[a])};
}

fn lookup_char_pos(map: codemap, pos: uint) -> loc {
    pure fn lookup(pos: file_pos) -> uint { ret pos.ch; }
    ret lookup_pos(map, pos, lookup);
}

fn lookup_byte_pos(map: codemap, pos: uint) -> loc {
    pure fn lookup(pos: file_pos) -> uint { ret pos.byte; }
    ret lookup_pos(map, pos, lookup);
}

fn lookup_char_pos_adj(map: codemap, pos: uint)
    -> {filename: str, line: uint, col: uint, file: option<filemap>}
{
    let loc = lookup_char_pos(map, pos);
    alt (loc.file.substr) {
      fss_none {
        {filename: loc.file.name, line: loc.line, col: loc.col,
         file: some(loc.file)}
      }
      fss_internal(sp) {
        lookup_char_pos_adj(map, sp.lo + (pos - loc.file.start_pos.ch))
      }
      fss_external(eloc) {
        {filename: eloc.filename,
         line: eloc.line + loc.line - 1u,
         col: if loc.line == 1u {eloc.col + loc.col} else {loc.col},
         file: none}
      }
    }
}

fn adjust_span(map: codemap, sp: span) -> span {
    pure fn lookup(pos: file_pos) -> uint { ret pos.ch; }
    let line = lookup_line(map, sp.lo, lookup);
    alt (line.fm.substr) {
      fss_none {sp}
      fss_internal(s) {
        adjust_span(map, {lo: s.lo + (sp.lo - line.fm.start_pos.ch),
                          hi: s.lo + (sp.hi - line.fm.start_pos.ch),
                          expn_info: sp.expn_info})}
      fss_external(_) {sp}
    }
}

enum expn_info_ {
    expanded_from({call_site: span,
                   callie: {name: str, span: option<span>}})
}
type expn_info = option<@expn_info_>;
type span = {lo: uint, hi: uint, expn_info: expn_info};

fn span_to_str_no_adj(sp: span, cm: codemap) -> str {
    let lo = lookup_char_pos(cm, sp.lo);
    let hi = lookup_char_pos(cm, sp.hi);
    ret #fmt("%s:%u:%u: %u:%u", lo.file.name,
             lo.line, lo.col, hi.line, hi.col)
}

fn span_to_str(sp: span, cm: codemap) -> str {
    let lo = lookup_char_pos_adj(cm, sp.lo);
    let hi = lookup_char_pos_adj(cm, sp.hi);
    ret #fmt("%s:%u:%u: %u:%u", lo.filename,
             lo.line, lo.col, hi.line, hi.col)
}

type file_lines = {file: filemap, lines: [uint]};

fn span_to_filename(sp: span, cm: codemap::codemap) -> filename {
    let lo = lookup_char_pos(cm, sp.lo);
    ret lo.file.name;
}

fn span_to_lines(sp: span, cm: codemap::codemap) -> @file_lines {
    let lo = lookup_char_pos(cm, sp.lo);
    let hi = lookup_char_pos(cm, sp.hi);
    let mut lines = [];
    for uint::range(lo.line - 1u, hi.line as uint) {|i| lines += [i]; };
    ret @{file: lo.file, lines: lines};
}

fn get_line(fm: filemap, line: int) -> str unsafe {
    let begin: uint = fm.lines[line].byte - fm.start_pos.byte;
    let end = alt str::find_char_from(*fm.src, '\n', begin) {
      some(e) { e }
      none { str::len(*fm.src) }
    };
    str::slice(*fm.src, begin, end)
}

fn lookup_byte_offset(cm: codemap::codemap, chpos: uint)
    -> {fm: filemap, pos: uint} {
    pure fn lookup(pos: file_pos) -> uint { ret pos.ch; }
    let {fm, line} = lookup_line(cm, chpos, lookup);
    let line_offset = fm.lines[line].byte - fm.start_pos.byte;
    let col = chpos - fm.lines[line].ch;
    let col_offset = str::count_bytes(*fm.src, line_offset, col);
    {fm: fm, pos: line_offset + col_offset}
}

fn span_to_snippet(sp: span, cm: codemap::codemap) -> str {
    let begin = lookup_byte_offset(cm, sp.lo);
    let end = lookup_byte_offset(cm, sp.hi);
    assert begin.fm == end.fm;
    ret str::slice(*begin.fm.src, begin.pos, end.pos);
}

fn get_snippet(cm: codemap::codemap, fidx: uint, lo: uint, hi: uint) -> str
{
    let fm = cm.files[fidx];
    ret str::slice(*fm.src, lo, hi)
}

fn get_filemap(cm: codemap, filename: str) -> filemap {
    for cm.files.each {|fm| if fm.name == filename { ret fm; } }
    //XXjdm the following triggers a mismatched type bug
    //      (or expected function, found _|_)
    fail; // ("asking for " + filename + " which we don't know about");
}

//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//
<|endoftext|>


<commit_before>use prelude::v1::*;

use any::Any;
use fmt;

#[cfg(not(test))]
/// Entry point of panic from the libcore crate.
#[lang = "panic_fmt"]
pub extern fn rust_begin_unwind(msg: fmt::Arguments,
                                file: &'static str, line: uint) -> ! {
    begin_unwind_fmt(msg, &(file, line))
}

/// The entry point for unwinding with a formatted message.
///
/// This is designed to reduce the amount of code required at the call
/// site as much as possible (so that `panic!()` has as low an impact
/// on (e.g.) the inlining of other functions as possible), by moving
/// the actual formatting into this shared place.
#[inline(never)] #[cold]
pub fn begin_unwind_fmt(msg: fmt::Arguments, file_line: &(&'static str, uint)) -> ! {
    loop{}
    //TODO

    //use fmt::Writer;

    // We do two allocations here, unfortunately. But (a) they're
    // required with the current scheme, and (b) we don't handle
    // panic + OOM properly anyway (see comment in begin_unwind
    // below).

    //let mut s = String::new();
    //let _ = write!(&mut s, "{}", msg);
    //begin_unwind_inner(box s, file_line)
}

/// This is the entry point of unwinding for panic!() and assert!().
#[inline(never)] #[cold] // avoid code bloat at the call sites as much as possible
pub fn begin_unwind<M: Any + Send>(msg: M, file_line: &(&'static str, uint)) -> ! {
    // Note that this should be the only allocation performed in this code path.
    // Currently this means that panic!() on OOM will invoke this code path,
    // but then again we're not really ready for panic on OOM anyway. If
    // we do start doing this, then we should propagate this allocation to
    // be performed in the parent of this thread instead of the thread that's
    // panicking.

    // see below for why we do the `Any` coercion here.
    // TODO
    //begin_unwind_inner(box msg, file_line)
    loop{}
}

<commit_msg>reexport alloc::heap<commit_after>use prelude::v1::*;

// Reexport some functionality from liballoc.
pub use alloc::heap;

use any::Any;
use fmt;

#[cfg(not(test))]
/// Entry point of panic from the libcore crate.
#[lang = "panic_fmt"]
pub extern fn rust_begin_unwind(msg: fmt::Arguments,
                                file: &'static str, line: uint) -> ! {
    begin_unwind_fmt(msg, &(file, line))
}

/// The entry point for unwinding with a formatted message.
///
/// This is designed to reduce the amount of code required at the call
/// site as much as possible (so that `panic!()` has as low an impact
/// on (e.g.) the inlining of other functions as possible), by moving
/// the actual formatting into this shared place.
#[inline(never)] #[cold]
pub fn begin_unwind_fmt(msg: fmt::Arguments, file_line: &(&'static str, uint)) -> ! {
    loop{}
    //TODO

    //use fmt::Writer;

    // We do two allocations here, unfortunately. But (a) they're
    // required with the current scheme, and (b) we don't handle
    // panic + OOM properly anyway (see comment in begin_unwind
    // below).

    //let mut s = String::new();
    //let _ = write!(&mut s, "{}", msg);
    //begin_unwind_inner(box s, file_line)
}

/// This is the entry point of unwinding for panic!() and assert!().
#[inline(never)] #[cold] // avoid code bloat at the call sites as much as possible
pub fn begin_unwind<M: Any + Send>(msg: M, file_line: &(&'static str, uint)) -> ! {
    // Note that this should be the only allocation performed in this code path.
    // Currently this means that panic!() on OOM will invoke this code path,
    // but then again we're not really ready for panic on OOM anyway. If
    // we do start doing this, then we should propagate this allocation to
    // be performed in the parent of this thread instead of the thread that's
    // panicking.

    // see below for why we do the `Any` coercion here.
    // TODO
    //begin_unwind_inner(box msg, file_line)
    loop{}
}

<|endoftext|>


<commit_before>//! Defines the renderable trait.
//! A renderable object holds the buffer that is written to wlc_pixel_write.
//! The buffer can only be modified by casting the type to a `Drawable`.

use rustwlc::{Geometry, WlcOutput};
use rustwlc::render::{write_pixels, wlc_pixel_format};
use cairo::{self, Context, ImageSurface, Operator};
use super::draw::BaseDraw;

/// Something that can be rendered by wlc.
/// At minimum, it must store a buffer of bytes to write to wlc,
/// a geometry to tell wlc where to place the bytes,
/// and the `WlcOutput` that it will be rendered on.
pub trait Renderable {
    /// Makes a new `Renderable`
    ///
    /// Allowed to return `None` so that a needless allocation doesn't occur
    /// (e.g when the geometry is 0).
    fn new(geometry: Geometry, output: WlcOutput) -> Option<Self>
        where Self: :: std::marker::Sized;

    /// Gets the underlying `ImageSurface` used by the `Renderable` to render
    /// to wlc.
    ///
    /// Is mutable to ensure no other threads are touching the data.
    fn get_surface(&mut self) -> &mut ImageSurface;

    /// Gets the geometry for where the buffer should be rendered on the output.
    fn get_geometry(&self) -> Geometry;

    /// Sets the geometry for where the buffer should be render on the output.
    fn set_geometry(&mut self, geometry: Geometry);

    /// Gets the output that this will be rendered on.
    fn get_output(&self) -> WlcOutput;

    /// Reallocates the buffer based on the new geometry.
    ///
    /// Allowed to return `None` so that a needless allocation doesn't occur
    /// (e.g when the geometry is 0).
    fn reallocate_buffer(self, geometry: Geometry) -> Option<Self>
        where Self: ::std::marker::Sized;

    fn enable_cairo(mut self) -> Result<BaseDraw<Self>, cairo::Status>
        where Self: ::std::marker::Sized
    {
        let cairo = Context::new(&*self.get_surface());
        match cairo.status() {
            cairo::Status::Success => {},
            err => return Err(err)
        }
        cairo.set_operator(Operator::Source);
        match cairo.status() {
            cairo::Status::Success => {},
            err => return Err(err)
        }
        Ok(BaseDraw::new(self, cairo))
    }

    /// Renders the data buffer at the internal geometry.
    ///
    /// Automatically ensures that the buffer does not clip the sides
    fn render(&mut self) {
        let output_res = self.get_output().get_resolution()
            .expect("Output had no resolution");
        let mut geometry = self.get_geometry();
        let surface = self.get_surface();
        let buffer = surface.get_data()
            .expect("Could not get surface buffer");

        // If the buffer would clip the side, keep it within the bounds
        // This is done because wlc wraps if it goes beyond, which we don't
        // want for the borders.
        if geometry.origin.x + geometry.size.w as i32 > output_res.w as i32 {
            let offset = (geometry.origin.x + geometry.size.w as i32) - output_res.w as i32;
            geometry.origin.x -= offset as i32;
        }
        if geometry.origin.y + geometry.size.h as i32 > output_res.h as i32 {
            let offset = (geometry.origin.y + geometry.size.h as i32) - output_res.h as i32;
            geometry.origin.y -= offset as i32;
        }
        if geometry.origin.x < 0 {
            geometry.origin.x = 0;
        }
        if geometry.origin.y < 0 {
            geometry.origin.y = 0;
        }
        write_pixels(wlc_pixel_format::WLC_RGBA8888, geometry, &buffer);
    }
}
<commit_msg>Added render check, fixes segfaults<commit_after>//! Defines the renderable trait.
//! A renderable object holds the buffer that is written to wlc_pixel_write.
//! The buffer can only be modified by casting the type to a `Drawable`.

use rustwlc::{Geometry, WlcOutput};
use rustwlc::render::{write_pixels, wlc_pixel_format, calculate_stride};
use cairo::{self, Context, ImageSurface, Operator};
use super::draw::BaseDraw;

/// Something that can be rendered by wlc.
/// At minimum, it must store a buffer of bytes to write to wlc,
/// a geometry to tell wlc where to place the bytes,
/// and the `WlcOutput` that it will be rendered on.
pub trait Renderable {
    /// Makes a new `Renderable`
    ///
    /// Allowed to return `None` so that a needless allocation doesn't occur
    /// (e.g when the geometry is 0).
    fn new(geometry: Geometry, output: WlcOutput) -> Option<Self>
        where Self: :: std::marker::Sized;

    /// Gets the underlying `ImageSurface` used by the `Renderable` to render
    /// to wlc.
    ///
    /// Is mutable to ensure no other threads are touching the data.
    fn get_surface(&mut self) -> &mut ImageSurface;

    /// Gets the geometry for where the buffer should be rendered on the output.
    fn get_geometry(&self) -> Geometry;

    /// Sets the geometry for where the buffer should be render on the output.
    fn set_geometry(&mut self, geometry: Geometry);

    /// Gets the output that this will be rendered on.
    fn get_output(&self) -> WlcOutput;

    /// Reallocates the buffer based on the new geometry.
    ///
    /// Allowed to return `None` so that a needless allocation doesn't occur
    /// (e.g when the geometry is 0).
    fn reallocate_buffer(self, geometry: Geometry) -> Option<Self>
        where Self: ::std::marker::Sized;

    fn enable_cairo(mut self) -> Result<BaseDraw<Self>, cairo::Status>
        where Self: ::std::marker::Sized
    {
        let cairo = Context::new(&*self.get_surface());
        match cairo.status() {
            cairo::Status::Success => {},
            err => return Err(err)
        }
        cairo.set_operator(Operator::Source);
        match cairo.status() {
            cairo::Status::Success => {},
            err => return Err(err)
        }
        Ok(BaseDraw::new(self, cairo))
    }

    /// Renders the data buffer at the internal geometry.
    ///
    /// Automatically ensures that the buffer does not clip the sides
    fn render(&mut self) {
        let output_res = self.get_output().get_resolution()
            .expect("Output had no resolution");
        let mut geometry = self.get_geometry();
        let surface = self.get_surface();
        let buffer = surface.get_data()
            .expect("Could not get surface buffer");

        // If the buffer would clip the side, keep it within the bounds
        // This is done because wlc wraps if it goes beyond, which we don't
        // want for the borders.
        if geometry.origin.x + geometry.size.w as i32 > output_res.w as i32 {
            let offset = (geometry.origin.x + geometry.size.w as i32) - output_res.w as i32;
            geometry.origin.x -= offset as i32;
        }
        if geometry.origin.y + geometry.size.h as i32 > output_res.h as i32 {
            let offset = (geometry.origin.y + geometry.size.h as i32) - output_res.h as i32;
            geometry.origin.y -= offset as i32;
        }
        if geometry.origin.x < 0 {
            geometry.origin.x = 0;
        }
        if geometry.origin.y < 0 {
            geometry.origin.y = 0;
        }
        let stride = calculate_stride(geometry.size.w);
        if stride * geometry.size.h > buffer.len() as u32 {
            warn!("Buffer to big to draw! Not drawing");
            return
        }
        write_pixels(wlc_pixel_format::WLC_RGBA8888, geometry, &buffer);
    }
}
<|endoftext|>


<commit_before>//! # The Rust core allocation and collections library
//!
//! This library provides smart pointers and collections for managing
//! heap-allocated values.
//!
//! This library, like libcore, normally doesn’t need to be used directly
//! since its contents are re-exported in the [`std` crate](../std/index.html).
//! Crates that use the `#![no_std]` attribute however will typically
//! not depend on `std`, so they’d use this crate instead.
//!
//! ## Boxed values
//!
//! The [`Box`] type is a smart pointer type. There can only be one owner of a
//! [`Box`], and the owner can decide to mutate the contents, which live on the
//! heap.
//!
//! This type can be sent among threads efficiently as the size of a `Box` value
//! is the same as that of a pointer. Tree-like data structures are often built
//! with boxes because each node often has only one owner, the parent.
//!
//! ## Reference counted pointers
//!
//! The [`Rc`] type is a non-threadsafe reference-counted pointer type intended
//! for sharing memory within a thread. An [`Rc`] pointer wraps a type, `T`, and
//! only allows access to `&T`, a shared reference.
//!
//! This type is useful when inherited mutability (such as using [`Box`]) is too
//! constraining for an application, and is often paired with the [`Cell`] or
//! [`RefCell`] types in order to allow mutation.
//!
//! ## Atomically reference counted pointers
//!
//! The [`Arc`] type is the threadsafe equivalent of the [`Rc`] type. It
//! provides all the same functionality of [`Rc`], except it requires that the
//! contained type `T` is shareable. Additionally, [`Arc<T>`][`Arc`] is itself
//! sendable while [`Rc<T>`][`Rc`] is not.
//!
//! This type allows for shared access to the contained data, and is often
//! paired with synchronization primitives such as mutexes to allow mutation of
//! shared resources.
//!
//! ## Collections
//!
//! Implementations of the most common general purpose data structures are
//! defined in this library. They are re-exported through the
//! [standard collections library](../std/collections/index.html).
//!
//! ## Heap interfaces
//!
//! The [`alloc`](alloc/index.html) module defines the low-level interface to the
//! default global allocator. It is not compatible with the libc allocator API.
//!
//! [`Arc`]: sync
//! [`Box`]: boxed
//! [`Cell`]: core::cell
//! [`Rc`]: rc
//! [`RefCell`]: core::cell

// To run liballoc tests without x.py without ending up with two copies of liballoc, Miri needs to be
// able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>.
// rustc itself never sets the feature, so this line has no affect there.
#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))]
#![allow(unused_attributes)]
#![stable(feature = "alloc", since = "1.36.0")]
#![doc(
    html_playground_url = "https://play.rust-lang.org/",
    issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
    test(no_crate_inject, attr(allow(unused_variables), deny(warnings)))
)]
#![cfg_attr(
    not(bootstrap),
    doc(cfg_hide(
        not(test),
        not(any(test, bootstrap)),
        any(not(feature = "miri-test-libstd"), test, doctest),
        no_global_oom_handling,
        not(no_global_oom_handling),
        target_has_atomic = "ptr"
    ))
)]
#![no_std]
#![needs_allocator]
//
// Lints:
#![deny(unsafe_op_in_unsafe_fn)]
#![warn(deprecated_in_future)]
#![warn(missing_debug_implementations)]
#![warn(missing_docs)]
#![allow(explicit_outlives_requirements)]
//
// Library features:
#![feature(alloc_layout_extra)]
#![feature(allocator_api)]
#![feature(array_chunks)]
#![feature(array_methods)]
#![feature(array_windows)]
#![feature(async_stream)]
#![feature(coerce_unsized)]
#![cfg_attr(not(no_global_oom_handling), feature(const_btree_new))]
#![feature(const_cow_is_borrowed)]
#![feature(core_intrinsics)]
#![feature(dispatch_from_dyn)]
#![feature(exact_size_is_empty)]
#![feature(extend_one)]
#![feature(fmt_internals)]
#![feature(fn_traits)]
#![feature(inplace_iteration)]
#![feature(iter_advance_by)]
#![feature(iter_zip)]
#![feature(layout_for_ptr)]
#![feature(maybe_uninit_extra)]
#![feature(maybe_uninit_slice)]
#![cfg_attr(test, feature(new_uninit))]
#![feature(nonnull_slice_from_raw_parts)]
#![feature(pattern)]
#![feature(ptr_internals)]
#![feature(receiver_trait)]
#![feature(set_ptr_value)]
#![feature(slice_group_by)]
#![feature(slice_ptr_get)]
#![feature(slice_ptr_len)]
#![feature(slice_range)]
#![feature(str_internals)]
#![feature(trusted_len)]
#![feature(trusted_random_access)]
#![feature(try_trait_v2)]
#![feature(unicode_internals)]
#![feature(unsize)]
//
// Language features:
#![feature(allocator_internals)]
#![feature(allow_internal_unstable)]
#![feature(associated_type_bounds)]
#![feature(box_syntax)]
#![feature(cfg_sanitize)]
#![feature(cfg_target_has_atomic)]
#![feature(const_fn_trait_bound)]
#![feature(const_trait_impl)]
#![feature(destructuring_assignment)]
#![feature(dropck_eyepatch)]
#![feature(exclusive_range_pattern)]
#![feature(fundamental)]
#![cfg_attr(not(test), feature(generator_trait))]
#![feature(lang_items)]
#![feature(min_specialization)]
#![feature(negative_impls)]
#![feature(never_type)]
#![feature(nll)] // Not necessary, but here to test the `nll` feature.
#![feature(rustc_allow_const_fn_unstable)]
#![feature(rustc_attrs)]
#![feature(staged_api)]
#![cfg_attr(test, feature(test))]
#![feature(unboxed_closures)]
#![feature(unsized_fn_params)]
//
// Rustdoc features:
#![feature(doc_cfg)]
#![feature(doc_cfg_hide)]
// Technically, this is a bug in rustdoc: rustdoc sees the documentation on `#[lang = slice_alloc]`
// blocks is for `&[T]`, which also has documentation using this feature in `core`, and gets mad
// that the feature-gate isn't enabled. Ideally, it wouldn't check for the feature gate for docs
// from other crates, but since this can only appear for lang items, it doesn't seem worth fixing.
#![feature(intra_doc_pointers)]

// Allow testing this library
#[cfg(test)]
#[macro_use]
extern crate std;
#[cfg(test)]
extern crate test;

// Module with internal macros used by other modules (needs to be included before other modules).
#[macro_use]
mod macros;

// Heaps provided for low-level allocation strategies

pub mod alloc;

// Primitive types using the heaps above

// Need to conditionally define the mod from `boxed.rs` to avoid
// duplicating the lang-items when building in test cfg; but also need
// to allow code to have `use boxed::Box;` declarations.
#[cfg(not(test))]
pub mod boxed;
#[cfg(test)]
mod boxed {
    pub use std::boxed::Box;
}
pub mod borrow;
pub mod collections;
pub mod fmt;
pub mod raw_vec;
pub mod rc;
pub mod slice;
pub mod str;
pub mod string;
#[cfg(target_has_atomic = "ptr")]
pub mod sync;
#[cfg(all(not(no_global_oom_handling), target_has_atomic = "ptr"))]
pub mod task;
#[cfg(test)]
mod tests;
pub mod vec;

#[doc(hidden)]
#[unstable(feature = "liballoc_internals", issue = "none", reason = "implementation detail")]
pub mod __export {
    pub use core::format_args;
}
<commit_msg>Add feature to `alloc` so we can re-export.<commit_after>//! # The Rust core allocation and collections library
//!
//! This library provides smart pointers and collections for managing
//! heap-allocated values.
//!
//! This library, like libcore, normally doesn’t need to be used directly
//! since its contents are re-exported in the [`std` crate](../std/index.html).
//! Crates that use the `#![no_std]` attribute however will typically
//! not depend on `std`, so they’d use this crate instead.
//!
//! ## Boxed values
//!
//! The [`Box`] type is a smart pointer type. There can only be one owner of a
//! [`Box`], and the owner can decide to mutate the contents, which live on the
//! heap.
//!
//! This type can be sent among threads efficiently as the size of a `Box` value
//! is the same as that of a pointer. Tree-like data structures are often built
//! with boxes because each node often has only one owner, the parent.
//!
//! ## Reference counted pointers
//!
//! The [`Rc`] type is a non-threadsafe reference-counted pointer type intended
//! for sharing memory within a thread. An [`Rc`] pointer wraps a type, `T`, and
//! only allows access to `&T`, a shared reference.
//!
//! This type is useful when inherited mutability (such as using [`Box`]) is too
//! constraining for an application, and is often paired with the [`Cell`] or
//! [`RefCell`] types in order to allow mutation.
//!
//! ## Atomically reference counted pointers
//!
//! The [`Arc`] type is the threadsafe equivalent of the [`Rc`] type. It
//! provides all the same functionality of [`Rc`], except it requires that the
//! contained type `T` is shareable. Additionally, [`Arc<T>`][`Arc`] is itself
//! sendable while [`Rc<T>`][`Rc`] is not.
//!
//! This type allows for shared access to the contained data, and is often
//! paired with synchronization primitives such as mutexes to allow mutation of
//! shared resources.
//!
//! ## Collections
//!
//! Implementations of the most common general purpose data structures are
//! defined in this library. They are re-exported through the
//! [standard collections library](../std/collections/index.html).
//!
//! ## Heap interfaces
//!
//! The [`alloc`](alloc/index.html) module defines the low-level interface to the
//! default global allocator. It is not compatible with the libc allocator API.
//!
//! [`Arc`]: sync
//! [`Box`]: boxed
//! [`Cell`]: core::cell
//! [`Rc`]: rc
//! [`RefCell`]: core::cell

// To run liballoc tests without x.py without ending up with two copies of liballoc, Miri needs to be
// able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>.
// rustc itself never sets the feature, so this line has no affect there.
#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))]
#![allow(unused_attributes)]
#![stable(feature = "alloc", since = "1.36.0")]
#![doc(
    html_playground_url = "https://play.rust-lang.org/",
    issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
    test(no_crate_inject, attr(allow(unused_variables), deny(warnings)))
)]
#![cfg_attr(
    not(bootstrap),
    doc(cfg_hide(
        not(test),
        not(any(test, bootstrap)),
        any(not(feature = "miri-test-libstd"), test, doctest),
        no_global_oom_handling,
        not(no_global_oom_handling),
        target_has_atomic = "ptr"
    ))
)]
#![no_std]
#![needs_allocator]
//
// Lints:
#![deny(unsafe_op_in_unsafe_fn)]
#![warn(deprecated_in_future)]
#![warn(missing_debug_implementations)]
#![warn(missing_docs)]
#![allow(explicit_outlives_requirements)]
//
// Library features:
#![feature(alloc_layout_extra)]
#![feature(allocator_api)]
#![feature(array_chunks)]
#![feature(array_methods)]
#![feature(array_windows)]
#![feature(async_stream)]
#![feature(coerce_unsized)]
#![cfg_attr(not(no_global_oom_handling), feature(const_btree_new))]
#![feature(const_cow_is_borrowed)]
#![feature(core_intrinsics)]
#![feature(dispatch_from_dyn)]
#![feature(exact_size_is_empty)]
#![feature(extend_one)]
#![feature(fmt_internals)]
#![feature(fn_traits)]
#![feature(inherent_ascii_escape)]
#![feature(inplace_iteration)]
#![feature(iter_advance_by)]
#![feature(iter_zip)]
#![feature(layout_for_ptr)]
#![feature(maybe_uninit_extra)]
#![feature(maybe_uninit_slice)]
#![cfg_attr(test, feature(new_uninit))]
#![feature(nonnull_slice_from_raw_parts)]
#![feature(pattern)]
#![feature(ptr_internals)]
#![feature(receiver_trait)]
#![feature(set_ptr_value)]
#![feature(slice_group_by)]
#![feature(slice_ptr_get)]
#![feature(slice_ptr_len)]
#![feature(slice_range)]
#![feature(str_internals)]
#![feature(trusted_len)]
#![feature(trusted_random_access)]
#![feature(try_trait_v2)]
#![feature(unicode_internals)]
#![feature(unsize)]
//
// Language features:
#![feature(allocator_internals)]
#![feature(allow_internal_unstable)]
#![feature(associated_type_bounds)]
#![feature(box_syntax)]
#![feature(cfg_sanitize)]
#![feature(cfg_target_has_atomic)]
#![feature(const_fn_trait_bound)]
#![feature(const_trait_impl)]
#![feature(destructuring_assignment)]
#![feature(dropck_eyepatch)]
#![feature(exclusive_range_pattern)]
#![feature(fundamental)]
#![cfg_attr(not(test), feature(generator_trait))]
#![feature(lang_items)]
#![feature(min_specialization)]
#![feature(negative_impls)]
#![feature(never_type)]
#![feature(nll)] // Not necessary, but here to test the `nll` feature.
#![feature(rustc_allow_const_fn_unstable)]
#![feature(rustc_attrs)]
#![feature(staged_api)]
#![cfg_attr(test, feature(test))]
#![feature(unboxed_closures)]
#![feature(unsized_fn_params)]
//
// Rustdoc features:
#![feature(doc_cfg)]
#![feature(doc_cfg_hide)]
// Technically, this is a bug in rustdoc: rustdoc sees the documentation on `#[lang = slice_alloc]`
// blocks is for `&[T]`, which also has documentation using this feature in `core`, and gets mad
// that the feature-gate isn't enabled. Ideally, it wouldn't check for the feature gate for docs
// from other crates, but since this can only appear for lang items, it doesn't seem worth fixing.
#![feature(intra_doc_pointers)]

// Allow testing this library
#[cfg(test)]
#[macro_use]
extern crate std;
#[cfg(test)]
extern crate test;

// Module with internal macros used by other modules (needs to be included before other modules).
#[macro_use]
mod macros;

// Heaps provided for low-level allocation strategies

pub mod alloc;

// Primitive types using the heaps above

// Need to conditionally define the mod from `boxed.rs` to avoid
// duplicating the lang-items when building in test cfg; but also need
// to allow code to have `use boxed::Box;` declarations.
#[cfg(not(test))]
pub mod boxed;
#[cfg(test)]
mod boxed {
    pub use std::boxed::Box;
}
pub mod borrow;
pub mod collections;
pub mod fmt;
pub mod raw_vec;
pub mod rc;
pub mod slice;
pub mod str;
pub mod string;
#[cfg(target_has_atomic = "ptr")]
pub mod sync;
#[cfg(all(not(no_global_oom_handling), target_has_atomic = "ptr"))]
pub mod task;
#[cfg(test)]
mod tests;
pub mod vec;

#[doc(hidden)]
#[unstable(feature = "liballoc_internals", issue = "none", reason = "implementation detail")]
pub mod __export {
    pub use core::format_args;
}
<|endoftext|>


<commit_before>use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer};
use std::fmt;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};

/// The Weight is an object used to control the elasticsearch sort.
///
/// A Weight's value must be a float between 0 and 1.
///
/// Since we need interior mutability for the weight and we need it to be std::sync,
/// it emulates an AtomicFloat.
/// The main idea is to store the value in an AtomicUSize and convert it to a float with the
/// `get_val` method.
///
/// The weight needs to be normalized before used.
/// The normalization works by giving the maximum value to the normalize method,
/// this way we can compute a weight between 0 and 1.
#[derive(Debug)]
pub struct Weight {
    val: AtomicUsize,
    normalized: AtomicBool,
}

// the max value is u32 to be able to keep the prevision while converting it to f64
const MAX_VAL: f64 = u32::max_value() as f64;

impl Weight {
    // Note we limit val to a u32 even if we store a usize because we'll loose precision while converting it to float
    pub fn new(val: u32) -> Weight {
        Weight {
            val: AtomicUsize::new(val as usize),
            normalized: AtomicBool::new(false),
        }
    }

    fn from_normalized_float(val: f64) -> Weight {
        debug_assert!(0f64 <= val);
        debug_assert!(val <= 1f64);
        Weight {
            val: AtomicUsize::new((val * MAX_VAL) as usize),
            normalized: AtomicBool::new(true),
        }
    }

    /// get the float value of the weight.
    /// If the weight has not yet been normlized returns `None` else returns the float
    pub fn value(&self) -> Option<f64> {
        match self.normalized.load(Ordering::Relaxed) {
            true => Some(self.unnormalized_value() as f64 / MAX_VAL),
            false => None,
        }
    }

    pub fn add(&self, val: u32) {
        self.val.fetch_add(val as usize, Ordering::Relaxed);
    }

    pub fn unnormalized_value(&self) -> u32 {
        // we can read the atomic without any ordering constraints as in practice
        // we don't change the value in multi thread context
        self.val.load(Ordering::Relaxed) as u32
    }

    pub fn normalize(&self, max_value: u32) {
        let mut val: f64 = self.val.load(Ordering::Relaxed) as f64 / max_value as f64;
        debug_assert!(0f64 <= val);
        debug_assert!(val <= 1f64);
        val *= MAX_VAL;
        self.val.store(val as usize, Ordering::Relaxed);
        self.normalized.store(true, Ordering::Relaxed);
    }
}

impl Clone for Weight {
    fn clone(&self) -> Weight {
        Weight {
            val: AtomicUsize::new(self.val.load(Ordering::Relaxed)),
            normalized: AtomicBool::new(self.normalized.load(Ordering::Relaxed)),
        }
    }
}

impl Serialize for Weight {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        // unwrap() here to ensure that the weight is always normalized before serialization
        serializer.serialize_f64(self.value().unwrap())
    }
}

impl Default for Weight {
    fn default() -> Self {
        Weight::new(0u32)
    }
}

impl<'de> Deserialize<'de> for Weight {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct Visitor;

        impl<'de> ::serde::de::Visitor<'de> for Visitor {
            type Value = Weight;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("float representing a weight")
            }

            fn visit_f64<E>(self, value: f64) -> Result<Weight, E>
            where
                E: ::serde::de::Error,
            {
                Ok(Weight::from_normalized_float(value))
            }
        }

        // Deserialize the weight as f64
        deserializer.deserialize_f64(Visitor)
    }
}

#[cfg(test)]
mod tests {
    use super::Weight;
    extern crate serde_json;

    #[test]
    pub fn test_basic_uses() {
        let weight = Weight::new(12u32);

        assert!(weight.value().is_none());
    }

    #[test]
    pub fn test_zero() {
        let weight = Weight::new(0u32);
        weight.normalize(12u32);

        abs_diff_eq!(0.0f64, weight.value().unwrap());
    }

    #[test]
    pub fn test_max_val() {
        let weight = Weight::new(12u32);
        weight.normalize(12u32);

        abs_diff_eq!(1.0f64, weight.value().unwrap());
    }

    proptest! {

        #[test]
        fn test_normalize_for_any_value(val in 0u32..1000000u32) {
            let weight = Weight::new(val);
            weight.normalize(1000000u32);
            abs_diff_eq!(weight.value().unwrap(), val as f64 / 1000000f64);
        }
    }

    #[test]
    pub fn test_normalize() {
        let weight = Weight::new(12u32);
        weight.normalize(24u32);

        abs_diff_eq!(0.5f64, weight.value().unwrap());
    }

    #[test]
    pub fn test_weight_serialization() {
        let weight = Weight::new(12u32);
        weight.normalize(24u32);

        let as_json = serde_json::to_string(&weight).unwrap();
        let from_json: Weight = serde_json::from_str(&as_json).unwrap();
        abs_diff_eq!(0.5f64, from_json.value().unwrap());
    }
}
<commit_msg>enforce atomic operation<commit_after>use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer};
use std::fmt;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};

/// The Weight is an object used to control the elasticsearch sort.
///
/// A Weight's value must be a float between 0 and 1.
///
/// Since we need interior mutability for the weight and we need it to be std::sync,
/// it emulates an AtomicFloat.
/// The main idea is to store the value in an AtomicUSize and convert it to a float with the
/// `get_val` method.
///
/// The weight needs to be normalized before used.
/// The normalization works by giving the maximum value to the normalize method,
/// this way we can compute a weight between 0 and 1.
#[derive(Debug)]
pub struct Weight {
    val: AtomicUsize,
    normalized: AtomicBool,
}

// the max value is u32 to be able to keep the prevision while converting it to f64
const MAX_VAL: f64 = u32::max_value() as f64;

impl Weight {
    // Note we limit val to a u32 even if we store a usize because we'll loose precision while converting it to float
    pub fn new(val: u32) -> Weight {
        Weight {
            val: AtomicUsize::new(val as usize),
            normalized: AtomicBool::new(false),
        }
    }

    fn from_normalized_float(val: f64) -> Weight {
        debug_assert!(0f64 <= val);
        debug_assert!(val <= 1f64);
        Weight {
            val: AtomicUsize::new((val * MAX_VAL) as usize),
            normalized: AtomicBool::new(true),
        }
    }

    /// get the float value of the weight.
    /// If the weight has not yet been normlized returns `None` else returns the float
    pub fn value(&self) -> Option<f64> {
        match self.normalized.load(Ordering::Relaxed) {
            true => Some(self.unnormalized_value() as f64 / MAX_VAL),
            false => None,
        }
    }

    pub fn add(&self, val: u32) {
        self.val.fetch_add(val as usize, Ordering::Relaxed);
    }

    pub fn unnormalized_value(&self) -> u32 {
        // we can read the atomic without any ordering constraints as in practice
        // we don't change the value in multi thread context
        self.val.load(Ordering::Relaxed) as u32
    }

    /// normalize the internal value so that once divided by MAX_VAL
    /// it spans between [0, 1]
    /// the `loop` is here to enfore the contraints on the atomicity
    pub fn normalize(&self, max_value: u32) {
        let mut old = self.val.load(Ordering::Relaxed);
        loop {
            let mut new = old as f64 / max_value as f64;
            debug_assert!(0f64 <= new);
            debug_assert!(new <= 1f64);
            new *= MAX_VAL;

            let current = self
                .val
                .compare_and_swap(old, new as usize, Ordering::Relaxed);
            if current == old {
                self.normalized.store(true, Ordering::Relaxed);
                break;
            }
            old = current;
        }
    }
}

impl Clone for Weight {
    fn clone(&self) -> Weight {
        Weight {
            val: AtomicUsize::new(self.val.load(Ordering::Relaxed)),
            normalized: AtomicBool::new(self.normalized.load(Ordering::Relaxed)),
        }
    }
}

impl Serialize for Weight {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        // unwrap() here to ensure that the weight is always normalized before serialization
        serializer.serialize_f64(self.value().unwrap())
    }
}

impl Default for Weight {
    fn default() -> Self {
        Weight::new(0u32)
    }
}

impl<'de> Deserialize<'de> for Weight {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct Visitor;

        impl<'de> ::serde::de::Visitor<'de> for Visitor {
            type Value = Weight;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("float representing a weight")
            }

            fn visit_f64<E>(self, value: f64) -> Result<Weight, E>
            where
                E: ::serde::de::Error,
            {
                Ok(Weight::from_normalized_float(value))
            }
        }

        // Deserialize the weight as f64
        deserializer.deserialize_f64(Visitor)
    }
}

#[cfg(test)]
mod tests {
    use super::Weight;
    extern crate serde_json;

    #[test]
    pub fn test_basic_uses() {
        let weight = Weight::new(12u32);

        assert!(weight.value().is_none());
    }

    #[test]
    pub fn test_zero() {
        let weight = Weight::new(0u32);
        weight.normalize(12u32);

        abs_diff_eq!(0.0f64, weight.value().unwrap());
    }

    #[test]
    pub fn test_max_val() {
        let weight = Weight::new(12u32);
        weight.normalize(12u32);

        abs_diff_eq!(1.0f64, weight.value().unwrap());
    }

    proptest! {

        #[test]
        fn test_normalize_for_any_value(val in 0u32..1000000u32) {
            let weight = Weight::new(val);
            weight.normalize(1000000u32);
            abs_diff_eq!(weight.value().unwrap(), val as f64 / 1000000f64);
        }
    }

    #[test]
    pub fn test_normalize() {
        let weight = Weight::new(12u32);
        weight.normalize(24u32);

        abs_diff_eq!(0.5f64, weight.value().unwrap());
    }

    #[test]
    pub fn test_weight_serialization() {
        let weight = Weight::new(12u32);
        weight.normalize(24u32);

        let as_json = serde_json::to_string(&weight).unwrap();
        let from_json: Weight = serde_json::from_str(&as_json).unwrap();
        abs_diff_eq!(0.5f64, from_json.value().unwrap());
    }
}
<|endoftext|>


<commit_before>#![feature(plugin, step_by)]
#![plugin(clippy)]

use std::collections::*;

#[deny(clippy)]
fn for_loop_over_option_and_result() {
    let option = Some(1);
    let result = option.ok_or("x not found");
    let v = vec![0,1,2];

    // check FOR_LOOP_OVER_OPTION lint

    for x in option {
        //~^ ERROR for loop over `option`, which is an `Option`.
        //~| HELP consider replacing `for x in option` with `if let Some(x) = option`
        println!("{}", x);
    }

    // check FOR_LOOP_OVER_RESULT lint

    for x in result {
        //~^ ERROR for loop over `result`, which is a `Result`.
        //~| HELP consider replacing `for x in result` with `if let Ok(x) = result`
        println!("{}", x);
    }

    for x in option.ok_or("x not found") {
        //~^ ERROR for loop over `option.ok_or("x not found")`, which is a `Result`.
        //~| HELP consider replacing `for x in option.ok_or("x not found")` with `if let Ok(x) = option.ok_or("x not found")`
        println!("{}", x);
    }

    // make sure LOOP_OVER_NEXT lint takes precedence when next() is the last call in the chain

    for x in v.iter().next() {
        //~^ ERROR you are iterating over `Iterator::next()` which is an Option
        println!("{}", x);
    }

    // make sure we lint when next() is not the last call in the chain

    for x in v.iter().next().and(Some(0)) {
        //~^ ERROR for loop over `v.iter().next().and(Some(0))`, which is an `Option`
        //~| HELP consider replacing `for x in v.iter().next().and(Some(0))` with `if let Some(x) = v.iter().next().and(Some(0))`
        println!("{}", x);
    }

    for x in v.iter().next().ok_or("x not found") {
        //~^ ERROR for loop over `v.iter().next().ok_or("x not found")`, which is a `Result`
        //~| HELP consider replacing `for x in v.iter().next().ok_or("x not found")` with `if let Ok(x) = v.iter().next().ok_or("x not found")`
        println!("{}", x);
    }

    // check for false positives

    // for loop false positive
    for x in v {
        println!("{}", x);
    }

    // while let false positive for Option
    while let Some(x) = option {
        println!("{}", x);
        break;
    }

    // while let false positive for Result
    while let Ok(x) = result {
        println!("{}", x);
        break;
    }
}

struct Unrelated(Vec<u8>);
impl Unrelated {
    fn next(&self) -> std::slice::Iter<u8> {
        self.0.iter()
    }

    fn iter(&self) -> std::slice::Iter<u8> {
        self.0.iter()
    }
}

#[deny(needless_range_loop, explicit_iter_loop, iter_next_loop, reverse_range_loop, explicit_counter_loop)]
#[deny(unused_collect)]
#[allow(linkedlist, shadow_unrelated, unnecessary_mut_passed, cyclomatic_complexity)]
fn main() {
    const MAX_LEN: usize = 42;

    let mut vec = vec![1, 2, 3, 4];
    let vec2 = vec![1, 2, 3, 4];
    for i in 0..vec.len() {
        //~^ ERROR `i` is only used to index `vec`. Consider using `for item in &vec`
        println!("{}", vec[i]);
    }
    for i in 0..vec.len() {
        //~^ ERROR `i` is used to index `vec`. Consider using `for (i, item) in vec.iter().enumerate()`
        println!("{} {}", vec[i], i);
    }
    for i in 0..vec.len() {      // not an error, indexing more than one variable
        println!("{} {}", vec[i], vec2[i]);
    }

    for i in 0..vec.len() {
        //~^ ERROR `i` is only used to index `vec2`. Consider using `for item in vec2.iter().take(vec.len())`
        println!("{}", vec2[i]);
    }

    for i in 5..vec.len() {
        //~^ ERROR `i` is only used to index `vec`. Consider using `for item in vec.iter().skip(5)`
        println!("{}", vec[i]);
    }

    for i in 0..MAX_LEN {
        //~^ ERROR `i` is only used to index `vec`. Consider using `for item in vec.iter().take(MAX_LEN)`
        println!("{}", vec[i]);
    }

    for i in 5..10 {
        //~^ ERROR `i` is only used to index `vec`. Consider using `for item in vec.iter().take(10).skip(5)`
        println!("{}", vec[i]);
    }

    for i in 5..vec.len() {
        //~^ ERROR `i` is used to index `vec`. Consider using `for (i, item) in vec.iter().enumerate().skip(5)`
        println!("{} {}", vec[i], i);
    }

    for i in 5..10 {
        //~^ ERROR `i` is used to index `vec`. Consider using `for (i, item) in vec.iter().enumerate().take(10).skip(5)`
        println!("{} {}", vec[i], i);
    }

    for i in 10..0 {
        //~^ERROR this range is empty so this for loop will never run
        //~|HELP consider
        //~|SUGGESTION (0..10).rev()
        println!("{}", i);
    }

    for i in MAX_LEN..0 { //~ERROR this range is empty so this for loop will never run
        //~|HELP consider
        //~|SUGGESTION (0..MAX_LEN).rev()
        println!("{}", i);
    }

    for i in 5..5 { //~ERROR this range is empty so this for loop will never run
        println!("{}", i);
    }

    for i in 0..10 { // not an error, the start index is less than the end index
        println!("{}", i);
    }

    for i in -10..0 { // not an error
        println!("{}", i);
    }

    for i in (10..0).rev() { // not an error, this is an established idiom for looping backwards on a range
        println!("{}", i);
    }

    for i in (10..0).map(|x| x * 2) { // not an error, it can't be known what arbitrary methods do to a range
        println!("{}", i);
    }

    // testing that the empty range lint folds constants
    for i in 10..5+4 { //~ERROR this range is empty so this for loop will never run
        println!("{}", i);
    }

    for i in (5+2)..(3-1) { //~ERROR this range is empty so this for loop will never run
        println!("{}", i);
    }

    for i in (5+2)..(8-1) { //~ERROR this range is empty so this for loop will never run
        println!("{}", i);
    }

    for i in (2*2)..(2*3) { // no error, 4..6 is fine
        println!("{}", i);
    }

    for i in (10..8).step_by(-1) {
        println!("{}", i);
    }

    let x = 42;
    for i in x..10 { // no error, not constant-foldable
        println!("{}", i);
    }

    // See #601
    for i in 0..10 { // no error, id_col does not exist outside the loop
        let mut id_col = vec![0f64; 10];
        id_col[i] = 1f64;
    }

    /*
    for i in (10..0).map(|x| x * 2) {
        println!("{}", i);
    }*/

    for _v in vec.iter() { } //~ERROR it is more idiomatic to loop over `&vec`
    for _v in vec.iter_mut() { } //~ERROR it is more idiomatic to loop over `&mut vec`

    for _v in &vec { } // these are fine
    for _v in &mut vec { } // these are fine

    for _v in [1, 2, 3].iter() { } //~ERROR it is more idiomatic to loop over `&[
    for _v in (&mut [1, 2, 3]).iter() { } // no error
    for _v in [0; 32].iter() {} //~ERROR it is more idiomatic to loop over `&[
    for _v in [0; 33].iter() {} // no error
    let ll: LinkedList<()> = LinkedList::new();
    for _v in ll.iter() { } //~ERROR it is more idiomatic to loop over `&ll`
    let vd: VecDeque<()> = VecDeque::new();
    for _v in vd.iter() { } //~ERROR it is more idiomatic to loop over `&vd`
    let bh: BinaryHeap<()> = BinaryHeap::new();
    for _v in bh.iter() { } //~ERROR it is more idiomatic to loop over `&bh`
    let hm: HashMap<(), ()> = HashMap::new();
    for _v in hm.iter() { } //~ERROR it is more idiomatic to loop over `&hm`
    let bt: BTreeMap<(), ()> = BTreeMap::new();
    for _v in bt.iter() { } //~ERROR it is more idiomatic to loop over `&bt`
    let hs: HashSet<()> = HashSet::new();
    for _v in hs.iter() { } //~ERROR it is more idiomatic to loop over `&hs`
    let bs: BTreeSet<()> = BTreeSet::new();
    for _v in bs.iter() { } //~ERROR it is more idiomatic to loop over `&bs`

    for _v in vec.iter().next() { } //~ERROR you are iterating over `Iterator::next()`

    let u = Unrelated(vec![]);
    for _v in u.next() { } // no error
    for _v in u.iter() { } // no error

    let mut out = vec![];
    vec.iter().map(|x| out.push(x)).collect::<Vec<_>>(); //~ERROR you are collect()ing an iterator
    let _y = vec.iter().map(|x| out.push(x)).collect::<Vec<_>>(); // this is fine

    // Loop with explicit counter variable
    let mut _index = 0;
    for _v in &vec { _index += 1 } //~ERROR the variable `_index` is used as a loop counter

    let mut _index = 1;
    _index = 0;
    for _v in &vec { _index += 1 } //~ERROR the variable `_index` is used as a loop counter

    // Potential false positives
    let mut _index = 0;
    _index = 1;
    for _v in &vec { _index += 1 }

    let mut _index = 0;
    _index += 1;
    for _v in &vec { _index += 1 }

    let mut _index = 0;
    if true { _index = 1 }
    for _v in &vec { _index += 1 }

    let mut _index = 0;
    let mut _index = 1;
    for _v in &vec { _index += 1 }

    let mut _index = 0;
    for _v in &vec { _index += 1; _index += 1 }

    let mut _index = 0;
    for _v in &vec { _index *= 2; _index += 1 }

    let mut _index = 0;
    for _v in &vec { _index = 1; _index += 1 }

    let mut _index = 0;

    for _v in &vec { let mut _index = 0; _index += 1 }

    let mut _index = 0;
    for _v in &vec { _index += 1; _index = 0; }

    let mut _index = 0;
    for _v in &vec { for _x in 0..1 { _index += 1; }; _index += 1 }

    let mut _index = 0;
    for x in &vec { if *x == 1 { _index += 1 } }

    let mut _index = 0;
    if true { _index = 1 };
    for _v in &vec { _index += 1 }

    let mut _index = 1;
    if false { _index = 0 };
    for _v in &vec { _index += 1 }

    let mut index = 0;
    { let mut _x = &mut index; }
    for _v in &vec { _index += 1 }

    let mut index = 0;
    for _v in &vec { index += 1 }
    println!("index: {}", index);

    for_loop_over_option_and_result();

    let m : HashMap<u64, u64> = HashMap::new();
    for (_, v) in &m {
        //~^ you seem to want to iterate on a map's values
        //~| HELP use the corresponding method
        //~| SUGGESTION for v in &m.values()
        let _v = v;
    }

    let mut m : HashMap<u64, u64> = HashMap::new();
    for (_, v) in &mut m {
        // Ok, there is no values_mut method or equivalent
        let _v = v;
    }

    let rm = &m;
    for (k, _value) in rm {
        //~^ you seem to want to iterate on a map's keys
        //~| HELP use the corresponding method
        //~| SUGGESTION for k in rm.keys()
        let _k = k;
    }

    test_for_kv_map();
}

#[allow(used_underscore_binding)]
fn test_for_kv_map() {
    let m : HashMap<u64, u64> = HashMap::new();

    // No error, _value is actually used
    for (k, _value) in &m {
        let _ = _value;
        let _k = k;
    }
}
<commit_msg>Remove bad test in for_loop<commit_after>#![feature(plugin, step_by)]
#![plugin(clippy)]

use std::collections::*;

#[deny(clippy)]
fn for_loop_over_option_and_result() {
    let option = Some(1);
    let result = option.ok_or("x not found");
    let v = vec![0,1,2];

    // check FOR_LOOP_OVER_OPTION lint

    for x in option {
        //~^ ERROR for loop over `option`, which is an `Option`.
        //~| HELP consider replacing `for x in option` with `if let Some(x) = option`
        println!("{}", x);
    }

    // check FOR_LOOP_OVER_RESULT lint

    for x in result {
        //~^ ERROR for loop over `result`, which is a `Result`.
        //~| HELP consider replacing `for x in result` with `if let Ok(x) = result`
        println!("{}", x);
    }

    for x in option.ok_or("x not found") {
        //~^ ERROR for loop over `option.ok_or("x not found")`, which is a `Result`.
        //~| HELP consider replacing `for x in option.ok_or("x not found")` with `if let Ok(x) = option.ok_or("x not found")`
        println!("{}", x);
    }

    // make sure LOOP_OVER_NEXT lint takes precedence when next() is the last call in the chain

    for x in v.iter().next() {
        //~^ ERROR you are iterating over `Iterator::next()` which is an Option
        println!("{}", x);
    }

    // make sure we lint when next() is not the last call in the chain

    for x in v.iter().next().and(Some(0)) {
        //~^ ERROR for loop over `v.iter().next().and(Some(0))`, which is an `Option`
        //~| HELP consider replacing `for x in v.iter().next().and(Some(0))` with `if let Some(x) = v.iter().next().and(Some(0))`
        println!("{}", x);
    }

    for x in v.iter().next().ok_or("x not found") {
        //~^ ERROR for loop over `v.iter().next().ok_or("x not found")`, which is a `Result`
        //~| HELP consider replacing `for x in v.iter().next().ok_or("x not found")` with `if let Ok(x) = v.iter().next().ok_or("x not found")`
        println!("{}", x);
    }

    // check for false positives

    // for loop false positive
    for x in v {
        println!("{}", x);
    }

    // while let false positive for Option
    while let Some(x) = option {
        println!("{}", x);
        break;
    }

    // while let false positive for Result
    while let Ok(x) = result {
        println!("{}", x);
        break;
    }
}

struct Unrelated(Vec<u8>);
impl Unrelated {
    fn next(&self) -> std::slice::Iter<u8> {
        self.0.iter()
    }

    fn iter(&self) -> std::slice::Iter<u8> {
        self.0.iter()
    }
}

#[deny(needless_range_loop, explicit_iter_loop, iter_next_loop, reverse_range_loop, explicit_counter_loop)]
#[deny(unused_collect)]
#[allow(linkedlist, shadow_unrelated, unnecessary_mut_passed, cyclomatic_complexity)]
fn main() {
    const MAX_LEN: usize = 42;

    let mut vec = vec![1, 2, 3, 4];
    let vec2 = vec![1, 2, 3, 4];
    for i in 0..vec.len() {
        //~^ ERROR `i` is only used to index `vec`. Consider using `for item in &vec`
        println!("{}", vec[i]);
    }
    for i in 0..vec.len() {
        //~^ ERROR `i` is used to index `vec`. Consider using `for (i, item) in vec.iter().enumerate()`
        println!("{} {}", vec[i], i);
    }
    for i in 0..vec.len() {      // not an error, indexing more than one variable
        println!("{} {}", vec[i], vec2[i]);
    }

    for i in 0..vec.len() {
        //~^ ERROR `i` is only used to index `vec2`. Consider using `for item in vec2.iter().take(vec.len())`
        println!("{}", vec2[i]);
    }

    for i in 5..vec.len() {
        //~^ ERROR `i` is only used to index `vec`. Consider using `for item in vec.iter().skip(5)`
        println!("{}", vec[i]);
    }

    for i in 0..MAX_LEN {
        //~^ ERROR `i` is only used to index `vec`. Consider using `for item in vec.iter().take(MAX_LEN)`
        println!("{}", vec[i]);
    }

    for i in 5..10 {
        //~^ ERROR `i` is only used to index `vec`. Consider using `for item in vec.iter().take(10).skip(5)`
        println!("{}", vec[i]);
    }

    for i in 5..vec.len() {
        //~^ ERROR `i` is used to index `vec`. Consider using `for (i, item) in vec.iter().enumerate().skip(5)`
        println!("{} {}", vec[i], i);
    }

    for i in 5..10 {
        //~^ ERROR `i` is used to index `vec`. Consider using `for (i, item) in vec.iter().enumerate().take(10).skip(5)`
        println!("{} {}", vec[i], i);
    }

    for i in 10..0 {
        //~^ERROR this range is empty so this for loop will never run
        //~|HELP consider
        //~|SUGGESTION (0..10).rev()
        println!("{}", i);
    }

    for i in MAX_LEN..0 { //~ERROR this range is empty so this for loop will never run
        //~|HELP consider
        //~|SUGGESTION (0..MAX_LEN).rev()
        println!("{}", i);
    }

    for i in 5..5 { //~ERROR this range is empty so this for loop will never run
        println!("{}", i);
    }

    for i in 0..10 { // not an error, the start index is less than the end index
        println!("{}", i);
    }

    for i in -10..0 { // not an error
        println!("{}", i);
    }

    for i in (10..0).map(|x| x * 2) { // not an error, it can't be known what arbitrary methods do to a range
        println!("{}", i);
    }

    // testing that the empty range lint folds constants
    for i in 10..5+4 { //~ERROR this range is empty so this for loop will never run
        println!("{}", i);
    }

    for i in (5+2)..(3-1) { //~ERROR this range is empty so this for loop will never run
        println!("{}", i);
    }

    for i in (5+2)..(8-1) { //~ERROR this range is empty so this for loop will never run
        println!("{}", i);
    }

    for i in (2*2)..(2*3) { // no error, 4..6 is fine
        println!("{}", i);
    }

    for i in (10..8).step_by(-1) {
        println!("{}", i);
    }

    let x = 42;
    for i in x..10 { // no error, not constant-foldable
        println!("{}", i);
    }

    // See #601
    for i in 0..10 { // no error, id_col does not exist outside the loop
        let mut id_col = vec![0f64; 10];
        id_col[i] = 1f64;
    }

    /*
    for i in (10..0).map(|x| x * 2) {
        println!("{}", i);
    }*/

    for _v in vec.iter() { } //~ERROR it is more idiomatic to loop over `&vec`
    for _v in vec.iter_mut() { } //~ERROR it is more idiomatic to loop over `&mut vec`

    for _v in &vec { } // these are fine
    for _v in &mut vec { } // these are fine

    for _v in [1, 2, 3].iter() { } //~ERROR it is more idiomatic to loop over `&[
    for _v in (&mut [1, 2, 3]).iter() { } // no error
    for _v in [0; 32].iter() {} //~ERROR it is more idiomatic to loop over `&[
    for _v in [0; 33].iter() {} // no error
    let ll: LinkedList<()> = LinkedList::new();
    for _v in ll.iter() { } //~ERROR it is more idiomatic to loop over `&ll`
    let vd: VecDeque<()> = VecDeque::new();
    for _v in vd.iter() { } //~ERROR it is more idiomatic to loop over `&vd`
    let bh: BinaryHeap<()> = BinaryHeap::new();
    for _v in bh.iter() { } //~ERROR it is more idiomatic to loop over `&bh`
    let hm: HashMap<(), ()> = HashMap::new();
    for _v in hm.iter() { } //~ERROR it is more idiomatic to loop over `&hm`
    let bt: BTreeMap<(), ()> = BTreeMap::new();
    for _v in bt.iter() { } //~ERROR it is more idiomatic to loop over `&bt`
    let hs: HashSet<()> = HashSet::new();
    for _v in hs.iter() { } //~ERROR it is more idiomatic to loop over `&hs`
    let bs: BTreeSet<()> = BTreeSet::new();
    for _v in bs.iter() { } //~ERROR it is more idiomatic to loop over `&bs`

    for _v in vec.iter().next() { } //~ERROR you are iterating over `Iterator::next()`

    let u = Unrelated(vec![]);
    for _v in u.next() { } // no error
    for _v in u.iter() { } // no error

    let mut out = vec![];
    vec.iter().map(|x| out.push(x)).collect::<Vec<_>>(); //~ERROR you are collect()ing an iterator
    let _y = vec.iter().map(|x| out.push(x)).collect::<Vec<_>>(); // this is fine

    // Loop with explicit counter variable
    let mut _index = 0;
    for _v in &vec { _index += 1 } //~ERROR the variable `_index` is used as a loop counter

    let mut _index = 1;
    _index = 0;
    for _v in &vec { _index += 1 } //~ERROR the variable `_index` is used as a loop counter

    // Potential false positives
    let mut _index = 0;
    _index = 1;
    for _v in &vec { _index += 1 }

    let mut _index = 0;
    _index += 1;
    for _v in &vec { _index += 1 }

    let mut _index = 0;
    if true { _index = 1 }
    for _v in &vec { _index += 1 }

    let mut _index = 0;
    let mut _index = 1;
    for _v in &vec { _index += 1 }

    let mut _index = 0;
    for _v in &vec { _index += 1; _index += 1 }

    let mut _index = 0;
    for _v in &vec { _index *= 2; _index += 1 }

    let mut _index = 0;
    for _v in &vec { _index = 1; _index += 1 }

    let mut _index = 0;

    for _v in &vec { let mut _index = 0; _index += 1 }

    let mut _index = 0;
    for _v in &vec { _index += 1; _index = 0; }

    let mut _index = 0;
    for _v in &vec { for _x in 0..1 { _index += 1; }; _index += 1 }

    let mut _index = 0;
    for x in &vec { if *x == 1 { _index += 1 } }

    let mut _index = 0;
    if true { _index = 1 };
    for _v in &vec { _index += 1 }

    let mut _index = 1;
    if false { _index = 0 };
    for _v in &vec { _index += 1 }

    let mut index = 0;
    { let mut _x = &mut index; }
    for _v in &vec { _index += 1 }

    let mut index = 0;
    for _v in &vec { index += 1 }
    println!("index: {}", index);

    for_loop_over_option_and_result();

    let m : HashMap<u64, u64> = HashMap::new();
    for (_, v) in &m {
        //~^ you seem to want to iterate on a map's values
        //~| HELP use the corresponding method
        //~| SUGGESTION for v in &m.values()
        let _v = v;
    }

    let mut m : HashMap<u64, u64> = HashMap::new();
    for (_, v) in &mut m {
        // Ok, there is no values_mut method or equivalent
        let _v = v;
    }

    let rm = &m;
    for (k, _value) in rm {
        //~^ you seem to want to iterate on a map's keys
        //~| HELP use the corresponding method
        //~| SUGGESTION for k in rm.keys()
        let _k = k;
    }

    test_for_kv_map();
}

#[allow(used_underscore_binding)]
fn test_for_kv_map() {
    let m : HashMap<u64, u64> = HashMap::new();

    // No error, _value is actually used
    for (k, _value) in &m {
        let _ = _value;
        let _k = k;
    }
}
<|endoftext|>


<commit_before>#[derive(Debug)]
pub struct Event {
    pub flags: u32,
    pub data: u64,
}

use miow::iocp::CompletionStatus;

use super::afd;
use crate::Token;

pub fn token(event: &Event) -> Token {
    Token(event.data as usize)
}

pub fn is_readable(event: &Event) -> bool {
    if is_error(event) || is_read_closed(event) {
        return true;
    }
    event.flags & (afd::AFD_POLL_RECEIVE | afd::AFD_POLL_ACCEPT) != 0
}

pub fn is_writable(event: &Event) -> bool {
    if is_error(event) {
        return true;
    }
    event.flags & afd::AFD_POLL_SEND != 0
}

pub fn is_error(event: &Event) -> bool {
    event.flags & afd::AFD_POLL_CONNECT_FAIL != 0
}

pub fn is_read_closed(event: &Event) -> bool {
    event.flags & afd::AFD_POLL_DISCONNECT != 0
}

pub fn is_write_closed(event: &Event) -> bool {
    event.flags & afd::AFD_POLL_ABORT != 0
}

pub fn is_priority(event: &Event) -> bool {
    event.flags & afd::AFD_POLL_RECEIVE_EXPEDITED != 0
}

pub fn is_aio(_: &Event) -> bool {
    // Not supported.
    false
}

pub fn is_lio(_: &Event) -> bool {
    // Not supported.
    false
}

pub struct Events {
    /// Raw I/O event completions are filled in here by the call to `get_many`
    /// on the completion port above. These are then processed to run callbacks
    /// which figure out what to do after the event is done.
    pub statuses: Box<[CompletionStatus]>,

    /// Literal events returned by `get` to the upwards `EventLoop`. This file
    /// doesn't really modify this (except for the waker), instead almost all
    /// events are filled in by the `ReadinessQueue` from the `poll` module.
    pub events: Vec<Event>,
}

impl Events {
    pub fn with_capacity(cap: usize) -> Events {
        // Note that it's possible for the output `events` to grow beyond the
        // capacity as it can also include deferred events, but that's certainly
        // not the end of the world!
        Events {
            statuses: vec![CompletionStatus::zero(); cap].into_boxed_slice(),
            events: Vec::with_capacity(cap),
        }
    }

    pub fn is_empty(&self) -> bool {
        self.events.is_empty()
    }

    pub fn capacity(&self) -> usize {
        self.events.capacity()
    }

    pub fn get(&self, idx: usize) -> Option<&Event> {
        self.events.get(idx)
    }

    pub fn clear(&mut self) {
        self.events.truncate(0);
        for c in 0..self.statuses.len() {
            self.statuses[c] = CompletionStatus::zero();
        }
    }
}
<commit_msg>Prefer to use iterators over traditional loops<commit_after>#[derive(Debug)]
pub struct Event {
    pub flags: u32,
    pub data: u64,
}

use miow::iocp::CompletionStatus;

use super::afd;
use crate::Token;

pub fn token(event: &Event) -> Token {
    Token(event.data as usize)
}

pub fn is_readable(event: &Event) -> bool {
    if is_error(event) || is_read_closed(event) {
        return true;
    }
    event.flags & (afd::AFD_POLL_RECEIVE | afd::AFD_POLL_ACCEPT) != 0
}

pub fn is_writable(event: &Event) -> bool {
    if is_error(event) {
        return true;
    }
    event.flags & afd::AFD_POLL_SEND != 0
}

pub fn is_error(event: &Event) -> bool {
    event.flags & afd::AFD_POLL_CONNECT_FAIL != 0
}

pub fn is_read_closed(event: &Event) -> bool {
    event.flags & afd::AFD_POLL_DISCONNECT != 0
}

pub fn is_write_closed(event: &Event) -> bool {
    event.flags & afd::AFD_POLL_ABORT != 0
}

pub fn is_priority(event: &Event) -> bool {
    event.flags & afd::AFD_POLL_RECEIVE_EXPEDITED != 0
}

pub fn is_aio(_: &Event) -> bool {
    // Not supported.
    false
}

pub fn is_lio(_: &Event) -> bool {
    // Not supported.
    false
}

pub struct Events {
    /// Raw I/O event completions are filled in here by the call to `get_many`
    /// on the completion port above. These are then processed to run callbacks
    /// which figure out what to do after the event is done.
    pub statuses: Box<[CompletionStatus]>,

    /// Literal events returned by `get` to the upwards `EventLoop`. This file
    /// doesn't really modify this (except for the waker), instead almost all
    /// events are filled in by the `ReadinessQueue` from the `poll` module.
    pub events: Vec<Event>,
}

impl Events {
    pub fn with_capacity(cap: usize) -> Events {
        // Note that it's possible for the output `events` to grow beyond the
        // capacity as it can also include deferred events, but that's certainly
        // not the end of the world!
        Events {
            statuses: vec![CompletionStatus::zero(); cap].into_boxed_slice(),
            events: Vec::with_capacity(cap),
        }
    }

    pub fn is_empty(&self) -> bool {
        self.events.is_empty()
    }

    pub fn capacity(&self) -> usize {
        self.events.capacity()
    }

    pub fn get(&self, idx: usize) -> Option<&Event> {
        self.events.get(idx)
    }

    pub fn clear(&mut self) {
        self.events.clear();
        for status in self.statuses.iter_mut() {
            *status = CompletionStatus::zero();
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

//! A transaction can have multiple operations on state. For example, it might update values
//! for a few existing keys. Imagine that we have the following tree.
//!
//! ```text
//!                 root0
//!                 /    \
//!                /      \
//!  key1 => value11        key2 => value21
//! ```
//!
//! The next transaction updates `key1`'s value to `value12` and `key2`'s value to `value22`.
//! Let's assume we update key2 first. Then the tree becomes:
//!
//! ```text
//!                   (on disk)              (in memory)
//!                     root0                  root1'
//!                    /     \                /     \
//!                   /   ___ \ _____________/       \
//!                  /  _/     \                      \
//!                 / _/        \                      \
//!                / /           \                      \
//!   key1 => value11           key2 => value21       key2 => value22
//!      (on disk)                 (on disk)            (in memory)
//! ```
//!
//! Note that
//!   1) we created a new version of the tree with `root1'` and the new `key2` node generated;
//!   2) both `root1'` and the new `key2` node are still held in memory within a batch of nodes
//!      that will be written into db atomically.
//!
//! Next, we need to update `key1`'s value. This time we are dealing with the tree starting from
//! the new root. Part of the tree is in memory and the rest of it is in database. We'll update the
//! left child and the new root. We should
//!   1) create a new version for `key1` child.
//!   2) update `root1'` directly instead of making another version.
//! The resulting tree should look like:
//!
//! ```text
//!                   (on disk)                                     (in memory)
//!                     root0                                         root1''
//!                    /     \                                       /     \
//!                   /       \                                     /       \
//!                  /         \                                   /         \
//!                 /           \                                 /           \
//!                /             \                               /             \
//!   key1 => value11             key2 => value21  key1 => value12              key2 => value22
//!      (on disk)                   (on disk)       (in memory)                  (in memory)
//! ```
//!
//! This means that we need to be able to tell whether to create a new version of a node or to
//! update an existing node by deleting it and creating a new node directly. `TreeCache` provides
//! APIs to cache intermediate nodes and blobs in memory and simplify the actual tree
//! implementation.
//!
//! If we are dealing with a single-version tree, any complex tree operation can be seen as a
//! collection of the following operations:
//!   - Put a new node.
//!   - Delete a node.
//! When we apply these operations on a multi-version tree:
//!   1) Put a new node.
//!   2) When we remove a node, if the node is in the previous on-disk version, we don't need to do
//!      anything. Otherwise we delete it from the tree cache.
//! Updating node could be operated as deletion of the node followed by insertion of the updated
//! node.

#[cfg(test)]
mod tree_cache_test;

use crate::{
    node_type::{Node, NodeKey},
    StaleNodeIndex, TreeReader, TreeUpdateBatch,
};
use crypto::HashValue;
use failure::prelude::*;
use std::{
    collections::{hash_map::Entry, BTreeMap, BTreeSet, HashMap, HashSet},
    convert::Into,
};
use types::transaction::Version;

/// `FrozenTreeCache` is used as a field of `TreeCache` storing all the nodes and blobs that are
/// are generated by earlier transactions so they have to be immutable. The motivation of
/// `FrozenTreeCache` is to let `TreeCache` freeze intermediate results from each transaction to
/// help commit more than one transaction in a row atomically.
#[derive(Default)]
struct FrozenTreeCache {
    /// Immutable node_cache.
    node_cache: BTreeMap<NodeKey, Node>,

    /// # of leaves in the `node_cache`,
    num_new_leaves: usize,

    /// Immutable stale_node_index_cache.
    stale_node_index_cache: BTreeSet<StaleNodeIndex>,

    /// # of leaves in the `stale_node_index_cache`,
    num_stale_leaves: usize,

    /// Frozen root hashes after each earlier transaction.
    root_hashes: Vec<HashValue>,
}

/// `TreeCache` is a in-memory cache for per-transaction updates of sparse Merkle nodes and value
/// blobs.
pub struct TreeCache<'a, R: 'a + TreeReader> {
    /// `NodeKey` of the current root node in cache.
    root_node_key: NodeKey,

    /// The version of the transaction to which the upcoming `put`s will be related.
    next_version: Version,

    /// Intermediate nodes keyed by node hash
    node_cache: HashMap<NodeKey, Node>,

    /// # of leaves in the `node_cache`,
    num_new_leaves: usize,

    /// Partial stale log. `NodeKey` to identify the stale record.
    stale_node_index_cache: HashSet<NodeKey>,

    /// # of leaves in the `stale_node_index_cache`,
    num_stale_leaves: usize,

    /// The immutable part of this cache, which will be committed to the underlying storage.
    frozen_cache: FrozenTreeCache,

    /// The underlying persistent storage.
    reader: &'a R,
}

impl<'a, R> TreeReader for TreeCache<'a, R>
where
    R: 'a + TreeReader,
{
    /// Gets a node with given hash. If it doesn't exist in node cache, read from `reader`.
    fn get_node(&self, node_key: &NodeKey) -> Result<Node> {
        Ok(if let Some(node) = self.node_cache.get(node_key) {
            node.clone()
        } else if let Some(node) = self.frozen_cache.node_cache.get(node_key) {
            node.clone()
        } else {
            self.reader.get_node(node_key)?
        })
    }
}

impl<'a, R> TreeCache<'a, R>
where
    R: 'a + TreeReader,
{
    /// Constructs a new `TreeCache` instance.
    pub fn new(reader: &'a R, next_version: Version) -> Self {
        let mut node_cache = HashMap::new();
        let root_node_key = if next_version == 0 {
            // If the first version is 0, it means we need to start from an empty tree so we insert
            // a null node beforehand deliberately to deal with this corner case.
            node_cache.insert(NodeKey::new_empty_path(0), Node::new_null());
            NodeKey::new_empty_path(0)
        } else {
            NodeKey::new_empty_path(next_version - 1)
        };
        Self {
            node_cache,
            stale_node_index_cache: HashSet::new(),
            frozen_cache: FrozenTreeCache::default(),
            root_node_key,
            next_version,
            reader,
            num_stale_leaves: 0,
            num_new_leaves: 0,
        }
    }

    /// Gets the current root node key.
    pub fn get_root_node_key(&self) -> &NodeKey {
        &self.root_node_key
    }

    /// Set roots `node_key`.
    pub fn set_root_node_key(&mut self, root_node_key: NodeKey) {
        self.root_node_key = root_node_key;
    }

    /// Puts the node with given hash as key into node_cache.
    pub fn put_node(&mut self, node_key: NodeKey, new_node: Node) -> Result<()> {
        match self.node_cache.entry(node_key) {
            Entry::Vacant(o) => {
                if new_node.is_leaf() {
                    self.num_new_leaves += 1
                }
                o.insert(new_node);
            }
            Entry::Occupied(o) => bail!("Node with key {:?} already exists in NodeBatch", o.key()),
        };
        Ok(())
    }

    /// Deletes a node with given hash.
    pub fn delete_node(&mut self, old_node_key: &NodeKey, is_leaf: bool) {
        // If node cache doesn't have this node, it means the node is in the previous version of
        // the tree on the disk.
        if self.node_cache.remove(&old_node_key).is_none() {
            let is_new_entry = self.stale_node_index_cache.insert(old_node_key.clone());
            assert!(is_new_entry, "Node gets stale twice unexpectedly.");
            if is_leaf {
                self.num_stale_leaves += 1;
            }
        } else if is_leaf {
            self.num_new_leaves -= 1;
        }
    }

    /// Freezes all the contents in cache to be immutable and clear `node_cache`.
    pub fn freeze(&mut self) {
        let root_node_key = self.get_root_node_key();
        let root_hash = self
            .get_node(root_node_key)
            .unwrap_or_else(|_| panic!("Root node with key {:?} must exist", root_node_key))
            .hash();
        self.frozen_cache.root_hashes.push(root_hash);
        self.frozen_cache.node_cache.extend(self.node_cache.drain());

        let stale_since_version = self.next_version;
        self.frozen_cache
            .stale_node_index_cache
            .extend(
                self.stale_node_index_cache
                    .drain()
                    .map(|node_key| StaleNodeIndex {
                        stale_since_version,
                        node_key,
                    }),
            );
        self.frozen_cache.num_stale_leaves += self.num_stale_leaves;
        self.num_stale_leaves = 0;
        self.frozen_cache.num_new_leaves += self.num_new_leaves;
        self.num_new_leaves = 0;

        self.next_version += 1;
    }
}

impl<'a, R> Into<(Vec<HashValue>, TreeUpdateBatch)> for TreeCache<'a, R>
where
    R: 'a + TreeReader,
{
    fn into(self) -> (Vec<HashValue>, TreeUpdateBatch) {
        (
            self.frozen_cache.root_hashes,
            TreeUpdateBatch {
                node_batch: self.frozen_cache.node_cache,
                stale_node_index_batch: self.frozen_cache.stale_node_index_cache,
                num_new_leaves: self.frozen_cache.num_new_leaves,
                num_stale_leaves: self.frozen_cache.num_stale_leaves,
            },
        )
    }
}
<commit_msg>[Storage] Do not implement TreeReader for TreeCache<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

//! A transaction can have multiple operations on state. For example, it might update values
//! for a few existing keys. Imagine that we have the following tree.
//!
//! ```text
//!                 root0
//!                 /    \
//!                /      \
//!  key1 => value11        key2 => value21
//! ```
//!
//! The next transaction updates `key1`'s value to `value12` and `key2`'s value to `value22`.
//! Let's assume we update key2 first. Then the tree becomes:
//!
//! ```text
//!                   (on disk)              (in memory)
//!                     root0                  root1'
//!                    /     \                /     \
//!                   /   ___ \ _____________/       \
//!                  /  _/     \                      \
//!                 / _/        \                      \
//!                / /           \                      \
//!   key1 => value11           key2 => value21       key2 => value22
//!      (on disk)                 (on disk)            (in memory)
//! ```
//!
//! Note that
//!   1) we created a new version of the tree with `root1'` and the new `key2` node generated;
//!   2) both `root1'` and the new `key2` node are still held in memory within a batch of nodes
//!      that will be written into db atomically.
//!
//! Next, we need to update `key1`'s value. This time we are dealing with the tree starting from
//! the new root. Part of the tree is in memory and the rest of it is in database. We'll update the
//! left child and the new root. We should
//!   1) create a new version for `key1` child.
//!   2) update `root1'` directly instead of making another version.
//! The resulting tree should look like:
//!
//! ```text
//!                   (on disk)                                     (in memory)
//!                     root0                                         root1''
//!                    /     \                                       /     \
//!                   /       \                                     /       \
//!                  /         \                                   /         \
//!                 /           \                                 /           \
//!                /             \                               /             \
//!   key1 => value11             key2 => value21  key1 => value12              key2 => value22
//!      (on disk)                   (on disk)       (in memory)                  (in memory)
//! ```
//!
//! This means that we need to be able to tell whether to create a new version of a node or to
//! update an existing node by deleting it and creating a new node directly. `TreeCache` provides
//! APIs to cache intermediate nodes and blobs in memory and simplify the actual tree
//! implementation.
//!
//! If we are dealing with a single-version tree, any complex tree operation can be seen as a
//! collection of the following operations:
//!   - Put a new node.
//!   - Delete a node.
//! When we apply these operations on a multi-version tree:
//!   1) Put a new node.
//!   2) When we remove a node, if the node is in the previous on-disk version, we don't need to do
//!      anything. Otherwise we delete it from the tree cache.
//! Updating node could be operated as deletion of the node followed by insertion of the updated
//! node.

#[cfg(test)]
mod tree_cache_test;

use crate::{
    node_type::{Node, NodeKey},
    StaleNodeIndex, TreeReader, TreeUpdateBatch,
};
use crypto::HashValue;
use failure::prelude::*;
use std::{
    collections::{hash_map::Entry, BTreeMap, BTreeSet, HashMap, HashSet},
    convert::Into,
};
use types::transaction::Version;

/// `FrozenTreeCache` is used as a field of `TreeCache` storing all the nodes and blobs that are
/// are generated by earlier transactions so they have to be immutable. The motivation of
/// `FrozenTreeCache` is to let `TreeCache` freeze intermediate results from each transaction to
/// help commit more than one transaction in a row atomically.
#[derive(Default)]
struct FrozenTreeCache {
    /// Immutable node_cache.
    node_cache: BTreeMap<NodeKey, Node>,

    /// # of leaves in the `node_cache`,
    num_new_leaves: usize,

    /// Immutable stale_node_index_cache.
    stale_node_index_cache: BTreeSet<StaleNodeIndex>,

    /// # of leaves in the `stale_node_index_cache`,
    num_stale_leaves: usize,

    /// Frozen root hashes after each earlier transaction.
    root_hashes: Vec<HashValue>,
}

/// `TreeCache` is a in-memory cache for per-transaction updates of sparse Merkle nodes and value
/// blobs.
pub struct TreeCache<'a, R: 'a + TreeReader> {
    /// `NodeKey` of the current root node in cache.
    root_node_key: NodeKey,

    /// The version of the transaction to which the upcoming `put`s will be related.
    next_version: Version,

    /// Intermediate nodes keyed by node hash
    node_cache: HashMap<NodeKey, Node>,

    /// # of leaves in the `node_cache`,
    num_new_leaves: usize,

    /// Partial stale log. `NodeKey` to identify the stale record.
    stale_node_index_cache: HashSet<NodeKey>,

    /// # of leaves in the `stale_node_index_cache`,
    num_stale_leaves: usize,

    /// The immutable part of this cache, which will be committed to the underlying storage.
    frozen_cache: FrozenTreeCache,

    /// The underlying persistent storage.
    reader: &'a R,
}

impl<'a, R> TreeCache<'a, R>
where
    R: 'a + TreeReader,
{
    /// Constructs a new `TreeCache` instance.
    pub fn new(reader: &'a R, next_version: Version) -> Self {
        let mut node_cache = HashMap::new();
        let root_node_key = if next_version == 0 {
            // If the first version is 0, it means we need to start from an empty tree so we insert
            // a null node beforehand deliberately to deal with this corner case.
            node_cache.insert(NodeKey::new_empty_path(0), Node::new_null());
            NodeKey::new_empty_path(0)
        } else {
            NodeKey::new_empty_path(next_version - 1)
        };
        Self {
            node_cache,
            stale_node_index_cache: HashSet::new(),
            frozen_cache: FrozenTreeCache::default(),
            root_node_key,
            next_version,
            reader,
            num_stale_leaves: 0,
            num_new_leaves: 0,
        }
    }

    /// Gets a node with given node key. If it doesn't exist in node cache, read from `reader`.
    pub fn get_node(&self, node_key: &NodeKey) -> Result<Node> {
        Ok(if let Some(node) = self.node_cache.get(node_key) {
            node.clone()
        } else if let Some(node) = self.frozen_cache.node_cache.get(node_key) {
            node.clone()
        } else {
            self.reader.get_node(node_key)?
        })
    }

    /// Gets the current root node key.
    pub fn get_root_node_key(&self) -> &NodeKey {
        &self.root_node_key
    }

    /// Set roots `node_key`.
    pub fn set_root_node_key(&mut self, root_node_key: NodeKey) {
        self.root_node_key = root_node_key;
    }

    /// Puts the node with given hash as key into node_cache.
    pub fn put_node(&mut self, node_key: NodeKey, new_node: Node) -> Result<()> {
        match self.node_cache.entry(node_key) {
            Entry::Vacant(o) => {
                if new_node.is_leaf() {
                    self.num_new_leaves += 1
                }
                o.insert(new_node);
            }
            Entry::Occupied(o) => bail!("Node with key {:?} already exists in NodeBatch", o.key()),
        };
        Ok(())
    }

    /// Deletes a node with given hash.
    pub fn delete_node(&mut self, old_node_key: &NodeKey, is_leaf: bool) {
        // If node cache doesn't have this node, it means the node is in the previous version of
        // the tree on the disk.
        if self.node_cache.remove(&old_node_key).is_none() {
            let is_new_entry = self.stale_node_index_cache.insert(old_node_key.clone());
            assert!(is_new_entry, "Node gets stale twice unexpectedly.");
            if is_leaf {
                self.num_stale_leaves += 1;
            }
        } else if is_leaf {
            self.num_new_leaves -= 1;
        }
    }

    /// Freezes all the contents in cache to be immutable and clear `node_cache`.
    pub fn freeze(&mut self) {
        let root_node_key = self.get_root_node_key();
        let root_hash = self
            .get_node(root_node_key)
            .unwrap_or_else(|_| panic!("Root node with key {:?} must exist", root_node_key))
            .hash();
        self.frozen_cache.root_hashes.push(root_hash);
        self.frozen_cache.node_cache.extend(self.node_cache.drain());

        let stale_since_version = self.next_version;
        self.frozen_cache
            .stale_node_index_cache
            .extend(
                self.stale_node_index_cache
                    .drain()
                    .map(|node_key| StaleNodeIndex {
                        stale_since_version,
                        node_key,
                    }),
            );
        self.frozen_cache.num_stale_leaves += self.num_stale_leaves;
        self.num_stale_leaves = 0;
        self.frozen_cache.num_new_leaves += self.num_new_leaves;
        self.num_new_leaves = 0;

        self.next_version += 1;
    }
}

impl<'a, R> Into<(Vec<HashValue>, TreeUpdateBatch)> for TreeCache<'a, R>
where
    R: 'a + TreeReader,
{
    fn into(self) -> (Vec<HashValue>, TreeUpdateBatch) {
        (
            self.frozen_cache.root_hashes,
            TreeUpdateBatch {
                node_batch: self.frozen_cache.node_cache,
                stale_node_index_batch: self.frozen_cache.stale_node_index_cache,
                num_new_leaves: self.frozen_cache.num_new_leaves,
                num_stale_leaves: self.frozen_cache.num_stale_leaves,
            },
        )
    }
}
<|endoftext|>