<commit_before>#[cfg(not(target_arch = "wasm32"))]
compile_error!("This module should only be included when compiling to wasm");

use std::ffi::{CStr, CString};
use std::fmt::Debug;
use std::mem;
use std::os::raw::{c_char, c_void};

use serde_json;

use query::{Query, Response};

// Functions preovided by JavaScript, to be called by the WebAssembly generated from Rust
extern "C" {
    fn send_query(query: *const c_char) -> *const c_char;
    fn _log(message: *const c_char);
}

// In order to work with the memory in WASM, we expose allocation and deallocation methods
#[no_mangle]
pub extern "C" fn alloc(size: usize) -> *const c_void {
    let buf = Vec::with_capacity(size);
    let ptr = buf.as_ptr();
    // Forget the pointer so that Rust doesn't free the memory we want to give JavaScript
    // access to. (Leaking memory is **safe**, so unsafe { ... } is not necessary.)
    mem::forget(buf);
    return ptr as *const c_void;
}

#[no_mangle]
pub extern "C" fn dealloc(ptr: *mut c_void, cap: usize) {
    unsafe {
        // Rust will drop this vector and free the memory
        let _buf = Vec::from_raw_parts(ptr, 0, cap);
    }
}

/// Specifically for deallocating NULL-terminated strings without knowing their length in advance
///
/// See `CString::into_raw` for more information:
/// https://doc.rust-lang.org/std/ffi/struct.CString.html#method.into_raw
#[no_mangle]
pub extern "C" fn dealloc_str(ptr: *mut c_char) {
    unsafe {
        let _ = CString::from_raw(ptr);
    }
}

/// Prints a value out to the JavaScript console (for debugging purposes)
pub(crate) fn _debug<T: Debug>(value: T) {
    let raw_str = CString::new(format!("{:?}", value)).unwrap().into_raw();
    unsafe { _log(raw_str) };
}

/// A special "renderer process" specifically for communicating through the web assembly boundary
/// to the JavaScript that is running this program.
pub struct RendererProcess {}

impl RendererProcess {
    pub fn new() -> Self {
        Self {}
    }

    pub fn send_query(&mut self, query: Query) -> Option<Response> {
        let query_str = serde_json::to_string(&query).unwrap();
        let c_str = CString::new(query_str).unwrap();
        // Once the string is passed into JavaScript, JavaScript is now considered the owner of
        // that string.
        let raw_str = c_str.into_raw();
        let response_cstr = unsafe { CStr::from_ptr(send_query(raw_str)) };
        // Requests need responses
        if let Query::Request(_) = query {
            let response_str = response_cstr.to_str().expect("String provided by JavaScript was not valid UTF-8");
            let response = serde_json::from_str(response_str).expect("String provided by JavaScript was not valid JSON");
            Some(response)
        } else {
            None
        }
    }
}
<commit_msg>Fixes for compiling to WASM<commit_after>#[cfg(not(target_arch = "wasm32"))]
compile_error!("This module should only be included when compiling to wasm");

use std::ffi::{CStr, CString};
use std::fmt::Debug;
use std::mem;
use std::os::raw::{c_char, c_void};

use crate::query::{Query, Response};

// Functions preovided by JavaScript, to be called by the WebAssembly generated from Rust
extern "C" {
    fn send_query(query: *const c_char) -> *const c_char;
    fn _log(message: *const c_char);
}

// In order to work with the memory in WASM, we expose allocation and deallocation methods
#[no_mangle]
pub extern "C" fn alloc(size: usize) -> *const c_void {
    let buf = Vec::with_capacity(size);
    let ptr = buf.as_ptr();
    // Forget the pointer so that Rust doesn't free the memory we want to give JavaScript
    // access to. (Leaking memory is **safe**, so unsafe { ... } is not necessary.)
    mem::forget(buf);
    return ptr as *const c_void;
}

#[no_mangle]
pub extern "C" fn dealloc(ptr: *mut c_void, cap: usize) {
    unsafe {
        // Rust will drop this vector and free the memory
        let _buf = Vec::from_raw_parts(ptr, 0, cap);
    }
}

/// Specifically for deallocating NULL-terminated strings without knowing their length in advance
///
/// See `CString::into_raw` for more information:
/// https://doc.rust-lang.org/std/ffi/struct.CString.html#method.into_raw
#[no_mangle]
pub extern "C" fn dealloc_str(ptr: *mut c_char) {
    unsafe {
        let _ = CString::from_raw(ptr);
    }
}

/// Prints a value out to the JavaScript console (for debugging purposes)
pub(crate) fn _debug<T: Debug>(value: T) {
    let raw_str = CString::new(format!("{:?}", value)).unwrap().into_raw();
    unsafe { _log(raw_str) };
}

/// A special "renderer process" specifically for communicating through the web assembly boundary
/// to the JavaScript that is running this program.
pub struct RendererProcess {}

impl RendererProcess {
    pub fn new() -> Self {
        Self {}
    }

    pub fn send_query(&mut self, query: Query) -> Option<Response> {
        let query_str = serde_json::to_string(&query).unwrap();
        let c_str = CString::new(query_str).unwrap();
        // Once the string is passed into JavaScript, JavaScript is now considered the owner of
        // that string.
        let raw_str = c_str.into_raw();
        let response_cstr = unsafe { CStr::from_ptr(send_query(raw_str)) };
        // Requests need responses
        if let Query::Request(_) = query {
            let response_str = response_cstr.to_str().expect("String provided by JavaScript was not valid UTF-8");
            let response = serde_json::from_str(response_str).expect("String provided by JavaScript was not valid JSON");
            Some(response)
        } else {
            None
        }
    }
}
<|endoftext|>


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

use app_units::Au;
use euclid::{Point2D, Rect, Size2D};
use font_template::FontTemplateDescriptor;
use platform::font::{FontHandle, FontTable};
use platform::font_context::FontContextHandle;
use platform::font_template::FontTemplateData;
use smallvec::SmallVec;
use std::borrow::ToOwned;
use std::cell::RefCell;
use std::rc::Rc;
use std::str;
use std::sync::Arc;
use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering};
use style::computed_values::{font_stretch, font_variant, font_weight};
use style::properties::style_structs::ServoFont;
use text::Shaper;
use text::glyph::{GlyphId, GlyphStore};
use text::shaping::ShaperMethods;
use time;
use unicode_script::Script;
use util::cache::HashCache;
use webrender_traits;

static TEXT_SHAPING_PERFORMANCE_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;

// FontHandle encapsulates access to the platform's font API,
// e.g. quartz, FreeType. It provides access to metrics and tables
// needed by the text shaper as well as access to the underlying font
// resources needed by the graphics layer to draw glyphs.

pub trait FontHandleMethods: Sized {
    fn new_from_template(fctx: &FontContextHandle, template: Arc<FontTemplateData>, pt_size: Option<Au>)
                    -> Result<Self, ()>;
    fn template(&self) -> Arc<FontTemplateData>;
    fn family_name(&self) -> String;
    fn face_name(&self) -> String;
    fn is_italic(&self) -> bool;
    fn boldness(&self) -> font_weight::T;
    fn stretchiness(&self) -> font_stretch::T;

    fn glyph_index(&self, codepoint: char) -> Option<GlyphId>;
    fn glyph_h_advance(&self, GlyphId) -> Option<FractionalPixel>;
    fn glyph_h_kerning(&self, GlyphId, GlyphId) -> FractionalPixel;
    fn metrics(&self) -> FontMetrics;
    fn table_for_tag(&self, FontTableTag) -> Option<Box<FontTable>>;
}

// Used to abstract over the shaper's choice of fixed int representation.
pub type FractionalPixel = f64;

pub type FontTableTag = u32;

pub trait FontTableTagConversions {
    fn tag_to_str(&self) -> String;
}

impl FontTableTagConversions for FontTableTag {
    fn tag_to_str(&self) -> String {
        let bytes = [(self >> 24) as u8,
                     (self >> 16) as u8,
                     (self >>  8) as u8,
                     (self >>  0) as u8];
        str::from_utf8(&bytes).unwrap().to_owned()
    }
}

pub trait FontTableMethods {
    fn with_buffer<F>(&self, F) where F: FnOnce(*const u8, usize);
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct FontMetrics {
    pub underline_size:   Au,
    pub underline_offset: Au,
    pub strikeout_size:   Au,
    pub strikeout_offset: Au,
    pub leading:          Au,
    pub x_height:         Au,
    pub em_size:          Au,
    pub ascent:           Au,
    pub descent:          Au,
    pub max_advance:      Au,
    pub average_advance:  Au,
    pub line_gap:         Au,
}

pub type SpecifiedFontStyle = ServoFont;

#[derive(Debug)]
pub struct Font {
    pub handle: FontHandle,
    pub metrics: FontMetrics,
    pub variant: font_variant::T,
    pub descriptor: FontTemplateDescriptor,
    pub requested_pt_size: Au,
    pub actual_pt_size: Au,
    pub shaper: Option<Shaper>,
    pub shape_cache: HashCache<ShapeCacheEntry, Arc<GlyphStore>>,
    pub glyph_advance_cache: HashCache<u32, FractionalPixel>,
    pub font_key: Option<webrender_traits::FontKey>,
}

bitflags! {
    pub flags ShapingFlags: u8 {
        #[doc = "Set if the text is entirely whitespace."]
        const IS_WHITESPACE_SHAPING_FLAG = 0x01,
        #[doc = "Set if we are to ignore ligatures."]
        const IGNORE_LIGATURES_SHAPING_FLAG = 0x02,
        #[doc = "Set if we are to disable kerning."]
        const DISABLE_KERNING_SHAPING_FLAG = 0x04,
        #[doc = "Text direction is right-to-left."]
        const RTL_FLAG = 0x08,
    }
}

/// Various options that control text shaping.
#[derive(Clone, Eq, PartialEq, Hash, Copy, Debug)]
pub struct ShapingOptions {
    /// Spacing to add between each letter. Corresponds to the CSS 2.1 `letter-spacing` property.
    /// NB: You will probably want to set the `IGNORE_LIGATURES_SHAPING_FLAG` if this is non-null.
    pub letter_spacing: Option<Au>,
    /// Spacing to add between each word. Corresponds to the CSS 2.1 `word-spacing` property.
    pub word_spacing: Au,
    /// The Unicode script property of the characters in this run.
    pub script: Script,
    /// Various flags.
    pub flags: ShapingFlags,
}

/// An entry in the shape cache.
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub struct ShapeCacheEntry {
    text: String,
    options: ShapingOptions,
}

impl Font {
    pub fn shape_text(&mut self, text: &str, options: &ShapingOptions) -> Arc<GlyphStore> {
        self.make_shaper(options);

        //FIXME: find the equivalent of Equiv and the old ShapeCacheEntryRef
        let shaper = &self.shaper;
        let lookup_key = ShapeCacheEntry {
            text: text.to_owned(),
            options: options.clone(),
        };
        if let Some(glyphs) = self.shape_cache.find(&lookup_key) {
            return glyphs.clone();
        }

        let start_time = time::precise_time_ns();

        let mut glyphs = GlyphStore::new(text.len(),
                                         options.flags.contains(IS_WHITESPACE_SHAPING_FLAG),
                                         options.flags.contains(RTL_FLAG));
        shaper.as_ref().unwrap().shape_text(text, options, &mut glyphs);

        let glyphs = Arc::new(glyphs);
        self.shape_cache.insert(ShapeCacheEntry {
            text: text.to_owned(),
            options: *options,
        }, glyphs.clone());

        let end_time = time::precise_time_ns();
        TEXT_SHAPING_PERFORMANCE_COUNTER.fetch_add((end_time - start_time) as usize,
                                                   Ordering::Relaxed);

        glyphs
    }

