<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/. */

//! A collection of invalidations due to changes in which stylesheets affect a
//! document.

#![deny(unsafe_code)]

use Atom;
use data::StoredRestyleHint;
use dom::{TElement, TNode};
use fnv::FnvHashSet;
use selector_parser::SelectorImpl;
use selectors::parser::{Component, Selector};
use shared_lock::SharedRwLockReadGuard;
use stylesheets::{CssRule, CssRules, Stylesheet};
use stylist::Stylist;

/// An invalidation scope represents a kind of subtree that may need to be
/// restyled.
#[derive(Debug, Hash, Eq, PartialEq)]
enum InvalidationScope {
    /// All the descendants of an element with a given id.
    ID(Atom),
    /// All the descendants of an element with a given class name.
    Class(Atom),
}

impl InvalidationScope {
    fn is_id(&self) -> bool {
        matches!(*self, InvalidationScope::ID(..))
    }

    fn matches<E>(&self, element: E) -> bool
        where E: TElement,
    {
        match *self {
            InvalidationScope::Class(ref class) => {
                element.has_class(class)
            }
            InvalidationScope::ID(ref id) => {
                match element.get_id() {
                    Some(element_id) => element_id == *id,
                    None => false,
                }
            }
        }
    }
}

/// A set of invalidations due to stylesheet additions.
///
/// TODO(emilio): We might be able to do the same analysis for removals and
/// media query changes too?
pub struct StylesheetInvalidationSet {
    /// The style scopes we know we have to restyle so far.
    invalid_scopes: FnvHashSet<InvalidationScope>,
    /// Whether the whole document should be invalid.
    fully_invalid: bool,
}

impl StylesheetInvalidationSet {
    /// Create an empty `StylesheetInvalidationSet`.
    pub fn new() -> Self {
        Self {
            invalid_scopes: FnvHashSet::default(),
            fully_invalid: false,
        }
    }

    /// Mark the DOM tree styles' as fully invalid.
    pub fn invalidate_fully(&mut self) {
        debug!("StylesheetInvalidationSet::invalidate_fully");
        self.invalid_scopes.clear();
        self.fully_invalid = true;
    }

    /// Analyze the given stylesheet, and collect invalidations from their
    /// rules, in order to avoid doing a full restyle when we style the document
    /// next time.
    pub fn collect_invalidations_for(
        &mut self,
        stylist: &Stylist,
        stylesheet: &Stylesheet,
        guard: &SharedRwLockReadGuard)
    {
        debug!("StylesheetInvalidationSet::collect_invalidations_for");
        if self.fully_invalid {
            debug!(" > Fully invalid already");
            return;
        }

        if stylesheet.disabled() ||
           !stylesheet.is_effective_for_device(stylist.device(), guard) {
            debug!(" > Stylesheet was not effective");
            return; // Nothing to do here.
        }

        self.collect_invalidations_for_rule_list(
            stylesheet.rules.read_with(guard),
            stylist,
            guard);

        debug!(" > resulting invalidations: {:?}", self.invalid_scopes);
        debug!(" > fully_invalid: {}", self.fully_invalid);
    }

    /// Clears the invalidation set, invalidating elements as needed if
    /// `document_element` is provided.
    pub fn flush<E>(&mut self, document_element: Option<E>)
        where E: TElement,
    {
        if let Some(e) = document_element {
            self.process_invalidations_in_subtree(e);
        }
        self.invalid_scopes.clear();
        self.fully_invalid = false;
    }

    /// Process style invalidations in a given subtree, that is, look for all
    /// the relevant scopes in the subtree, and mark as dirty only the relevant
    /// ones.
    ///
    /// Returns whether it invalidated at least one element's style.
    #[allow(unsafe_code)]
    fn process_invalidations_in_subtree<E>(&self, element: E) -> bool
        where E: TElement,
    {
        let mut data = match element.mutate_data() {
            Some(data) => data,
            None => return false,
        };

        if !data.has_styles() {
            return false;
        }

        if let Some(ref r) = data.get_restyle() {
            if r.hint.contains_subtree() {
                debug!("process_invalidations_in_subtree: {:?} was already invalid",
                       element);
                return false;
            }
        }

        if self.fully_invalid {
            debug!("process_invalidations_in_subtree: fully_invalid({:?})",
                   element);
            data.ensure_restyle().hint.insert(StoredRestyleHint::subtree());
            return true;
        }

        for scope in &self.invalid_scopes {
            if scope.matches(element) {
                debug!("process_invalidations_in_subtree: {:?} matched {:?}",
                       element, scope);
                data.ensure_restyle().hint.insert(StoredRestyleHint::subtree());
                return true;
            }
        }

        let mut any_children_invalid = false;

        for child in element.as_node().children() {
            let child = match child.as_element() {
                Some(e) => e,
                None => continue,
            };

            any_children_invalid |= self.process_invalidations_in_subtree(child);
        }

        if any_children_invalid {
            debug!("Children of {:?} changed, setting dirty descendants",
                   element);
            unsafe { element.set_dirty_descendants() }
        }

        return any_children_invalid
    }

    /// Collects invalidations for a given list of CSS rules.
    fn collect_invalidations_for_rule_list(
        &mut self,
        rules: &CssRules,
        stylist: &Stylist,
        guard: &SharedRwLockReadGuard)
    {
        for rule in &rules.0 {
            if !self.collect_invalidations_for_rule(rule, stylist, guard) {
                return;
            }
        }
    }

    fn scan_component(
        component: &Component<SelectorImpl>,
        scope: &mut Option<InvalidationScope>)
    {
        match *component {
            Component::Class(ref class) => {
                if scope.as_ref().map_or(true, |s| !s.is_id()) {
                    *scope = Some(InvalidationScope::Class(class.clone()));
                }
            }
            Component::ID(ref id) => {
                if scope.is_none() {
                    *scope = Some(InvalidationScope::ID(id.clone()));
                }
            }
            _ => {
                // Ignore everything else, at least for now.
            }
        }
    }

    /// Collect a style scopes for a given selector.
    ///
    /// We look at the outermost class or id selector to the left of an ancestor
    /// combinator, in order to restyle only a given subtree.
    ///
    /// We prefer id scopes to class scopes, and outermost scopes to innermost
    /// scopes (to reduce the amount of traversal we need to do).
    fn collect_scopes(&mut self, selector: &Selector<SelectorImpl>) {
        debug!("StylesheetInvalidationSet::collect_scopes({:?})", selector);

        let mut scope: Option<InvalidationScope> = None;

        let mut scan = true;
        let mut iter = selector.inner.complex.iter();

        loop {
            for component in &mut iter {
                if scan {
                    Self::scan_component(component, &mut scope);
                }
            }
            match iter.next_sequence() {
                None => break,
                Some(combinator) => {
                    scan = combinator.is_ancestor();
                }
            }
        }

        match scope {
            Some(s) => {
                debug!(" > Found scope: {:?}", s);
                self.invalid_scopes.insert(s);
            }
            None => {
                debug!(" > Scope not found");

                // If we didn't find a scope, any element could match this, so
                // let's just bail out.
                self.fully_invalid = true;
            }
        }
    }

    /// Collects invalidations for a given CSS rule.
    ///
    /// Returns true if it needs to keep collecting invalidations for subsequent
    /// rules in this list.
    fn collect_invalidations_for_rule(
        &mut self,
        rule: &CssRule,
        stylist: &Stylist,
        guard: &SharedRwLockReadGuard)
        -> bool
    {
        use stylesheets::CssRule::*;
        debug!("StylesheetInvalidationSet::collect_invalidations_for_rule");
        debug_assert!(!self.fully_invalid, "Not worth to be here!");

        match *rule {
            Document(ref lock) => {
                let doc_rule = lock.read_with(guard);
                if !doc_rule.condition.evaluate(stylist.device()) {
                    return false; // Won't apply anything else after this.
                }
            }
            Style(ref lock) => {
                let style_rule = lock.read_with(guard);
                for selector in &style_rule.selectors.0 {
                    self.collect_scopes(selector);
                    if self.fully_invalid {
                        return false;
                    }
                }
            }
            Namespace(..) => {
                // Irrelevant to which selector scopes match.
            }
            Import(..) => {
                // We'll visit the appropriate stylesheet if/when it matters.
            }
            Media(ref lock) => {
                let media_rule = lock.read_with(guard);

                let mq = media_rule.media_queries.read_with(guard);
                if !mq.evaluate(stylist.device(), stylist.quirks_mode()) {
                    return true;
                }

                self.collect_invalidations_for_rule_list(
                    media_rule.rules.read_with(guard),
                    stylist,
                    guard);
            }
            Supports(ref lock) => {
                let supports_rule = lock.read_with(guard);
                if !supports_rule.enabled {
                    return true;
                }

                self.collect_invalidations_for_rule_list(
                    supports_rule.rules.read_with(guard),
                    stylist,
                    guard);
            }
            FontFace(..) |
            CounterStyle(..) |
            Keyframes(..) |
            Page(..) |
            Viewport(..) => {
                debug!(" > Found unsupported rule, marking the whole subtree \
                       invalid.");

                // TODO(emilio): Can we do better here?
                //
                // At least in `@page`, we could check the relevant media, I
                // guess.
                self.fully_invalid = true;
            }
        }

        return !self.fully_invalid
    }
}
<commit_msg>Bug 1357583: style: Recurse into @import rules when looking at the added rules. r=heycam<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/. */

