<commit_before>use command::Command;
use vm::VM;

pub struct Program {
    instructions : Vec<Command>,
    instruction_pointer: Option<usize>,
    current_depth: u64,
    pub status: ProgramStatus,
}

#[derive(Clone,Copy,PartialEq,Debug)]
pub enum ProgramStatus {
    Normal,
    Seeking(u64),
}

impl Program {
    pub fn new () -> Program {
        Program {
            instructions: Vec::new(),
            instruction_pointer: None,
            current_depth: 0,
            status: ProgramStatus::Normal,
        }
    }

    pub fn append(&mut self, instructions: &[Command]) {
        self.instructions.extend(instructions.iter().cloned());
        if self.instruction_pointer.is_none() { self.instruction_pointer = Some(0); }
    }

    pub fn execute(&mut self, vm: &mut VM) {
        match (self.instruction_pointer, self.status) {
            (Some(mut index), ProgramStatus::Normal) => {
                while index < self.instructions.len() {
                    match self.instructions[index] {
                        Command::JumpForward => {
                            let jump_report = self.start_jump_forward(vm, index);
                            index = jump_report.0;
                            self.status = jump_report.1;
                        },
                        Command::JumpBackward => index = self.jump_backward(&vm, index),
                        command => {
                            vm.apply(command);
                            index += 1;
                        }
                    }
                }
                self.instruction_pointer = Some(index);
            },

            (Some(index), ProgramStatus::Seeking(goal_depth)) => {
                let (new_index, new_status) = self.seek_forward(index, goal_depth);
                self.instruction_pointer = Some(new_index);
                self.status = new_status;
                self.execute(vm);
            },

            _ => {}
        }
    }

    fn jump_backward (&mut self, vm: &VM, starting_index: usize) -> usize {
        match vm.cells[vm.data_pointer] {
            0 => {
                self.current_depth = self.current_depth - 1;
                starting_index + 1
            },
            _ => {
                let goal_depth = self.current_depth;
                for index in (0..starting_index).rev() {
                    match self.instructions[index] {
                        Command::JumpBackward => self.current_depth += 1,
                        Command::JumpForward => {
                            if self.current_depth == goal_depth { return index + 1 }
                            self.current_depth -= 1;
                        },
                        _ => {},
                    }
                }
                panic!("No starting brace found!");
            },
        }
    }

    fn seek_forward(&mut self, starting_index: usize, goal_depth: u64) -> (usize, ProgramStatus) {
        for index in starting_index..self.instructions.len() {
            match self.instructions[index] {
                Command::JumpForward => self.current_depth += 1,
                Command::JumpBackward => self.current_depth -= 1,
                _ => {},
            }
            if self.current_depth == goal_depth {
                return (index + 1, ProgramStatus::Normal);
            }
        }
        return (self.instructions.len(), ProgramStatus::Seeking(goal_depth));
    }