    fn make_shaper<'a>(&'a mut self, options: &ShapingOptions) -> &'a Shaper {
        // fast path: already created a shaper
        if let Some(ref mut shaper) = self.shaper {
            shaper.set_options(options);
            return shaper
        }

        let shaper = Shaper::new(self, options);
        self.shaper = Some(shaper);
        self.shaper.as_ref().unwrap()
    }

    pub fn table_for_tag(&self, tag: FontTableTag) -> Option<Box<FontTable>> {
        let result = self.handle.table_for_tag(tag);
        let status = if result.is_some() { "Found" } else { "Didn't find" };

        debug!("{} font table[{}] with family={}, face={}",
               status, tag.tag_to_str(),
               self.handle.family_name(), self.handle.face_name());

        result
    }

    #[inline]
    pub fn glyph_index(&self, codepoint: char) -> Option<GlyphId> {
        let codepoint = match self.variant {
            font_variant::T::small_caps => codepoint.to_uppercase().next().unwrap(), //FIXME: #5938
            font_variant::T::normal => codepoint,
        };
        self.handle.glyph_index(codepoint)
    }

    pub fn glyph_h_kerning(&mut self, first_glyph: GlyphId, second_glyph: GlyphId)
                           -> FractionalPixel {
        self.handle.glyph_h_kerning(first_glyph, second_glyph)
    }

    pub fn glyph_h_advance(&mut self, glyph: GlyphId) -> FractionalPixel {
        let handle = &self.handle;
        self.glyph_advance_cache.find_or_create(&glyph, |glyph| {
            match handle.glyph_h_advance(*glyph) {
                Some(adv) => adv,
                None => 10f64 as FractionalPixel // FIXME: Need fallback strategy
            }
        })
    }
}

#[derive(Debug)]
pub struct FontGroup {
    pub fonts: SmallVec<[Rc<RefCell<Font>>; 8]>,
}

impl FontGroup {
    pub fn new(fonts: SmallVec<[Rc<RefCell<Font>>; 8]>) -> FontGroup {
        FontGroup {
            fonts: fonts,
        }
    }
}

pub struct RunMetrics {
    // may be negative due to negative width (i.e., kerning of '.' in 'P.T.')
    pub advance_width: Au,
    pub ascent: Au, // nonzero
    pub descent: Au, // nonzero
    // this bounding box is relative to the left origin baseline.
    // so, bounding_box.position.y = -ascent
    pub bounding_box: Rect<Au>
}

impl RunMetrics {
    pub fn new(advance: Au, ascent: Au, descent: Au) -> RunMetrics {
        let bounds = Rect::new(Point2D::new(Au(0), -ascent),
                               Size2D::new(advance, ascent + descent));

        // TODO(Issue #125): support loose and tight bounding boxes; using the
        // ascent+descent and advance is sometimes too generous and
        // looking at actual glyph extents can yield a tighter box.

        RunMetrics {
            advance_width: advance,
            bounding_box: bounds,
            ascent: ascent,
            descent: descent,
        }
    }
}

pub fn get_and_reset_text_shaping_performance_counter() -> usize {
    let value = TEXT_SHAPING_PERFORMANCE_COUNTER.load(Ordering::SeqCst);
    TEXT_SHAPING_PERFORMANCE_COUNTER.store(0, Ordering::SeqCst);
    value
}
<commit_msg>Remove unnecessary pub<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use app_units::Au;
use euclid::{Point2D, Rect, Size2D};
use font_template::FontTemplateDescriptor;
use platform::font::{FontHandle, FontTable};
use platform::font_context::FontContextHandle;
use platform::font_template::FontTemplateData;
use smallvec::SmallVec;
use std::borrow::ToOwned;
use std::cell::RefCell;
use std::rc::Rc;
use std::str;
use std::sync::Arc;
use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering};
use style::computed_values::{font_stretch, font_variant, font_weight};
use style::properties::style_structs::ServoFont;
use text::Shaper;
use text::glyph::{GlyphId, GlyphStore};
use text::shaping::ShaperMethods;
use time;
use unicode_script::Script;
use util::cache::HashCache;
use webrender_traits;

static TEXT_SHAPING_PERFORMANCE_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;

// FontHandle encapsulates access to the platform's font API,
// e.g. quartz, FreeType. It provides access to metrics and tables
// needed by the text shaper as well as access to the underlying font
// resources needed by the graphics layer to draw glyphs.

pub trait FontHandleMethods: Sized {
    fn new_from_template(fctx: &FontContextHandle, template: Arc<FontTemplateData>, pt_size: Option<Au>)
                    -> Result<Self, ()>;
    fn template(&self) -> Arc<FontTemplateData>;
    fn family_name(&self) -> String;
    fn face_name(&self) -> String;
    fn is_italic(&self) -> bool;
    fn boldness(&self) -> font_weight::T;
    fn stretchiness(&self) -> font_stretch::T;

    fn glyph_index(&self, codepoint: char) -> Option<GlyphId>;
    fn glyph_h_advance(&self, GlyphId) -> Option<FractionalPixel>;
    fn glyph_h_kerning(&self, GlyphId, GlyphId) -> FractionalPixel;
    fn metrics(&self) -> FontMetrics;
    fn table_for_tag(&self, FontTableTag) -> Option<Box<FontTable>>;
}

// Used to abstract over the shaper's choice of fixed int representation.
pub type FractionalPixel = f64;

pub type FontTableTag = u32;

trait FontTableTagConversions {
    fn tag_to_str(&self) -> String;
}

impl FontTableTagConversions for FontTableTag {
    fn tag_to_str(&self) -> String {
        let bytes = [(self >> 24) as u8,
                     (self >> 16) as u8,
                     (self >>  8) as u8,
                     (self >>  0) as u8];
        str::from_utf8(&bytes).unwrap().to_owned()
    }
}

pub trait FontTableMethods {
    fn with_buffer<F>(&self, F) where F: FnOnce(*const u8, usize);
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct FontMetrics {
    pub underline_size:   Au,
    pub underline_offset: Au,
    pub strikeout_size:   Au,
    pub strikeout_offset: Au,
    pub leading:          Au,
    pub x_height:         Au,
    pub em_size:          Au,
    pub ascent:           Au,
    pub descent:          Au,
    pub max_advance:      Au,
    pub average_advance:  Au,
    pub line_gap:         Au,
}

pub type SpecifiedFontStyle = ServoFont;

#[derive(Debug)]
pub struct Font {
    pub handle: FontHandle,
    pub metrics: FontMetrics,
    pub variant: font_variant::T,
    pub descriptor: FontTemplateDescriptor,
    pub requested_pt_size: Au,
    pub actual_pt_size: Au,
    pub shaper: Option<Shaper>,
    pub shape_cache: HashCache<ShapeCacheEntry, Arc<GlyphStore>>,
    pub glyph_advance_cache: HashCache<u32, FractionalPixel>,
    pub font_key: Option<webrender_traits::FontKey>,
}

bitflags! {
    pub flags ShapingFlags: u8 {
        #[doc = "Set if the text is entirely whitespace."]
        const IS_WHITESPACE_SHAPING_FLAG = 0x01,
        #[doc = "Set if we are to ignore ligatures."]
        const IGNORE_LIGATURES_SHAPING_FLAG = 0x02,
        #[doc = "Set if we are to disable kerning."]
        const DISABLE_KERNING_SHAPING_FLAG = 0x04,
        #[doc = "Text direction is right-to-left."]
        const RTL_FLAG = 0x08,
    }
}

/// Various options that control text shaping.
#[derive(Clone, Eq, PartialEq, Hash, Copy, Debug)]
pub struct ShapingOptions {
    /// Spacing to add between each letter. Corresponds to the CSS 2.1 `letter-spacing` property.
    /// NB: You will probably want to set the `IGNORE_LIGATURES_SHAPING_FLAG` if this is non-null.
    pub letter_spacing: Option<Au>,
    /// Spacing to add between each word. Corresponds to the CSS 2.1 `word-spacing` property.
    pub word_spacing: Au,
    /// The Unicode script property of the characters in this run.
    pub script: Script,
    /// Various flags.
    pub flags: ShapingFlags,
}

/// An entry in the shape cache.
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub struct ShapeCacheEntry {
    text: String,
    options: ShapingOptions,
}

impl Font {
    pub fn shape_text(&mut self, text: &str, options: &ShapingOptions) -> Arc<GlyphStore> {
        self.make_shaper(options);

        //FIXME: find the equivalent of Equiv and the old ShapeCacheEntryRef
        let shaper = &self.shaper;
        let lookup_key = ShapeCacheEntry {
            text: text.to_owned(),
            options: options.clone(),
        };
        if let Some(glyphs) = self.shape_cache.find(&lookup_key) {
            return glyphs.clone();
        }

        let start_time = time::precise_time_ns();

        let mut glyphs = GlyphStore::new(text.len(),
                                         options.flags.contains(IS_WHITESPACE_SHAPING_FLAG),
                                         options.flags.contains(RTL_FLAG));
        shaper.as_ref().unwrap().shape_text(text, options, &mut glyphs);

        let glyphs = Arc::new(glyphs);
        self.shape_cache.insert(ShapeCacheEntry {
            text: text.to_owned(),
            options: *options,
        }, glyphs.clone());

        let end_time = time::precise_time_ns();
        TEXT_SHAPING_PERFORMANCE_COUNTER.fetch_add((end_time - start_time) as usize,
                                                   Ordering::Relaxed);

        glyphs
    }

    fn make_shaper<'a>(&'a mut self, options: &ShapingOptions) -> &'a Shaper {
        // fast path: already created a shaper
        if let Some(ref mut shaper) = self.shaper {
            shaper.set_options(options);
            return shaper
        }

        let shaper = Shaper::new(self, options);
        self.shaper = Some(shaper);
        self.shaper.as_ref().unwrap()
    }

    pub fn table_for_tag(&self, tag: FontTableTag) -> Option<Box<FontTable>> {
        let result = self.handle.table_for_tag(tag);
        let status = if result.is_some() { "Found" } else { "Didn't find" };

        debug!("{} font table[{}] with family={}, face={}",
               status, tag.tag_to_str(),
               self.handle.family_name(), self.handle.face_name());

        result
    }

    #[inline]
    pub fn glyph_index(&self, codepoint: char) -> Option<GlyphId> {
        let codepoint = match self.variant {
            font_variant::T::small_caps => codepoint.to_uppercase().next().unwrap(), //FIXME: #5938
            font_variant::T::normal => codepoint,
        };
        self.handle.glyph_index(codepoint)
    }

    pub fn glyph_h_kerning(&mut self, first_glyph: GlyphId, second_glyph: GlyphId)
                           -> FractionalPixel {
        self.handle.glyph_h_kerning(first_glyph, second_glyph)
    }

    pub fn glyph_h_advance(&mut self, glyph: GlyphId) -> FractionalPixel {
        let handle = &self.handle;
        self.glyph_advance_cache.find_or_create(&glyph, |glyph| {
            match handle.glyph_h_advance(*glyph) {
                Some(adv) => adv,
                None => 10f64 as FractionalPixel // FIXME: Need fallback strategy
            }
        })
    }
}