//! A collection of invalidations due to changes in which stylesheets affect a
//! document.

#![deny(unsafe_code)]

use Atom;
use data::StoredRestyleHint;
use dom::{TElement, TNode};
use fnv::FnvHashSet;
use selector_parser::SelectorImpl;
use selectors::parser::{Component, Selector};
use shared_lock::SharedRwLockReadGuard;
use stylesheets::{CssRule, CssRules, Stylesheet};
use stylist::Stylist;

/// An invalidation scope represents a kind of subtree that may need to be
/// restyled.
#[derive(Debug, Hash, Eq, PartialEq)]
enum InvalidationScope {
    /// All the descendants of an element with a given id.
    ID(Atom),
    /// All the descendants of an element with a given class name.
    Class(Atom),
}

impl InvalidationScope {
    fn is_id(&self) -> bool {
        matches!(*self, InvalidationScope::ID(..))
    }

    fn matches<E>(&self, element: E) -> bool
        where E: TElement,
    {
        match *self {
            InvalidationScope::Class(ref class) => {
                element.has_class(class)
            }
            InvalidationScope::ID(ref id) => {
                match element.get_id() {
                    Some(element_id) => element_id == *id,
                    None => false,
                }
            }
        }
    }
}

/// A set of invalidations due to stylesheet additions.
///
/// TODO(emilio): We might be able to do the same analysis for removals and
/// media query changes too?
pub struct StylesheetInvalidationSet {
    /// The style scopes we know we have to restyle so far.
    invalid_scopes: FnvHashSet<InvalidationScope>,
    /// Whether the whole document should be invalid.
    fully_invalid: bool,
}

impl StylesheetInvalidationSet {
    /// Create an empty `StylesheetInvalidationSet`.
    pub fn new() -> Self {
        Self {
            invalid_scopes: FnvHashSet::default(),
            fully_invalid: false,
        }
    }

    /// Mark the DOM tree styles' as fully invalid.
    pub fn invalidate_fully(&mut self) {
        debug!("StylesheetInvalidationSet::invalidate_fully");
        self.invalid_scopes.clear();
        self.fully_invalid = true;
    }

    /// Analyze the given stylesheet, and collect invalidations from their
    /// rules, in order to avoid doing a full restyle when we style the document
    /// next time.
    pub fn collect_invalidations_for(
        &mut self,
        stylist: &Stylist,
        stylesheet: &Stylesheet,
        guard: &SharedRwLockReadGuard)
    {
        debug!("StylesheetInvalidationSet::collect_invalidations_for");
        if self.fully_invalid {
            debug!(" > Fully invalid already");
            return;
        }

        if stylesheet.disabled() ||
           !stylesheet.is_effective_for_device(stylist.device(), guard) {
            debug!(" > Stylesheet was not effective");
            return; // Nothing to do here.
        }

        self.collect_invalidations_for_rule_list(
            stylesheet.rules.read_with(guard),
            stylist,
            guard);

        debug!(" > resulting invalidations: {:?}", self.invalid_scopes);
        debug!(" > fully_invalid: {}", self.fully_invalid);
    }

    /// Clears the invalidation set, invalidating elements as needed if
    /// `document_element` is provided.
    pub fn flush<E>(&mut self, document_element: Option<E>)
        where E: TElement,
    {
        if let Some(e) = document_element {
            self.process_invalidations_in_subtree(e);
        }
        self.invalid_scopes.clear();
        self.fully_invalid = false;
    }

    /// Process style invalidations in a given subtree, that is, look for all
    /// the relevant scopes in the subtree, and mark as dirty only the relevant
    /// ones.
    ///
    /// Returns whether it invalidated at least one element's style.
    #[allow(unsafe_code)]
    fn process_invalidations_in_subtree<E>(&self, element: E) -> bool
        where E: TElement,
    {
        let mut data = match element.mutate_data() {
            Some(data) => data,
            None => return false,
        };

        if !data.has_styles() {
            return false;
        }

        if let Some(ref r) = data.get_restyle() {
            if r.hint.contains_subtree() {
                debug!("process_invalidations_in_subtree: {:?} was already invalid",
                       element);
                return false;
            }
        }

        if self.fully_invalid {
            debug!("process_invalidations_in_subtree: fully_invalid({:?})",
                   element);
            data.ensure_restyle().hint.insert(StoredRestyleHint::subtree());
            return true;
        }

        for scope in &self.invalid_scopes {
            if scope.matches(element) {
                debug!("process_invalidations_in_subtree: {:?} matched {:?}",
                       element, scope);
                data.ensure_restyle().hint.insert(StoredRestyleHint::subtree());
                return true;
            }
        }

        let mut any_children_invalid = false;

        for child in element.as_node().children() {
            let child = match child.as_element() {
                Some(e) => e,
                None => continue,
            };

            any_children_invalid |= self.process_invalidations_in_subtree(child);
        }

        if any_children_invalid {
            debug!("Children of {:?} changed, setting dirty descendants",
                   element);
            unsafe { element.set_dirty_descendants() }
        }

        return any_children_invalid
    }

    /// Collects invalidations for a given list of CSS rules.
    ///
    /// TODO(emilio): Convert stylesheet.effective_rules into an iterator to
    /// share code. This needs the ability to stop ASAP.
    fn collect_invalidations_for_rule_list(
        &mut self,
        rules: &CssRules,
        stylist: &Stylist,
        guard: &SharedRwLockReadGuard)
    {
        for rule in &rules.0 {
            if !self.collect_invalidations_for_rule(rule, stylist, guard) {
                return;
            }
        }
    }

    fn scan_component(
        component: &Component<SelectorImpl>,
        scope: &mut Option<InvalidationScope>)
    {
        match *component {
            Component::Class(ref class) => {
                if scope.as_ref().map_or(true, |s| !s.is_id()) {
                    *scope = Some(InvalidationScope::Class(class.clone()));
                }
            }
            Component::ID(ref id) => {
                if scope.is_none() {
                    *scope = Some(InvalidationScope::ID(id.clone()));
                }
            }
            _ => {
                // Ignore everything else, at least for now.
            }
        }
    }

    /// Collect a style scopes for a given selector.
    ///
    /// We look at the outermost class or id selector to the left of an ancestor
    /// combinator, in order to restyle only a given subtree.
    ///
    /// We prefer id scopes to class scopes, and outermost scopes to innermost
    /// scopes (to reduce the amount of traversal we need to do).
    fn collect_scopes(&mut self, selector: &Selector<SelectorImpl>) {
        debug!("StylesheetInvalidationSet::collect_scopes({:?})", selector);

        let mut scope: Option<InvalidationScope> = None;

        let mut scan = true;
        let mut iter = selector.inner.complex.iter();

        loop {
            for component in &mut iter {
                if scan {
                    Self::scan_component(component, &mut scope);
                }
            }
            match iter.next_sequence() {
                None => break,
                Some(combinator) => {
                    scan = combinator.is_ancestor();
                }
            }
        }

        match scope {
            Some(s) => {
                debug!(" > Found scope: {:?}", s);
                self.invalid_scopes.insert(s);
            }
            None => {
                debug!(" > Scope not found");

                // If we didn't find a scope, any element could match this, so
                // let's just bail out.
                self.fully_invalid = true;
            }
        }
    }

    /// Collects invalidations for a given CSS rule.
    ///
    /// Returns true if it needs to keep collecting invalidations for subsequent
    /// rules in this list.
    fn collect_invalidations_for_rule(
        &mut self,
        rule: &CssRule,
        stylist: &Stylist,
        guard: &SharedRwLockReadGuard)
        -> bool
    {
        use stylesheets::CssRule::*;
        debug!("StylesheetInvalidationSet::collect_invalidations_for_rule");
        debug_assert!(!self.fully_invalid, "Not worth to be here!");

        match *rule {
            Document(ref lock) => {
                let doc_rule = lock.read_with(guard);
                if !doc_rule.condition.evaluate(stylist.device()) {
                    return false; // Won't apply anything else after this.
                }
            }
            Style(ref lock) => {
                let style_rule = lock.read_with(guard);
                for selector in &style_rule.selectors.0 {
                    self.collect_scopes(selector);
                    if self.fully_invalid {
                        return false;
                    }
                }
            }
            Namespace(..) => {
                // Irrelevant to which selector scopes match.
            }
            // NB: We need to do it here, we won't visit the appropriate sheet
            // otherwise!
            Import(ref lock) => {
                let import_rule = lock.read_with(guard);

                let mq = import_rule.stylesheet.media.read_with(guard);
                if !mq.evaluate(stylist.device(), stylist.quirks_mode()) {
                    return true;
                }

                self.collect_invalidations_for_rule_list(
                    import_rule.stylesheet.rules.read_with(guard),
                    stylist,
                    guard);
            }
            Media(ref lock) => {
                let media_rule = lock.read_with(guard);

                let mq = media_rule.media_queries.read_with(guard);
                if !mq.evaluate(stylist.device(), stylist.quirks_mode()) {
                    return true;
                }

                self.collect_invalidations_for_rule_list(
                    media_rule.rules.read_with(guard),
                    stylist,
                    guard);
            }
            Supports(ref lock) => {
                let supports_rule = lock.read_with(guard);
                if !supports_rule.enabled {
                    return true;
                }

                self.collect_invalidations_for_rule_list(
                    supports_rule.rules.read_with(guard),
                    stylist,
                    guard);
            }
            FontFace(..) |
            CounterStyle(..) |
            Keyframes(..) |
            Page(..) |
            Viewport(..) => {
                debug!(" > Found unsupported rule, marking the whole subtree \
                       invalid.");

                // TODO(emilio): Can we do better here?
                //
                // At least in `@page`, we could check the relevant media, I
                // guess.
                self.fully_invalid = true;
            }
        }

        return !self.fully_invalid
    }
}
<|endoftext|>


