<commit_before>use core_foundation::base::{CFRelease, CFRetain, CFTypeID, CFTypeRef, TCFType};
use event_source::{CGEventSource,CGEventSourceRef};

use libc;
use std::mem;
use std::ptr;

pub type CGKeyCode = libc::uint16_t;

/// Flags for events
///
/// [Ref] (http://opensource.apple.com//source/IOHIDFamily/IOHIDFamily-308/IOHIDSystem/IOKit/hidsystem/IOLLEvent.h)
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGEventFlags {
  // Device-independent modifier key bits.
  AlphaShift = 0x00010000,
  Shift = 0x00020000,
  Control = 0x00040000,
  Alternate = 0x00080000,
  Command = 0x00100000,

  // Special key identifiers.
  Help = 0x00400000,
  SecondaryFn = 0x00800000,

  // Identifies key events from numeric keypad area on extended keyboards.
  NumericPad = 0x00200000,

  // Indicates if mouse/pen movement events are not being coalesced
  NonCoalesced = 0x00000100,
}

/// Possible tapping points for events.
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGEventTapLocation {
    HIDEventTap,
    SessionEventTap,
    AnnotatedSessionEventTap,
}

#[repr(C)]
pub struct __CGEvent;

pub type CGEventRef = *const __CGEvent;

pub struct CGEvent {
    obj: CGEventRef,
}

impl Clone for CGEvent {
    #[inline]
    fn clone(&self) -> CGEvent {
        unsafe {
            TCFType::wrap_under_get_rule(self.obj)
        }
    }
}

impl Drop for CGEvent {
    fn drop(&mut self) {
        unsafe {
            let ptr = self.as_CFTypeRef();
            assert!(ptr != ptr::null());
            CFRelease(ptr);
        }
    }
}

impl TCFType<CGEventRef> for CGEvent {
    #[inline]
    fn as_concrete_TypeRef(&self) -> CGEventRef {
        self.obj
    }

    #[inline]
    unsafe fn wrap_under_get_rule(reference: CGEventRef) -> CGEvent {
        let reference: CGEventRef = mem::transmute(CFRetain(mem::transmute(reference)));
        TCFType::wrap_under_create_rule(reference)
    }

    #[inline]
    fn as_CFTypeRef(&self) -> CFTypeRef {
        unsafe {
            mem::transmute(self.as_concrete_TypeRef())
        }
    }

    #[inline]
    unsafe fn wrap_under_create_rule(obj: CGEventRef) -> CGEvent {
        CGEvent {
            obj: obj,
        }
    }

    #[inline]
    fn type_id() -> CFTypeID {
        unsafe {
            CGEventGetTypeID()
        }
    }
}

impl CGEvent {
    pub fn new(source: CGEventSource, keycode: CGKeyCode, keydown: bool) -> Result<CGEvent, ()> {
        unsafe {
            let event_ref = CGEventCreateKeyboardEvent(source.as_concrete_TypeRef(), keycode, keydown);
            if event_ref != ptr::null() {
                Ok(TCFType::wrap_under_create_rule(event_ref))
            } else {
                Err(())
            }
        }
    }

    pub fn post(&self, tapLocation: CGEventTapLocation) {
        unsafe {
            CGEventPost(tapLocation, self.as_concrete_TypeRef());
        }
    }

    pub fn post_to_pid(&self, pid: libc::pid_t) {
        unsafe {
            CGEventPostToPid(pid, self.as_concrete_TypeRef());
        }
    }

    pub fn set_flags(&self, flags: CGEventFlags) {
        unsafe {
            CGEventSetFlags(self.as_concrete_TypeRef(), flags);
        }
    }

    pub fn get_flags(&self) -> CGEventFlags {
        unsafe {
            CGEventGetFlags(self.as_concrete_TypeRef())
        }
    }
}

#[link(name = "ApplicationServices", kind = "framework")]
extern {
    /// Return the type identifier for the opaque type `CGEventRef'.
    fn CGEventGetTypeID() -> CFTypeID;

    /// Return a new keyboard event.
    ///
    /// The event source may be taken from another event, or may be NULL. Based
    /// on the virtual key code values entered, the appropriate key down, key up,
    /// or flags changed events are generated.
    ///
    /// All keystrokes needed to generate a character must be entered, including
    /// SHIFT, CONTROL, OPTION, and COMMAND keys. For example, to produce a 'Z',
    /// the SHIFT key must be down, the 'z' key must go down, and then the SHIFT
    /// and 'z' key must be released:
    fn CGEventCreateKeyboardEvent(source: CGEventSourceRef, keycode: CGKeyCode,
        keydown: bool) -> CGEventRef;

    /// Post an event into the event stream at a specified location.
    ///
    /// This function posts the specified event immediately before any event taps
    /// instantiated for that location, and the event passes through any such
    /// taps.
    fn CGEventPost(tapLocation: CGEventTapLocation, event: CGEventRef);

    /// Post an event to a specified process ID
    fn CGEventPostToPid(pid: libc::pid_t, event: CGEventRef);

    /// Set the event flags of an event.
    fn CGEventSetFlags(event: CGEventRef, flags: CGEventFlags);

    /// Return the event flags of an event.
    fn CGEventGetFlags(event: CGEventRef) -> CGEventFlags;
}
<commit_msg>Add MouseEvent<commit_after>use core_foundation::base::{CFRelease, CFRetain, CFTypeID, CFTypeRef, TCFType};
use geometry::CGPoint;
use event_source::{CGEventSource,CGEventSourceRef};

use libc;
use std::mem;
use std::ptr;

pub type CGKeyCode = libc::uint16_t;

/// Flags for events
///
/// [Ref](http://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-700/IOHIDSystem/IOKit/hidsystem/IOLLEvent.h)
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGEventFlags {
  // Device-independent modifier key bits.
  AlphaShift = 0x00010000,
  Shift = 0x00020000,
  Control = 0x00040000,
  Alternate = 0x00080000,
  Command = 0x00100000,

  // Special key identifiers.
  Help = 0x00400000,
  SecondaryFn = 0x00800000,

  // Identifies key events from numeric keypad area on extended keyboards.
  NumericPad = 0x00200000,

  // Indicates if mouse/pen movement events are not being coalesced
  NonCoalesced = 0x00000100,
}

/// Constants that specify the different types of input events.
///
/// [Ref](http://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-700/IOHIDSystem/IOKit/hidsystem/IOLLEvent.h)
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGEventType {
    Null = 1 << 0,

    // Mouse events.
    LeftMouseDown = 1 << 1,
    LeftMouseUp = 1 << 2,
    RightMouseDown = 1 << 3,
    RightMouseUp = 1 << 4,
    MouseMoved = 1 << 5,
    LeftMouseDragged = 1 << 6,
    RightMouseDragged = 1 << 7,

    // Keyboard events.
    KeyDown = 1 << 10,
    KeyUp = 1 << 11,
    FlagsChanged = 1 << 12,

    // Specialized control devices.
    ScrollWheel = 1 << 22,
    TabletPointer = 1 << 23,
    TabletProximity = 1 << 24,
    OtherMouseDown = 1 << 25,
    OtherMouseUp = 1 << 26,
    OtherMouseDragged = 1 << 27,

    // Out of band event types. These are delivered to the event tap callback
    // to notify it of unusual conditions that disable the event tap.
    TapDisabledByTimeout = 0xFFFFFFFE,
    TapDisabledByUserInput = 0xFFFFFFFF,
}

// Constants that specify buttons on a one, two, or three-button mouse.
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGMouseButton {
    Left,
    Right,
    Center,
}

/// Possible tapping points for events.
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub enum CGEventTapLocation {
    HIDEventTap,
    SessionEventTap,
    AnnotatedSessionEventTap,
}

#[repr(C)]
pub struct __CGEvent;

pub type CGEventRef = *const __CGEvent;

pub struct CGEvent {
    obj: CGEventRef,
}

impl Clone for CGEvent {
    #[inline]
    fn clone(&self) -> CGEvent {
        unsafe {
            TCFType::wrap_under_get_rule(self.obj)
        }
    }
}

impl Drop for CGEvent {
    fn drop(&mut self) {
        unsafe {
            let ptr = self.as_CFTypeRef();
            assert!(ptr != ptr::null());
            CFRelease(ptr);
        }
    }
}

impl TCFType<CGEventRef> for CGEvent {
    #[inline]
    fn as_concrete_TypeRef(&self) -> CGEventRef {
        self.obj
    }

    #[inline]
    unsafe fn wrap_under_get_rule(reference: CGEventRef) -> CGEvent {
        let reference: CGEventRef = mem::transmute(CFRetain(mem::transmute(reference)));
        TCFType::wrap_under_create_rule(reference)
    }

    #[inline]
    fn as_CFTypeRef(&self) -> CFTypeRef {
        unsafe {
            mem::transmute(self.as_concrete_TypeRef())
        }
    }

    #[inline]
    unsafe fn wrap_under_create_rule(obj: CGEventRef) -> CGEvent {
        CGEvent {
            obj: obj,
        }
    }

    #[inline]
    fn type_id() -> CFTypeID {
        unsafe {
            CGEventGetTypeID()
        }
    }
}

impl CGEvent {
    pub fn new(source: CGEventSource, keycode: CGKeyCode, keydown: bool) -> Result<CGEvent, ()> {
        unsafe {
            let event_ref = CGEventCreateKeyboardEvent(source.as_concrete_TypeRef(), keycode, keydown);
            if event_ref != ptr::null() {
                Ok(TCFType::wrap_under_create_rule(event_ref))
            } else {
                Err(())
            }
        }
    }

    pub fn post(&self, tapLocation: CGEventTapLocation) {
        unsafe {
            CGEventPost(tapLocation, self.as_concrete_TypeRef());
        }
    }

    pub fn post_to_pid(&self, pid: libc::pid_t) {
        unsafe {
            CGEventPostToPid(pid, self.as_concrete_TypeRef());
        }
    }

    pub fn set_flags(&self, flags: CGEventFlags) {
        unsafe {
            CGEventSetFlags(self.as_concrete_TypeRef(), flags);
        }
    }

    pub fn get_flags(&self) -> CGEventFlags {
        unsafe {
            CGEventGetFlags(self.as_concrete_TypeRef())
        }
    }
}

#[link(name = "ApplicationServices", kind = "framework")]
extern {
    /// Return the type identifier for the opaque type `CGEventRef'.
    fn CGEventGetTypeID() -> CFTypeID;

    /// Return a new keyboard event.
    ///
    /// The event source may be taken from another event, or may be NULL. Based
    /// on the virtual key code values entered, the appropriate key down, key up,
    /// or flags changed events are generated.
    ///
    /// All keystrokes needed to generate a character must be entered, including
    /// SHIFT, CONTROL, OPTION, and COMMAND keys. For example, to produce a 'Z',
    /// the SHIFT key must be down, the 'z' key must go down, and then the SHIFT
    /// and 'z' key must be released:
    fn CGEventCreateKeyboardEvent(source: CGEventSourceRef, keycode: CGKeyCode,
        keydown: bool) -> CGEventRef;

    /// Return a new mouse event.
    ///
    /// The event source may be taken from another event, or may be NULL.
    /// `mouseType' should be one of the mouse event types. `mouseCursorPosition'
    /// should be the position of the mouse cursor in global coordinates.
    /// `mouseButton' should be the button that's changing state; `mouseButton'
    /// is ignored unless `mouseType' is one of `kCGEventOtherMouseDown',
    /// `kCGEventOtherMouseDragged', or `kCGEventOtherMouseUp'.
    ///
    /// The current implemementation of the event system supports a maximum of
    /// thirty-two buttons. Mouse button 0 is the primary button on the mouse.
    /// Mouse button 1 is the secondary mouse button (right). Mouse button 2 is
    /// the center button, and the remaining buttons are in USB device order.
    fn CGEventCreateMouseEvent(source: CGEventSourceRef, mouseType: CGEventType,
        mouseCursorPosition: CGPoint, mouseButton: CGMouseButton) -> CGEventRef;

    /// Post an event into the event stream at a specified location.
    ///
    /// This function posts the specified event immediately before any event taps
    /// instantiated for that location, and the event passes through any such
    /// taps.
    fn CGEventPost(tapLocation: CGEventTapLocation, event: CGEventRef);

    /// Post an event to a specified process ID
    fn CGEventPostToPid(pid: libc::pid_t, event: CGEventRef);

    /// Set the event flags of an event.
    fn CGEventSetFlags(event: CGEventRef, flags: CGEventFlags);

    /// Return the event flags of an event.
    fn CGEventGetFlags(event: CGEventRef) -> CGEventFlags;
}
<|endoftext|>