#[derive(Debug)]
pub struct FontGroup {
    pub fonts: SmallVec<[Rc<RefCell<Font>>; 8]>,
}

impl FontGroup {
    pub fn new(fonts: SmallVec<[Rc<RefCell<Font>>; 8]>) -> FontGroup {
        FontGroup {
            fonts: fonts,
        }
    }
}

pub struct RunMetrics {
    // may be negative due to negative width (i.e., kerning of '.' in 'P.T.')
    pub advance_width: Au,
    pub ascent: Au, // nonzero
    pub descent: Au, // nonzero
    // this bounding box is relative to the left origin baseline.
    // so, bounding_box.position.y = -ascent
    pub bounding_box: Rect<Au>
}

impl RunMetrics {
    pub fn new(advance: Au, ascent: Au, descent: Au) -> RunMetrics {
        let bounds = Rect::new(Point2D::new(Au(0), -ascent),
                               Size2D::new(advance, ascent + descent));

        // TODO(Issue #125): support loose and tight bounding boxes; using the
        // ascent+descent and advance is sometimes too generous and
        // looking at actual glyph extents can yield a tighter box.

        RunMetrics {
            advance_width: advance,
            bounding_box: bounds,
            ascent: ascent,
            descent: descent,
        }
    }
}

pub fn get_and_reset_text_shaping_performance_counter() -> usize {
    let value = TEXT_SHAPING_PERFORMANCE_COUNTER.load(Ordering::SeqCst);
    TEXT_SHAPING_PERFORMANCE_COUNTER.store(0, Ordering::SeqCst);
    value
}
<|endoftext|>


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

#![feature(box_syntax)]
#![feature(core_intrinsics)]
#![feature(custom_derive)]
#![feature(fnbox)]
#![feature(optin_builtin_traits)]
#![feature(plugin)]
#![feature(panic_handler)]
#![feature(reflect_marker)]
#![feature(step_by)]

#![plugin(heapsize_plugin, plugins, serde_macros)]

#![deny(unsafe_code)]

extern crate app_units;
extern crate backtrace;
#[allow(unused_extern_crates)]
#[macro_use]
extern crate bitflags;
extern crate deque;
extern crate euclid;
extern crate getopts;
extern crate heapsize;
extern crate ipc_channel;
#[cfg(feature = "non-geckolib")]
extern crate js;
#[allow(unused_extern_crates)]
#[macro_use]
extern crate lazy_static;
extern crate libc;
#[macro_use]
extern crate log;
extern crate num_cpus;
extern crate num_traits;
extern crate rand;
extern crate rustc_serialize;
extern crate serde;
extern crate smallvec;
extern crate string_cache;
extern crate url;

use std::sync::Arc;

pub mod cache;
#[allow(unsafe_code)]
pub mod debug_utils;
pub mod geometry;
#[allow(unsafe_code)]
pub mod ipc;
pub mod linked_list;
#[cfg(feature = "non-geckolib")]
#[allow(unsafe_code)]
pub mod non_geckolib;
#[allow(unsafe_code)]
pub mod opts;
pub mod panicking;
#[allow(unsafe_code)]
pub mod prefs;
pub mod print_tree;
#[allow(unsafe_code)]
pub mod resource_files;
#[allow(unsafe_code)]
pub mod str;
pub mod thread;
pub mod thread_state;
pub mod tid;
pub mod time;
pub mod vec;
#[allow(unsafe_code)]
pub mod workqueue;

#[allow(unsafe_code)]
pub fn breakpoint() {
    unsafe { ::std::intrinsics::breakpoint() };
}

// Workaround for lack of `ptr_eq` on Arcs...
#[inline]
pub fn arc_ptr_eq<T: 'static + Send + Sync>(a: &Arc<T>, b: &Arc<T>) -> bool {
    let a: &T = &**a;
    let b: &T = &**b;
    (a as *const T) == (b as *const T)
}
<commit_msg>Remove unnecessary bounds on arc_ptr_eq.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![feature(box_syntax)]
#![feature(core_intrinsics)]
#![feature(custom_derive)]
#![feature(fnbox)]
#![feature(optin_builtin_traits)]
#![feature(plugin)]
#![feature(panic_handler)]
#![feature(reflect_marker)]
#![feature(step_by)]

#![plugin(heapsize_plugin, plugins, serde_macros)]

#![deny(unsafe_code)]

extern crate app_units;
extern crate backtrace;
#[allow(unused_extern_crates)]
#[macro_use]
extern crate bitflags;
extern crate deque;
extern crate euclid;
extern crate getopts;
extern crate heapsize;
extern crate ipc_channel;
#[cfg(feature = "non-geckolib")]
extern crate js;
#[allow(unused_extern_crates)]
#[macro_use]
extern crate lazy_static;
extern crate libc;
#[macro_use]
extern crate log;
extern crate num_cpus;
extern crate num_traits;
extern crate rand;
extern crate rustc_serialize;
extern crate serde;
extern crate smallvec;
extern crate string_cache;
extern crate url;

use std::sync::Arc;

pub mod cache;
#[allow(unsafe_code)]
pub mod debug_utils;
pub mod geometry;
#[allow(unsafe_code)]
pub mod ipc;
pub mod linked_list;
#[cfg(feature = "non-geckolib")]
#[allow(unsafe_code)]
pub mod non_geckolib;
#[allow(unsafe_code)]
pub mod opts;
pub mod panicking;
#[allow(unsafe_code)]
pub mod prefs;
pub mod print_tree;
#[allow(unsafe_code)]
pub mod resource_files;
#[allow(unsafe_code)]
pub mod str;
pub mod thread;
pub mod thread_state;
pub mod tid;
pub mod time;
pub mod vec;
#[allow(unsafe_code)]
pub mod workqueue;

#[allow(unsafe_code)]
pub fn breakpoint() {
    unsafe { ::std::intrinsics::breakpoint() };
}

// Workaround for lack of `ptr_eq` on Arcs...
#[inline]
pub fn arc_ptr_eq<T: 'static>(a: &Arc<T>, b: &Arc<T>) -> bool {
    let a: &T = &**a;
    let b: &T = &**b;
    (a as *const T) == (b as *const T)
}
<|endoftext|>


<commit_before>use bls::PublicKey;
use futures::Future;
use grpcio::{RpcContext, RpcStatus, RpcStatusCode, UnarySink};
use protos::services::{
    GetDutiesRequest, GetDutiesResponse, Validators};
use protos::services_grpc::ValidatorService;
use slog::{debug, Logger};
use ssz::Decodable;
use std::sync::Arc;
use crate::beacon_chain::BeaconChain;

#[derive(Clone)]
pub struct ValidatorServiceInstance {
    pub chain: Arc<BeaconChain>,
    pub log: Logger,
}
//TODO: Refactor Errors

impl ValidatorService for ValidatorServiceInstance {

