<commit_before>use token::Token;
use book::{Book, compile_str};
use number::Number;
use error::Result;
use templates::odt;
use zipper::Zipper;
use parser::Parser;

use crowbook_text_processing::escape;

/// Rendererer for ODT
///
/// Still very experimental.
pub struct OdtRenderer<'a> {
    book: &'a Book,
    current_numbering: i32,
    current_hide: bool,
    current_chapter: i32,
    automatic_styles: String,
}

impl<'a> OdtRenderer<'a> {
    /// Creates a new OdtRenderer
    pub fn new(book: &'a Book) -> OdtRenderer {
        OdtRenderer {
            book: book,
            current_chapter: 1,
            current_numbering: book.options.get_i32("rendering.num_depth").unwrap(),
            current_hide: false,
            automatic_styles: String::from("
<style:style style:name=\"T1\" \
                                            style:family=\"text\">
  <style:text-properties \
                                            fo:font-style=\"italic\" \
                                            style:font-style-asian=\"italic\" \
                                            style:font-style-complex=\"italic\"/>
</style:style>
\
                                            <style:style style:name=\"T2\" \
                                            style:family=\"text\">
  <style:text-properties \
                                            fo:font-weight=\"bold\" \
                                            style:font-weight-asian=\"bold\" \
                                            style:font-weight-complex=\"bold\"/>
</style:style>"),
        }
    }

    /// Renders a full book
    ///
    /// This will try to generate an ODT file according to self.book options.
    ///
    /// # Returns
    /// * `Ok(s)` where `s` contains the output of the `zip` command
    ///   used to create the ODT file.
    /// * An error if there was somel problem during either the rendering to
    ///   ODT format, or the generation of the ODT file itself.
    pub fn render_book(&mut self) -> Result<String> {
        let content = try!(self.render_content());

        let mut zipper =
            try!(Zipper::new(&self.book.options.get_path("crowbook.temp_dir").unwrap()));

        // Write template.odt there
        try!(zipper.write("template.odt", odt::ODT, false));
        // unzip it
        try!(zipper.unzip("template.odt"));
        // Complete it with content.xml
        try!(zipper.write("content.xml", &content.as_bytes(), false));
        // Zip and copy
        if let Ok(ref file) = self.book.options.get_path("output.odt") {
            zipper.generate_odt(self.book.options.get_str("crowbook.zip.command").unwrap(),
                                file)
        } else {
            panic!(lformat!("odt.render_book called while book.output_odt is not set"));
        }
    }

    /// Render content.xml
    fn render_content(&mut self) -> Result<String> {
        let mut content = String::new();

        for &(n, ref v) in &self.book.chapters {
            self.current_hide = false;
            match n {
                Number::Unnumbered => self.current_numbering = 0,
                Number::Default => {
                    self.current_numbering =
                        self.book.options.get_i32("rendering.num_depth").unwrap()
                }
                Number::Specified(n) => {
                    self.current_numbering = self.book.options.get_i32("numbering").unwrap();
                    self.current_chapter = n;
                }
                Number::Hidden => {
                    self.current_numbering = 0;
                    self.current_hide = true;
                }
                _ => panic!(lformat!("Parts are not supported yet")),
            }
            for token in v {
                content.push_str(&self.parse_token(token));
            }
        }

        let template = try!(compile_str(odt::CONTENT,
                                        &self.book.source,
                                        "could not compile template for content.xml"));
        let data = try!(self.book.get_metadata(|s| Ok(s.to_owned())))
            .insert_str("content", content)
            .insert_str("automatic_styles", &self.automatic_styles)
            .build();

        let mut res: Vec<u8> = vec![];
        template.render_data(&mut res, &data);
        match String::from_utf8(res) {
            Err(_) => panic!(lformat!("generated content.xml was not utf-8 valid")),
            Ok(res) => Ok(res),
        }
    }

    /// Transform a vector of `Token`s to Odt format
    fn render_vec(&mut self, tokens: &[Token]) -> String {
        let mut res = String::new();

        for token in tokens {
            res.push_str(&self.parse_token(&token));
        }
        res
    }

    fn parse_token(&mut self, token: &Token) -> String {
        match *token {
            Token::Str(ref text) => escape::html(text.as_ref()).into_owned(),
            Token::Paragraph(ref vec) => {
                format!("<text:p text:style-name=\"Text_20_body\">{}</text:p>\n",
                        self.book.clean(self.render_vec(vec), false))
            }
            Token::Header(n, ref vec) => {
                if n == 1 && self.current_hide {
                    return String::new();
                }
                let s = if n == 1 && self.current_numbering >= 1 {
                    let chapter = self.current_chapter;
                    self.current_chapter += 1;
                    let res = self.book.get_chapter_header(chapter, self.render_vec(vec), |s| {
                        Ok(self.render_vec(&try!(Parser::new().parse_inline(s))))
                    });
                    res.unwrap()
                } else {
                    self.render_vec(vec)
                };
                format!("<text:h text:style-name=\"Heading_20_{}\">\n{}</text:h>\n",
                        n,
                        escape::html(self.book.clean(s, false)))
            }
            Token::Emphasis(ref vec) => {
                format!("<text:span text:style-name=\"T1\">{}</text:span>",
                        self.render_vec(vec))
            }
            Token::Strong(ref vec) => {
                format!("<text:span text:style-name=\"T2\">{}</text:span>",
                        self.render_vec(vec))
            }
            Token::List(ref vec) => format!("<text:list>\n{}</text:list>\n", self.render_vec(vec)),
            Token::OrderedList(_, ref vec) => {
                self.book
                    .logger
                    .warning(lformat!("ODT: ordered list not currently implemented for this \
                                       format, fallbacking to unordered one"));
                format!("<text:list>\n{}</text:list>\n", self.render_vec(vec))
            }
            Token::Item(ref vec) => {
                format!("<text:list-item>\n<text:p>{}</text:p></text:list-item>",
                        self.book.clean(self.render_vec(vec), false))
            }
            Token::Link(ref url, _, ref vec) => {
                format!("<text:a xlink:type=\"simple\"  xlink:href=\"{}\">{}</text:a>",
                        url,
                        self.render_vec(vec))
            }
            Token::Code(ref vec) => {
                format!("<text:span text:style-name=\"Preformatted_20_Text\">{}</text:span>",
                        self.render_vec(vec))
            }
            Token::BlockQuote(ref vec) |
            Token::CodeBlock(_, ref vec) => {
                self.book
                    .logger
                    .warning(lformat!("ODT: blockquotes and codeblocks are not currently \
                                       implemented for ODT"));
                format!("<text:p text:style-name=\"Text_20_Body\">{}</text:p>\n",
                        self.book.clean(self.render_vec(vec), false))
            }
            Token::SoftBreak | Token::HardBreak => String::from(" "),
            Token::Rule => String::from("<text:p /><text:p>***</text:p><text:p />"),
            Token::Image(_, _, _) |
            Token::StandaloneImage(_, _, _) => {
                self.book
                    .logger
                    .warning(lformat!("ODT: images not currently implemented for this format"));
                String::from(" ")
            }
            Token::Table(_, _) |
            Token::TableHead(_) |
            Token::TableRow(_) |
            Token::TableCell(_) => {
                self.book
                    .logger
                    .warning(lformat!("ODT: tables are not currently implemented for this format"));
                String::from(" ")
            }
            Token::Footnote(_) => {
                self.book
                    .logger
                    .warning(lformat!("ODT: footnotes are not yet implemented in this format, \
                                       ignoring {:?}",
                                      token));
                String::new()
            }
            Token::Annotation(_, ref vec) => self.render_vec(vec),
            Token::__NonExhaustive => unreachable!(),
        }
    }
}
<commit_msg>Fix bug in odt rendering<commit_after>use token::Token;
use book::{Book, compile_str};
use number::Number;
use error::Result;
use templates::odt;
use zipper::Zipper;
use parser::Parser;

use crowbook_text_processing::escape;

/// Rendererer for ODT
///
/// Still very experimental.
pub struct OdtRenderer<'a> {
    book: &'a Book,
    current_numbering: i32,
    current_hide: bool,
    current_chapter: i32,
    automatic_styles: String,
}