<commit_before>extern crate leap;

#[test]
fn test_vanilla_leap_year() {
    assert_eq!(leap::is_leap_year(1996), true);
}

#[test]
#[ignore]
fn test_any_old_year() {
    assert_eq!(leap::is_leap_year(1997), false);
}

#[test]
#[ignore]
fn test_century() {
    assert_eq!(leap::is_leap_year(1900), false);
}

#[test]
#[ignore]
fn test_exceptional_centuries() {
    assert_eq!(leap::is_leap_year(2000), true);
    assert_eq!(leap::is_leap_year(2400), true);
}
<commit_msg>leap: add more test cases<commit_after>extern crate leap;

#[test]
fn test_vanilla_leap_year() {
    assert_eq!(leap::is_leap_year(1996), true);
}

#[test]
#[ignore]
fn test_any_old_year() {
    assert_eq!(leap::is_leap_year(1997), false);
}

#[test]
#[ignore]
fn test_century() {
    assert_eq!(leap::is_leap_year(1700), false);
    assert_eq!(leap::is_leap_year(1800), false);
    assert_eq!(leap::is_leap_year(1900), false);
}

#[test]
#[ignore]
fn test_exceptional_centuries() {
    assert_eq!(leap::is_leap_year(1600), true);
    assert_eq!(leap::is_leap_year(2000), true);
    assert_eq!(leap::is_leap_year(2400), true);
}

#[test]
#[ignore]
fn test_years_1600_to_1699() {
    let incorrect_years = (1600..1700)
        .filter(|&year| leap::is_leap_year(year) != (year % 4 == 0))
        .collect::<Vec<_>>();

    if !incorrect_years.is_empty() {
        panic!("incorrect result for years: {:?}", incorrect_years);
    }
}
<|endoftext|>


<commit_before>generate_error_imports!();
use std::convert::From;

#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Copy)]
pub struct CustomErrorData {}

generate_custom_error_types!(StoreError, StoreErrorKind, CustomErrorData,
    ConfigurationError      => "Store Configuration Error",
    CreateStoreDirDenied    => "Creating store directory implicitely denied",
    FileError               => "File Error",
    IoError                 => "IO Error",
    IdLocked                => "ID locked",
    IdNotFound              => "ID not found",
    OutOfMemory             => "Out of Memory",
    FileNotFound            => "File corresponding to ID not found",
    FileNotCreated          => "File corresponding to ID could not be created",
    FileNotWritten          => "File corresponding to ID could not be written to",
    FileNotSeeked           => "File corresponding to ID could not be seeked",
    FileNotRemoved          => "File corresponding to ID could not be removed",
    FileNotRenamed          => "File corresponding to ID could not be renamed",
    FileNotCopied           => "File could not be copied",
    DirNotCreated           => "Directory/Directories could not be created",
    StorePathExists         => "Store path exists",
    StorePathCreate         => "Store path create",
    LockError               => "Error locking datastructure",
    LockPoisoned            => "The internal Store Lock has been poisoned",
    EntryAlreadyBorrowed    => "Entry is already borrowed",
    EntryAlreadyExists      => "Entry already exists",
    MalformedEntry          => "Entry has invalid formatting, missing header",
    HeaderPathSyntaxError   => "Syntax error in accessor string",
    HeaderPathTypeFailure   => "Header has wrong type for path",
    HeaderKeyNotFound       => "Header Key not found",
    HeaderTypeFailure       => "Header type is wrong",
    HookRegisterError       => "Hook register error",
    AspectNameNotFoundError => "Aspect name not found",
    HookExecutionError      => "Hook execution error",
    PreHookExecuteError     => "Pre-Hook execution error",
    PostHookExecuteError    => "Post-Hook execution error",
    StorePathLacksVersion   => "The supplied store path has no version part",
    GlobError               => "glob() error",
    EncodingError           => "Encoding error",
    StorePathError          => "Store Path error",
    EntryRenameError        => "Entry rename error",
    StoreIdHandlingError    => "StoreId handling error",
    StoreIdLocalPartAbsoluteError => "StoreId 'id' part is absolute (starts with '/') which is not allowed",

    CreateCallError            => "Error when calling create()",
    RetrieveCallError          => "Error when calling retrieve()",
    GetCallError               => "Error when calling get()",
    GetAllVersionsCallError    => "Error when calling get_all_versions()",
    RetrieveForModuleCallError => "Error when calling retrieve_for_module()",
    UpdateCallError            => "Error when calling update()",
    RetrieveCopyCallError      => "Error when calling retrieve_copy()",
    DeleteCallError            => "Error when calling delete()",
    MoveCallError              => "Error when calling move()",
    MoveByIdCallError          => "Error when calling move_by_id()"
);

generate_result_helper!(StoreError, StoreErrorKind);
generate_option_helper!(StoreError, StoreErrorKind);

generate_custom_error_types!(ParserError, ParserErrorKind, CustomErrorData,
    TOMLParserErrors    => "Several TOML-Parser-Errors",
    MissingMainSection  => "Missing main section",
    MissingVersionInfo  => "Missing version information in main section",
    NonTableInBaseTable => "A non-table was found in the base table",
    HeaderInconsistency => "The header is inconsistent"
);

impl From<ParserError> for StoreError {
    fn from(ps: ParserError) -> StoreError {
        StoreError {
            err_type: StoreErrorKind::MalformedEntry,
            cause: Some(Box::new(ps)),
            custom_data: None,
        }
    }
}

impl From<::std::io::Error> for StoreError {
    fn from(ps: ::std::io::Error) -> StoreError {
        StoreError {
            err_type: StoreErrorKind::IoError,
            cause: Some(Box::new(ps)),
            custom_data: None,
        }
    }
}

<commit_msg>Add error type for failed build of StoreId object from full path<commit_after>generate_error_imports!();
use std::convert::From;

#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Copy)]
pub struct CustomErrorData {}

generate_custom_error_types!(StoreError, StoreErrorKind, CustomErrorData,
    ConfigurationError      => "Store Configuration Error",
    CreateStoreDirDenied    => "Creating store directory implicitely denied",
    FileError               => "File Error",
    IoError                 => "IO Error",
    IdLocked                => "ID locked",
    IdNotFound              => "ID not found",
    OutOfMemory             => "Out of Memory",
    FileNotFound            => "File corresponding to ID not found",
    FileNotCreated          => "File corresponding to ID could not be created",
    FileNotWritten          => "File corresponding to ID could not be written to",
    FileNotSeeked           => "File corresponding to ID could not be seeked",
    FileNotRemoved          => "File corresponding to ID could not be removed",
    FileNotRenamed          => "File corresponding to ID could not be renamed",
    FileNotCopied           => "File could not be copied",
    DirNotCreated           => "Directory/Directories could not be created",
    StorePathExists         => "Store path exists",
    StorePathCreate         => "Store path create",
    LockError               => "Error locking datastructure",
    LockPoisoned            => "The internal Store Lock has been poisoned",
    EntryAlreadyBorrowed    => "Entry is already borrowed",
    EntryAlreadyExists      => "Entry already exists",
    MalformedEntry          => "Entry has invalid formatting, missing header",
    HeaderPathSyntaxError   => "Syntax error in accessor string",
    HeaderPathTypeFailure   => "Header has wrong type for path",
    HeaderKeyNotFound       => "Header Key not found",
    HeaderTypeFailure       => "Header type is wrong",
    HookRegisterError       => "Hook register error",
    AspectNameNotFoundError => "Aspect name not found",
    HookExecutionError      => "Hook execution error",
    PreHookExecuteError     => "Pre-Hook execution error",
    PostHookExecuteError    => "Post-Hook execution error",
    StorePathLacksVersion   => "The supplied store path has no version part",
    GlobError               => "glob() error",
    EncodingError           => "Encoding error",
    StorePathError          => "Store Path error",
    EntryRenameError        => "Entry rename error",
    StoreIdHandlingError    => "StoreId handling error",
    StoreIdLocalPartAbsoluteError => "StoreId 'id' part is absolute (starts with '/') which is not allowed",
    StoreIdBuildFromFullPathError => "Building StoreId from full file path failed",

    CreateCallError            => "Error when calling create()",
    RetrieveCallError          => "Error when calling retrieve()",
    GetCallError               => "Error when calling get()",
    GetAllVersionsCallError    => "Error when calling get_all_versions()",
    RetrieveForModuleCallError => "Error when calling retrieve_for_module()",
    UpdateCallError            => "Error when calling update()",
    RetrieveCopyCallError      => "Error when calling retrieve_copy()",
    DeleteCallError            => "Error when calling delete()",
    MoveCallError              => "Error when calling move()",
    MoveByIdCallError          => "Error when calling move_by_id()"
);

generate_result_helper!(StoreError, StoreErrorKind);
generate_option_helper!(StoreError, StoreErrorKind);