    /// For a list of validator public keys, this function returns the slot at which each
    /// validator must propose a block, attest to a shard, their shard committee and the shard they
    /// need to attest to.
    fn get_validator_duties (
        &mut self,
        ctx: RpcContext,
        req: GetDutiesRequest,
        sink: UnarySink<GetDutiesResponse>,
    ) {
        let validators = req.get_validators();
        debug!(self.log, "RPC request"; "endpoint" => "GetValidatorDuties", "epoch" => req.get_epoch());

        let epoch = req.get_epoch();
        let mut resp = GetDutiesResponse::new();

        let spec = self.chain.spec;
        let state = self.chain.state.read();

        //TODO: Decide whether to rebuild the cache
        //TODO: Get the active validator indicies
        //let active_validator_indices = self.chain.state.read().get_cached_active_validator_indices(
        let active_validator_indices = &[1,2,3,4,5,6,7,8];
        // TODO: Is this the most efficient? Perhaps we cache this data structure.

        // this is an array of validators who are to propose this epoch
        // TODO: RelativeEpoch?
        let validator_proposers = 0..spec.slots_per_epoch.to_iter().map(|slot| state.get_beacon_proposer_index(slot, epoch, &spec)).collect();

        // get the duties for each validator
        for validator in validators {
            let active_validator = ActiveValidator::new();

        let public_key = match PublicKey::ssz_decode(validator, 0) {
            Ok((v_) => v,
            Err(_) => {
                let f = sink
                .fail(RpcStatus::new(
                    RpcStatusCode::InvalidArgument,
                    Some("Invalid public_key".to_string()),
                ))
                //TODO: Handle error correctly
                .map_err(move |e| println!("failed to reply {:?}: {:?}", req, e));
                return ctx.spawn(f);
            }
            };

            // is the validator active
            let val_index = match state.get_validator_index(&public_key) {
                Ok(index) => {
                    if active_validator_indices.contains(index) {
                        // validator is active, return the index
                        index
                    }
                    else {
                        // validator is inactive, go to the next validator
                        active_validator.set_none();
                        resp.push(active_validator);
                        break;
                    }
                },
                // the cache is not built, throw an error
                Err(_) =>{
                    let f = sink
                    .fail(RpcStatus::new(
                        RpcStatusCode::FailedPreCondition,
                        Some("Beacon state cache is not built".to_string()),
                    ))
                    //TODO: Handle error correctly
                    .map_err(move |e| println!("failed to reply {:?}: {:?}", req, e));
                    return ctx.spawn(f);
                }
            };

            // we have an active validator, set its duties
            let duty = ValidatorDuty::new();

            // check if it needs to propose a block
            let Some(slot) = validator_proposers.iter().position(|&v| val_index ==v) {
                duty.set_block_production_slot(slot);
            }
            else {
                // no blocks to propose this epoch
                duty.set_none()
            }

            // get attestation duties
            let attestation_duties = match state.get_attestation_duties(val_index, &spec) {
                Ok(v) => v,
                // the cache is not built, throw an error
                Err(_) =>{
                    let f = sink
                    .fail(RpcStatus::new(
                        RpcStatusCode::FailedPreCondition,
                        Some("Beacon state cache is not built".to_string()),
                    ))
                    //TODO: Handle error correctly
                    .map_err(move |e| println!("failed to reply {:?}: {:?}", req, e));
                    return ctx.spawn(f);
                }
            };

            duty.set_committee_index(attestation_duties.committee_index);
            duty.set_attestation_slot(attestation_duties.slot);
            duty.set_attestation_shard(attestation_duties.shard);

            active_validator.set_duty(duty);
            resp.push(active_validator);
            }

        let f = sink
            .success(resp)
            .map_err(move |e| println!("failed to reply {:?}: {:?}", req, e));
        ctx.spawn(f)
    }
}
<commit_msg>Fix beacon node rpc compilation issues<commit_after>use crate::beacon_chain::BeaconChain;
use bls::PublicKey;
use futures::Future;
use grpcio::{RpcContext, RpcStatus, RpcStatusCode, UnarySink};
use protos::services::{ActiveValidator, GetDutiesRequest, GetDutiesResponse, ValidatorDuty};
use protos::services_grpc::ValidatorService;
use slog::{debug, Logger};
use ssz::Decodable;
use std::sync::Arc;

#[derive(Clone)]
pub struct ValidatorServiceInstance {
    pub chain: Arc<BeaconChain>,
    pub log: Logger,
}
//TODO: Refactor Errors

impl ValidatorService for ValidatorServiceInstance {
    /// For a list of validator public keys, this function returns the slot at which each
    /// validator must propose a block, attest to a shard, their shard committee and the shard they
    /// need to attest to.
    fn get_validator_duties(
        &mut self,
        ctx: RpcContext,
        req: GetDutiesRequest,
        sink: UnarySink<GetDutiesResponse>,
    ) {
        let validators = req.get_validators();
        debug!(self.log, "RPC request"; "endpoint" => "GetValidatorDuties", "epoch" => req.get_epoch());

        let epoch = req.get_epoch();
        let mut resp = GetDutiesResponse::new();
        let resp_validators = resp.mut_active_validators();

        let spec = self.chain.get_spec();
        let state = self.chain.get_state();

        //TODO: Decide whether to rebuild the cache
        //TODO: Get the active validator indicies
        //let active_validator_indices = self.chain.state.read().get_cached_active_validator_indices(
        let active_validator_indices = vec![1, 2, 3, 4, 5, 6, 7, 8];
        // TODO: Is this the most efficient? Perhaps we cache this data structure.

        // this is an array of validators who are to propose this epoch
        // TODO: RelativeEpoch?
        //let validator_proposers = [0..spec.slots_per_epoch].iter().map(|slot| state.get_beacon_proposer_index(Slot::from(slot), epoch, &spec)).collect();
        let validator_proposers: Vec<u64> = vec![1, 2, 3, 4, 5];

        // get the duties for each validator
        for validator_pk in validators.get_public_keys() {
            let mut active_validator = ActiveValidator::new();

            let public_key = match PublicKey::ssz_decode(validator_pk, 0) {
                Ok((v, _index)) => v,
                Err(_) => {
                    let f = sink
                        .fail(RpcStatus::new(
                            RpcStatusCode::InvalidArgument,
                            Some("Invalid public_key".to_string()),
                        ))
                        //TODO: Handle error correctly
                        .map_err(move |e| println!("failed to reply {:?}: {:?}", req, e));
                    return ctx.spawn(f);
                }
            };

            // is the validator active
            let val_index = match state.get_validator_index(&public_key) {
                Ok(Some(index)) => {
                    if active_validator_indices.contains(&index) {
                        // validator is active, return the index
                        index
                    } else {
                        // validator is inactive, go to the next validator
                        active_validator.set_none(false);
                        resp_validators.push(active_validator);
                        break;
                    }
                }
                // validator index is not known, skip it
                Ok(_) => {
                    active_validator.set_none(false);
                    resp_validators.push(active_validator);
                    break;
                }
                // the cache is not built, throw an error
                Err(_) => {
                    let f = sink
                        .fail(RpcStatus::new(
                            RpcStatusCode::FailedPrecondition,
                            Some("Beacon state cache is not built".to_string()),
                        ))
                        //TODO: Handle error correctly
                        .map_err(move |e| println!("failed to reply {:?}: {:?}", req, e));
                    return ctx.spawn(f);
                }
            };

            // we have an active validator, set its duties
            let mut duty = ValidatorDuty::new();

            // check if the validator needs to propose a block
            if let Some(slot) = validator_proposers
                .iter()
                .position(|&v| val_index as u64 == v)
            {
                duty.set_block_production_slot(epoch * spec.slots_per_epoch + slot as u64);
            } else {
                // no blocks to propose this epoch
                duty.set_none(false)
            }

            // get attestation duties
            let attestation_duties = match state.get_attestation_duties(val_index, &spec) {
                Ok(Some(v)) => v,
                Ok(_) => unreachable!(), //we've checked the validator index
                // the cache is not built, throw an error
                Err(_) => {
                    let f = sink
                        .fail(RpcStatus::new(
                            RpcStatusCode::FailedPrecondition,
                            Some("Beacon state cache is not built".to_string()),
                        ))
                        //TODO: Handle error correctly
                        .map_err(move |e| println!("failed to reply {:?}: {:?}", req, e));
                    return ctx.spawn(f);
                }
            };

            duty.set_committee_index(attestation_duties.committee_index as u64);
            duty.set_attestation_slot(attestation_duties.slot.as_u64());
            duty.set_attestation_shard(attestation_duties.shard);

            active_validator.set_duty(duty);
            resp_validators.push(active_validator);
        }

        let f = sink
            .success(resp)
            .map_err(move |e| println!("failed to reply {:?}: {:?}", req, e));
        ctx.spawn(f)
    }
}
<|endoftext|>


<commit_before>extern crate getopts;
use getopts::Options;
use std::env;
use std::fs::File;
use std::io;
use std::io::Read;
use std::mem;

fn pointer_size() -> usize {
    let tmp = 0u8;
    let boxed = Box::new(tmp);
    mem::size_of_val(&boxed)
}

fn read_blend_file(inp: &str) -> io::Result<()> {
    // open file
    let file = try!(File::open(inp));
    // read 12 bytes from the Blender file
    let mut take = file.take(12u64);
    let mut header = String::new();
    try!(take.read_to_string(&mut header));
    println!("header = \"{}\"", header);
    // compare first 7 chars to "BLENDER"
    if header.len() >= 7 {
        // create copy of header without moving value
        let mut blender = String::new();
        blender = blender + &header;
        blender.truncate(7); // first 7 chars
        if blender == "BLENDER" {
            println!("starts with \"BLENDER\" ...");
            // TODO: check version (next 5 chars in header)

            // switch to byte copy of String representation
            let bytes = header.into_bytes();
            // check 8th char of header
            println!("8th char of header = '{}'", bytes[7] as char);
            // check for 32-bit pointers vs. 64-bit pointers
            let ptr_size = pointer_size();
            println!("size of pointer in bytes: {}", ptr_size);
            let mut ptr_size_differs = false;
            if bytes[7] as char == '_' {
                // 32-bit pointers expected
                if ptr_size != 4 {
                    ptr_size_differs = true;
                }
                println!("32-bit pointers in file, pointer size differs? {}",
                         ptr_size_differs);
            } else {
                // 64-bit pointers expected
                if ptr_size != 8 {
                        ptr_size_differs = true;
                }
                println!("64-bit pointers in file, pointer size differs? {}",
                         ptr_size_differs);
            }
        } else {
            println!("ERROR: FILE is not a Blender file");
        }
    } else {
        println!("ERROR: FILE is not a Blender file");
    }
    Ok(())
}

fn do_work(inp: &str, out: Option<String>) {
    println!("FILE = {}", inp);
    match out {
        Some(x) => println!("output file name: {}", x),
        None => println!("no output file name"),
    }
    match read_blend_file(inp) {
        Ok(_) => { ; }
        Err(f) => { panic!(f.to_string()) }
    };
}

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} FILE [options]", program);
    print!("{}", opts.usage(&brief));
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();

    let mut opts = Options::new();
    opts.optopt("o", "", "set output file name", "NAME");
    opts.optflag("h", "help", "print this help menu");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => { panic!(f.to_string()) }
    };
    if matches.opt_present("h") {
        print_usage(&program, opts);
        return;
    }
    let output = matches.opt_str("o");
    let input = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        print_usage(&program, opts);
        return;
    };
    do_work(&input, output);
}
<commit_msg>Little endian or big endian? Need to switch?<commit_after>extern crate getopts;
use getopts::Options;
use std::env;
use std::fs::File;
use std::io;
use std::io::Read;
use std::mem;

fn pointer_size() -> usize {
    let tmp = 0u8;
    let boxed = Box::new(tmp);
    mem::size_of_val(&boxed)
}

fn read_blend_file(inp: &str) -> io::Result<()> {
    // open file
    let file = try!(File::open(inp));
    // read 12 bytes from the Blender file
    let mut take = file.take(12u64);
    let mut header = String::new();
    try!(take.read_to_string(&mut header));
    println!("header = \"{}\"", header);
    // compare first 7 chars to "BLENDER"
    if header.len() >= 7 {
        // create copy of header without moving value
        let mut blender = String::new();
        blender = blender + &header;
        blender.truncate(7); // first 7 chars
        if blender == "BLENDER" {
            println!("starts with \"BLENDER\" ...");
            // TODO: check version (next 5 chars in header)

            // switch to byte copy of String representation
            let bytes = header.into_bytes();
            // check 8th char of header
            println!("8th char of header = '{}'", bytes[7] as char);
            // check for 32-bit pointers vs. 64-bit pointers
            let ptr_size = pointer_size();
            println!("size of pointer in bytes: {}", ptr_size);
            let mut ptr_size_differs = false;
            if bytes[7] as char == '_' {
                // 32-bit pointers expected
                if ptr_size != 4 {
                    ptr_size_differs = true;
                }
                println!("32-bit pointers in file, pointer size differs? {}",
                         ptr_size_differs);
            } else {
                // 64-bit pointers expected
                if ptr_size != 8 {
                    ptr_size_differs = true;
                }
                println!("64-bit pointers in file, pointer size differs? {}",
                         ptr_size_differs);
            }
            // little endian or big endian?
            let mut l_endian;
            let endian_test = 1u16; // value one stored in two bytes
            if endian_test.to_le() != endian_test {
                l_endian = false;
            } else {
                // if we are on a little endian machine to_le() is a no-op
                l_endian = true;
            }
            println!("l_endian = {}", l_endian);
            let mut switch_endian;
            if bytes[8] as char == 'v' {
                // file stores little endian
                if !l_endian {
                    switch_endian = true;
                } else {
                    switch_endian = false;
                }
            } else {
                // file stores big endian
                if l_endian {
                    switch_endian = true;
                } else {
                    switch_endian = false;
                }
            }
            println!("switch_endian = {}", switch_endian);
            // TODO: get the version number
        } else {
            println!("ERROR: FILE is not a Blender file");
        }
    } else {
        println!("ERROR: FILE is not a Blender file");
    }
    Ok(())
}

fn do_work(inp: &str, out: Option<String>) {
    println!("FILE = {}", inp);
    match out {
        Some(x) => println!("output file name: {}", x),
        None => println!("no output file name"),
    }
    match read_blend_file(inp) {
        Ok(_) => { ; }
        Err(f) => { panic!(f.to_string()) }
    };
}

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} FILE [options]", program);
    print!("{}", opts.usage(&brief));
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();

    let mut opts = Options::new();
    opts.optopt("o", "", "set output file name", "NAME");
    opts.optflag("h", "help", "print this help menu");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => { panic!(f.to_string()) }
    };
    if matches.opt_present("h") {
        print_usage(&program, opts);
        return;
    }
    let output = matches.opt_str("o");
    let input = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        print_usage(&program, opts);
        return;
    };
    do_work(&input, output);
}
<|endoftext|>