impl<'a> OdtRenderer<'a> {
    /// Creates a new OdtRenderer
    pub fn new(book: &'a Book) -> OdtRenderer {
        OdtRenderer {
            book: book,
            current_chapter: 1,
            current_numbering: book.options.get_i32("rendering.num_depth").unwrap(),
            current_hide: false,
            automatic_styles: String::from("
<style:style style:name=\"T1\" \
                                            style:family=\"text\">
  <style:text-properties \
                                            fo:font-style=\"italic\" \
                                            style:font-style-asian=\"italic\" \
                                            style:font-style-complex=\"italic\"/>
</style:style>
\
                                            <style:style style:name=\"T2\" \
                                            style:family=\"text\">
  <style:text-properties \
                                            fo:font-weight=\"bold\" \
                                            style:font-weight-asian=\"bold\" \
                                            style:font-weight-complex=\"bold\"/>
</style:style>"),
        }
    }

    /// Renders a full book
    ///
    /// This will try to generate an ODT file according to self.book options.
    ///
    /// # Returns
    /// * `Ok(s)` where `s` contains the output of the `zip` command
    ///   used to create the ODT file.
    /// * An error if there was somel problem during either the rendering to
    ///   ODT format, or the generation of the ODT file itself.
    pub fn render_book(&mut self) -> Result<String> {
        let content = try!(self.render_content());

        let mut zipper =
            try!(Zipper::new(&self.book.options.get_path("crowbook.temp_dir").unwrap()));

        // Write template.odt there
        try!(zipper.write("template.odt", odt::ODT, false));
        // unzip it
        try!(zipper.unzip("template.odt"));
        // Complete it with content.xml
        try!(zipper.write("content.xml", &content.as_bytes(), false));
        // Zip and copy
        if let Ok(ref file) = self.book.options.get_path("output.odt") {
            zipper.generate_odt(self.book.options.get_str("crowbook.zip.command").unwrap(),
                                file)
        } else {
            panic!(lformat!("odt.render_book called while book.output_odt is not set"));
        }
    }

    /// Render content.xml
    fn render_content(&mut self) -> Result<String> {
        let mut content = String::new();

        for &(n, ref v) in &self.book.chapters {
            self.current_hide = false;
            match n {
                Number::Unnumbered => self.current_numbering = 0,
                Number::Default => {
                    self.current_numbering =
                        self.book.options.get_i32("rendering.num_depth").unwrap()
                }
                Number::Specified(n) => {
                    self.current_numbering = self.book.options.get_i32("numbering").unwrap();
                    self.current_chapter = n;
                }
                Number::Hidden => {
                    self.current_numbering = 0;
                    self.current_hide = true;
                }
                _ => panic!(lformat!("Parts are not supported yet")),
            }
            for token in v {
                content.push_str(&self.parse_token(token));
            }
        }

        let template = try!(compile_str(odt::CONTENT,
                                        &self.book.source,
                                        "could not compile template for content.xml"));
        let data = try!(self.book.get_metadata(|s| Ok(s.to_owned())))
            .insert_str("content", content)
            .insert_str("automatic_styles", &self.automatic_styles)
            .build();

        let mut res: Vec<u8> = vec![];
        template.render_data(&mut res, &data);
        match String::from_utf8(res) {
            Err(_) => panic!(lformat!("generated content.xml was not utf-8 valid")),
            Ok(res) => Ok(res),
        }
    }

    /// Transform a vector of `Token`s to Odt format
    fn render_vec(&mut self, tokens: &[Token]) -> String {
        let mut res = String::new();

        for token in tokens {
            res.push_str(&self.parse_token(&token));
        }
        res
    }

    fn parse_token(&mut self, token: &Token) -> String {
        match *token {
            Token::Str(ref text) => escape::html(self.book.clean(text.as_str(), false)).into_owned(),
            Token::Paragraph(ref vec) => {
                format!("<text:p text:style-name=\"Text_20_body\">{}</text:p>\n",
                        self.render_vec(vec))
            }
            Token::Header(n, ref vec) => {
                if n == 1 && self.current_hide {
                    return String::new();
                }
                let s = if n == 1 && self.current_numbering >= 1 {
                    let chapter = self.current_chapter;
                    self.current_chapter += 1;
                    let res = self.book.get_chapter_header(chapter, self.render_vec(vec), |s| {
                        Ok(self.render_vec(&try!(Parser::new().parse_inline(s))))
                    });
                    res.unwrap()
                } else {
                    self.render_vec(vec)
                };
                format!("<text:h text:style-name=\"Heading_20_{}\">\n{}</text:h>\n",
                        n,
                        s)
            }
            Token::Emphasis(ref vec) => {
                format!("<text:span text:style-name=\"T1\">{}</text:span>",
                        self.render_vec(vec))
            }
            Token::Strong(ref vec) => {
                format!("<text:span text:style-name=\"T2\">{}</text:span>",
                        self.render_vec(vec))
            }
            Token::List(ref vec) => format!("<text:list>\n{}</text:list>\n", self.render_vec(vec)),
            Token::OrderedList(_, ref vec) => {
                self.book
                    .logger
                    .warning(lformat!("ODT: ordered list not currently implemented for this \
                                       format, fallbacking to unordered one"));
                format!("<text:list>\n{}</text:list>\n", self.render_vec(vec))
            }
            Token::Item(ref vec) => {
                format!("<text:list-item>\n<text:p>{}</text:p></text:list-item>",
                        self.book.clean(self.render_vec(vec), false))
            }
            Token::Link(ref url, _, ref vec) => {
                format!("<text:a xlink:type=\"simple\"  xlink:href=\"{}\">{}</text:a>",
                        url,
                        self.render_vec(vec))
            }
            Token::Code(ref vec) => {
                format!("<text:span text:style-name=\"Preformatted_20_Text\">{}</text:span>",
                        self.render_vec(vec))
            }
            Token::BlockQuote(ref vec) |
            Token::CodeBlock(_, ref vec) => {
                self.book
                    .logger
                    .warning(lformat!("ODT: blockquotes and codeblocks are not currently \
                                       implemented for ODT"));
                format!("<text:p text:style-name=\"Text_20_Body\">{}</text:p>\n",
                        self.book.clean(self.render_vec(vec), false))
            }
            Token::SoftBreak | Token::HardBreak => String::from(" "),
            Token::Rule => String::from("<text:p /><text:p>***</text:p><text:p />"),
            Token::Image(_, _, _) |
            Token::StandaloneImage(_, _, _) => {
                self.book
                    .logger
                    .warning(lformat!("ODT: images not currently implemented for this format"));
                String::from(" ")
            }
            Token::Table(_, _) |
            Token::TableHead(_) |
            Token::TableRow(_) |
            Token::TableCell(_) => {
                self.book
                    .logger
                    .warning(lformat!("ODT: tables are not currently implemented for this format"));
                String::from(" ")
            }
            Token::Footnote(_) => {
                self.book
                    .logger
                    .warning(lformat!("ODT: footnotes are not yet implemented in this format, \
                                       ignoring {:?}",
                                      token));
                String::new()
            }
            Token::Annotation(_, ref vec) => self.render_vec(vec),
            Token::__NonExhaustive => unreachable!(),
        }
    }
}
<|endoftext|>


<commit_before>//! Lua functionality

use hlua;
use hlua::Lua;
use std::thread;
use std::time::Duration;
use std::fs::{File};
use std::io::Write;
use std::sync::Mutex;
use std::sync::mpsc::{channel, Sender, Receiver};

lazy_static! {
    static ref SENDER: Mutex<Sender<LuaQuery>> = {
        let (tx, rx) = channel::<LuaQuery>();
        Mutex::new(tx)
    };
    static ref RECEIVER: Mutex<Receiver<LuaResponse>> = {
        let (tx, rx) = channel::<LuaResponse>();
        Mutex::new(rx)
    };
}

/// Messages sent to the lua thread
pub enum LuaQuery {
    CallFunction(String),
    GetVariable(String)
}

/// Messages received from lua thread
pub enum LuaResponse {
    Error(hlua::LuaError),
    Function(hlua::functions_read::LuaFunction<String>)
}

unsafe impl Send for LuaQuery { }
unsafe impl Send for LuaResponse { }
unsafe impl Sync for LuaQuery { }
unsafe impl Sync for LuaResponse { }

pub fn init() {
    print!("[lua] Initializing...");
    let (query_tx, query_rx) = channel::<LuaQuery>();
    let (answer_tx, answer_rx) = channel::<LuaResponse>();
    {
        let mut sender = SENDER.lock().unwrap();
        let mut receiver = RECEIVER.lock().unwrap();

        *sender = query_tx;
        *receiver = answer_rx;
    }

    thread::spawn(move || {
        println!("[lua] Inside thread!");
        let receiver = query_rx;
        let sender = answer_tx;
        let mut LUA = Lua::new();
        print!("[lua] Loading libs...");
        LUA.openlibs();
        println!(" done!");
        println!("[lua] Creating init file");
        let mut file = File::create("/tmp/init.lua").unwrap();
        file.write(b"print('Hello world!')").unwrap();
        println!("[lua] Created hello world file!");
        println!("[lua] Executing init.lua...");
        LUA.execute_from_reader::<(), File>(File::open("/tmp/init.lua").unwrap());
        println!("[lua] Done!");
        thread::sleep(Duration::from_secs(10));
        println!("[lua] Exiting thread...");
    });
    println!(" created thread.")
}
<commit_msg>Add variants to LuaQuery to allow better communication<commit_after>//! Lua functionality

use hlua;
use hlua::Lua;
use std::thread;
use std::time::Duration;
use std::fs::{File};
use std::path::Path;
use std::io::Write;
use std::sync::Mutex;
use std::sync::mpsc::{channel, Sender, Receiver};

lazy_static! {
    static ref SENDER: Mutex<Sender<LuaQuery>> = {
        let (tx, rx) = channel::<LuaQuery>();
        Mutex::new(tx)
    };
    static ref RECEIVER: Mutex<Receiver<LuaResponse>> = {
        let (tx, rx) = channel::<LuaResponse>();
        Mutex::new(rx)
    };
}

/// Messages sent to the lua thread
pub enum LuaQuery {
    /// Execute a string
    Execute(String),
    /// Execute a file
    ExecuteFile(String),
    /// Get a variable
    GetVariable(String),
    /// Set a value
    SetValue {
        name: Box<::std::borrow::Borrow<str> + Sized>,
        val: Box<hlua::Push<&'static mut Lua<'static>> + Sized>
    },
    /// Create a new array
    EmptyArray(String),
}

/// Messages received from lua thread
pub enum LuaResponse {
    Error(hlua::LuaError),
    Function(hlua::functions_read::LuaFunction<String>)
}

unsafe impl Send for LuaQuery { }
unsafe impl Send for LuaResponse { }
unsafe impl Sync for LuaQuery { }
unsafe impl Sync for LuaResponse { }

pub fn init() {
    print!("[lua] Initializing...");
    let (query_tx, query_rx) = channel::<LuaQuery>();
    let (answer_tx, answer_rx) = channel::<LuaResponse>();
    {
        let mut sender = SENDER.lock().unwrap();
        let mut receiver = RECEIVER.lock().unwrap();

        *sender = query_tx;
        *receiver = answer_rx;
    }

    thread::spawn(move || {
        println!("[lua] Inside thread!");
        let receiver = query_rx;
        let sender = answer_tx;
        let mut lua = Lua::new();
        print!("[lua] Loading libs...");
        lua.openlibs();
        println!(" done!");
        println!("[lua] Creating init file");
        let mut file = File::create("/tmp/init.lua").unwrap();
        file.write(b"print('Hello world!')").unwrap();
        println!("[lua] Created hello world file!");
        println!("[lua] Executing init.lua...");
        lua.execute_from_reader::<(), File>(File::open("/tmp/init.lua")
                                            .unwrap()).unwrap();
        println!("[lua] Done!");
        thread::sleep(Duration::from_secs(10));
        println!("[lua] Exiting thread...");
    });
    println!(" created thread.")
}
<|endoftext|>


<commit_before>use action;
use settings;
use glfw;
use Settings = piston::game::Settings;
use Game = piston::game::Game;
use piston::gl::Gl;
use graphics;
use graphics::*;
use object;
use Object = object::Object;
use text;
use game_state;

pub struct SnakeApp {
    settings: Settings,
    // Tells where the surface is.
    surface_y: Option<f64>,
    game_state: Option<game_state::GameState>,
    camera_pos: Option<[f64, ..2]>,
    camera_follow_percentage: Option<f64>,
    player_index: Option<uint>,
    blood_bar_index: Option<uint>,
    air_bar_index: Option<uint>,
    // Contains the game objects.
    objects: Vec<Object>,
}

impl Game for SnakeApp {
    fn get_settings<'a>(&'a self) -> &'a Settings { &self.settings }

    fn render(&self, c: &graphics::Context, gl: &mut Gl) {
        // Get camera coordinates.
        let (cam_x, cam_y) = if self.camera_pos.is_some() {
                let camera_pos = self.camera_pos.unwrap();
                (camera_pos[0], camera_pos[1])
            } else { (0.0, 0.0) };

        // Render surface.
        let surface_y = self.surface_y.unwrap();
        c.rect(-1.0, surface_y - cam_y, 2.0, 0.05).color(settings::BLUE).fill(gl);

        // Render objects in layers.
        let cam = &c.trans(-cam_x, -cam_y);
        for i in range(0u, settings::NUMBER_OF_LAYERS) {
            for obj in self.objects.iter() {
                if obj.layer == i { obj.render(cam, c, gl); }
            }
        }

        let text_c = c.flip_v_local();
        let text_c = text_c.zoom(0.0025);
        match self.game_state.unwrap() {
            game_state::Win => {
                let pos = settings::YOU_WIN_POS;
                text::text(settings::YOU_WIN_TEXT,
                    &text_c
                    .trans(pos[0], pos[1])
                    .color(settings::YOU_WIN_TEXT_COLOR)
                , gl);
            },
            game_state::Loose => {
                let pos = settings::YOU_LOOSE_POS;
                text::text(settings::YOU_LOOSE_TEXT,
                    &text_c
                    .trans(pos[0], pos[1])
                    .color(settings::YOU_LOOSE_TEXT_COLOR)
                , gl);
            },
            game_state::Play => {

            },
        }

        // TEST
        // text::text("restart", &c.flip_v_local().zoom(0.001).color(settings::BLACK), gl);
    }