generate_custom_error_types!(ParserError, ParserErrorKind, CustomErrorData,
    TOMLParserErrors    => "Several TOML-Parser-Errors",
    MissingMainSection  => "Missing main section",
    MissingVersionInfo  => "Missing version information in main section",
    NonTableInBaseTable => "A non-table was found in the base table",
    HeaderInconsistency => "The header is inconsistent"
);

impl From<ParserError> for StoreError {
    fn from(ps: ParserError) -> StoreError {
        StoreError {
            err_type: StoreErrorKind::MalformedEntry,
            cause: Some(Box::new(ps)),
            custom_data: None,
        }
    }
}

impl From<::std::io::Error> for StoreError {
    fn from(ps: ::std::io::Error) -> StoreError {
        StoreError {
            err_type: StoreErrorKind::IoError,
            cause: Some(Box::new(ps)),
            custom_data: None,
        }
    }
}

<|endoftext|>


<commit_before>use std::error::Error;
use std::fmt::Error as FmtError;
use std::clone::Clone;
use std::fmt::{Debug, Display, Formatter};
use std::fmt;
use std::convert::From;

/**
 * Kind of store error
 */
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum StoreErrorKind {
    FileError,
    IdLocked,
    IdNotFound,
    OutOfMemory,
    FileNotFound,
    FileNotCreated,
    IoError,
    StorePathExists,
    StorePathCreate,
    StorePathOutsideStore,
    LockPoisoned,
    EntryAlreadyBorrowed,
    EntryAlreadyExists,
    MalformedEntry,
    HeaderPathSyntaxError,
        // maybe more
}

fn store_error_type_as_str(e: &StoreErrorKind) -> &'static str {
    match e {
        &StoreErrorKind::FileError       => "File Error",
        &StoreErrorKind::IdLocked        => "ID locked",
        &StoreErrorKind::IdNotFound      => "ID not found",
        &StoreErrorKind::OutOfMemory     => "Out of Memory",
        &StoreErrorKind::FileNotFound    => "File corresponding to ID not found",
        &StoreErrorKind::FileNotCreated  => "File corresponding to ID could not be created",
        &StoreErrorKind::IoError         => "File Error",
        &StoreErrorKind::StorePathExists => "Store path exists",
        &StoreErrorKind::StorePathCreate => "Store path create",
        &StoreErrorKind::StorePathOutsideStore => "Store path would be outside of store",
        &StoreErrorKind::LockPoisoned
            => "The internal Store Lock has been poisoned",
        &StoreErrorKind::EntryAlreadyBorrowed => "Entry is already borrowed",
        &StoreErrorKind::EntryAlreadyExists   => "Entry already exists",
        &StoreErrorKind::MalformedEntry => "Entry has invalid formatting, missing header",
        &StoreErrorKind::HeaderPathSyntaxError => "Syntax error in accessor string",
    }
}

impl Display for StoreErrorKind {

    fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
        try!(write!(fmt, "{}", store_error_type_as_str(self)));
        Ok(())
    }

}

/**
 * Store error type
 */
#[derive(Debug)]
pub struct StoreError {
    err_type: StoreErrorKind,
    cause: Option<Box<Error>>,
}

impl StoreError {

    /**
     * Build a new StoreError from an StoreErrorKind, optionally with cause
     */
    pub fn new(errtype: StoreErrorKind, cause: Option<Box<Error>>)
        -> StoreError
        {
            StoreError {
                err_type: errtype,
                cause: cause,
            }
        }

    /**
     * Get the error type of this StoreError
     */
    pub fn err_type(&self) -> StoreErrorKind {
        self.err_type.clone()
    }

}

impl Display for StoreError {

    fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
        try!(write!(fmt, "[{}]", store_error_type_as_str(&self.err_type.clone())));
        Ok(())
    }

}

impl Error for StoreError {

    fn description(&self) -> &str {
        store_error_type_as_str(&self.err_type.clone())
    }

    fn cause(&self) -> Option<&Error> {
        self.cause.as_ref().map(|e| &**e)
    }

}

impl From<ParserError> for StoreError {
    fn from(ps: ParserError) -> StoreError {
        StoreError {
            err_type: StoreErrorKind::MalformedEntry,
            cause: Some(Box::new(ps)),
        }
    }
}

impl From<::std::io::Error> for StoreError {
    fn from(ps: ::std::io::Error) -> StoreError {
        StoreError {
            err_type: StoreErrorKind::IoError,
            cause: Some(Box::new(ps)),
        }
    }
}

#[derive(Clone)]
pub enum ParserErrorKind {
    TOMLParserErrors,
    MissingMainSection,
    MissingVersionInfo,
    NonTableInBaseTable,
    HeaderInconsistency,
}

pub struct ParserError {
    kind: ParserErrorKind,
    cause: Option<Box<Error>>,
}

impl ParserError {

    pub fn new(k: ParserErrorKind, cause: Option<Box<Error>>) -> ParserError {
        ParserError {
            kind: k,
            cause: cause,
        }
    }

}

impl Debug for ParserError {

    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "{:?}", self.description()));
        Ok(())
    }

}

impl Display for ParserError {

    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "{}", self.description()));
        Ok(())
    }

}

impl Error for ParserError {

    fn description(&self) -> &str {
        match self.kind {
            ParserErrorKind::TOMLParserErrors   => "Several TOML-Parser-Errors",
            ParserErrorKind::MissingMainSection => "Missing main section",
            ParserErrorKind::MissingVersionInfo => "Missing version information in main section",
            ParserErrorKind::NonTableInBaseTable => "A non-table was found in the base table",
            ParserErrorKind::HeaderInconsistency => "The header is inconsistent",
        }
    }

    fn cause(&self) -> Option<&Error> {
        self.cause.as_ref().map(|e| &**e)
    }

}

<commit_msg>Add more error types for header walking<commit_after>use std::error::Error;
use std::fmt::Error as FmtError;
use std::clone::Clone;
use std::fmt::{Debug, Display, Formatter};
use std::fmt;
use std::convert::From;

/**
 * Kind of store error
 */
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum StoreErrorKind {
    FileError,
    IdLocked,
    IdNotFound,
    OutOfMemory,
    FileNotFound,
    FileNotCreated,
    IoError,
    StorePathExists,
    StorePathCreate,
    StorePathOutsideStore,
    LockPoisoned,
    EntryAlreadyBorrowed,
    EntryAlreadyExists,
    MalformedEntry,
    HeaderPathSyntaxError,
    HeaderPathTypeFailure,
    HeaderKeyNotFound,
        // maybe more
}

fn store_error_type_as_str(e: &StoreErrorKind) -> &'static str {
    match e {
        &StoreErrorKind::FileError       => "File Error",
        &StoreErrorKind::IdLocked        => "ID locked",
        &StoreErrorKind::IdNotFound      => "ID not found",
        &StoreErrorKind::OutOfMemory     => "Out of Memory",
        &StoreErrorKind::FileNotFound    => "File corresponding to ID not found",
        &StoreErrorKind::FileNotCreated  => "File corresponding to ID could not be created",
        &StoreErrorKind::IoError         => "File Error",
        &StoreErrorKind::StorePathExists => "Store path exists",
        &StoreErrorKind::StorePathCreate => "Store path create",
        &StoreErrorKind::StorePathOutsideStore => "Store path would be outside of store",
        &StoreErrorKind::LockPoisoned
            => "The internal Store Lock has been poisoned",
        &StoreErrorKind::EntryAlreadyBorrowed => "Entry is already borrowed",
        &StoreErrorKind::EntryAlreadyExists   => "Entry already exists",
        &StoreErrorKind::MalformedEntry => "Entry has invalid formatting, missing header",
        &StoreErrorKind::HeaderPathSyntaxError => "Syntax error in accessor string",
        &StoreErrorKind::HeaderPathTypeFailure => "Header has wrong type for path",
        &StoreErrorKind::HeaderKeyNotFound     => "Header Key not found",
    }
}

impl Display for StoreErrorKind {

    fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
        try!(write!(fmt, "{}", store_error_type_as_str(self)));
        Ok(())
    }

}

/**
 * Store error type
 */
#[derive(Debug)]
pub struct StoreError {
    err_type: StoreErrorKind,
    cause: Option<Box<Error>>,
}

impl StoreError {

    /**
     * Build a new StoreError from an StoreErrorKind, optionally with cause
     */
    pub fn new(errtype: StoreErrorKind, cause: Option<Box<Error>>)
        -> StoreError
        {
            StoreError {
                err_type: errtype,
                cause: cause,
            }
        }

    /**
     * Get the error type of this StoreError
     */
    pub fn err_type(&self) -> StoreErrorKind {
        self.err_type.clone()
    }

}

impl Display for StoreError {

    fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
        try!(write!(fmt, "[{}]", store_error_type_as_str(&self.err_type.clone())));
        Ok(())
    }

}

impl Error for StoreError {

    fn description(&self) -> &str {
        store_error_type_as_str(&self.err_type.clone())
    }

    fn cause(&self) -> Option<&Error> {
        self.cause.as_ref().map(|e| &**e)
    }

}

impl From<ParserError> for StoreError {
    fn from(ps: ParserError) -> StoreError {
        StoreError {
            err_type: StoreErrorKind::MalformedEntry,
            cause: Some(Box::new(ps)),
        }
    }
}

impl From<::std::io::Error> for StoreError {
    fn from(ps: ::std::io::Error) -> StoreError {
        StoreError {
            err_type: StoreErrorKind::IoError,
            cause: Some(Box::new(ps)),
        }
    }
}