<commit_before>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use syntax::codemap::Span;
use std::collections::hashmap;
use std::gc::Gc;

pub enum AttributeValue {
  UIntValue(uint),
  StrValue(String),
  RefValue(String),
}

pub struct Attribute {
  pub value: AttributeValue,
  pub key_span: Span,
  pub value_span: Span,
}

impl Attribute {
  pub fn new(value: AttributeValue, key_span: Span, value_span: Span)
      -> Attribute {
    Attribute {
      value: value,
      key_span: key_span,
      value_span: value_span,
    }
  }
}

pub struct Node {
  pub name: Option<String>,
  pub name_span: Span,

  pub path: String,
  pub path_span: Span,

  pub attributes: hashmap::HashMap<String, Attribute>,

  pub subnodes: Vec<Gc<Node>>,
}

impl Node {
  pub fn new(name: Option<String>, name_span: Span, path: String,
      path_span: Span) -> Node {
    Node {
      name: name,
      name_span: name_span,
      path: path,
      path_span: path_span,
      attributes: hashmap::HashMap::new(),
      subnodes: Vec::new(),
    }
  }

  pub fn get_string_attr<'a>(&'a self, key: &str) -> Option<&'a String> {
    let val = self.attributes.find(&key.to_str());
    match val {
      Some(av) => {
        match av.value {
          StrValue(ref s) => Some(s),
          _ => None,
        }
      }
      None => None,
    }
  }

  pub fn get_int_attr(&self, key: &str) -> Option<uint> {
    let val = self.attributes.find(&key.to_str());
    match val {
      Some(av) => {
        match av.value {
          UIntValue(ref u) => Some(*u),
          _ => None,
        }
      }
      None => None,
    }
  }
}

pub struct PlatformTree {
  pub nodes: Vec<Gc<Node>>,
}

impl PlatformTree {
  pub fn new(nodes: Vec<Gc<Node>>) -> PlatformTree {
    PlatformTree {nodes: nodes}
  }
}
<commit_msg>Simplified some Option handling code.<commit_after>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use syntax::codemap::Span;
use std::collections::hashmap;
use std::gc::Gc;

pub enum AttributeValue {
  UIntValue(uint),
  StrValue(String),
  RefValue(String),
}

pub struct Attribute {
  pub value: AttributeValue,
  pub key_span: Span,
  pub value_span: Span,
}

impl Attribute {
  pub fn new(value: AttributeValue, key_span: Span, value_span: Span)
      -> Attribute {
    Attribute {
      value: value,
      key_span: key_span,
      value_span: value_span,
    }
  }
}

pub struct Node {
  pub name: Option<String>,
  pub name_span: Span,

  pub path: String,
  pub path_span: Span,

  pub attributes: hashmap::HashMap<String, Attribute>,

  pub subnodes: Vec<Gc<Node>>,
}

impl Node {
  pub fn new(name: Option<String>, name_span: Span, path: String,
      path_span: Span) -> Node {
    Node {
      name: name,
      name_span: name_span,
      path: path,
      path_span: path_span,
      attributes: hashmap::HashMap::new(),
      subnodes: Vec::new(),
    }
  }

  pub fn get_string_attr<'a>(&'a self, key: &str) -> Option<&'a String> {
    self.attributes.find(&key.to_str()).and_then(|av| match av.value {
      StrValue(ref s) => Some(s),
      _ => None,
    })
  }

  pub fn get_int_attr(&self, key: &str) -> Option<uint> {
    self.attributes.find(&key.to_str()).and_then(|av| match av.value {
      UIntValue(ref u) => Some(*u),
      _ => None,
    })
  }
}

pub struct PlatformTree {
  pub nodes: Vec<Gc<Node>>,
}

impl PlatformTree {
  pub fn new(nodes: Vec<Gc<Node>>) -> PlatformTree {
    PlatformTree {nodes: nodes}
  }
}
<|endoftext|>


<commit_before>use std::usize;

#[derive(Eq, PartialEq, Clone, Hash)]
pub struct BitVec {
    inner: Vec<usize>,
    units: usize,
    bits: usize,
    max_bits: usize,
    leftover: usize,
}

impl BitVec {
    pub fn new(bits: usize) -> BitVec {
        let max = usize::MAX.count_ones() as usize;
        if bits > max {
            // We can store more bits, but then we might need BigInt to get them out!
            panic!("cannot hold more than {} bits at a time", max);
        }

        BitVec {
            inner: vec![0],
            units: 0,
            bits: bits,
            max_bits: max,
            leftover: max,
        }
    }

    pub fn push(&mut self, mut value: usize) {
        if value >> self.bits != 0 {
            panic!("size of {} is more than allowed bits ({})", value, self.bits)
        }

        let mut idx = self.inner.len() - 1;
        let shift_amount;

        if self.leftover < self.bits {
            let left = self.bits - self.leftover;
            self.inner[idx] |= value >> left;
            if self.leftover != 0 {     // special case, in which masking would result in zero!
                value &= 1 << (left - 1);
            }

            self.inner.push(0);
            self.leftover = self.max_bits - left;
            shift_amount = self.max_bits - left;
            idx += 1;
        } else {
            shift_amount = self.leftover - self.bits;
            self.leftover -= self.bits;
        }

        value <<= shift_amount;
        self.inner[idx] |= value;
        self.units += 1;
    }

    pub fn len(&self) -> usize {
        self.units
    }

    pub fn inner_len(&self) -> usize {
        self.inner.len()
    }
}
<commit_msg>Working get and push<commit_after>use std::usize;

#[derive(Eq, PartialEq, Clone, Hash)]
pub struct BitsVec {
    inner: Vec<usize>,
    units: usize,
    bits: usize,
    max_bits: usize,
    leftover: usize,
}

impl BitsVec {
    pub fn new(bits: usize) -> BitsVec {
        let max = usize::MAX.count_ones() as usize;
        if bits > max {
            // We can store more bits, but then we might need BigInt to get them out!
            panic!("cannot hold more than {} bits at a time", max);
        }

        BitsVec {
            inner: vec![0],
            units: 0,
            bits: bits,
            max_bits: max,
            leftover: max,
        }
    }

    pub fn push(&mut self, mut value: usize) {
        assert!(value >> self.bits == 0,
                "input size is more than allowed size ({} >= {})", value, 2usize.pow(self.bits as u32));

        let mut idx = self.inner.len() - 1;
        let shift_amount;

        if self.leftover < self.bits {
            let left = self.bits - self.leftover;
            self.inner[idx] |= value >> left;
            if self.leftover != 0 {     // special case, in which masking would result in zero!
                value &= (1 << left) - 1;
            }

            self.inner.push(0);
            self.leftover = self.max_bits - left;
            shift_amount = self.max_bits - left;
            idx += 1;
        } else {
            shift_amount = self.leftover - self.bits;
            self.leftover -= self.bits;
        }

        value <<= shift_amount;
        self.inner[idx] |= value;
        self.units += 1;
    }

    pub fn get(&self, i: usize) -> Option<usize> {
        if i >= self.units {
            return None
        }

        let idx = i * self.bits / self.max_bits;
        let bits = (i * self.bits) % self.max_bits;
        let mut val = self.inner[idx];
        if bits != 0 {
            val &= (1 << (self.max_bits - bits)) - 1;
        }

        let diff = self.max_bits - bits;
        if diff >= self.bits {
            Some(val >> (diff - self.bits))
        } else {
            let shift = self.bits - diff;
            Some((val << shift) | (self.inner[idx + 1] >> (self.max_bits - shift)))
        }
    }

    pub fn len(&self) -> usize {
        self.units
    }

    pub fn inner_len(&self) -> usize {
        self.inner.len()
    }
}
<|endoftext|>


<commit_before>// A module for searching for libraries
// FIXME: I'm not happy how this module turned out. Should probably
// just be folded into cstore.

import result::result;
export filesearch;
export mk_filesearch;
export pick;
export pick_file;
export search;
export relative_target_lib_path;
export get_cargo_sysroot;
export get_cargo_root;
export get_cargo_root_nearest;
export libdir;

import path::path;

type pick<T> = fn(path: path) -> option<T>;

fn pick_file(file: path, path: path) -> option<path> {
    if path::basename(path) == file { option::some(path) }
    else { option::none }
}

iface filesearch {
    fn sysroot() -> path;
    fn lib_search_paths() -> [path];
    fn get_target_lib_path() -> path;
    fn get_target_lib_file_path(file: path) -> path;
}

fn mk_filesearch(maybe_sysroot: option<path>,
                 target_triple: str,
                 addl_lib_search_paths: [path]) -> filesearch {
    type filesearch_impl = {sysroot: path,
                            addl_lib_search_paths: [path],
                            target_triple: str};
    impl of filesearch for filesearch_impl {
        fn sysroot() -> path { self.sysroot }
        fn lib_search_paths() -> [path] {
            self.addl_lib_search_paths
                + [make_target_lib_path(self.sysroot, self.target_triple)]
                + alt get_cargo_lib_path_nearest() {
                  result::ok(p) { [p] }
                  result::err(p) { [] }
                }
                + alt get_cargo_lib_path() {
                  result::ok(p) { [p] }
                  result::err(p) { [] }
                }
        }
        fn get_target_lib_path() -> path {
            make_target_lib_path(self.sysroot, self.target_triple)
        }
        fn get_target_lib_file_path(file: path) -> path {
            path::connect(self.get_target_lib_path(), file)
        }
    }

    let sysroot = get_sysroot(maybe_sysroot);
    #debug("using sysroot = %s", sysroot);
    {sysroot: sysroot,
     addl_lib_search_paths: addl_lib_search_paths,
     target_triple: target_triple} as filesearch
}

// FIXME #1001: This can't be an obj method
fn search<T: copy>(filesearch: filesearch, pick: pick<T>) -> option<T> {
    let mut rslt = none;
    for filesearch.lib_search_paths().each {|lib_search_path|
        #debug("searching %s", lib_search_path);
        for os::list_dir_path(lib_search_path).each {|path|
            #debug("testing %s", path);
            let maybe_picked = pick(path);
            if option::is_some(maybe_picked) {
                #debug("picked %s", path);
                rslt = maybe_picked;
                break;
            } else {
                #debug("rejected %s", path);
            }
        }
        if option::is_some(rslt) { break; }
    }
    ret rslt;
}

fn relative_target_lib_path(target_triple: str) -> [path] {
    [libdir(), "rustc", target_triple, libdir()]
}

fn make_target_lib_path(sysroot: path,
                        target_triple: str) -> path {
    let path = [sysroot] + relative_target_lib_path(target_triple);
    let path = path::connect_many(path);
    ret path;
}

fn get_default_sysroot() -> path {
    alt os::self_exe_path() {
      option::some(p) { path::normalize(path::connect(p, "..")) }
      option::none {
        fail "can't determine value for sysroot";
      }
    }
}

fn get_sysroot(maybe_sysroot: option<path>) -> path {
    alt maybe_sysroot {
      option::some(sr) { sr }
      option::none { get_default_sysroot() }
    }
}