    fn update(&mut self, dt: f64) {
        self.update_objects(dt);
        self.fill_air();
        self.win();
        self.loose();
        self.show_blood();
        self.show_air();
        self.follow_player(dt);
    }

    fn load(&mut self) {
        self.camera_follow_percentage = Some(settings::CAMERA_FOLLOW_PERCENTAGE);
        self.camera_pos = Some(settings::INITIAL_CAMERA_POS);
        self.surface_y = Some(settings::SURFACE_Y);
        self.game_state = Some(settings::INITIAL_GAME_STATE);

        // Add player.
        self.objects.push(Object::player(
            settings::ORIGIN,
            settings::BLUE,
            settings::PLAYER_INITIAL_BLOOD,
            settings::PLAYER_INITIAL_AIR,
            [settings::PLAYER_ACCELERATION_LEFT, settings::PLAYER_ACCELERATION_RIGHT],
            [settings::PLAYER_ACCELERATION_UP, settings::PLAYER_ACCELERATION_DOWN]
        ));
        self.objects.push(Object::bar_background());
        self.player_index = Some(0);

        // Add blood and air bar.
        self.add_bars();

        // Add air bottles.
        self.add_air_bottles();

        // Add sharks.
        self.add_snakes();
    }

    fn key_press(&mut self, key: glfw::Key) {
        // TEST
        // println!("Key pressed {}", key);

        if self.game_state.unwrap() != game_state::Play { return; }

        match (key, self.player_index) {
            (glfw::KeyRight, Some(player_index)) => {
                self.objects.get_mut(player_index).move_right();
            },
            (glfw::KeyUp, Some(player_index)) => {
                self.objects.get_mut(player_index).move_up();
            },
            (glfw::KeyLeft, Some(player_index)) => {
                self.objects.get_mut(player_index).move_left();
            },
            (glfw::KeyDown, Some(player_index)) => {
                self.objects.get_mut(player_index).move_down();
            },
            _ => {},
        }
    }

    fn key_release(&mut self, key: glfw::Key) {
        // TEST
        // println!("Key released {}", key);

        if key == glfw::KeyEnter || key == glfw::KeySpace {
            match self.game_state.unwrap() {
                game_state::Win | game_state::Loose => self.restart(),
                _ => {},
            }
        }
    }
}

impl SnakeApp {
    pub fn new() -> SnakeApp {
        let exit_on_esc = true;
        let background_color = settings::WATER_COLOR;
        SnakeApp {
            camera_pos: None,
            camera_follow_percentage: None,
            settings: Settings::new(exit_on_esc, background_color),
            game_state: None,
            surface_y: None,
            objects: Vec::new(),
            player_index: None,
            blood_bar_index: None,
            air_bar_index: None,
        }
    }

    pub fn add_bars(&mut self) {
        self.objects.push(Object::bar(
            settings::AIR_BAR_POS,
            "air",
            settings::AIR_BAR_TEXT_COLOR,
            settings::AIR_BAR_BACKGROUND_COLOR,
            settings::AIR_BAR_BAR_COLOR,
            settings::AIR_BAR_INITIAL_VALUE
        ));
        self.air_bar_index = Some(self.objects.len() - 1);
        self.objects.push(Object::bar(
            settings::BLOOD_BAR_POS,
            "blood",
            settings::BLOOD_BAR_TEXT_COLOR,
            settings::BLOOD_BAR_BACKGROUND_COLOR,
            settings::BLOOD_BAR_BAR_COLOR,
            settings::BLOOD_BAR_INITIAL_VALUE
        ));
        self.blood_bar_index = Some(self.objects.len() - 1);
    }

    pub fn add_snakes(&mut self) {
        if settings::SNAKE_1_ADD { self.objects.push(Object::snake(settings::SNAKE_1_POS, settings::SNAKE_1_SETTINGS)); }
        if settings::SNAKE_2_ADD { self.objects.push(Object::snake(settings::SNAKE_2_POS, settings::SNAKE_2_SETTINGS)); }
    }

    pub fn add_air_bottles(&mut self) {
        let air_bottles = settings::AIR_BOTTLE_POS;
        let n = air_bottles.len() / 2;
        for i in range(0, n) {
            self.objects.push(Object::air_bottle([air_bottles[i * 2], air_bottles[i * 2 + 1]]));
        }
    }

    fn follow_player(&mut self, dt: f64) {
        if self.camera_pos.is_none() { return; }
        // Make camera follow player.
        let camera_pos = self.camera_pos.unwrap();
        let camera_follow_percentage = self.camera_follow_percentage.unwrap();
        let player_pos = self.player_pos();
        let (dx, dy) = (player_pos[0] - camera_pos[0], player_pos[1] - camera_pos[1]);
        let dx = camera_follow_percentage * dt * dx;
        let dy = camera_follow_percentage * dt * dy;
        self.camera_pos = Some([camera_pos[0] + dx, camera_pos[1] + dy]);
    }

    fn show_blood(&mut self) {
        if self.blood_bar_index == None { return; }
        // Show blood.
        let player_blood = self.player_blood();
        let blood_bar_index = self.blood_bar_index.unwrap();
        let blood_bar = self.objects.get_mut(blood_bar_index);
        match blood_bar.data {
            object::BarData(ref mut bar) => {
                bar.value = player_blood;
            },
            _ => {},
        }
    }

    fn show_air(&mut self) {
        if self.air_bar_index == None { return; }
        // Show air.
        let player_air = self.player_air();
        let air_bar_index = self.air_bar_index.unwrap();
        let air_bar = self.objects.get_mut(air_bar_index);
        match air_bar.data {
            object::BarData(ref mut bar) => {
                bar.value = player_air;
            },
            _ => {},
        }
    }

    fn win(&mut self) {
        let player_pos = self.player_pos();
        // When player reaches surface, win.
        if player_pos[1] >= self.surface_y.unwrap() {
            self.game_state = Some(game_state::Win);
            return;
        }
    }

    fn loose(&mut self) {
        let blood = self.player_blood();
        let air = self.player_air();
        if blood < 0.0 || air < 0.0 {
            self.game_state = Some(game_state::Loose);
            return;
        }
    }

    fn restart(&mut self) {
        *self = SnakeApp::new();
        self.load();
    }

    fn update_objects(&mut self, dt: f64) {
        if self.game_state.unwrap() != game_state::Play { return; }

        // Update states of objects.
        let player_pos = self.player_pos();
        let mut attack_damage: f64 = 0.0;
        for obj in self.objects.mut_iter() {
            match obj.update(dt, player_pos) {
                action::Passive => {},
                action::Attack(attack) => { attack_damage += attack; },
            }
        }
        // Bite player.
        self.bite_player(attack_damage);

        // Decrease the player's air with time.
        let air = self.player_air();
        self.set_player_air(air - dt * settings::PLAYER_LOOSE_AIR_SPEED);
    }

    fn player_pos(&self) -> [f64, ..2] {
        let player_index = self.player_index.unwrap();
        self.objects.get(player_index).pos
    }

    fn player_blood(&self) -> f64 {
        let player_index = self.player_index.unwrap();
        self.objects.get(player_index).blood().unwrap()
    }

    fn set_player_blood(&mut self, val: f64) {
        let player_index = self.player_index.unwrap();
        *self.objects.get_mut(player_index).blood_mut().unwrap() = val;
    }

    fn player_air(&self) -> f64 {
        let player_index = self.player_index.unwrap();
        self.objects.get(player_index).air().unwrap()
    }

    fn set_player_air(&mut self, val: f64) {
        let player_index = self.player_index.unwrap();
        *self.objects.get_mut(player_index).air_mut().unwrap() = val;
    }

    fn bite_player(&mut self, damage: f64) {
        let player_index = self.player_index.unwrap();
        self.objects.get_mut(player_index).player_mut().unwrap().bite(damage);
    }

    fn fill_air(&mut self) {
        let player_pos = self.player_pos();
        let mut air = self.player_air();
        for obj in self.objects.mut_iter() {
            let pos = obj.pos;
            match obj.air_bottle_mut() {
                None => {},
                Some(air_bottle) => {
                    let dx = pos[0] - player_pos[0];
                    let dy = pos[1] - player_pos[1];
                    let d = dx * dx + dy * dy;
                    if d <= settings::AIR_BOTTLE_RADIUS {
                        air += air_bottle.fill_up;
                        air_bottle.fill_up = 0.0;
                    }
                },
            }
        }
        self.set_player_air(air);
    }
}

<commit_msg>Prevent air from being filled up more than 100%<commit_after>use action;
use settings;
use glfw;
use Settings = piston::game::Settings;
use Game = piston::game::Game;
use piston::gl::Gl;
use graphics;
use graphics::*;
use object;
use Object = object::Object;
use text;
use game_state;

pub struct SnakeApp {
    settings: Settings,
    // Tells where the surface is.
    surface_y: Option<f64>,
    game_state: Option<game_state::GameState>,
    camera_pos: Option<[f64, ..2]>,
    camera_follow_percentage: Option<f64>,
    player_index: Option<uint>,
    blood_bar_index: Option<uint>,
    air_bar_index: Option<uint>,
    // Contains the game objects.
    objects: Vec<Object>,
}

impl Game for SnakeApp {
    fn get_settings<'a>(&'a self) -> &'a Settings { &self.settings }

    fn render(&self, c: &graphics::Context, gl: &mut Gl) {
        // Get camera coordinates.
        let (cam_x, cam_y) = if self.camera_pos.is_some() {
                let camera_pos = self.camera_pos.unwrap();
                (camera_pos[0], camera_pos[1])
            } else { (0.0, 0.0) };

        // Render surface.
        let surface_y = self.surface_y.unwrap();
        c.rect(-1.0, surface_y - cam_y, 2.0, 0.05).color(settings::BLUE).fill(gl);

        // Render objects in layers.
        let cam = &c.trans(-cam_x, -cam_y);
        for i in range(0u, settings::NUMBER_OF_LAYERS) {
            for obj in self.objects.iter() {
                if obj.layer == i { obj.render(cam, c, gl); }
            }
        }

        let text_c = c.flip_v_local();
        let text_c = text_c.zoom(0.0025);
        match self.game_state.unwrap() {
            game_state::Win => {
                let pos = settings::YOU_WIN_POS;
                text::text(settings::YOU_WIN_TEXT,
                    &text_c
                    .trans(pos[0], pos[1])
                    .color(settings::YOU_WIN_TEXT_COLOR)
                , gl);
            },
            game_state::Loose => {
                let pos = settings::YOU_LOOSE_POS;
                text::text(settings::YOU_LOOSE_TEXT,
                    &text_c
                    .trans(pos[0], pos[1])
                    .color(settings::YOU_LOOSE_TEXT_COLOR)
                , gl);
            },
            game_state::Play => {

            },
        }

        // TEST
        // text::text("restart", &c.flip_v_local().zoom(0.001).color(settings::BLACK), gl);
    }

    fn update(&mut self, dt: f64) {
        self.update_objects(dt);
        self.fill_air();
        self.win();
        self.loose();
        self.show_blood();
        self.show_air();
        self.follow_player(dt);
    }

    fn load(&mut self) {
        self.camera_follow_percentage = Some(settings::CAMERA_FOLLOW_PERCENTAGE);
        self.camera_pos = Some(settings::INITIAL_CAMERA_POS);
        self.surface_y = Some(settings::SURFACE_Y);
        self.game_state = Some(settings::INITIAL_GAME_STATE);

        // Add player.
        self.objects.push(Object::player(
            settings::ORIGIN,
            settings::BLUE,
            settings::PLAYER_INITIAL_BLOOD,
            settings::PLAYER_INITIAL_AIR,
            [settings::PLAYER_ACCELERATION_LEFT, settings::PLAYER_ACCELERATION_RIGHT],
            [settings::PLAYER_ACCELERATION_UP, settings::PLAYER_ACCELERATION_DOWN]
        ));
        self.objects.push(Object::bar_background());
        self.player_index = Some(0);

        // Add blood and air bar.
        self.add_bars();

        // Add air bottles.
        self.add_air_bottles();

        // Add sharks.
        self.add_snakes();
    }

    fn key_press(&mut self, key: glfw::Key) {
        // TEST
        // println!("Key pressed {}", key);

        if self.game_state.unwrap() != game_state::Play { return; }

        match (key, self.player_index) {
            (glfw::KeyRight, Some(player_index)) => {
                self.objects.get_mut(player_index).move_right();
            },
            (glfw::KeyUp, Some(player_index)) => {
                self.objects.get_mut(player_index).move_up();
            },
            (glfw::KeyLeft, Some(player_index)) => {
                self.objects.get_mut(player_index).move_left();
            },
            (glfw::KeyDown, Some(player_index)) => {
                self.objects.get_mut(player_index).move_down();
            },
            _ => {},
        }
    }

    fn key_release(&mut self, key: glfw::Key) {
        // TEST
        // println!("Key released {}", key);

        if key == glfw::KeyEnter || key == glfw::KeySpace {
            match self.game_state.unwrap() {
                game_state::Win | game_state::Loose => self.restart(),
                _ => {},
            }
        }
    }
}

