<commit_before>extern crate term_painter;

use term_painter::{ToStyle, Color};
use term_painter::Color::*;
use term_painter::Attr::*;

fn main() {
    simple_examples();
    with_example();
    doc_examples();

    all_styles(
        &[Normal, Black, Red, Green, Yellow, Blue, Magenta, Cyan, White]);
    all_styles(
        &[BrightBlack, BrightRed, BrightGreen, BrightYellow, BrightBlue,
         BrightMagenta, BrightCyan, BrightWhite]);
}

fn simple_examples() {
    println!("{} | {} | {} | {} | {}",
        Red.bg(Green).bold().paint("Red-Green-Bold"),
        Blue.paint("Blue"),
        Blue.bold().paint("BlueBold"),
        Blue.bg(Magenta).paint("BlueMagentaBG"),
        Plain.underline().paint("Underline"));
}

fn with_example() {
    Red.with(|| {
         print!("JustRed");
         Bold.with(|| {
             print!(" BoldRed {} BoldRed ", Underline.paint("Underline"));
         });
         print!("JustRed ");

         print!("{}", Blue.paint("Blue (overwrite) "));
         Green.with(|| {
             println!("Green (overwrite)");
         });
     });
}

fn doc_examples() {
    // --- Doc example 1
    println!("{} or {} or {}",
        Red.paint("Red"),
        Bold.paint("Bold"),
        Red.bold().paint("Both!"));

    // --- Doc example 2
    let x = 5;

    // These two are equivalent
    println!("{} | {}", x, Plain.paint(x));

    // These two are equivalent, too
    println!("{} | {}", Red.paint(x), Plain.fg(Red).paint(x));

    // --- Doc example 3
    let non_copy = "cake".to_string();  // String is *not* Copy
    let copy = 27;  // usize/isize *is* Copy

    println!("{}", Plain.paint(&non_copy));
    println!("{}", Plain.paint(&copy));
    // non_copy is still usable here...
    // copy is still usable here...

    println!("{}", Plain.paint(non_copy));
    println!("{}", Plain.paint(copy));
    // non_copy was moved into paint, so it not usable anymore...
    // copy is still usable here...
}

fn all_styles(colors: &[Color]) {
    // Normal test
    for c in colors { print!("{:?} ", c.paint(c)); }
    println!("    (fg)");
    for c in colors { print!("{:?} ", Plain.bg(*c).paint(c)); }
    println!("    (bg)");

    // Bold text
    for c in colors { print!("{:?} ", c.bold().paint(c)); }
    println!("    (bold fg)");
    for c in colors { print!("{:?} ", Bold.bg(*c).paint(c)); }
    println!("    (bold bg)");

    // Dim text
    for c in colors { print!("{:?} ", c.dim().paint(c)); }
    println!("    (dim fg)");
    for c in colors { print!("{:?} ", Dim.bg(*c).paint(c)); }
    println!("    (dim bg)");

    // Underlined text
    for c in colors { print!("{:?} ", c.underline().paint(c)); }
    println!("    (underline fg)");
    for c in colors { print!("{:?} ", Underline.bg(*c).paint(c)); }
    println!("    (underline bg)");

    // Blinking text
    for c in colors { print!("{:?} ", c.blink().paint(c)); }
    println!("    (blink fg)");
    for c in colors { print!("{:?} ", Blink.bg(*c).paint(c)); }
    println!("    (blink bg)");

    // Reverse text
    for c in colors { print!("{:?} ", c.reverse().paint(c)); }
    println!("    (reverse fg)");
    for c in colors { print!("{:?} ", Reverse.bg(*c).paint(c)); }
    println!("    (reverse bg)");

    // Secure text
    for c in colors { print!("{:?} ", c.secure().paint(c)); }
    println!("    (secure fg)");
    for c in colors { print!("{:?} ", Secure.bg(*c).paint(c)); }
    println!("    (secure bg)");

}
<commit_msg>Example: Add function to print byte sizes of used structs and enums<commit_after>extern crate term_painter;

use term_painter::{ToStyle, Color};
use term_painter::Color::*;
use term_painter::Attr::*;

fn main() {
    struct_sizes();

    simple_examples();
    with_example();
    doc_examples();

    all_styles(
        &[Normal, Black, Red, Green, Yellow, Blue, Magenta, Cyan, White]);
    all_styles(
        &[BrightBlack, BrightRed, BrightGreen, BrightYellow, BrightBlue,
         BrightMagenta, BrightCyan, BrightWhite]);
}

fn struct_sizes() {
    use std::mem::size_of;

    println!("size_of(Style): {}", size_of::<term_painter::Style>());
    println!("size_of(Color): {}", size_of::<Color>());
    println!("size_of(Attr):  {}", size_of::<term_painter::Attr>());
}

fn simple_examples() {
    println!("{} | {} | {} | {} | {}",
        Red.bg(Green).bold().paint("Red-Green-Bold"),
        Blue.paint("Blue"),
        Blue.bold().paint("BlueBold"),
        Blue.bg(Magenta).paint("BlueMagentaBG"),
        Plain.underline().paint("Underline"));
}

fn with_example() {
    Red.with(|| {
         print!("JustRed");
         Bold.with(|| {
             print!(" BoldRed {} BoldRed ", Underline.paint("Underline"));
         });
         print!("JustRed ");

         print!("{}", Blue.paint("Blue (overwrite) "));
         Green.with(|| {
             println!("Green (overwrite)");
         });
     });
}

fn doc_examples() {
    // --- Doc example 1
    println!("{} or {} or {}",
        Red.paint("Red"),
        Bold.paint("Bold"),
        Red.bold().paint("Both!"));

    // --- Doc example 2
    let x = 5;

    // These two are equivalent
    println!("{} | {}", x, Plain.paint(x));

    // These two are equivalent, too
    println!("{} | {}", Red.paint(x), Plain.fg(Red).paint(x));

    // --- Doc example 3
    let non_copy = "cake".to_string();  // String is *not* Copy
    let copy = 27;  // usize/isize *is* Copy

    println!("{}", Plain.paint(&non_copy));
    println!("{}", Plain.paint(&copy));
    // non_copy is still usable here...
    // copy is still usable here...

    println!("{}", Plain.paint(non_copy));
    println!("{}", Plain.paint(copy));
    // non_copy was moved into paint, so it not usable anymore...
    // copy is still usable here...
}

fn all_styles(colors: &[Color]) {
    // Normal test
    for c in colors { print!("{:?} ", c.paint(c)); }
    println!("    (fg)");
    for c in colors { print!("{:?} ", Plain.bg(*c).paint(c)); }
    println!("    (bg)");

    // Bold text
    for c in colors { print!("{:?} ", c.bold().paint(c)); }
    println!("    (bold fg)");
    for c in colors { print!("{:?} ", Bold.bg(*c).paint(c)); }
    println!("    (bold bg)");

    // Dim text
    for c in colors { print!("{:?} ", c.dim().paint(c)); }
    println!("    (dim fg)");
    for c in colors { print!("{:?} ", Dim.bg(*c).paint(c)); }
    println!("    (dim bg)");

    // Underlined text
    for c in colors { print!("{:?} ", c.underline().paint(c)); }
    println!("    (underline fg)");
    for c in colors { print!("{:?} ", Underline.bg(*c).paint(c)); }
    println!("    (underline bg)");

    // Blinking text
    for c in colors { print!("{:?} ", c.blink().paint(c)); }
    println!("    (blink fg)");
    for c in colors { print!("{:?} ", Blink.bg(*c).paint(c)); }
    println!("    (blink bg)");

    // Reverse text
    for c in colors { print!("{:?} ", c.reverse().paint(c)); }
    println!("    (reverse fg)");
    for c in colors { print!("{:?} ", Reverse.bg(*c).paint(c)); }
    println!("    (reverse bg)");

    // Secure text
    for c in colors { print!("{:?} ", c.secure().paint(c)); }
    println!("    (secure fg)");
    for c in colors { print!("{:?} ", Secure.bg(*c).paint(c)); }
    println!("    (secure bg)");

}
<|endoftext|>


<commit_before>extern crate pty;
extern crate libc;
extern crate errno;

use pty::fork::*;
use std::ffi;
use std::io::Read;
use std::ptr;

fn main() {
    let fork = Fork::from_ptmx().unwrap();

    if let Some(mut master) = fork.is_parent().ok() {
        // Read output via PTY master
        let mut output = String::new();

        match master.read_to_string(&mut output) {
            Ok(_nread) => println!("child tty is: {}", output.trim()),
            Err(e) => panic!("read error: {}", e),
        }
    } else {
        // Child process just exec `tty`
        let cmd = ffi::CString::new("tty").unwrap();
        let mut args: Vec<*const libc::c_char> = Vec::with_capacity(1);

        args.push(cmd.as_ptr());
        args.push(ptr::null());
        unsafe {
            if libc::execvp(cmd.as_ptr(), args.as_mut_ptr()).eq(&-1) {
                panic!("{}: {}", cmd.to_string_lossy(), ::errno::errno());
            }
        };
    }
}
<commit_msg>switch to Command::new so it consistent with other examples/tests<commit_after>extern crate pty;
extern crate libc;
extern crate errno;

use pty::fork::*;
use std::io::Read;
use std::process::{Command};