    fn start_jump_forward(&mut self, vm: &VM, index: usize) -> (usize, ProgramStatus) {
        match vm.cells[vm.data_pointer] {
            0 => {
                let goal_depth = self.current_depth;
                return self.seek_forward(index, goal_depth);
            },
            _ => {
                self.current_depth += 1;
                return (index + 1, ProgramStatus::Normal);
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    pub fn test_seek_forward_normal() {
        let mut program = Program {
            instruction_pointer: Some(0),
            current_depth: 0,
            status: ProgramStatus::Normal,
            instructions: vec![ Command::JumpForward
                              , Command::JumpForward
                              , Command::JumpBackward
                              , Command::JumpBackward]};
        let actual = program.seek_forward(0, 0);
        let expected = (4, ProgramStatus::Normal);
        assert_eq!(actual, expected);
    }

    #[test]
    pub fn test_seek_forward_seeking() {
        let mut program = Program {
            instruction_pointer: Some(0),
            current_depth: 0,
            status: ProgramStatus::Normal,
            instructions: vec![ Command::JumpForward
                              , Command::JumpForward
                              , Command::JumpBackward]};
        let actual = program.seek_forward(0, 0);
        let expected = (3, ProgramStatus::Seeking(0));
        assert_eq!(actual, expected);
    }
}
<commit_msg>Make statements more readable<commit_after>use command::Command;
use vm::VM;

pub struct Program {
    instructions : Vec<Command>,
    instruction_pointer: Option<usize>,
    current_depth: u64,
    pub status: ProgramStatus,
}

#[derive(Clone,Copy,PartialEq,Debug)]
pub enum ProgramStatus {
    Normal,
    Seeking(u64),
}

impl Program {
    pub fn new () -> Program {
        Program {
            instructions: Vec::new(),
            instruction_pointer: None,
            current_depth: 0,
            status: ProgramStatus::Normal,
        }
    }

    pub fn append(&mut self, instructions: &[Command]) {
        self.instructions.extend(instructions.iter().cloned());
        if self.instruction_pointer.is_none() { self.instruction_pointer = Some(0); }
    }

    pub fn execute(&mut self, vm: &mut VM) {
        match (self.instruction_pointer, self.status) {
            (Some(mut index), ProgramStatus::Normal) => {
                while index < self.instructions.len() {
                    match self.instructions[index] {
                        Command::JumpForward => {
                            let jump_report = self.start_jump_forward(vm, index);
                            index = jump_report.0;
                            self.status = jump_report.1;
                        },
                        Command::JumpBackward => index = self.jump_backward(&vm, index),
                        command => {
                            vm.apply(command);
                            index += 1;
                        }
                    }
                }
                self.instruction_pointer = Some(index);
            },

            (Some(index), ProgramStatus::Seeking(goal_depth)) => {
                let (new_index, new_status) = self.seek_forward(index, goal_depth);
                self.instruction_pointer = Some(new_index);
                self.status = new_status;
                self.execute(vm);
            },

            _ => {}
        }
    }

    fn jump_backward (&mut self, vm: &VM, starting_index: usize) -> usize {
        match vm.cells[vm.data_pointer] {
            0 => {
                self.current_depth -= 1;
                return starting_index + 1;
            },
            _ => {
                let goal_depth = self.current_depth;
                for index in (0..starting_index).rev() {
                    match self.instructions[index] {
                        Command::JumpBackward => self.current_depth += 1,
                        Command::JumpForward => {
                            if self.current_depth == goal_depth { return index + 1 }
                            self.current_depth -= 1;
                        },
                        _ => {},
                    }
                }
                panic!("No starting brace found!");
            },
        }
    }

    fn seek_forward(&mut self, starting_index: usize, goal_depth: u64) -> (usize, ProgramStatus) {
        for index in starting_index..self.instructions.len() {
            match self.instructions[index] {
                Command::JumpForward => self.current_depth += 1,
                Command::JumpBackward => self.current_depth -= 1,
                _ => {},
            }
            if self.current_depth == goal_depth {
                return (index + 1, ProgramStatus::Normal);
            }
        }
        return (self.instructions.len(), ProgramStatus::Seeking(goal_depth));
    }

    fn start_jump_forward(&mut self, vm: &VM, index: usize) -> (usize, ProgramStatus) {
        match vm.cells[vm.data_pointer] {
            0 => {
                let goal_depth = self.current_depth;
                return self.seek_forward(index, goal_depth);
            },
            _ => {
                self.current_depth += 1;
                return (index + 1, ProgramStatus::Normal);
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    pub fn test_seek_forward_normal() {
        let mut program = Program {
            instruction_pointer: Some(0),
            current_depth: 0,
            status: ProgramStatus::Normal,
            instructions: vec![ Command::JumpForward
                              , Command::JumpForward
                              , Command::JumpBackward
                              , Command::JumpBackward]};
        let actual = program.seek_forward(0, 0);
        let expected = (4, ProgramStatus::Normal);
        assert_eq!(actual, expected);
    }

    #[test]
    pub fn test_seek_forward_seeking() {
        let mut program = Program {
            instruction_pointer: Some(0),
            current_depth: 0,
            status: ProgramStatus::Normal,
            instructions: vec![ Command::JumpForward
                              , Command::JumpForward
                              , Command::JumpBackward]};
        let actual = program.seek_forward(0, 0);
        let expected = (3, ProgramStatus::Seeking(0));
        assert_eq!(actual, expected);
    }
}
<|endoftext|>


<commit_before>#![allow(non_snake_case)]

use std::str::from_utf8;
use std::collections::HashMap;
use std::thread;

use rustc_serialize::json;
use curl::http;

pub const SESSION_TTL: &'static str = "15s";

#[derive(RustcDecodable, RustcEncodable, Debug)]
pub struct SessionCreate {
    Name: String,
    TTL: String
}

#[derive(RustcDecodable, RustcEncodable, Debug)]
pub struct SessionID {
    ID: String
}

pub struct Session {
    endpoint: String
}

impl Session {
    pub fn new(address: &str) ->  Session {
        Session {
            endpoint: format!("http://{}/v1/session", address)
        }
    }

    pub fn create(&self, name: String) -> String{
        let url = format!("{}/create", self.endpoint);
        let session = SessionCreate {
            Name: name,
            TTL: self::SESSION_TTL.to_owned()
        };
        let json_str = json::encode(&session).unwrap();

        let resp = http::handle()
            .put(url, &json_str)
            .content_type("application/json")
            .exec().unwrap();
        if resp.get_code() != 200 {
            panic!("Consul: Error creating a session!");
        }
        let result = from_utf8(resp.get_body()).unwrap();
        let json_data = match json::Json::from_str(result) {
            Ok(value) => value,
            Err(err) => panic!("consul: Could not convert to json: {:?}", result)
        };
        super::get_string(&json_data, &["ID"])
    }

    pub fn renew(&self, session_id: &String) {
        for i in 0..10 {
            let url = format!("{}/renew/{}", self.endpoint, session_id);
            let resp = http::handle()
                .put(url, "")
                .content_type("application/json")
                .exec().unwrap();
            if resp.get_code() != 200 {
                println!("Could not renew ession: {}, returned HTTP code: {:?}. Sleeping for 1 sec", session_id, resp.get_code());
                if i == 10 {
                    panic!("Cound not renew session: {} after 10 tries. Panicing.", session_id);
                }
                thread::sleep_ms(1000);
            }
            else {
                break;
            }
        }

    }

    pub fn end(&self, session_id: &String) {
        let url = format!("{}/destroy/{}", self.endpoint, session_id);
        let resp = http::handle()
            .put(url, "")
            .content_type("application/json")
            .exec().unwrap();
        if resp.get_code() != 200 {
            panic!("Cound not destroy session: {}", session_id);
        }

    }

}
<commit_msg>Bugfixes<commit_after>#![allow(non_snake_case)]

use std::str::from_utf8;
use std::collections::HashMap;
use std::thread;

use rustc_serialize::json;
use curl::http;

pub const SESSION_TTL: &'static str = "15s";

#[derive(RustcDecodable, RustcEncodable, Debug)]
pub struct SessionCreate {
    Name: String,
    TTL: String
}

#[derive(RustcDecodable, RustcEncodable, Debug)]
pub struct SessionID {
    ID: String
}

pub struct Session {
    endpoint: String
}

impl Session {
    pub fn new(address: &str) ->  Session {
        Session {
            endpoint: format!("http://{}/v1/session", address)
        }
    }

    pub fn create(&self, name: String) -> String{
        let url = format!("{}/create", self.endpoint);
        let session = SessionCreate {
            Name: name,
            TTL: self::SESSION_TTL.to_owned()
        };
        let json_str = json::encode(&session).unwrap();

        let resp = http::handle()
            .put(url, &json_str)
            .content_type("application/json")
            .exec().unwrap();
        if resp.get_code() != 200 {
            panic!("Consul: Error creating a session!");
        }
        let result = from_utf8(resp.get_body()).unwrap();
        let json_data = match json::Json::from_str(result) {
            Ok(value) => value,
            Err(err) => panic!("consul: Could not convert to json: {:?}", result)
        };
        super::get_string(&json_data, &["ID"])
    }

    pub fn renew(&self, session_id: &String) -> bool {
        for i in 0..10 {
            let url = format!("{}/renew/{}", self.endpoint, session_id);
            let resp = http::handle()
                .put(url, "")
                .content_type("application/json")
                .exec().unwrap();
            if resp.get_code() != 200 {
                println!("Could not renew ession: {}, returned HTTP code: {:?}. Sleeping for 1 sec", session_id, resp.get_code());
                thread::sleep_ms(1000);
            }
            else {
                return true;
            }
        }
        false
    }

    pub fn end(&self, session_id: &String) {
        let url = format!("{}/destroy/{}", self.endpoint, session_id);
        let resp = http::handle()
            .put(url, "")
            .content_type("application/json")
            .exec().unwrap();
        if resp.get_code() != 200 {
            panic!("Cound not destroy session: {}", session_id);
        }

    }

}
<|endoftext|>


<commit_before>use std::error::Error;
use std::fmt::Error as FmtError;
use std::fmt::{Display, Formatter};

generate_error_types!(TagError, TagErrorKind,
    TagTypeError     => "Entry Header Tag Type wrong",
    HeaderReadError  => "Error while reading entry header",
    HeaderWriteError => "Error while writing entry header",
    NotATag          => "String is not a tag"
);

<commit_msg>libimagentrytag: Replace error module imports with macro helper<commit_after>generate_error_imports!();

generate_error_types!(TagError, TagErrorKind,
    TagTypeError     => "Entry Header Tag Type wrong",
    HeaderReadError  => "Error while reading entry header",
    HeaderWriteError => "Error while writing entry header",
    NotATag          => "String is not a tag"
);

<|endoftext|>


<commit_before>#![crate_type = "rlib"]

//! Macro to create a "view box", a box containing immutable data
//! plus a "view" struct that can have interior references into
//! the data.  The view box can be moved around as an atomic unit.
//! I haven't completely convinced myself this is memory safe yet.
//! In particular, I need to make sure dangling pointers can't be
//! observed if the view struct implements Drop
#![feature(macro_rules, globs)]

#[macro_export]
macro_rules! viewbox(
    ($(#[$attr:meta])* struct $name:ident<$d:ty, $v:ident>;) => (
        $(#[$attr])*
        pub struct $name {
            data: Box<$d>,
            view: $v<'static>
        }

        #[allow(dead_code)]
        impl $name {
            pub fn new(data: $d, f: <'a>|&'a mut $d| -> $v<'a>) -> $name {
                let mut d = box data;
                let v = unsafe { ::std::mem::transmute(f(&mut *d)) };

                $name {
                    data: d,
                    view: v
                }
            }

            pub fn new_result<E>(data: $d,
                                 f: <'a>|&'a mut $d|
                                    -> ::std::result::Result<$v<'a>,E>)
                                 -> ::std::result::Result<$name,($d,E)> {
                let mut d = box data;
                match f(&mut *d).map(|v| unsafe { ::std::mem::transmute(v) }) {
                    Ok(v) => {
                        Ok($name {
                            data: d,
                            view: v
                        })
                    },
                    Err(e) => Err((*d,e))
                }
            }

            pub fn unwrap(self)-> $d {
                let $name { data: box data, .. } = self;
                data
            }

            pub fn view<'a>(&'a self) -> &'a $v<'a> {
                &self.view
            }

            pub fn mut_view<'a>(&'a mut self) -> &'a mut $v<'a> {
                unsafe { ::std::mem::transmute(&mut self.view) }
            }
        }
    )
)

#[cfg(test)]
mod test {
    // Test data structure
    #[deriving(PartialEq,Show)]
    struct TestData {
        foo: i32,
        bar: String
    }

    // View structure that has references into the boxed data
    struct TestView<'a> {
        x: &'a i32,
        y: &'a str
    }

    // Create TestBox which combines TestData and TestView
    viewbox! {
        struct TestBox<TestData,TestView>;
    }

    // Mutable view into string
    struct MutView<'a> {
        x: &'a mut String
    }

    // MutBox combines TestData and MutView
    viewbox! {
        struct MutBox<TestData, MutView>;
    }

    #[test]
    fn basic() {
        // Create some data
        let t = TestData { foo: 42, bar: "Hello".to_string() };
        // Move it into box, creating a view with interior references
        let v = TestBox::new(t, |d| TestView { x: &d.foo, y: d.bar.as_slice() });

        // We can access the boxed data via the view
        assert_eq!(v.view().x, &42i32);
        assert_eq!(v.view().y, "Hello");
        // We can unwrap the view to get the data back
        let t = v.unwrap();
        assert_eq!(t.foo, 42i32);
        assert_eq!(t.bar, "Hello".to_string());
    }

    #[test]
    fn mutation() {
        let t = TestData { foo: 42, bar: "Hello".to_string() };
        let mut v = MutBox::new(t, |d| MutView { x: &mut d.bar });

        *v.mut_view().x = "Goodbye".to_string();
        let t = v.unwrap();
        assert_eq!(t.bar, "Goodbye".to_string());
    }

    #[test]
    fn error() {
        let t = TestData { foo: 42, bar: "Hello".to_string() };
        let v = MutBox::new_result(t, |_| Err("Nope")).err().unwrap();
        assert_eq!(v, (TestData { foo: 42, bar: "Hello".to_string() }, "Nope"))
    }
}
<commit_msg>Need a cast here too<commit_after>#![crate_type = "rlib"]

//! Macro to create a "view box", a box containing immutable data
//! plus a "view" struct that can have interior references into
//! the data.  The view box can be moved around as an atomic unit.
//! I haven't completely convinced myself this is memory safe yet.
//! In particular, I need to make sure dangling pointers can't be
//! observed if the view struct implements Drop
#![feature(macro_rules, globs)]

#[macro_export]
macro_rules! viewbox(
    ($(#[$attr:meta])* struct $name:ident<$d:ty, $v:ident>;) => (
        $(#[$attr])*
        pub struct $name {
            data: Box<$d>,
            view: $v<'static>
        }

        #[allow(dead_code)]
        impl $name {
            pub fn new(data: $d, f: <'a>|&'a mut $d| -> $v<'a>) -> $name {
                let mut d = box data;
                let v = unsafe { ::std::mem::transmute(f(&mut *d)) };

                $name {
                    data: d,
                    view: v
                }
            }

            pub fn new_result<E>(data: $d,
                                 f: <'a>|&'a mut $d|
                                    -> ::std::result::Result<$v<'a>,E>)
                                 -> ::std::result::Result<$name,($d,E)> {
                let mut d = box data;
                match f(&mut *d).map(|v| unsafe { ::std::mem::transmute(v) }) {
                    Ok(v) => {
                        Ok($name {
                            data: d,
                            view: v
                        })
                    },
                    Err(e) => Err((*d,e))
                }
            }

            pub fn unwrap(self)-> $d {
                let $name { data: box data, .. } = self;
                data
            }

            pub fn view<'a>(&'a self) -> &'a $v<'a> {
                unsafe { ::std::mem::transmute(&self.view) }
            }

            pub fn mut_view<'a>(&'a mut self) -> &'a mut $v<'a> {
                unsafe { ::std::mem::transmute(&mut self.view) }
            }
        }
    )
)

#[cfg(test)]
mod test {
    // Test data structure
    #[deriving(PartialEq,Show)]
    struct TestData {
        foo: i32,
        bar: String
    }

    // View structure that has references into the boxed data
    struct TestView<'a> {
        x: &'a i32,
        y: &'a str
    }

    // Create TestBox which combines TestData and TestView
    viewbox! {
        struct TestBox<TestData,TestView>;
    }

    // Mutable view into string
    struct MutView<'a> {
        x: &'a mut String
    }

    // MutBox combines TestData and MutView
    viewbox! {
        struct MutBox<TestData, MutView>;
    }

    #[test]
    fn basic() {
        // Create some data
        let t = TestData { foo: 42, bar: "Hello".to_string() };
        // Move it into box, creating a view with interior references
        let v = TestBox::new(t, |d| TestView { x: &d.foo, y: d.bar.as_slice() });

        // We can access the boxed data via the view
        assert_eq!(v.view().x, &42i32);
        assert_eq!(v.view().y, "Hello");
        // We can unwrap the view to get the data back
        let t = v.unwrap();
        assert_eq!(t.foo, 42i32);
        assert_eq!(t.bar, "Hello".to_string());
    }

    #[test]
    fn mutation() {
        let t = TestData { foo: 42, bar: "Hello".to_string() };
        let mut v = MutBox::new(t, |d| MutView { x: &mut d.bar });

        *v.mut_view().x = "Goodbye".to_string();
        let t = v.unwrap();
        assert_eq!(t.bar, "Goodbye".to_string());
    }

    #[test]
    fn error() {
        let t = TestData { foo: 42, bar: "Hello".to_string() };
        let v = MutBox::new_result(t, |_| Err("Nope")).err().unwrap();
        assert_eq!(v, (TestData { foo: 42, bar: "Hello".to_string() }, "Nope"))
    }
}
<|endoftext|>


<commit_before>use crate::syntax::namespace::Namespace;
use quote::quote;
use syn::parse::{Error, Parse, ParseStream, Result};
use syn::{
    braced, token, Abi, Attribute, ForeignItem, Ident, Item as RustItem, ItemEnum, ItemImpl,
    ItemStruct, ItemUse, LitStr, Token, Visibility,
};

pub struct Module {
    pub namespace: Namespace,
    pub attrs: Vec<Attribute>,
    pub vis: Visibility,
    pub unsafety: Option<Token![unsafe]>,
    pub mod_token: Token![mod],
    pub ident: Ident,
    pub brace_token: token::Brace,
    pub content: Vec<Item>,
}

pub enum Item {
    Struct(ItemStruct),
    Enum(ItemEnum),
    ForeignMod(ItemForeignMod),
    Use(ItemUse),
    Impl(ItemImpl),
    Other(RustItem),
}

pub struct ItemForeignMod {
    pub attrs: Vec<Attribute>,
    pub unsafety: Option<Token![unsafe]>,
    pub abi: Abi,
    pub brace_token: token::Brace,
    pub items: Vec<ForeignItem>,
}

impl Parse for Module {
    fn parse(input: ParseStream) -> Result<Self> {
        let namespace = Namespace::ROOT;
        let mut attrs = input.call(Attribute::parse_outer)?;
        let vis: Visibility = input.parse()?;
        let unsafety: Option<Token![unsafe]> = input.parse()?;
        let mod_token: Token![mod] = input.parse()?;
        let ident: Ident = input.parse()?;

        let semi: Option<Token![;]> = input.parse()?;
        if let Some(semi) = semi {
            let span = quote!(#vis #mod_token #semi);
            return Err(Error::new_spanned(
                span,
                "#[cxx::bridge] module must have inline contents",
            ));
        }

        let content;
        let brace_token = braced!(content in input);
        attrs.extend(content.call(Attribute::parse_inner)?);

        let mut items = Vec::new();
        while !content.is_empty() {
            items.push(content.parse()?);
        }

        Ok(Module {
            namespace,
            attrs,
            vis,
            unsafety,
            mod_token,
            ident,
            brace_token,
            content: items,
        })
    }
}

impl Parse for Item {
    fn parse(input: ParseStream) -> Result<Self> {
        let attrs = input.call(Attribute::parse_outer)?;

        let ahead = input.fork();
        let unsafety = if ahead.parse::<Option<Token![unsafe]>>()?.is_some()
            && ahead.parse::<Option<Token![extern]>>()?.is_some()
            && ahead.parse::<Option<LitStr>>().is_ok()
            && ahead.peek(token::Brace)
        {
            Some(input.parse()?)
        } else {
            None
        };

        let item = input.parse()?;
        match item {
            RustItem::Struct(item) => Ok(Item::Struct(ItemStruct { attrs, ..item })),
            RustItem::Enum(item) => Ok(Item::Enum(ItemEnum { attrs, ..item })),
            RustItem::ForeignMod(item) => Ok(Item::ForeignMod(ItemForeignMod {
                attrs,
                unsafety,
                abi: item.abi,
                brace_token: item.brace_token,
                items: item.items,
            })),
            RustItem::Impl(item) => Ok(Item::Impl(ItemImpl { attrs, ..item })),
            RustItem::Use(item) => Ok(Item::Use(ItemUse { attrs, ..item })),
            other => Ok(Item::Other(other)),
        }
    }
}
<commit_msg>Preserve item inner attrs<commit_after>use crate::syntax::namespace::Namespace;
use quote::quote;
use syn::parse::{Error, Parse, ParseStream, Result};
use syn::{
    braced, token, Abi, Attribute, ForeignItem, Ident, Item as RustItem, ItemEnum, ItemImpl,
    ItemStruct, ItemUse, LitStr, Token, Visibility,
};

pub struct Module {
    pub namespace: Namespace,
    pub attrs: Vec<Attribute>,
    pub vis: Visibility,
    pub unsafety: Option<Token![unsafe]>,
    pub mod_token: Token![mod],
    pub ident: Ident,
    pub brace_token: token::Brace,
    pub content: Vec<Item>,
}

pub enum Item {
    Struct(ItemStruct),
    Enum(ItemEnum),
    ForeignMod(ItemForeignMod),
    Use(ItemUse),
    Impl(ItemImpl),
    Other(RustItem),
}

pub struct ItemForeignMod {
    pub attrs: Vec<Attribute>,
    pub unsafety: Option<Token![unsafe]>,
    pub abi: Abi,
    pub brace_token: token::Brace,
    pub items: Vec<ForeignItem>,
}

impl Parse for Module {
    fn parse(input: ParseStream) -> Result<Self> {
        let namespace = Namespace::ROOT;
        let mut attrs = input.call(Attribute::parse_outer)?;
        let vis: Visibility = input.parse()?;
        let unsafety: Option<Token![unsafe]> = input.parse()?;
        let mod_token: Token![mod] = input.parse()?;
        let ident: Ident = input.parse()?;

        let semi: Option<Token![;]> = input.parse()?;
        if let Some(semi) = semi {
            let span = quote!(#vis #mod_token #semi);
            return Err(Error::new_spanned(
                span,
                "#[cxx::bridge] module must have inline contents",
            ));
        }

        let content;
        let brace_token = braced!(content in input);
        attrs.extend(content.call(Attribute::parse_inner)?);

        let mut items = Vec::new();
        while !content.is_empty() {
            items.push(content.parse()?);
        }

        Ok(Module {
            namespace,
            attrs,
            vis,
            unsafety,
            mod_token,
            ident,
            brace_token,
            content: items,
        })
    }
}

impl Parse for Item {
    fn parse(input: ParseStream) -> Result<Self> {
        let attrs = input.call(Attribute::parse_outer)?;

        let ahead = input.fork();
        let unsafety = if ahead.parse::<Option<Token![unsafe]>>()?.is_some()
            && ahead.parse::<Option<Token![extern]>>()?.is_some()
            && ahead.parse::<Option<LitStr>>().is_ok()
            && ahead.peek(token::Brace)
        {
            Some(input.parse()?)
        } else {
            None
        };

        let item = input.parse()?;
        match item {
            RustItem::Struct(mut item) => {
                item.attrs.splice(..0, attrs);
                Ok(Item::Struct(item))
            }
            RustItem::Enum(mut item) => {
                item.attrs.splice(..0, attrs);
                Ok(Item::Enum(item))
            }
            RustItem::ForeignMod(mut item) => {
                item.attrs.splice(..0, attrs);
                Ok(Item::ForeignMod(ItemForeignMod {
                    attrs: item.attrs,
                    unsafety,
                    abi: item.abi,
                    brace_token: item.brace_token,
                    items: item.items,
                }))
            }
            RustItem::Impl(mut item) => {
                item.attrs.splice(..0, attrs);
                Ok(Item::Impl(item))
            }
            RustItem::Use(mut item) => {
                item.attrs.splice(..0, attrs);
                Ok(Item::Use(item))
            }
            other => Ok(Item::Other(other)),
        }
    }
}
<|endoftext|>


<commit_before>use core::clone::Clone;

use kernel::mm::{Flags, PageDirectory};
use kernel::mm::physical;

use util::rt::breakpoint;

use platform::cpu::mmu;

pub struct Process {
    pub eip: u32,
    pub esp: u32,
    pub paging: physical::Phys<PageDirectory>
}

impl Process {
    pub fn new() -> Process {
        Process {
            eip: 0,
            esp: 0,
            // paging: unsafe { physical::zero_alloc_frames(1) as *mut PageDirectory }
            paging: unsafe { mmu::clone_directory() }
        }
    }

    pub fn mmap(&self, page_ptr: *mut u8, size: uint, flags: Flags) {
        unsafe {
            (*self.paging.as_ptr()).map(page_ptr, size, flags);
        }
    }

    #[cfg(target_arch = "x86")]
    pub fn enter(&self) {
        unsafe {
            breakpoint();
            // TODO need to store physical address
            mmu::switch_directory(self.paging);
            asm!("xor %eax, %eax
                  xor %edx, %edx
                  jmp *$0" :: "m"(self.eip), "{esp}"(self.esp) :: "volatile")
        }
    }

    #[cfg(target_arch = "arm")]
    pub fn enter(&self) {}
}
<commit_msg>Fix memory access (0xc0000014) error<commit_after>use core::clone::Clone;

use kernel::mm::{Flags, PageDirectory};
use kernel::mm::physical;

use util::rt::breakpoint;

use platform::cpu::mmu;

pub struct Process {
    pub eip: u32,
    pub esp: u32,
    pub paging: physical::Phys<PageDirectory>
}

impl Process {
    pub fn new() -> Process {
        Process {
            eip: 0,
            esp: 0,
            // paging: unsafe { physical::zero_alloc_frames(1) as *mut PageDirectory }
            paging: unsafe { mmu::clone_directory() }
        }
    }

    pub fn mmap(&self, page_ptr: *mut u8, size: uint, flags: Flags) {
        unsafe {
            (*self.paging.as_ptr()).map(page_ptr, size, flags);
        }
    }

    #[cfg(target_arch = "x86")]
    pub fn enter(&self) {
        unsafe {
            breakpoint();
            // TODO need to store physical address
            mmu::switch_directory(self.paging);
            asm!("xor edx, edx
                  jmp DWORD PTR $0" :: "{eax}"(self.eip), "{esp}"(self.esp) :: "volatile", "intel");
        }
    }

    #[cfg(target_arch = "arm")]
    pub fn enter(&self) {}
}
<|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/. */

//! Per-node data used in style calculation.

use context::SharedStyleContext;
use dom::TElement;
use invalidation::element::restyle_hints::RestyleHint;
use properties::ComputedValues;
use properties::longhands::display::computed_value as display;
use rule_tree::StrongRuleNode;
use selector_parser::{EAGER_PSEUDO_COUNT, PseudoElement, RestyleDamage};
use servo_arc::Arc;
use shared_lock::StylesheetGuards;
use std::ops::{Deref, DerefMut};

bitflags! {
    flags RestyleFlags: u8 {
        /// Whether the styles changed for this restyle.
        const WAS_RESTYLED = 1 << 0,
        /// Whether we reframed/reconstructed any ancestor or self.
        const ANCESTOR_WAS_RECONSTRUCTED = 1 << 1,
    }
}

/// Transient data used by the restyle algorithm. This structure is instantiated
/// either before or during restyle traversal, and is cleared at the end of node
/// processing.
#[derive(Debug)]
pub struct RestyleData {
    /// The restyle hint, which indicates whether selectors need to be rematched
    /// for this element, its children, and its descendants.
    pub hint: RestyleHint,

    /// A few flags to have in mind.
    flags: RestyleFlags,

    /// The restyle damage, indicating what kind of layout changes are required
    /// afte restyling.
    pub damage: RestyleDamage,
}

impl Default for RestyleData {
    fn default() -> Self {
        Self::new()
    }
}

impl RestyleData {
    fn new() -> Self {
        Self {
            hint: RestyleHint::empty(),
            flags: RestyleFlags::empty(),
            damage: RestyleDamage::empty(),
        }
    }

    /// Clear all the restyle state associated with this element.
    fn clear(&mut self) {
        *self = Self::new();
    }

    /// Clear restyle flags and damage.
    fn clear_flags_and_damage(&mut self) {
        self.damage = RestyleDamage::empty();
        self.flags = RestyleFlags::empty();
    }

    /// Returns whether this element or any ancestor is going to be
    /// reconstructed.
    pub fn reconstructed_self_or_ancestor(&self) -> bool {
        self.reconstructed_ancestor() || self.reconstructed_self()
    }

    /// Returns whether this element is going to be reconstructed.
    pub fn reconstructed_self(&self) -> bool {
        self.damage.contains(RestyleDamage::reconstruct())
    }

    /// Returns whether any ancestor of this element is going to be
    /// reconstructed.
    fn reconstructed_ancestor(&self) -> bool {
        self.flags.contains(ANCESTOR_WAS_RECONSTRUCTED)
    }

    /// Sets the flag that tells us whether we've reconstructed an ancestor.
    pub fn set_reconstructed_ancestor(&mut self) {
        // If it weren't for animation-only traversals, we could assert
        // `!self.reconstructed_ancestor()` here.
        self.flags.insert(ANCESTOR_WAS_RECONSTRUCTED);
    }

    /// Mark this element as restyled, which is useful to know whether we need
    /// to do a post-traversal.
    pub fn set_restyled(&mut self) {
        self.flags.insert(WAS_RESTYLED);
    }

    /// Mark this element as restyled, which is useful to know whether we need
    /// to do a post-traversal.
    pub fn is_restyle(&self) -> bool {
        self.flags.contains(WAS_RESTYLED)
    }

    /// Returns whether this element has been part of a restyle.
    pub fn contains_restyle_data(&self) -> bool {
        self.is_restyle() || !self.hint.is_empty() || !self.damage.is_empty()
    }
}

/// A lazily-allocated list of styles for eagerly-cascaded pseudo-elements.
///
/// We use an Arc so that sharing these styles via the style sharing cache does
/// not require duplicate allocations. We leverage the copy-on-write semantics of
/// Arc::make_mut(), which is free (i.e. does not require atomic RMU operations)
/// in servo_arc.
#[derive(Clone, Debug, Default)]
pub struct EagerPseudoStyles(Option<Arc<EagerPseudoArray>>);

#[derive(Debug, Default)]
struct EagerPseudoArray(EagerPseudoArrayInner);
type EagerPseudoArrayInner = [Option<Arc<ComputedValues>>; EAGER_PSEUDO_COUNT];

impl Deref for EagerPseudoArray {
    type Target = EagerPseudoArrayInner;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl DerefMut for EagerPseudoArray {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

// Manually implement `Clone` here because the derived impl of `Clone` for
// array types assumes the value inside is `Copy`.
impl Clone for EagerPseudoArray {
    fn clone(&self) -> Self {
        let mut clone = Self::default();
        for i in 0..EAGER_PSEUDO_COUNT {
            clone[i] = self.0[i].clone();
        }
        clone
    }
}

impl EagerPseudoStyles {
    /// Returns whether there are any pseudo styles.
    pub fn is_empty(&self) -> bool {
        self.0.is_none()
    }

    /// Grabs a reference to the list of styles, if they exist.
    pub fn as_array(&self) -> Option<&EagerPseudoArrayInner> {
        match self.0 {
            None => None,
            Some(ref x) => Some(&x.0),
        }
    }

    /// Returns a reference to the style for a given eager pseudo, if it exists.
    pub fn get(&self, pseudo: &PseudoElement) -> Option<&Arc<ComputedValues>> {
        debug_assert!(pseudo.is_eager());
        self.0.as_ref().and_then(|p| p[pseudo.eager_index()].as_ref())
    }

    /// Sets the style for the eager pseudo.
    pub fn set(&mut self, pseudo: &PseudoElement, value: Arc<ComputedValues>) {
        if self.0.is_none() {
            self.0 = Some(Arc::new(Default::default()));
        }
        let arr = Arc::make_mut(self.0.as_mut().unwrap());
        arr[pseudo.eager_index()] = Some(value);
    }
}

/// The styles associated with a node, including the styles for any
/// pseudo-elements.
#[derive(Clone, Debug, Default)]
pub struct ElementStyles {
    /// The element's style.
    pub primary: Option<Arc<ComputedValues>>,
    /// A list of the styles for the element's eagerly-cascaded pseudo-elements.
    pub pseudos: EagerPseudoStyles,
}

impl ElementStyles {
    /// Returns the primary style.
    pub fn get_primary(&self) -> Option<&Arc<ComputedValues>> {
        self.primary.as_ref()
    }

    /// Returns the primary style.  Panic if no style available.
    pub fn primary(&self) -> &Arc<ComputedValues> {
        self.primary.as_ref().unwrap()
    }

    /// Whether this element `display` value is `none`.
    pub fn is_display_none(&self) -> bool {
        self.primary().get_box().clone_display() == display::T::none
    }
}

/// Style system data associated with an Element.
///
/// In Gecko, this hangs directly off the Element. Servo, this is embedded
/// inside of layout data, which itself hangs directly off the Element. In
/// both cases, it is wrapped inside an AtomicRefCell to ensure thread safety.
#[derive(Debug, Default)]
pub struct ElementData {
    /// The styles for the element and its pseudo-elements.
    pub styles: ElementStyles,

    /// Restyle state.
    pub restyle: RestyleData,
}

/// The kind of restyle that a single element should do.
#[derive(Debug)]
pub enum RestyleKind {
    /// We need to run selector matching plus re-cascade, that is, a full
    /// restyle.
    MatchAndCascade,
    /// We need to recascade with some replacement rule, such as the style
    /// attribute, or animation rules.
    CascadeWithReplacements(RestyleHint),
    /// We only need to recascade, for example, because only inherited
    /// properties in the parent changed.
    CascadeOnly,
}

impl ElementData {
    /// Invalidates style for this element, its descendants, and later siblings,
    /// based on the snapshot of the element that we took when attributes or
    /// state changed.
    pub fn invalidate_style_if_needed<'a, E: TElement>(
        &mut self,
        element: E,
        shared_context: &SharedStyleContext)
    {
        // In animation-only restyle we shouldn't touch snapshot at all.
        if shared_context.traversal_flags.for_animation_only() {
            return;
        }

        use invalidation::element::invalidator::TreeStyleInvalidator;

        debug!("invalidate_style_if_needed: {:?}, flags: {:?}, has_snapshot: {}, \
                handled_snapshot: {}, pseudo: {:?}",
                element,
                shared_context.traversal_flags,
                element.has_snapshot(),
                element.handled_snapshot(),
                element.implemented_pseudo_element());

        if element.has_snapshot() && !element.handled_snapshot() {
            let invalidator = TreeStyleInvalidator::new(
                element,
                Some(self),
                shared_context,
            );
            invalidator.invalidate();
            unsafe { element.set_handled_snapshot() }
            debug_assert!(element.handled_snapshot());
        }
    }

    /// Returns true if this element has styles.
    pub fn has_styles(&self) -> bool {
        self.styles.primary.is_some()
    }

    /// Returns whether we have any outstanding style invalidation.
    pub fn has_invalidations(&self) -> bool {
        self.restyle.hint.has_self_invalidations()
    }

    /// Returns the kind of restyling that we're going to need to do on this
    /// element, based of the stored restyle hint.
    pub fn restyle_kind(&self,
                        shared_context: &SharedStyleContext)
                        -> RestyleKind {
        if shared_context.traversal_flags.for_animation_only() {
            return self.restyle_kind_for_animation(shared_context);
        }

        debug_assert!(!self.has_styles() || self.has_invalidations(),
                      "Should've stopped earlier");
        if !self.has_styles() {
            return RestyleKind::MatchAndCascade;
        }

        let hint = self.restyle.hint;
        if hint.match_self() {
            return RestyleKind::MatchAndCascade;
        }

        if hint.has_replacements() {
            debug_assert!(!hint.has_animation_hint(),
                          "Animation only restyle hint should have already processed");
            return RestyleKind::CascadeWithReplacements(hint & RestyleHint::replacements());
        }

        debug_assert!(hint.has_recascade_self(),
                      "We definitely need to do something!");
        return RestyleKind::CascadeOnly;
    }

    /// Returns the kind of restyling for animation-only restyle.
    pub fn restyle_kind_for_animation(&self,
                                      shared_context: &SharedStyleContext)
                                      -> RestyleKind {
        debug_assert!(shared_context.traversal_flags.for_animation_only());
        debug_assert!(self.has_styles(),
                      "Unstyled element shouldn't be traversed during \
                       animation-only traversal");

        // return either CascadeWithReplacements or CascadeOnly in case of
        // animation-only restyle. I.e. animation-only restyle never does
        // selector matching.
        let hint = self.restyle.hint;
        if hint.has_animation_hint() {
            return RestyleKind::CascadeWithReplacements(hint & RestyleHint::for_animations());
        }
        return RestyleKind::CascadeOnly;

    }

    /// Return true if important rules are different.
    /// We use this to make sure the cascade of off-main thread animations is correct.
    /// Note: Ignore custom properties for now because we only support opacity and transform
    ///       properties for animations running on compositor. Actually, we only care about opacity
    ///       and transform for now, but it's fine to compare all properties and let the user
    ///       the check which properties do they want.
    ///       If it costs too much, get_properties_overriding_animations() should return a set
    ///       containing only opacity and transform properties.
    pub fn important_rules_are_different(&self,
                                         rules: &StrongRuleNode,
                                         guards: &StylesheetGuards) -> bool {
        debug_assert!(self.has_styles());
        let (important_rules, _custom) =
            self.styles.primary().rules().get_properties_overriding_animations(&guards);
        let (other_important_rules, _custom) = rules.get_properties_overriding_animations(&guards);
        important_rules != other_important_rules
    }

    /// Drops any restyle state from the element.
    pub fn clear_restyle_state(&mut self) {
        self.restyle.clear();
    }

    /// Drops restyle flags and damage from the element.
    pub fn clear_restyle_flags_and_damage(&mut self) {
        self.restyle.clear_flags_and_damage();
    }
}
<commit_msg>Bring back concise logging for ElementData.<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/. */

//! Per-node data used in style calculation.

use context::SharedStyleContext;
use dom::TElement;
use invalidation::element::restyle_hints::RestyleHint;
use properties::ComputedValues;
use properties::longhands::display::computed_value as display;
use rule_tree::StrongRuleNode;
use selector_parser::{EAGER_PSEUDO_COUNT, PseudoElement, RestyleDamage};
use servo_arc::Arc;
use shared_lock::StylesheetGuards;
use std::fmt;
use std::ops::{Deref, DerefMut};

bitflags! {
    flags RestyleFlags: u8 {
        /// Whether the styles changed for this restyle.
        const WAS_RESTYLED = 1 << 0,
        /// Whether we reframed/reconstructed any ancestor or self.
        const ANCESTOR_WAS_RECONSTRUCTED = 1 << 1,
    }
}

/// Transient data used by the restyle algorithm. This structure is instantiated
/// either before or during restyle traversal, and is cleared at the end of node
/// processing.
#[derive(Debug)]
pub struct RestyleData {
    /// The restyle hint, which indicates whether selectors need to be rematched
    /// for this element, its children, and its descendants.
    pub hint: RestyleHint,

    /// A few flags to have in mind.
    flags: RestyleFlags,

    /// The restyle damage, indicating what kind of layout changes are required
    /// afte restyling.
    pub damage: RestyleDamage,
}

impl Default for RestyleData {
    fn default() -> Self {
        Self::new()
    }
}

impl RestyleData {
    fn new() -> Self {
        Self {
            hint: RestyleHint::empty(),
            flags: RestyleFlags::empty(),
            damage: RestyleDamage::empty(),
        }
    }

    /// Clear all the restyle state associated with this element.
    fn clear(&mut self) {
        *self = Self::new();
    }

    /// Clear restyle flags and damage.
    fn clear_flags_and_damage(&mut self) {
        self.damage = RestyleDamage::empty();
        self.flags = RestyleFlags::empty();
    }

    /// Returns whether this element or any ancestor is going to be
    /// reconstructed.
    pub fn reconstructed_self_or_ancestor(&self) -> bool {
        self.reconstructed_ancestor() || self.reconstructed_self()
    }

    /// Returns whether this element is going to be reconstructed.
    pub fn reconstructed_self(&self) -> bool {
        self.damage.contains(RestyleDamage::reconstruct())
    }

    /// Returns whether any ancestor of this element is going to be
    /// reconstructed.
    fn reconstructed_ancestor(&self) -> bool {
        self.flags.contains(ANCESTOR_WAS_RECONSTRUCTED)
    }

    /// Sets the flag that tells us whether we've reconstructed an ancestor.
    pub fn set_reconstructed_ancestor(&mut self) {
        // If it weren't for animation-only traversals, we could assert
        // `!self.reconstructed_ancestor()` here.
        self.flags.insert(ANCESTOR_WAS_RECONSTRUCTED);
    }

    /// Mark this element as restyled, which is useful to know whether we need
    /// to do a post-traversal.
    pub fn set_restyled(&mut self) {
        self.flags.insert(WAS_RESTYLED);
    }

    /// Mark this element as restyled, which is useful to know whether we need
    /// to do a post-traversal.
    pub fn is_restyle(&self) -> bool {
        self.flags.contains(WAS_RESTYLED)
    }

    /// Returns whether this element has been part of a restyle.
    pub fn contains_restyle_data(&self) -> bool {
        self.is_restyle() || !self.hint.is_empty() || !self.damage.is_empty()
    }
}

/// A lazily-allocated list of styles for eagerly-cascaded pseudo-elements.
///
/// We use an Arc so that sharing these styles via the style sharing cache does
/// not require duplicate allocations. We leverage the copy-on-write semantics of
/// Arc::make_mut(), which is free (i.e. does not require atomic RMU operations)
/// in servo_arc.
#[derive(Clone, Debug, Default)]
pub struct EagerPseudoStyles(Option<Arc<EagerPseudoArray>>);

#[derive(Default)]
struct EagerPseudoArray(EagerPseudoArrayInner);
type EagerPseudoArrayInner = [Option<Arc<ComputedValues>>; EAGER_PSEUDO_COUNT];

impl Deref for EagerPseudoArray {
    type Target = EagerPseudoArrayInner;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl DerefMut for EagerPseudoArray {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

// Manually implement `Clone` here because the derived impl of `Clone` for
// array types assumes the value inside is `Copy`.
impl Clone for EagerPseudoArray {
    fn clone(&self) -> Self {
        let mut clone = Self::default();
        for i in 0..EAGER_PSEUDO_COUNT {
            clone[i] = self.0[i].clone();
        }
        clone
    }
}

// Override Debug to print which pseudos we have, and substitute the rule node
// for the much-more-verbose ComputedValues stringification.
impl fmt::Debug for EagerPseudoArray {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "EagerPseudoArray {{ ")?;
        for i in 0..EAGER_PSEUDO_COUNT {
            if let Some(ref values) = self[i] {
                write!(f, "{:?}: {:?}, ", PseudoElement::from_eager_index(i), &values.rules)?;
            }
        }
        write!(f, "}}")
    }
}

impl EagerPseudoStyles {
    /// Returns whether there are any pseudo styles.
    pub fn is_empty(&self) -> bool {
        self.0.is_none()
    }

    /// Grabs a reference to the list of styles, if they exist.
    pub fn as_array(&self) -> Option<&EagerPseudoArrayInner> {
        match self.0 {
            None => None,
            Some(ref x) => Some(&x.0),
        }
    }

    /// Returns a reference to the style for a given eager pseudo, if it exists.
    pub fn get(&self, pseudo: &PseudoElement) -> Option<&Arc<ComputedValues>> {
        debug_assert!(pseudo.is_eager());
        self.0.as_ref().and_then(|p| p[pseudo.eager_index()].as_ref())
    }

    /// Sets the style for the eager pseudo.
    pub fn set(&mut self, pseudo: &PseudoElement, value: Arc<ComputedValues>) {
        if self.0.is_none() {
            self.0 = Some(Arc::new(Default::default()));
        }
        let arr = Arc::make_mut(self.0.as_mut().unwrap());
        arr[pseudo.eager_index()] = Some(value);
    }
}

/// The styles associated with a node, including the styles for any
/// pseudo-elements.
#[derive(Clone, Default)]
pub struct ElementStyles {
    /// The element's style.
    pub primary: Option<Arc<ComputedValues>>,
    /// A list of the styles for the element's eagerly-cascaded pseudo-elements.
    pub pseudos: EagerPseudoStyles,
}

impl ElementStyles {
    /// Returns the primary style.
    pub fn get_primary(&self) -> Option<&Arc<ComputedValues>> {
        self.primary.as_ref()
    }

    /// Returns the primary style.  Panic if no style available.
    pub fn primary(&self) -> &Arc<ComputedValues> {
        self.primary.as_ref().unwrap()
    }

    /// Whether this element `display` value is `none`.
    pub fn is_display_none(&self) -> bool {
        self.primary().get_box().clone_display() == display::T::none
    }
}

// We manually implement Debug for ElementStyles so that we can avoid the
// verbose stringification of every property in the ComputedValues. We
// substitute the rule node instead.
impl fmt::Debug for ElementStyles {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "ElementStyles {{ primary: {:?}, pseudos: {:?} }}",
               self.primary.as_ref().map(|x| &x.rules), self.pseudos)
    }
}

/// Style system data associated with an Element.
///
/// In Gecko, this hangs directly off the Element. Servo, this is embedded
/// inside of layout data, which itself hangs directly off the Element. In
/// both cases, it is wrapped inside an AtomicRefCell to ensure thread safety.
#[derive(Debug, Default)]
pub struct ElementData {
    /// The styles for the element and its pseudo-elements.
    pub styles: ElementStyles,

    /// Restyle state.
    pub restyle: RestyleData,
}

/// The kind of restyle that a single element should do.
#[derive(Debug)]
pub enum RestyleKind {
    /// We need to run selector matching plus re-cascade, that is, a full
    /// restyle.
    MatchAndCascade,
    /// We need to recascade with some replacement rule, such as the style
    /// attribute, or animation rules.
    CascadeWithReplacements(RestyleHint),
    /// We only need to recascade, for example, because only inherited
    /// properties in the parent changed.
    CascadeOnly,
}

impl ElementData {
    /// Invalidates style for this element, its descendants, and later siblings,
    /// based on the snapshot of the element that we took when attributes or
    /// state changed.
    pub fn invalidate_style_if_needed<'a, E: TElement>(
        &mut self,
        element: E,
        shared_context: &SharedStyleContext)
    {
        // In animation-only restyle we shouldn't touch snapshot at all.
        if shared_context.traversal_flags.for_animation_only() {
            return;
        }

        use invalidation::element::invalidator::TreeStyleInvalidator;

        debug!("invalidate_style_if_needed: {:?}, flags: {:?}, has_snapshot: {}, \
                handled_snapshot: {}, pseudo: {:?}",
                element,
                shared_context.traversal_flags,
                element.has_snapshot(),
                element.handled_snapshot(),
                element.implemented_pseudo_element());

        if element.has_snapshot() && !element.handled_snapshot() {
            let invalidator = TreeStyleInvalidator::new(
                element,
                Some(self),
                shared_context,
            );
            invalidator.invalidate();
            unsafe { element.set_handled_snapshot() }
            debug_assert!(element.handled_snapshot());
        }
    }

    /// Returns true if this element has styles.
    pub fn has_styles(&self) -> bool {
        self.styles.primary.is_some()
    }

    /// Returns whether we have any outstanding style invalidation.
    pub fn has_invalidations(&self) -> bool {
        self.restyle.hint.has_self_invalidations()
    }

    /// Returns the kind of restyling that we're going to need to do on this
    /// element, based of the stored restyle hint.
    pub fn restyle_kind(&self,
                        shared_context: &SharedStyleContext)
                        -> RestyleKind {
        if shared_context.traversal_flags.for_animation_only() {
            return self.restyle_kind_for_animation(shared_context);
        }

        debug_assert!(!self.has_styles() || self.has_invalidations(),
                      "Should've stopped earlier");
        if !self.has_styles() {
            return RestyleKind::MatchAndCascade;
        }

        let hint = self.restyle.hint;
        if hint.match_self() {
            return RestyleKind::MatchAndCascade;
        }

        if hint.has_replacements() {
            debug_assert!(!hint.has_animation_hint(),
                          "Animation only restyle hint should have already processed");
            return RestyleKind::CascadeWithReplacements(hint & RestyleHint::replacements());
        }

        debug_assert!(hint.has_recascade_self(),
                      "We definitely need to do something!");
        return RestyleKind::CascadeOnly;
    }

    /// Returns the kind of restyling for animation-only restyle.
    pub fn restyle_kind_for_animation(&self,
                                      shared_context: &SharedStyleContext)
                                      -> RestyleKind {
        debug_assert!(shared_context.traversal_flags.for_animation_only());
        debug_assert!(self.has_styles(),
                      "Unstyled element shouldn't be traversed during \
                       animation-only traversal");

        // return either CascadeWithReplacements or CascadeOnly in case of
        // animation-only restyle. I.e. animation-only restyle never does
        // selector matching.
        let hint = self.restyle.hint;
        if hint.has_animation_hint() {
            return RestyleKind::CascadeWithReplacements(hint & RestyleHint::for_animations());
        }
        return RestyleKind::CascadeOnly;

    }

    /// Return true if important rules are different.
    /// We use this to make sure the cascade of off-main thread animations is correct.
    /// Note: Ignore custom properties for now because we only support opacity and transform
    ///       properties for animations running on compositor. Actually, we only care about opacity
    ///       and transform for now, but it's fine to compare all properties and let the user
    ///       the check which properties do they want.
    ///       If it costs too much, get_properties_overriding_animations() should return a set
    ///       containing only opacity and transform properties.
    pub fn important_rules_are_different(&self,
                                         rules: &StrongRuleNode,
                                         guards: &StylesheetGuards) -> bool {
        debug_assert!(self.has_styles());
        let (important_rules, _custom) =
            self.styles.primary().rules().get_properties_overriding_animations(&guards);
        let (other_important_rules, _custom) = rules.get_properties_overriding_animations(&guards);
        important_rules != other_important_rules
    }

    /// Drops any restyle state from the element.
    pub fn clear_restyle_state(&mut self) {
        self.restyle.clear();
    }

    /// Drops restyle flags and damage from the element.
    pub fn clear_restyle_flags_and_damage(&mut self) {
        self.restyle.clear_flags_and_damage();
    }
}
<|endoftext|>


<commit_before>use ahash::{AHasher, CallHasher};
use criterion::*;
use fxhash::FxHasher;
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};

#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes"))]
fn aeshash<H: Hash>(b: &H) -> u64 {
    let hasher = AHasher::new_with_keys(1234, 5678);
    b.get_hash(hasher)
}
#[cfg(not(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes")))]
fn aeshash<H: Hash>(_b: &H) -> u64 {
    panic!("aes must be enabled")
}

#[cfg(not(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes")))]
fn fallbackhash<H: Hash>(b: &H) -> u64 {
    let hasher = AHasher::new_with_keys(1234, 5678);
    b.get_hash(hasher)
}
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes"))]
fn fallbackhash<H: Hash>(_b: &H) -> u64 {
    panic!("aes must be disabled")
}

fn fnvhash<H: Hash>(b: &H) -> u64 {
    let mut hasher = fnv::FnvHasher::default();
    b.hash(&mut hasher);
    hasher.finish()
}

fn siphash<H: Hash>(b: &H) -> u64 {
    let mut hasher = DefaultHasher::default();
    b.hash(&mut hasher);
    hasher.finish()
}

fn fxhash<H: Hash>(b: &H) -> u64 {
    let mut hasher = FxHasher::default();
    b.hash(&mut hasher);
    hasher.finish()
}

fn seahash<H: Hash>(b: &H) -> u64 {
    let mut hasher = seahash::SeaHasher::default();
    b.hash(&mut hasher);
    hasher.finish()
}

const STRING_LENGTHS: [u32; 11] = [1, 3, 4, 7, 8, 15, 16, 24, 68, 132, 1024];

fn gen_strings() -> Vec<String> {
    STRING_LENGTHS
        .iter()
        .map(|len| {
            let mut string = String::default();
            for pos in 1..=*len {
                let c = (48 + (pos % 10) as u8) as char;
                string.push(c);
            }
            string
        })
        .collect()
}

const U8_VALUES: [u8; 1] = [8];
const U16_VALUES: [u16; 1] = [16];
const U32_VALUES: [u32; 1] = [32];
const U64_VALUES: [u64; 1] = [64];
const U128_VALUES: [u128; 1] = [128];

fn bench_ahash(c: &mut Criterion) {
    c.bench(
        "aeshash",
        ParameterizedBenchmark::new("u8", |b, &s| b.iter(|| black_box(aeshash(s))), &U8_VALUES),
    );
    c.bench(
        "aeshash",
        ParameterizedBenchmark::new("u16", |b, &s| b.iter(|| black_box(aeshash(s))), &U16_VALUES),
    );
    c.bench(
        "aeshash",
        ParameterizedBenchmark::new("u32", |b, &s| b.iter(|| black_box(aeshash(s))), &U32_VALUES),
    );
    c.bench(
        "aeshash",
        ParameterizedBenchmark::new("u64", |b, &s| b.iter(|| black_box(aeshash(s))), &U64_VALUES),
    );
    c.bench(
        "aeshash",
        ParameterizedBenchmark::new("u128", |b, &s| b.iter(|| black_box(aeshash(s))), &U128_VALUES),
    );
    c.bench(
        "aeshash",
        ParameterizedBenchmark::new("string", |b, s| b.iter(|| black_box(aeshash(s))), gen_strings()),
    );
}

fn bench_fallback(c: &mut Criterion) {
    c.bench(
        "fallback",
        ParameterizedBenchmark::new("u8", |b, &s| b.iter(|| black_box(fallbackhash(s))), &U8_VALUES),
    );
    c.bench(
        "fallback",
        ParameterizedBenchmark::new("u16", |b, &s| b.iter(|| black_box(fallbackhash(s))), &U16_VALUES),
    );
    c.bench(
        "fallback",
        ParameterizedBenchmark::new("u32", |b, &s| b.iter(|| black_box(fallbackhash(s))), &U32_VALUES),
    );
    c.bench(
        "fallback",
        ParameterizedBenchmark::new("u64", |b, &s| b.iter(|| black_box(fallbackhash(s))), &U64_VALUES),
    );
    c.bench(
        "fallback",
        ParameterizedBenchmark::new("u128", |b, &s| b.iter(|| black_box(fallbackhash(s))), &U128_VALUES),
    );
    c.bench(
        "fallback",
        ParameterizedBenchmark::new("string", |b, s| b.iter(|| black_box(fallbackhash(s))), gen_strings()),
    );
}

fn bench_fx(c: &mut Criterion) {
    c.bench(
        "fx",
        ParameterizedBenchmark::new("u8", |b, &s| b.iter(|| black_box(fxhash(s))), &U8_VALUES),
    );
    c.bench(
        "fx",
        ParameterizedBenchmark::new("u16", |b, &s| b.iter(|| black_box(fxhash(s))), &U16_VALUES),
    );
    c.bench(
        "fx",
        ParameterizedBenchmark::new("u32", |b, &s| b.iter(|| black_box(fxhash(s))), &U32_VALUES),
    );
    c.bench(
        "fx",
        ParameterizedBenchmark::new("u64", |b, &s| b.iter(|| black_box(fxhash(s))), &U64_VALUES),
    );
    c.bench(
        "fx",
        ParameterizedBenchmark::new("u128", |b, &s| b.iter(|| black_box(fxhash(s))), &U128_VALUES),
    );
    c.bench(
        "fx",
        ParameterizedBenchmark::new("string", |b, s| b.iter(|| black_box(fxhash(s))), gen_strings()),
    );
}

fn bench_fnv(c: &mut Criterion) {
    c.bench(
        "fnv",
        ParameterizedBenchmark::new("u8", |b, &s| b.iter(|| black_box(fnvhash(s))), &U8_VALUES),
    );
    c.bench(
        "fnv",
        ParameterizedBenchmark::new("u16", |b, &s| b.iter(|| black_box(fnvhash(s))), &U16_VALUES),
    );
    c.bench(
        "fnv",
        ParameterizedBenchmark::new("u32", |b, &s| b.iter(|| black_box(fnvhash(s))), &U32_VALUES),
    );
    c.bench(
        "fnv",
        ParameterizedBenchmark::new("u64", |b, &s| b.iter(|| black_box(fnvhash(s))), &U64_VALUES),
    );
    c.bench(
        "fnv",
        ParameterizedBenchmark::new("u128", |b, &s| b.iter(|| black_box(fnvhash(s))), &U128_VALUES),
    );
    c.bench(
        "fnv",
        ParameterizedBenchmark::new("string", |b, s| b.iter(|| black_box(fnvhash(s))), gen_strings()),
    );
}

fn bench_sea(c: &mut Criterion) {
    c.bench(
        "sea",
        ParameterizedBenchmark::new("string", |b, s| b.iter(|| black_box(seahash(s))), gen_strings()),
    );
}

fn bench_sip(c: &mut Criterion) {
    c.bench(
        "sip",
        ParameterizedBenchmark::new("u8", |b, &s| b.iter(|| black_box(siphash(s))), &U8_VALUES),
    );
    c.bench(
        "sip",
        ParameterizedBenchmark::new("u16", |b, &s| b.iter(|| black_box(siphash(s))), &U16_VALUES),
    );
    c.bench(
        "sip",
        ParameterizedBenchmark::new("u32", |b, &s| b.iter(|| black_box(siphash(s))), &U32_VALUES),
    );
    c.bench(
        "sip",
        ParameterizedBenchmark::new("u64", |b, &s| b.iter(|| black_box(siphash(s))), &U64_VALUES),
    );
    c.bench(
        "sip",
        ParameterizedBenchmark::new("u128", |b, &s| b.iter(|| black_box(siphash(s))), &U128_VALUES),
    );
    c.bench(
        "sip",
        ParameterizedBenchmark::new("string", |b, s| b.iter(|| black_box(siphash(s))), gen_strings()),
    );
}

criterion_main!(benches);
criterion_group!(
    benches,
    bench_ahash,
    bench_fallback,
    bench_fx,
    bench_fnv,
    bench_sea,
    bench_sip
);
<commit_msg>Add a bench for 33 bytes<commit_after>use ahash::{AHasher, CallHasher};
use criterion::*;
use fxhash::FxHasher;
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};

#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes"))]
fn aeshash<H: Hash>(b: &H) -> u64 {
    let hasher = AHasher::new_with_keys(1234, 5678);
    b.get_hash(hasher)
}
#[cfg(not(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes")))]
fn aeshash<H: Hash>(_b: &H) -> u64 {
    panic!("aes must be enabled")
}

#[cfg(not(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes")))]
fn fallbackhash<H: Hash>(b: &H) -> u64 {
    let hasher = AHasher::new_with_keys(1234, 5678);
    b.get_hash(hasher)
}
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes"))]
fn fallbackhash<H: Hash>(_b: &H) -> u64 {
    panic!("aes must be disabled")
}

fn fnvhash<H: Hash>(b: &H) -> u64 {
    let mut hasher = fnv::FnvHasher::default();
    b.hash(&mut hasher);
    hasher.finish()
}

fn siphash<H: Hash>(b: &H) -> u64 {
    let mut hasher = DefaultHasher::default();
    b.hash(&mut hasher);
    hasher.finish()
}

fn fxhash<H: Hash>(b: &H) -> u64 {
    let mut hasher = FxHasher::default();
    b.hash(&mut hasher);
    hasher.finish()
}

fn seahash<H: Hash>(b: &H) -> u64 {
    let mut hasher = seahash::SeaHasher::default();
    b.hash(&mut hasher);
    hasher.finish()
}

const STRING_LENGTHS: [u32; 12] = [1, 3, 4, 7, 8, 15, 16, 24, 33, 68, 132, 1024];

fn gen_strings() -> Vec<String> {
    STRING_LENGTHS
        .iter()
        .map(|len| {
            let mut string = String::default();
            for pos in 1..=*len {
                let c = (48 + (pos % 10) as u8) as char;
                string.push(c);
            }
            string
        })
        .collect()
}

const U8_VALUES: [u8; 1] = [123];
const U16_VALUES: [u16; 1] = [1234];
const U32_VALUES: [u32; 1] = [12345678];
const U64_VALUES: [u64; 1] = [1234567890123456];
const U128_VALUES: [u128; 1] = [12345678901234567890123456789012];

fn bench_ahash(c: &mut Criterion) {
    c.bench(
        "aeshash",
        ParameterizedBenchmark::new("u8", |b, &s| b.iter(|| black_box(aeshash(s))), &U8_VALUES),
    );
    c.bench(
        "aeshash",
        ParameterizedBenchmark::new("u16", |b, &s| b.iter(|| black_box(aeshash(s))), &U16_VALUES),
    );
    c.bench(
        "aeshash",
        ParameterizedBenchmark::new("u32", |b, &s| b.iter(|| black_box(aeshash(s))), &U32_VALUES),
    );
    c.bench(
        "aeshash",
        ParameterizedBenchmark::new("u64", |b, &s| b.iter(|| black_box(aeshash(s))), &U64_VALUES),
    );
    c.bench(
        "aeshash",
        ParameterizedBenchmark::new("u128", |b, &s| b.iter(|| black_box(aeshash(s))), &U128_VALUES),
    );
    c.bench(
        "aeshash",
        ParameterizedBenchmark::new("string", |b, s| b.iter(|| black_box(aeshash(s))), gen_strings()),
    );
}

fn bench_fallback(c: &mut Criterion) {
    c.bench(
        "fallback",
        ParameterizedBenchmark::new("u8", |b, &s| b.iter(|| black_box(fallbackhash(s))), &U8_VALUES),
    );
    c.bench(
        "fallback",
        ParameterizedBenchmark::new("u16", |b, &s| b.iter(|| black_box(fallbackhash(s))), &U16_VALUES),
    );
    c.bench(
        "fallback",
        ParameterizedBenchmark::new("u32", |b, &s| b.iter(|| black_box(fallbackhash(s))), &U32_VALUES),
    );
    c.bench(
        "fallback",
        ParameterizedBenchmark::new("u64", |b, &s| b.iter(|| black_box(fallbackhash(s))), &U64_VALUES),
    );
    c.bench(
        "fallback",
        ParameterizedBenchmark::new("u128", |b, &s| b.iter(|| black_box(fallbackhash(s))), &U128_VALUES),
    );
    c.bench(
        "fallback",
        ParameterizedBenchmark::new("string", |b, s| b.iter(|| black_box(fallbackhash(s))), gen_strings()),
    );
}

fn bench_fx(c: &mut Criterion) {
    c.bench(
        "fx",
        ParameterizedBenchmark::new("u8", |b, &s| b.iter(|| black_box(fxhash(s))), &U8_VALUES),
    );
    c.bench(
        "fx",
        ParameterizedBenchmark::new("u16", |b, &s| b.iter(|| black_box(fxhash(s))), &U16_VALUES),
    );
    c.bench(
        "fx",
        ParameterizedBenchmark::new("u32", |b, &s| b.iter(|| black_box(fxhash(s))), &U32_VALUES),
    );
    c.bench(
        "fx",
        ParameterizedBenchmark::new("u64", |b, &s| b.iter(|| black_box(fxhash(s))), &U64_VALUES),
    );
    c.bench(
        "fx",
        ParameterizedBenchmark::new("u128", |b, &s| b.iter(|| black_box(fxhash(s))), &U128_VALUES),
    );
    c.bench(
        "fx",
        ParameterizedBenchmark::new("string", |b, s| b.iter(|| black_box(fxhash(s))), gen_strings()),
    );
}

fn bench_fnv(c: &mut Criterion) {
    c.bench(
        "fnv",
        ParameterizedBenchmark::new("u8", |b, &s| b.iter(|| black_box(fnvhash(s))), &U8_VALUES),
    );
    c.bench(
        "fnv",
        ParameterizedBenchmark::new("u16", |b, &s| b.iter(|| black_box(fnvhash(s))), &U16_VALUES),
    );
    c.bench(
        "fnv",
        ParameterizedBenchmark::new("u32", |b, &s| b.iter(|| black_box(fnvhash(s))), &U32_VALUES),
    );
    c.bench(
        "fnv",
        ParameterizedBenchmark::new("u64", |b, &s| b.iter(|| black_box(fnvhash(s))), &U64_VALUES),
    );
    c.bench(
        "fnv",
        ParameterizedBenchmark::new("u128", |b, &s| b.iter(|| black_box(fnvhash(s))), &U128_VALUES),
    );
    c.bench(
        "fnv",
        ParameterizedBenchmark::new("string", |b, s| b.iter(|| black_box(fnvhash(s))), gen_strings()),
    );
}

fn bench_sea(c: &mut Criterion) {
    c.bench(
        "sea",
        ParameterizedBenchmark::new("string", |b, s| b.iter(|| black_box(seahash(s))), gen_strings()),
    );
}

fn bench_sip(c: &mut Criterion) {
    c.bench(
        "sip",
        ParameterizedBenchmark::new("u8", |b, &s| b.iter(|| black_box(siphash(s))), &U8_VALUES),
    );
    c.bench(
        "sip",
        ParameterizedBenchmark::new("u16", |b, &s| b.iter(|| black_box(siphash(s))), &U16_VALUES),
    );
    c.bench(
        "sip",
        ParameterizedBenchmark::new("u32", |b, &s| b.iter(|| black_box(siphash(s))), &U32_VALUES),
    );
    c.bench(
        "sip",
        ParameterizedBenchmark::new("u64", |b, &s| b.iter(|| black_box(siphash(s))), &U64_VALUES),
    );
    c.bench(
        "sip",
        ParameterizedBenchmark::new("u128", |b, &s| b.iter(|| black_box(siphash(s))), &U128_VALUES),
    );
    c.bench(
        "sip",
        ParameterizedBenchmark::new("string", |b, s| b.iter(|| black_box(siphash(s))), gen_strings()),
    );
}

criterion_main!(benches);
criterion_group!(
    benches,
    bench_ahash,
    bench_fallback,
    bench_fx,
    bench_fnv,
    bench_sea,
    bench_sip
);
<|endoftext|>


<commit_before>//! Library to parse movie scripts and output them in a structured format

extern crate regex;
extern crate xml;

pub mod parse;
pub mod serialize;

/// A `Script` consists of a list of `Scene`s.
pub type Script = Vec<Scene>;

/// A `Scene` consists of a list of `Location`s.
///
/// Some scripts do not distinguish between scenes and locations and will
/// thus only have one `Scene` with several `Location`s or several `Scene`s
/// with each containing only one `Location`.
pub type Scene = Vec<Location>;

/// Represents a location in which part of a `Scene` takes place.
#[derive(Default, Clone, Debug)]
pub struct Location {
    /// The kind of the location (like internal)
    pub kind: LocationType,
    /// The name of the location
    pub name: String,
    /// The `Dialog` and `Direction` which take place in this location
    pub parts: Vec<ScenePart>,
}

/// Represents the types of locations often used in scripts.
#[derive(Clone, Debug)]
pub enum LocationType {
    Undefined,
    Internal,
    External,
    InternalExternal,
}

/// A `Scene` consists of `Direction`s and `Dialog`s.
///
/// Each `ScenePart` carries the page number from which it was extracted
/// originally.
#[derive(Debug, Clone)]
pub enum ScenePart {
    Direction {
        direction: String,
        page: u32,
    },
    Dialog {
        speaker: String,
        dialog: Vec<DialogPart>,
        page: u32,
    }
}

/// The different parts of a `Dialog`.
///
/// A `DialogPart` can have inline `Direction`s in between normal `Dialog`.
#[derive(Debug, Clone)]
pub enum DialogPart {
    /// What a speaker says
    Dialog(String),
    /// How or to whom the speaker says it
    Direction(String),
}

/// The default for `LocationType` is `Undefined`.
impl Default for LocationType {
    fn default() -> LocationType { LocationType::Undefined }
}

/// Converts the `LocationType` into a string representation.
///
/// `Undefined` becomes the empty string.
impl Into<&'static str> for LocationType {
    fn into(self) -> &'static str {
        match self {
            LocationType::Undefined => "",
            LocationType::Internal => "internal",
            LocationType::External => "external",
            LocationType::InternalExternal => "internal,external",
        }
    }
}

/// Parses the given string into a range.
///
/// This is used when parsing the "--pages" cli argument.
///
/// # Examples
///
/// ```
/// assert_eq!(extract_range("42"), (42, 42));
/// assert_eq!(extract_range("3-15"), (3, 15));
/// assert_eq!(extract_range("foo"), (0, u32::max_value()));
/// ```
pub fn extract_range(range_string: &str) -> Option<(u32, u32)> {
    let range_regex = regex::Regex::new(r"^(?P<lower>\d+)-(?P<upper>\d+)$").unwrap();

    if let Ok(page) = range_string.parse() {
        return Some((page, page));
    } else if let Some(captures) = range_regex.captures(range_string) {
        if let (Ok(lower), Ok(upper)) = (captures.name("lower").unwrap().parse(),
                                         captures.name("upper").unwrap().parse()) {
            return Some((lower, upper));
        }
    }

    None
}

/// Filter the script using a range of pages.
///
/// The range is inclusive and empty scenes and locations are removed.
pub fn filter_script(script: Script, page_range: (u32, u32)) -> Script {
    let (lower, upper) = page_range;

    script.into_iter().filter_map(|scene| {
        let filtered_scene: Scene = scene.into_iter().filter_map(|mut location| {
            let filtered_scene_parts: Vec<ScenePart> = location.parts.into_iter().filter_map(|scene_part| {
                let page = match scene_part {
                    ScenePart::Direction { page, .. } => page,
                    ScenePart::Dialog { page, .. } => page
                };

                // filter using the given range
                if lower <= page && page <= upper {
                    Some(scene_part)
                } else {
                    None
                }
            }).collect();

            // filter out locations with no scene parts
            if filtered_scene_parts.len() > 0 {
                location.parts = filtered_scene_parts;
                Some(location)
            } else {
                None
            }
        }).collect();

        // filter out scenes with no locations
        if filtered_scene.len() > 0 {
            Some(filtered_scene)
        } else {
            None
        }
    }).collect()
}
<commit_msg>Fix rustdoc test for the extract_range function<commit_after>//! Library to parse movie scripts and output them in a structured format

extern crate regex;
extern crate xml;

pub mod parse;
pub mod serialize;

/// A `Script` consists of a list of `Scene`s.
pub type Script = Vec<Scene>;

/// A `Scene` consists of a list of `Location`s.
///
/// Some scripts do not distinguish between scenes and locations and will
/// thus only have one `Scene` with several `Location`s or several `Scene`s
/// with each containing only one `Location`.
pub type Scene = Vec<Location>;

/// Represents a location in which part of a `Scene` takes place.
#[derive(Default, Clone, Debug)]
pub struct Location {
    /// The kind of the location (like internal)
    pub kind: LocationType,
    /// The name of the location
    pub name: String,
    /// The `Dialog` and `Direction` which take place in this location
    pub parts: Vec<ScenePart>,
}

/// Represents the types of locations often used in scripts.
#[derive(Clone, Debug)]
pub enum LocationType {
    Undefined,
    Internal,
    External,
    InternalExternal,
}

/// A `Scene` consists of `Direction`s and `Dialog`s.
///
/// Each `ScenePart` carries the page number from which it was extracted
/// originally.
#[derive(Debug, Clone)]
pub enum ScenePart {
    Direction {
        direction: String,
        page: u32,
    },
    Dialog {
        speaker: String,
        dialog: Vec<DialogPart>,
        page: u32,
    }
}

/// The different parts of a `Dialog`.
///
/// A `DialogPart` can have inline `Direction`s in between normal `Dialog`.
#[derive(Debug, Clone)]
pub enum DialogPart {
    /// What a speaker says
    Dialog(String),
    /// How or to whom the speaker says it
    Direction(String),
}

/// The default for `LocationType` is `Undefined`.
impl Default for LocationType {
    fn default() -> LocationType { LocationType::Undefined }
}

/// Converts the `LocationType` into a string representation.
///
/// `Undefined` becomes the empty string.
impl Into<&'static str> for LocationType {
    fn into(self) -> &'static str {
        match self {
            LocationType::Undefined => "",
            LocationType::Internal => "internal",
            LocationType::External => "external",
            LocationType::InternalExternal => "internal,external",
        }
    }
}