#[derive(Clone)]
pub enum ParserErrorKind {
    TOMLParserErrors,
    MissingMainSection,
    MissingVersionInfo,
    NonTableInBaseTable,
    HeaderInconsistency,
}

pub struct ParserError {
    kind: ParserErrorKind,
    cause: Option<Box<Error>>,
}

impl ParserError {

    pub fn new(k: ParserErrorKind, cause: Option<Box<Error>>) -> ParserError {
        ParserError {
            kind: k,
            cause: cause,
        }
    }

}

impl Debug for ParserError {

    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "{:?}", self.description()));
        Ok(())
    }

}

impl Display for ParserError {

    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "{}", self.description()));
        Ok(())
    }

}

impl Error for ParserError {

    fn description(&self) -> &str {
        match self.kind {
            ParserErrorKind::TOMLParserErrors   => "Several TOML-Parser-Errors",
            ParserErrorKind::MissingMainSection => "Missing main section",
            ParserErrorKind::MissingVersionInfo => "Missing version information in main section",
            ParserErrorKind::NonTableInBaseTable => "A non-table was found in the base table",
            ParserErrorKind::HeaderInconsistency => "The header is inconsistent",
        }
    }

    fn cause(&self) -> Option<&Error> {
        self.cause.as_ref().map(|e| &**e)
    }

}

<|endoftext|>


<commit_before>// Needed for reading a Json File
// extern crate rustc_serialize;
// use rustc_serialize::json::Json;
// use std::fs::File;
// use std::io::Read;

use std::ops::Deref;
use toml::Value;

use libimagstore::store::Store;
use libimagstore::storeid::IntoStoreId;
use module_path::ModuleEntryPath;

/// With the uuid we get the storeid and than we can delete the entry
fn deleteFunc(uuid: i32, store : &Store) {
	// With this we can read from a .json File
	// let mut file = File::open("text.json").unwrap();
	// let mut data = String::new();
	// file.rad_to_string(&mut data).unwrap();
	//
	// let jeson = Json::from_str(&data).unwrap();
	// println!("{}", json.find_path(&["uuid"]).unwrap());

	// With the uuid we get the storeid
	let store_id = ModuleEntryPath::new(format!("taskwarrior/{}", uuid)).into_storeid();
	// It deletes an entry
	store.delete(store_id);

	println!("The {} was delete!", uuid);
}

<commit_msg>Do the changes for the Delete function<commit_after>// Needed for reading a Json File
// extern crate rustc_serialize;
// use rustc_serialize::json::Json;
// use std::fs::File;
// use std::io::Read;

use std::ops::Deref;
use toml::Value;
use uuid::Uuid;

use libimagstore::store::Store;
use libimagstore::storeid::IntoStoreId;
use module_path::ModuleEntryPath;

/// With the uuid we get the storeid and than we can delete the entry
fn deleteFunc(uuid: Uuid, store : &Store) {
	// With this we can read from a .json File
	// let mut file = File::open("text.json").unwrap();
	// let mut data = String::new();
	// file.rad_to_string(&mut data).unwrap();
	//
	// let jeson = Json::from_str(&data).unwrap();
	// println!("{}", json.find_path(&["uuid"]).unwrap());

	// With the uuid we get the storeid
	let store_id = ModuleEntryPath::new(format!("taskwarrior/{}", uuid)).into_storeid();
	// It deletes an entry
	store.delete(store_id);
}

<|endoftext|>


<commit_before>extern crate regex;

use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;

use regex::Regex;

#[derive(Debug)]
struct Reindeer {
    name: String,
    speed: isize,
    speed_time: isize,
    rest_time: isize,
}

impl Reindeer {
    fn distance_traveled(&self, seconds: isize) -> isize {
        let mut distance = 0;
        let mut seconds = seconds;
        while seconds > 0 {
            if seconds > self.speed_time {
                distance += self.speed * self.speed_time;
                seconds -= self.speed_time;
            } else {
                distance += self.speed * seconds;
                break;
            }
            seconds -= self.rest_time;
        }
        return distance;
    }
}

fn main() {
    let file = File::open("input.txt").unwrap();
    let reader = BufReader::new(&file);

    let regex = Regex::new(r"(?P<name>[[:alpha:]]+) can fly (?P<speed>[[:digit:]]+) km/s for (?P<speed_time>[[:digit:]]+) seconds, but then must rest for (?P<rest_time>[[:digit:]]+) seconds.").unwrap();
    let mut reindeers: Vec<Reindeer> = Vec::with_capacity(10);
    for wrapped_line in reader.lines() {
        let line = wrapped_line.unwrap();
        let maybe_match = regex.captures(line.as_str());
        match maybe_match {
            Some(capture) => {
                let name = capture.name("name").unwrap().as_str();
                let speed = capture.name("speed").unwrap().as_str().parse::<isize>().unwrap();
                let speed_time =
                    capture.name("speed_time").unwrap().as_str().parse::<isize>().unwrap();
                let rest_time =
                    capture.name("rest_time").unwrap().as_str().parse::<isize>().unwrap();
                reindeers.push(Reindeer {
                    name: String::from(name),
                    speed: speed,
                    speed_time: speed_time,
                    rest_time: rest_time,
                });

            }
            None => panic!("No match for '{}'", line),
        }
    }
    let time_in_secs = 2503;
    for r in reindeers {
        println!("{:10} traveled {:4} km in {:5} seconds",
                 r.name,
                 r.distance_traveled(time_in_secs),
                 time_in_secs);
    }
}
<commit_msg>Part 2 solved.<commit_after>extern crate regex;

use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;

use regex::Regex;

#[derive(Debug, Clone)]
struct Reindeer {
    name: String,
    speed: isize,
    speed_time: isize,
    rest_time: isize,
    current_distance: isize,
    points: isize,
    rest_time_left: isize,
    speed_time_left: isize,
}

impl Reindeer {
    fn distance_traveled(&self, seconds: isize) -> isize {
        let mut distance = 0;
        let mut seconds = seconds;
        while seconds > 0 {
            if seconds > self.speed_time {
                distance += self.speed * self.speed_time;
                seconds -= self.speed_time;
            } else {
                distance += self.speed * seconds;
                break;
            }
            seconds -= self.rest_time;
        }
        return distance;
    }

    /// Move the race forward one second.
    fn tick(&mut self) {
        if self.speed_time_left > 0 {
            self.current_distance += self.speed;
            self.speed_time_left -= 1;
            if self.speed_time_left == 0 {
                self.rest_time_left = self.rest_time;
            }
        } else {
            self.rest_time_left -= 1;
            if self.rest_time_left == 0 {
                self.speed_time_left = self.speed_time;
            }
        }
    }
}

fn award_points(reindeers: &mut Vec<Reindeer>) {
    let mut max_distance = 0;
    for r in reindeers.iter() {
        if r.current_distance > max_distance {
            max_distance = r.current_distance;
        }
    }

    for r in reindeers.iter_mut() {
        if r.current_distance >= max_distance {
            r.points += 1;
        }
    }
}

fn part1(reindeers: Vec<Reindeer>) {
    let time_in_secs = 2503;
    for r in reindeers.iter() {
        println!("{:10} traveled {:4} km in {:5} seconds",
                 r.name,
                 r.distance_traveled(time_in_secs),
                 time_in_secs);
    }
}

fn part2(reindeers: Vec<Reindeer>) {
    let mut reindeers = reindeers;
    let time_in_secs = 2503;
    for _ in 0..time_in_secs {
        for r in reindeers.iter_mut() {
            r.tick();
        }

        // Find the winning reindeer and award them a point.
        award_points(&mut reindeers);
    }
    for r in reindeers.iter() {
        println!("{:10} traveled {:4} km in {:5} seconds and received {:5} points.",
                 r.name,
                 r.distance_traveled(time_in_secs),
                 time_in_secs,
                 r.points);
    }
}

fn main() {
    let file = File::open("input.txt").unwrap();
    let reader = BufReader::new(&file);

    let regex = Regex::new(r"(?P<name>[[:alpha:]]+) can fly (?P<speed>[[:digit:]]+) km/s for (?P<speed_time>[[:digit:]]+) seconds, but then must rest for (?P<rest_time>[[:digit:]]+) seconds.").unwrap();
    let mut reindeers: Vec<Reindeer> = Vec::with_capacity(10);
    for wrapped_line in reader.lines() {
        let line = wrapped_line.unwrap();
        let maybe_match = regex.captures(line.as_str());
        match maybe_match {
            Some(capture) => {
                let name = capture.name("name").unwrap().as_str();
                let speed = capture.name("speed").unwrap().as_str().parse::<isize>().unwrap();
                let speed_time =
                    capture.name("speed_time").unwrap().as_str().parse::<isize>().unwrap();
                let rest_time =
                    capture.name("rest_time").unwrap().as_str().parse::<isize>().unwrap();
                reindeers.push(Reindeer {
                    name: String::from(name),
                    speed: speed,
                    speed_time: speed_time,
                    rest_time: rest_time,
                    current_distance: 0,
                    points: 0,
                    rest_time_left: 0,
                    speed_time_left: speed_time,
                });

            }
            None => panic!("No match for '{}'", line),
        }
    }
    part1(reindeers.clone());
    part2(reindeers);
}
<|endoftext|>


<commit_before>extern crate syntex_syntax;

use std::fs::File;
use std::io::{self, Write};
use std::path::Path;