fn main() {
    let fork = Fork::from_ptmx().unwrap();

    if let Some(mut master) = fork.is_parent().ok() {
        // Read output via PTY master
        let mut output = String::new();

        match master.read_to_string(&mut output) {
            Ok(_nread) => println!("child tty is: {}", output.trim()),
            Err(e) => panic!("read error: {}", e),
        }
    } else {
        // Child process just exec `tty`
        Command::new("tty").status().expect("could not execute tty");
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate korome;

use korome::*;
use std::rc::Rc;

fn main() {
    let graphics = Graphics::new("Menu example!", 800, 600);

    let menu_state = Menu {
        planet: Rc::new(include_texture!(graphics, "assets/planet.png").unwrap()),
        start_game: include_texture!(graphics, "assets/start_game.png").unwrap()
    };

    let mut gm = GameManager::new(graphics);
    gm.run(Box::new(menu_state));
}

use korome::StateAction::*;

impl State for Menu{
    fn frame(&mut self, closed: bool, info: FrameInfo, mut drawer: Drawer) -> StateAction{
        if closed{
            Close
        }else{
            drawer.clear(0., 0., 0.);
            drawer.draw_texture_rigid(&self.start_game, 0., 0.).unwrap();

            for &e in info.get_mouse_events(){
                if let (true, MouseButton::Left) = e{
                    if info.mousepos.0 <= 100. && info.mousepos.0 >= -100. && info.mousepos.1 <= 25. && info.mousepos.1 >= -25.{
                        return ChangeTo(Box::new(Game{
                            planet: self.planet.clone(),
                            pos: Vector2(0., 0.)
                        }))
                    }
                }
            }
            Continue
        }
    }
}

struct Menu{
    planet    : Rc<Texture>,
    start_game: Texture
}

struct Game{
    planet: Rc<Texture>,
    pos: Vector2<f32>,
}

impl State for Game{
    fn frame(&mut self, closed: bool, info: FrameInfo, mut drawer: Drawer) -> StateAction{
        if closed{
            Close
        }else{
            drawer.clear(0., 0., 0.);
            drawer.draw_texture_rigid(&self.planet, self.pos.0, self.pos.1).unwrap();

            let vel = 100. * info.delta as f32;

            is_down!{info;
                A, Left => {
                    self.pos.0 -= vel
                },
                D, Right => {
                    self.pos.0 += vel
                },
                S, Down => {
                    self.pos.1 -= vel
                },
                W, Up => {
                    self.pos.1 += vel
                }
            }

            Continue
        }
    }
}
<commit_msg>Use closures in the example<commit_after>#[macro_use]
extern crate korome;

use korome::*;
use korome::StateAction::*;

use std::rc::Rc;

fn main() {
    let graphics = Graphics::new("Menu example!", 800, 600);

    let planet = Rc::new(include_texture!(graphics, "assets/planet.png").unwrap());
    let start_game = include_texture!(graphics, "assets/start_game.png").unwrap();

    let mut gm = GameManager::new(graphics);

    gm.run(Box::new(move|closed, info: FrameInfo, mut drawer: Drawer|{
        if closed{
            Close
        }else{
            drawer.clear(0., 0., 0.);
            drawer.draw_texture_rigid(&start_game, 0., 0.).unwrap();

            for &e in info.get_mouse_events(){
                if let (true, MouseButton::Left) = e{
                    if info.mousepos.0 <= 100. && info.mousepos.0 >= -100. && info.mousepos.1 <= 25. && info.mousepos.1 >= -25.{
                        let mut pos = Vector2(0., 0.);
                        let pl = planet.clone();

                        return ChangeTo(Box::new(move|closed, info: FrameInfo, mut drawer: Drawer|{
                            if closed{
                                Close
                            }else{
                                drawer.clear(0., 0., 0.);
                                drawer.draw_texture_rigid(&pl, pos.0, pos.1).unwrap();

                                let vel = 100. * info.delta as f32;

                                is_down!{info;
                                    A, Left => {
                                        pos.0 -= vel
                                    },
                                    D, Right => {
                                        pos.0 += vel
                                    },
                                    S, Down => {
                                        pos.1 -= vel
                                    },
                                    W, Up => {
                                        pos.1 += vel
                                    }
                                }

                                Continue
                            }
                        }))
                    }
                }
            }
            Continue
        }
    }));
}
<|endoftext|>


<commit_before>use std::hash::{hash,Hash};
use std::collections::HashMap;
use std::thunk::Invoke;
use std::mem::replace;
//use std::sync::Arc;
use std::cell::RefCell;
use std::rc::Rc;

// "One big memo table" design

pub trait Adapton {
    fn new () -> Self ;

    // Names
    fn name_of_string (self:&mut Self, String) -> Name ;
    fn name_of_u64 (self:&mut Self, u64) -> Name ;
    fn name_pair (self: &Self, Name, Name) -> Name ;
    fn name_fork (self:&mut Self, Name) -> (Name, Name) ;

    fn ns<T,F> (self: &mut Self, Name, body:F) -> T
        where F:FnOnce(&mut Self) -> T ;

    fn put<T:Eq> (self:&mut Self, T) -> Art<T> ;

    // Mutable cells
    fn cell<T:Eq> (self:&mut Self, ArtId, T) -> MutArt<T> ;
    fn set<T:Eq> (self:&mut Self, MutArt<T>) ;

    fn thunk<Arg:Eq+Hash,T:Eq>
        (self:&mut Self, id:ArtId,
         fn_body:Box<Invoke<Arg, T> + 'static>, arg:Arg) -> Art<T> ;

    fn force<T:Eq> (self:&mut Self, Art<T>) -> T ;
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Lineage {
    Unknown, Structural,
    Root,
    Pair(Rc<Lineage>,Rc<Lineage>),
    ForkL(Rc<Lineage>),
    ForkR(Rc<Lineage>),
    String(String),
    U64(u64),
    Rc(Rc<Lineage>),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Path {
    Empty,
    Child(Rc<Path>,Name),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub struct Name {
    hash : u64,
    lineage : Rc<Lineage>,
}

#[derive(Hash,Show,PartialEq,Eq)]
pub struct Loc {
    hash : u64,
    name : Rc<Name>,
    path : Rc<Path>
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum ArtId {
    None,
    Structural(u64),
    Nominal(Name),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Art<T> {
    Box(Box<T>),
    Loc(Rc<Loc>),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum MutArt<T> {
    MutArt(Art<T>)
}

enum Node<T> {
    Pure(PureNode<T>),
    Mut(MutNode<T>),
    Compute(ComputeNode<T>),
}

struct PureNode<T> {
    loc : Rc<Loc>,
    val : T,
}

struct MutNode<T> {
    loc : Rc<Loc>,
    dem_precs : Vec<DemPrec>,
    val : RefCell<T>,
}

trait Body<T> {
    fn run (self:&Self, st:&mut AdaptonState) -> T ;
}

struct ComputeNode<T> {
    loc : Rc<Loc>,
    dem_precs : Vec<DemPrec>,
    dem_succs : Vec<DemSucc>,
    body : Box<Body<T> + 'static>, // Trait in Type: Need lifetime.
    val  : RefCell<Option<T>>,
}

struct DemPrec {
    loc : Rc<Loc>,
}

struct DemSucc {
    loc : Rc<Loc>,
    dirty : RefCell<bool>
}

pub struct AdaptonState {
    memo_table : HashMap<Rc<Loc>, *mut ()>, // memo table
    curr_path : Rc<Path>, // current_namespace
    curr_name : Rc<Name>, // current articulation point
}

impl Adapton for AdaptonState {
    fn new () -> AdaptonState {
        let empty = Rc::new(Path::Empty);
        let root = Rc::new(Name{hash:0, lineage:Rc::new(Lineage::Root) });
        AdaptonState {
            memo_table : HashMap::new (),
            curr_path : empty,
            curr_name : root,
        }
    }
    fn name_of_string (self:&mut AdaptonState, sym:String) -> Name {
        let h = hash::<_>(&sym) ;
        let s = Lineage::String(sym) ;
        Name{ hash:h, lineage:Rc::new(s) }
    }
    fn name_of_u64 (self:&mut AdaptonState, sym:u64) -> Name {
        let h = hash::<_>(&sym) ;
        let s = Lineage::U64(sym) ;
        Name{ hash:h, lineage:Rc::new(s) }
    }
    fn name_pair (self: &AdaptonState, fst: Name, snd: Name) -> Name {
        let h = hash::<_>( &(fst.hash,snd.hash) ) ;
        let p = Lineage::Pair(fst.lineage, snd.lineage) ;
        Name{ hash:h, lineage:Rc::new(p) }
    }
    fn name_fork (self:&mut AdaptonState, nm:Name) -> (Name, Name) {
        let h1 = hash::<_>( &(&nm, 11111111) ) ; // TODO: make this hashing better.
        let h2 = hash::<_>( &(&nm, 22222222) ) ;
        ( Name{ hash:h1,
                lineage:Rc::new(Lineage::ForkL(nm.lineage.clone())) } ,
          Name{ hash:h2,
                lineage:Rc::new(Lineage::ForkR(nm.lineage)) } )
    }
    fn ns<T,F> (self: &mut Self, nm:Name, body:F) -> T where F:FnOnce(&mut Self) -> T {
        let path_body = Rc::new(Path::Child(self.curr_path.clone(), nm)) ;
        let path_pre = replace(&mut self.curr_path, path_body ) ;
        let x = body(self) ;
        let path_body = replace(&mut self.curr_path, path_pre) ;
        drop(path_body);
        x
    }
    fn put<T:Eq> (self:&mut AdaptonState, x:T) -> Art<T> {
        Art::Box(box x)
    }
    fn cell<T:Eq> (self:&mut AdaptonState, id:ArtId, x:T) -> MutArt<T> {
        panic!("")
    }
    fn set<T:Eq> (self:&mut Self, cell:MutArt<T>) {
        panic!("")
    }
    fn thunk<Arg:Eq+Hash,T:Eq>
        (self:&mut AdaptonState,
         id:ArtId, fn_body:Box<Invoke<Arg,T>+'static>, arg:Arg) -> Art<T>
    {
        panic!("")
    }
    fn force<T:Eq> (self:&mut AdaptonState, art:Art<T>) -> T {
        match art {
            Art::Box(b) => *b,
            Art::Loc(l) => panic!(""),
        }
    }
}

pub fn main () {

}
<commit_msg>implemented set and force for mutable cells; still need dirtying traversal; thinking about thunks next<commit_after>use std::fmt::Show;
use std::hash::{hash,Hash};
use std::collections::HashMap;
use std::thunk::Invoke;
use std::mem::replace;
//use std::sync::Arc;
use std::rc::Rc;

// "One big memo table" design

pub trait Adapton {
    fn new () -> Self ;

    // Names
    fn name_of_string (self:&mut Self, String) -> Name ;
    fn name_of_u64 (self:&mut Self, u64) -> Name ;
    fn name_pair (self: &Self, Name, Name) -> Name ;
    fn name_fork (self:&mut Self, Name) -> (Name, Name) ;

    fn ns<T,F> (self: &mut Self, Name, body:F) -> T
        where F:FnOnce(&mut Self) -> T ;

    fn put<T:Eq+Clone+Show> (self:&mut Self, T) -> Art<T> ;

    // Mutable cells
    fn cell<T:Eq+Clone+Show> (self:&mut Self, ArtId, T) -> MutArt<T> ;
    fn set<T:Eq+Clone+Show> (self:&mut Self, MutArt<T>, T) ;

    fn thunk<Arg:Eq+Hash+Clone+Show,T:Eq+Clone+Show>
        (self:&mut Self, id:ArtId,
         fn_body:Box<Invoke<Arg, T> + 'static>, arg:Arg) -> Art<T> ;

    fn force<T:Eq+Clone+Show> (self:&mut Self, Art<T>) -> T ;
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Lineage {
    Unknown, Structural,
    Root,
    Pair(Rc<Lineage>,Rc<Lineage>),
    ForkL(Rc<Lineage>),
    ForkR(Rc<Lineage>),
    String(String),
    U64(u64),
    Rc(Rc<Lineage>),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Path {
    Empty,
    Child(Rc<Path>,Name),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub struct Name {
    hash : u64,
    lineage : Rc<Lineage>,
}

#[derive(Hash,Show,PartialEq,Eq)]
pub struct Loc {
    hash : u64,
    name : Rc<Name>,
    path : Rc<Path>
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum ArtId {
    None,
    Structural(u64),
    Nominal(Name),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum Art<T> {
    Box(Box<T>),
    Loc(Rc<Loc>),
}

#[derive(Hash,Show,PartialEq,Eq)]
pub enum MutArt<T> {
    MutArt(Art<T>)
}

#[derive(Show)]
enum Node<T> {
    Pure(PureNode<T>),
    Mut(MutNode<T>),
    Compute(ComputeNode<T>),
}

#[derive(Show)]
struct PureNode<T> {
    loc : Rc<Loc>,
    val : T,
}

#[derive(Show)]
struct MutNode<T> {
    loc : Rc<Loc>,
    dem_precs : Vec<DemPrec>,
    val : T,
}

#[derive(Show)]
struct ComputeNode<T> {
    loc : Rc<Loc>,
    dem_precs : Vec<DemPrec>,
    dem_succs : Vec<DemSucc>,
    val  : Option<T>,
}

#[derive(Show)]
struct DemPrec {
    loc : Rc<Loc>,
}

#[derive(Show)]
struct DemSucc {
    loc : Rc<Loc>,
    dirty : bool
}

pub struct AdaptonState {
    memo_table : HashMap<Rc<Loc>, *mut ()>, // memo table
    curr_path : Rc<Path>, // current_namespace
    curr_name : Rc<Name>, // current articulation point
}

impl Adapton for AdaptonState {
    fn new () -> AdaptonState {
        let empty = Rc::new(Path::Empty);
        let root = Rc::new(Name{hash:0, lineage:Rc::new(Lineage::Root) });
        AdaptonState {
            memo_table : HashMap::new (),
            curr_path : empty,
            curr_name : root,
        }
    }
    fn name_of_string (self:&mut AdaptonState, sym:String) -> Name {
        let h = hash::<_>(&sym) ;
        let s = Lineage::String(sym) ;
        Name{ hash:h, lineage:Rc::new(s) }
    }
    fn name_of_u64 (self:&mut AdaptonState, sym:u64) -> Name {
        let h = hash::<_>(&sym) ;
        let s = Lineage::U64(sym) ;
        Name{ hash:h, lineage:Rc::new(s) }
    }
    fn name_pair (self: &AdaptonState, fst: Name, snd: Name) -> Name {
        let h = hash::<_>( &(fst.hash,snd.hash) ) ;
        let p = Lineage::Pair(fst.lineage, snd.lineage) ;
        Name{ hash:h, lineage:Rc::new(p) }
    }
    fn name_fork (self:&mut AdaptonState, nm:Name) -> (Name, Name) {
        let h1 = hash::<_>( &(&nm, 11111111) ) ; // TODO: make this hashing better.
        let h2 = hash::<_>( &(&nm, 22222222) ) ;
        ( Name{ hash:h1,
                lineage:Rc::new(Lineage::ForkL(nm.lineage.clone())) } ,
          Name{ hash:h2,
                lineage:Rc::new(Lineage::ForkR(nm.lineage)) } )
    }
    fn ns<T,F> (self: &mut Self, nm:Name, body:F) -> T where F:FnOnce(&mut Self) -> T {
        let path_body = Rc::new(Path::Child(self.curr_path.clone(), nm)) ;
        let path_pre = replace(&mut self.curr_path, path_body ) ;
        let x = body(self) ;
        let path_body = replace(&mut self.curr_path, path_pre) ;
        drop(path_body);
        x
    }
    fn put<T:Eq> (self:&mut AdaptonState, x:T) -> Art<T> {
        Art::Box(box x)
    }
    fn cell<T:Eq+Clone+Show> (self:&mut AdaptonState, id:ArtId, x:T) -> MutArt<T> {
        match id {
            ArtId::None => panic!(""),
            ArtId::Structural(hash) => {
                let loc = Loc{hash:hash,
                              name:Rc::new(Name{hash:hash,
                                                lineage:Rc::new(Lineage::Structural)}),
                              path:self.curr_path.clone()} ;
                MutArt::MutArt(Art::Loc(Rc::new(loc)))
            }
            ArtId::Nominal(nm) => {
                let loc = Loc{hash:nm.hash,
                              name:Rc::new(nm),
                              path:self.curr_path.clone()} ;
                MutArt::MutArt(Art::Loc(Rc::new(loc)))
            }
        }
    }
    fn set<T:Eq+Clone+Show> (self:&mut Self, cell:MutArt<T>, val:T) {
        match cell {
            MutArt::MutArt(Art::Box(b)) => {
                panic!("cannot set pure value");
            }
            MutArt::MutArt(Art::Loc(loc)) => {
                let node = self.memo_table.get(&loc) ;
                match node {
                    None => panic!("dangling pointer: {}", loc),
                    Some(ptr) => {
                        let node : &mut MutNode<T> = unsafe {
                            let node = std::mem::transmute::<*mut (), *mut Node<T>>(*ptr) ;
                            match *node {
                                Node::Mut(ref mut nd) => nd,
                                ref nd => panic!("impossible: {}", nd)
                            }} ;
                        if (node.val == val) {
                            // Nothing.
                        }
                        else {
                            node.val = val;
                            // TODO: Dirty traversal. Notify/mark demand precs.
                        }
                    }
                }
            }
        }
    }
    fn thunk<Arg:Eq+Hash+Clone+Show,T:Eq+Clone+Show>
        (self:&mut AdaptonState,
         id:ArtId, fn_body:Box<Invoke<Arg,T>+'static>, arg:Arg) -> Art<T>
    {
        panic!("")
    }
    fn force<T:Eq+Clone+Show> (self:&mut AdaptonState, art:Art<T>) -> T {
        match art {
            Art::Box(b) => *b,
            Art::Loc(loc) => {
                let node = self.memo_table.get(&loc) ;
                match node {
                    None => panic!("dangling pointer: {}", loc),
                    Some(ptr) => {
                        let node : &mut Node<T> = unsafe {
                            let node = std::mem::transmute::<*mut (), *mut Node<T>>(*ptr) ;
                            &mut ( *node ) } ;
                        match *node {
                            Node::Pure(ref mut nd) => {
                                nd.val.clone()
                            }
                            Node::Mut(ref mut nd) => {
                                // TODO: Record dependency edge
                                nd.val.clone()
                            }
                            Node::Compute(ref mut nd) => {
                                panic!("TODO")
                            }
                        }
                    }
                }
            }
        }
    }
}

pub fn main () {

}
<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Interfaces to the operating system provided random number
//! generators.

pub use self::imp::OSRng;

#[cfg(unix)]
mod imp {
    use Rng;
    use reader::ReaderRng;
    use std::io::{IoResult, File};

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    ///
    /// This does not block.
    #[cfg(unix)]
    pub struct OSRng {
        inner: ReaderRng<File>
    }

    impl OSRng {
        /// Create a new `OSRng`.
        pub fn new() -> IoResult<OSRng> {
            let reader = try!(File::open(&Path::new("/dev/urandom")));
            let reader_rng = ReaderRng::new(reader);

            Ok(OSRng { inner: reader_rng })
        }
    }

    impl Rng for OSRng {
        fn next_u32(&mut self) -> u32 {
            self.inner.next_u32()
        }
        fn next_u64(&mut self) -> u64 {
            self.inner.next_u64()
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            self.inner.fill_bytes(v)
        }
    }
}

#[cfg(windows)]
mod imp {
    use Rng;
    use std::cast;
    use std::io::{IoResult, IoError};
    use std::libc::{c_ulong, DWORD, BYTE, LPCSTR, BOOL};
    use std::os;
    use std::rt::stack;

    type HCRYPTPROV = c_ulong;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    ///
    /// This does not block.
    pub struct OSRng {
        hcryptprov: HCRYPTPROV
    }

    static PROV_RSA_FULL: DWORD = 1;
    static CRYPT_SILENT: DWORD = 64;
    static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;
    static NTE_BAD_SIGNATURE: DWORD = 0x80090006;

    extern "system" {
        fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
                                pszContainer: LPCSTR,
                                pszProvider: LPCSTR,
                                dwProvType: DWORD,
                                dwFlags: DWORD) -> BOOL;
        fn CryptGenRandom(hProv: HCRYPTPROV,
                          dwLen: DWORD,
                          pbBuffer: *mut BYTE) -> BOOL;
        fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
    }

    impl OSRng {
        /// Create a new `OSRng`.
        pub fn new() -> IoResult<OSRng> {
            let mut hcp = 0;
            let mut ret = unsafe {
                CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
                                     PROV_RSA_FULL,
                                     CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
            };

            // It turns out that if we can't acquire a context with the
            // NTE_BAD_SIGNATURE error code, the documentation states:
            //
            //     The provider DLL signature could not be verified. Either the
            //     DLL or the digital signature has been tampered with.
            //
            // Sounds fishy, no? As it turns out, our signature can be bad
            // because our Thread Information Block (TIB) isn't exactly what it
            // expects. As to why, I have no idea. The only data we store in the
            // TIB is the stack limit for each thread, but apparently that's
            // enough to make the signature valid.
            //
            // Furthermore, this error only happens the *first* time we call
            // CryptAcquireContext, so we don't have to worry about future
            // calls.
            //
            // Anyway, the fix employed here is that if we see this error, we
            // pray that we're not close to the end of the stack, temporarily
            // set the stack limit to 0 (what the TIB originally was), acquire a
            // context, and then reset the stack limit.
            //
            // Again, I'm not sure why this is the fix, nor why we're getting
            // this error. All I can say is that this seems to allow libnative
            // to progress where it otherwise would be hindered. Who knew?
            if ret == 0 && os::errno() as DWORD == NTE_BAD_SIGNATURE {
                unsafe {
                    let limit = stack::get_sp_limit();
                    stack::record_sp_limit(0);
                    ret = CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
                                               PROV_RSA_FULL,
                                               CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
                    stack::record_sp_limit(limit);
                }
            }

            if ret == 0 {
                Err(IoError::last_error())
            } else {
                Ok(OSRng { hcryptprov: hcp })
            }
        }
    }

    impl Rng for OSRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(v);
            unsafe { cast::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 8];
            self.fill_bytes(v);
            unsafe { cast::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                CryptGenRandom(self.hcryptprov, v.len() as DWORD,
                               v.as_mut_ptr())
            };
            if ret == 0 {
                fail!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }

    impl Drop for OSRng {
        fn drop(&mut self) {
            let ret = unsafe {
                CryptReleaseContext(self.hcryptprov, 0)
            };
            if ret == 0 {
                fail!("couldn't release context: {}", os::last_os_error());
            }
        }
    }
}

#[cfg(test)]
mod test {
    use super::OSRng;
    use Rng;
    use std::task;

    #[test]
    fn test_os_rng() {
        let mut r = OSRng::new().unwrap();

        r.next_u32();
        r.next_u64();

        let mut v = [0u8, .. 1000];
        r.fill_bytes(v);
    }

    #[test]
    fn test_os_rng_tasks() {

        let mut txs = vec!();
        for _ in range(0, 20) {
            let (tx, rx) = channel();
            txs.push(tx);
            task::spawn(proc() {
                // wait until all the tasks are ready to go.
                rx.recv();

                // deschedule to attempt to interleave things as much
                // as possible (XXX: is this a good test?)
                let mut r = OSRng::new().unwrap();
                task::deschedule();
                let mut v = [0u8, .. 1000];

                for _ in range(0, 100) {
                    r.next_u32();
                    task::deschedule();
                    r.next_u64();
                    task::deschedule();
                    r.fill_bytes(v);
                    task::deschedule();
                }
            })
        }

        // start all the tasks
        for tx in txs.iter() {
            tx.send(())
        }
    }
}
<commit_msg>Fix fallout from std::libc separation<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Interfaces to the operating system provided random number
//! generators.

pub use self::imp::OSRng;

#[cfg(unix)]
mod imp {
    use Rng;
    use reader::ReaderRng;
    use std::io::{IoResult, File};

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    ///
    /// This does not block.
    #[cfg(unix)]
    pub struct OSRng {
        inner: ReaderRng<File>
    }

    impl OSRng {
        /// Create a new `OSRng`.
        pub fn new() -> IoResult<OSRng> {
            let reader = try!(File::open(&Path::new("/dev/urandom")));
            let reader_rng = ReaderRng::new(reader);

            Ok(OSRng { inner: reader_rng })
        }
    }

    impl Rng for OSRng {
        fn next_u32(&mut self) -> u32 {
            self.inner.next_u32()
        }
        fn next_u64(&mut self) -> u64 {
            self.inner.next_u64()
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            self.inner.fill_bytes(v)
        }
    }
}

#[cfg(windows)]
mod imp {
    extern crate libc;

    use Rng;
    use std::cast;
    use std::io::{IoResult, IoError};
    use std::os;
    use std::rt::stack;
    use self::libc::{c_ulong, DWORD, BYTE, LPCSTR, BOOL};

    type HCRYPTPROV = c_ulong;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    ///
    /// This does not block.
    pub struct OSRng {
        hcryptprov: HCRYPTPROV
    }

    static PROV_RSA_FULL: DWORD = 1;
    static CRYPT_SILENT: DWORD = 64;
    static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;
    static NTE_BAD_SIGNATURE: DWORD = 0x80090006;

    extern "system" {
        fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
                                pszContainer: LPCSTR,
                                pszProvider: LPCSTR,
                                dwProvType: DWORD,
                                dwFlags: DWORD) -> BOOL;
        fn CryptGenRandom(hProv: HCRYPTPROV,
                          dwLen: DWORD,
                          pbBuffer: *mut BYTE) -> BOOL;
        fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
    }

    impl OSRng {
        /// Create a new `OSRng`.
        pub fn new() -> IoResult<OSRng> {
            let mut hcp = 0;
            let mut ret = unsafe {
                CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
                                     PROV_RSA_FULL,
                                     CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
            };

            // It turns out that if we can't acquire a context with the
            // NTE_BAD_SIGNATURE error code, the documentation states:
            //
            //     The provider DLL signature could not be verified. Either the
            //     DLL or the digital signature has been tampered with.
            //
            // Sounds fishy, no? As it turns out, our signature can be bad
            // because our Thread Information Block (TIB) isn't exactly what it
            // expects. As to why, I have no idea. The only data we store in the
            // TIB is the stack limit for each thread, but apparently that's
            // enough to make the signature valid.
            //
            // Furthermore, this error only happens the *first* time we call
            // CryptAcquireContext, so we don't have to worry about future
            // calls.
            //
            // Anyway, the fix employed here is that if we see this error, we
            // pray that we're not close to the end of the stack, temporarily
            // set the stack limit to 0 (what the TIB originally was), acquire a
            // context, and then reset the stack limit.
            //
            // Again, I'm not sure why this is the fix, nor why we're getting
            // this error. All I can say is that this seems to allow libnative
            // to progress where it otherwise would be hindered. Who knew?
            if ret == 0 && os::errno() as DWORD == NTE_BAD_SIGNATURE {
                unsafe {
                    let limit = stack::get_sp_limit();
                    stack::record_sp_limit(0);
                    ret = CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
                                               PROV_RSA_FULL,
                                               CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
                    stack::record_sp_limit(limit);
                }
            }

            if ret == 0 {
                Err(IoError::last_error())
            } else {
                Ok(OSRng { hcryptprov: hcp })
            }
        }
    }

    impl Rng for OSRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(v);
            unsafe { cast::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 8];
            self.fill_bytes(v);
            unsafe { cast::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                CryptGenRandom(self.hcryptprov, v.len() as DWORD,
                               v.as_mut_ptr())
            };
            if ret == 0 {
                fail!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }

    impl Drop for OSRng {
        fn drop(&mut self) {
            let ret = unsafe {
                CryptReleaseContext(self.hcryptprov, 0)
            };
            if ret == 0 {
                fail!("couldn't release context: {}", os::last_os_error());
            }
        }
    }
}

#[cfg(test)]
mod test {
    use super::OSRng;
    use Rng;
    use std::task;

    #[test]
    fn test_os_rng() {
        let mut r = OSRng::new().unwrap();

        r.next_u32();
        r.next_u64();

        let mut v = [0u8, .. 1000];
        r.fill_bytes(v);
    }

    #[test]
    fn test_os_rng_tasks() {

        let mut txs = vec!();
        for _ in range(0, 20) {
            let (tx, rx) = channel();
            txs.push(tx);
            task::spawn(proc() {
                // wait until all the tasks are ready to go.
                rx.recv();

                // deschedule to attempt to interleave things as much
                // as possible (XXX: is this a good test?)
                let mut r = OSRng::new().unwrap();
                task::deschedule();
                let mut v = [0u8, .. 1000];

                for _ in range(0, 100) {
                    r.next_u32();
                    task::deschedule();
                    r.next_u64();
                    task::deschedule();
                    r.fill_bytes(v);
                    task::deschedule();
                }
            })
        }

        // start all the tasks
        for tx in txs.iter() {
            tx.send(())
        }
    }
}
<|endoftext|>


<commit_before>extern crate sdl2;
extern crate sdl2_gfx;

use sdl2::pixels::Color;
use sdl2::event::Event;
use sdl2::keyboard::Scancode::*;

mod matrix;
mod primitives;
mod line;
use primitives::*;

const WIDTH: u32 = 1280;
const HEIGHT: u32 = 720;

fn main() {
    // Initialize SDL2
    let sdl_context   = sdl2::init().unwrap();
    let video_context = sdl_context.video().unwrap();

    // Create window
    let window = video_context.window("Graphics Task 1", WIDTH, HEIGHT)
        .position_centered()
        .opengl()
        .build()
        .unwrap();

    // Get renderer binded to window
    let mut renderer = window.renderer().build().unwrap();

    // Create FPS manager to precisely control inter-frames delays
    let mut fps_manager = sdl2_gfx::framerate::FPSManager::new();
    fps_manager.set_framerate(60).unwrap();

    // Set draw color and clear the screen
    renderer.set_draw_color(Color::RGB(0, 0, 0));
    renderer.clear();
    renderer.present();

    // Get event pump
    let mut events = sdl_context.event_pump().unwrap();

    // Set initial lines coordinates
    let startx  = ((WIDTH/2) - 10) as f32;
    let starty1 = (HEIGHT/4)       as f32;
    let starty2 = (HEIGHT/4*3)     as f32;

    // Create lines
    let mut line1 = line::Line::new(
        Point2D::new(startx - 10.0, starty1),
        Point2D::new(startx - 10.0, starty2),
        Color::RGB(0, 255, 0)
    );

    let mut line2 = line::Line::new(
        Point2D::new(startx + 10.0, starty1),
        Point2D::new(startx + 10.0, starty2),
        Color::RGB(255, 0, 0)
    );

    // Start main loop
    'main:
    loop {
        // If exit event passed, break the loop
        for event in events.poll_iter() {
            match event {
                Event::Quit {..} => break 'main,
                _ => ()
            }
        }

        // Initialize variables
        let mut dx = 0.0;
        let mut dy = 0.0;
        let mut scale = 1.0;
        let mut angle = 0.0;

        // Poll presed keys
        for key in events.keyboard_state().pressed_scancodes() {
            match key {
                W       => dy -= 1.0,
                S       => dy += 1.0,
                D       => dx += 1.0,
                A       => dx -= 1.0,
                Up      => scale += 0.01,
                Down    => scale -= 0.01,
                Left    => angle -= 1.0,
                Right   => angle += 1.0,
                _       => (),
            }
        }

        // Do affine transformations
        line1.translate(dx, dy);
        line1.scale(scale, scale);
        line1.rotate(angle);

        line2.translate(dx, dy);
        line2.scale(scale, scale);
        line2.rotate(angle);

        // Clear render buffer
        renderer.set_draw_color(Color::RGB(0, 0, 0));
        renderer.clear();

        // Draw lines
        line1.draw(&renderer);
        line2.draw_builtin_line(&renderer);

        // Present render buffer
        renderer.present();

        // Sleep until the next frame should be rendered
        fps_manager.delay();
    }
}
<commit_msg>Changed coefficients, more rusty loops<commit_after>extern crate sdl2;
extern crate sdl2_gfx;

use sdl2::pixels::Color;
use sdl2::event::Event;
use sdl2::keyboard::Scancode::*;

mod matrix;
mod primitives;
mod line;
use primitives::*;

const WIDTH: u32 = 1280;
const HEIGHT: u32 = 720;

fn main() {
    // Initialize SDL2
    let sdl_context   = sdl2::init().unwrap();
    let video_context = sdl_context.video().unwrap();

    // Create window
    let window = video_context.window("Graphics Task 1", WIDTH, HEIGHT)
        .position_centered()
        .opengl()
        .build()
        .unwrap();

    // Get renderer binded to window
    let mut renderer = window.renderer().build().unwrap();

    // Create FPS manager to precisely control inter-frames delays
    let mut fps_manager = sdl2_gfx::framerate::FPSManager::new();
    fps_manager.set_framerate(60).unwrap();

    // Set draw color and clear the screen
    renderer.set_draw_color(Color::RGB(0, 0, 0));
    renderer.clear();
    renderer.present();

    // Get event pump
    let mut events = sdl_context.event_pump().unwrap();

    // Set initial lines coordinates
    let startx  = ((WIDTH/2) - 10) as f32;
    let starty1 = (HEIGHT/4)       as f32;
    let starty2 = (HEIGHT/4*3)     as f32;

    // Create lines
    let mut line1 = line::Line::new(
        Point2D::new(startx - 10.0, starty1),
        Point2D::new(startx - 10.0, starty2),
        Color::RGB(0, 255, 0)
    );

    let mut line2 = line::Line::new(
        Point2D::new(startx + 10.0, starty1),
        Point2D::new(startx + 10.0, starty2),
        Color::RGB(255, 0, 0)
    );

    // Start main loop
    'main:
    loop {
        // If exit event passed, break the loop
        for event in events.poll_iter() {
            match event {
                Event::Quit {..} => break 'main,
                _ => ()
            }
        }

        // Initialize variables
        let mut dx = 0.0;
        let mut dy = 0.0;
        let mut scale = 1.0;
        let mut angle = 0.0;

        // Poll presed keys
        for key in events.keyboard_state().pressed_scancodes() {
            match key {
                W       => dy -= 3.0,
                S       => dy += 3.0,
                D       => dx += 3.0,
                A       => dx -= 3.0,
                Up      => scale += 0.05,
                Down    => scale -= 0.05,
                Left    => angle -= 3.0,
                Right   => angle += 3.0,
                _       => (),
            }
        }

        // Do affine transformations
        line1.translate(dx, dy);
        line1.scale(scale, scale);
        line1.rotate(angle);

        line2.translate(dx, dy);
        line2.scale(scale, scale);
        line2.rotate(angle);

        // Clear render buffer
        renderer.set_draw_color(Color::RGB(0, 0, 0));
        renderer.clear();

        // Draw lines
        line1.draw(&renderer);
        line2.draw_builtin_line(&renderer);

        // Present render buffer
        renderer.present();

        // Sleep until the next frame should be rendered
        fps_manager.delay();
    }
}
<|endoftext|>


<commit_before>extern crate collections;
extern crate sync;
extern crate rand;
use collections::HashMap;
use std::io::{File, Open, Read, Write, TempDir};
use std::num::Zero;
use std::comm::{Data, Empty, Disconnected};
use sync::{Arc, RWLock};
use sync::Future;
use rand::task_rng;
use rand::distributions::{IndependentSample, Range};
use rand::distributions::range::SampleRange;

struct BufferManager {
	size: uint,
	entries: HashMap<u64, BufferEntry>,
	path: Path,
}

struct BufferEntry {
	frame: Arc<RWLock<BufferFrame>>,
}

struct BufferFrame {
	page_id: u64,
	data: Vec<u8>,
}

/* Destructor trait implementation */
impl Drop for BufferManager {
	fn drop(&mut self) {
		println!("Dropping");
		// TODO
	}
}

impl BufferManager {
	pub fn new(size: uint, path: Path) -> BufferManager {
		let h = HashMap::with_capacity(size);
		BufferManager {size: size, entries: h, path: path}
	}

	fn open_or_create(&self, page_id: u64) -> File {
		let file_path = self.path.join(page_id.to_str());
		match File::open_mode(&file_path, Open, Read) {
			Ok(f) => f,
			Err(_) => {
				match File::open_mode(&file_path, Open, Write) {
					Ok(mut f) => {
						match f.write([0_u8, ..4 * 1024]) {
							Ok(_) => (),
							Err(e) => fail!("writing page failed: {}", e),
						}
						match File::open_mode(&file_path, Open, Read) {
							Ok(f) => f,
							Err(e) => fail!("failed reading file: {}", e),
						}
					},
					Err(e) => fail!("Writing file failed: {}", e),
				}
			},
		}
	}

	fn load_page(&mut self, page_id: u64) {
		if self.entries.len() == self.size {
			self.evict_page();
		}

		let mut file_handle = self.open_or_create(page_id);
		//let content = match file_handle.read_exact(4*1024) {
		let content = match file_handle.read_exact(10) {
			Ok(c) => Vec::from_slice(c),
			Err(e) => fail!("Couldn't read from page: {}", e),
		};

		let frame = BufferFrame {data: content, page_id: page_id};
		let entry = BufferEntry {frame: Arc::new(RWLock::new(frame))};
		self.entries.insert(page_id, entry);
	}

	fn evict_page(&mut self) {
		let random_key = {
			let mut iter = self.entries.keys();
			sample(&mut iter).map(|v| v.clone())
		};

		match random_key {
			None => false,
			Some(key) => self.entries.remove(&key),
		};
	}

	pub fn fix_page(&mut self, page_id: u64) -> Option<Arc<RWLock<BufferFrame>>> {
		if !self.entries.contains_key(&page_id) {
			self.load_page(page_id);
		}
		let entry = self.entries.get(&page_id);
		// Arcs can be cloned and they will all point to the same RWLock
		Some(entry.frame.clone())
	}

	pub fn unfix_page(&mut self, frame: Arc<RWLock<BufferFrame>>, is_dirty: bool) {
		if !is_dirty {
			return;
		}
		let frame = frame.read();
		println!("writing back {}", frame.page_id);
		self.write_page(frame.page_id, frame.get_data());
	}

	fn write_page(&mut self, page_id: u64, data: &[u8]) {
		let file_path = self.path.join(page_id.to_str());
		let mut handle = match File::open_mode(&file_path, Open, Write) {
			Ok(handle) => handle,
			Err(e) => fail!("Opening file for writing failed: {}", e),
		};

		match handle.write(data) {
			Ok(_) => (),
			Err(e) => fail!("Writing to file failed: {}", e),
		};
	}
}

/*
 * A buffer frame, the unit that gets the data
 */
impl BufferFrame {
	/*
	 * get_mut_data returns a borrowed reference to a mutable slice to the vector
	 * contents.
	 */
	pub fn get_mut_data<'a>(&'a mut self) -> &'a mut [u8] {
		self.data.as_mut_slice()
	}
	pub fn get_data<'a>(&'a self) -> &'a [u8] {
		self.data.as_slice()
	}
}

fn sample<'a, T, I:Iterator<T>>(from: &'a mut I) -> Option<T> {
	let from: ~[T] = from.collect();
	let l = from.len();
	if l == 0 {
		return None;
	}
	let index = randrange(l);
	Some(from[index])
}

fn randrange<X: SampleRange + Ord + Zero>(high: X) -> X {
	let between: Range<X> = Range::new(Zero::zero(), high);
	let mut rng = rand::task_rng();
	between.ind_sample(&mut rng)
}

#[test]
fn test_create() {
	let dir = match TempDir::new("buffermanager") {
		Some(temp_dir) => temp_dir,
		None => fail!("creation of temporary directory"),
	};

	let mut bm = BufferManager::new(16, dir.path().clone());
	let pageref = match bm.fix_page(42) {
		Some(p) => p,
		None => fail!("Getting page failed"),
	};
	{
		let mut page = pageref.write();
		let data = page.get_mut_data();
		data[0] = 42;
		//println!("data: {}", Vec::from_slice(data));
	}
	bm.unfix_page(pageref, true);
	fail!("always");
}

#[test]
fn test_threads() {
	use rand::random;
	use std::task::spawn;

	let pages_in_ram = 1;
	let pages_on_disk: u64 = 20;
	let thread_count = 3;
	let dir = match TempDir::new("buffermanager") {
		Some(temp_dir) => temp_dir,
		None => fail!("creation of temporary directory"),
	};
	let p = dir.path();
	let p = Path::new(".");

	let mut buffermanager = BufferManager::new(pages_in_ram, p.clone());

	for i in range(0, pages_on_disk) {
		let bf = match buffermanager.fix_page(i) {
			Some(frame) => frame,
			None => fail!("Couldn't fix page {}", i),
		};
		{
			let mut lock = bf.write();
			lock.get_mut_data()[0] = 0;
		}
		buffermanager.unfix_page(bf, true);
	}
	let bm = Arc::new(RWLock::new(buffermanager));

	// start scan thread
	let (tx, rx) = channel();
	let bm_scan = bm.clone();
	let mut scan = Future::spawn(proc() {
		let mut counters = Vec::from_elem(pages_on_disk as uint, 0_u8);
		loop {
			println!("Running scan thread...");
			match rx.try_recv() {
				Empty => {
					let page_number = randrange(pages_on_disk);
					let mut bm = bm_scan.write();
					let bf = match bm.fix_page(page_number) {
						Some(frame) => frame,
						None => fail!("Couldn't scan/fix page"),
					};
					let current_val = {
						let lock = bf.read();
						lock.get_data()[0]
					};
					bm.unfix_page(bf, false);
					bm.downgrade();
					// check if the value is going up
					assert!(&current_val >= counters.get(page_number as uint));
					// set to the new value
					let v = counters.get_mut(page_number as uint);
					*v = current_val;

				},
				/*
				 * terminate on both disconnect and when any kind of
				 * data arrives
				 */
				Disconnected => break,
				Data(_) => break,
			};
		}
	});

	// start read/write threads
	let mut rw_threads: Vec<Future<int>> = Vec::new();
	for _ in range(0, thread_count) {
		let bm = bm.clone();
		rw_threads.push(Future::spawn(proc() {
			let is_write = random::<bool>();
			println!("Creating new {} task",
				if is_write {"write"} else {"read"});
			let page_number = randrange(pages_on_disk);
			let mut bm = bm.write();
			if is_write {
				let bf = match bm.fix_page(page_number) {
					Some(frame) => frame,
					None => fail!("Couldn't fix page"),
				};
				{
					println!("Wrote to page");
					let mut lock = bf.write();
					let data = lock.get_mut_data();
					data[0] = data[0] + 1;
					println!("data: {}", Vec::from_slice(data));
				}
				bm.unfix_page(bf, is_write);
			} else {
				let bf = match bm.fix_page(page_number) {
					Some(frame) => frame,
					None => fail!("Couldn't fix page"),
				};
				bm.unfix_page(bf, is_write);
			}
			// return whether we wrote (1) or read (0) as future
			if is_write {1} else {0}
		}));
	}

	// Rust does not have join, but we can wait on Futures which does the same
	let total_count = rw_threads.mut_iter().fold(0, |acc, val| acc + val.get());
	println!("total_count: {}", total_count);

	// terminate the scan thread and wait until it has completed
	tx.send("terminate");
	scan.get();

	// re-open the pages and check whether all numbers got saved
	let mut bm = BufferManager::new(pages_in_ram, p.clone());
	let mut total_count_on_disk = 0;
	for i in range(0, pages_on_disk) {
		let bf = match bm.fix_page(i) {
			Some(frame) => frame,
			None => fail!("Couldn't fix page")
		};
		let value = {
			let lock = bf.read();
			let data = lock.get_data();
			data[0]
		};
		bm.unfix_page(bf, false);
		// cast up from u8 to int
		total_count_on_disk += value as int;
	}
	println!("Total count on disk: {}", total_count_on_disk);
	assert_eq!(total_count, total_count_on_disk);

	fail!("always");
}
<commit_msg>Added a counter of fixes per frame<commit_after>extern crate collections;
extern crate sync;
extern crate rand;
use collections::HashMap;
use std::io::{File, Open, Read, Write, TempDir};
use std::num::Zero;
use std::comm::{Data, Empty, Disconnected};
use sync::{Arc, RWLock};
use sync::Future;
use rand::task_rng;
use rand::distributions::{IndependentSample, Range};
use rand::distributions::range::SampleRange;

struct BufferManager {
	size: uint,
	entries: HashMap<u64, BufferEntry>,
	path: Path,
}

struct BufferEntry {
	frame: Arc<RWLock<BufferFrame>>,
}

#[deriving(Eq)]
enum Status {
	Free,
	Fixed(uint),
}

struct BufferFrame {
	page_id: u64,
	data: Vec<u8>,
	fixed: Status,
}

/* Destructor trait implementation */
impl Drop for BufferManager {
	fn drop(&mut self) {
		println!("Dropping");
		// TODO
	}
}

impl BufferManager {
	pub fn new(size: uint, path: Path) -> BufferManager {
		let h = HashMap::with_capacity(size);
		BufferManager {size: size, entries: h, path: path}
	}

	fn open_or_create(&self, page_id: u64) -> File {
		let file_path = self.path.join(page_id.to_str());
		match File::open_mode(&file_path, Open, Read) {
			Ok(f) => f,
			Err(_) => {
				match File::open_mode(&file_path, Open, Write) {
					Ok(mut f) => {
						match f.write([0_u8, ..4 * 1024]) {
							Ok(_) => (),
							Err(e) => fail!("writing page failed: {}", e),
						}
						match File::open_mode(&file_path, Open, Read) {
							Ok(f) => f,
							Err(e) => fail!("failed reading file: {}", e),
						}
					},
					Err(e) => fail!("Writing file failed: {}", e),
				}
			},
		}
	}

	/*
	 * returns true if page could be loaded
	 */
	fn load_page(&mut self, page_id: u64) -> bool {
		if self.entries.len() == self.size {
			if !self.evict_page() {
				return false;
			}
		}

		let mut file_handle = self.open_or_create(page_id);
		//let content = match file_handle.read_exact(4*1024) {
		let content = match file_handle.read_exact(10) {
			Ok(c) => Vec::from_slice(c),
			Err(e) => fail!("Couldn't read from page: {}", e),
		};

		let frame = BufferFrame {data: content, page_id: page_id, fixed: Free};
		let entry = BufferEntry {frame: Arc::new(RWLock::new(frame))};
		self.entries.insert(page_id, entry);
		true
	}

	/*
	 * return false if no page could be evicted
	 */
	fn evict_page(&mut self) -> bool {
		let random_key = {
			let mut iter = self.entries.keys();
			// TODO check if there is a free page
			sample(&mut iter).map(|v| v.clone())
		};

		match random_key {
			None => false,
			Some(key) => self.entries.remove(&key),
		}
	}

	pub fn fix_page(&mut self, page_id: u64) -> Option<Arc<RWLock<BufferFrame>>> {
		if !self.entries.contains_key(&page_id) {
			if !self.load_page(page_id) {
				return None;
			}
		}
		let entry = self.entries.get(&page_id);
		{
			let mut f = entry.frame.write();
			f.fixed = match f.fixed {
				Free => Fixed(1),
				Fixed(n) => Fixed(n+1),
			};
		}
		// Arcs can be cloned and they will all point to the same RWLock
		Some(entry.frame.clone())
	}

	pub fn unfix_page(&mut self, frame: Arc<RWLock<BufferFrame>>, is_dirty: bool) {
		{
			let mut frame = frame.write();
			frame.fixed = match frame.fixed {
				Fixed(1) => Free,
				Fixed(n) => Fixed(n-1),
				Free => fail!("Unfixing unfixed page"),
			};
		}

		if !is_dirty {
			return;
		}
		let frame = frame.read();
		if frame.fixed == Free {
			println!("writing back {}", frame.page_id);
			self.write_page(frame.page_id, frame.get_data());
		}
	}

	fn write_page(&mut self, page_id: u64, data: &[u8]) {
		let file_path = self.path.join(page_id.to_str());
		let mut handle = match File::open_mode(&file_path, Open, Write) {
			Ok(handle) => handle,
			Err(e) => fail!("Opening file for writing failed: {}", e),
		};

		match handle.write(data) {
			Ok(_) => (),
			Err(e) => fail!("Writing to file failed: {}", e),
		};
	}
}

/*
 * A buffer frame, the unit that gets the data
 */
impl BufferFrame {
	/*
	 * get_mut_data returns a borrowed reference to a mutable slice to the vector
	 * contents.
	 */
	pub fn get_mut_data<'a>(&'a mut self) -> &'a mut [u8] {
		self.data.as_mut_slice()
	}
	pub fn get_data<'a>(&'a self) -> &'a [u8] {
		self.data.as_slice()
	}
}

fn sample<'a, T, I:Iterator<T>>(from: &'a mut I) -> Option<T> {
	let from: ~[T] = from.collect();
	let l = from.len();
	if l == 0 {
		return None;
	}
	let index = randrange(l);
	Some(from[index])
}

fn randrange<X: SampleRange + Ord + Zero>(high: X) -> X {
	let between: Range<X> = Range::new(Zero::zero(), high);
	let mut rng = rand::task_rng();
	between.ind_sample(&mut rng)
}

#[test]
fn test_create() {
	let dir = match TempDir::new("buffermanager") {
		Some(temp_dir) => temp_dir,
		None => fail!("creation of temporary directory"),
	};

	let mut bm = BufferManager::new(16, dir.path().clone());
	let pageref = match bm.fix_page(42) {
		Some(p) => p,
		None => fail!("Getting page failed"),
	};
	{
		let mut page = pageref.write();
		let data = page.get_mut_data();
		data[0] = 42;
		//println!("data: {}", Vec::from_slice(data));
	}
	bm.unfix_page(pageref, true);
	fail!("always");
}

#[test]
fn test_threads() {
	use rand::random;
	use std::task::spawn;

	let pages_in_ram = 1;
	let pages_on_disk: u64 = 20;
	let thread_count = 3;
	let dir = match TempDir::new("buffermanager") {
		Some(temp_dir) => temp_dir,
		None => fail!("creation of temporary directory"),
	};
	let p = dir.path();
	let p = Path::new(".");

	let mut buffermanager = BufferManager::new(pages_in_ram, p.clone());

	for i in range(0, pages_on_disk) {
		let bf = match buffermanager.fix_page(i) {
			Some(frame) => frame,
			None => fail!("Couldn't fix page {}", i),
		};
		{
			let mut lock = bf.write();
			lock.get_mut_data()[0] = 0;
		}
		buffermanager.unfix_page(bf, true);
	}
	let bm = Arc::new(RWLock::new(buffermanager));

	// start scan thread
	let (tx, rx) = channel();
	let bm_scan = bm.clone();
	let mut scan = Future::spawn(proc() {
		let mut counters = Vec::from_elem(pages_on_disk as uint, 0_u8);
		loop {
			println!("Running scan thread...");
			match rx.try_recv() {
				Empty => {
					let page_number = randrange(pages_on_disk);
					let mut bm = bm_scan.write();
					let bf = match bm.fix_page(page_number) {
						Some(frame) => frame,
						None => fail!("Couldn't scan/fix page"),
					};
					let current_val = {
						let lock = bf.read();
						lock.get_data()[0]
					};
					bm.unfix_page(bf, false);
					bm.downgrade();
					// check if the value is going up
					assert!(&current_val >= counters.get(page_number as uint));
					// set to the new value
					let v = counters.get_mut(page_number as uint);
					*v = current_val;

				},
				/*
				 * terminate on both disconnect and when any kind of
				 * data arrives
				 */
				Disconnected => break,
				Data(_) => break,
			};
		}
	});

	// start read/write threads
	let mut rw_threads: Vec<Future<int>> = Vec::new();
	for _ in range(0, thread_count) {
		let bm = bm.clone();
		rw_threads.push(Future::spawn(proc() {
			let is_write = random::<bool>();
			println!("Creating new {} task",
				if is_write {"write"} else {"read"});
			let page_number = randrange(pages_on_disk);
			let mut bm = bm.write();
			if is_write {
				let bf = match bm.fix_page(page_number) {
					Some(frame) => frame,
					None => fail!("Couldn't fix page"),
				};
				{
					println!("Wrote to page");
					let mut lock = bf.write();
					let data = lock.get_mut_data();
					data[0] = data[0] + 1;
					println!("data: {}", Vec::from_slice(data));
				}
				bm.unfix_page(bf, is_write);
			} else {
				let bf = match bm.fix_page(page_number) {
					Some(frame) => frame,
					None => fail!("Couldn't fix page"),
				};
				bm.unfix_page(bf, is_write);
			}
			// return whether we wrote (1) or read (0) as future
			if is_write {1} else {0}
		}));
	}

	// Rust does not have join, but we can wait on Futures which does the same
	let total_count = rw_threads.mut_iter().fold(0, |acc, val| acc + val.get());
	println!("total_count: {}", total_count);

	// terminate the scan thread and wait until it has completed
	tx.send("terminate");
	scan.get();

	// re-open the pages and check whether all numbers got saved
	let mut bm = BufferManager::new(pages_in_ram, p.clone());
	let mut total_count_on_disk = 0;
	for i in range(0, pages_on_disk) {
		let bf = match bm.fix_page(i) {
			Some(frame) => frame,
			None => fail!("Couldn't fix page")
		};
		let value = {
			let lock = bf.read();
			let data = lock.get_data();
			data[0]
		};
		bm.unfix_page(bf, false);
		// cast up from u8 to int
		total_count_on_disk += value as int;
	}
	println!("Total count on disk: {}", total_count_on_disk);
	assert_eq!(total_count, total_count_on_disk);

	fail!("always");
}
<|endoftext|>


<commit_before>extern crate hematite_server as hem;
#[macro_use]
extern crate log;

use std::net::TcpListener;
use std::sync::Arc;
use std::thread;

use hem::vanilla::Server;

use log::{LogLevel, LogLevelFilter, LogMetadata, LogRecord, SetLoggerError};

struct SimpleLogger;

impl log::Log for SimpleLogger {
    fn enabled(&self, metadata: &LogMetadata) -> bool {
        metadata.level() <= LogLevel::Info
    }

    fn log(&self, record: &LogRecord) {
        if self.enabled(record.metadata()) {
            println!("{} - {}", record.level(), record.args());
        }
    }
}

fn init() -> Result<(), SetLoggerError> {
    log::set_logger(|max_log_level| {
        max_log_level.set(LogLevelFilter::Info);
        Box::new(SimpleLogger)
    })
}

fn main () {
    init().unwrap();

    info!("hematite server");

    let server = Server::new().unwrap();

    let listener = TcpListener::bind(&(server.addr(), server.port())).unwrap();
    // NOTE(toqueteos): As soon as we need &mut server reference this won't work
    let server_ref = Arc::new(server);
    // Accept connections and process them, spawning a new tasks for each one
    for conn in listener.incoming() {
        match conn {
            Ok(conn) => {
                let srv = server_ref.clone();
                thread::spawn(move|| {
                    match srv.handle(conn) {
                        Ok(_) => {}
                        Err(err) => info!("{}", err)
                    }
                });
            }
            Err(e) => info!("Connection error {:?}", e)
        }
    }
}
<commit_msg>Use expect instead of unwrap<commit_after>extern crate hematite_server as hem;
#[macro_use]
extern crate log;

use std::net::TcpListener;
use std::sync::Arc;
use std::thread;

use hem::vanilla::Server;

use log::{LogLevel, LogLevelFilter, LogMetadata, LogRecord, SetLoggerError};

struct SimpleLogger;

impl log::Log for SimpleLogger {
    fn enabled(&self, metadata: &LogMetadata) -> bool {
        metadata.level() <= LogLevel::Info
    }

    fn log(&self, record: &LogRecord) {
        if self.enabled(record.metadata()) {
            println!("{} - {}", record.level(), record.args());
        }
    }
}

fn init_logger() -> Result<(), SetLoggerError> {
    log::set_logger(|max_log_level| {
        max_log_level.set(LogLevelFilter::Info);
        Box::new(SimpleLogger)
    })
}

fn main () {
    init_logger().expect("failed to initialize logger");

    info!("hematite server");

    let server = Server::new().expect("failed new server");

    let listener = TcpListener::bind(&(server.addr(), server.port())).expect("failed tcp bind");
    // NOTE(toqueteos): As soon as we need &mut server reference this won't work
    let server_ref = Arc::new(server);
    // Accept connections and process them, spawning a new tasks for each one
    for conn in listener.incoming() {
        match conn {
            Ok(conn) => {
                let srv = server_ref.clone();
                thread::spawn(move|| {
                    match srv.handle(conn) {
                        Ok(_) => {}
                        Err(err) => info!("{}", err)
                    }
                });
            }
            Err(e) => info!("Connection error {:?}", e)
        }
    }
}
<|endoftext|>


<commit_before>pub use super::*;

use rustc::mir::*;
use rustc::mir::visit::Visitor;
use crate::dataflow::BitDenotation;

/// This calculates if any part of a MIR local could have previously been borrowed.
/// This means that once a local has been borrowed, its bit will be set
/// from that point and onwards, until we see a StorageDead statement for the local,
/// at which points there is no memory associated with the local, so it cannot be borrowed.
/// This is used to compute which locals are live during a yield expression for
/// immovable generators.
#[derive(Copy, Clone)]
pub struct HaveBeenBorrowedLocals<'a, 'tcx: 'a> {
    mir: &'a Mir<'tcx>,
}

impl<'a, 'tcx: 'a> HaveBeenBorrowedLocals<'a, 'tcx> {
    pub fn new(mir: &'a Mir<'tcx>)
               -> Self {
        HaveBeenBorrowedLocals { mir }
    }

    pub fn mir(&self) -> &Mir<'tcx> {
        self.mir
    }
}

impl<'a, 'tcx> BitDenotation<'tcx> for HaveBeenBorrowedLocals<'a, 'tcx> {
    type Idx = Local;
    fn name() -> &'static str { "has_been_borrowed_locals" }
    fn bits_per_block(&self) -> usize {
        self.mir.local_decls.len()
    }

    fn start_block_effect(&self, _sets: &mut BitSet<Local>) {
        // Nothing is borrowed on function entry
    }

    fn statement_effect(&self,
                        sets: &mut BlockSets<'_, Local>,
                        loc: Location) {
        let stmt = &self.mir[loc.block].statements[loc.statement_index];

        BorrowedLocalsVisitor {
            sets,
        }.visit_statement(stmt, loc);

        // StorageDead invalidates all borrows and raw pointers to a local
        match stmt.kind {
            StatementKind::StorageDead(l) => sets.kill(l),
            _ => (),
        }
    }

    fn terminator_effect(&self,
                         sets: &mut BlockSets<'_, Local>,
                         loc: Location) {
        BorrowedLocalsVisitor {
            sets,
        }.visit_terminator(self.mir[loc.block].terminator(), loc);
    }

    fn propagate_call_return(
        &self,
        _in_out: &mut BitSet<Local>,
        _call_bb: mir::BasicBlock,
        _dest_bb: mir::BasicBlock,
        _dest_place: &mir::Place<'tcx>,
    ) {
        // Nothing to do when a call returns successfully
    }
}

impl<'a, 'tcx> BitSetOperator for HaveBeenBorrowedLocals<'a, 'tcx> {
    #[inline]
    fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool {
        inout_set.union(in_set) // "maybe" means we union effects of both preds
    }
}

impl<'a, 'tcx> InitialFlow for HaveBeenBorrowedLocals<'a, 'tcx> {
    #[inline]
    fn bottom_value() -> bool {
        false // bottom = unborrowed
    }
}

struct BorrowedLocalsVisitor<'b, 'c: 'b> {
    sets: &'b mut BlockSets<'c, Local>,
}