/// Parses the given string into a range.
///
/// This is used when parsing the "--pages" cli argument.
///
/// # Examples
///
/// ```
/// # use script_extractor::extract_range;
/// assert_eq!(extract_range("42"), Some((42, 42)));
/// assert_eq!(extract_range("3-15"), Some((3, 15)));
/// assert_eq!(extract_range("foo"), None);
/// ```
pub fn extract_range(range_string: &str) -> Option<(u32, u32)> {
    let range_regex = regex::Regex::new(r"^(?P<lower>\d+)-(?P<upper>\d+)$").unwrap();

    if let Ok(page) = range_string.parse() {
        return Some((page, page));
    } else if let Some(captures) = range_regex.captures(range_string) {
        if let (Ok(lower), Ok(upper)) = (captures.name("lower").unwrap().parse(),
                                         captures.name("upper").unwrap().parse()) {
            return Some((lower, upper));
        }
    }

    None
}

/// Filter the script using a range of pages.
///
/// The range is inclusive and empty scenes and locations are removed.
pub fn filter_script(script: Script, page_range: (u32, u32)) -> Script {
    let (lower, upper) = page_range;

    script.into_iter().filter_map(|scene| {
        let filtered_scene: Scene = scene.into_iter().filter_map(|mut location| {
            let filtered_scene_parts: Vec<ScenePart> = location.parts.into_iter().filter_map(|scene_part| {
                let page = match scene_part {
                    ScenePart::Direction { page, .. } => page,
                    ScenePart::Dialog { page, .. } => page
                };

                // filter using the given range
                if lower <= page && page <= upper {
                    Some(scene_part)
                } else {
                    None
                }
            }).collect();

            // filter out locations with no scene parts
            if filtered_scene_parts.len() > 0 {
                location.parts = filtered_scene_parts;
                Some(location)
            } else {
                None
            }
        }).collect();

        // filter out scenes with no locations
        if filtered_scene.len() > 0 {
            Some(filtered_scene)
        } else {
            None
        }
    }).collect()
}
<|endoftext|>