impl SnakeApp {
    pub fn new() -> SnakeApp {
        let exit_on_esc = true;
        let background_color = settings::WATER_COLOR;
        SnakeApp {
            camera_pos: None,
            camera_follow_percentage: None,
            settings: Settings::new(exit_on_esc, background_color),
            game_state: None,
            surface_y: None,
            objects: Vec::new(),
            player_index: None,
            blood_bar_index: None,
            air_bar_index: None,
        }
    }

    pub fn add_bars(&mut self) {
        self.objects.push(Object::bar(
            settings::AIR_BAR_POS,
            "air",
            settings::AIR_BAR_TEXT_COLOR,
            settings::AIR_BAR_BACKGROUND_COLOR,
            settings::AIR_BAR_BAR_COLOR,
            settings::AIR_BAR_INITIAL_VALUE
        ));
        self.air_bar_index = Some(self.objects.len() - 1);
        self.objects.push(Object::bar(
            settings::BLOOD_BAR_POS,
            "blood",
            settings::BLOOD_BAR_TEXT_COLOR,
            settings::BLOOD_BAR_BACKGROUND_COLOR,
            settings::BLOOD_BAR_BAR_COLOR,
            settings::BLOOD_BAR_INITIAL_VALUE
        ));
        self.blood_bar_index = Some(self.objects.len() - 1);
    }

    pub fn add_snakes(&mut self) {
        if settings::SNAKE_1_ADD { self.objects.push(Object::snake(settings::SNAKE_1_POS, settings::SNAKE_1_SETTINGS)); }
        if settings::SNAKE_2_ADD { self.objects.push(Object::snake(settings::SNAKE_2_POS, settings::SNAKE_2_SETTINGS)); }
    }

    pub fn add_air_bottles(&mut self) {
        let air_bottles = settings::AIR_BOTTLE_POS;
        let n = air_bottles.len() / 2;
        for i in range(0, n) {
            self.objects.push(Object::air_bottle([air_bottles[i * 2], air_bottles[i * 2 + 1]]));
        }
    }

    fn follow_player(&mut self, dt: f64) {
        if self.camera_pos.is_none() { return; }
        // Make camera follow player.
        let camera_pos = self.camera_pos.unwrap();
        let camera_follow_percentage = self.camera_follow_percentage.unwrap();
        let player_pos = self.player_pos();
        let (dx, dy) = (player_pos[0] - camera_pos[0], player_pos[1] - camera_pos[1]);
        let dx = camera_follow_percentage * dt * dx;
        let dy = camera_follow_percentage * dt * dy;
        self.camera_pos = Some([camera_pos[0] + dx, camera_pos[1] + dy]);
    }

    fn show_blood(&mut self) {
        if self.blood_bar_index == None { return; }
        // Show blood.
        let player_blood = self.player_blood();
        let blood_bar_index = self.blood_bar_index.unwrap();
        let blood_bar = self.objects.get_mut(blood_bar_index);
        match blood_bar.data {
            object::BarData(ref mut bar) => {
                bar.value = player_blood;
            },
            _ => {},
        }
    }

    fn show_air(&mut self) {
        if self.air_bar_index == None { return; }
        // Show air.
        let player_air = self.player_air();
        let air_bar_index = self.air_bar_index.unwrap();
        let air_bar = self.objects.get_mut(air_bar_index);
        match air_bar.data {
            object::BarData(ref mut bar) => {
                bar.value = player_air;
            },
            _ => {},
        }
    }

    fn win(&mut self) {
        let player_pos = self.player_pos();
        // When player reaches surface, win.
        if player_pos[1] >= self.surface_y.unwrap() {
            self.game_state = Some(game_state::Win);
            return;
        }
    }

    fn loose(&mut self) {
        let blood = self.player_blood();
        let air = self.player_air();
        if blood < 0.0 || air < 0.0 {
            self.game_state = Some(game_state::Loose);
            return;
        }
    }

    fn restart(&mut self) {
        *self = SnakeApp::new();
        self.load();
    }

    fn update_objects(&mut self, dt: f64) {
        if self.game_state.unwrap() != game_state::Play { return; }

        // Update states of objects.
        let player_pos = self.player_pos();
        let mut attack_damage: f64 = 0.0;
        for obj in self.objects.mut_iter() {
            match obj.update(dt, player_pos) {
                action::Passive => {},
                action::Attack(attack) => { attack_damage += attack; },
            }
        }
        // Bite player.
        self.bite_player(attack_damage);

        // Decrease the player's air with time.
        let air = self.player_air();
        self.set_player_air(air - dt * settings::PLAYER_LOOSE_AIR_SPEED);
    }

    fn player_pos(&self) -> [f64, ..2] {
        let player_index = self.player_index.unwrap();
        self.objects.get(player_index).pos
    }

    fn player_blood(&self) -> f64 {
        let player_index = self.player_index.unwrap();
        self.objects.get(player_index).blood().unwrap()
    }

    fn set_player_blood(&mut self, val: f64) {
        let player_index = self.player_index.unwrap();
        *self.objects.get_mut(player_index).blood_mut().unwrap() = val;
    }

    fn player_air(&self) -> f64 {
        let player_index = self.player_index.unwrap();
        self.objects.get(player_index).air().unwrap()
    }

    fn set_player_air(&mut self, val: f64) {
        let player_index = self.player_index.unwrap();
        *self.objects.get_mut(player_index).air_mut().unwrap() = val;
    }

    fn bite_player(&mut self, damage: f64) {
        let player_index = self.player_index.unwrap();
        self.objects.get_mut(player_index).player_mut().unwrap().bite(damage);
    }

    fn fill_air(&mut self) {
        let player_pos = self.player_pos();
        let mut air = self.player_air();
        for obj in self.objects.mut_iter() {
            let pos = obj.pos;
            match obj.air_bottle_mut() {
                None => {},
                Some(air_bottle) => {
                    let dx = pos[0] - player_pos[0];
                    let dy = pos[1] - player_pos[1];
                    let d = dx * dx + dy * dy;
                    if d <= settings::AIR_BOTTLE_RADIUS {
                        air += air_bottle.fill_up;
                        air_bottle.fill_up = 0.0;
                    }
                },
            }
        }

        air = if air > 1.0 { 1.0 } else { air };
        self.set_player_air(air);
    }
}

<|endoftext|>


<commit_before><commit_msg>Use rl/wl shortcut<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2013-2016 Sandstorm Development Group, Inc. and contributors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use futures::{Future};

use std::cell::{Cell, RefCell};
use std::rc::{Rc, Weak};
use std::sync::Arc;

use stack::Stack;

enum Slot<T> {
    Next(usize),
    Data(T),
}

struct Inner<T, E> {
    // A slab of futures that are being executed. Each slot in this vector is
    // either an active future or a pointer to the next empty slot. This is used
    // to get O(1) deallocation in the slab and O(1) allocation.
    //
    // The `next_future` field is the next slot in the `futures` array that's a
    // `Slot::Next` variant. If it points to the end of the array then the array
    // is full.
    futures: RefCell<Vec<Slot<Box<Future<Item=T, Error=E>>>>>,
    next_future: Cell<usize>,

    new_futures: RefCell<Vec<Box<Future<Item=T, Error=E>>>>,

    stack: Arc<Stack<usize>>,
    reaper: RefCell<Box<TaskReaper<T, E>>>,

    terminate_with: RefCell<Option<Result<(), E>>>,

    handle_count: Cell<usize>,
    task: RefCell<Option<::futures::task::Task>>,
}

#[must_use = "a TaskSet does nothing unless polled"]
pub struct TaskSet<T, E> {
    inner: Rc<Inner<T, E>>,
}

impl<T, E> TaskSet<T, E> where T: 'static, E: 'static {
    pub fn new(reaper: Box<TaskReaper<T, E>>)
               -> (TaskSetHandle<T, E>, TaskSet<T, E>)
        where E: 'static, T: 'static, E: ::std::fmt::Debug,
    {
        let inner = Rc::new(Inner {
            futures: RefCell::new(Vec::new()),
            next_future: Cell::new(0),
            new_futures: RefCell::new(Vec::new()),
            stack: Arc::new(Stack::new()),
            reaper: RefCell::new(reaper),
            terminate_with: RefCell::new(None),
            handle_count: Cell::new(1),
            task: RefCell::new(None),
        });

        let weak_inner = Rc::downgrade(&inner);

        let set = TaskSet {
            inner: inner,
        };

        let handle = TaskSetHandle {
            inner: weak_inner,
        };

        (handle, set)
    }
}

pub struct TaskSetHandle<T, E> {
    inner: Weak<Inner<T, E>>,
}

impl<T, E> Clone for TaskSetHandle<T, E> {
    fn clone(&self) -> TaskSetHandle<T, E> {
        match self.inner.upgrade() {
            None => (),
            Some(inner) => {
                inner.handle_count.set(inner.handle_count.get() + 1);
            }
        }
        TaskSetHandle {
            inner: self.inner.clone()
        }
    }
}

impl <T, E> Drop for TaskSetHandle<T, E> {
    fn drop(&mut self) {
        match self.inner.upgrade() {
            None => (),
            Some(inner) => {
                inner.handle_count.set(inner.handle_count.get() - 1);
            }
        }
    }
}