fn find_local<'tcx>(place: &Place<'tcx>) -> Option<Local> {
    match *place {
        Place::Base(PlaceBase::Local(l)) => Some(l),
        Place::Base(PlaceBase::Static(..)) => None,
        Place::Projection(ref proj) => {
            match proj.elem {
                ProjectionElem::Deref => None,
                _ => find_local(&proj.base)
            }
        }
    }
}

impl<'tcx, 'b, 'c> Visitor<'tcx> for BorrowedLocalsVisitor<'b, 'c> {
    fn visit_rvalue(&mut self,
                    rvalue: &Rvalue<'tcx>,
                    location: Location) {
        if let Rvalue::Ref(_, _, ref place) = *rvalue {
            if let Some(local) = find_local(place) {
                self.sets.gen(local);
            }
        }

        self.super_rvalue(rvalue, location)
    }
}
<commit_msg>Make find_local iterate instead of recurse<commit_after>pub use super::*;

use rustc::mir::*;
use rustc::mir::visit::Visitor;
use crate::dataflow::BitDenotation;

/// This calculates if any part of a MIR local could have previously been borrowed.
/// This means that once a local has been borrowed, its bit will be set
/// from that point and onwards, until we see a StorageDead statement for the local,
/// at which points there is no memory associated with the local, so it cannot be borrowed.
/// This is used to compute which locals are live during a yield expression for
/// immovable generators.
#[derive(Copy, Clone)]
pub struct HaveBeenBorrowedLocals<'a, 'tcx: 'a> {
    mir: &'a Mir<'tcx>,
}