<commit_before>fn edit_distance(str1: &str, str2: &str) -> usize {
    // TODO
    1
}

#[cfg(test)]
mod test {
    use fdupe;

    #[test]
    fn test_edit_distance() {
        assert_eq!(1, fdupe::edit_distance("hello", "holla"));
    }
}<commit_msg>Pseudo code for edit distance<commit_after>use std::cmp;

fn edit_distance(str1: &str, str2: &str) -> usize {
    // let str1_size = str1.chars().count() + 1;
    // let str2_size = str2.chars().count() + 1;
    // let mut dp = vec![vec![0; str2_size]; str1_size];
    // for i in 0..str1_size {
    //     for j in 0..str2_size {
    //         if i == 0 {
    //             dp[i][j] = j;
    //         } else if j == 0 {
    //             dp[i][j] = i;
    //         } else if vec_str1[i - 1] == vec_str2[j - 1] {
    //             dp[i][j] = dp[i - 1][j - 1];
    //         } else {
    //             dp[i][j] = 1 + cmp::min(
    //                 dp[i][j - 1],
    //                 cmp::min(dp[i - 1][j],
    //                     dp[i - 1][j - 1]));
    //         }
    //     }
    // }
    // dp[str1_size][str2_size]
    0
}

#[cfg(test)]
mod test {
    use fdupe;

    #[test]
    fn test_edit_distance() {
        assert_eq!(1, fdupe::edit_distance("hello", "holla"));
    }
}<|endoftext|>


<commit_before>use ::*;
use rand::Rng;
use rocket::response::Responder;

#[get("/newgame")]
fn newgame<'a>() -> Res<'a> {
    TERA.render("pages/newgame.html", newgame_con()).respond()
}

fn newgame_con() -> Context {
    let conn = DB_CONNECTION.lock().unwrap();
    let mut stmt = conn.prepare("SELECT id, name FROM players").unwrap();
    let mut names: Vec<_> = stmt.query_map(&[], |row| {
            Named {
                id: row.get(0),
                name: row.get(1)
            }
        })
        .unwrap()
        .map(Result::unwrap)
        .collect();

    names.sort_by(|_, _| *rand::thread_rng().choose(&[Greater, Less]).unwrap());

    let mut ballstmt = conn.prepare("SELECT id, name, img FROM balls").unwrap();
    let balls: Vec<_> = ballstmt.query_map(&[], |row| {
            Ball {
                id: row.get(0),
                name: row.get(1),
                img: row.get(2),
            }
        })
        .unwrap()
        .map(Result::unwrap)
        .collect();

    let mut context = create_context("newgame");

    context.add("names", &names);
    context.add("balls", &balls);
    context
}

fromform_struct!{
    struct NewGame {
        home: i32,
        away: i32,
        home_score: i32,
        away_score: i32,
        ball: i32,
        secret: String,
    }
}

#[post("/newgame/submit", data = "<f>")]
fn submit_newgame<'a>(f: Form<NewGame>) -> Res<'a> {
    let conn = DB_CONNECTION.lock().unwrap();
    let f = f.into_inner();

    if f.secret != CONFIG.secret {
        let mut context = newgame_con();
        context.add("fejl", &"Det indtastede kodeord er forkert 💩");
        return TERA.render("pages/newgame_fejl.html", context).respond();
    }

    if !(f.home_score == 10 || f.away_score == 10) || f.home_score == f.away_score ||
       f.home == f.away {
        let mut context = newgame_con();

        context.add("fejl",
                       &"Den indtastede kamp er ikke lovlig 😜");
        return TERA.render("pages/newgame_fejl.html", context).respond();
    }

    let res = conn.execute("INSERT INTO games (home_id, away_id, home_score, away_score, dato, \
                            ball_id) VALUES (?, ?, ?, ?, datetime('now'), ?)",
                           &[&f.home, &f.away, &f.home_score, &f.away_score, &f.ball]);
    println!("{:?}", res);

    Redirect::to("/").respond()
}

#[get("/games")]
fn games<'a>() -> Res<'a> {
    let conn = DB_CONNECTION.lock().unwrap();
    let mut stmt =
        conn.prepare("SELECT (SELECT name FROM players p WHERE p.id = g.home_id) AS home, \
                      (SELECT name FROM players p WHERE p.id = g.away_id) AS away, home_score, \
                      away_score, ball_id, (SELECT img FROM balls b WHERE ball_id = b.id), \
                      (SELECT name FROM balls b WHERE ball_id = b.id), dato FROM games g ORDER BY ID DESC")
            .unwrap();
    let games: Vec<_> = stmt.query_map(&[], |row| {
            PlayedGame {
                home: row.get(0),
                away: row.get(1),
                home_score: row.get(2),
                away_score: row.get(3),
                ball: row.get(5),
                ball_name: row.get(6),
                dato: row.get(7),
            }
        })
        .unwrap()
        .map(Result::unwrap)
        .collect();

    let mut context = create_context("games");

    context.add("games", &games);
    TERA.render("pages/games.html", context).respond()
}
<commit_msg>Fix #21<commit_after>use ::*;
use rand::Rng;
use rocket::response::Responder;

#[get("/newgame")]
fn newgame<'a>() -> Res<'a> {
    TERA.render("pages/newgame.html", newgame_con()).respond()
}

fn newgame_con() -> Context {
    let conn = DB_CONNECTION.lock().unwrap();
    let mut stmt = conn.prepare("SELECT id, name FROM players").unwrap();
    let mut names: Vec<_> = stmt.query_map(&[], |row| {
            Named {
                id: row.get(0),
                name: row.get(1)
            }
        })
        .unwrap()
        .map(Result::unwrap)
        .collect();

    names.sort_by(|_, _| *rand::thread_rng().choose(&[Greater, Less]).unwrap());

    let mut ballstmt = conn.prepare("SELECT id, name, img FROM balls").unwrap();
    let balls: Vec<_> = ballstmt.query_map(&[], |row| {
            Ball {
                id: row.get(0),
                name: row.get(1),
                img: row.get(2),
            }
        })
        .unwrap()
        .map(Result::unwrap)
        .collect();

    let mut context = create_context("newgame");

    context.add("names", &names);
    context.add("balls", &balls);
    context
}

fromform_struct!{
    struct NewGame {
        home: i32,
        away: i32,
        home_score: i32,
        away_score: i32,
        ball: i32,
        secret: String,
    }
}

#[post("/newgame/submit", data = "<f>")]
fn submit_newgame<'a>(f: Form<NewGame>) -> Res<'a> {
    let f = f.into_inner();

    if f.secret != CONFIG.secret {
        let mut context = newgame_con();
        context.add("fejl", &"Det indtastede kodeord er forkert 💩");
        return TERA.render("pages/newgame_fejl.html", context).respond();
    }

    if !(f.home_score == 10 || f.away_score == 10) || f.home_score == f.away_score ||
       f.home == f.away {
        let mut context = newgame_con();

        context.add("fejl",
                       &"Den indtastede kamp er ikke lovlig 😜");
        return TERA.render("pages/newgame_fejl.html", context).respond();
    }

    let res = DB_CONNECTION.lock().unwrap().execute("INSERT INTO games (home_id, away_id, home_score, away_score, dato, \
                            ball_id) VALUES (?, ?, ?, ?, datetime('now'), ?)",
                           &[&f.home, &f.away, &f.home_score, &f.away_score, &f.ball]);
    println!("{:?}", res);

    Redirect::to("/").respond()
}