impl <T, E> TaskSetHandle<T, E> where T: 'static, E: 'static {
    pub fn add<F>(&mut self, promise: F)
        where F: Future<Item=T, Error=E> + 'static
    {
        match self.inner.upgrade() {
            None => (),
            Some(rc_inner) => {
                rc_inner.new_futures.borrow_mut().push(Box::new(promise));

                match rc_inner.task.borrow_mut().take() {
                    Some(t) => t.unpark(),
                    None => (),
                }
            }
        }
    }

    pub fn terminate(&mut self, result: Result<(), E>) {
        match self.inner.upgrade() {
            None => (),
            Some(rc_inner) => {
                *rc_inner.terminate_with.borrow_mut() = Some(result);

                match rc_inner.task.borrow_mut().take() {
                    Some(t) => t.unpark(),
                    None => (),
                }
            }
        }
    }
}

pub trait TaskReaper<T, E> where T: 'static, E: 'static
{
    fn task_succeeded(&mut self, _value: T) {}
    fn task_failed(&mut self, error: E);
}

impl <T, E> Future for TaskSet<T, E> where T: 'static, E: 'static {
    type Item = ();
    type Error = E;

    fn poll(&mut self) -> ::futures::Poll<Self::Item, Self::Error> {

        match self.inner.terminate_with.borrow_mut().take() {
            None => (),
            Some(Ok(v)) => return Ok(::futures::Async::Ready(v)),
            Some(Err(e)) => return Err(e),
        }

        let new_futures = ::std::mem::replace(&mut *self.inner.new_futures.borrow_mut(), Vec::new());
        for future in new_futures {
            let added_idx = self.inner.next_future.get();
            if self.inner.next_future.get() == self.inner.futures.borrow().len() {
                self.inner.futures.borrow_mut().push(Slot::Data(future));
                self.inner.next_future.set(self.inner.next_future.get() + 1);
            } else {
                match ::std::mem::replace(&mut self.inner.futures.borrow_mut()[self.inner.next_future.get()],
                                          Slot::Data(future)) {
                    Slot::Next(next) => self.inner.next_future.set(next),
                    Slot::Data(_) => unreachable!(),
                }
            }

            self.inner.stack.push(added_idx);
        }

        let drain = self.inner.stack.drain();
        for idx in drain {
            match self.inner.futures.borrow_mut()[idx] {
                Slot::Next(_) => continue,
                Slot::Data(ref mut f) => {
                    let event = ::futures::task::UnparkEvent::new(self.inner.stack.clone(), idx);
                    match ::futures::task::with_unpark_event(event, || f.poll()) {
                        Ok(::futures::Async::NotReady) => continue,
                        Ok(::futures::Async::Ready(v)) => {
                            self.inner.reaper.borrow_mut().task_succeeded(v);
                        }
                        Err(e) => {
                            self.inner.reaper.borrow_mut().task_failed(e);
                        }
                    }
                }
            }
            self.inner.futures.borrow_mut()[idx] = Slot::Next(self.inner.next_future.get());
            self.inner.next_future.set(idx);
        }

        if self.inner.futures.borrow().len() == 0 && self.inner.handle_count.get() == 0 {
            Ok(::futures::Async::Ready(()))
        } else {
            let task = ::futures::task::park();
            if self.inner.new_futures.borrow().len() > 0 {
                // Some new futures got added when we called poll().
                task.unpark();
            }
            *self.inner.task.borrow_mut() = Some(task);
            Ok(::futures::Async::NotReady)
        }
    }
}
<commit_msg>add comment about buffer_unordered()<commit_after>// Copyright (c) 2013-2016 Sandstorm Development Group, Inc. and contributors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

// Much of the details of this task_set implementation are borrowed from
// the buffer_unordered() in futures-rs.

use futures::{Future};

use std::cell::{Cell, RefCell};
use std::rc::{Rc, Weak};
use std::sync::Arc;

use stack::Stack;

enum Slot<T> {
    Next(usize),
    Data(T),
}

struct Inner<T, E> {
    // A slab of futures that are being executed. Each slot in this vector is
    // either an active future or a pointer to the next empty slot. This is used
    // to get O(1) deallocation in the slab and O(1) allocation.
    //
    // The `next_future` field is the next slot in the `futures` array that's a
    // `Slot::Next` variant. If it points to the end of the array then the array
    // is full.
    futures: RefCell<Vec<Slot<Box<Future<Item=T, Error=E>>>>>,
    next_future: Cell<usize>,

    new_futures: RefCell<Vec<Box<Future<Item=T, Error=E>>>>,

    stack: Arc<Stack<usize>>,
    reaper: RefCell<Box<TaskReaper<T, E>>>,

    terminate_with: RefCell<Option<Result<(), E>>>,

    handle_count: Cell<usize>,
    task: RefCell<Option<::futures::task::Task>>,
}

#[must_use = "a TaskSet does nothing unless polled"]
pub struct TaskSet<T, E> {
    inner: Rc<Inner<T, E>>,
}

impl<T, E> TaskSet<T, E> where T: 'static, E: 'static {
    pub fn new(reaper: Box<TaskReaper<T, E>>)
               -> (TaskSetHandle<T, E>, TaskSet<T, E>)
        where E: 'static, T: 'static, E: ::std::fmt::Debug,
    {
        let inner = Rc::new(Inner {
            futures: RefCell::new(Vec::new()),
            next_future: Cell::new(0),
            new_futures: RefCell::new(Vec::new()),
            stack: Arc::new(Stack::new()),
            reaper: RefCell::new(reaper),
            terminate_with: RefCell::new(None),
            handle_count: Cell::new(1),
            task: RefCell::new(None),
        });

        let weak_inner = Rc::downgrade(&inner);

        let set = TaskSet {
            inner: inner,
        };

        let handle = TaskSetHandle {
            inner: weak_inner,
        };

        (handle, set)
    }
}

pub struct TaskSetHandle<T, E> {
    inner: Weak<Inner<T, E>>,
}

impl<T, E> Clone for TaskSetHandle<T, E> {
    fn clone(&self) -> TaskSetHandle<T, E> {
        match self.inner.upgrade() {
            None => (),
            Some(inner) => {
                inner.handle_count.set(inner.handle_count.get() + 1);
            }
        }
        TaskSetHandle {
            inner: self.inner.clone()
        }
    }
}

impl <T, E> Drop for TaskSetHandle<T, E> {
    fn drop(&mut self) {
        match self.inner.upgrade() {
            None => (),
            Some(inner) => {
                inner.handle_count.set(inner.handle_count.get() - 1);
            }
        }
    }
}

impl <T, E> TaskSetHandle<T, E> where T: 'static, E: 'static {
    pub fn add<F>(&mut self, promise: F)
        where F: Future<Item=T, Error=E> + 'static
    {
        match self.inner.upgrade() {
            None => (),
            Some(rc_inner) => {
                rc_inner.new_futures.borrow_mut().push(Box::new(promise));

                match rc_inner.task.borrow_mut().take() {
                    Some(t) => t.unpark(),
                    None => (),
                }
            }
        }
    }

    pub fn terminate(&mut self, result: Result<(), E>) {
        match self.inner.upgrade() {
            None => (),
            Some(rc_inner) => {
                *rc_inner.terminate_with.borrow_mut() = Some(result);

                match rc_inner.task.borrow_mut().take() {
                    Some(t) => t.unpark(),
                    None => (),
                }
            }
        }
    }
}

pub trait TaskReaper<T, E> where T: 'static, E: 'static
{
    fn task_succeeded(&mut self, _value: T) {}
    fn task_failed(&mut self, error: E);
}

impl <T, E> Future for TaskSet<T, E> where T: 'static, E: 'static {
    type Item = ();
    type Error = E;