impl<'a, 'tcx: 'a> HaveBeenBorrowedLocals<'a, 'tcx> {
    pub fn new(mir: &'a Mir<'tcx>)
               -> Self {
        HaveBeenBorrowedLocals { mir }
    }

    pub fn mir(&self) -> &Mir<'tcx> {
        self.mir
    }
}

impl<'a, 'tcx> BitDenotation<'tcx> for HaveBeenBorrowedLocals<'a, 'tcx> {
    type Idx = Local;
    fn name() -> &'static str { "has_been_borrowed_locals" }
    fn bits_per_block(&self) -> usize {
        self.mir.local_decls.len()
    }

    fn start_block_effect(&self, _sets: &mut BitSet<Local>) {
        // Nothing is borrowed on function entry
    }

    fn statement_effect(&self,
                        sets: &mut BlockSets<'_, Local>,
                        loc: Location) {
        let stmt = &self.mir[loc.block].statements[loc.statement_index];

        BorrowedLocalsVisitor {
            sets,
        }.visit_statement(stmt, loc);

        // StorageDead invalidates all borrows and raw pointers to a local
        match stmt.kind {
            StatementKind::StorageDead(l) => sets.kill(l),
            _ => (),
        }
    }

    fn terminator_effect(&self,
                         sets: &mut BlockSets<'_, Local>,
                         loc: Location) {
        BorrowedLocalsVisitor {
            sets,
        }.visit_terminator(self.mir[loc.block].terminator(), loc);
    }

    fn propagate_call_return(
        &self,
        _in_out: &mut BitSet<Local>,
        _call_bb: mir::BasicBlock,
        _dest_bb: mir::BasicBlock,
        _dest_place: &mir::Place<'tcx>,
    ) {
        // Nothing to do when a call returns successfully
    }
}