<commit_before>//! Module defining all sensor related structures.

use std::collections::BTreeMap;
use rustc_serialize::json::{Json, ToJson};
use utils::Optional;

//--- Templates ---//

/// A trait for all possible sensor templates.
/// the `SensorTemplate`s are capable of registering themselves in a `Sensors` struct
pub trait SensorTemplate : Send+Sync {
    fn to_sensor(&self, value_str: &str, sensors: &mut Sensors);
}

#[derive(Debug, Clone)]
pub struct PeopleNowPresentSensorTemplate {
    pub location: Optional<String>,
    pub name: Optional<String>,
    pub names: Optional<Vec<String>>,
    pub description: Optional<String>,
}

impl SensorTemplate for PeopleNowPresentSensorTemplate {
    fn to_sensor(&self, value_str: &str, sensors: &mut Sensors) {
        if value_str.parse::<i64>().map(|value|{
            let sensor = PeopleNowPresentSensor {
                location: self.location.clone(),
                name: self.name.clone(),
                names: self.names.clone(),
                description: self.description.clone(),
                value: value,
            };

            match sensors.people_now_present {
                Optional::Value(ref mut vec_sensors) => vec_sensors.push(sensor),
                Optional::Absent => sensors.people_now_present = Optional::Value(vec![sensor]),
            }
        }).is_err() {
            warn!("Could not parse '{}': omiting the sensor", value_str);
        }
    }
}