    fn poll(&mut self) -> ::futures::Poll<Self::Item, Self::Error> {

        match self.inner.terminate_with.borrow_mut().take() {
            None => (),
            Some(Ok(v)) => return Ok(::futures::Async::Ready(v)),
            Some(Err(e)) => return Err(e),
        }

        let new_futures = ::std::mem::replace(&mut *self.inner.new_futures.borrow_mut(), Vec::new());
        for future in new_futures {
            let added_idx = self.inner.next_future.get();
            if self.inner.next_future.get() == self.inner.futures.borrow().len() {
                self.inner.futures.borrow_mut().push(Slot::Data(future));
                self.inner.next_future.set(self.inner.next_future.get() + 1);
            } else {
                match ::std::mem::replace(&mut self.inner.futures.borrow_mut()[self.inner.next_future.get()],
                                          Slot::Data(future)) {
                    Slot::Next(next) => self.inner.next_future.set(next),
                    Slot::Data(_) => unreachable!(),
                }
            }

            self.inner.stack.push(added_idx);
        }

        let drain = self.inner.stack.drain();
        for idx in drain {
            match self.inner.futures.borrow_mut()[idx] {
                Slot::Next(_) => continue,
                Slot::Data(ref mut f) => {
                    let event = ::futures::task::UnparkEvent::new(self.inner.stack.clone(), idx);
                    match ::futures::task::with_unpark_event(event, || f.poll()) {
                        Ok(::futures::Async::NotReady) => continue,
                        Ok(::futures::Async::Ready(v)) => {
                            self.inner.reaper.borrow_mut().task_succeeded(v);
                        }
                        Err(e) => {
                            self.inner.reaper.borrow_mut().task_failed(e);
                        }
                    }
                }
            }
            self.inner.futures.borrow_mut()[idx] = Slot::Next(self.inner.next_future.get());
            self.inner.next_future.set(idx);
        }

        if self.inner.futures.borrow().len() == 0 && self.inner.handle_count.get() == 0 {
            Ok(::futures::Async::Ready(()))
        } else {
            let task = ::futures::task::park();
            if self.inner.new_futures.borrow().len() > 0 {
                // Some new futures got added when we called poll().
                task.unpark();
            }
            *self.inner.task.borrow_mut() = Some(task);
            Ok(::futures::Async::NotReady)
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <https://opensource.org/licenses/MIT>

use glib_sys;
use std::mem;
use translate::{StashMut, ToGlibPtrMut, Uninitialized};

pub use glib_sys::GTimeVal as TimeVal;

pub fn get_current_time() -> TimeVal {
    unsafe {
        let mut ret = mem::MaybeUninit::uninit();
        glib_sys::g_get_current_time(ret.as_mut_ptr());
        ret.assume_init()
    }
}

#[doc(hidden)]
impl<'a> ToGlibPtrMut<'a, *mut glib_sys::GTimeVal> for TimeVal {
    type Storage = &'a mut Self;

    fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut glib_sys::GTimeVal, Self> {
        StashMut(self as *mut _, self)
    }
}

impl Uninitialized for TimeVal {
    unsafe fn uninitialized() -> TimeVal {
        mem::zeroed()
    }
}
<commit_msg>Add missing ToGlibPtr implementation<commit_after>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <https://opensource.org/licenses/MIT>

use glib_sys;
use std::mem;
use translate::{Stash, StashMut, ToGlibPtr, ToGlibPtrMut, Uninitialized};

pub use glib_sys::GTimeVal as TimeVal;

pub fn get_current_time() -> TimeVal {
    unsafe {
        let mut ret = mem::MaybeUninit::uninit();
        glib_sys::g_get_current_time(ret.as_mut_ptr());
        ret.assume_init()
    }
}

#[doc(hidden)]
impl<'a> ToGlibPtr<'a, *const glib_sys::GTimeVal> for TimeVal {
    type Storage = &'a Self;

    fn to_glib_none(&'a self) -> Stash<'a, *const glib_sys::GTimeVal, Self> {
        Stash(self as *const _, self)
    }
}

#[doc(hidden)]
impl<'a> ToGlibPtrMut<'a, *mut glib_sys::GTimeVal> for TimeVal {
    type Storage = &'a mut Self;

    fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut glib_sys::GTimeVal, Self> {
        StashMut(self as *mut _, self)
    }
}

impl Uninitialized for TimeVal {
    unsafe fn uninitialized() -> TimeVal {
        mem::zeroed()
    }
}
<|endoftext|>


<commit_before>#![crate_id = "yaml#0.1-pre"]

#![comment = "LibYAML bindings for Rust"]
#![license = "MIT"]
#![crate_type = "dylib"]
#![crate_type = "rlib"]

#![feature(globs)]
#![feature(phase)]

#[cfg(test)]
extern crate debug;

extern crate libc;

#[phase(syntax)]
extern crate regex_macros;
extern crate regex;

use parser::YamlParser;
use constructor::{YamlStandardData, YamlStandardConstructor, YamlConstructor};
use std::result;

pub mod ffi;
pub mod event;
pub mod parser;
pub mod emitter;
pub mod document;
pub mod codecs;
pub mod constructor;

mod type_size;

pub fn version_string() -> String {
    let c_vsn = unsafe {
        std::c_str::CString::new(ffi::yaml_get_version_string(), false)
    };

    c_vsn.as_str().unwrap().to_string()
}

pub fn version() -> (int, int, int) {
    let mut c_major: libc::c_int = 0;
    let mut c_minor: libc::c_int = 0;
    let mut c_patch: libc::c_int = 0;

    unsafe {
        ffi::yaml_get_version(
            &mut c_major as *mut libc::c_int,
            &mut c_minor as *mut libc::c_int,
            &mut c_patch as *mut libc::c_int
        );
    }

    (c_major as int, c_minor as int, c_patch as int)
}

pub fn parse_bytes_utf8(bytes: &[u8]) -> Result<Vec<YamlStandardData>, String> {
    parse_bytes(bytes, ffi::YamlUtf8Encoding)
}

pub fn parse_bytes(bytes: &[u8], encoding: ffi::YamlEncoding) -> Result<Vec<YamlStandardData>, String> {
    let parser = parser::YamlByteParser::init(bytes, encoding);
    let ctor = YamlStandardConstructor::new();

    result::collect(parser.load().map(|doc_res| {
        match doc_res {
            Err(e) => Err(e.to_str()),
            Ok(doc) => ctor.construct(doc.root().unwrap())
        }
    }))
}

pub fn parse_io_utf8(reader: &mut Reader) -> Result<Vec<YamlStandardData>, String> {
    parse_io(reader, ffi::YamlUtf8Encoding)
}

pub fn parse_io(reader: &mut Reader, encoding: ffi::YamlEncoding) -> Result<Vec<YamlStandardData>, String> {
    let parser = parser::YamlIoParser::init(reader, encoding);
    let ctor = YamlStandardConstructor::new();

    result::collect(parser.load().map(|doc_res| {
        match doc_res {
            Err(e) => Err(e.to_str()),
            Ok(doc) => ctor.construct(doc.root().unwrap())
        }
    }))
}

#[cfg(test)]
mod test {
    use std::mem;
    use std::io;
    use constructor::*;

    #[test]
    fn test_version_string() {
        let vsn = super::version_string();
        assert!("0.1.4".to_string() <= vsn && vsn < "0.2".to_string())
    }

    #[test]
    fn test_version() {
        let vsn = super::version();
        assert!((0, 1, 4) <= vsn && vsn < (0, 2, 0))
    }

    #[test]
    fn test_event_size() {
        assert_eq!(super::type_size::yaml_event_t_size, mem::size_of::<super::ffi::yaml_event_t>())
    }

    #[test]
    fn test_parser_size() {
        assert_eq!(super::type_size::yaml_parser_t_size, mem::size_of::<super::ffi::yaml_parser_t>())
    }

    #[test]
    fn test_emitter_size() {
        assert_eq!(super::type_size::yaml_emitter_t_size, mem::size_of::<super::ffi::yaml_emitter_t>())
    }

    #[test]
    fn test_document_size() {
        assert_eq!(super::type_size::yaml_document_t_size, mem::size_of::<super::ffi::yaml_document_t>())
    }

    #[test]
    fn test_node_size() {
        assert_eq!(super::type_size::yaml_node_t_size, mem::size_of::<super::ffi::yaml_node_t>())
    }

    #[test]
    fn test_parse_bytes() {
        let data = "[1, 2, 3]";
        assert_eq!(Ok(vec![YamlSequence(vec![YamlInteger(1), YamlInteger(2), YamlInteger(3)])]), super::parse_bytes_utf8(data.as_bytes()))
    }

    #[test]
    fn test_parse_io() {
        let data = "[1, 2, 3]";
        let mut reader = io::BufReader::new(data.as_bytes());
        assert_eq!(Ok(vec![YamlSequence(vec![YamlInteger(1), YamlInteger(2), YamlInteger(3)])]), super::parse_io_utf8(&mut reader))
    }
}
<commit_msg>Language changes: phase(syntax) -> phase(plugin)<commit_after>#![crate_id = "yaml#0.1-pre"]

#![comment = "LibYAML bindings for Rust"]
#![license = "MIT"]
#![crate_type = "dylib"]
#![crate_type = "rlib"]

#![feature(globs)]
#![feature(phase)]

#[cfg(test)]
extern crate debug;

extern crate libc;

#[phase(plugin)]
extern crate regex_macros;
extern crate regex;

use parser::YamlParser;
use constructor::{YamlStandardData, YamlStandardConstructor, YamlConstructor};
use std::result;

pub mod ffi;
pub mod event;
pub mod parser;
pub mod emitter;
pub mod document;
pub mod codecs;
pub mod constructor;

mod type_size;

pub fn version_string() -> String {
    let c_vsn = unsafe {
        std::c_str::CString::new(ffi::yaml_get_version_string(), false)
    };

    c_vsn.as_str().unwrap().to_string()
}

pub fn version() -> (int, int, int) {
    let mut c_major: libc::c_int = 0;
    let mut c_minor: libc::c_int = 0;
    let mut c_patch: libc::c_int = 0;

    unsafe {
        ffi::yaml_get_version(
            &mut c_major as *mut libc::c_int,
            &mut c_minor as *mut libc::c_int,
            &mut c_patch as *mut libc::c_int
        );
    }

    (c_major as int, c_minor as int, c_patch as int)
}

pub fn parse_bytes_utf8(bytes: &[u8]) -> Result<Vec<YamlStandardData>, String> {
    parse_bytes(bytes, ffi::YamlUtf8Encoding)
}

pub fn parse_bytes(bytes: &[u8], encoding: ffi::YamlEncoding) -> Result<Vec<YamlStandardData>, String> {
    let parser = parser::YamlByteParser::init(bytes, encoding);
    let ctor = YamlStandardConstructor::new();

    result::collect(parser.load().map(|doc_res| {
        match doc_res {
            Err(e) => Err(e.to_str()),
            Ok(doc) => ctor.construct(doc.root().unwrap())
        }
    }))
}

pub fn parse_io_utf8(reader: &mut Reader) -> Result<Vec<YamlStandardData>, String> {
    parse_io(reader, ffi::YamlUtf8Encoding)
}

pub fn parse_io(reader: &mut Reader, encoding: ffi::YamlEncoding) -> Result<Vec<YamlStandardData>, String> {
    let parser = parser::YamlIoParser::init(reader, encoding);
    let ctor = YamlStandardConstructor::new();

    result::collect(parser.load().map(|doc_res| {
        match doc_res {
            Err(e) => Err(e.to_str()),
            Ok(doc) => ctor.construct(doc.root().unwrap())
        }
    }))
}

#[cfg(test)]
mod test {
    use std::mem;
    use std::io;
    use constructor::*;

    #[test]
    fn test_version_string() {
        let vsn = super::version_string();
        assert!("0.1.4".to_string() <= vsn && vsn < "0.2".to_string())
    }

    #[test]
    fn test_version() {
        let vsn = super::version();
        assert!((0, 1, 4) <= vsn && vsn < (0, 2, 0))
    }

    #[test]
    fn test_event_size() {
        assert_eq!(super::type_size::yaml_event_t_size, mem::size_of::<super::ffi::yaml_event_t>())
    }

    #[test]
    fn test_parser_size() {
        assert_eq!(super::type_size::yaml_parser_t_size, mem::size_of::<super::ffi::yaml_parser_t>())
    }

    #[test]
    fn test_emitter_size() {
        assert_eq!(super::type_size::yaml_emitter_t_size, mem::size_of::<super::ffi::yaml_emitter_t>())
    }

    #[test]
    fn test_document_size() {
        assert_eq!(super::type_size::yaml_document_t_size, mem::size_of::<super::ffi::yaml_document_t>())
    }

    #[test]
    fn test_node_size() {
        assert_eq!(super::type_size::yaml_node_t_size, mem::size_of::<super::ffi::yaml_node_t>())
    }

    #[test]
    fn test_parse_bytes() {
        let data = "[1, 2, 3]";
        assert_eq!(Ok(vec![YamlSequence(vec![YamlInteger(1), YamlInteger(2), YamlInteger(3)])]), super::parse_bytes_utf8(data.as_bytes()))
    }

    #[test]
    fn test_parse_io() {
        let data = "[1, 2, 3]";
        let mut reader = io::BufReader::new(data.as_bytes());
        assert_eq!(Ok(vec![YamlSequence(vec![YamlInteger(1), YamlInteger(2), YamlInteger(3)])]), super::parse_io_utf8(&mut reader))
    }
}
<|endoftext|>


<commit_before>// A version of pstree targetting linux written in rust!
//
// This is based on the following exercise from the excellent
// book "The Linux Programming Interface" by Michael Kerridsk.
//
//----------------------------------------------------------------------
//
// Write a program that draws a tree showing the hierarchical
// parent-child relationships of all processes on the system, going all
// the way back to init.  For each process, the program should display
// the process ID and the command being executed.  The output of the
// program should be similar to that produced by pstree(1), although it
// does need not to be as sophisticated.  The parent of each process on
// the system can be found by inspecing the PPid: line of all of the
// /proc/PID/status files on the system.  Be careful to handle the
// possibilty that a process's parent (and thus its /proc/PID directory)
// disappears during the scan of all /proc/PID directories.

// Implementation Notes
// --------------------
// The linux /proc filesystem is a virtual filesystem that provides information
// about processes running on a linux system among other things.  The /proc
// filesystem contains a directory, /proc/<pid>, for each running process in
// the system.
//
// Each process directory has a status file with contents including a bunch
// of different items, notably the process name and its parent process id (ppid).
// And with that information, we can build the process tree.

use std::io::fs::PathExtensions;
use std::io::fs;
use std::io::File;
use std::io::BufferedReader;
use std::fmt;

struct ProcessRecord {
    name: String,
    pid: int,
    ppid: int
}

impl fmt::Show for ProcessRecord {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "ProcessRecord [ name: {}, pid: {}, ppid: {} )",
               self.name,
               self.pid,
               self.ppid)
    }
}

// Given a status file path, return a hashmap with the following form:
// pid -> ProcessRecord
fn get_status_info(status_path: &Path) -> Option<ProcessRecord> {
    let mut pid : Option<int> = None;
    let mut ppid : Option<int> = None;
    let mut name : Option<String> = None;

    let mut status_file = BufferedReader::new(File::open(status_path));
    for line in status_file.lines() {
        let unwrapped = line.unwrap(); // need a new lifeline
        let parts : Vec<&str> = unwrapped.as_slice().splitn(2, ':').collect();
        if parts.len() == 2 {
            let key = parts[0].trim();
            let value = parts[1].trim();
            match key {
                "Name" => name = Some(value.to_string()),
                "Pid" => pid = from_str(value),
                "PPid" => ppid = from_str(value),
                _ => (),
            }
        }
    }

    return if pid.is_some() && ppid.is_some() && name.is_some() {
        Some(ProcessRecord { name: name.unwrap(), pid: pid.unwrap(), ppid: ppid.unwrap() })
    } else {
        None
    }
}

fn dump_process_info() {
    let proc_directory = Path::new("/proc");
    let proc_directory_contents = match fs::readdir(&proc_directory) {
        Err(why) => fail!("{}", why.desc),
        Ok(res) => res
    };
    for entry in proc_directory_contents.iter() {
        if entry.is_dir() {
            let status_path = entry.join("status");
            if status_path.exists() {
                let record = get_status_info(&status_path);
                match record {
                    Some(record) => println!("{}", record),
                    None => ()
                }
            }
        }
    }
}

fn main() {
    dump_process_info();
}
<commit_msg>pstree: It works... it actually works!<commit_after>// A version of pstree targetting linux written in rust!
//
// This is based on the following exercise from the excellent
// book "The Linux Programming Interface" by Michael Kerridsk.
//
//----------------------------------------------------------------------
//
// Write a program that draws a tree showing the hierarchical
// parent-child relationships of all processes on the system, going all
// the way back to init.  For each process, the program should display
// the process ID and the command being executed.  The output of the
// program should be similar to that produced by pstree(1), although it
// does need not to be as sophisticated.  The parent of each process on
// the system can be found by inspecing the PPid: line of all of the
// /proc/PID/status files on the system.  Be careful to handle the
// possibilty that a process's parent (and thus its /proc/PID directory)
// disappears during the scan of all /proc/PID directories.

// Implementation Notes
// --------------------
// The linux /proc filesystem is a virtual filesystem that provides information
// about processes running on a linux system among other things.  The /proc
// filesystem contains a directory, /proc/<pid>, for each running process in
// the system.
//
// Each process directory has a status file with contents including a bunch
// of different items, notably the process name and its parent process id (ppid).
// And with that information, we can build the process tree.

use std::io::fs::PathExtensions;
use std::io::fs;
use std::io::File;
use std::io::BufferedReader;

#[deriving(Clone,Show)]
struct ProcessRecord {
    name: String,
    pid: int,
    ppid: int
}

#[deriving(Clone,Show)]
struct ProcessTreeNode {
    record: ProcessRecord,  // the node owns the associated record
    children: Vec<ProcessTreeNode>, // nodes own their children
}

#[deriving(Clone,Show)]
struct ProcessTree {
    root: ProcessTreeNode, // tree owns ref to root node
}

impl ProcessTreeNode {
    // constructor
    fn new(record : &ProcessRecord) -> ProcessTreeNode {
        ProcessTreeNode { record: (*record).clone(), children: Vec::new() }
    }
}

// Given a status file path, return a hashmap with the following form:
// pid -> ProcessRecord
fn get_process_record(status_path: &Path) -> Option<ProcessRecord> {
    let mut pid : Option<int> = None;
    let mut ppid : Option<int> = None;
    let mut name : Option<String> = None;

    let mut status_file = BufferedReader::new(File::open(status_path));
    for line in status_file.lines() {
        let unwrapped = line.unwrap(); // need a new lifeline
        let parts : Vec<&str> = unwrapped.as_slice().splitn(2, ':').collect();
        if parts.len() == 2 {
            let key = parts[0].trim();
            let value = parts[1].trim();
            match key {
                "Name" => name = Some(value.to_string()),
                "Pid" => pid = from_str(value),
                "PPid" => ppid = from_str(value),
                _ => (),
            }
        }
    }

    return if pid.is_some() && ppid.is_some() && name.is_some() {
        Some(ProcessRecord { name: name.unwrap(), pid: pid.unwrap(), ppid: ppid.unwrap() })
    } else {
        None
    }
}

// build a simple struct (ProcessRecord) for each process
fn get_process_records() -> Vec<ProcessRecord> {
    let mut records : Vec<ProcessRecord> = Vec::new();
    let proc_directory = Path::new("/proc");

    // find potential process directories under /proc
    let proc_directory_contents = match fs::readdir(&proc_directory) {
        Err(why) => fail!("{}", why.desc),
        Ok(res) => res
    };

    for entry in proc_directory_contents.iter().filter(|entry| entry.is_dir()) {
        let status_path = entry.join("status");
        if status_path.exists() {
            match get_process_record(&status_path) {
                Some(record) => records.push(record),
                None => (),
            }
        }
    }
    records
}

fn populate_node(node : &mut ProcessTreeNode, records: &Vec<ProcessRecord>) {
    // populate the node by finding its children... recursively
    let pid = node.record.pid; // avoid binding node as immutable in closure
    for record in records.iter().filter(|record| record.ppid == pid) {
        let mut child = ProcessTreeNode::new(record);
        populate_node(&mut child, records);
        node.children.push(child);
    }
}

fn build_process_tree() -> ProcessTree {
    let records = get_process_records();
    let mut tree = ProcessTree {
        root : ProcessTreeNode::new(
            &ProcessRecord { name: "/".to_string(), pid: 0, ppid: -1 })
    };

    // recursively populate all nodes in the tree starting from root (pid 0)
    {
        let root = &mut tree.root;
        populate_node(root, &records);
    }
    tree
}

fn print_node(node : &ProcessTreeNode, indent_level : int) {
    // print indentation
    for _ in range(0, indent_level * 2) {
        print!(" ");
    }
    println!("- {} #{}", node.record.name, node.record.pid);
    for child in node.children.iter() {
        print_node(child, indent_level + 1);  // recurse
    }
}

fn main() {
    let ptree = build_process_tree();
    print_node(&(ptree.root), 0)
}
<|endoftext|>


<commit_before>//! An enum mapping type.
//!
//! It is implemented using an array type, so using it is as fast as using Rust
//! arrays.
//!
//! # Examples
//!
//! ```
//! use enum_map::{enum_map, Enum, EnumMap};
//!
//! #[derive(Debug, Enum)]
//! enum Example {
//!     A,
//!     B,
//!     C,
//! }
//!
//! fn main() {
//!     let mut map = enum_map! {
//!         Example::A => 1,
//!         Example::B => 2,
//!         Example::C => 3,
//!     };
//!     map[Example::C] = 4;
//!
//!     assert_eq!(map[Example::A], 1);
//!
//!     for (key, &value) in &map {
//!         println!("{:?} has {} as value.", key, value);
//!     }
//! }
//! ```

#![no_std]
#![deny(missing_docs)]

mod enum_map_impls;
mod internal;
mod iter;
mod serde;

pub use enum_map_derive::Enum;
pub use internal::Enum;
pub use iter::{IntoIter, Iter, IterMut, Values, ValuesMut};

/// Enum map constructor.
///
/// This macro allows to create a new enum map in a type safe way. It takes
/// a list of `,` separated pairs separated by `=>`. Left side is `|`
/// separated list of enum keys, or `_` to match all unmatched enum keys,
/// while right side is a value.
///
/// # Examples
///
/// ```
/// # extern crate enum_map;
/// use enum_map::{enum_map, Enum};
///
/// #[derive(Enum)]
/// enum Example {
///     A,
///     B,
///     C,
///     D,
/// }
///
/// fn main() {
///     let enum_map = enum_map! {
///         Example::A | Example::B => 1,
///         Example::C => 2,
///         _ => 3,
///     };
///     assert_eq!(enum_map[Example::A], 1);
///     assert_eq!(enum_map[Example::B], 1);
///     assert_eq!(enum_map[Example::C], 2);
///     assert_eq!(enum_map[Example::D], 3);
/// }
/// ```
#[macro_export]
macro_rules! enum_map {
    {$($t:tt)*} => {
        $crate::__from_fn(|k| match k { $($t)* })
    };
}

/// An enum mapping.
///
/// This internally uses an array which stores a value for each possible
/// enum value. To work, it requires implementation of internal (private,
/// although public due to macro limitations) trait which allows extracting
/// information about an enum, which can be automatically generated using
/// `#[derive(Enum)]` macro.
///
/// Additionally, `bool` and `u8` automatically derives from `Enum`. While
/// `u8` is not technically an enum, it's convenient to consider it like one.
/// In particular, [reverse-complement in benchmark game] could be using `u8`
/// as an enum.
///
/// # Examples
///
/// ```
/// # extern crate enum_map;
/// use enum_map::{enum_map, Enum, EnumMap};
///
/// #[derive(Enum)]
/// enum Example {
///     A,
///     B,
///     C,
/// }
///
/// fn main() {
///     let mut map = EnumMap::new();
///     // new initializes map with default values
///     assert_eq!(map[Example::A], 0);
///     map[Example::A] = 3;
///     assert_eq!(map[Example::A], 3);
/// }
/// ```
///
/// [reverse-complement in benchmark game]:
///     http://benchmarksgame.alioth.debian.org/u64q/program.php?test=revcomp&lang=rust&id=2
pub struct EnumMap<K: Enum<V>, V> {
    array: K::Array,
}

impl<K: Enum<V>, V: Default> EnumMap<K, V> {
    /// Creates an enum map with default values.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate enum_map;
    /// use enum_map::{Enum, EnumMap};
    ///
    /// #[derive(Enum)]
    /// enum Example {
    ///     A,
    /// }
    ///
    /// fn main() {
    ///     let enum_map = EnumMap::<_, i32>::new();
    ///     assert_eq!(enum_map[Example::A], 0);
    /// }
    /// ```
    #[inline]
    pub fn new() -> Self {
        EnumMap::default()
    }
}

impl<K: Enum<V>, V> EnumMap<K, V> {
    /// Returns an iterator over enum map.
    #[inline]
    pub fn iter(&self) -> Iter<K, V> {
        self.into_iter()
    }

    /// Returns a mutable iterator over enum map.
    #[inline]
    pub fn iter_mut(&mut self) -> IterMut<K, V> {
        self.into_iter()
    }

    /// Returns number of elements in enum map.
    #[inline]
    pub fn len(&self) -> usize {
        self.as_slice().len()
    }

    /// Returns whether the enum variant set is empty.
    ///
    /// This isn't particularly useful, as there is no real reason to use
    /// enum map for enums without variants. However, it is provided for
    /// consistency with data structures providing len method (and I will
    /// admit, to avoid clippy warnings).
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate enum_map;
    /// use enum_map::{Enum, EnumMap};
    ///
    /// #[derive(Enum)]
    /// enum Void {}
    ///
    /// #[derive(Enum)]
    /// enum SingleVariant {
    ///     Variant,
    /// }
    ///
    /// fn main() {
    ///     assert!(EnumMap::<Void, ()>::new().is_empty());
    ///     assert!(!EnumMap::<SingleVariant, ()>::new().is_empty());
    /// }
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.as_slice().is_empty()
    }

    /// Swaps two indexes.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate enum_map;
    /// use enum_map::enum_map;
    ///
    /// fn main() {
    ///     let mut map = enum_map! { false => 0, true => 1 };
    ///     map.swap(false, true);
    ///     assert_eq!(map[false], 1);
    ///     assert_eq!(map[true], 0);
    /// }
    /// ```
    #[inline]
    pub fn swap(&mut self, a: K, b: K) {
        self.as_mut_slice().swap(a.to_usize(), b.to_usize())
    }

    /// Converts an enum map to a slice representing values.
    #[inline]
    pub fn as_slice(&self) -> &[V] {
        K::slice(&self.array)
    }

    /// Converts a mutable enum map to a mutable slice representing values.
    #[inline]
    pub fn as_mut_slice(&mut self) -> &mut [V] {
        K::slice_mut(&mut self.array)
    }

    /// Returns a raw pointer to the enum map's slice.
    ///
    /// The caller must ensure that the slice outlives the pointer this
    /// function returns, or else it will end up pointing to garbage.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate enum_map;
    /// use enum_map::{enum_map, EnumMap};
    ///
    /// fn main() {
    ///     let map = enum_map! { 5 => 42, _ => 0 };
    ///     assert_eq!(unsafe { *map.as_ptr().offset(5) }, 42);
    /// }
    /// ```
    #[inline]
    pub fn as_ptr(&self) -> *const V {
        self.as_slice().as_ptr()
    }

    /// Returns an unsafe mutable pointer to the enum map's slice.
    ///
    /// The caller must ensure that the slice outlives the pointer this
    /// function returns, or else it will end up pointing to garbage.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate enum_map;
    /// use enum_map::{enum_map, EnumMap};
    ///
    /// fn main() {
    ///     let mut map = enum_map! { _ => 0 };
    ///     unsafe {
    ///         *map.as_mut_ptr().offset(11) = 23
    ///     };
    ///     assert_eq!(map[11], 23);
    /// }
    /// ```
    #[inline]
    pub fn as_mut_ptr(&mut self) -> *mut V {
        self.as_mut_slice().as_mut_ptr()
    }
}

impl<F: FnMut(K) -> V, K: Enum<V>, V> From<F> for EnumMap<K, V> {
    #[inline]
    fn from(f: F) -> Self {
        EnumMap {
            array: K::from_function(f),
        }
    }
}

#[doc(hidden)]
pub fn __from_fn<K, V>(f: impl FnMut(K) -> V) -> EnumMap<K, V>
where
    K: Enum<V>,
{
    f.into()
}
<commit_msg>Add clear<commit_after>//! An enum mapping type.
//!
//! It is implemented using an array type, so using it is as fast as using Rust
//! arrays.
//!
//! # Examples
//!
//! ```
//! use enum_map::{enum_map, Enum, EnumMap};
//!
//! #[derive(Debug, Enum)]
//! enum Example {
//!     A,
//!     B,
//!     C,
//! }
//!
//! fn main() {
//!     let mut map = enum_map! {
//!         Example::A => 1,
//!         Example::B => 2,
//!         Example::C => 3,
//!     };
//!     map[Example::C] = 4;
//!
//!     assert_eq!(map[Example::A], 1);
//!
//!     for (key, &value) in &map {
//!         println!("{:?} has {} as value.", key, value);
//!     }
//! }
//! ```

#![no_std]
#![deny(missing_docs)]

mod enum_map_impls;
mod internal;
mod iter;
mod serde;

pub use enum_map_derive::Enum;
pub use internal::Enum;
pub use iter::{IntoIter, Iter, IterMut, Values, ValuesMut};

/// Enum map constructor.
///
/// This macro allows to create a new enum map in a type safe way. It takes
/// a list of `,` separated pairs separated by `=>`. Left side is `|`
/// separated list of enum keys, or `_` to match all unmatched enum keys,
/// while right side is a value.
///
/// # Examples
///
/// ```
/// # extern crate enum_map;
/// use enum_map::{enum_map, Enum};
///
/// #[derive(Enum)]
/// enum Example {
///     A,
///     B,
///     C,
///     D,
/// }
///
/// fn main() {
///     let enum_map = enum_map! {
///         Example::A | Example::B => 1,
///         Example::C => 2,
///         _ => 3,
///     };
///     assert_eq!(enum_map[Example::A], 1);
///     assert_eq!(enum_map[Example::B], 1);
///     assert_eq!(enum_map[Example::C], 2);
///     assert_eq!(enum_map[Example::D], 3);
/// }
/// ```
#[macro_export]
macro_rules! enum_map {
    {$($t:tt)*} => {
        $crate::__from_fn(|k| match k { $($t)* })
    };
}

/// An enum mapping.
///
/// This internally uses an array which stores a value for each possible
/// enum value. To work, it requires implementation of internal (private,
/// although public due to macro limitations) trait which allows extracting
/// information about an enum, which can be automatically generated using
/// `#[derive(Enum)]` macro.
///
/// Additionally, `bool` and `u8` automatically derives from `Enum`. While
/// `u8` is not technically an enum, it's convenient to consider it like one.
/// In particular, [reverse-complement in benchmark game] could be using `u8`
/// as an enum.
///
/// # Examples
///
/// ```
/// # extern crate enum_map;
/// use enum_map::{enum_map, Enum, EnumMap};
///
/// #[derive(Enum)]
/// enum Example {
///     A,
///     B,
///     C,
/// }
///
/// fn main() {
///     let mut map = EnumMap::new();
///     // new initializes map with default values
///     assert_eq!(map[Example::A], 0);
///     map[Example::A] = 3;
///     assert_eq!(map[Example::A], 3);
/// }
/// ```
///
/// [reverse-complement in benchmark game]:
///     http://benchmarksgame.alioth.debian.org/u64q/program.php?test=revcomp&lang=rust&id=2
pub struct EnumMap<K: Enum<V>, V> {
    array: K::Array,
}

impl<K: Enum<V>, V: Default> EnumMap<K, V> {
    /// Creates an enum map with default values.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate enum_map;
    /// use enum_map::{Enum, EnumMap};
    ///
    /// #[derive(Enum)]
    /// enum Example {
    ///     A,
    /// }
    ///
    /// fn main() {
    ///     let enum_map = EnumMap::<_, i32>::new();
    ///     assert_eq!(enum_map[Example::A], 0);
    /// }
    /// ```
    #[inline]
    pub fn new() -> Self {
        EnumMap::default()
    }