impl<'a, 'tcx> BitSetOperator for HaveBeenBorrowedLocals<'a, 'tcx> {
    #[inline]
    fn join<T: Idx>(&self, inout_set: &mut BitSet<T>, in_set: &BitSet<T>) -> bool {
        inout_set.union(in_set) // "maybe" means we union effects of both preds
    }
}

impl<'a, 'tcx> InitialFlow for HaveBeenBorrowedLocals<'a, 'tcx> {
    #[inline]
    fn bottom_value() -> bool {
        false // bottom = unborrowed
    }
}

struct BorrowedLocalsVisitor<'b, 'c: 'b> {
    sets: &'b mut BlockSets<'c, Local>,
}

fn find_local<'tcx>(place: &Place<'tcx>) -> Option<Local> {
    place.iterate(|place_base, place_projection| {
        for proj in place_projection {
            if proj.elem == ProjectionElem::Deref {
                return None;
            }
        }

        if let PlaceBase::Local(local) = place_base {
            Some(*local)
        } else {
            None
        }
    })
}

impl<'tcx, 'b, 'c> Visitor<'tcx> for BorrowedLocalsVisitor<'b, 'c> {
    fn visit_rvalue(&mut self,
                    rvalue: &Rvalue<'tcx>,
                    location: Location) {
        if let Rvalue::Ref(_, _, ref place) = *rvalue {
            if let Some(local) = find_local(place) {
                self.sets.gen(local);
            }
        }

        self.super_rvalue(rvalue, location)
    }
}
<|endoftext|>


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