#[derive(Debug, Clone)]
pub struct TemperatureSensorTemplate {
    pub unit: String,
    pub location: String,
    pub name: Optional<String>,
    pub description: Optional<String>,
}

impl SensorTemplate for TemperatureSensorTemplate {
    fn to_sensor(&self, value_str: &str, sensors: &mut Sensors) {
        if value_str.parse::<f64>().map(|value|{
            let sensor = TemperatureSensor {
                unit: self.unit.clone(),
                location: self.location.clone(),
                name: self.name.clone(),
                description: self.description.clone(),
                value: value,
            };
            match sensors.temperature {
                Optional::Value(ref mut vec_sensors) => vec_sensors.push(sensor),
                Optional::Absent => sensors.temperature = Optional::Value(vec![sensor]),
            }
        }).is_err() {
            warn!("Could not parse '{}': omiting the sensor", value_str);
        }
    }
}

//--- Structures ---//

#[derive(Debug, Clone)]
pub struct PeopleNowPresentSensor {
    pub location: Optional<String>,
    pub name: Optional<String>,
    pub names: Optional<Vec<String>>,
    pub description: Optional<String>,
    pub value: i64,
}

#[derive(Debug, Clone)]
pub struct TemperatureSensor {
    pub unit: String,
    pub location: String,
    pub name: Optional<String>,
    pub description: Optional<String>,
    pub value: f64,
}