    /// Clear enum map with default values.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate enum_map;
    /// use enum_map::{Enum, EnumMap};
    ///
    /// #[derive(Enum)]
    /// enum Example {
    ///     A,
    ///     B,
    /// }
    ///
    /// fn main() {
    ///     let mut enum_map = EnumMap::<_, String>::new();
    ///     enum_map[Example::B] = "foo".into();
    ///     enum_map.clear();
    ///     assert_eq!(enum_map[Example::A], "");
    ///     assert_eq!(enum_map[Example::B], "");
    /// }
    /// ```
    #[inline]
    pub fn clear(&mut self) {
        for v in self.as_mut_slice() {
            *v = V::default();
        }
    }
}

impl<K: Enum<V>, V> EnumMap<K, V> {
    /// Returns an iterator over enum map.
    #[inline]
    pub fn iter(&self) -> Iter<K, V> {
        self.into_iter()
    }

    /// Returns a mutable iterator over enum map.
    #[inline]
    pub fn iter_mut(&mut self) -> IterMut<K, V> {
        self.into_iter()
    }

    /// Returns number of elements in enum map.
    #[inline]
    pub fn len(&self) -> usize {
        self.as_slice().len()
    }

    /// Returns whether the enum variant set is empty.
    ///
    /// This isn't particularly useful, as there is no real reason to use
    /// enum map for enums without variants. However, it is provided for
    /// consistency with data structures providing len method (and I will
    /// admit, to avoid clippy warnings).
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate enum_map;
    /// use enum_map::{Enum, EnumMap};
    ///
    /// #[derive(Enum)]
    /// enum Void {}
    ///
    /// #[derive(Enum)]
    /// enum SingleVariant {
    ///     Variant,
    /// }
    ///
    /// fn main() {
    ///     assert!(EnumMap::<Void, ()>::new().is_empty());
    ///     assert!(!EnumMap::<SingleVariant, ()>::new().is_empty());
    /// }
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.as_slice().is_empty()
    }