use bson::Document;
use error::Error as MongoError;

pub struct CommandStarted {
    pub command: Document,
    pub database_name: String,
    pub command_name: String,
    pub request_id: i64,
    pub connection_string: String,
}

impl Display for CommandStarted {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        fmt.write_fmt(format_args!("COMMAND.{} {} STARTED: {}", self.command_name,
                                   self.connection_string, self.command))
    }
}

pub enum CommandResult<'a> {
    Success {
        duration: i64,
        reply: Document,
        command_name: String,
        request_id: i64,
        connection_string: String,
    },
    Failure {
        duration: i64,
        command_name: String,
        failure: &'a MongoError,
        request_id: i64,
        connection_string: String,
    }
}

impl<'a> Display for CommandResult<'a> {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        match self {
            &CommandResult::Success { duration, ref reply, ref command_name, request_id: _,
                                     ref connection_string } => {
                fmt.write_fmt(format_args!("COMMAND.{} {} COMPLETED: {} ({} ns)", command_name,
                                           connection_string, reply, duration))
            },
            &CommandResult::Failure { duration, ref command_name, ref failure, request_id: _,
                                      ref connection_string } => {
                fmt.write_fmt(format_args!("COMMAND.{} {} FAILURE: {} ({} NS)", command_name,
                                           connection_string, failure, duration))
            }
        }
    }
}
<commit_msg>changed duration to unsigned<commit_after>use std::fmt::{Display, Error, Formatter};