#[derive(Debug, Clone)]
pub struct Sensors {
    pub people_now_present: Optional<Vec<PeopleNowPresentSensor>>,
    pub temperature: Optional<Vec<TemperatureSensor>>,
}

//--- Serialization ---//

impl ToJson for Sensors {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        self.people_now_present.as_ref().map_or((), |v| { d.insert("people_now_present".to_string(), v.to_json()); });
        self.temperature.as_ref().map_or((), |v| { d.insert("temperature".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for PeopleNowPresentSensor {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("value".to_string(), self.value.to_json());
        self.location.as_ref().map_or((), |v| { d.insert("location".to_string(), v.to_json()); });
        self.name.as_ref().map_or((), |v| { d.insert("name".to_string(), v.to_json()); });
        self.names.as_ref().map_or((), |v| { d.insert("names".to_string(), v.to_json()); });
        self.description.as_ref().map_or((), |v| { d.insert("description".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for TemperatureSensor {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("value".to_string(), self.value.to_json());
        d.insert("unit".to_string(), self.unit.to_json());
        d.insert("location".to_string(), self.location.to_json());
        self.name.as_ref().map_or((), |v| { d.insert("name".to_string(), v.to_json()); });
        self.description.as_ref().map_or((), |v| { d.insert("description".to_string(), v.to_json()); });
        Json::Object(d)
    }
}
<commit_msg>spaceapi: Improve readability in SensorTemplate<commit_after>//! Module defining all sensor related structures.

use std::collections::BTreeMap;
use rustc_serialize::json::{Json, ToJson};
use utils::Optional;

//--- Templates ---//

/// A trait for all possible sensor templates.
/// the `SensorTemplate`s are capable of registering themselves in a `Sensors` struct
pub trait SensorTemplate : Send+Sync {
    fn to_sensor(&self, value_str: &str, sensors: &mut Sensors);
}

#[derive(Debug, Clone)]
pub struct PeopleNowPresentSensorTemplate {
    pub location: Optional<String>,
    pub name: Optional<String>,
    pub names: Optional<Vec<String>>,
    pub description: Optional<String>,
}

impl SensorTemplate for PeopleNowPresentSensorTemplate {
    fn to_sensor(&self, value_str: &str, sensors: &mut Sensors) {
        if value_str.parse::<i64>().map(|value|{
            let sensor = PeopleNowPresentSensor {
                location: self.location.clone(),
                name: self.name.clone(),
                names: self.names.clone(),
                description: self.description.clone(),
                value: value,
            };

            match sensors.people_now_present {
                Optional::Value(ref mut vec_sensors) => {
                    vec_sensors.push(sensor)
                }
                Optional::Absent => {
                    sensors.people_now_present = Optional::Value(vec![sensor])
                }
            }
        }).is_err() {
            warn!("Could not parse '{}': omiting the sensor", value_str);
        }
    }
}

#[derive(Debug, Clone)]
pub struct TemperatureSensorTemplate {
    pub unit: String,
    pub location: String,
    pub name: Optional<String>,
    pub description: Optional<String>,
}

impl SensorTemplate for TemperatureSensorTemplate {
    fn to_sensor(&self, value_str: &str, sensors: &mut Sensors) {
        if value_str.parse::<f64>().map(|value|{
            let sensor = TemperatureSensor {
                unit: self.unit.clone(),
                location: self.location.clone(),
                name: self.name.clone(),
                description: self.description.clone(),
                value: value,
            };
            match sensors.temperature {
                Optional::Value(ref mut vec_sensors) => {
                    vec_sensors.push(sensor)
                }
                Optional::Absent => {
                    sensors.temperature = Optional::Value(vec![sensor])
                }
            }
        }).is_err() {
            warn!("Could not parse '{}': omiting the sensor", value_str);
        }
    }
}

//--- Structures ---//

#[derive(Debug, Clone)]
pub struct PeopleNowPresentSensor {
    pub location: Optional<String>,
    pub name: Optional<String>,
    pub names: Optional<Vec<String>>,
    pub description: Optional<String>,
    pub value: i64,
}

#[derive(Debug, Clone)]
pub struct TemperatureSensor {
    pub unit: String,
    pub location: String,
    pub name: Optional<String>,
    pub description: Optional<String>,
    pub value: f64,
}

#[derive(Debug, Clone)]
pub struct Sensors {
    pub people_now_present: Optional<Vec<PeopleNowPresentSensor>>,
    pub temperature: Optional<Vec<TemperatureSensor>>,
}

//--- Serialization ---//

impl ToJson for Sensors {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        self.people_now_present.as_ref().map_or((), |v| { d.insert("people_now_present".to_string(), v.to_json()); });
        self.temperature.as_ref().map_or((), |v| { d.insert("temperature".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for PeopleNowPresentSensor {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("value".to_string(), self.value.to_json());
        self.location.as_ref().map_or((), |v| { d.insert("location".to_string(), v.to_json()); });
        self.name.as_ref().map_or((), |v| { d.insert("name".to_string(), v.to_json()); });
        self.names.as_ref().map_or((), |v| { d.insert("names".to_string(), v.to_json()); });
        self.description.as_ref().map_or((), |v| { d.insert("description".to_string(), v.to_json()); });
        Json::Object(d)
    }
}

impl ToJson for TemperatureSensor {
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("value".to_string(), self.value.to_json());
        d.insert("unit".to_string(), self.unit.to_json());
        d.insert("location".to_string(), self.location.to_json());
        self.name.as_ref().map_or((), |v| { d.insert("name".to_string(), v.to_json()); });
        self.description.as_ref().map_or((), |v| { d.insert("description".to_string(), v.to_json()); });
        Json::Object(d)
    }
}
<|endoftext|>


<commit_before>// This function takes ownership of the box
fn eat_box(boxed_int: Box<i32>) {
    println!("destroying box that contains {}", boxed_int);
}

// This function borrows the box
fn peep_inside_box(borrowed_box: &Box<i32>) {
    println!("This box contains {}", borrowed_box);
}

fn main() {
    // A boxed integer
    let boxed_int = Box::new(5);

    // Borrow the box, ownership is not taken
    peep_inside_box(&boxed_int);

    // The box can be borrowed again
    peep_inside_box(&boxed_int);

    {
        // Take a reference to the data contained inside the box
        let _ref_to_int: &i32 = &*boxed_int;

        // Error! Can't destroy boxed_int, while the inner value has been
        // borrowed
        eat_box(boxed_int);
        // FIXME ^ Comment out this line

        // `_ref_to_int` goes out of scope
    }

    // Give up ownership of the box
    eat_box(boxed_int);
}
<commit_msg>borrow<commit_after>// This function takes ownership of the box
fn eat_box(boxed_int: Box<i32>) {
    println!("destroying box that contains {}", boxed_int);
}

// This function borrows an i32 instead
fn peep_inside_box(borrowed_int: &i32) {
    println!("This int is: {}", borrowed_int);
}

fn main() {
    // A boxed integer
    let boxed_int = Box::new(5);

    // Borrow the contents of the box, ownership is not taken
    peep_inside_box(&boxed_int);

    // The contents can be borrowed again
    peep_inside_box(&boxed_int);

    {
        // Take a reference to the data contained inside the box
        let _ref_to_int: &i32 = &boxed_int;

        // Error! Can't destroy boxed_int, while the inner value has been
        // borrowed
        eat_box(boxed_int);
        // FIXME ^ Comment out this line

        // `_ref_to_int` goes out of scope
    }

    // Give up ownership of the box
    eat_box(boxed_int);
}
<|endoftext|>


<commit_before>/// Utilities to make it easier to maintain Janus session state between plugin callbacks.
use super::PluginSession;
use std::error::Error;
use std::fmt;
use std::ops::Deref;
use std::sync::Arc;

/// An error indicating that someone handed us a null plugin session handle.
#[derive(Debug)]
pub struct NullHandleError;

impl Error for NullHandleError {
    fn description(&self) -> &str {
        "A null session handle was provided."
    }
}

impl fmt::Display for NullHandleError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(self.description())
    }
}

/// A wrapper for a Janus session. Contains a pointer to the Janus PluginSession (which is used to identify
/// this session in the Janus FFI) and any Rust state associated with the session.
#[derive(Debug)]
pub struct SessionWrapper<T> {
    pub handle: *mut PluginSession,
    state: T,
}

impl<T> SessionWrapper<T> {
    /// Allocates a boxed, reference-counted state wrapper associated with a Janus PluginSession
    /// (whose plugin_handle will then point to the contents of the box).
    pub fn associate(handle: *mut PluginSession, state: T) -> Result<Box<Arc<Self>>, NullHandleError> {
        unsafe {
            match handle.as_mut() {
                Some(x) => {
                    let mut result = Box::new(Arc::new(Self { handle, state }));
                    x.plugin_handle = result.as_mut() as *mut Arc<Self> as *mut _;
                    Ok(result)
                }
                None => Err(NullHandleError),
            }
        }
    }

    /// Retrieves and clones the reference-counted state wrapper associated with a Janus PluginSession.
    pub fn from_ptr<'a>(handle: *mut PluginSession) -> Result<Arc<Self>, NullHandleError> {
        unsafe {
            match handle.as_ref() {
                Some(x) => Ok(Arc::clone(
                    (x.plugin_handle as *mut Arc<Self>).as_ref().unwrap(),
                )),
                None => Err(NullHandleError),
            }
        }
    }
}

impl<T> Deref for SessionWrapper<T> {
    type Target = T;
    fn deref(&self) -> &T {
        &self.state
    }
}

// the pointer is opaque to Janus code, so this handle is threadsafe to the extent that the state is

unsafe impl<T: Sync> Sync for SessionWrapper<T> {}
unsafe impl<T: Send> Send for SessionWrapper<T> {}

#[cfg(test)]
mod tests {

    use super::*;
    use std::ptr;

    #[test]
    fn handle_round_trip() {
        struct State(i32);
        let mut handle = PluginSession {
            gateway_handle: ptr::null_mut(),
            plugin_handle: ptr::null_mut(),
            stopped_bitfield: 0,
            __padding: Default::default(),
        };
        let ptr = &mut handle as *mut _;
        let session = SessionWrapper::associate(ptr, State(42)).unwrap();
        assert_eq!(session.as_ref() as *const _ as *mut _, handle.plugin_handle);
        assert_eq!(SessionWrapper::<State>::from_ptr(ptr).unwrap().state.0, 42);
    }
}
<commit_msg>Improve implementation of SessionWrapper<commit_after>/// Utilities to make it easier to maintain Janus session state between plugin callbacks.
use super::PluginSession;
use std::error::Error;
use std::hash::{Hash, Hasher};
use std::fmt;
use std::ops::Deref;
use std::sync::Arc;

/// An error indicating that someone handed us a null plugin session handle.
#[derive(Debug)]
pub struct NullHandleError;

impl Error for NullHandleError {
    fn description(&self) -> &str {
        "A null session handle was provided."
    }
}

impl fmt::Display for NullHandleError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(self.description())
    }
}

/// A wrapper for a Janus session. Contains a pointer to the Janus PluginSession (which is used to identify
/// this session in the Janus FFI) and any Rust state associated with the session.
#[derive(Debug, Clone)]
pub struct SessionWrapper<T> {
    pub handle: *mut PluginSession,
    state: T,
}

impl<T> Hash for SessionWrapper<T> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.handle.hash(state);
    }
}

impl<T> PartialEq for SessionWrapper<T> {
    fn eq(&self, other: &Self) -> bool {
        self.handle == other.handle
    }
}

impl<T> Eq for SessionWrapper<T> {}

impl<T> SessionWrapper<T> {
    /// Allocates a boxed, reference-counted state wrapper associated with a Janus PluginSession
    /// (whose plugin_handle will then point to the contents of the box).
    pub fn associate(handle: *mut PluginSession, state: T) -> Result<Box<Arc<Self>>, NullHandleError> {
        unsafe {
            match handle.as_mut() {
                Some(x) => {
                    let mut result = Box::new(Arc::new(Self { handle, state }));
                    x.plugin_handle = result.as_mut() as *mut Arc<Self> as *mut _;
                    Ok(result)
                }
                None => Err(NullHandleError),
            }
        }
    }

    /// Retrieves and clones the reference-counted state wrapper associated with a Janus PluginSession.
    pub fn from_ptr(handle: *mut PluginSession) -> Result<Arc<Self>, NullHandleError> {
        unsafe {
            match handle.as_ref() {
                Some(x) => Ok(Arc::clone(
                    (x.plugin_handle as *mut Arc<Self>).as_ref().unwrap()
                )),
                None => Err(NullHandleError),
            }
        }
    }

    /// Returns the opaque pointer for this session.
    pub fn as_ptr(&self) -> *mut PluginSession {
        self.handle
    }
}

impl<T> Deref for SessionWrapper<T> {
    type Target = T;
    fn deref(&self) -> &T {
        &self.state
    }
}

// the pointer is opaque to Janus code, so this handle is threadsafe to the extent that the state is

unsafe impl<T: Sync> Sync for SessionWrapper<T> {}
unsafe impl<T: Send> Send for SessionWrapper<T> {}

#[cfg(test)]
mod tests {

    use super::*;
    use std::ptr;

    #[test]
    fn handle_round_trip() {
        struct State(i32);
        let mut handle = PluginSession {
            gateway_handle: ptr::null_mut(),
            plugin_handle: ptr::null_mut(),
            stopped_bitfield: 0,
            __padding: Default::default(),
        };
        let ptr = &mut handle as *mut _;
        let session = SessionWrapper::associate(ptr, State(42)).unwrap();
        assert_eq!(session.as_ref() as *const _ as *mut _, handle.plugin_handle);
        assert_eq!(SessionWrapper::<State>::from_ptr(ptr).unwrap().state.0, 42);
    }
}
<|endoftext|>