use syntex_syntax::ast;
use syntex_syntax::attr;
use syntex_syntax::codemap::{DUMMY_SP, respan};
use syntex_syntax::ext::base::{
    IdentMacroExpander,
    MultiItemDecorator,
    MultiItemModifier,
    NamedSyntaxExtension,
    SyntaxExtension,
    TTMacroExpander,
};
use syntex_syntax::ext::base::ExtCtxt;
use syntex_syntax::ext::expand;
use syntex_syntax::feature_gate;
use syntex_syntax::parse::{self, token};
use syntex_syntax::print::pprust;
use syntex_syntax::ptr::P;

pub type Pass = fn(ast::Crate) -> ast::Crate;

pub struct Registry {
    macros: Vec<ast::MacroDef>,
    syntax_exts: Vec<NamedSyntaxExtension>,
    pre_expansion_passes: Vec<Box<Pass>>,
    post_expansion_passes: Vec<Box<Pass>>,
    cfg: Vec<P<ast::MetaItem>>,
    attrs: Vec<ast::Attribute>,
}

impl Registry {
    pub fn new() -> Registry {
        Registry {
            macros: Vec::new(),
            syntax_exts: Vec::new(),
            pre_expansion_passes: Vec::new(),
            post_expansion_passes: Vec::new(),
            cfg: Vec::new(),
            attrs: Vec::new(),
        }
    }

    pub fn add_cfg(&mut self, cfg: &str) {
        let meta_item = parse::parse_meta_from_source_str(
            "cfgspec".to_string(),
            cfg.to_string(),
            Vec::new(),
            &parse::ParseSess::new());

        self.cfg.push(meta_item);
    }

    pub fn add_attr(&mut self, attr: &str) {
        let meta_item = parse::parse_meta_from_source_str(
            "attrspec".to_string(),
            attr.to_string(),
            Vec::new(),
            &parse::ParseSess::new());

        self.attrs.push(respan(DUMMY_SP, ast::Attribute_ {
            id: attr::mk_attr_id(),
            style: ast::AttrStyle::Outer,
            value: meta_item,
            is_sugared_doc: false,
        }));
    }

    pub fn add_macro<F>(&mut self, name: &str, extension: F)
        where F: TTMacroExpander + 'static
    {
        let name = token::intern(name);
        let syntax_extension = SyntaxExtension::NormalTT(
            Box::new(extension),
            None,
            false
        );
        self.syntax_exts.push((name, syntax_extension));
    }

    pub fn add_ident_macro<F>(&mut self, name: &str, extension: F)
        where F: IdentMacroExpander + 'static
    {
        let name = token::intern(name);
        let syntax_extension = SyntaxExtension::IdentTT(
            Box::new(extension),
            None,
            false
        );
        self.syntax_exts.push((name, syntax_extension));
    }

    pub fn add_decorator<F>(&mut self, name: &str, extension: F)
        where F: MultiItemDecorator + 'static
    {
        let name = token::intern(name);
        let syntax_extension = SyntaxExtension::MultiDecorator(Box::new(extension));
        self.syntax_exts.push((name, syntax_extension));
    }

    pub fn add_modifier<F>(&mut self, name: &str, extension: F)
        where F: MultiItemModifier + 'static
    {
        let name = token::intern(name);
        let syntax_extension = SyntaxExtension::MultiModifier(Box::new(extension));
        self.syntax_exts.push((name, syntax_extension));
    }

    pub fn add_pre_expansion_pass(&mut self, pass: Pass) {
        self.pre_expansion_passes.push(Box::new(pass))
    }

    pub fn add_post_expansion_pass(&mut self, pass: Pass) {
        self.post_expansion_passes.push(Box::new(pass))
    }

    pub fn expand(self, crate_name: &str, src: &Path, dst: &Path) -> io::Result<()> {
        let sess = parse::ParseSess::new();

        let mut krate = parse::parse_crate_from_file(
            src,
            self.cfg,
            &sess);

        krate.attrs.extend(self.attrs);

        let features = feature_gate::check_crate_macros(
            &sess.codemap(),
            &sess.span_diagnostic,
            &krate);

        let krate = self.pre_expansion_passes.iter()
            .fold(krate, |krate, f| (f)(krate));

        let mut ecfg = expand::ExpansionConfig::default(crate_name.to_string());
        ecfg.features = Some(&features);

        let cfg = Vec::new();
        let mut gated_cfgs = Vec::new();
        let ecx = ExtCtxt::new(&sess, cfg, ecfg, &mut gated_cfgs);

        let (krate, _) = expand::expand_crate(ecx, self.macros, self.syntax_exts, krate);

        let krate = self.post_expansion_passes.iter()
            .fold(krate, |krate, f| (f)(krate));

        let src_name = src.to_str().unwrap().to_string();
        let src = sess.codemap()
            .get_filemap(&src_name)
            .src
            .as_ref()
            .unwrap()
            .as_bytes()
            .to_vec();
        let mut rdr = &src[..];

        let mut out = Vec::new();
        let annotation = pprust::NoAnn;

        {
            let out: &mut io::Write = &mut out;

            try!(pprust::print_crate(
                sess.codemap(),
                &sess.span_diagnostic,
                &krate,
                src_name.to_string(),
                &mut rdr,
                Box::new(out),
                &annotation,
                false)
            );
        }

        let mut dst = try!(File::create(dst));
        dst.write_all(&out)
    }
}
<commit_msg>Updated following libsyntax changes<commit_after>extern crate syntex_syntax;

use std::fs::File;
use std::io::{self, Write};
use std::path::Path;

use syntex_syntax::ast;
use syntex_syntax::attr;
use syntex_syntax::codemap::{DUMMY_SP, respan};
use syntex_syntax::ext::base::{
    IdentMacroExpander,
    MultiItemDecorator,
    MultiItemModifier,
    NamedSyntaxExtension,
    SyntaxExtension,
    TTMacroExpander,
};
use syntex_syntax::ext::base::ExtCtxt;
use syntex_syntax::ext::expand;
use syntex_syntax::feature_gate;
use syntex_syntax::parse::{self, token};
use syntex_syntax::print::pprust;
use syntex_syntax::ptr::P;

pub type Pass = fn(ast::Crate) -> ast::Crate;

pub struct Registry {
    macros: Vec<ast::MacroDef>,
    syntax_exts: Vec<NamedSyntaxExtension>,
    pre_expansion_passes: Vec<Box<Pass>>,
    post_expansion_passes: Vec<Box<Pass>>,
    cfg: Vec<P<ast::MetaItem>>,
    attrs: Vec<ast::Attribute>,
}

impl Registry {
    pub fn new() -> Registry {
        Registry {
            macros: Vec::new(),
            syntax_exts: Vec::new(),
            pre_expansion_passes: Vec::new(),
            post_expansion_passes: Vec::new(),
            cfg: Vec::new(),
            attrs: Vec::new(),
        }
    }

    pub fn add_cfg(&mut self, cfg: &str) {
        let parse_sess = parse::ParseSess::new();
        let meta_item = parse::parse_meta_from_source_str(
            "cfgspec".to_string(),
            cfg.to_string(),
            Vec::new(),
            &parse_sess).unwrap();

        self.cfg.push(meta_item);
    }

    pub fn add_attr(&mut self, attr: &str) {
        let parse_sess = parse::ParseSess::new();
        let meta_item = parse::parse_meta_from_source_str(
            "attrspec".to_string(),
            attr.to_string(),
            Vec::new(),
            &parse_sess).unwrap();

        self.attrs.push(respan(DUMMY_SP, ast::Attribute_ {
            id: attr::mk_attr_id(),
            style: ast::AttrStyle::Outer,
            value: meta_item,
            is_sugared_doc: false,
        }));
    }

    pub fn add_macro<F>(&mut self, name: &str, extension: F)
        where F: TTMacroExpander + 'static
    {
        let name = token::intern(name);
        let syntax_extension = SyntaxExtension::NormalTT(
            Box::new(extension),
            None,
            false
        );
        self.syntax_exts.push((name, syntax_extension));
    }

    pub fn add_ident_macro<F>(&mut self, name: &str, extension: F)
        where F: IdentMacroExpander + 'static
    {
        let name = token::intern(name);
        let syntax_extension = SyntaxExtension::IdentTT(
            Box::new(extension),
            None,
            false
        );
        self.syntax_exts.push((name, syntax_extension));
    }

    pub fn add_decorator<F>(&mut self, name: &str, extension: F)
        where F: MultiItemDecorator + 'static
    {
        let name = token::intern(name);
        let syntax_extension = SyntaxExtension::MultiDecorator(Box::new(extension));
        self.syntax_exts.push((name, syntax_extension));
    }

    pub fn add_modifier<F>(&mut self, name: &str, extension: F)
        where F: MultiItemModifier + 'static
    {
        let name = token::intern(name);
        let syntax_extension = SyntaxExtension::MultiModifier(Box::new(extension));
        self.syntax_exts.push((name, syntax_extension));
    }

    pub fn add_pre_expansion_pass(&mut self, pass: Pass) {
        self.pre_expansion_passes.push(Box::new(pass))
    }

    pub fn add_post_expansion_pass(&mut self, pass: Pass) {
        self.post_expansion_passes.push(Box::new(pass))
    }