fn get_cargo_sysroot() -> result<path, str> {
    let path = [get_default_sysroot(), libdir(), "cargo"];
    result::ok(path::connect_many(path))
}

fn get_cargo_root() -> result<path, str> {
    alt os::getenv("CARGO_ROOT") {
        some(_p) { result::ok(_p) }
        none {
          alt os::homedir() {
            some(_q) { result::ok(path::connect(_q, ".cargo")) }
            none { result::err("no CARGO_ROOT or home directory") }
          }
        }
    }
}

fn get_cargo_root_nearest() -> result<path, str> {
    result::chain(get_cargo_root()) { |p|
        let cwd = os::getcwd();
        let mut dirname = path::dirname(cwd);
        let mut dirpath = path::split(dirname);
        let cwd_cargo = path::connect(cwd, ".cargo");
        let mut par_cargo = path::connect(dirname, ".cargo");
        let mut rslt = result::ok(cwd_cargo);

        if !os::path_is_dir(cwd_cargo) && cwd_cargo != p {
            while vec::is_not_empty(dirpath) && par_cargo != p {
                if os::path_is_dir(par_cargo) {
                    rslt = result::ok(par_cargo);
                    break;
                }
                vec::pop(dirpath);
                dirname = path::dirname(dirname);
                par_cargo = path::connect(dirname, ".cargo");
            }
        }
        rslt
    }
}

fn get_cargo_lib_path() -> result<path, str> {
    result::chain(get_cargo_root()) { |p|
        result::ok(path::connect(p, libdir()))
    }
}

fn get_cargo_lib_path_nearest() -> result<path, str> {
    result::chain(get_cargo_root_nearest()) { |p|
        result::ok(path::connect(p, libdir()))
    }
}

// The name of the directory rustc expects libraries to be located.
// On Unix should be "lib", on windows "bin"
fn libdir() -> str {
   let libdir = #env("CFG_LIBDIR");
   if str::is_empty(libdir) {
      fail "rustc compiled without CFG_LIBDIR environment variable";
   }
   libdir
}
<commit_msg>Remove a FIXME note about closed issue #1001<commit_after>// A module for searching for libraries
// FIXME: I'm not happy how this module turned out. Should probably
// just be folded into cstore.

import result::result;
export filesearch;
export mk_filesearch;
export pick;
export pick_file;
export search;
export relative_target_lib_path;
export get_cargo_sysroot;
export get_cargo_root;
export get_cargo_root_nearest;
export libdir;

import path::path;

type pick<T> = fn(path: path) -> option<T>;

fn pick_file(file: path, path: path) -> option<path> {
    if path::basename(path) == file { option::some(path) }
    else { option::none }
}

iface filesearch {
    fn sysroot() -> path;
    fn lib_search_paths() -> [path];
    fn get_target_lib_path() -> path;
    fn get_target_lib_file_path(file: path) -> path;
}

fn mk_filesearch(maybe_sysroot: option<path>,
                 target_triple: str,
                 addl_lib_search_paths: [path]) -> filesearch {
    type filesearch_impl = {sysroot: path,
                            addl_lib_search_paths: [path],
                            target_triple: str};
    impl of filesearch for filesearch_impl {
        fn sysroot() -> path { self.sysroot }
        fn lib_search_paths() -> [path] {
            self.addl_lib_search_paths
                + [make_target_lib_path(self.sysroot, self.target_triple)]
                + alt get_cargo_lib_path_nearest() {
                  result::ok(p) { [p] }
                  result::err(p) { [] }
                }
                + alt get_cargo_lib_path() {
                  result::ok(p) { [p] }
                  result::err(p) { [] }
                }
        }
        fn get_target_lib_path() -> path {
            make_target_lib_path(self.sysroot, self.target_triple)
        }
        fn get_target_lib_file_path(file: path) -> path {
            path::connect(self.get_target_lib_path(), file)
        }
    }

    let sysroot = get_sysroot(maybe_sysroot);
    #debug("using sysroot = %s", sysroot);
    {sysroot: sysroot,
     addl_lib_search_paths: addl_lib_search_paths,
     target_triple: target_triple} as filesearch
}

fn search<T: copy>(filesearch: filesearch, pick: pick<T>) -> option<T> {
    let mut rslt = none;
    for filesearch.lib_search_paths().each {|lib_search_path|
        #debug("searching %s", lib_search_path);
        for os::list_dir_path(lib_search_path).each {|path|
            #debug("testing %s", path);
            let maybe_picked = pick(path);
            if option::is_some(maybe_picked) {
                #debug("picked %s", path);
                rslt = maybe_picked;
                break;
            } else {
                #debug("rejected %s", path);
            }
        }
        if option::is_some(rslt) { break; }
    }
    ret rslt;
}

fn relative_target_lib_path(target_triple: str) -> [path] {
    [libdir(), "rustc", target_triple, libdir()]
}

fn make_target_lib_path(sysroot: path,
                        target_triple: str) -> path {
    let path = [sysroot] + relative_target_lib_path(target_triple);
    let path = path::connect_many(path);
    ret path;
}

fn get_default_sysroot() -> path {
    alt os::self_exe_path() {
      option::some(p) { path::normalize(path::connect(p, "..")) }
      option::none {
        fail "can't determine value for sysroot";
      }
    }
}

fn get_sysroot(maybe_sysroot: option<path>) -> path {
    alt maybe_sysroot {
      option::some(sr) { sr }
      option::none { get_default_sysroot() }
    }
}

fn get_cargo_sysroot() -> result<path, str> {
    let path = [get_default_sysroot(), libdir(), "cargo"];
    result::ok(path::connect_many(path))
}

fn get_cargo_root() -> result<path, str> {
    alt os::getenv("CARGO_ROOT") {
        some(_p) { result::ok(_p) }
        none {
          alt os::homedir() {
            some(_q) { result::ok(path::connect(_q, ".cargo")) }
            none { result::err("no CARGO_ROOT or home directory") }
          }
        }
    }
}

fn get_cargo_root_nearest() -> result<path, str> {
    result::chain(get_cargo_root()) { |p|
        let cwd = os::getcwd();
        let mut dirname = path::dirname(cwd);
        let mut dirpath = path::split(dirname);
        let cwd_cargo = path::connect(cwd, ".cargo");
        let mut par_cargo = path::connect(dirname, ".cargo");
        let mut rslt = result::ok(cwd_cargo);

        if !os::path_is_dir(cwd_cargo) && cwd_cargo != p {
            while vec::is_not_empty(dirpath) && par_cargo != p {
                if os::path_is_dir(par_cargo) {
                    rslt = result::ok(par_cargo);
                    break;
                }
                vec::pop(dirpath);
                dirname = path::dirname(dirname);
                par_cargo = path::connect(dirname, ".cargo");
            }
        }
        rslt
    }
}

fn get_cargo_lib_path() -> result<path, str> {
    result::chain(get_cargo_root()) { |p|
        result::ok(path::connect(p, libdir()))
    }
}

fn get_cargo_lib_path_nearest() -> result<path, str> {
    result::chain(get_cargo_root_nearest()) { |p|
        result::ok(path::connect(p, libdir()))
    }
}

// The name of the directory rustc expects libraries to be located.
// On Unix should be "lib", on windows "bin"
fn libdir() -> str {
   let libdir = #env("CFG_LIBDIR");
   if str::is_empty(libdir) {
      fail "rustc compiled without CFG_LIBDIR environment variable";
   }
   libdir
}
<|endoftext|>


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

use futures::prelude::*;
use futures::task;
use futures::task::{Poll};
use futures::channel::oneshot;

use std::mem;
use std::pin::*;

///
/// The state of a SyncFuture operation
///
enum SyncFutureState<TFn, TFuture>
where TFuture: Future {
    /// Waiting for the queue to start running the future
    WaitingForQueue(oneshot::Receiver<()>, TFn),

    /// Evaluating an active future for its result
    WaitingForFuture(TFuture),

    /// The sync future has completed and now we're waiting for the scheduler to complete
    WaitingForScheduler(Box<TFuture::Output>),

    /// Finished evaluating
    Completed
}

///
/// Represents a future that runs synchronously with a queue
///
/// The future is only run in an exclusive time slot within the queue - this property is used to guarantee the
/// safety of `Desync::future_sync`, which provides exclusive access to the data store while the future is running.
/// The queue is allowed to continue once the returned future has completed.
///
pub struct SyncFuture<TFn, TFuture>
where   TFn:                Send+FnOnce() -> TFuture,
        TFuture:            Send+Future,
        TFuture::Output:    Send {
    /// The state of this future
    state: SyncFutureState<TFn, TFuture>,

    /// Tracks this future on the scheduler (this allows polling this future to invoke desync's thread-stealing semantics instead of leaving the queue scheduling to a separate thread)
    scheduler_future: SchedulerFuture<()>,

    /// Signals when the future has finished running (None if this future is completed)
    task_finished: Option<oneshot::Sender<()>>
}

impl<TFn, TFuture> SyncFuture<TFn, TFuture>
where   TFn:                Send+FnOnce() -> TFuture,
        TFuture:            Send+Future,
        TFuture::Output:    Send {
    ///
    /// Creates a new SyncFuture
    ///
    pub fn new(create_future: TFn, scheduler_future: SchedulerFuture<()>, queue_ready: oneshot::Receiver<()>, task_finished: oneshot::Sender<()>) -> SyncFuture<TFn, TFuture> {
        SyncFuture {
            state:              SyncFutureState::WaitingForQueue(queue_ready, create_future),
            scheduler_future:   scheduler_future,
            task_finished:      Some(task_finished)
        }
    }
}