    /// Swaps two indexes.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate enum_map;
    /// use enum_map::enum_map;
    ///
    /// fn main() {
    ///     let mut map = enum_map! { false => 0, true => 1 };
    ///     map.swap(false, true);
    ///     assert_eq!(map[false], 1);
    ///     assert_eq!(map[true], 0);
    /// }
    /// ```
    #[inline]
    pub fn swap(&mut self, a: K, b: K) {
        self.as_mut_slice().swap(a.to_usize(), b.to_usize())
    }

    /// Converts an enum map to a slice representing values.
    #[inline]
    pub fn as_slice(&self) -> &[V] {
        K::slice(&self.array)
    }

    /// Converts a mutable enum map to a mutable slice representing values.
    #[inline]
    pub fn as_mut_slice(&mut self) -> &mut [V] {
        K::slice_mut(&mut self.array)
    }

    /// Returns a raw pointer to the enum map's slice.
    ///
    /// The caller must ensure that the slice outlives the pointer this
    /// function returns, or else it will end up pointing to garbage.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate enum_map;
    /// use enum_map::{enum_map, EnumMap};
    ///
    /// fn main() {
    ///     let map = enum_map! { 5 => 42, _ => 0 };
    ///     assert_eq!(unsafe { *map.as_ptr().offset(5) }, 42);
    /// }
    /// ```
    #[inline]
    pub fn as_ptr(&self) -> *const V {
        self.as_slice().as_ptr()
    }

    /// Returns an unsafe mutable pointer to the enum map's slice.
    ///
    /// The caller must ensure that the slice outlives the pointer this
    /// function returns, or else it will end up pointing to garbage.
    ///
    /// # Examples
    ///
    /// ```
    /// # extern crate enum_map;
    /// use enum_map::{enum_map, EnumMap};
    ///
    /// fn main() {
    ///     let mut map = enum_map! { _ => 0 };
    ///     unsafe {
    ///         *map.as_mut_ptr().offset(11) = 23
    ///     };
    ///     assert_eq!(map[11], 23);
    /// }
    /// ```
    #[inline]
    pub fn as_mut_ptr(&mut self) -> *mut V {
        self.as_mut_slice().as_mut_ptr()
    }
}

impl<F: FnMut(K) -> V, K: Enum<V>, V> From<F> for EnumMap<K, V> {
    #[inline]
    fn from(f: F) -> Self {
        EnumMap {
            array: K::from_function(f),
        }
    }
}

#[doc(hidden)]
pub fn __from_fn<K, V>(f: impl FnMut(K) -> V) -> EnumMap<K, V>
where
    K: Enum<V>,
{
    f.into()
}
<|endoftext|>