#[get("/games")]
fn games<'a>() -> Res<'a> {
    let conn = DB_CONNECTION.lock().unwrap();
    let mut stmt =
        conn.prepare("SELECT (SELECT name FROM players p WHERE p.id = g.home_id) AS home, \
                      (SELECT name FROM players p WHERE p.id = g.away_id) AS away, home_score, \
                      away_score, ball_id, (SELECT img FROM balls b WHERE ball_id = b.id), \
                      (SELECT name FROM balls b WHERE ball_id = b.id), dato FROM games g ORDER BY ID DESC")
            .unwrap();
    let games: Vec<_> = stmt.query_map(&[], |row| {
            PlayedGame {
                home: row.get(0),
                away: row.get(1),
                home_score: row.get(2),
                away_score: row.get(3),
                ball: row.get(5),
                ball_name: row.get(6),
                dato: row.get(7),
            }
        })
        .unwrap()
        .map(Result::unwrap)
        .collect();

    let mut context = create_context("games");

    context.add("games", &games);
    TERA.render("pages/games.html", context).respond()
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

use vertex::Vertex;
use path::Element;
use treepath::TreePath;
use parser::{parse, Arg};
use std::sync::mpsc::{channel, Sender};

#[derive(Debug)]
pub struct Graph {
    elements: i64,
    vertices: HashMap<i64, Vertex>
}

// comes in through the request channel
pub struct Request {
    query: String
}

// graph is not thread safe - needs to be wrapped in an Arc<Mutex> when running as server
impl Graph {
    pub fn new() -> Box<Graph> {
        Box::new(Graph{elements:0,
                        vertices:HashMap::new() })
    }

    pub fn execution_channel(&self) -> Sender<Request> {
        let (tx, rx) = channel();
        // fire off listener thread for receiving messages

        tx
    }

    pub fn execute(&self, query: &str) -> Result<GraphQueryResult, &str>  {
        // parse the graph query

        // let mut steps_table : HashMap<&'static str, FnMut() -> Result<&'static str, &'static str> > = HashMap::new();
        // steps_table.insert("outV", traverse_out);
        // steps_table.insert("inV", traverse_in);

        // todo - validate query is using legit steps
        let mut result = GraphQueryResult::new();
        println!("===== Begin query {} ======", query);
        match parse(query) {
            Ok(query) => {
                // execute each of the steps sequentially
                for step in query.steps.iter() {
                    // lookup step in hash table
                    println!("{}", step);

                    let name : &str = &step.name;

                    // there has to be a better way of doing this?
                    let step_result = match name {
                        "outV" => self.traverse_out_vertex(&step.args),
                        "inV" => self.traverse_in_vertex(&step.args),
                        "outE" => self.traverse_out_edge(&step.args),
                        "inE" => self.traverse_in_edge(&step.args),
                        "v" => self.vertex_query(&mut result, &step.args),
                        "V" => self.global_query(&result, &step.args),
                        _ => return Err("no step found")
                    };
                    match step_result {
                        Err(_) => return Err("fail"),
                        Ok(_) => ()
                    };
                    // execute function, passing step args
                }
            },
            Err(_) => {
                println!("SUCH FAIL!!!!")

            }
                // Result::Err("meh")
        };
        println!("===== query finished =====");
        Ok(result)
    }

    fn vertex_query(&self, result: &mut GraphQueryResult, args: &Vec<Arg>) ->
                    Result<&'static str, &'static str>  {

        println!("vertex query");
        // gather the requested vertices
        let mut error = false;

        for arg in args.iter() {
            // this better be an integer
            match *arg {
                Arg::Integer(x) => {
                    // lookup the vertex
                    let v = self.get(x);
                    match v {
                        Some(vertex) => {
                            result.tree.add_child(Element::Vertex(vertex));
                        },
                        None => { }
                    }
                }
                _ => error = true
            }
        }
        if error {
            Err("errors")
        } else {
            Ok("you are a pirate")
        }
    }

    fn global_query(&self, result: &GraphQueryResult, args: &Vec<Arg>)
        -> Result<&'static str, &'static str>  {
        println!("global query");
        unimplemented!();
        Ok("cool")
    }

    fn traverse_out_vertex(&self, args: &Vec<Arg>) -> Result<&'static str, &'static str>  {
        println!("outV traversal");

        Ok("cool")
    }

    fn traverse_in_vertex(&self, args: &Vec<Arg>) -> Result<&'static str, &'static str>  {
        println!("inV traversal");

        unimplemented!();
        Ok("cool")
    }

    fn traverse_out_edge(&self, args: &Vec<Arg>) -> Result<&'static str, &'static str>  {
        println!("outE traversal");
        unimplemented!();
        Ok("cool")
    }

    fn traverse_in_edge(&self, args: &Vec<Arg>) -> Result<&'static str, &'static str>  {
        println!("inE traversal");
        unimplemented!();
        Ok("cool")
    }
    pub fn add_vertex(&mut self) -> Vertex {
        let new_id = self.elements + 1;
        self.elements += 1;
        let v = Vertex::new(new_id);
        self.vertices.insert(new_id, v.clone());
        // return the proxy which knows it's own id
        v
    }

    pub fn get(&self, vertex_id:i64) -> Option<Vertex>  {
        self.vertices.get(&vertex_id).cloned()
    }

}

pub trait TraversableToVertex {
	fn inV(&self) -> Vec<Vertex>;
	fn outV(&self, &[&str]) -> Vec<Vertex>;
//	fn inE(&self) -> Vec<Edge>;

}

pub struct GraphQueryResult {
    pub tree: TreePath
}

impl GraphQueryResult {
    pub fn new() -> GraphQueryResult {
        GraphQueryResult{ tree: TreePath::new() }
    }
}
<commit_msg>new add edge call, now on graph<commit_after>use std::collections::HashMap;

use vertex::Vertex;
use path::Element;
use treepath::TreePath;
use parser::{parse, Arg};
use std::sync::mpsc::{channel, Sender};
use edge::{EdgePointer, Edge};

#[derive(Debug)]
pub struct Graph {
    elements: i64,
    vertices: HashMap<i64, Vertex>
}

// comes in through the request channel
pub struct Request {
    query: String
}

// graph is not thread safe - needs to be wrapped in an Arc<Mutex> when running as server
impl Graph {
    pub fn new() -> Box<Graph> {
        Box::new(Graph{elements:0,
                        vertices:HashMap::new() })
    }

    pub fn execution_channel(&self) -> Sender<Request> {
        let (tx, rx) = channel();
        // fire off listener thread for receiving messages

        tx
    }

    pub fn add_edge(&self, v1: &Vertex, v2: &Vertex, label: String) -> EdgePointer {
        println!("adding vertex of edge {}", label.to_string());

        // keep it on the heap but manage it myself
        let edge = Edge::new(v1.clone(), v2.clone(), label);

        v1.write().unwrap().out_edges.push(edge.clone());
        v2.write().unwrap().in_edges.push(edge.clone());
        edge

    }
    pub fn execute(&self, query: &str) -> Result<GraphQueryResult, &str>  {
        // parse the graph query

        // let mut steps_table : HashMap<&'static str, FnMut() -> Result<&'static str, &'static str> > = HashMap::new();
        // steps_table.insert("outV", traverse_out);
        // steps_table.insert("inV", traverse_in);

        // todo - validate query is using legit steps
        let mut result = GraphQueryResult::new();
        println!("===== Begin query {} ======", query);
        match parse(query) {
            Ok(query) => {
                // execute each of the steps sequentially
                for step in query.steps.iter() {
                    // lookup step in hash table
                    println!("{}", step);

                    let name : &str = &step.name;

                    // there has to be a better way of doing this?
                    let step_result = match name {
                        "outV" => self.traverse_out_vertex(&step.args),
                        "inV" => self.traverse_in_vertex(&step.args),
                        "outE" => self.traverse_out_edge(&step.args),
                        "inE" => self.traverse_in_edge(&step.args),
                        "v" => self.vertex_query(&mut result, &step.args),
                        "V" => self.global_query(&result, &step.args),
                        _ => return Err("no step found")
                    };
                    match step_result {
                        Err(_) => return Err("fail"),
                        Ok(_) => ()
                    };
                    // execute function, passing step args
                }
            },
            Err(_) => {
                println!("SUCH FAIL!!!!")

            }
                // Result::Err("meh")
        };
        println!("===== query finished =====");
        Ok(result)
    }

    fn vertex_query(&self, result: &mut GraphQueryResult, args: &Vec<Arg>) ->
                    Result<&'static str, &'static str>  {

        println!("vertex query");
        // gather the requested vertices
        let mut error = false;

        for arg in args.iter() {
            // this better be an integer
            match *arg {
                Arg::Integer(x) => {
                    // lookup the vertex
                    let v = self.get(x);
                    match v {
                        Some(vertex) => {
                            result.tree.add_child(Element::Vertex(vertex));
                        },
                        None => { }
                    }
                }
                _ => error = true
            }
        }
        if error {
            Err("errors")
        } else {
            Ok("you are a pirate")
        }
    }

    fn global_query(&self, result: &GraphQueryResult, args: &Vec<Arg>)
        -> Result<&'static str, &'static str>  {
        println!("global query");
        unimplemented!();
        Ok("cool")
    }

    fn traverse_out_vertex(&self, args: &Vec<Arg>) -> Result<&'static str, &'static str>  {
        println!("outV traversal");

        Ok("cool")
    }

    fn traverse_in_vertex(&self, args: &Vec<Arg>) -> Result<&'static str, &'static str>  {
        println!("inV traversal");

        unimplemented!();
        Ok("cool")
    }

    fn traverse_out_edge(&self, args: &Vec<Arg>) -> Result<&'static str, &'static str>  {
        println!("outE traversal");
        unimplemented!();
        Ok("cool")
    }

    fn traverse_in_edge(&self, args: &Vec<Arg>) -> Result<&'static str, &'static str>  {
        println!("inE traversal");
        unimplemented!();
        Ok("cool")
    }
    pub fn add_vertex(&mut self) -> Vertex {
        let new_id = self.elements + 1;
        self.elements += 1;
        let v = Vertex::new(new_id);
        self.vertices.insert(new_id, v.clone());
        // return the proxy which knows it's own id
        v
    }

    pub fn get(&self, vertex_id:i64) -> Option<Vertex>  {
        self.vertices.get(&vertex_id).cloned()
    }

}

pub trait TraversableToVertex {
	fn inV(&self) -> Vec<Vertex>;
	fn outV(&self, &[&str]) -> Vec<Vertex>;
//	fn inE(&self) -> Vec<Edge>;

}

pub struct GraphQueryResult {
    pub tree: TreePath
}

impl GraphQueryResult {
    pub fn new() -> GraphQueryResult {
        GraphQueryResult{ tree: TreePath::new() }
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::mem;

use vertex::{RawVertex,Vertex};
use traversal::GraphQuery;
use path::{Path, Element};
use edge::Edge;
use parser::parse;

#[derive(Debug)]
pub struct Graph {
    elements: i64,
    // we transmute our Boxed vertex into a pointer later
    vertices: HashMap<i64, *mut RawVertex>,
    queue: Vec<String>,
}

// graph is not thread safe - needs to be wrapped in an Arc<Mutex> when running as server
impl Graph {
    pub fn new() -> Box<Graph> {
        let vertices: HashMap<i64, *mut RawVertex> = HashMap::new();
        Box::new(Graph{elements:0, vertices:vertices, queue:Vec::with_capacity(100)})
    }

    // todo actually return a result DERP DERP DERP
    pub fn execute(&self, query: &str) {
        // parse the graph query

        let mut steps_table = HashMap::new();
        steps_table.insert("outV", traverse_out);
        steps_table.insert("inV", traverse_out);

        match parse(query) {
            Ok(query) => {
                // execute each of the steps sequentially
                for step in query.steps.iter() {
                    // lookup step in hash table
                    println!("{}", step);
                    // execute function, passing step args
                }
            },
            Err(x) => {
                println!("SUCH FAIL!!!!")
            }
                // Result::Err("meh")
        }

        // i'm tempted to say global graph traversals must include a
        // starting point, g.v(predicate)

    }

    pub fn add_vertex(&mut self) -> Vertex {
        let new_id = self.elements + 1;
        self.elements += 1;
        let v = RawVertex::new(new_id);
        let ptr: *mut RawVertex = unsafe { mem::transmute(v) };

        self.vertices.insert(new_id, ptr);

        // return the proxy which knows it's own id
        Vertex{id:new_id, v: ptr}
    }

    pub fn get(&self, vertex_id:i64) -> Option<Vertex>  {
        let vertex_pointer = self.vertices.get(&vertex_id);
        // return a proxy
        match vertex_pointer {
            Some(ptr) =>
                Some(Vertex{id:vertex_id, v:*ptr}),
            None =>
                None
        }
    }

    // this will be used to start a graph query
    pub fn v(&self, vertex_id:i64) -> GraphQuery {
        // grab the original vertex
        let vertex = self.get(vertex_id);
        let mut v = Vec::new();
        match vertex {
            Some(result) => {
                v.push(result);
                GraphQuery::new(v)
            }
            None => GraphQuery::empty()
        }
    }
}

pub trait TraversableToVertex {
	fn inV(&self) -> Vec<Vertex>;
	fn outV(&self, &[&str]) -> Vec<Vertex>;
//	fn inE(&self) -> Vec<Edge>;

}

fn traverse_out() -> Result<&'static str, &'static str>  {
    Ok("cool")
}

fn traverse_in() -> Result<&'static str, &'static str>  {
    Ok("cool")

}
<commit_msg>starting to set up the steps<commit_after>use std::collections::HashMap;
use std::mem;

use vertex::{RawVertex,Vertex};
use traversal::GraphQuery;
use path::{Path, Element};
use edge::Edge;
use parser::parse;

#[derive(Debug)]
pub struct Graph {
    elements: i64,
    // we transmute our Boxed vertex into a pointer later
    vertices: HashMap<i64, *mut RawVertex>,
    queue: Vec<String>,
}

// graph is not thread safe - needs to be wrapped in an Arc<Mutex> when running as server
impl Graph {
    pub fn new() -> Box<Graph> {
        let vertices: HashMap<i64, *mut RawVertex> = HashMap::new();
        Box::new(Graph{elements:0, vertices:vertices, queue:Vec::with_capacity(100)})
    }

    // todo actually return a result DERP DERP DERP
    pub fn execute(&self, query: &str) {
        // parse the graph query

        // let mut steps_table : HashMap<&'static str, FnMut() -> Result<&'static str, &'static str> > = HashMap::new();
        // steps_table.insert("outV", traverse_out);
        // steps_table.insert("inV", traverse_in);

        // todo - validate query is using legit steps

        match parse(query) {
            Ok(query) => {
                // execute each of the steps sequentially
                for step in query.steps.iter() {
                    // lookup step in hash table
                    println!("{}", step);

                    let name : &str = &step.name;
                    let step_result = match name {
                        "outV" => self.traverse_out_vertex(),
                        "inV" => self.traverse_in_vertex(),
                        _ => Err("no thingy found")
                    };
                    // execute function, passing step args
                }
            },
            Err(x) => {
                println!("SUCH FAIL!!!!")
            }
                // Result::Err("meh")
        }
        println!("query finished");
        ()
    }

    fn traverse_out_vertex(&self) -> Result<&'static str, &'static str>  {
        Ok("cool")
    }

    fn traverse_in_vertex(&self) -> Result<&'static str, &'static str>  {
        Ok("cool")
    }

    pub fn add_vertex(&mut self) -> Vertex {
        let new_id = self.elements + 1;
        self.elements += 1;
        let v = RawVertex::new(new_id);
        let ptr: *mut RawVertex = unsafe { mem::transmute(v) };

        self.vertices.insert(new_id, ptr);

        // return the proxy which knows it's own id
        Vertex{id:new_id, v: ptr}
    }

    pub fn get(&self, vertex_id:i64) -> Option<Vertex>  {
        let vertex_pointer = self.vertices.get(&vertex_id);
        // return a proxy
        match vertex_pointer {
            Some(ptr) =>
                Some(Vertex{id:vertex_id, v:*ptr}),
            None =>
                None
        }
    }

    // this will be used to start a graph query
    pub fn v(&self, vertex_id:i64) -> GraphQuery {
        // grab the original vertex
        let vertex = self.get(vertex_id);
        let mut v = Vec::new();
        match vertex {
            Some(result) => {
                v.push(result);
                GraphQuery::new(v)
            }
            None => GraphQuery::empty()
        }
    }
}

pub trait TraversableToVertex {
	fn inV(&self) -> Vec<Vertex>;
	fn outV(&self, &[&str]) -> Vec<Vertex>;
//	fn inE(&self) -> Vec<Edge>;

}
<|endoftext|>


<commit_before>use std::collections::{HashMap, HashSet, VecDeque};
use std::hash::Hash;

use crate::colour::Colour;
use crate::grid::Grid;

// Represent the state of the game as a graph.  One node for each cell.  There is an edge between
// two cells if and only if they are the same colour and have a distance of 1 according to the
// Manhattan metric.
//
// The game has only one real operation (i.e. not counting level generation): Switching the colour
// of the connected component containing the top left cell to whichever colour the clicked cell
// has.  This results in said component growing by every component it neighbours which has its new
// colour.  In essence, the aim of the gaim is to join connected components until only one is
// left.  Fewer clicks is better.
//
// So, we represent the game state as a collection of connected components, each of which has a
// colour, a list of coordinates of the constituent cells, and a list of it s neighbours.  As we
// do all our operations on connected components, we actually work not with the graph of
// neighbouring cells but with a graph of connected components.  The graph of connected components
// is made up of one node representing each connected component and an edge between any two
// connected components that have cells which share an edge, i.e. two cells which would have been
// connected by an edge in the original graph if they had had the same colour (which they did
// not).

#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct Position {
    pub row: usize,
    pub column: usize,
}

#[derive(Debug, Clone)]
pub struct ConnectedComponent {
    id: usize,
    pub colour: Colour,
    pub cells: HashSet<Position>,
}

impl PartialEq for ConnectedComponent {
    fn eq(&self, other: &Self) -> bool {
        self.id == other.id
    }
}

impl Eq for ConnectedComponent {}

impl Hash for ConnectedComponent {
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
        self.id.hash(state);
    }
}

#[derive(Debug)]
pub struct Graph {
    pub components: HashMap<usize, ConnectedComponent>,
    pub neighbours: HashMap<usize, HashSet<usize>>,
}

fn find_connected_components(grid: &Grid) -> Vec<(ConnectedComponent, HashSet<usize>)> {
    let rows = grid.number_of_rows;
    let columns = grid.number_of_columns;

    let mut remaining_cells: HashSet<usize> = (0..grid.cells.len()).into_iter().collect();

    let mut components = vec![];
    let mut counter = 0;

    // Take any element to land in any component.
    while let Some(&start_cell_index) = remaining_cells.iter().next() {
        let mut visited = HashSet::new();
        let mut neighbours = HashSet::new();
        let mut queue = VecDeque::new();

        queue.push_back(start_cell_index);

        // Gather all cells in the connected component of start_cell_index.
        while let Some(i) = queue.pop_front() {
            visited.insert(i);
            remaining_cells.remove(&i);

            let mut neighbouring_cells = vec![];
            if i % columns > 0 {
                neighbouring_cells.push(i - 1);
            }
            if i % columns < columns - 1 {
                neighbouring_cells.push(i + 1);
            }
            if i >= columns {
                neighbouring_cells.push(i - columns)
            }
            if i < (rows - 1) * columns {
                neighbouring_cells.push(i + columns)
            }

            for neighbour in neighbouring_cells {
                if visited.contains(&neighbour) {
                    continue;
                }

                if grid.cells[i] == grid.cells[neighbour] {
                    queue.push_back(neighbour);
                } else {
                    neighbours.insert(neighbour);
                }
            }
        }

        let cells = visited
            .iter()
            .map(|&i| Position {
                column: i % columns,
                row: i / columns,
            })
            .collect();

        let component = ConnectedComponent {
            id: counter,
            colour: grid.cells[*visited.iter().next().unwrap()],
            cells,
        };
        counter += 1;

        components.push((component, neighbours));
    }

    return components;
}

impl Graph {
    pub fn create(grid: &Grid) -> Self {
        let components_and_neighbours = find_connected_components(&grid);

        let mut components = HashMap::with_capacity(components_and_neighbours.len());
        let mut neighbours: HashMap<usize, HashSet<usize>> = HashMap::new();

        for (c, n) in components_and_neighbours.into_iter() {
            let id = c.id;
            components.insert(id, c);
            neighbours.insert(id, n);
        }

        Self {
            components,
            neighbours
        }
    }

    fn to_grid(&self, rows: usize, columns: usize) -> Grid {
        let mut cells = vec![Colour::Red; rows * columns];

        for component in self.neighbours.keys() {
            for position in &self.components[component].cells {
                cells[position.column + position.row * columns] = self.components[component].colour;
            }
        }

        Grid {
            number_of_rows: rows,
            number_of_columns: columns,
            cells,
        }
    }

    pub fn find_component(&self, position: &Position) -> &ConnectedComponent {
        for component in self.neighbours.keys() {
            if self.components[component].cells.contains(&position) {
                return &self.components[component];
            }
        }

        unreachable!()
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn should_return_same_grid_as_input() {
        let size = 4;
        let grid = Grid::generate(size);

        let graph = Graph::create(&grid);
        let reconstituted_grid = graph.to_grid(size, size);

        assert_eq!(reconstituted_grid, grid);
    }

    #[test]
    fn should_have_one_component() {
        let grid = Grid {
            number_of_columns: 2,
            number_of_rows: 2,
            cells: vec![Colour::Red; 4],
        };

        let graph = Graph::create(&grid);

        assert_eq!(graph.neighbours.len(), 1);
    }

    #[test]
    fn should_have_four_component() {
        let grid = Grid {
            number_of_columns: 2,
            number_of_rows: 2,
            cells: vec![Colour::Red, Colour::Yellow, Colour::Yellow, Colour::Red],
        };

        let graph = Graph::create(&grid);

        assert_eq!(graph.neighbours.len(), 4);
    }

    #[test]
    fn should_have_two_component() {
        let grid = Grid {
            number_of_columns: 2,
            number_of_rows: 2,
            cells: vec![Colour::Red, Colour::Red, Colour::Yellow, Colour::Yellow],
        };

        let graph = Graph::create(&grid);

        assert_eq!(graph.neighbours.len(), 2);
    }
}
<commit_msg>Check component IDs in Graph<commit_after>use std::collections::{HashMap, HashSet, VecDeque};
use std::hash::Hash;

use crate::colour::Colour;
use crate::grid::Grid;

// Represent the state of the game as a graph.  One node for each cell.  There is an edge between
// two cells if and only if they are the same colour and have a distance of 1 according to the
// Manhattan metric.
//
// The game has only one real operation (i.e. not counting level generation): Switching the colour
// of the connected component containing the top left cell to whichever colour the clicked cell
// has.  This results in said component growing by every component it neighbours which has its new
// colour.  In essence, the aim of the gaim is to join connected components until only one is
// left.  Fewer clicks is better.
//
// So, we represent the game state as a collection of connected components, each of which has a
// colour, a list of coordinates of the constituent cells, and a list of it s neighbours.  As we
// do all our operations on connected components, we actually work not with the graph of
// neighbouring cells but with a graph of connected components.  The graph of connected components
// is made up of one node representing each connected component and an edge between any two
// connected components that have cells which share an edge, i.e. two cells which would have been
// connected by an edge in the original graph if they had had the same colour (which they did
// not).

#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct Position {
    pub row: usize,
    pub column: usize,
}

#[derive(Debug, Clone)]
pub struct ConnectedComponent {
    id: usize,
    pub colour: Colour,
    pub cells: HashSet<Position>,
}

impl PartialEq for ConnectedComponent {
    fn eq(&self, other: &Self) -> bool {
        self.id == other.id
    }
}

impl Eq for ConnectedComponent {}

impl Hash for ConnectedComponent {
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
        self.id.hash(state);
    }
}