    pub fn expand(self, crate_name: &str, src: &Path, dst: &Path) -> io::Result<()> {
        let sess = parse::ParseSess::new();

        let mut krate = parse::parse_crate_from_file(
            src,
            self.cfg,
            &sess).unwrap();

        krate.attrs.extend(self.attrs);

        let features = feature_gate::check_crate_macros(
            &sess.codemap(),
            &sess.span_diagnostic,
            &krate);

        let krate = self.pre_expansion_passes.iter()
            .fold(krate, |krate, f| (f)(krate));

        let mut ecfg = expand::ExpansionConfig::default(crate_name.to_string());
        ecfg.features = Some(&features);

        let cfg = Vec::new();
        let mut gated_cfgs = Vec::new();
        let ecx = ExtCtxt::new(&sess, cfg, ecfg, &mut gated_cfgs);

        let (krate, _) = expand::expand_crate(ecx, self.macros, self.syntax_exts, krate);

        let krate = self.post_expansion_passes.iter()
            .fold(krate, |krate, f| (f)(krate));

        let src_name = src.to_str().unwrap().to_string();
        let src = sess.codemap()
            .get_filemap(&src_name)
            .src
            .as_ref()
            .unwrap()
            .as_bytes()
            .to_vec();
        let mut rdr = &src[..];

        let mut out = Vec::new();
        let annotation = pprust::NoAnn;

        {
            let out: &mut io::Write = &mut out;

            try!(pprust::print_crate(
                sess.codemap(),
                &sess.span_diagnostic,
                &krate,
                src_name.to_string(),
                &mut rdr,
                Box::new(out),
                &annotation,
                false)
            );
        }

        let mut dst = try!(File::create(dst));
        dst.write_all(&out)
    }
}
<|endoftext|>


<commit_before>//! Arbitrator, mainly used for client TCP sessions
//! Enforces a maximum amount of simultaneous sessions, but refusing new oneshot
//! once the slab is full, or by reusing existing slots.

use futures::sync::oneshot;
use parking_lot::Mutex;
use rand::{self, Rng};
use rand::distributions::{IndependentSample, Range};
use siphasher::sip::SipHasher13;
use slab::Slab;
use std::hash::{Hash, Hasher};
use std::net::SocketAddr;
use std::sync::Arc;
use super::MAX_TCP_HASH_DISTANCE;

struct Session {
    session_tx: oneshot::Sender<()>,
    h: u64,
}

struct Sessions {
    slab: Slab<Session>,
}

#[derive(Clone)]
pub struct TcpArbitrator {
    sessions_mx: Arc<Mutex<Sessions>>,
    hasher: SipHasher13,
}

impl TcpArbitrator {
    pub fn with_capacity(capacity: usize) -> Self {
        let slab = Slab::with_capacity(capacity);
        let sessions = Sessions { slab: slab };
        let mut rng = rand::thread_rng();
        let hasher = SipHasher13::new_with_keys(rng.gen(), rng.gen());
        TcpArbitrator {
            sessions_mx: Arc::new(Mutex::new(sessions)),
            hasher: hasher,
        }
    }

    pub fn new_session(&mut self,
                       client_addr: &SocketAddr)
                       -> Result<(oneshot::Receiver<()>, usize), &'static str> {
        let mut hasher = self.hasher.clone();
        client_addr.ip().hash(&mut hasher);
        let h = hasher.finish();
        let (session_tx, session_rx) = oneshot::channel();
        let session = Session {
            session_tx: session_tx,
            h: h,
        };
        let mut slab = &mut self.sessions_mx.lock().slab;
        self.recycle_slot_if_full(&mut slab, h);
        match slab.insert(session) {
            Err(_) => {
                warn!("Tcp arbitrator slab is full");
                Err("Tcp arbitrator slab is full")
            }
            Ok(idx) => Ok((session_rx, idx)),
        }
    }

    pub fn delete_session(&mut self, idx: usize) -> Option<()> {
        self.sessions_mx.lock().slab.remove(idx).map(|_| {})
    }

    fn recycle_slot_if_full(&self, mut slab: &mut Slab<Session>, h: u64) {
        if slab.has_available() {
            return;
        }
        let mut rng = rand::thread_rng();
        let random_distance = Range::new(0, MAX_TCP_HASH_DISTANCE).ind_sample(&mut rng);
        let capacity = slab.capacity();
        let base_slot = (h as usize) % capacity;
        let mut new_slot = None;
        for i in 0..MAX_TCP_HASH_DISTANCE {
            let probed_slot = (base_slot + (random_distance + i) % MAX_TCP_HASH_DISTANCE) %
                              capacity;
            match slab.get(probed_slot) {
                None => {
                    new_slot = Some(probed_slot);
                    break;
                }
                Some(session) => {
                    if session.h == h {
                        new_slot = Some(probed_slot);
                        break;
                    }
                }
            }
        }
        let new_slot = new_slot.unwrap_or((base_slot + random_distance) % MAX_TCP_HASH_DISTANCE);
        if let Some(prev_session) = slab.remove(new_slot) {
            info!("Recycling session index {}", new_slot);
            let _ = prev_session.session_tx.send(());
        }
    }
}
<commit_msg>SipHasher has the Copy trait, no need to clone() it<commit_after>//! Arbitrator, mainly used for client TCP sessions
//! Enforces a maximum amount of simultaneous sessions, but refusing new oneshot
//! once the slab is full, or by reusing existing slots.

use futures::sync::oneshot;
use parking_lot::Mutex;
use rand::{self, Rng};
use rand::distributions::{IndependentSample, Range};
use siphasher::sip::SipHasher13;
use slab::Slab;
use std::hash::{Hash, Hasher};
use std::net::SocketAddr;
use std::sync::Arc;
use super::MAX_TCP_HASH_DISTANCE;

struct Session {
    session_tx: oneshot::Sender<()>,
    h: u64,
}

struct Sessions {
    slab: Slab<Session>,
}

#[derive(Clone)]
pub struct TcpArbitrator {
    sessions_mx: Arc<Mutex<Sessions>>,
    hasher: SipHasher13,
}

impl TcpArbitrator {
    pub fn with_capacity(capacity: usize) -> Self {
        let slab = Slab::with_capacity(capacity);
        let sessions = Sessions { slab: slab };
        let mut rng = rand::thread_rng();
        let hasher = SipHasher13::new_with_keys(rng.gen(), rng.gen());
        TcpArbitrator {
            sessions_mx: Arc::new(Mutex::new(sessions)),
            hasher: hasher,
        }
    }

    pub fn new_session(&mut self,
                       client_addr: &SocketAddr)
                       -> Result<(oneshot::Receiver<()>, usize), &'static str> {
        let mut hasher = self.hasher;
        client_addr.ip().hash(&mut hasher);
        let h = hasher.finish();
        let (session_tx, session_rx) = oneshot::channel();
        let session = Session {
            session_tx: session_tx,
            h: h,
        };
        let mut slab = &mut self.sessions_mx.lock().slab;
        self.recycle_slot_if_full(&mut slab, h);
        match slab.insert(session) {
            Err(_) => {
                warn!("Tcp arbitrator slab is full");
                Err("Tcp arbitrator slab is full")
            }
            Ok(idx) => Ok((session_rx, idx)),
        }
    }

    pub fn delete_session(&mut self, idx: usize) -> Option<()> {
        self.sessions_mx.lock().slab.remove(idx).map(|_| {})
    }

    fn recycle_slot_if_full(&self, mut slab: &mut Slab<Session>, h: u64) {
        if slab.has_available() {
            return;
        }
        let mut rng = rand::thread_rng();
        let random_distance = Range::new(0, MAX_TCP_HASH_DISTANCE).ind_sample(&mut rng);
        let capacity = slab.capacity();
        let base_slot = (h as usize) % capacity;
        let mut new_slot = None;
        for i in 0..MAX_TCP_HASH_DISTANCE {
            let probed_slot = (base_slot + (random_distance + i) % MAX_TCP_HASH_DISTANCE) %
                              capacity;
            match slab.get(probed_slot) {
                None => {
                    new_slot = Some(probed_slot);
                    break;
                }
                Some(session) => {
                    if session.h == h {
                        new_slot = Some(probed_slot);
                        break;
                    }
                }
            }
        }
        let new_slot = new_slot.unwrap_or((base_slot + random_distance) % MAX_TCP_HASH_DISTANCE);
        if let Some(prev_session) = slab.remove(new_slot) {
            info!("Recycling session index {}", new_slot);
            let _ = prev_session.session_tx.send(());
        }
    }
}
<|endoftext|>


<commit_before>use redox::Box;
use redox::fs::File;
use redox::io::*;
use redox::mem;
use redox::ops::DerefMut;
use redox::slice;
use redox::syscall::sys_yield;
use redox::String;
use redox::ToString;
use redox::Vec;

use super::Event;
use super::Color;

/// A window
pub struct Window {
    /// The x coordinate of the window
    x: isize,
    /// The y coordinate of the window
    y: isize,
    /// The width of the window
    w: usize,
    /// The height of the window
    h: usize,
    /// The title of the window
    t: String,
    /// The input scheme
    file: File,
    /// Font file
    font: Vec<u8>,
    /// Window data
    data: Vec<u32>,
}

impl Window {
    /// Create a new window
    pub fn new(x: isize, y: isize, w: usize, h: usize, title: &str) -> Option<Box<Self>> {
        let mut font = Vec::new();
        if let Some(mut font_file) = File::open("file:/ui/unifont.font") {
            font_file.read_to_end(&mut font);
        }

        match File::open(&format!("orbital:///{}/{}/{}/{}/{}", x, y, w, h, title)) {
            Some(file) => Some(box Window {
                x: x,
                y: y,
                w: w,
                h: h,
                t: title.to_string(),
                file: file,
                font: font,
                data: vec![0; w * h * 4],
            }),
            None => None
        }
    }