use bson::Document;
use error::Error as MongoError;

pub struct CommandStarted {
    pub command: Document,
    pub database_name: String,
    pub command_name: String,
    pub request_id: i64,
    pub connection_string: String,
}

impl Display for CommandStarted {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        fmt.write_fmt(format_args!("COMMAND.{} {} STARTED: {}", self.command_name,
                                   self.connection_string, self.command))
    }
}

pub enum CommandResult<'a> {
    Success {
        duration: u64,
        reply: Document,
        command_name: String,
        request_id: i64,
        connection_string: String,
    },
    Failure {
        duration: u64,
        command_name: String,
        failure: &'a MongoError,
        request_id: i64,
        connection_string: String,
    }
}

impl<'a> Display for CommandResult<'a> {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        match self {
            &CommandResult::Success { duration, ref reply, ref command_name, request_id: _,
                                     ref connection_string } => {
                fmt.write_fmt(format_args!("COMMAND.{} {} COMPLETED: {} ({} ns)", command_name,
                                           connection_string, reply, duration))
            },
            &CommandResult::Failure { duration, ref command_name, ref failure, request_id: _,
                                      ref connection_string } => {
                fmt.write_fmt(format_args!("COMMAND.{} {} FAILURE: {} ({} NS)", command_name,
                                           connection_string, failure, duration))
            }
        }
    }
}
<|endoftext|>


<commit_before>#![warn(unused, bad_style,
        unused_qualifications, unused_typecasts, unused_results)]

#![feature(macro_rules, slicing_syntax)]

extern crate glob;
extern crate num;
extern crate serialize;
extern crate term;
extern crate common;

use std::{io, os, str};
use std::io::{Command, MemReader};
use std::io::process::ExitStatus;
use std::path::Display;
use std::str::{MaybeOwned, SendStr};
use glob::Paths;
use num::Integer;
use serialize::{json, Decodable};
use term::{color, Terminal};
use term::color::Color;
use common::SolveResult;

const PROBLEM_EXE_PAT: &'static str = "p[0-9][0-9][0-9]";

const NSEC_PER_SEC:    u64 = 1000000000;
const NSEC_WARN_LIMIT: u64 = 1  * NSEC_PER_SEC;
const NSEC_NG_LIMIT:   u64 = 10 * NSEC_PER_SEC;

const COLOR_OK:   Color = color::GREEN;
const COLOR_NG:   Color = color::RED;
const COLOR_WARN: Color = color::YELLOW;

macro_rules! try2(
    ($e:expr) => (try!($e.map_err(|e| e.to_program_error())))
)

type ProgramResult<T> = Result<T, ProgramError>;
type OutputPair<'a> = (Option<Color>, MaybeOwned<'a>);

#[deriving(Show)]
enum ProgramErrorKind {
    IoError(io::IoError),
    JsonSyntaxError(json::ErrorCode, uint, uint),
    JsonDecoderError(json::DecoderError),
    Unknown
}

#[deriving(Show)]
struct ProgramError {
    kind: ProgramErrorKind,
    message: SendStr
}

impl ProgramError {
    pub fn new<T: IntoMaybeOwned<'static>>(msg: T, kind: ProgramErrorKind) -> ProgramError {
        ProgramError {
            kind: kind,
            message: msg.into_maybe_owned()
        }
    }
}

trait ToProgramError {
    fn to_program_error(self) -> ProgramError;
}

impl ToProgramError for io::IoError {
    fn to_program_error(self) -> ProgramError {
        ProgramError::new(self.desc.into_maybe_owned(), IoError(self))
    }
}

impl ToProgramError for json::ParserError {
    fn to_program_error(self) -> ProgramError {
        match self {
            json::SyntaxError(code, line, col) => {
                ProgramError::new(format!("{}:{}:{}", line, col, json::error_str(code)),
                                  JsonSyntaxError(code, line, col))
            },
            json::IoError(kind, desc) => {
                (io::IoError {kind: kind, desc: desc, detail: None })
                    .to_program_error()
            }
        }
    }
}

impl ToProgramError for json::DecoderError {
    fn to_program_error(self: json::DecoderError) -> ProgramError {
        ProgramError::new(format!("{}", self), JsonDecoderError(self))
    }
}

fn exe_path() -> ProgramResult<Path> {
    match os::self_exe_name() {
        Some(x) => Ok(x),
        None    => Err(ProgramError::new("cannot get self exe name", Unknown))
    }
}

fn problem_paths(dir_path: Path) -> ProgramResult<Paths> {
    let pat = dir_path.join(PROBLEM_EXE_PAT);
    match pat.as_str() {
        Some(x) => Ok(glob::glob(x)),
        None    => Err(ProgramError::new("path contains non-utf8 character", Unknown))
    }
}

fn run_problem(path: &Path) -> ProgramResult<SolveResult<String>> {
    let proc_out = try2!(Command::new(path).output());

    if !proc_out.error.is_empty() {
        let _ = match str::from_utf8(proc_out.error[]) {
            Some(s) => writeln!(&mut io::stderr(), "{}", s.trim()),
            None    => writeln!(&mut io::stderr(), "{}", proc_out.error)
        };
    }

    match proc_out.status {
        ExitStatus(0) | ExitStatus(1) => { } // expected
        st => {
            return Err(ProgramError::new(format!("child process exit with {}", st), Unknown))
        }
    }

    let json = try2!(json::from_reader(&mut MemReader::new(proc_out.output)));
    Ok(try2!(Decodable::decode(&mut json::Decoder::new(json))))
}

fn print_items<'a>(items: &[OutputPair]) {
    match term::stdout() {
        None => {
            let mut out = io::stdout();
            for &(_, ref s) in items.iter() { let _ = out.write_str(s.as_slice()); }
            let _ = out.flush();
        },
        Some(mut t) => {
            for &(c, ref s) in items.iter() {
                match c {
                    Some(c) => { let _ = t.fg(c); let _ = t.write_str(s.as_slice()); let _ = t.reset(); }
                    None    => { let _ = t.write_str(s.as_slice()); }
                }
            }
            let _ = t.flush();
        }
    }
}

fn print_result<'a, T: GenericPath>(name: Display<T>, result: ProgramResult<SolveResult<String>>) {
    let mut items = vec![];
    match result {
        Ok(r) => {
            items.push(normal("["));
            if r.is_ok {
                items.push(ok("OK"));
            } else {
                items.push(ng("NG"));
            }
            items.push(normal("] "));
            items.push(normal(format!("{} ", name)));
            items.push(normal(format!("{:20} ", r.answer)));
            let (sec, nsec) = r.time.div_rem(&NSEC_PER_SEC);
            let time_str = format!("{:3}.{:09}", sec, nsec);
            if r.time < NSEC_WARN_LIMIT {
                items.push(normal(time_str));
            } else if r.time < NSEC_NG_LIMIT {
                items.push(warn(time_str));
            } else {
                items.push(ng(time_str));
            }
        }
        Err(e) => {
            items.push(normal("["));
            items.push(ng("!!"));
            items.push(normal("] "));
            items.push(normal(format!("{} ", name)));
            items.push(normal(format!("{}", e)));
            os::set_exit_status(1);
        }
    }
    items.push(normal("\n"));
    print_items(items[]);

    fn normal<'a, T: IntoMaybeOwned<'a>>(s: T) -> OutputPair<'a> {
        (None, s.into_maybe_owned())
    }
    fn ok<'a, T: IntoMaybeOwned<'a>>(s: T) -> OutputPair<'a> {
        (Some(COLOR_OK), s.into_maybe_owned())
    }
    fn warn<'a, T: IntoMaybeOwned<'a>>(s: T) -> OutputPair<'a> {
        (Some(COLOR_WARN), s.into_maybe_owned())
    }
    fn ng<'a, T: IntoMaybeOwned<'a>>(s: T) -> OutputPair<'a> {
        (Some(COLOR_NG), s.into_maybe_owned())
    }
}

fn run() -> ProgramResult<()> {
    let dir_path = try!(exe_path()).dir_path();

    for path in try!(problem_paths(dir_path)) {
        print_result(path.filename_display(), run_problem(&path));
    }

    Ok(())
}

fn main() {
    match run() {
        Ok(()) => {}
        Err(e) => {
            let _ = writeln!(&mut io::stderr(), "{}", e);
            os::set_exit_status(255);
        }
    }
}
<commit_msg>euler: set exitcode=1 when some test fails<commit_after>#![warn(unused, bad_style,
        unused_qualifications, unused_typecasts, unused_results)]

#![feature(macro_rules, slicing_syntax)]

extern crate glob;
extern crate num;
extern crate serialize;
extern crate term;
extern crate common;

use std::{io, os, str};
use std::io::{Command, MemReader};
use std::io::process::ExitStatus;
use std::path::Display;
use std::str::{MaybeOwned, SendStr};
use glob::Paths;
use num::Integer;
use serialize::{json, Decodable};
use term::{color, Terminal};
use term::color::Color;
use common::SolveResult;

const PROBLEM_EXE_PAT: &'static str = "p[0-9][0-9][0-9]";

const NSEC_PER_SEC:    u64 = 1000000000;
const NSEC_WARN_LIMIT: u64 = 1  * NSEC_PER_SEC;
const NSEC_NG_LIMIT:   u64 = 10 * NSEC_PER_SEC;

const COLOR_OK:   Color = color::GREEN;
const COLOR_NG:   Color = color::RED;
const COLOR_WARN: Color = color::YELLOW;

macro_rules! try2(
    ($e:expr) => (try!($e.map_err(|e| e.to_program_error())))
)