#[derive(Debug)]
pub struct Graph {
    pub components: HashMap<usize, ConnectedComponent>,
    pub neighbours: HashMap<usize, HashSet<usize>>,
}

fn find_connected_components(grid: &Grid) -> Vec<(ConnectedComponent, HashSet<usize>)> {
    let rows = grid.number_of_rows;
    let columns = grid.number_of_columns;

    let mut remaining_cells: HashSet<usize> = (0..grid.cells.len()).into_iter().collect();

    let mut components = vec![];
    let mut counter = 0;

    // Take any element to land in any component.
    while let Some(&start_cell_index) = remaining_cells.iter().next() {
        let mut visited = HashSet::new();
        let mut neighbours = HashSet::new();
        let mut queue = VecDeque::new();

        queue.push_back(start_cell_index);

        // Gather all cells in the connected component of start_cell_index.
        while let Some(i) = queue.pop_front() {
            visited.insert(i);
            remaining_cells.remove(&i);

            let mut neighbouring_cells = vec![];
            if i % columns > 0 {
                neighbouring_cells.push(i - 1);
            }
            if i % columns < columns - 1 {
                neighbouring_cells.push(i + 1);
            }
            if i >= columns {
                neighbouring_cells.push(i - columns)
            }
            if i < (rows - 1) * columns {
                neighbouring_cells.push(i + columns)
            }

            for neighbour in neighbouring_cells {
                if visited.contains(&neighbour) {
                    continue;
                }

                if grid.cells[i] == grid.cells[neighbour] {
                    queue.push_back(neighbour);
                } else {
                    neighbours.insert(neighbour);
                }
            }
        }

        let cells = visited
            .iter()
            .map(|&i| Position {
                column: i % columns,
                row: i / columns,
            })
            .collect();

        let component = ConnectedComponent {
            id: counter,
            colour: grid.cells[*visited.iter().next().unwrap()],
            cells,
        };
        counter += 1;

        components.push((component, neighbours));
    }

    return components;
}

impl Graph {
    pub fn create(grid: &Grid) -> Self {
        let components_and_neighbours = find_connected_components(&grid);

        let mut components = HashMap::with_capacity(components_and_neighbours.len());
        let mut neighbours: HashMap<usize, HashSet<usize>> = HashMap::new();

        for (c, n) in components_and_neighbours.into_iter() {
            let id = c.id;
            components.insert(id, c);
            neighbours.insert(id, n);
        }

        Self {
            components,
            neighbours
        }
    }

    fn to_grid(&self, rows: usize, columns: usize) -> Grid {
        let mut cells = vec![Colour::Red; rows * columns];

        for component in self.neighbours.keys() {
            for position in &self.components[component].cells {
                cells[position.column + position.row * columns] = self.components[component].colour;
            }
        }

        Grid {
            number_of_rows: rows,
            number_of_columns: columns,
            cells,
        }
    }

    pub fn find_component(&self, position: &Position) -> &ConnectedComponent {
        for component in self.neighbours.keys() {
            if self.components[component].cells.contains(&position) {
                return &self.components[component];
            }
        }

        unreachable!()
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn should_return_same_grid_as_input() {
        let size = 4;
        let grid = Grid::generate(size);

        let graph = Graph::create(&grid);
        let reconstituted_grid = graph.to_grid(size, size);

        assert_eq!(reconstituted_grid, grid);
    }

    #[test]
    fn should_have_one_component() {
        let grid = Grid {
            number_of_columns: 2,
            number_of_rows: 2,
            cells: vec![Colour::Red; 4],
        };

        let graph = Graph::create(&grid);

        assert_eq!(graph.neighbours.len(), 1);
    }

    #[test]
    fn should_have_four_component() {
        let grid = Grid {
            number_of_columns: 2,
            number_of_rows: 2,
            cells: vec![Colour::Red, Colour::Yellow, Colour::Yellow, Colour::Red],
        };

        let graph = Graph::create(&grid);

        assert_eq!(graph.neighbours.len(), 4);
    }

    #[test]
    fn should_have_two_component() {
        let grid = Grid {
            number_of_columns: 2,
            number_of_rows: 2,
            cells: vec![Colour::Red, Colour::Red, Colour::Yellow, Colour::Yellow],
        };

        let graph = Graph::create(&grid);

        assert_eq!(graph.neighbours.len(), 2);
    }

    #[test]
    fn should_have_same_keys_for_components_and_neighbours_maps() {
        let size = 4;
        let grid = Grid::generate(size);

        let graph = Graph::create(&grid);

        let components_keys: HashSet<_> = graph.components.keys().collect();
        let neighbours_keys: HashSet<_> = graph.neighbours.keys().collect();
        assert_eq!(components_keys, neighbours_keys);
    }

    #[test]
    fn should_contain_exactly_the_component_ids_as_keys() {
        let size = 4;
        let grid = Grid::generate(size);

        let graph = Graph::create(&grid);

        let component_keys: HashSet<_> = graph.components.keys().collect();
        let component_ids: HashSet<_> = graph.components.values().map(|x| &x.id).collect();
        assert_eq!(component_keys, component_ids);

        for (id, component) in graph.components {
            assert_eq!(id, component.id);
        }
    }
}
<|endoftext|>


<commit_before>use glut;
use azure;

import layers::*;
import rendergl::*;
import util::convert_rgb32_to_rgb24;

import glut::{create_window, display_func, init};
import glut::bindgen::{glutInitDisplayMode, glutMainLoop, glutPostRedisplay, glutSwapBuffers};

import azure::cairo::CAIRO_FORMAT_RGB24;
import CairoContext = azure::cairo_hl::Context;
import azure::cairo_hl::ImageSurface;

import comm::{chan, port, recv, send};
import libc::c_uint;
import os::{getenv, setenv};
import task::{builder, get_opts, run_listener, set_opts};

class Renderer {
    let image: @Image;
    let mut image_layer: ImageLayer;
    let mut t: f32;
    let mut delta: f32;
    let mut render_context: option<RenderContext>;