    /// Get x
    //TODO: Sync with window movements
    pub fn x(&self) -> isize {
        self.x
    }

    /// Get y
    //TODO: Sync with window movements
    pub fn y(&self) -> isize {
        self.y
    }

    /// Get width
    pub fn width(&self) -> usize {
        self.w
    }

    /// Get height
    pub fn height(&self) -> usize {
        self.h
    }

    /// Get title
    pub fn title(&self) -> String {
        self.t.clone()
    }

    /// Set title
    pub fn set_title(&mut self, title: &str) {
        //TODO
    }

    /// Draw a pixel
    pub fn pixel(&mut self, x: isize, y: isize, color: Color) {
        if x >= 0 && y >= 0 && x < self.w as isize && y < self.h as isize {
            let offset = y as usize * self.w + x as usize;
            self.data[offset] = color.data;
        }
    }

    /// Draw a character, using the loaded font
    pub fn char(&mut self, x: isize, y: isize, c: char, color: Color) {
        let mut offset = (c as usize) * 16;
        for row in 0..16 {
            let row_data;
            if offset < self.font.len() {
                row_data = self.font[offset];
            } else {
                row_data = 0;
            }

            for col in 0..8 {
                let pixel = (row_data >> (7 - col)) & 1;
                if pixel > 0 {
                    self.pixel(x + col as isize, y + row as isize, color);
                }
            }
            offset += 1;
        }
    }

    //TODO move, resize, set_title

    /// Set entire window to a color
    // TODO: Improve speed
    #[allow(unused_variables)]
    pub fn set(&mut self, color: Color) {
        let w = self.w;
        let h = self.h;
        self.rect(0, 0, w, h, color);
    }

    /// Draw rectangle
    // TODO: Improve speed
    #[allow(unused_variables)]
    pub fn rect(&mut self, start_x: isize, start_y: isize, w: usize, h: usize, color: Color) {
        for y in start_y..start_y + h as isize {
            for x in start_x..start_x + w as isize {
                self.pixel(x, y, color);
            }
        }
    }

    /// Display an image
    //TODO: Improve speed
    pub fn image(&mut self, start_x: isize, start_y: isize, w: usize, h: usize, data: &[Color]) {
        let mut i = 0;
        for y in start_y..start_y + h as isize {
            for x in start_x..start_x + w as isize {
                if i < data.len() {
                    self.pixel(x, y, data[i])
                }
                i += 1;
            }
        }
    }

    /// Poll for an event
    //TODO: clean this up
    pub fn poll(&mut self) -> Option<Event> {
        let mut event = box Event::new();
        let event_ptr: *mut Event = event.deref_mut();
        loop {
            match self.file.read(&mut unsafe {
                slice::from_raw_parts_mut(event_ptr as *mut u8, mem::size_of::<Event>())
            }) {
                Some(0) => unsafe { sys_yield() },
                Some(_) => return Some(*event),
                None => return None,
            }
        }
    }

    /// Flip the window buffer
    pub fn sync(&mut self) -> bool {
        self.file.seek(SeekFrom::Start(0));
        let to_write: &[u8] = unsafe{ mem::transmute::<&[u32],&[u8]>(&self.data) };
        self.file.write(to_write);
        return self.file.sync();
    }

    /// Return a iterator over events
    pub fn event_iter<'a>(&'a mut self) -> EventIter<'a> {
        EventIter {
            window: self,
        }
    }
}

/// Event iterator
pub struct EventIter<'a> {
    window: &'a mut Window,
}

impl<'a> Iterator for EventIter<'a> {
    type Item = Event;
    fn next(&mut self) -> Option<Event> {
        self.window.poll()
    }
}
<commit_msg>Fix file manager window movement<commit_after>use redox::Box;
use redox::fs::File;
use redox::io::*;
use redox::mem;
use redox::ops::DerefMut;
use redox::slice;
use redox::syscall::sys_yield;
use redox::String;
use redox::ToString;
use redox::to_num::ToNum;
use redox::Vec;

use super::Event;
use super::Color;

/// A window
pub struct Window {
    /// The x coordinate of the window
    x: isize,
    /// The y coordinate of the window
    y: isize,
    /// The width of the window
    w: usize,
    /// The height of the window
    h: usize,
    /// The title of the window
    t: String,
    /// The input scheme
    file: File,
    /// Font file
    font: Vec<u8>,
    /// Window data
    data: Vec<u32>,
}

impl Window {
    /// Create a new window
    pub fn new(x: isize, y: isize, w: usize, h: usize, title: &str) -> Option<Box<Self>> {
        let mut font = Vec::new();
        if let Some(mut font_file) = File::open("file:/ui/unifont.font") {
            font_file.read_to_end(&mut font);
        }

        match File::open(&format!("orbital:///{}/{}/{}/{}/{}", x, y, w, h, title)) {
            Some(file) => Some(box Window {
                x: x,
                y: y,
                w: w,
                h: h,
                t: title.to_string(),
                file: file,
                font: font,
                data: vec![0; w * h * 4],
            }),
            None => None
        }
    }

    //TODO: Replace with smarter mechanism, maybe a move event?
    pub fn sync_path(&mut self) {
        if let Some(path) = self.file.path() {
            //orbital://x/y/w/h/t
            let parts: Vec<&str> = path.split('/').collect();
            if let Some(x) = parts.get(3) {
                self.x = x.to_num_signed();
            }
            if let Some(y) = parts.get(4) {
                self.y = y.to_num_signed();
            }
            if let Some(w) = parts.get(5) {
                self.w = w.to_num();
            }
            if let Some(h) = parts.get(6) {
                self.h = h.to_num();
            }
        }
    }

    /// Get x
    //TODO: Sync with window movements
    pub fn x(&self) -> isize {
        self.x
    }

    /// Get y
    //TODO: Sync with window movements
    pub fn y(&self) -> isize {
        self.y
    }

    /// Get width
    pub fn width(&self) -> usize {
        self.w
    }

    /// Get height
    pub fn height(&self) -> usize {
        self.h
    }

    /// Get title
    pub fn title(&self) -> String {
        self.t.clone()
    }

    /// Set title
    pub fn set_title(&mut self, title: &str) {
        //TODO
    }

    /// Draw a pixel
    pub fn pixel(&mut self, x: isize, y: isize, color: Color) {
        if x >= 0 && y >= 0 && x < self.w as isize && y < self.h as isize {
            let offset = y as usize * self.w + x as usize;
            self.data[offset] = color.data;
        }
    }

    /// Draw a character, using the loaded font
    pub fn char(&mut self, x: isize, y: isize, c: char, color: Color) {
        let mut offset = (c as usize) * 16;
        for row in 0..16 {
            let row_data;
            if offset < self.font.len() {
                row_data = self.font[offset];
            } else {
                row_data = 0;
            }

            for col in 0..8 {
                let pixel = (row_data >> (7 - col)) & 1;
                if pixel > 0 {
                    self.pixel(x + col as isize, y + row as isize, color);
                }
            }
            offset += 1;
        }
    }

    //TODO move, resize, set_title

    /// Set entire window to a color
    // TODO: Improve speed
    #[allow(unused_variables)]
    pub fn set(&mut self, color: Color) {
        let w = self.w;
        let h = self.h;
        self.rect(0, 0, w, h, color);
    }

    /// Draw rectangle
    // TODO: Improve speed
    #[allow(unused_variables)]
    pub fn rect(&mut self, start_x: isize, start_y: isize, w: usize, h: usize, color: Color) {
        for y in start_y..start_y + h as isize {
            for x in start_x..start_x + w as isize {
                self.pixel(x, y, color);
            }
        }
    }

    /// Display an image
    //TODO: Improve speed
    pub fn image(&mut self, start_x: isize, start_y: isize, w: usize, h: usize, data: &[Color]) {
        let mut i = 0;
        for y in start_y..start_y + h as isize {
            for x in start_x..start_x + w as isize {
                if i < data.len() {
                    self.pixel(x, y, data[i])
                }
                i += 1;
            }
        }
    }

    /// Poll for an event
    //TODO: clean this up
    pub fn poll(&mut self) -> Option<Event> {
        let mut event = box Event::new();
        let event_ptr: *mut Event = event.deref_mut();
        loop {
            match self.file.read(&mut unsafe {
                slice::from_raw_parts_mut(event_ptr as *mut u8, mem::size_of::<Event>())
            }) {
                Some(0) => unsafe { sys_yield() },
                Some(_) => return Some(*event),
                None => return None,
            }
        }
    }

    /// Flip the window buffer
    pub fn sync(&mut self) -> bool {
        self.file.seek(SeekFrom::Start(0));
        let to_write: &[u8] = unsafe{ mem::transmute::<&[u32],&[u8]>(&self.data) };
        self.file.write(to_write);
        return self.file.sync();
    }

    /// Return a iterator over events
    pub fn event_iter<'a>(&'a mut self) -> EventIter<'a> {
        EventIter {
            window: self,
        }
    }
}

/// Event iterator
pub struct EventIter<'a> {
    window: &'a mut Window,
}

impl<'a> Iterator for EventIter<'a> {
    type Item = Event;
    fn next(&mut self) -> Option<Event> {
        self.window.poll()
    }
}
<|endoftext|>