type ProgramResult<T> = Result<T, ProgramError>;
type OutputPair<'a> = (Option<Color>, MaybeOwned<'a>);

#[deriving(Show)]
enum ProgramErrorKind {
    IoError(io::IoError),
    JsonSyntaxError(json::ErrorCode, uint, uint),
    JsonDecoderError(json::DecoderError),
    Unknown
}

#[deriving(Show)]
struct ProgramError {
    kind: ProgramErrorKind,
    message: SendStr
}

impl ProgramError {
    pub fn new<T: IntoMaybeOwned<'static>>(msg: T, kind: ProgramErrorKind) -> ProgramError {
        ProgramError {
            kind: kind,
            message: msg.into_maybe_owned()
        }
    }
}

trait ToProgramError {
    fn to_program_error(self) -> ProgramError;
}

impl ToProgramError for io::IoError {
    fn to_program_error(self) -> ProgramError {
        ProgramError::new(self.desc.into_maybe_owned(), IoError(self))
    }
}

impl ToProgramError for json::ParserError {
    fn to_program_error(self) -> ProgramError {
        match self {
            json::SyntaxError(code, line, col) => {
                ProgramError::new(format!("{}:{}:{}", line, col, json::error_str(code)),
                                  JsonSyntaxError(code, line, col))
            },
            json::IoError(kind, desc) => {
                (io::IoError {kind: kind, desc: desc, detail: None })
                    .to_program_error()
            }
        }
    }
}

impl ToProgramError for json::DecoderError {
    fn to_program_error(self: json::DecoderError) -> ProgramError {
        ProgramError::new(format!("{}", self), JsonDecoderError(self))
    }
}

fn exe_path() -> ProgramResult<Path> {
    match os::self_exe_name() {
        Some(x) => Ok(x),
        None    => Err(ProgramError::new("cannot get self exe name", Unknown))
    }
}

fn problem_paths(dir_path: Path) -> ProgramResult<Paths> {
    let pat = dir_path.join(PROBLEM_EXE_PAT);
    match pat.as_str() {
        Some(x) => Ok(glob::glob(x)),
        None    => Err(ProgramError::new("path contains non-utf8 character", Unknown))
    }
}

fn run_problem(path: &Path) -> ProgramResult<SolveResult<String>> {
    let proc_out = try2!(Command::new(path).output());

    if !proc_out.error.is_empty() {
        let _ = match str::from_utf8(proc_out.error[]) {
            Some(s) => writeln!(&mut io::stderr(), "{}", s.trim()),
            None    => writeln!(&mut io::stderr(), "{}", proc_out.error)
        };
    }

    match proc_out.status {
        ExitStatus(0) | ExitStatus(1) => { } // expected
        st => {
            return Err(ProgramError::new(format!("child process exit with {}", st), Unknown))
        }
    }

    let json = try2!(json::from_reader(&mut MemReader::new(proc_out.output)));
    Ok(try2!(Decodable::decode(&mut json::Decoder::new(json))))
}

fn print_items<'a>(items: &[OutputPair]) {
    match term::stdout() {
        None => {
            let mut out = io::stdout();
            for &(_, ref s) in items.iter() { let _ = out.write_str(s.as_slice()); }
            let _ = out.flush();
        },
        Some(mut t) => {
            for &(c, ref s) in items.iter() {
                match c {
                    Some(c) => { let _ = t.fg(c); let _ = t.write_str(s.as_slice()); let _ = t.reset(); }
                    None    => { let _ = t.write_str(s.as_slice()); }
                }
            }
            let _ = t.flush();
        }
    }
}

fn print_result<'a, T: GenericPath>(name: Display<T>, result: ProgramResult<SolveResult<String>>) {
    let mut items = vec![];
    match result {
        Ok(r) => {
            items.push(normal("["));
            if r.is_ok {
                items.push(ok("OK"));
            } else {
                items.push(ng("NG"));
                os::set_exit_status(1);
            }
            items.push(normal("] "));
            items.push(normal(format!("{} ", name)));
            items.push(normal(format!("{:20} ", r.answer)));
            let (sec, nsec) = r.time.div_rem(&NSEC_PER_SEC);
            let time_str = format!("{:3}.{:09}", sec, nsec);
            if r.time < NSEC_WARN_LIMIT {
                items.push(normal(time_str));
            } else if r.time < NSEC_NG_LIMIT {
                items.push(warn(time_str));
            } else {
                items.push(ng(time_str));
            }
        }
        Err(e) => {
            items.push(normal("["));
            items.push(ng("!!"));
            items.push(normal("] "));
            items.push(normal(format!("{} ", name)));
            items.push(normal(format!("{}", e)));
            os::set_exit_status(1);
        }
    }
    items.push(normal("\n"));
    print_items(items[]);

    fn normal<'a, T: IntoMaybeOwned<'a>>(s: T) -> OutputPair<'a> {
        (None, s.into_maybe_owned())
    }
    fn ok<'a, T: IntoMaybeOwned<'a>>(s: T) -> OutputPair<'a> {
        (Some(COLOR_OK), s.into_maybe_owned())
    }
    fn warn<'a, T: IntoMaybeOwned<'a>>(s: T) -> OutputPair<'a> {
        (Some(COLOR_WARN), s.into_maybe_owned())
    }
    fn ng<'a, T: IntoMaybeOwned<'a>>(s: T) -> OutputPair<'a> {
        (Some(COLOR_NG), s.into_maybe_owned())
    }
}

fn run() -> ProgramResult<()> {
    let dir_path = try!(exe_path()).dir_path();

    for path in try!(problem_paths(dir_path)) {
        print_result(path.filename_display(), run_problem(&path));
    }

    Ok(())
}

fn main() {
    match run() {
        Ok(()) => {}
        Err(e) => {
            let _ = writeln!(&mut io::stderr(), "{}", e);
            os::set_exit_status(255);
        }
    }
}
<|endoftext|>


<commit_before>extern crate docopt;
use docopt::Docopt;

use std::io::{BufRead, BufReader, BufWriter, Write};
use std::fs::File;
use std::slice;
use std::mem;

static USAGE: &'static str = "
Usage: digest <source> <target>
";

fn main() {
    let args = Docopt::new(USAGE).and_then(|dopt| dopt.parse()).unwrap_or_else(|e| e.exit());

    println!("digest will overwrite <target>.targets and <target>.offsets, so careful");
    println!("at least, it will once you edit the code to uncomment the line.");
    let source = args.get_str("<source>");
    let _target = args.get_str("<target>");
    let graph = read_edges(&source);
    _digest_graph_vector(&_extract_fragment(graph.iter().map(|x| *x), 0, 1), _target); // will overwrite "prefix.offsets" and "prefix.targets"

}

// loads the read_edges file available at https://snap.stanford.edu/data/soc-LiveJournal1.html
fn read_edges(filename: &str) -> Vec<(u32, u32)> {
    let mut graph = Vec::new();
    let file = BufReader::new(File::open(filename).unwrap());
    for readline in file.lines() {
        let line = readline.ok().expect("read error");
        if !line.starts_with('#') {
            let elts: Vec<&str> = line[..].split(",").collect();
            let src: u32 = elts[0].parse().ok().expect("malformed src");
            let dst: u32 = elts[1].parse().ok().expect("malformed dst");
            graph.push((src, dst))
        }
    }

    println!("graph data loaded; {:?} edges", graph.len());
    return graph;
}

fn _extract_fragment<I: Iterator<Item=(u32, u32)>>(graph: I, index: u64, parts: u64) -> (Vec<u32>, Vec<u32>) {
    let mut nodes = Vec::new();
    let mut edges = Vec::new();

    for (src, dst) in graph {
        if src as u64 % parts == index {
            while src + 1 >= nodes.len() as u32 { nodes.push(0); }
            while dst + 1 >= nodes.len() as u32 { nodes.push(0); } // allows unsafe access to nodes

            nodes[src as usize + 1] += 1;
            edges.push(dst);
        }
    }

    for index in (1..nodes.len()) {
        nodes[index] += nodes[index - 1];
    }

    return (nodes, edges);
}

fn _digest_graph_vector(graph: &(Vec<u32>, Vec<u32>), output_prefix: &str) {
    let mut edge_writer = BufWriter::new(File::create(format!("{}.targets", output_prefix)).unwrap());
    let mut node_writer = BufWriter::new(File::create(format!("{}.offsets", output_prefix)).unwrap());
    node_writer.write_all(unsafe { _typed_as_byte_slice(&graph.0[..]) }).unwrap();

    let mut slice = unsafe { _typed_as_byte_slice(&graph.0[..]) };
    while slice.len() > 0 {
        let to_write = if slice.len() < 1000000 { slice.len() } else { 1000000 };
        edge_writer.write_all(&slice[..to_write]).unwrap();
        println!("wrote some; remaining: {}", slice.len());
        slice = &slice[to_write..];
    }
}

unsafe fn _typed_as_byte_slice<T>(slice: &[T]) -> &[u8] {
    slice::from_raw_parts(slice.as_ptr() as *const u8, slice.len() * mem::size_of::<T>())
}
<commit_msg>bug in which data are written out<commit_after>extern crate docopt;
use docopt::Docopt;

use std::io::{BufRead, BufReader, BufWriter, Write};
use std::fs::File;
use std::slice;
use std::mem;

static USAGE: &'static str = "
Usage: digest <source> <target>
";

fn main() {
    let args = Docopt::new(USAGE).and_then(|dopt| dopt.parse()).unwrap_or_else(|e| e.exit());

    println!("digest will overwrite <target>.targets and <target>.offsets, so careful");
    println!("at least, it will once you edit the code to uncomment the line.");
    let source = args.get_str("<source>");
    let _target = args.get_str("<target>");
    let graph = read_edges(&source);
    _digest_graph_vector(&_extract_fragment(graph.iter().map(|x| *x), 0, 1), _target); // will overwrite "prefix.offsets" and "prefix.targets"

}

// loads the read_edges file available at https://snap.stanford.edu/data/soc-LiveJournal1.html
fn read_edges(filename: &str) -> Vec<(u32, u32)> {
    let mut graph = Vec::new();
    let file = BufReader::new(File::open(filename).unwrap());
    for readline in file.lines() {
        let line = readline.ok().expect("read error");
        if !line.starts_with('#') {
            let elts: Vec<&str> = line[..].split("\t").collect();
            let src: u32 = elts[0].parse().ok().expect("malformed src");
            let dst: u32 = elts[1].parse().ok().expect("malformed dst");
            graph.push((src, dst))
        }
    }

    println!("graph data loaded; {:?} edges", graph.len());
    return graph;
}

fn _extract_fragment<I: Iterator<Item=(u32, u32)>>(graph: I, index: u64, parts: u64) -> (Vec<u32>, Vec<u32>) {
    let mut nodes = Vec::new();
    let mut edges = Vec::new();

    for (src, dst) in graph {
        if src as u64 % parts == index {
            while src + 1 >= nodes.len() as u32 { nodes.push(0); }
            while dst + 1 >= nodes.len() as u32 { nodes.push(0); } // allows unsafe access to nodes

            nodes[src as usize + 1] += 1;
            edges.push(dst);
        }
    }

    for index in (1..nodes.len()) {
        nodes[index] += nodes[index - 1];
    }

    return (nodes, edges);
}

fn _digest_graph_vector(graph: &(Vec<u32>, Vec<u32>), output_prefix: &str) {
    let mut edge_writer = BufWriter::new(File::create(format!("{}.targets", output_prefix)).unwrap());
    let mut node_writer = BufWriter::new(File::create(format!("{}.offsets", output_prefix)).unwrap());
    node_writer.write_all(unsafe { _typed_as_byte_slice(&graph.0[..]) }).unwrap();

    let mut slice = unsafe { _typed_as_byte_slice(&graph.1[..]) };
    while slice.len() > 0 {
        let to_write = if slice.len() < 1000000 { slice.len() } else { 1000000 };
        edge_writer.write_all(&slice[..to_write]).unwrap();
        println!("wrote some; remaining: {}", slice.len());
        slice = &slice[to_write..];
    }
}

unsafe fn _typed_as_byte_slice<T>(slice: &[T]) -> &[u8] {
    slice::from_raw_parts(slice.as_ptr() as *const u8, slice.len() * mem::size_of::<T>())
}
<|endoftext|>