    new() {
        let cairo_image = ImageSurface(CAIRO_FORMAT_RGB24, 500, 704);

        let cairo_context = CairoContext(cairo_image);
        cairo_context.set_line_width(5.0f64);
        cairo_context.set_source_rgb(255.0f64, 255.0f64, 0.0f64);
        cairo_context.rectangle(50.0f64, 50.0f64, 300.0f64, 284.0f64);
        cairo_context.stroke();

        self.image = @Image(cairo_image.width() as uint, cairo_image.height() as uint, RGB24Format,
                            convert_rgb32_to_rgb24(cairo_image.data()));
        io::println(#fmt("image is %ux%u", self.image.width, self.image.height));

        self.image_layer = ImageLayer(self.image);

        self.t = 1.0f32;
        self.delta = -0.001f32;

        self.render_context = none;
    }

    fn get_display_callback(this: @Renderer) -> fn@() {
        fn@() {
            (*this).display_callback();
        }
    }

    fn display_callback() {
        alt self.render_context {
            none {
                self.render_context = some(init_render_context());
            }
            some(_) {
                // Nothing to do.
            }
        }
        let context = alt self.render_context {
            none { fail }
            some(ctx) { ctx }
        };

        let t = self.t;
        self.image_layer.common.transform = Matrix4(1.0f32 * t, 0.0f32,     0.0f32, 0.0f32,
                                                    0.0f32,     1.0f32 * t, 0.0f32, 0.0f32,
                                                    0.0f32,     0.0f32,     1.0f32, 0.0f32,
                                                    0.0f32,     0.0f32,     0.0f32, 1.0f32);

        render_scene(context, self.image_layer);

        self.t += self.delta;
        if self.t < 0.0f32 || self.t > 1.0f32 {
            self.delta = -self.delta;
        }

        glutSwapBuffers();

        glutPostRedisplay();
    }
}

#[test]
fn test_triangle_and_square() unsafe {
    let builder = builder();
    let opts = {
        sched: some({ mode: task::osmain, foreign_stack_size: none })
        with get_opts(builder)
    };
    set_opts(builder, opts);

    let port: port<()> = port();
    let chan = chan(port);
    let _result_ch: chan<()> = run_listener(builder, {
        |_port|

        let renderer = @Renderer();

        init();
        glutInitDisplayMode(0 as c_uint);
        create_window("Rust Layers");
        display_func(renderer.get_display_callback(renderer));
        glutMainLoop();

        send(chan, ());
    });
    recv(port);
}

<commit_msg>Azure bindings<commit_after>use glut;
use azure;
use geom;

import geom::point::Point2D;
import geom::rect::Rect;
import geom::size::Size2D;
import layers::*;
import rendergl::*;
import util::convert_rgb32_to_rgb24;

import glut::{create_window, display_func, init};
import glut::bindgen::{glutInitDisplayMode, glutMainLoop, glutPostRedisplay, glutSwapBuffers};

import azure::cairo::CAIRO_FORMAT_RGB24;
import CairoContext = azure::cairo_hl::Context;
import azure::azure_hl::{Color, ColorPattern, DrawTarget};
import azure::cairo_hl::ImageSurface;

import comm::{chan, port, recv, send};
import libc::c_uint;
import os::{getenv, setenv};
import task::{builder, get_opts, run_listener, set_opts};

class Renderer {
    let image: @Image;
    let mut image_layer: ImageLayer;
    let mut t: f32;
    let mut delta: f32;
    let mut render_context: option<RenderContext>;