impl<TFn, TFuture> Future for SyncFuture<TFn, TFuture>
where   TFn:                Unpin+Send+FnOnce() -> TFuture,
        TFuture:            Unpin+Send+Future,
        TFuture::Output:    Send {
    type Output = Result<TFuture::Output, oneshot::Canceled>;

    fn poll(mut self: Pin<&mut Self>, context: &mut task::Context) -> Poll<Self::Output> {
        use self::SyncFutureState::*;

        // Rust doesn't seem to have a way to let us update the state in-place, so we need to swap out the old state and swap in the new state
        let mut result;
        let mut state = Completed;
        mem::swap(&mut state, &mut self.state);

        // Update the state now we own it
        loop {
            // Set to true if a 'pending' result should trigger another state update (eg, if we start a new future, we should poll it)
            let mut retry = false;

            state = match state {
                WaitingForQueue(mut recv, create_future) => {
                    // Check the scheduler future (give it a chance to steal the thread)
                    if let Poll::Ready(Err(_)) = self.scheduler_future.poll_unpin(context) {
                        // The queue will never get to the point of polling this future
                        result = Poll::Ready(Err(oneshot::Canceled));
                        self.task_finished.take().map(|finished| finished.send(()));
                        Completed
                    } else {
                        // Poll the receiver
                        match recv.poll_unpin(context) {
                            Poll::Ready(Ok(())) => {
                                // Start the future
                                let future = create_future();

                                // Poll it immediately to determine its status
                                result = Poll::Pending;

                                retry = true;
                                WaitingForFuture(future)
                            }

                            Poll::Ready(Err(_)) => {
                                // Future never became ready
                                result = Poll::Ready(Err(oneshot::Canceled));
                                Completed
                            }

                            Poll::Pending => {
                                // Waiting for the queue to start this future
                                result = Poll::Pending;
                                WaitingForQueue(recv, create_future)
                            }
                        }
                    }
                }

                WaitingForFuture(mut future) => {
                    if let Poll::Ready(future_result) = future.poll_unpin(context) {
                        // Future has completed
                        result = Poll::Pending;
                        self.task_finished.take().map(|finished| finished.send(()));

                        retry = true;
                        WaitingForScheduler(Box::new(future_result))
                    } else {
                        // Future is still running
                        result = Poll::Pending;
                        WaitingForFuture(future)
                    }
                }

                WaitingForScheduler(future_result) => {
                    // Poll until the scheduler has finished running the task entirely (can deadlock while draining if we don't)
                    if true {
                        result = Poll::Ready(Ok(*future_result));
                        Completed
                    } else {
                        result = Poll::Pending;
                        WaitingForScheduler(future_result)
                    }
                }

                Completed => {
                    // Polling after the result has been returned
                    result = Poll::Ready(Err(oneshot::Canceled));
                    Completed
                }
            };

            // Finish once retry is left at false
            if !retry {
                break;
            }
        }

        // Swap the state back into the structure
        self.state = state;

        result
    }
}
<commit_msg>Need to signal the scheduler for the sync futures test to pass<commit_after>use super::scheduler_future::*;

use futures::prelude::*;
use futures::task;
use futures::task::{Poll};
use futures::channel::oneshot;

use std::mem;
use std::pin::*;

///
/// The state of a SyncFuture operation
///
enum SyncFutureState<TFn, TFuture>
where TFuture: Future {
    /// Waiting for the queue to start running the future
    WaitingForQueue(oneshot::Receiver<()>, TFn),

    /// Evaluating an active future for its result
    WaitingForFuture(TFuture),

    /// The sync future has completed and now we're waiting for the scheduler to complete
    WaitingForScheduler(Box<TFuture::Output>),

    /// Finished evaluating
    Completed
}

///
/// Represents a future that runs synchronously with a queue
///
/// The future is only run in an exclusive time slot within the queue - this property is used to guarantee the
/// safety of `Desync::future_sync`, which provides exclusive access to the data store while the future is running.
/// The queue is allowed to continue once the returned future has completed.
///
pub struct SyncFuture<TFn, TFuture>
where   TFn:                Send+FnOnce() -> TFuture,
        TFuture:            Send+Future,
        TFuture::Output:    Send {
    /// The state of this future
    state: SyncFutureState<TFn, TFuture>,

    /// Tracks this future on the scheduler (this allows polling this future to invoke desync's thread-stealing semantics instead of leaving the queue scheduling to a separate thread)
    scheduler_future: SchedulerFuture<()>,

    /// Signals when the future has finished running (None if this future is completed)
    task_finished: Option<oneshot::Sender<()>>
}

impl<TFn, TFuture> SyncFuture<TFn, TFuture>
where   TFn:                Send+FnOnce() -> TFuture,
        TFuture:            Send+Future,
        TFuture::Output:    Send {
    ///
    /// Creates a new SyncFuture
    ///
    pub fn new(create_future: TFn, scheduler_future: SchedulerFuture<()>, queue_ready: oneshot::Receiver<()>, task_finished: oneshot::Sender<()>) -> SyncFuture<TFn, TFuture> {
        SyncFuture {
            state:              SyncFutureState::WaitingForQueue(queue_ready, create_future),
            scheduler_future:   scheduler_future,
            task_finished:      Some(task_finished)
        }
    }
}

impl<TFn, TFuture> Future for SyncFuture<TFn, TFuture>
where   TFn:                Unpin+Send+FnOnce() -> TFuture,
        TFuture:            Unpin+Send+Future,
        TFuture::Output:    Send {
    type Output = Result<TFuture::Output, oneshot::Canceled>;

    fn poll(mut self: Pin<&mut Self>, context: &mut task::Context) -> Poll<Self::Output> {
        use self::SyncFutureState::*;

        // Rust doesn't seem to have a way to let us update the state in-place, so we need to swap out the old state and swap in the new state
        let mut result;
        let mut state = Completed;
        mem::swap(&mut state, &mut self.state);

        // Update the state now we own it
        loop {
            // Set to true if a 'pending' result should trigger another state update (eg, if we start a new future, we should poll it)
            let mut retry = false;

            state = match state {
                WaitingForQueue(mut recv, create_future) => {
                    // Check the scheduler future (give it a chance to steal the thread)
                    if let Poll::Ready(Err(_)) = self.scheduler_future.poll_unpin(context) {
                        // The queue will never get to the point of polling this future
                        result = Poll::Ready(Err(oneshot::Canceled));
                        self.task_finished.take().map(|finished| finished.send(()));
                        Completed
                    } else {
                        // Poll the receiver
                        match recv.poll_unpin(context) {
                            Poll::Ready(Ok(())) => {
                                // Start the future
                                let future = create_future();

                                // Poll it immediately to determine its status
                                result = Poll::Pending;

                                retry = true;
                                WaitingForFuture(future)
                            }

                            Poll::Ready(Err(_)) => {
                                // Future never became ready
                                result = Poll::Ready(Err(oneshot::Canceled));
                                Completed
                            }

                            Poll::Pending => {
                                // Waiting for the queue to start this future
                                result = Poll::Pending;
                                WaitingForQueue(recv, create_future)
                            }
                        }
                    }
                }

                WaitingForFuture(mut future) => {
                    if let Poll::Ready(future_result) = future.poll_unpin(context) {
                        // Future has completed
                        result = Poll::Pending;
                        self.task_finished.take().map(|finished| finished.send(()));

                        retry = true;
                        WaitingForScheduler(Box::new(future_result))
                    } else {
                        // Future is still running
                        result = Poll::Pending;
                        WaitingForFuture(future)
                    }
                }

                WaitingForScheduler(future_result) => {
                    // Poll until the scheduler has finished running the task entirely (can deadlock while draining if we don't)
                    if let Poll::Ready(_) = self.scheduler_future.poll_unpin(context) {
                        result = Poll::Ready(Ok(*future_result));
                        Completed
                    } else {
                        result = Poll::Pending;
                        WaitingForScheduler(future_result)
                    }
                }

                Completed => {
                    // Polling after the result has been returned
                    result = Poll::Ready(Err(oneshot::Canceled));
                    Completed
                }
            };

            // Finish once retry is left at false
            if !retry {
                break;
            }
        }

        // Swap the state back into the structure
        self.state = state;

        result
    }
}
<|endoftext|>


<commit_before>//! Abstractions for page tables and other paging related structures.

pub use self::page_table::*;

use addr::{VirtAddr, PhysAddr};
use core::ops::{Add, AddAssign, Sub, SubAssign};
use ux::*;

mod page_table;

/// The default page size on x86_64.
pub const PAGE_SIZE: u16 = 4096;

/// A virtual 4kB page.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Page {
   number: u64,
}

impl Page {
    /// Returns the page that contains the given virtual address.
    pub fn containing_address(address: VirtAddr) -> Page {
        Page { number: address.as_u64() / u64::from(PAGE_SIZE) }
    }

    /// Returns the start address of the page.
    pub fn start_address(&self) -> VirtAddr {
        VirtAddr::new(self.number * u64::from(PAGE_SIZE))
    }

    /// Returns the level 4 page table index of this page.
    pub fn p4_index(&self) -> u9 {
        self.start_address().p4_index()
    }

    /// Returns the level 3 page table index of this page.
    pub fn p3_index(&self) -> u9 {
        self.start_address().p3_index()
    }

    /// Returns the level 2 page table index of this page.
    pub fn p2_index(&self) -> u9 {
        self.start_address().p2_index()
    }

    /// Returns the level 1 page table index of this page.
    pub fn p1_index(&self) -> u9 {
        self.start_address().p1_index()
    }
}

impl Add<u64> for Page {
    type Output = Self;
    fn add(self, rhs: u64) -> Self::Output {
        Page::containing_address(self.start_address() + rhs * u64::from(PAGE_SIZE))
    }
}

impl AddAssign<u64> for Page {
    fn add_assign(&mut self, rhs: u64) {
        *self = self.clone() + rhs;
    }
}

impl Sub<u64> for Page {
    type Output = Self;
    fn sub(self, rhs: u64) -> Self::Output {
        Page::containing_address(self.start_address() - rhs * u64::from(PAGE_SIZE))
    }
}

impl SubAssign<u64> for Page {
    fn sub_assign(&mut self, rhs: u64) {
        *self = self.clone() - rhs;
    }
}

/// A physical 4kB frame.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct PhysFrame {
   number: u64,
}

impl PhysFrame {
    /// Returns the frame that contains the given physical address.
    pub fn containing_address(address: PhysAddr) -> PhysFrame {
        PhysFrame { number: address.as_u64() / u64::from(PAGE_SIZE) }
    }

    /// Returns the start address of the page.
    pub fn start_address(&self) -> PhysAddr {
        PhysAddr::new(self.number * u64::from(PAGE_SIZE))
    }
}

impl Add<u64> for PhysFrame {
    type Output = Self;
    fn add(self, rhs: u64) -> Self::Output {
        PhysFrame::containing_address(self.start_address() + rhs * u64::from(PAGE_SIZE))
    }
}

impl AddAssign<u64> for PhysFrame {
    fn add_assign(&mut self, rhs: u64) {
        *self = self.clone() + rhs;
    }
}

impl Sub<u64> for PhysFrame {
    type Output = Self;
    fn sub(self, rhs: u64) -> Self::Output {
        PhysFrame::containing_address(self.start_address() - rhs * u64::from(PAGE_SIZE))
    }
}

impl SubAssign<u64> for PhysFrame {
    fn sub_assign(&mut self, rhs: u64) {
        *self = self.clone() - rhs;
    }
}
<commit_msg>Add a Page::from_page_table_indices function<commit_after>//! Abstractions for page tables and other paging related structures.

pub use self::page_table::*;

use addr::{VirtAddr, PhysAddr};
use core::ops::{Add, AddAssign, Sub, SubAssign};
use ux::*;

mod page_table;

/// The default page size on x86_64.
pub const PAGE_SIZE: u16 = 4096;

/// A virtual 4kB page.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Page {
   number: u64,
}

impl Page {
    /// Returns the page that contains the given virtual address.
    pub fn containing_address(address: VirtAddr) -> Page {
        Page { number: address.as_u64() / u64::from(PAGE_SIZE) }
    }

    pub fn from_page_table_indices(p4_index: u9, p3_index: u9, p2_index: u9, p1_index: u9)
        -> Page
    {
        use bit_field::BitField;

        let mut addr = 0;
        addr.set_bits(39..48, u64::from(p4_index));
        addr.set_bits(30..39, u64::from(p3_index));
        addr.set_bits(21..30, u64::from(p2_index));
        addr.set_bits(12..21, u64::from(p1_index));
        Page::containing_address(VirtAddr::new(addr))
    }