    new() {
        let cairo_image = ImageSurface(CAIRO_FORMAT_RGB24, 500, 704);

        let draw_target = DrawTarget(cairo_image);
        draw_target.fill_rect(Rect(Point2D(50.0f32, 50.0f32), Size2D(300.0f32, 284.0f32)),
                              ColorPattern(Color(1.0f32, 1.0f32, 0.0f32, 1.0f32)));
        draw_target.flush();

        self.image = @Image(cairo_image.width() as uint, cairo_image.height() as uint, RGB24Format,
                            convert_rgb32_to_rgb24(cairo_image.data()));
        io::println(#fmt("image is %ux%u", self.image.width, self.image.height));

        self.image_layer = ImageLayer(self.image);

        self.t = 1.0f32;
        self.delta = -0.001f32;

        self.render_context = none;
    }

    fn get_display_callback(this: @Renderer) -> fn@() {
        fn@() {
            (*this).display_callback();
        }
    }

    fn display_callback() {
        alt self.render_context {
            none {
                self.render_context = some(init_render_context());
            }
            some(_) {
                // Nothing to do.
            }
        }
        let context = alt self.render_context {
            none { fail }
            some(ctx) { ctx }
        };

        let t = self.t;
        self.image_layer.common.transform = Matrix4(1.0f32 * t, 0.0f32,     0.0f32, 0.0f32,
                                                    0.0f32,     1.0f32 * t, 0.0f32, 0.0f32,
                                                    0.0f32,     0.0f32,     1.0f32, 0.0f32,
                                                    0.0f32,     0.0f32,     0.0f32, 1.0f32);

        render_scene(context, self.image_layer);

        self.t += self.delta;
        if self.t < 0.0f32 || self.t > 1.0f32 {
            self.delta = -self.delta;
        }

        glutSwapBuffers();

        glutPostRedisplay();
    }
}

#[test]
fn test_triangle_and_square() unsafe {
    let builder = builder();
    let opts = {
        sched: some({ mode: task::osmain, foreign_stack_size: none })
        with get_opts(builder)
    };
    set_opts(builder, opts);

    let port: port<()> = port();
    let chan = chan(port);
    let _result_ch: chan<()> = run_listener(builder, {
        |_port|

        let renderer = @Renderer();

        init();
        glutInitDisplayMode(0 as c_uint);
        create_window("Rust Layers");
        display_func(renderer.get_display_callback(renderer));
        glutMainLoop();

        send(chan, ());
    });
    recv(port);
}

<|endoftext|>


<commit_before>extern mod opengles;   // FIXME: Should only be for tests.
use glut::{check_loop, create_window, destroy_window, init, init_display_mode, swap_buffers};
use opengles::gl2::{ARRAY_BUFFER, COLOR_BUFFER_BIT, COMPILE_STATUS};
use opengles::gl2::{FRAGMENT_SHADER, LINK_STATUS, NO_ERROR, STATIC_DRAW};
use opengles::gl2::{TRIANGLE_STRIP, VERTEX_SHADER, GLclampf, GLenum};
use opengles::gl2::{GLsizei, GLuint, attach_shader, bind_buffer};
use opengles::gl2::{buffer_data, create_program, clear, clear_color};
use opengles::gl2::{compile_shader, create_shader, draw_arrays};
use opengles::gl2::{enable_vertex_attrib_array, gen_buffers};
use opengles::gl2::{get_attrib_location, get_error, get_program_iv};
use opengles::gl2::{get_shader_info_log, get_shader_iv};
use opengles::gl2::{get_uniform_location, link_program, shader_source};
use opengles::gl2::{use_program, vertex_attrib_pointer_f32};

use comm::{Chan, peek, Port, recv, send};
use io::println;
use ptr::{addr_of, null};
use str::to_bytes;
use task::TaskBuilder;
use vec::raw::to_ptr;

fn fragment_shader_source() -> ~str {
    ~"
    #ifdef GLES2
        precision mediump float;
    #endif

        void main(void) {
            gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
        }
    "
}

fn vertex_shader_source() -> ~str {
    ~"
        attribute vec3 aVertexPosition;

        /*uniform mat4 uMVMatrix;
        uniform mat4 uPMatrix;*/

        void main(void) {
            gl_Position = /*uPMatrix * uMVMatrix **/
                vec4(aVertexPosition, 1.0);
        }
    "
}

fn load_shader(source_str: ~str, shader_type: GLenum) -> GLuint {
    let shader_id = create_shader(shader_type);
    shader_source(shader_id, ~[to_bytes(source_str)]);
    compile_shader(shader_id);

    if get_error() != NO_ERROR {
        println(#fmt("error: %d", get_error() as int));
        fail ~"failed to compile shader with error";
    }

    if get_shader_iv(shader_id, COMPILE_STATUS) == (0 as GLint) {
        println(get_shader_info_log(shader_id));
        fail ~"failed to compile shader";
    }
    return shader_id;
}

struct ShaderProgram {
    program: GLuint,
    aVertexPosition: c_int,
    /*let uPMatrix: c_int;
    let uMVMatrix: c_int;*/
}

fn ShaderProgram(program: GLuint) -> ShaderProgram {
    let p = ShaderProgram {
        program : program,
        aVertexPosition : get_attrib_location(program, ~"aVertexPosition"),
        /*self.uPMatrix : get_uniform_location(program, "uPMatrix"),
        self.uMVMatrix : get_uniform_location(program, "uMVMatrix")*/
    };
    enable_vertex_attrib_array(p.aVertexPosition as GLuint);
    return p;
}

fn init_shaders() -> ShaderProgram {
    let vertex_shader = load_shader(vertex_shader_source(), VERTEX_SHADER);
    let fragment_shader = load_shader(fragment_shader_source(),
                                      FRAGMENT_SHADER);

    let program = create_program();
    attach_shader(program, vertex_shader);
    attach_shader(program, fragment_shader);
    link_program(program);

    if get_program_iv(program, LINK_STATUS) == (0 as GLint) {
        fail ~"failed to initialize program";
    }

    use_program(program);

    return ShaderProgram(program);
}

fn init_buffers() -> GLuint {
    let triangle_vertex_buffer = gen_buffers(1 as GLsizei)[0];
    bind_buffer(ARRAY_BUFFER, triangle_vertex_buffer);
    let vertices = ~[
        0.0f32, 1.0f32, 0.0f32,
        1.0f32, 0.0f32, 0.0f32,
        0.0f32, 0.0f32, 0.0f32
    ];
    buffer_data(ARRAY_BUFFER, vertices, STATIC_DRAW);
    return triangle_vertex_buffer;
}

fn draw_scene(shader_program: ShaderProgram, vertex_buffer: GLuint) {
    clear_color(0.0f32, 0.0f32, 1.0f32, 1.0f32);
    clear(COLOR_BUFFER_BIT);

    bind_buffer(ARRAY_BUFFER, vertex_buffer);
    vertex_attrib_pointer_f32(shader_program.aVertexPosition as GLuint,
                              3 as GLint, false, 0 as GLsizei, 0 as GLuint);
    draw_arrays(TRIANGLE_STRIP, 0 as GLint, 3 as GLint);
}

fn display_callback() {
    let program = init_shaders();
    let vertex_buffer = init_buffers();
    draw_scene(program, vertex_buffer);

    swap_buffers();
}

#[test]
fn test_triangle_and_square() unsafe {
    let builder = task::task().sched_mode(task::PlatformThread);

    let po: Port<()> = Port();
    let ch = Chan(po);
    let _result_ch: Chan<()> = builder.spawn_listener(|_port| {
        init();
        init_display_mode(0 as c_uint);
        let window = create_window(~"Rust GLUT");
        display_func(display_callback);

        let wakeup = Port();
        let wakeup_chan = Chan(wakeup);
        timer_func(1000, || send(wakeup_chan, ()));

        loop {
            check_loop();

            if peek(wakeup) {
                recv(wakeup);
                send(ch, ());
                destroy_window(window);
                break;
            }
        }
    });

    recv(po);
}

<commit_msg>Un-bust tests (upstream Port/Chan API changes).<commit_after>extern mod opengles;   // FIXME: Should only be for tests.
use glut::{check_loop, create_window, destroy_window, init, init_display_mode, swap_buffers};
use opengles::gl2::{ARRAY_BUFFER, COLOR_BUFFER_BIT, COMPILE_STATUS};
use opengles::gl2::{FRAGMENT_SHADER, LINK_STATUS, NO_ERROR, STATIC_DRAW};
use opengles::gl2::{TRIANGLE_STRIP, VERTEX_SHADER, GLclampf, GLenum};
use opengles::gl2::{GLsizei, GLuint, attach_shader, bind_buffer};
use opengles::gl2::{buffer_data, create_program, clear, clear_color};
use opengles::gl2::{compile_shader, create_shader, draw_arrays};
use opengles::gl2::{enable_vertex_attrib_array, gen_buffers};
use opengles::gl2::{get_attrib_location, get_error, get_program_iv};
use opengles::gl2::{get_shader_info_log, get_shader_iv};
use opengles::gl2::{get_uniform_location, link_program, shader_source};
use opengles::gl2::{use_program, vertex_attrib_pointer_f32};

use comm::{Chan, peek, Port, recv, send};
use io::println;
use ptr::{addr_of, null};
use str::to_bytes;
use task::TaskBuilder;
use vec::raw::to_ptr;

fn fragment_shader_source() -> ~str {
    ~"
    #ifdef GLES2
        precision mediump float;
    #endif

        void main(void) {
            gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
        }
    "
}

fn vertex_shader_source() -> ~str {
    ~"
        attribute vec3 aVertexPosition;

        /*uniform mat4 uMVMatrix;
        uniform mat4 uPMatrix;*/

        void main(void) {
            gl_Position = /*uPMatrix * uMVMatrix **/
                vec4(aVertexPosition, 1.0);
        }
    "
}

fn load_shader(source_str: ~str, shader_type: GLenum) -> GLuint {
    let shader_id = create_shader(shader_type);
    shader_source(shader_id, ~[to_bytes(source_str)]);
    compile_shader(shader_id);

    if get_error() != NO_ERROR {
        println(#fmt("error: %d", get_error() as int));
        fail ~"failed to compile shader with error";
    }

    if get_shader_iv(shader_id, COMPILE_STATUS) == (0 as GLint) {
        println(get_shader_info_log(shader_id));
        fail ~"failed to compile shader";
    }
    return shader_id;
}

struct ShaderProgram {
    program: GLuint,
    aVertexPosition: c_int,
    /*let uPMatrix: c_int;
    let uMVMatrix: c_int;*/
}

fn ShaderProgram(program: GLuint) -> ShaderProgram {
    let p = ShaderProgram {
        program : program,
        aVertexPosition : get_attrib_location(program, ~"aVertexPosition"),
        /*self.uPMatrix : get_uniform_location(program, "uPMatrix"),
        self.uMVMatrix : get_uniform_location(program, "uMVMatrix")*/
    };
    enable_vertex_attrib_array(p.aVertexPosition as GLuint);
    return p;
}

fn init_shaders() -> ShaderProgram {
    let vertex_shader = load_shader(vertex_shader_source(), VERTEX_SHADER);
    let fragment_shader = load_shader(fragment_shader_source(),
                                      FRAGMENT_SHADER);

    let program = create_program();
    attach_shader(program, vertex_shader);
    attach_shader(program, fragment_shader);
    link_program(program);

    if get_program_iv(program, LINK_STATUS) == (0 as GLint) {
        fail ~"failed to initialize program";
    }

    use_program(program);

    return ShaderProgram(program);
}

fn init_buffers() -> GLuint {
    let triangle_vertex_buffer = gen_buffers(1 as GLsizei)[0];
    bind_buffer(ARRAY_BUFFER, triangle_vertex_buffer);
    let vertices = ~[
        0.0f32, 1.0f32, 0.0f32,
        1.0f32, 0.0f32, 0.0f32,
        0.0f32, 0.0f32, 0.0f32
    ];
    buffer_data(ARRAY_BUFFER, vertices, STATIC_DRAW);
    return triangle_vertex_buffer;
}

fn draw_scene(shader_program: ShaderProgram, vertex_buffer: GLuint) {
    clear_color(0.0f32, 0.0f32, 1.0f32, 1.0f32);
    clear(COLOR_BUFFER_BIT);

    bind_buffer(ARRAY_BUFFER, vertex_buffer);
    vertex_attrib_pointer_f32(shader_program.aVertexPosition as GLuint,
                              3 as GLint, false, 0 as GLsizei, 0 as GLuint);
    draw_arrays(TRIANGLE_STRIP, 0 as GLint, 3 as GLint);
}

fn display_callback() {
    let program = init_shaders();
    let vertex_buffer = init_buffers();
    draw_scene(program, vertex_buffer);

    swap_buffers();
}

#[test]
fn test_triangle_and_square() unsafe {
    let builder = task::task().sched_mode(task::PlatformThread);

    let po: Port<()> = Port();
    let ch = Chan(&po);
    let _result_ch: Chan<()> = builder.spawn_listener(|_port| {
        init();
        init_display_mode(0 as c_uint);
        let window = create_window(~"Rust GLUT");
        display_func(display_callback);

        let wakeup: Port<()> = Port();
        let wakeup_chan = Chan(&wakeup);
        timer_func(1000, || send(wakeup_chan, ()));

        loop {
            check_loop();

            if peek(wakeup) {
                recv(wakeup);
                send(ch, ());
                destroy_window(window);
                break;
            }
        }
    });

    recv(po);
}

<|endoftext|>


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

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Logic {
  High,
  Low
}

impl Logic {
    pub fn inverse(self) -> Logic {
        match self {
            Logic::High => Logic::Low,
            Logic::Low  => Logic::High
        }
    }
}

impl Into<usize> for Logic {
    fn into(self) -> usize {
        match self {
            Logic::High => 1,
            Logic::Low  => 0
        }
    }
}

impl Display for Logic {
    fn fmt(&self, f: &mut Formatter) -> std::result::Result<(), std::fmt::Error> {
        let v: usize = (*self).into();
        write!(f, "{}", v)
    }
}

#[derive(Debug, Copy, Clone)]
pub enum Logic3 {
  High,
  Low,
  Z
}

pub trait DigitalLogic {
  fn logic_level(&self) -> Logic;
}

impl DigitalLogic for i32 {
  fn logic_level(&self) -> Logic {
    match *self { 0 => Logic::Low, _ => Logic::High }
  }
}

impl DigitalLogic for u32 {
  fn logic_level(&self) -> Logic {
    match *self { 0 => Logic::Low, _ => Logic::High }
  }
}

impl DigitalLogic for isize {
  fn logic_level(&self) -> Logic {
    match *self { 0 => Logic::Low, _ => Logic::High }
  }
}

impl DigitalLogic for usize {
  fn logic_level(&self) -> Logic {
    match *self { 0 => Logic::Low, _ => Logic::High }
  }
}
impl DigitalLogic for Logic {
  fn logic_level(&self) -> Logic {
    *self
  }
}

pub trait DigitalRead {
  fn digital_read(&mut self) -> Result<Logic>;

  fn get(&mut self) -> Result<Logic> {
    self.digital_read()
  }

  fn is_high(&mut self) -> Result<bool> {
      match try!(self.digital_read()) {
          Logic::High => Ok(true),
          Logic::Low => Ok(false)
      }
  }

  fn is_low(&mut self) -> Result<bool> {
      match try!(self.digital_read()) {
          Logic::High => Ok(false),
          Logic::Low => Ok(true)
      }
  }
}

pub trait DigitalWrite {
  fn digital_write<L: DigitalLogic>(&mut self, level: L) -> Result<()>;

  fn set<L: DigitalLogic>(&mut self, level: L) -> Result<()> {
    self.digital_write(level)
  }

  fn high(&mut self) -> Result<()> {
    self.digital_write(Logic::High)
  }

  fn low(&mut self) -> Result<()> {
    self.digital_write(Logic::Low)
  }
}

pub trait AnalogRead {
  fn analog_read(&self) -> usize;
}

pub trait AnalogWrite {
  fn analog_write(&self, value: usize);
}

#[cfg(test)]
mod test {
    use super::Logic;

    #[test]
    fn logic_inverse() {
        let low = Logic::Low;
        let high = Logic::High;
        assert_eq!(low.inverse(), high);
        assert_eq!(low, high.inverse());
    }
}
<commit_msg>Compare logic levels<commit_after>use std;
use std::fmt::{Display, Formatter};
use Result;

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Logic {
  High,
  Low
}

impl Logic {
    pub fn inverse(self) -> Logic {
        match self {
            Logic::High => Logic::Low,
            Logic::Low  => Logic::High
        }
    }
}

impl Into<usize> for Logic {
    fn into(self) -> usize {
        match self {
            Logic::High => 1,
            Logic::Low  => 0
        }
    }
}

impl Display for Logic {
    fn fmt(&self, f: &mut Formatter) -> std::result::Result<(), std::fmt::Error> {
        let v: usize = (*self).into();
        write!(f, "{}", v)
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Logic3 {
  High,
  Low,
  Z
}

pub trait DigitalLogic {
  fn logic_level(&self) -> Logic;
}

impl DigitalLogic for i32 {
  fn logic_level(&self) -> Logic {
    match *self { 0 => Logic::Low, _ => Logic::High }
  }
}

impl DigitalLogic for u32 {
  fn logic_level(&self) -> Logic {
    match *self { 0 => Logic::Low, _ => Logic::High }
  }
}

impl DigitalLogic for isize {
  fn logic_level(&self) -> Logic {
    match *self { 0 => Logic::Low, _ => Logic::High }
  }
}

impl DigitalLogic for usize {
  fn logic_level(&self) -> Logic {
    match *self { 0 => Logic::Low, _ => Logic::High }
  }
}

impl DigitalLogic for Logic {
  fn logic_level(&self) -> Logic {
    *self
  }
}

pub trait DigitalRead {
  fn digital_read(&mut self) -> Result<Logic>;

  fn get(&mut self) -> Result<Logic> {
    self.digital_read()
  }

  fn is_high(&mut self) -> Result<bool> {
      match try!(self.digital_read()) {
          Logic::High => Ok(true),
          Logic::Low => Ok(false)
      }
  }

  fn is_low(&mut self) -> Result<bool> {
      match try!(self.digital_read()) {
          Logic::High => Ok(false),
          Logic::Low => Ok(true)
      }
  }
}

pub trait DigitalWrite {
  fn digital_write<L: DigitalLogic>(&mut self, level: L) -> Result<()>;

  fn set<L: DigitalLogic>(&mut self, level: L) -> Result<()> {
    self.digital_write(level)
  }

  fn high(&mut self) -> Result<()> {
    self.digital_write(Logic::High)
  }

  fn low(&mut self) -> Result<()> {
    self.digital_write(Logic::Low)
  }
}

pub trait AnalogRead {
  fn analog_read(&self) -> usize;
}

pub trait AnalogWrite {
  fn analog_write(&self, value: usize);
}

#[cfg(test)]
mod test {
    use super::Logic;

    #[test]
    fn logic_inverse() {
        let low = Logic::Low;
        let high = Logic::High;
        assert_eq!(low.inverse(), high);
        assert_eq!(low, high.inverse());
    }
}
<|endoftext|>


<commit_before>import comm::*;
import libc::*;
import js = jsapi::bindgen;
import jsapi::*;
import ptr::null;
import void = c_void;

mod jsrust {
    /* Bindings to work around Rust's missing features. */
    fn JSRust_GetPropertyStub() -> JSPropertyOp { fail }
    fn JSRust_GetStrictPropertyStub() -> JSStrictPropertyOp { fail }
    fn JSRust_GetEnumerateStub() -> JSEnumerateOp { fail }
    fn JSRust_GetResolveStub() -> JSResolveOp { fail }
    fn JSRust_GetConvertStub() -> JSConvertOp { fail }
    fn JSRust_GetFinalizeStub() -> JSFinalizeOp { fail }

	/* Additional features. */
    fn JSRust_NewContext(rt : *JSRuntime, stackChunkSize : size_t)
        -> *JSContext { fail }
    fn JSRust_SetErrorChannel(cx : *JSContext, chan : chan<error_report>)
	-> bool { fail }
    fn JSRust_SetLogChannel(cx : *JSContext, object : *JSObject, chan : chan<log_message>)
	-> bool { fail }
    fn JSRust_InitRustLibrary(cx : *JSContext, object : *JSObject) -> bool { fail }
    fn JSRust_SetDataOnObject(cx : *JSContext, object : *JSObject, val : *c_char, vallen: u32) { fail }
    fn JSRust_GetThreadRuntime(maxbytes : u32) -> *JSRuntime { fail }
    fn JSRust_Exit(code : c_int) { fail }
}

type error_report = {
	message: str,
	filename: str,
	lineno: u32,
	flags: u32
};

type log_message = {
	message: str,
	level: u32,
        tag: u32,
        timeout: u32
};

enum object { object_priv(*JSObject) }
enum principals { principals_priv(*JSPrincipals) }
enum script { script_priv(*JSScript) }
enum string { string_priv(*JSString) }

resource runtime(_rt : *JSRuntime) {
    // because there is one runtime per thread, raii does not
    // work. one task will finish but there may be other tasks
    // on the same os thread.
    //js::JS_Finish(rt);
}

resource context(_cx : *JSContext) {
    //js::JS_DestroyContext(cx);
}

fn begin_request(cx : *JSContext) {
    js::JS_BeginRequest(cx);
}

fn end_request(cx : *JSContext) {
    js::JS_EndRequest(cx);
}

resource request(cx : *JSContext) {
    js::JS_EndRequest(cx);
}

/* Runtimes */

fn new_runtime(maxbytes : u32) -> runtime {
    ret runtime(js::JS_Init(maxbytes));
}

fn get_thread_runtime(maxbytes : u32) -> runtime {
    ret runtime(jsrust::JSRust_GetThreadRuntime(maxbytes));
}

fn shut_down() {
    js::JS_ShutDown();
}

/* Contexts */

fn new_context(rt : runtime, stack_chunk_size : size_t) -> context {
    ret context(jsrust::JSRust_NewContext(*rt, stack_chunk_size));
}

/* Options */

fn get_options(cx : context) -> u32 {
    ret js::JS_GetOptions(*cx);
}

fn set_options(cx : context, options : u32) {
    let _ = js::JS_SetOptions(*cx, options);
}

fn set_version(cx : context, version : JSVersion) {
    let _ = js::JS_SetVersion(*cx, version);
}

/* Objects */

fn new_compartment_and_global_object(cx : context, clas : @class,
                                     principals : principals) -> object {
    let jsclass = ptr::addr_of(clas.jsclass);
    let jsobj = js::JS_NewCompartmentAndGlobalObject(*cx, jsclass,
                                                     *principals);
    if jsobj == null() { fail; }
    ret object_priv(jsobj);
}

/* Principals */

fn null_principals() -> principals {
    ret principals_priv(null());
}

/* Classes */

type class_spec = {
    name: str,
    flags: u32
    /* TODO: More to add here. */
};

type class = {
    name: @str,
    jsclass: JSClass
};

fn new_class(spec : class_spec) -> @class unsafe {
    // Root the name separately, and make the JSClass name point into it.
    let name = @spec.name;
    let x : *void = ptr::null();
    ret @{
        name: name,
        jsclass: {
            name: str::as_c_str(*name, { |b| b }),
            flags: spec.flags,

            addProperty: jsrust::JSRust_GetPropertyStub(),
            delProperty: jsrust::JSRust_GetPropertyStub(),
            getProperty: jsrust::JSRust_GetPropertyStub(),
            setProperty: jsrust::JSRust_GetStrictPropertyStub(),
            enumerate: jsrust::JSRust_GetEnumerateStub(),
            resolve: jsrust::JSRust_GetResolveStub(),
            convert: jsrust::JSRust_GetConvertStub(),
            finalize: jsrust::JSRust_GetFinalizeStub(),

            reserved0: unsafe::reinterpret_cast(0),
            checkAccess: unsafe::reinterpret_cast(0),
            call: unsafe::reinterpret_cast(0),
            construct: unsafe::reinterpret_cast(0),
            xdrObject: unsafe::reinterpret_cast(0),
            hasInstance: unsafe::reinterpret_cast(0),
            trace: unsafe::reinterpret_cast(0),

            reserved1: unsafe::reinterpret_cast(0),
            reserved: (x,x,x,x,x,x,x,x, x,x,x,x,x,x,x,x,    /* 16 */
                       x,x,x,x,x,x,x,x, x,x,x,x,x,x,x,x,    /* 32 */
                       x,x,x,x,x,x,x,x)

        }
    };
}

/* Standard classes */

fn init_standard_classes(cx : context, object : object) {
    if js::JS_InitStandardClasses(*cx, *object) == 0 as JSBool { fail; }
}

/* Script compilation */

fn compile_script(cx : context, object : object, src : [u8], filename : str,
                  lineno : uint) -> script unsafe {
    let jsscript = str::as_c_str(filename, { |buf|
        js::JS_CompileScript(*cx, *object,
                             unsafe::reinterpret_cast(vec::unsafe::to_ptr(src)),
                             vec::len(src) as size_t, buf, lineno as c_uint)
    });
    if jsscript == ptr::null() {
        fail;   // TODO: this is antisocial
    }
    ret script_priv(jsscript);
}

/* Script execution */

fn execute_script(cx : context, object : object, script : script)
        -> option<jsval> unsafe {
    let rv : jsval = unsafe::reinterpret_cast(0);
    if js::JS_ExecuteScript(*cx, *object, *script, ptr::addr_of(rv)) == 0 as JSBool {
        ret none;
    }
    ret some(rv);
}

/* Value conversion */

fn value_to_source(cx : context, v : jsval) -> string {
    ret string_priv(js::JS_ValueToSource(*cx, v));
}

/* String conversion */

fn get_string_bytes(cx : context, jsstr : string) -> [u16] unsafe {
    // FIXME: leaks, probably
    let size = 0 as size_t;
    let bytes = js::JS_GetStringCharsZAndLength(*cx, *jsstr,
                                                ptr::addr_of(size));
    ret vec::unsafe::from_buf(bytes, ((size + (1 as size_t)) * (2 as size_t)));
}

fn get_string(cx : context, jsstr : string) -> str unsafe {
    let bytes = get_string_bytes(cx, jsstr);

    // Make a sizing call.
    let len = 0 as size_t;
    if js::JS_EncodeCharacters(*cx, vec::unsafe::to_ptr(bytes),
                               (vec::len(bytes) / 2u) as size_t, ptr::null(),
                               ptr::addr_of(len)) == 0 as JSBool {
        fail;
    }

    let buf = vec::from_elem(len + 1u, 0 as libc::c_char);
    if js::JS_EncodeCharacters(*cx, vec::unsafe::to_ptr(bytes),
                               (vec::len(bytes) / 2u) as size_t,
                               vec::unsafe::to_ptr(buf),
                               ptr::addr_of(len)) == 0 as JSBool {
        fail;
    }

    ret vec::as_buf(buf) {|buf| str::unsafe::from_c_str_len(buf, len as uint) };
}

fn get_int(cx : context, num : jsval) -> i32 unsafe {
    let oparam : i32 = 0i32;
    js::JS_ValueToInt32(*cx, num, ptr::addr_of(oparam));
    ret oparam;
}

fn set_data_property(cx : context, obj : object, value : str) {
    ret str::as_c_str(value) {|buf|
        jsrust::JSRust_SetDataOnObject(*cx, *obj, buf, value.len() as u32);
    }
}

/** Rust extensions to the JavaScript language bindings. */
mod ext {
	fn set_error_channel(cx : context, chan : chan<error_report>) {
		if !jsrust::JSRust_SetErrorChannel(*cx, chan) { fail; }
	}

	fn set_log_channel(cx : context, object : object, chan : chan<log_message>) {
		if !jsrust::JSRust_SetLogChannel(*cx, *object, chan) { fail; }
	}

	fn init_rust_library(cx : context, object : object) {
		if !jsrust::JSRust_InitRustLibrary(*cx, *object) { fail; }
	}

	fn rust_exit_now(code : int) {
		jsrust::JSRust_Exit(code as c_int);
	}
}

<commit_msg>Use crust functions for missing rust-spidermonkey functions<commit_after>import comm::*;
import libc::*;
import js = jsapi::bindgen;
import jsapi::*;
import ptr::null;
import void = c_void;

mod jsrust {
	/* Additional features. */
    fn JSRust_NewContext(rt : *JSRuntime, stackChunkSize : size_t)
        -> *JSContext { fail }
    fn JSRust_SetErrorChannel(cx : *JSContext, chan : chan<error_report>)
	-> bool { fail }
    fn JSRust_SetLogChannel(cx : *JSContext, object : *JSObject, chan : chan<log_message>)
	-> bool { fail }
    fn JSRust_InitRustLibrary(cx : *JSContext, object : *JSObject) -> bool { fail }
    fn JSRust_SetDataOnObject(cx : *JSContext, object : *JSObject, val : *c_char, vallen: u32) { fail }
    fn JSRust_GetThreadRuntime(maxbytes : u32) -> *JSRuntime { fail }
    fn JSRust_Exit(code : c_int) { fail }
}

type error_report = {
	message: str,
	filename: str,
	lineno: u32,
	flags: u32
};

type log_message = {
	message: str,
	level: u32,
        tag: u32,
        timeout: u32
};

enum object { object_priv(*JSObject) }
enum principals { principals_priv(*JSPrincipals) }
enum script { script_priv(*JSScript) }
enum string { string_priv(*JSString) }

resource runtime(_rt : *JSRuntime) {
    // because there is one runtime per thread, raii does not
    // work. one task will finish but there may be other tasks
    // on the same os thread.
    //js::JS_Finish(rt);
}

resource context(_cx : *JSContext) {
    //js::JS_DestroyContext(cx);
}

fn begin_request(cx : *JSContext) {
    js::JS_BeginRequest(cx);
}

fn end_request(cx : *JSContext) {
    js::JS_EndRequest(cx);
}

resource request(cx : *JSContext) {
    js::JS_EndRequest(cx);
}

/* Runtimes */

fn new_runtime(maxbytes : u32) -> runtime {
    ret runtime(js::JS_Init(maxbytes));
}

fn get_thread_runtime(maxbytes : u32) -> runtime {
    ret runtime(jsrust::JSRust_GetThreadRuntime(maxbytes));
}

fn shut_down() {
    js::JS_ShutDown();
}

/* Contexts */

fn new_context(rt : runtime, stack_chunk_size : size_t) -> context {
    ret context(jsrust::JSRust_NewContext(*rt, stack_chunk_size));
}

/* Options */

fn get_options(cx : context) -> u32 {
    ret js::JS_GetOptions(*cx);
}

fn set_options(cx : context, options : u32) {
    let _ = js::JS_SetOptions(*cx, options);
}

fn set_version(cx : context, version : JSVersion) {
    let _ = js::JS_SetVersion(*cx, version);
}

/* Objects */

fn new_compartment_and_global_object(cx : context, clas : @class,
                                     principals : principals) -> object {
    let jsclass = ptr::addr_of(clas.jsclass);
    let jsobj = js::JS_NewCompartmentAndGlobalObject(*cx, jsclass,
                                                     *principals);
    if jsobj == null() { fail; }
    ret object_priv(jsobj);
}

/* Principals */

fn null_principals() -> principals {
    ret principals_priv(null());
}

/* Classes */

type class_spec = {
    name: str,
    flags: u32
    /* TODO: More to add here. */
};

type class = {
    name: @str,
    jsclass: JSClass
};

fn new_class(spec : class_spec) -> @class unsafe {
    // Root the name separately, and make the JSClass name point into it.
    let name = @spec.name;
    let x : *void = ptr::null();
    ret @{
        name: name,
        jsclass: {
            name: str::as_c_str(*name, { |b| b }),
            flags: spec.flags,

            addProperty: crust::JS_PropertyStub,
            delProperty: crust::JS_PropertyStub,
            getProperty: crust::JS_PropertyStub,
            setProperty: crust::JS_StrictPropertyStub,
            enumerate: crust::JS_EnumerateStub,
            resolve: crust::JS_ResolveStub,
            convert: crust::JS_ConvertStub,
            finalize: crust::JS_FinalizeStub,

            reserved0: unsafe::reinterpret_cast(0),
            checkAccess: unsafe::reinterpret_cast(0),
            call: unsafe::reinterpret_cast(0),
            construct: unsafe::reinterpret_cast(0),
            xdrObject: unsafe::reinterpret_cast(0),
            hasInstance: unsafe::reinterpret_cast(0),
            trace: unsafe::reinterpret_cast(0),

            reserved1: unsafe::reinterpret_cast(0),
            reserved: (x,x,x,x,x,x,x,x, x,x,x,x,x,x,x,x,    /* 16 */
                       x,x,x,x,x,x,x,x, x,x,x,x,x,x,x,x,    /* 32 */
                       x,x,x,x,x,x,x,x)

        }
    };
}

/* Standard classes */

fn init_standard_classes(cx : context, object : object) {
    if js::JS_InitStandardClasses(*cx, *object) == 0 as JSBool { fail; }
}

/* Script compilation */

fn compile_script(cx : context, object : object, src : [u8], filename : str,
                  lineno : uint) -> script unsafe {
    let jsscript = str::as_c_str(filename, { |buf|
        js::JS_CompileScript(*cx, *object,
                             unsafe::reinterpret_cast(vec::unsafe::to_ptr(src)),
                             vec::len(src) as size_t, buf, lineno as c_uint)
    });
    if jsscript == ptr::null() {
        fail;   // TODO: this is antisocial
    }
    ret script_priv(jsscript);
}

/* Script execution */

fn execute_script(cx : context, object : object, script : script)
        -> option<jsval> unsafe {
    let rv : jsval = unsafe::reinterpret_cast(0);
    if js::JS_ExecuteScript(*cx, *object, *script, ptr::addr_of(rv)) == 0 as JSBool {
        ret none;
    }
    ret some(rv);
}

/* Value conversion */

fn value_to_source(cx : context, v : jsval) -> string {
    ret string_priv(js::JS_ValueToSource(*cx, v));
}

/* String conversion */

fn get_string_bytes(cx : context, jsstr : string) -> [u16] unsafe {
    // FIXME: leaks, probably
    let size = 0 as size_t;
    let bytes = js::JS_GetStringCharsZAndLength(*cx, *jsstr,
                                                ptr::addr_of(size));
    ret vec::unsafe::from_buf(bytes, ((size + (1 as size_t)) * (2 as size_t)));
}

fn get_string(cx : context, jsstr : string) -> str unsafe {
    let bytes = get_string_bytes(cx, jsstr);

    // Make a sizing call.
    let len = 0 as size_t;
    if js::JS_EncodeCharacters(*cx, vec::unsafe::to_ptr(bytes),
                               (vec::len(bytes) / 2u) as size_t, ptr::null(),
                               ptr::addr_of(len)) == 0 as JSBool {
        fail;
    }

    let buf = vec::from_elem(len + 1u, 0 as libc::c_char);
    if js::JS_EncodeCharacters(*cx, vec::unsafe::to_ptr(bytes),
                               (vec::len(bytes) / 2u) as size_t,
                               vec::unsafe::to_ptr(buf),
                               ptr::addr_of(len)) == 0 as JSBool {
        fail;
    }

    ret vec::as_buf(buf) {|buf| str::unsafe::from_c_str_len(buf, len as uint) };
}

fn get_int(cx : context, num : jsval) -> i32 unsafe {
    let oparam : i32 = 0i32;
    js::JS_ValueToInt32(*cx, num, ptr::addr_of(oparam));
    ret oparam;
}

fn set_data_property(cx : context, obj : object, value : str) {
    ret str::as_c_str(value) {|buf|
        jsrust::JSRust_SetDataOnObject(*cx, *obj, buf, value.len() as u32);
    }
}

/** Rust extensions to the JavaScript language bindings. */
mod ext {
	fn set_error_channel(cx : context, chan : chan<error_report>) {
		if !jsrust::JSRust_SetErrorChannel(*cx, chan) { fail; }
	}

	fn set_log_channel(cx : context, object : object, chan : chan<log_message>) {
		if !jsrust::JSRust_SetLogChannel(*cx, *object, chan) { fail; }
	}

	fn init_rust_library(cx : context, object : object) {
		if !jsrust::JSRust_InitRustLibrary(*cx, *object) { fail; }
	}

	fn rust_exit_now(code : int) {
		jsrust::JSRust_Exit(code as c_int);
	}
}

<|endoftext|>


<commit_before>use libc::{c_ulong, c_int};
use {Result, NixPath, from_ffi};

bitflags!(
    flags MsFlags: c_ulong {
        const MS_RDONLY      = 1 << 0,  // Mount read-only
        const MS_NOSUID      = 1 << 1,  // Ignore suid and sgid bits
        const MS_NODEV       = 1 << 2,  // Disallow access to device special files
        const MS_NOEXEC      = 1 << 3,  // Disallow program execution
        const MS_SYNCHRONOUS = 1 << 4,  // Writes are synced at once
        const MS_REMOUNT     = 1 << 5,  // Alter flags of a mounted FS
        const MS_MANDLOCK    = 1 << 6,  // Allow mandatory locks on a FS
        const MS_DIRSYNC     = 1 << 7,  // Directory modifications are synchronous
        const MS_NOATIME     = 1 << 10, // Do not update access times
        const MS_NODIRATIME  = 1 << 11, // Do not update directory access times
        const MS_BIND        = 1 << 12, // Linux 2.4.0 - Bind directory at different place
        const MS_MOVE        = 1 << 13,
        const MS_REC         = 1 << 14,
        const MS_VERBOSE     = 1 << 15, // Deprecated
        const MS_SILENT      = 1 << 15,
        const MS_POSIXACL    = 1 << 16,
        const MS_UNBINDABLE  = 1 << 17,
        const MS_PRIVATE     = 1 << 18,
        const MS_SLAVE       = 1 << 19,
        const MS_SHARED      = 1 << 20,
        const MS_RELATIME    = 1 << 21,
        const MS_KERNMOUNT   = 1 << 22,
        const MS_I_VERSION   = 1 << 23,
        const MS_STRICTATIME = 1 << 24,
        const MS_NOSEC       = 1 << 28,
        const MS_BORN        = 1 << 29,
        const MS_ACTIVE      = 1 << 30,
        const MS_NOUSER      = 1 << 31,
        const MS_RMT_MASK    = MS_RDONLY.bits
                              | MS_SYNCHRONOUS.bits
                              | MS_MANDLOCK.bits
                              | MS_I_VERSION.bits,
        const MS_MGC_VAL     = 0xC0ED0000,
        const MS_MGC_MSK     = 0xffff0000
    }
);

bitflags!(
    flags MntFlags: c_int {
        const MNT_FORCE   = 1 << 0,
        const MNT_DETATCH = 1 << 1,
        const MNT_EXPIRE  = 1 << 2
    }
);

mod ffi {
    use libc::{c_char, c_int};

    extern {
        /*
         * TODO: Bring back
        pub fn mount(
                source: *const c_char,
                target: *const c_char,
                fstype: *const c_char,
                flags: c_ulong,
                data: *const c_void) -> c_int;
                */

        pub fn umount(target: *const c_char) -> c_int;

        pub fn umount2(target: *const c_char, flags: c_int) -> c_int;
    }
}

/*
 * TODO: Bring this back with a test
 *
pub fn mount<P1: ?Sized + NixPath, P2: ?Sized + NixPath, P3: ?Sized + NixPath, P4: ?Sized + NixPath>(
        source: Option<&P1>,
        target: P2,
        fstype: Option<&P3>,
        flags: MsFlags,
        data: Option<&P4>) -> Result<()> {
    use libc;

    let res = try!(try!(try!(try!(
        source.with_nix_path(|source| {
            target.with_nix_path(|target| {
                fstype.with_nix_path(|fstype| {
                    data.with_nix_path(|data| {
                        unsafe {
                            ffi::mount(source.as_ext_str(),
                                       target.as_ext_str(),
                                       fstype,
                                       flags.bits,
                                       data as *const libc::c_void)
                        }
                    })
                })
            })
        })))));

    return from_ffi(res);
}
*/

pub fn umount<P: ?Sized + NixPath>(target: &P) -> Result<()> {
    let res = try!(target.with_nix_path(|cstr| {
        unsafe { ffi::umount(cstr.as_ptr()) }
    }));

    from_ffi(res)
}

pub fn umount2<P: ?Sized + NixPath>(target: &P, flags: MntFlags) -> Result<()> {
    let res = try!(target.with_nix_path(|cstr| {
        unsafe { ffi::umount2(cstr.as_ptr(), flags.bits) }
    }));

    from_ffi(res)
}
<commit_msg>Fix name of MNT_DETACH flag<commit_after>use libc::{c_ulong, c_int};
use {Result, NixPath, from_ffi};

bitflags!(
    flags MsFlags: c_ulong {
        const MS_RDONLY      = 1 << 0,  // Mount read-only
        const MS_NOSUID      = 1 << 1,  // Ignore suid and sgid bits
        const MS_NODEV       = 1 << 2,  // Disallow access to device special files
        const MS_NOEXEC      = 1 << 3,  // Disallow program execution
        const MS_SYNCHRONOUS = 1 << 4,  // Writes are synced at once
        const MS_REMOUNT     = 1 << 5,  // Alter flags of a mounted FS
        const MS_MANDLOCK    = 1 << 6,  // Allow mandatory locks on a FS
        const MS_DIRSYNC     = 1 << 7,  // Directory modifications are synchronous
        const MS_NOATIME     = 1 << 10, // Do not update access times
        const MS_NODIRATIME  = 1 << 11, // Do not update directory access times
        const MS_BIND        = 1 << 12, // Linux 2.4.0 - Bind directory at different place
        const MS_MOVE        = 1 << 13,
        const MS_REC         = 1 << 14,
        const MS_VERBOSE     = 1 << 15, // Deprecated
        const MS_SILENT      = 1 << 15,
        const MS_POSIXACL    = 1 << 16,
        const MS_UNBINDABLE  = 1 << 17,
        const MS_PRIVATE     = 1 << 18,
        const MS_SLAVE       = 1 << 19,
        const MS_SHARED      = 1 << 20,
        const MS_RELATIME    = 1 << 21,
        const MS_KERNMOUNT   = 1 << 22,
        const MS_I_VERSION   = 1 << 23,
        const MS_STRICTATIME = 1 << 24,
        const MS_NOSEC       = 1 << 28,
        const MS_BORN        = 1 << 29,
        const MS_ACTIVE      = 1 << 30,
        const MS_NOUSER      = 1 << 31,
        const MS_RMT_MASK    = MS_RDONLY.bits
                              | MS_SYNCHRONOUS.bits
                              | MS_MANDLOCK.bits
                              | MS_I_VERSION.bits,
        const MS_MGC_VAL     = 0xC0ED0000,
        const MS_MGC_MSK     = 0xffff0000
    }
);

bitflags!(
    flags MntFlags: c_int {
        const MNT_FORCE   = 1 << 0,
        const MNT_DETACH  = 1 << 1,
        const MNT_EXPIRE  = 1 << 2
    }
);

mod ffi {
    use libc::{c_char, c_int};

    extern {
        /*
         * TODO: Bring back
        pub fn mount(
                source: *const c_char,
                target: *const c_char,
                fstype: *const c_char,
                flags: c_ulong,
                data: *const c_void) -> c_int;
                */

        pub fn umount(target: *const c_char) -> c_int;

        pub fn umount2(target: *const c_char, flags: c_int) -> c_int;
    }
}

/*
 * TODO: Bring this back with a test
 *
pub fn mount<P1: ?Sized + NixPath, P2: ?Sized + NixPath, P3: ?Sized + NixPath, P4: ?Sized + NixPath>(
        source: Option<&P1>,
        target: P2,
        fstype: Option<&P3>,
        flags: MsFlags,
        data: Option<&P4>) -> Result<()> {
    use libc;

    let res = try!(try!(try!(try!(
        source.with_nix_path(|source| {
            target.with_nix_path(|target| {
                fstype.with_nix_path(|fstype| {
                    data.with_nix_path(|data| {
                        unsafe {
                            ffi::mount(source.as_ext_str(),
                                       target.as_ext_str(),
                                       fstype,
                                       flags.bits,
                                       data as *const libc::c_void)
                        }
                    })
                })
            })
        })))));

    return from_ffi(res);
}
*/

pub fn umount<P: ?Sized + NixPath>(target: &P) -> Result<()> {
    let res = try!(target.with_nix_path(|cstr| {
        unsafe { ffi::umount(cstr.as_ptr()) }
    }));

    from_ffi(res)
}

pub fn umount2<P: ?Sized + NixPath>(target: &P, flags: MntFlags) -> Result<()> {
    let res = try!(target.with_nix_path(|cstr| {
        unsafe { ffi::umount2(cstr.as_ptr(), flags.bits) }
    }));

    from_ffi(res)
}
<|endoftext|>