    /// Returns the start address of the page.
    pub fn start_address(&self) -> VirtAddr {
        VirtAddr::new(self.number * u64::from(PAGE_SIZE))
    }

    /// Returns the level 4 page table index of this page.
    pub fn p4_index(&self) -> u9 {
        self.start_address().p4_index()
    }

    /// Returns the level 3 page table index of this page.
    pub fn p3_index(&self) -> u9 {
        self.start_address().p3_index()
    }

    /// Returns the level 2 page table index of this page.
    pub fn p2_index(&self) -> u9 {
        self.start_address().p2_index()
    }

    /// Returns the level 1 page table index of this page.
    pub fn p1_index(&self) -> u9 {
        self.start_address().p1_index()
    }
}

impl Add<u64> for Page {
    type Output = Self;
    fn add(self, rhs: u64) -> Self::Output {
        Page::containing_address(self.start_address() + rhs * u64::from(PAGE_SIZE))
    }
}

impl AddAssign<u64> for Page {
    fn add_assign(&mut self, rhs: u64) {
        *self = self.clone() + rhs;
    }
}

impl Sub<u64> for Page {
    type Output = Self;
    fn sub(self, rhs: u64) -> Self::Output {
        Page::containing_address(self.start_address() - rhs * u64::from(PAGE_SIZE))
    }
}

impl SubAssign<u64> for Page {
    fn sub_assign(&mut self, rhs: u64) {
        *self = self.clone() - rhs;
    }
}

/// A physical 4kB frame.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct PhysFrame {
   number: u64,
}

impl PhysFrame {
    /// Returns the frame that contains the given physical address.
    pub fn containing_address(address: PhysAddr) -> PhysFrame {
        PhysFrame { number: address.as_u64() / u64::from(PAGE_SIZE) }
    }

    /// Returns the start address of the page.
    pub fn start_address(&self) -> PhysAddr {
        PhysAddr::new(self.number * u64::from(PAGE_SIZE))
    }
}

impl Add<u64> for PhysFrame {
    type Output = Self;
    fn add(self, rhs: u64) -> Self::Output {
        PhysFrame::containing_address(self.start_address() + rhs * u64::from(PAGE_SIZE))
    }
}

impl AddAssign<u64> for PhysFrame {
    fn add_assign(&mut self, rhs: u64) {
        *self = self.clone() + rhs;
    }
}

impl Sub<u64> for PhysFrame {
    type Output = Self;
    fn sub(self, rhs: u64) -> Self::Output {
        PhysFrame::containing_address(self.start_address() - rhs * u64::from(PAGE_SIZE))
    }
}

impl SubAssign<u64> for PhysFrame {
    fn sub_assign(&mut self, rhs: u64) {
        *self = self.clone() - rhs;
    }
}
<|endoftext|>


<commit_before>//! This crates contains the types and methods needed to interact
//! with DICOM nodes through the upper layer protocol.
//!
//! This crate can be used as a base
//! for finite-state machines and higher-level helpers,
//! enabling the creation of concrete service class users (SCUs)
//! and service class providers (SCPs).
//!
//! - The [`pdu`](crate::pdu) module
//! provides data structures representing _protocol data units_,
//! which are passed around as part of the DICOM network communication support.
//! - The [`association`](crate::association) module
//! comprises abstractions for establishing and negotiating associations
//! between application entities,
//! via the upper layer protocol by TCP.

pub mod association;
pub mod pdu;
pub mod address;

/// The current implementation class UID generically referring to DICOM-rs.
///
/// Automatically generated as per the standard, part 5, section B.2.
///
/// This UID is subject to changes in future versions.
pub const IMPLEMENTATION_CLASS_UID: &str = "2.25.137038125948464847900039011591283709926";

/// The current implementation version name generically referring to DICOM-rs.
///
/// This names is subject to changes in future versions.
pub const IMPLEMENTATION_VERSION_NAME: &str = "DICOM-rs 0.3";

// re-exports

pub use association::client::{ClientAssociation, ClientAssociationOptions};
pub use association::server::{ServerAssociation, ServerAssociationOptions};
pub use pdu::reader::read_pdu;
pub use pdu::writer::write_pdu;
pub use pdu::Pdu;
pub use address::{AeAddr, FullAeAddr};
<commit_msg>[ul] update root crate doc<commit_after>//! This crates contains the types and methods needed to interact
//! with DICOM nodes through the upper layer protocol.
//!
//! This crate can be used as a base
//! for finite-state machines and higher-level helpers,
//! enabling the creation of concrete service class users (SCUs)
//! and service class providers (SCPs).
//!
//! - The [`address`](crate::address) module
//! provides an abstraction for working with compound addresses
//! referring to application entities in a network.
//! - The [`pdu`](crate::pdu) module
//! provides data structures representing _protocol data units_,
//! which are passed around as part of the DICOM network communication support.
//! - The [`association`](crate::association) module
//! comprises abstractions for establishing and negotiating associations
//! between application entities,
//! via the upper layer protocol by TCP.

pub mod association;
pub mod pdu;
pub mod address;

/// The current implementation class UID generically referring to DICOM-rs.
///
/// Automatically generated as per the standard, part 5, section B.2.
///
/// This UID is subject to changes in future versions.
pub const IMPLEMENTATION_CLASS_UID: &str = "2.25.137038125948464847900039011591283709926";

/// The current implementation version name generically referring to DICOM-rs.
///
/// This names is subject to changes in future versions.
pub const IMPLEMENTATION_VERSION_NAME: &str = "DICOM-rs 0.3";

// re-exports

pub use association::client::{ClientAssociation, ClientAssociationOptions};
pub use association::server::{ServerAssociation, ServerAssociationOptions};
pub use pdu::reader::read_pdu;
pub use pdu::writer::write_pdu;
pub use pdu::Pdu;
pub use address::{AeAddr, FullAeAddr};
<|endoftext|>


<commit_before>extern crate libc;

use x11::xlib::Window;
use x11::xlib;

use super::super::libx;

const CWX: libc::c_uint = 1<<0;
const CWY: libc::c_uint = 1<<1;
const CWWidth: libc::c_uint = 1<<2;
const CWHeight: libc::c_uint = 1<<3;
const CWBorderWidth: libc::c_uint = 1<<4;
const CWSibling: libc::c_uint =	1<<5;
const CWStackMode: libc::c_uint = 1<<6;

pub trait Layout {
    fn configure(&self, windows: &[Window], context: libx::Context,screen_num: libc::c_int);
    fn toggle(&mut self) {}
    fn get_type(&self) -> Type;
}

pub enum Direction {
    Vertical,
    Horizontal,
    Up,
    Down,
    Left,
    Right,
}

#[derive(PartialEq, Clone)]
pub enum Type {
    Tiling,
}

pub struct TilingLayout {
    direction: Direction,
}

impl TilingLayout {
    pub fn new(d: Direction) -> TilingLayout{
        TilingLayout {
            direction: d,
        }
    }
}

impl Layout for TilingLayout {
    fn get_type(&self) -> Type { Type::Tiling }
    fn toggle(&mut self) {
        match self.direction {
            Direction::Vertical => self.direction = Direction::Horizontal,
            Direction::Horizontal => self.direction = Direction::Vertical,
            _ => {}
        }
    }
    /// once we add or remove a window, we need to reconfig
    fn configure(&self, windows: &[Window], context: libx::Context,screen_num: libc::c_int,) {
        let size = windows.len();
        if size == 0 {
            return;
        }

        unsafe {
            let screen_height = libx::display_height(context, screen_num);
            let screen_width = libx::display_height(context, screen_num);
            let mask = CWX | CWY | CWHeight | CWWidth;

            let width = screen_width  / size as libc::c_int;
            let height = screen_height / size as libc::c_int;

            for (i, w) in windows.iter().enumerate() {
                let mut change = xlib::XWindowChanges {
                    x: 0,
                    y: 0,
                    width: screen_width,
                    height: screen_height,
                    border_width: 0,
                    sibling: 0,
                    stack_mode: 0
                };
                match self.direction {
                    Direction::Vertical => {
                        change.y = height * i as libc::c_int;
                        change.height = height;
                    }
                    Direction::Horizontal => {
                        change.x = width * i as libc::c_int;
                        change.width = width;
                    }
                    _ => {}
                };

                debug!("config x: {}, y: {}, width: {}, height: {}",
                       change.x, change.y, change.width, change.height);
                libx::configure_window(context, *w, mask, change);
            }
        }
    }
}
<commit_msg>layout<commit_after>extern crate libc;

use x11::xlib::Window;
use x11::xlib;

use super::super::libx;

const CWX: libc::c_uint = 1<<0;
const CWY: libc::c_uint = 1<<1;
const CWWidth: libc::c_uint = 1<<2;
const CWHeight: libc::c_uint = 1<<3;
const CWBorderWidth: libc::c_uint = 1<<4;
const CWSibling: libc::c_uint =	1<<5;
const CWStackMode: libc::c_uint = 1<<6;

pub trait Layout {
    fn configure(&self, windows: &[Window], context: libx::Context,screen_num: libc::c_int);
    fn toggle(&mut self) {}
    fn get_type(&self) -> Type;
}

pub enum Direction {
    Vertical,
    Horizontal,
    Up,
    Down,
    Left,
    Right,
}

#[derive(PartialEq, Clone)]
pub enum Type {
    Tiling,
}

pub struct TilingLayout {
    direction: Direction,
}

impl TilingLayout {
    pub fn new(d: Direction) -> TilingLayout{
        TilingLayout {
            direction: d,
        }
    }
}

impl Layout for TilingLayout {
    fn get_type(&self) -> Type { Type::Tiling }
    fn toggle(&mut self) {
        match self.direction {
            Direction::Vertical => self.direction = Direction::Horizontal,
            Direction::Horizontal => self.direction = Direction::Vertical,
            _ => {}
        }
    }
    /// once we add or remove a window, we need to reconfig
    fn configure(&self, windows: &[Window], context: libx::Context,screen_num: libc::c_int,) {
        let size = windows.len();
        if size == 0 {
            return;
        }
        let screen_height = libx::display_height(context, screen_num);
        let screen_width = libx::display_width(context, screen_num);

        let mask = CWX | CWY | CWHeight | CWWidth;

        let width = screen_width  / size as libc::c_int;
        let height = screen_height / size as libc::c_int;
        println!("screen width {} height {}", width, height);
        for (i, w) in windows.iter().enumerate() {
            let mut change = xlib::XWindowChanges {
                x: 0,
                y: 0,
                width: screen_width,
                height: screen_height,
                border_width: 0,
                sibling: 0,
                stack_mode: 0
            };
            match self.direction {
                Direction::Vertical => {
                    change.y = height * i as libc::c_int;
                    change.height = height;
                }
                Direction::Horizontal => {
                    change.x = width * i as libc::c_int;
                    change.width = width;
                }
                _ => {}
            };

            debug!("config window {} x: {}, y: {}, width: {}, height: {}",
                   *w, change.x, change.y, change.width, change.height);
            libx::configure_window(context, *w, mask, change);
        }
    }
}
<|endoftext|>