<commit_before>use grain_capnp::{PowerboxCapability, UiView, UiSession};
use web_session_capnp::{WebSession};

use collections::hashmap::HashMap;
use capnp::capability::{ClientHook, FromServer};
use capnp::AnyPointer;
use capnp_rpc::rpc::{RpcConnectionState, SturdyRefRestorer};
use capnp_rpc::capability::{LocalClient};

use sqlite3;

pub struct UiViewImpl;

impl PowerboxCapability::Server for UiViewImpl {
    fn get_powerbox_info(&mut self, context : PowerboxCapability::GetPowerboxInfoContext) {
        context.done()
    }
}

impl UiView::Server for UiViewImpl {
    fn get_view_info(&mut self, context : UiView::GetViewInfoContext) {
        context.done()
    }

    fn new_session(&mut self, mut context : UiView::NewSessionContext) {
        println!("asked for a new session!");
        let (_, results) = context.get();

        let client : WebSession::Client = FromServer::new(None::<LocalClient>, ~WebSessionImpl::new());
        // we need to do this dance to upcast.
        results.set_session(UiSession::Client { client : client.client});

        context.done()
    }
}

pub struct WebSessionImpl {
    db : sqlite3::Database,
}

impl WebSessionImpl {
    pub fn new() -> WebSessionImpl {
        WebSessionImpl {
            db : sqlite3::open("/var/data.db").unwrap(),
        }
    }
}

impl UiSession::Server for WebSessionImpl {

}

struct Path {
    path : ~str,
    query : HashMap<~str, ~str>,
}

impl Path {
    fn new() -> Path {
        Path { path : ~"", query : HashMap::new() }
    }
}

fn parse_path(path : &str) -> Path {
    let mut result = Path::new();

    let v : ~[&str] = path.splitn('?', 2).collect();
    if v.len() == 0 {
        return result;
    }
    result.path = v[0].into_owned();
    if v.len() == 1 {
        return result;
    }
    for attr in v[1].split('&') {
        let a : ~[&str] = attr.splitn('=', 2).collect();
        if a.len() == 2 {
            result.query.insert(a[0].into_owned(),
                                a[1].into_owned());
        }
    }
    return result;
}

impl WebSessionImpl {

    fn checked<T>(&self, result : sqlite3::SqliteResult<T>) -> T {
        match result {
            Err(e) => {fail!("database error: {}, {:?}", e, self.db.get_errmsg()) }
            Ok(v) => { return v; }
        }
    }

    fn is_word(&self, word : &str) -> sqlite3::SqliteResult<bool> {

        if ! word.is_alphanumeric() { return Ok(false); }

        let cursor = try!(self.db.prepare(
            format!("SELECT * FROM Words WHERE Word = \"{}\";", word),
            &None));

        return Ok(try!(cursor.step_row()).is_some());
    }

    fn validate_def(&self, word : &str, definition : &[&str]) -> sqlite3::SqliteResult<bool> {

        if definition.len() != word.len() { return Ok(false); }

        let mut idx = 0;
        for &d in definition.iter() {
            if !(try!(self.is_word(d)) && d.len() > 0 && d[0] == word[idx]) {
                return Ok(false);
            }

            idx += 1;
        }

        return Ok(true);
    }

    fn write_def(&self, word : &str, definition : &[&str]) -> sqlite3::SqliteResult<()> {

        let time : i64 = ::time::get_time().sec;
        let mut query = StrBuf::new();
        query.push_str(format!("BEGIN; DELETE FROM Definitions WHERE Definee =\"{}\"; ", word));
        query.push_str("INSERT INTO Definitions(Definee, Idx, Definer) VALUES");
        let mut idx = 0;
        for &d in definition.iter() {
            if idx != 0 { query.push_str(","); }
            query.push_str(format!("(\"{}\", {}, \"{}\")", word, idx, d));
            idx += 1;
        }
        query.push_str(";");
        query.push_str(format!("INSERT Into Log(Word, Timestamp) VALUES({},{});", word, time));
        query.push_str("COMMIT;");

        println!("query: {}", query);

        try!(self.db.exec(query.as_slice()));

        return Ok(());
    }

    fn get_def(&self, word : &str) -> sqlite3::SqliteResult<~str> {

        let cursor = try!(self.db.prepare(
            format!("SELECT * FROM Definitions WHERE Definee = \"{}\";", word),
            &None));

        let mut map = HashMap::<int, ~str>::new();

        loop {
            match try!(cursor.step_row()) {
                None => break,
                Some(row) => {
                    let definer = match row.get(&~"Definer") { &sqlite3::Text(ref t) => t.clone(), _ => fail!(), };
                    let idx = match row.get(&~"Idx") { &sqlite3::Integer(ref i) => i.clone(), _ => fail!(), };

                    map.insert(idx, definer);
                }
            }
        }

        if map.len() != word.len() {
            return Ok(~"
this word has no definition yet
");
        } else {

            let mut result = StrBuf::new();
            result.push_str("
");
            for idx in range::<int>(0, word.len() as int) {
                let definer : &str = map.get(&idx).as_slice();
                result.push_str(format!(" {word} ", word=definer));
            }
            result.push_str("
");
            return Ok(result.into_owned());
        }
    }

    fn count_defs(&self) -> sqlite3::SqliteResult<(int, int, Vec<~str>)> {
        let cursor = try!(self.db.prepare("SELECT COUNT(*) FROM Words;", &None));
        assert!(cursor.step() == sqlite3::SQLITE_ROW);
        let num_words = cursor.get_int(0);

        let cursor = try!(self.db.prepare("SELECT COUNT(*) FROM Definitions WHERE Idx = 0;", &None));
        assert!(cursor.step() == sqlite3::SQLITE_ROW);
        let defined_words = cursor.get_int(0);

        let mut recent_words = Vec::new();
        let cursor = try!(
            self.db.prepare("SELECT Word, Timestamp FROM Log ORDER BY Timestamp DESC LIMIT 5;", &None));
        loop {
            match try!(cursor.step_row()) {
                None => break,
                Some(row) => {
                    let word : ~str = match row.get(&~"Word") {&sqlite3::Text(ref t) => t.clone(), _ => fail!(),};
                    recent_words.push(word);
                }
            }
        }
        Ok((defined_words, num_words, recent_words))

    }

}

static main_css : &'static str =
    "body { font-family: Helvetica, Sans, Arial;
            font-size: medium;
             margin-left: auto;
             margin-right: auto;
             width: 600px;
             text-align: center;
     }
     div {
          padding-bottom: 10pt;
     }
    .word {
        text-align: center;
        font-size: 500%;
     }
     .err {
       font-size: 90%;
       color: #AA0000;
     }
     .title {
       text-align: center;
       font-size:500%;
     }
     ";

static header : &'static str =
  r#"<title> acronymy </title><link rel="stylesheet" type="text/css" href="main.css" >
 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
  "#;

static lookup_form : &'static str =
      r#"<form action="define" method="get">
          <input name="word" maxlength=\"100\"/><button>find word</button></form>"#;

fn define_form(word :&str) -> ~str {
       format!("<form action=\"define\" method=\"get\">
               <input name=\"word\" value=\"{word}\" type=\"hidden\"/>
               <input name=\"definition\" maxlength=\"2000\"/>
                   <button>submit definition</button></form>", word=word)
}

enum PageData<'a> {
    NoWord,
    WordAndDef(&'a str, &'a str, Option<&'a str>),
    HomePage(int, int, Vec<~str>),
}

fn construct_html(page_data : PageData) -> ~str {
    let mut result = StrBuf::new();
    result.push_str(format!("{}", header));

    static home_link : &'static str = "home";
    match page_data {
        NoWord => {
            result.push_str("
 that's not a word
");
            result.push_str(lookup_form);
            result.push_str(home_link);
        }
        WordAndDef(word, def_div, err) => {
            result.push_str(format!("
{}
", word));

            result.push_str(def_div);

            match err {
                None => {}
                Some(e) => {
                    result.push_str(format!("
{}
", e));
                }
            }

            result.push_str(define_form(word));
            result.push_str(home_link);
        }
        HomePage(num_defined, total, recent) => {
            result.push_str("
Acronymy
");
            result.push_str("
A user-editable, acronym-only dictionary.
");
            result.push_str(format!("
So far, we have defined {} out of {} words.
",
                                    num_defined, total));
            if recent.len() > 0 {
                result.push_str("
Recently modified words: ");
                let mut idx = 0;
                for w in recent.iter() {
                    if idx != 0 {
                        result.push_str(", ");
                    }
                    result.push_str(format!("{word}", word=*w));
                    idx += 1;
                }
                result.push_str(".
");
            }
            result.push_str(lookup_form);
        }
    }

    result.push_str("");
    result.into_owned()
}

impl WebSession::Server for WebSessionImpl {
    fn get(&mut self, mut context : WebSession::GetContext) {
        println!("GET");
        let (params, results) = context.get();
        let raw_path = params.get_path();
        let content = results.init_content();
        content.set_mime_type("text/html");

        let path = parse_path(raw_path);
        println!("path = {}", raw_path);

        if raw_path == "main.css" {
            content.get_body().set_bytes(main_css.as_bytes())
        } else if path.path.as_slice() == "define" {
            let word : ~str = match path.query.find(&~"word") {
                Some(w) if self.checked(self.is_word(*w)) => {
                    w.clone()
                }
                _ => {
                    content.get_body().set_bytes(construct_html(NoWord).as_bytes());
                    return context.done();
                }
            };

            match path.query.find(&~"definition") {
                None => {
                    let def_div = self.checked(self.get_def(word));

                    content.get_body().set_bytes(construct_html(WordAndDef(word.as_slice(),
                                                                           def_div.as_slice(),
                                                                           None)).as_bytes());
                }
                Some(def_query) => {

                    let definition : ~[&str] = def_query.split('+').collect();

                    if self.checked(self.validate_def(word, definition)) {

                        self.checked(self.write_def(word, definition));
                        let def_div = self.checked(self.get_def(word));
                        content.get_body().set_bytes(
                            construct_html(WordAndDef(word.as_slice(),
                                                      def_div.as_slice(),
                                                      None)).as_bytes());

                    } else {

                        let def_div = self.checked(self.get_def(word));

                        content.get_body().set_bytes(
                            construct_html(WordAndDef(word.as_slice(),
                                                      def_div.as_slice(),
                                                      Some("invalid definition"))).as_bytes());
                    }
                }
            }

        } else {
            let (num_defined, total, recent) = self.checked(self.count_defs());
            content.get_body().set_bytes(construct_html(HomePage(num_defined, total, recent)).as_bytes());
        }
        context.done()
    }
    fn post(&mut self, context : WebSession::PostContext) {
        println!("POST");
        context.done()
    }
    fn put(&mut self, context : WebSession::PutContext) {
        println!("PUT");
        context.done()
    }
    fn delete(&mut self, context : WebSession::DeleteContext) {
        println!("DELETE");
        context.done()
    }
    fn open_web_socket(&mut self, context : WebSession::OpenWebSocketContext) {
        println!("OPEN WEB SOCKET");
        context.done()
    }
}

pub struct FdStream {
    inner : ~::std::rt::rtio::RtioFileStream:Send,
}

impl FdStream {
    pub fn new(fd : ::libc::c_int) -> ::std::io::IoResult<FdStream> {
        ::std::rt::rtio::LocalIo::maybe_raise(|io| {
            Ok (FdStream { inner : io.fs_from_raw_fd(fd, ::std::rt::rtio::DontClose) })
        })
    }
}

impl Reader for FdStream {
    fn read(&mut self, buf : &mut [u8]) -> ::std::io::IoResult<uint> {
        self.inner.read(buf).map(|i| i as uint)
    }
}

impl Writer for FdStream {
    fn write(&mut self, buf : &[u8]) -> ::std::io::IoResult<()> {
        self.inner.write(buf)
    }
}

pub struct Restorer;

impl SturdyRefRestorer for Restorer {
    fn restore(&self, obj_id : AnyPointer::Reader) -> Option<~ClientHook:Send> {
        if obj_id.is_null() {
            let client : UiView::Client = FromServer::new(None::<LocalClient>, ~UiViewImpl);
            Some(client.client.hook)
        } else {
            None
        }
    }
}

pub fn main() -> ::std::io::IoResult<()> {

    let args = ::std::os::args();

    if args.len() == 4 && args[1].as_slice() == "--init" {
        println!("initializing...");
        let initdb_path = ::std::path::Path::new(args[2].as_slice());
        let proddb_path = ::std::path::Path::new(args[3].as_slice());
        println!("copying database from {} to {}", args[2], args[3]);
        try!(::std::io::fs::copy(&initdb_path, &proddb_path));
        println!("success!");
    }

    // sandstorm launches us with a connection file descriptor 3
    let ifs = try!(FdStream::new(3));
    let ofs = try!(FdStream::new(3));

    let connection_state = RpcConnectionState::new();
    connection_state.run(ifs, ofs, Restorer);

    Ok(())
}

<commit_msg>oops, forgot quote marks<commit_after>use grain_capnp::{PowerboxCapability, UiView, UiSession};
use web_session_capnp::{WebSession};

use collections::hashmap::HashMap;
use capnp::capability::{ClientHook, FromServer};
use capnp::AnyPointer;
use capnp_rpc::rpc::{RpcConnectionState, SturdyRefRestorer};
use capnp_rpc::capability::{LocalClient};

use sqlite3;

pub struct UiViewImpl;

impl PowerboxCapability::Server for UiViewImpl {
    fn get_powerbox_info(&mut self, context : PowerboxCapability::GetPowerboxInfoContext) {
        context.done()
    }
}

impl UiView::Server for UiViewImpl {
    fn get_view_info(&mut self, context : UiView::GetViewInfoContext) {
        context.done()
    }

    fn new_session(&mut self, mut context : UiView::NewSessionContext) {
        println!("asked for a new session!");
        let (_, results) = context.get();

        let client : WebSession::Client = FromServer::new(None::<LocalClient>, ~WebSessionImpl::new());
        // we need to do this dance to upcast.
        results.set_session(UiSession::Client { client : client.client});

        context.done()
    }
}

pub struct WebSessionImpl {
    db : sqlite3::Database,
}

impl WebSessionImpl {
    pub fn new() -> WebSessionImpl {
        WebSessionImpl {
            db : sqlite3::open("/var/data.db").unwrap(),
        }
    }
}

impl UiSession::Server for WebSessionImpl {

}

struct Path {
    path : ~str,
    query : HashMap<~str, ~str>,
}

impl Path {
    fn new() -> Path {
        Path { path : ~"", query : HashMap::new() }
    }
}

fn parse_path(path : &str) -> Path {
    let mut result = Path::new();

    let v : ~[&str] = path.splitn('?', 2).collect();
    if v.len() == 0 {
        return result;
    }
    result.path = v[0].into_owned();
    if v.len() == 1 {
        return result;
    }
    for attr in v[1].split('&') {
        let a : ~[&str] = attr.splitn('=', 2).collect();
        if a.len() == 2 {
            result.query.insert(a[0].into_owned(),
                                a[1].into_owned());
        }
    }
    return result;
}

impl WebSessionImpl {

    fn checked<T>(&self, result : sqlite3::SqliteResult<T>) -> T {
        match result {
            Err(e) => {fail!("database error: {}, {:?}", e, self.db.get_errmsg()) }
            Ok(v) => { return v; }
        }
    }

    fn is_word(&self, word : &str) -> sqlite3::SqliteResult<bool> {

        if ! word.is_alphanumeric() { return Ok(false); }

        let cursor = try!(self.db.prepare(
            format!("SELECT * FROM Words WHERE Word = \"{}\";", word),
            &None));

        return Ok(try!(cursor.step_row()).is_some());
    }

    fn validate_def(&self, word : &str, definition : &[&str]) -> sqlite3::SqliteResult<bool> {

        if definition.len() != word.len() { return Ok(false); }

        let mut idx = 0;
        for &d in definition.iter() {
            if !(try!(self.is_word(d)) && d.len() > 0 && d[0] == word[idx]) {
                return Ok(false);
            }

            idx += 1;
        }

        return Ok(true);
    }

    fn write_def(&self, word : &str, definition : &[&str]) -> sqlite3::SqliteResult<()> {

        let time : i64 = ::time::get_time().sec;
        let mut query = StrBuf::new();
        query.push_str(format!("BEGIN; DELETE FROM Definitions WHERE Definee =\"{}\"; ", word));
        query.push_str("INSERT INTO Definitions(Definee, Idx, Definer) VALUES");
        let mut idx = 0;
        for &d in definition.iter() {
            if idx != 0 { query.push_str(","); }
            query.push_str(format!("(\"{}\", {}, \"{}\")", word, idx, d));
            idx += 1;
        }
        query.push_str(";");
        query.push_str(format!("INSERT Into Log(Word, Timestamp) VALUES(\"{}\",{});", word, time));
        query.push_str("COMMIT;");

        println!("query: {}", query);

        try!(self.db.exec(query.as_slice()));

        return Ok(());
    }

    fn get_def(&self, word : &str) -> sqlite3::SqliteResult<~str> {

        let cursor = try!(self.db.prepare(
            format!("SELECT * FROM Definitions WHERE Definee = \"{}\";", word),
            &None));

        let mut map = HashMap::<int, ~str>::new();

        loop {
            match try!(cursor.step_row()) {
                None => break,
                Some(row) => {
                    let definer = match row.get(&~"Definer") { &sqlite3::Text(ref t) => t.clone(), _ => fail!(), };
                    let idx = match row.get(&~"Idx") { &sqlite3::Integer(ref i) => i.clone(), _ => fail!(), };

                    map.insert(idx, definer);
                }
            }
        }

        if map.len() != word.len() {
            return Ok(~"
this word has no definition yet
");
        } else {

            let mut result = StrBuf::new();
            result.push_str("
");
            for idx in range::<int>(0, word.len() as int) {
                let definer : &str = map.get(&idx).as_slice();
                result.push_str(format!(" {word} ", word=definer));
            }
            result.push_str("
");
            return Ok(result.into_owned());
        }
    }

    fn count_defs(&self) -> sqlite3::SqliteResult<(int, int, Vec<~str>)> {
        let cursor = try!(self.db.prepare("SELECT COUNT(*) FROM Words;", &None));
        assert!(cursor.step() == sqlite3::SQLITE_ROW);
        let num_words = cursor.get_int(0);

        let cursor = try!(self.db.prepare("SELECT COUNT(*) FROM Definitions WHERE Idx = 0;", &None));
        assert!(cursor.step() == sqlite3::SQLITE_ROW);
        let defined_words = cursor.get_int(0);

        let mut recent_words = Vec::new();
        let cursor = try!(
            self.db.prepare("SELECT Word, Timestamp FROM Log ORDER BY Timestamp DESC LIMIT 5;", &None));
        loop {
            match try!(cursor.step_row()) {
                None => break,
                Some(row) => {
                    let word : ~str = match row.get(&~"Word") {&sqlite3::Text(ref t) => t.clone(), _ => fail!(),};
                    recent_words.push(word);
                }
            }
        }
        Ok((defined_words, num_words, recent_words))

    }

}

static main_css : &'static str =
    "body { font-family: Helvetica, Sans, Arial;
            font-size: medium;
             margin-left: auto;
             margin-right: auto;
             width: 600px;
             text-align: center;
     }
     div {
          padding-bottom: 10pt;
     }
    .word {
        text-align: center;
        font-size: 500%;
     }
     .err {
       font-size: 90%;
       color: #AA0000;
     }
     .title {
       text-align: center;
       font-size:500%;
     }
     ";

static header : &'static str =
  r#"<title> acronymy </title><link rel="stylesheet" type="text/css" href="main.css" >
 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
  "#;

static lookup_form : &'static str =
      r#"<form action="define" method="get">
          <input name="word" maxlength=\"100\"/><button>find word</button></form>"#;

fn define_form(word :&str) -> ~str {
       format!("<form action=\"define\" method=\"get\">
               <input name=\"word\" value=\"{word}\" type=\"hidden\"/>
               <input name=\"definition\" maxlength=\"2000\"/>
                   <button>submit definition</button></form>", word=word)
}

enum PageData<'a> {
    NoWord,
    WordAndDef(&'a str, &'a str, Option<&'a str>),
    HomePage(int, int, Vec<~str>),
}

fn construct_html(page_data : PageData) -> ~str {
    let mut result = StrBuf::new();
    result.push_str(format!("{}", header));

    static home_link : &'static str = "home";
    match page_data {
        NoWord => {
            result.push_str("
 that's not a word
");
            result.push_str(lookup_form);
            result.push_str(home_link);
        }
        WordAndDef(word, def_div, err) => {
            result.push_str(format!("
{}
", word));

            result.push_str(def_div);

            match err {
                None => {}
                Some(e) => {
                    result.push_str(format!("
{}
", e));
                }
            }

            result.push_str(define_form(word));
            result.push_str(home_link);
        }
        HomePage(num_defined, total, recent) => {
            result.push_str("
Acronymy
");
            result.push_str("
A user-editable, acronym-only dictionary.
");
            result.push_str(format!("
So far, we have defined {} out of {} words.
",
                                    num_defined, total));
            if recent.len() > 0 {
                result.push_str("
Recently modified words: ");
                let mut idx = 0;
                for w in recent.iter() {
                    if idx != 0 {
                        result.push_str(", ");
                    }
                    result.push_str(format!("{word}", word=*w));
                    idx += 1;
                }
                result.push_str(".
");
            }
            result.push_str(lookup_form);
        }
    }

    result.push_str("");
    result.into_owned()
}

impl WebSession::Server for WebSessionImpl {
    fn get(&mut self, mut context : WebSession::GetContext) {
        println!("GET");
        let (params, results) = context.get();
        let raw_path = params.get_path();
        let content = results.init_content();
        content.set_mime_type("text/html");

        let path = parse_path(raw_path);
        println!("path = {}", raw_path);

        if raw_path == "main.css" {
            content.get_body().set_bytes(main_css.as_bytes())
        } else if path.path.as_slice() == "define" {
            let word : ~str = match path.query.find(&~"word") {
                Some(w) if self.checked(self.is_word(*w)) => {
                    w.clone()
                }
                _ => {
                    content.get_body().set_bytes(construct_html(NoWord).as_bytes());
                    return context.done();
                }
            };

            match path.query.find(&~"definition") {
                None => {
                    let def_div = self.checked(self.get_def(word));

                    content.get_body().set_bytes(construct_html(WordAndDef(word.as_slice(),
                                                                           def_div.as_slice(),
                                                                           None)).as_bytes());
                }
                Some(def_query) => {

                    let definition : ~[&str] = def_query.split('+').collect();

                    if self.checked(self.validate_def(word, definition)) {

                        self.checked(self.write_def(word, definition));
                        let def_div = self.checked(self.get_def(word));
                        content.get_body().set_bytes(
                            construct_html(WordAndDef(word.as_slice(),
                                                      def_div.as_slice(),
                                                      None)).as_bytes());

                    } else {

                        let def_div = self.checked(self.get_def(word));

                        content.get_body().set_bytes(
                            construct_html(WordAndDef(word.as_slice(),
                                                      def_div.as_slice(),
                                                      Some("invalid definition"))).as_bytes());
                    }
                }
            }

        } else {
            let (num_defined, total, recent) = self.checked(self.count_defs());
            content.get_body().set_bytes(construct_html(HomePage(num_defined, total, recent)).as_bytes());
        }
        context.done()
    }
    fn post(&mut self, context : WebSession::PostContext) {
        println!("POST");
        context.done()
    }
    fn put(&mut self, context : WebSession::PutContext) {
        println!("PUT");
        context.done()
    }
    fn delete(&mut self, context : WebSession::DeleteContext) {
        println!("DELETE");
        context.done()
    }
    fn open_web_socket(&mut self, context : WebSession::OpenWebSocketContext) {
        println!("OPEN WEB SOCKET");
        context.done()
    }
}

pub struct FdStream {
    inner : ~::std::rt::rtio::RtioFileStream:Send,
}

impl FdStream {
    pub fn new(fd : ::libc::c_int) -> ::std::io::IoResult<FdStream> {
        ::std::rt::rtio::LocalIo::maybe_raise(|io| {
            Ok (FdStream { inner : io.fs_from_raw_fd(fd, ::std::rt::rtio::DontClose) })
        })
    }
}

impl Reader for FdStream {
    fn read(&mut self, buf : &mut [u8]) -> ::std::io::IoResult<uint> {
        self.inner.read(buf).map(|i| i as uint)
    }
}

impl Writer for FdStream {
    fn write(&mut self, buf : &[u8]) -> ::std::io::IoResult<()> {
        self.inner.write(buf)
    }
}

pub struct Restorer;

impl SturdyRefRestorer for Restorer {
    fn restore(&self, obj_id : AnyPointer::Reader) -> Option<~ClientHook:Send> {
        if obj_id.is_null() {
            let client : UiView::Client = FromServer::new(None::<LocalClient>, ~UiViewImpl);
            Some(client.client.hook)
        } else {
            None
        }
    }
}

pub fn main() -> ::std::io::IoResult<()> {

    let args = ::std::os::args();

    if args.len() == 4 && args[1].as_slice() == "--init" {
        println!("initializing...");
        let initdb_path = ::std::path::Path::new(args[2].as_slice());
        let proddb_path = ::std::path::Path::new(args[3].as_slice());
        println!("copying database from {} to {}", args[2], args[3]);
        try!(::std::io::fs::copy(&initdb_path, &proddb_path));
        println!("success!");
    }

    // sandstorm launches us with a connection file descriptor 3
    let ifs = try!(FdStream::new(3));
    let ofs = try!(FdStream::new(3));

    let connection_state = RpcConnectionState::new();
    connection_state.run(ifs, ofs, Restorer);

    Ok(())
}

<|endoftext|>


<commit_before>use std::io::{Read, Write, Result};
use std::net::{ToSocketAddrs, SocketAddr};
use std::ops::Deref;
use socket::UtpSocket;

/// A structure that represents a uTP (Micro Transport Protocol) stream between a local socket and a
/// remote socket.
///
/// The connection will be closed when the value is dropped (either explicitly or when it goes out of
/// scope).
///
/// # Examples
///
/// ```no_run
/// use utp::UtpStream;
/// use std::io::{Read, Write};
///
/// let mut stream = UtpStream::bind("127.0.0.1:1234").unwrap();
/// let _ = stream.write(&[1]);
/// let _ = stream.read(&mut [0; 1000]);
/// ```
pub struct UtpStream {
    socket: UtpSocket,
}

impl UtpStream {
    /// Creates a uTP stream listening on the given address.
    ///
    /// The address type can be any implementor of the `ToSocketAddr` trait. See its documentation
    /// for concrete examples.
    ///
    /// If more than one valid address is specified, only the first will be used.
    pub fn bind<A: ToSocketAddrs>(addr: A) -> Result<UtpStream> {
        UtpSocket::bind(addr).and_then(|s| Ok(UtpStream { socket: s }))
    }

    /// Opens a uTP connection to a remote host by hostname or IP address.
    ///
    /// The address type can be any implementor of the `ToSocketAddr` trait. See its documentation
    /// for concrete examples.
    ///
    /// If more than one valid address is specified, only the first will be used.
    pub fn connect<A: ToSocketAddrs>(dst: A) -> Result<UtpStream> {
        // Port 0 means the operating system gets to choose it
        UtpSocket::connect(dst)
            .and_then(|s| Ok(UtpStream { socket: s }))
    }

    /// Gracefully closes connection to peer.
    ///
    /// This method allows both peers to receive all packets still in
    /// flight.
    pub fn close(&mut self) -> Result<()> {
        self.socket.close()
    }

    /// Returns the socket address of the local half of this uTP connection.
    pub fn local_addr(&self) -> Result<SocketAddr> {
        self.socket.local_addr()
    }
}

impl Read for UtpStream {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        self.socket.recv_from(buf).map(|(read, _src)| read)
    }
}

impl Write for UtpStream {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        self.socket.send_to(buf)
    }

    fn flush(&mut self) -> Result<()> {
        self.socket.flush()
    }
}

impl Into<UtpStream> for UtpSocket {
    fn into(self) -> UtpStream {
        UtpStream { socket: self }
    }
}

impl Deref for UtpStream {
    type Target = UtpSocket;

    fn deref(&self) -> &UtpSocket {
        &self.socket
    }
}
<commit_msg>Replace `and_then` with `map`.<commit_after>use std::io::{Read, Write, Result};
use std::net::{ToSocketAddrs, SocketAddr};
use std::ops::Deref;
use socket::UtpSocket;

/// A structure that represents a uTP (Micro Transport Protocol) stream between a local socket and a
/// remote socket.
///
/// The connection will be closed when the value is dropped (either explicitly or when it goes out of
/// scope).
///
/// # Examples
///
/// ```no_run
/// use utp::UtpStream;
/// use std::io::{Read, Write};
///
/// let mut stream = UtpStream::bind("127.0.0.1:1234").unwrap();
/// let _ = stream.write(&[1]);
/// let _ = stream.read(&mut [0; 1000]);
/// ```
pub struct UtpStream {
    socket: UtpSocket,
}

impl UtpStream {
    /// Creates a uTP stream listening on the given address.
    ///
    /// The address type can be any implementor of the `ToSocketAddr` trait. See its documentation
    /// for concrete examples.
    ///
    /// If more than one valid address is specified, only the first will be used.
    pub fn bind<A: ToSocketAddrs>(addr: A) -> Result<UtpStream> {
        UtpSocket::bind(addr).map(|s| UtpStream { socket: s })
    }

    /// Opens a uTP connection to a remote host by hostname or IP address.
    ///
    /// The address type can be any implementor of the `ToSocketAddr` trait. See its documentation
    /// for concrete examples.
    ///
    /// If more than one valid address is specified, only the first will be used.
    pub fn connect<A: ToSocketAddrs>(dst: A) -> Result<UtpStream> {
        // Port 0 means the operating system gets to choose it
        UtpSocket::connect(dst).map(|s| UtpStream { socket: s })
    }

    /// Gracefully closes connection to peer.
    ///
    /// This method allows both peers to receive all packets still in
    /// flight.
    pub fn close(&mut self) -> Result<()> {
        self.socket.close()
    }

    /// Returns the socket address of the local half of this uTP connection.
    pub fn local_addr(&self) -> Result<SocketAddr> {
        self.socket.local_addr()
    }
}

impl Read for UtpStream {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        self.socket.recv_from(buf).map(|(read, _src)| read)
    }
}

impl Write for UtpStream {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        self.socket.send_to(buf)
    }

    fn flush(&mut self) -> Result<()> {
        self.socket.flush()
    }
}

impl Into<UtpStream> for UtpSocket {
    fn into(self) -> UtpStream {
        UtpStream { socket: self }
    }
}

impl Deref for UtpStream {
    type Target = UtpSocket;

    fn deref(&self) -> &UtpSocket {
        &self.socket
    }
}
<|endoftext|>


<commit_before>//! An efficient module for generating unique IDs
//! The unique ID's are 128bits so you can theoretically run out of them but that's very unlikely.
use std::cell::{UnsafeCell, Cell};
use std::sync::{StaticMutex, MUTEX_INIT};
use std::marker::Sync;
use std::u16;
use std::num::Int;

#[derive(Copy, PartialEq, Eq)]
pub struct Tag {
    prefix: TagPrefix,
    offset: u16,
}
#[derive(Copy, PartialEq, Eq)]
struct TagPrefix(u64, u32, u16);

struct Tagger {
    mutex: StaticMutex,
    value: UnsafeCell<(u64, u64)>,
}

impl Tagger {
    fn next(&'static self) -> TagPrefix {
        let old;
        unsafe {
            let _l = self.mutex.lock().unwrap();
            old = *self.value.get();
            *self.value.get() = match old.1 + 1 {
                n if n <= (u16::MAX as u64) => (old.0, n),
                _ => match old.0.checked_add(1) {
                    Some(n) => (n, 0),
                    None => panic!("CoatCheck ID overflow!")
                }
            };
        }
        TagPrefix(old.0, (old.1 >> 16) as u32, old.1 as u16)
    }
}

unsafe impl Sync for Tagger {}

static GLOBAL_TAG_PREFIX: Tagger = Tagger {
    mutex: MUTEX_INIT,
    value: UnsafeCell { value: (0, 0) },
};

thread_local!(static NEXT_LOCAL_TAG: Cell<Tag> = Cell::new(Tag { prefix: GLOBAL_TAG_PREFIX.next(), offset: 0 }));

pub fn next_tag() -> Tag {
    NEXT_LOCAL_TAG.with(|tag| match tag.get() {
        Tag { offset: u16::MAX, .. } => {
            let prefix = GLOBAL_TAG_PREFIX.next();
            tag.set(Tag { prefix: prefix, offset: 1 });
            Tag { prefix: prefix, offset: 0 }
        },
        inner_tag => {
            tag.set(Tag {
                prefix: inner_tag.prefix,
                offset: inner_tag.offset + 1
            });
            inner_tag
        }
    })
}
<commit_msg>make next_tag inline (slight improvement).<commit_after>//! An efficient module for generating unique IDs
//! The unique ID's are 128bits so you can theoretically run out of them but that's very unlikely.
use std::cell::{UnsafeCell, Cell};
use std::sync::{StaticMutex, MUTEX_INIT};
use std::marker::Sync;
use std::u16;
use std::num::Int;

#[derive(Copy, PartialEq, Eq)]
pub struct Tag {
    prefix: TagPrefix,
    offset: u16,
}
#[derive(Copy, PartialEq, Eq)]
struct TagPrefix(u64, u32, u16);

struct Tagger {
    mutex: StaticMutex,
    value: UnsafeCell<(u64, u64)>,
}

impl Tagger {
    fn next(&'static self) -> TagPrefix {
        let old;
        unsafe {
            let _l = self.mutex.lock().unwrap();
            old = *self.value.get();
            *self.value.get() = match old.1 + 1 {
                n if n <= (u16::MAX as u64) => (old.0, n),
                _ => match old.0.checked_add(1) {
                    Some(n) => (n, 0),
                    None => panic!("CoatCheck ID overflow!")
                }
            };
        }
        TagPrefix(old.0, (old.1 >> 16) as u32, old.1 as u16)
    }
}

unsafe impl Sync for Tagger {}

static GLOBAL_TAG_PREFIX: Tagger = Tagger {
    mutex: MUTEX_INIT,
    value: UnsafeCell { value: (0, 0) },
};

thread_local!(static NEXT_LOCAL_TAG: Cell<Tag> = Cell::new(Tag { prefix: GLOBAL_TAG_PREFIX.next(), offset: 0 }));

#[inline]
pub fn next_tag() -> Tag {
    NEXT_LOCAL_TAG.with(|tag| match tag.get() {
        Tag { offset: u16::MAX, .. } => {
            let prefix = GLOBAL_TAG_PREFIX.next();
            tag.set(Tag { prefix: prefix, offset: 1 });
            Tag { prefix: prefix, offset: 0 }
        },
        inner_tag => {
            tag.set(Tag {
                prefix: inner_tag.prefix,
                offset: inner_tag.offset + 1
            });
            inner_tag
        }
    })
}
<|endoftext|>


<commit_before>extern crate ndarray;

use ndarray_ext::NdArray;
use op;
use op::Op;
use ops;
use std::cell::Cell;
use std::fmt;
use std::mem;
use std::ops::{Deref, DerefMut};
use std::rc::Rc;

/// Symbolic multi-dimensional array.
pub struct Tensor(pub Rc<TensorCore>);

pub struct TensorCore
{
    /// Operation of this node.
    pub op: Box<op::Op>,
    /// References to immediate predecessors.
    pub inputs: Vec<Tensor>,
    /// Rank number for topological ordering in a graph.
    pub top_rank: usize,
    /// Symbolic shape of this tensor.
    pub shape: Option<Tensor>,
    /// Variable or constant array is placed here.
    pub persistent_array: Option<PersistentArray>,
    /// Used to look up a resource of this tensor.
    pub resource_lookup_key: Cell<usize>,
    /// Immutable flag of tensor is placeholder or not.
    pub is_placeholder: bool,
    /// `op` can have gradient?
    pub has_gradient: bool,
    /// Indices of arrays used in `compute`
    pub input_indices: Vec<usize>,
}

pub enum PersistentArray
{
    Variable(NdArray),
    Constant(NdArray),
}

impl PersistentArray
{
    pub fn get_as_variable(&self) -> &NdArray
    {
        match *self {
            PersistentArray::Variable(ref a) => a,
            PersistentArray::Constant(_) => panic!("Can't mutate constant tensor"),
        }
    }

    #[allow(mutable_transmutes)]
    pub unsafe fn get_as_variable_mut(&self) -> &mut NdArray
    {
        mem::transmute(self.get_as_variable())
    }

    pub fn get_array(&self) -> &NdArray
    {
        match *self {
            PersistentArray::Variable(ref a) => a,
            PersistentArray::Constant(ref a) => a,
        }
    }

    pub fn shape(&self) -> &[usize]
    {
        match *self {
            PersistentArray::Variable(ref a) => a.shape(),
            PersistentArray::Constant(ref a) => a.shape(),
        }
    }
}

pub struct TensorBuilder
{
    shape:            Option<Tensor>,
    inputs:           Vec<Tensor>,
    has_gradient:     bool,
    is_placeholder:   bool,
    persistent_array: Option<PersistentArray>,
    input_indices:    Option<Vec<usize>>,
}

impl TensorBuilder
{
    #[inline]
    pub fn set_shape(mut self, s: Tensor) -> TensorBuilder
    {
        self.shape = Some(s);
        self
    }

    #[inline]
    pub fn set_has_gradient(mut self, a: bool) -> TensorBuilder
    {
        self.has_gradient = a;
        self
    }

    #[inline]
    pub fn set_inputs(mut self, a: Vec<&Tensor>) -> TensorBuilder
    {
        self.inputs = a.iter().map(|b| (*b).clone()).collect::<Vec<Tensor>>();
        self
    }

    #[inline]
    pub fn set_inputs_slice(mut self, a: &[&Tensor]) -> TensorBuilder
    {
        self.inputs = a.iter().map(|b| (*b).clone()).collect::<Vec<Tensor>>();
        self
    }

    #[inline]
    pub fn set_input(mut self, a: &Tensor) -> TensorBuilder
    {
        self.inputs = vec![a.clone()];
        self
    }

    #[inline]
    pub fn set_is_placeholder(mut self, a: bool) -> TensorBuilder
    {
        self.is_placeholder = a;
        self
    }

    #[inline]
    pub fn set_constant_array(mut self, a: NdArray) -> TensorBuilder
    {
        self.persistent_array = Some(PersistentArray::Constant(a));
        self
    }

    #[inline]
    pub fn set_variable_array(mut self, a: NdArray) -> TensorBuilder
    {
        self.persistent_array = Some(PersistentArray::Variable(a));
        self
    }

    #[inline]
    pub fn set_input_indices(mut self, a: Vec<usize>) -> TensorBuilder
    {
        self.input_indices = Some(a);
        self
    }

    /// ```
    /// extern crate ndarray;
    /// extern crate autograd as ag;
    ///
    /// let ref a = ag::zeros(&[4, 2]);
    /// let ref v = ag::zeros(&[2, 3]);
    /// let ref b = ag::zeros(&[4, 3]);
    /// let ref z = ag::matmul(a, v) + b;
    /// let mut vars = [a, v, b, z];
    /// // `sort_by_key` don't reverse the order of `a` and `v`
    /// vars.sort_by_key(|a| a.top_rank);
    /// assert!(vars == [a, v, b, z])
    /// ```
    #[inline]
    pub fn build<T: Op + 'static>(self, op: T) -> Tensor
    {
        let rank = if self.inputs.len() == 0 {
            0
        } else {
            self.inputs
                .iter()
                .map(|a| a.top_rank)
                .max()
                .map(|a| a + 1)
                .unwrap_or(0)
        };

        let input_indices = if let Some(a) = self.input_indices {
            assert_eq!(a.len(), self.inputs.len());
            a
        } else {
            vec![0; self.inputs.len()]
        };

        Tensor(Rc::new(TensorCore {
            op: Box::new(op),
            inputs: self.inputs,
            top_rank: rank,
            shape: self.shape,
            persistent_array: self.persistent_array,
            is_placeholder: self.is_placeholder,
            resource_lookup_key: Cell::new(!0),
            has_gradient: self.has_gradient,
            input_indices,
        }))
    }
}

impl Tensor
{
    #[inline]
    pub fn builder() -> TensorBuilder
    {
        TensorBuilder {
            shape:            None,
            inputs:           Vec::new(),
            has_gradient:     true,
            persistent_array: None,
            is_placeholder:   false,
            input_indices:    None,
        }
    }

    /// Evaluates this tensor as a ndarray's array object.
    ///
    /// See [eval](../fn.eval.html).
    pub fn eval<'a, 'b: 'a, 'c: 'a, T>(&self, feeds: T)
        -> Result<ndarray::Array<f32, ndarray::IxDyn>, ::runtime::EvaluationError>
    where
        T: IntoIterator<Item = &'a (&'b Tensor, &'c ndarray::Array<f32, ndarray::IxDyn>)>,
    {
        ::runtime::eval(&[self], feeds).remove(0)
    }

    /// Returns the (symbolic) shape of this tensor.
    ///
    /// See [shape](../ops/fn.shape.html).
    pub fn shape(&self) -> Tensor
    {
        ::ops::shape(self)
    }

    /// Returns the (symbolic) rank of this tensor.
    ///
    /// See [rank](../ops/fn.rank.html).
    pub fn rank(&self) -> Tensor
    {
        ::ops::rank(self)
    }

    /// Returns the (symbolic) size of this tensor.
    ///
    /// See [size](../ops/fn.size.html).
    pub fn size(&self) -> Tensor
    {
        ::ops::size(self)
    }

    #[doc(hidden)]
    #[inline]
    /// Returns true if this node has no incoming nodes.
    pub fn is_source(&self) -> bool
    {
        self.inputs.is_empty()
    }
}

// empty implementation
impl Eq for Tensor {}

impl PartialEq for Tensor
{
    fn eq(&self, other: &Tensor) -> bool
    {
        // compare addresses on the heap
        Rc::ptr_eq(&self.0, &other.0)
    }
}

impl AsRef<Tensor> for Tensor
{
    #[inline(always)]
    fn as_ref(&self) -> &Tensor
    {
        self
    }
}

// data is not cloned; only reference count is incremented.
impl Clone for Tensor
{
    fn clone(&self) -> Tensor
    {
        Tensor(self.0.clone())
    }
}

impl Deref for Tensor
{
    type Target = Rc<TensorCore>;
    fn deref(&self) -> &Self::Target
    {
        &self.0
    }
}

impl DerefMut for Tensor
{
    fn deref_mut<'a>(&'a mut self) -> &'a mut Rc<TensorCore>
    {
        &mut self.0
    }
}

impl fmt::Display for Tensor
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        let input_names = self.0
            .inputs
            .iter()
            .map(|a| a.op.name().to_string())
            .collect::<Vec<String>>();
        write!(
            f,
            "name={}, inputs={:?}",
            self.0.op.name(),
            input_names.as_slice()
        )
    }
}

/// Implementors can be converted to `Tensor`.
pub trait ArrayLike
{
    fn as_tensor(&self) -> Tensor;
}

impl ArrayLike for Tensor
{
    fn as_tensor(&self) -> Tensor
    {
        self.clone()
    }
}

macro_rules! impl_array_like_for_array {
    ($scalar_type:ty, $num_elems:expr) => {
        impl ArrayLike for [$scalar_type; $num_elems] {
            fn as_tensor(&self) -> Tensor
            {
                let vec = self
                    .iter()
                    .map(|&a| a as f32 )
                    .collect::<Vec<f32>>();

                // unwrap is safe
                let arr = NdArray::from_shape_vec(ndarray::IxDyn(&[self.len()]), vec).unwrap();
                ops::convert_to_tensor(arr)
            }
        }
    };
}

impl_array_like_for_array!(f32, 0);
impl_array_like_for_array!(f32, 1);
impl_array_like_for_array!(f32, 2);
impl_array_like_for_array!(f32, 3);
impl_array_like_for_array!(f32, 4);
impl_array_like_for_array!(f32, 5);
impl_array_like_for_array!(f32, 6);
impl_array_like_for_array!(f32, 7);
impl_array_like_for_array!(f32, 8);

impl_array_like_for_array!(f64, 0);
impl_array_like_for_array!(f64, 1);
impl_array_like_for_array!(f64, 2);
impl_array_like_for_array!(f64, 3);
impl_array_like_for_array!(f64, 4);
impl_array_like_for_array!(f64, 5);
impl_array_like_for_array!(f64, 6);
impl_array_like_for_array!(f64, 7);
impl_array_like_for_array!(f64, 8);

impl_array_like_for_array!(i32, 0);
impl_array_like_for_array!(i32, 1);
impl_array_like_for_array!(i32, 2);
impl_array_like_for_array!(i32, 3);
impl_array_like_for_array!(i32, 4);
impl_array_like_for_array!(i32, 5);
impl_array_like_for_array!(i32, 6);
impl_array_like_for_array!(i32, 7);
impl_array_like_for_array!(i32, 8);

impl_array_like_for_array!(i64, 0);
impl_array_like_for_array!(i64, 1);
impl_array_like_for_array!(i64, 2);
impl_array_like_for_array!(i64, 3);
impl_array_like_for_array!(i64, 4);
impl_array_like_for_array!(i64, 5);
impl_array_like_for_array!(i64, 6);
impl_array_like_for_array!(i64, 7);
impl_array_like_for_array!(i64, 8);

impl_array_like_for_array!(isize, 0);
impl_array_like_for_array!(isize, 1);
impl_array_like_for_array!(isize, 2);
impl_array_like_for_array!(isize, 3);
impl_array_like_for_array!(isize, 4);
impl_array_like_for_array!(isize, 5);
impl_array_like_for_array!(isize, 6);
impl_array_like_for_array!(isize, 7);
impl_array_like_for_array!(isize, 8);

impl_array_like_for_array!(usize, 0);
impl_array_like_for_array!(usize, 1);
impl_array_like_for_array!(usize, 2);
impl_array_like_for_array!(usize, 3);
impl_array_like_for_array!(usize, 4);
impl_array_like_for_array!(usize, 5);
impl_array_like_for_array!(usize, 6);
impl_array_like_for_array!(usize, 7);
impl_array_like_for_array!(usize, 8);

impl_array_like_for_array!(u32, 0);
impl_array_like_for_array!(u32, 1);
impl_array_like_for_array!(u32, 2);
impl_array_like_for_array!(u32, 3);
impl_array_like_for_array!(u32, 4);
impl_array_like_for_array!(u32, 5);
impl_array_like_for_array!(u32, 6);
impl_array_like_for_array!(u32, 7);
impl_array_like_for_array!(u32, 8);

impl_array_like_for_array!(u64, 0);
impl_array_like_for_array!(u64, 1);
impl_array_like_for_array!(u64, 2);
impl_array_like_for_array!(u64, 3);
impl_array_like_for_array!(u64, 4);
impl_array_like_for_array!(u64, 5);
impl_array_like_for_array!(u64, 6);
impl_array_like_for_array!(u64, 7);
impl_array_like_for_array!(u64, 8);
<commit_msg>Adds `Tensor::get_array` and `Tensor::get_array_mut`<commit_after>extern crate ndarray;

use ndarray_ext::NdArray;
use op;
use op::Op;
use ops;
use std::cell::Cell;
use std::fmt;
use std::mem;
use std::ops::{Deref, DerefMut};
use std::rc::Rc;

/// Symbolic multi-dimensional array.
pub struct Tensor(pub Rc<TensorCore>);

pub struct TensorCore
{
    /// Operation of this node.
    pub op: Box<op::Op>,
    /// References to immediate predecessors.
    pub inputs: Vec<Tensor>,
    /// Rank number for topological ordering in a graph.
    pub top_rank: usize,
    /// Symbolic shape of this tensor.
    pub shape: Option<Tensor>,
    /// Variable or constant array is placed here.
    pub persistent_array: Option<PersistentArray>,
    /// Used to look up a resource of this tensor.
    pub resource_lookup_key: Cell<usize>,
    /// Immutable flag of tensor is placeholder or not.
    pub is_placeholder: bool,
    /// `op` can have gradient?
    pub has_gradient: bool,
    /// Indices of arrays used in `compute`
    pub input_indices: Vec<usize>,
}

pub enum PersistentArray
{
    Variable(NdArray),
    Constant(NdArray),
}

impl Tensor {
    /// Returns a reference to the backing array, if one exists. A `Tensor`
    /// that's a placeholder won't have a backing array, and will return
    /// `None`.
    pub fn get_array(&self) -> Option<&NdArray> {
        self.0.persistent_array.as_ref()
            .map(|p| {
                match p {
                    &PersistentArray::Variable(ref arr) => arr,
                    &PersistentArray::Constant(ref arr) => arr,
                }
            })
    }

    /// Returns a mutable reference to the backing array, if one exists, the
    /// `Tensor` has not been copied, and is permissible to mutate. A placeholder
    /// `Tensor` has no backing array, and will return `None`. If the `Tensor` is
    /// a constant, this will also return `None`, as mutating a constant is not
    /// permitted. If any copies have been made, accessing a `&mut` of the
    /// inner `Rc<TensorCore>` that houses the backing array will be impossible.
    pub fn get_array_mut(&mut self) -> Option<&mut NdArray> {
        //inner.persistent_array.as_mut()
        Rc::get_mut(&mut self.0)
            .and_then(|t| {
                t.persistent_array.as_mut()
            }).and_then(|p| {
                match p {
                    &mut PersistentArray::Variable(ref mut arr) => Some(arr),
                    _ => None
                }
            })
    }
}

impl PersistentArray
{
    pub fn get_as_variable(&self) -> &NdArray
    {
        match *self {
            PersistentArray::Variable(ref a) => a,
            PersistentArray::Constant(_) => panic!("Can't mutate constant tensor"),
        }
    }

    #[allow(mutable_transmutes)]
    pub unsafe fn get_as_variable_mut(&self) -> &mut NdArray
    {
        mem::transmute(self.get_as_variable())
    }

    pub fn get_array(&self) -> &NdArray
    {
        match *self {
            PersistentArray::Variable(ref a) => a,
            PersistentArray::Constant(ref a) => a,
        }
    }

    pub fn shape(&self) -> &[usize]
    {
        match *self {
            PersistentArray::Variable(ref a) => a.shape(),
            PersistentArray::Constant(ref a) => a.shape(),
        }
    }
}

pub struct TensorBuilder
{
    shape:            Option<Tensor>,
    inputs:           Vec<Tensor>,
    has_gradient:     bool,
    is_placeholder:   bool,
    persistent_array: Option<PersistentArray>,
    input_indices:    Option<Vec<usize>>,
}

impl TensorBuilder
{
    #[inline]
    pub fn set_shape(mut self, s: Tensor) -> TensorBuilder
    {
        self.shape = Some(s);
        self
    }

    #[inline]
    pub fn set_has_gradient(mut self, a: bool) -> TensorBuilder
    {
        self.has_gradient = a;
        self
    }

    #[inline]
    pub fn set_inputs(mut self, a: Vec<&Tensor>) -> TensorBuilder
    {
        self.inputs = a.iter().map(|b| (*b).clone()).collect::<Vec<Tensor>>();
        self
    }

    #[inline]
    pub fn set_inputs_slice(mut self, a: &[&Tensor]) -> TensorBuilder
    {
        self.inputs = a.iter().map(|b| (*b).clone()).collect::<Vec<Tensor>>();
        self
    }

    #[inline]
    pub fn set_input(mut self, a: &Tensor) -> TensorBuilder
    {
        self.inputs = vec![a.clone()];
        self
    }

    #[inline]
    pub fn set_is_placeholder(mut self, a: bool) -> TensorBuilder
    {
        self.is_placeholder = a;
        self
    }

    #[inline]
    pub fn set_constant_array(mut self, a: NdArray) -> TensorBuilder
    {
        self.persistent_array = Some(PersistentArray::Constant(a));
        self
    }

    #[inline]
    pub fn set_variable_array(mut self, a: NdArray) -> TensorBuilder
    {
        self.persistent_array = Some(PersistentArray::Variable(a));
        self
    }

    #[inline]
    pub fn set_input_indices(mut self, a: Vec<usize>) -> TensorBuilder
    {
        self.input_indices = Some(a);
        self
    }

    /// ```
    /// extern crate ndarray;
    /// extern crate autograd as ag;
    ///
    /// let ref a = ag::zeros(&[4, 2]);
    /// let ref v = ag::zeros(&[2, 3]);
    /// let ref b = ag::zeros(&[4, 3]);
    /// let ref z = ag::matmul(a, v) + b;
    /// let mut vars = [a, v, b, z];
    /// // `sort_by_key` don't reverse the order of `a` and `v`
    /// vars.sort_by_key(|a| a.top_rank);
    /// assert!(vars == [a, v, b, z])
    /// ```
    #[inline]
    pub fn build<T: Op + 'static>(self, op: T) -> Tensor
    {
        let rank = if self.inputs.len() == 0 {
            0
        } else {
            self.inputs
                .iter()
                .map(|a| a.top_rank)
                .max()
                .map(|a| a + 1)
                .unwrap_or(0)
        };

        let input_indices = if let Some(a) = self.input_indices {
            assert_eq!(a.len(), self.inputs.len());
            a
        } else {
            vec![0; self.inputs.len()]
        };

        Tensor(Rc::new(TensorCore {
            op: Box::new(op),
            inputs: self.inputs,
            top_rank: rank,
            shape: self.shape,
            persistent_array: self.persistent_array,
            is_placeholder: self.is_placeholder,
            resource_lookup_key: Cell::new(!0),
            has_gradient: self.has_gradient,
            input_indices,
        }))
    }
}

impl Tensor
{
    #[inline]
    pub fn builder() -> TensorBuilder
    {
        TensorBuilder {
            shape:            None,
            inputs:           Vec::new(),
            has_gradient:     true,
            persistent_array: None,
            is_placeholder:   false,
            input_indices:    None,
        }
    }

    /// Evaluates this tensor as a ndarray's array object.
    ///
    /// See [eval](../fn.eval.html).
    pub fn eval<'a, 'b: 'a, 'c: 'a, T>(&self, feeds: T)
        -> Result<ndarray::Array<f32, ndarray::IxDyn>, ::runtime::EvaluationError>
    where
        T: IntoIterator<Item = &'a (&'b Tensor, &'c ndarray::Array<f32, ndarray::IxDyn>)>,
    {
        ::runtime::eval(&[self], feeds).remove(0)
    }

    /// Returns the (symbolic) shape of this tensor.
    ///
    /// See [shape](../ops/fn.shape.html).
    pub fn shape(&self) -> Tensor
    {
        ::ops::shape(self)
    }

    /// Returns the (symbolic) rank of this tensor.
    ///
    /// See [rank](../ops/fn.rank.html).
    pub fn rank(&self) -> Tensor
    {
        ::ops::rank(self)
    }

    /// Returns the (symbolic) size of this tensor.
    ///
    /// See [size](../ops/fn.size.html).
    pub fn size(&self) -> Tensor
    {
        ::ops::size(self)
    }

    #[doc(hidden)]
    #[inline]
    /// Returns true if this node has no incoming nodes.
    pub fn is_source(&self) -> bool
    {
        self.inputs.is_empty()
    }
}

// empty implementation
impl Eq for Tensor {}

impl PartialEq for Tensor
{
    fn eq(&self, other: &Tensor) -> bool
    {
        // compare addresses on the heap
        Rc::ptr_eq(&self.0, &other.0)
    }
}

impl AsRef<Tensor> for Tensor
{
    #[inline(always)]
    fn as_ref(&self) -> &Tensor
    {
        self
    }
}

// data is not cloned; only reference count is incremented.
impl Clone for Tensor
{
    fn clone(&self) -> Tensor
    {
        Tensor(self.0.clone())
    }
}

impl Deref for Tensor
{
    type Target = Rc<TensorCore>;
    fn deref(&self) -> &Self::Target
    {
        &self.0
    }
}

impl DerefMut for Tensor
{
    fn deref_mut<'a>(&'a mut self) -> &'a mut Rc<TensorCore>
    {
        &mut self.0
    }
}

impl fmt::Display for Tensor
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        let input_names = self.0
            .inputs
            .iter()
            .map(|a| a.op.name().to_string())
            .collect::<Vec<String>>();
        write!(
            f,
            "name={}, inputs={:?}",
            self.0.op.name(),
            input_names.as_slice()
        )
    }
}

/// Implementors can be converted to `Tensor`.
pub trait ArrayLike
{
    fn as_tensor(&self) -> Tensor;
}

impl ArrayLike for Tensor
{
    fn as_tensor(&self) -> Tensor
    {
        self.clone()
    }
}

macro_rules! impl_array_like_for_array {
    ($scalar_type:ty, $num_elems:expr) => {
        impl ArrayLike for [$scalar_type; $num_elems] {
            fn as_tensor(&self) -> Tensor
            {
                let vec = self
                    .iter()
                    .map(|&a| a as f32 )
                    .collect::<Vec<f32>>();

                // unwrap is safe
                let arr = NdArray::from_shape_vec(ndarray::IxDyn(&[self.len()]), vec).unwrap();
                ops::convert_to_tensor(arr)
            }
        }
    };
}

impl_array_like_for_array!(f32, 0);
impl_array_like_for_array!(f32, 1);
impl_array_like_for_array!(f32, 2);
impl_array_like_for_array!(f32, 3);
impl_array_like_for_array!(f32, 4);
impl_array_like_for_array!(f32, 5);
impl_array_like_for_array!(f32, 6);
impl_array_like_for_array!(f32, 7);
impl_array_like_for_array!(f32, 8);

impl_array_like_for_array!(f64, 0);
impl_array_like_for_array!(f64, 1);
impl_array_like_for_array!(f64, 2);
impl_array_like_for_array!(f64, 3);
impl_array_like_for_array!(f64, 4);
impl_array_like_for_array!(f64, 5);
impl_array_like_for_array!(f64, 6);
impl_array_like_for_array!(f64, 7);
impl_array_like_for_array!(f64, 8);

impl_array_like_for_array!(i32, 0);
impl_array_like_for_array!(i32, 1);
impl_array_like_for_array!(i32, 2);
impl_array_like_for_array!(i32, 3);
impl_array_like_for_array!(i32, 4);
impl_array_like_for_array!(i32, 5);
impl_array_like_for_array!(i32, 6);
impl_array_like_for_array!(i32, 7);
impl_array_like_for_array!(i32, 8);

impl_array_like_for_array!(i64, 0);
impl_array_like_for_array!(i64, 1);
impl_array_like_for_array!(i64, 2);
impl_array_like_for_array!(i64, 3);
impl_array_like_for_array!(i64, 4);
impl_array_like_for_array!(i64, 5);
impl_array_like_for_array!(i64, 6);
impl_array_like_for_array!(i64, 7);
impl_array_like_for_array!(i64, 8);

impl_array_like_for_array!(isize, 0);
impl_array_like_for_array!(isize, 1);
impl_array_like_for_array!(isize, 2);
impl_array_like_for_array!(isize, 3);
impl_array_like_for_array!(isize, 4);
impl_array_like_for_array!(isize, 5);
impl_array_like_for_array!(isize, 6);
impl_array_like_for_array!(isize, 7);
impl_array_like_for_array!(isize, 8);

impl_array_like_for_array!(usize, 0);
impl_array_like_for_array!(usize, 1);
impl_array_like_for_array!(usize, 2);
impl_array_like_for_array!(usize, 3);
impl_array_like_for_array!(usize, 4);
impl_array_like_for_array!(usize, 5);
impl_array_like_for_array!(usize, 6);
impl_array_like_for_array!(usize, 7);
impl_array_like_for_array!(usize, 8);

impl_array_like_for_array!(u32, 0);
impl_array_like_for_array!(u32, 1);
impl_array_like_for_array!(u32, 2);
impl_array_like_for_array!(u32, 3);
impl_array_like_for_array!(u32, 4);
impl_array_like_for_array!(u32, 5);
impl_array_like_for_array!(u32, 6);
impl_array_like_for_array!(u32, 7);
impl_array_like_for_array!(u32, 8);

impl_array_like_for_array!(u64, 0);
impl_array_like_for_array!(u64, 1);
impl_array_like_for_array!(u64, 2);
impl_array_like_for_array!(u64, 3);
impl_array_like_for_array!(u64, 4);
impl_array_like_for_array!(u64, 5);
impl_array_like_for_array!(u64, 6);
impl_array_like_for_array!(u64, 7);
impl_array_like_for_array!(u64, 8);
<|endoftext|>


<commit_before>use super::ToTokens;
use std::fmt::{self, Display};

#[derive(Debug)]
pub struct Tokens(String);

impl Tokens {
    pub fn new() -> Self {
        Tokens(String::new())
    }

    pub fn append(&mut self, token: &str) {
        self.0.push_str(token);
        self.0.push(' ');
    }

    pub fn append_separated<T, I>(&mut self, iter: I, sep: &str)
        where T: ToTokens,
              I: IntoIterator<Item = T>
    {
        for (i, token) in iter.into_iter().enumerate() {
            if i > 0 {
                self.append(sep);
            }
            token.to_tokens(self);
        }
    }
}

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

impl Display for Tokens {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.0.fmt(formatter)
    }
}
<commit_msg>Allow cloning `Tokens`<commit_after>use super::ToTokens;
use std::fmt::{self, Display};

#[derive(Debug, Clone)]
pub struct Tokens(String);

impl Tokens {
    pub fn new() -> Self {
        Tokens(String::new())
    }

    pub fn append(&mut self, token: &str) {
        self.0.push_str(token);
        self.0.push(' ');
    }

    pub fn append_separated<T, I>(&mut self, iter: I, sep: &str)
        where T: ToTokens,
              I: IntoIterator<Item = T>
    {
        for (i, token) in iter.into_iter().enumerate() {
            if i > 0 {
                self.append(sep);
            }
            token.to_tokens(self);
        }
    }
}

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

impl Display for Tokens {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.0.fmt(formatter)
    }
}
<|endoftext|>


<commit_before>use gcref::GCRef;

/// `InHeap` types can be stored directly in the GC heap. All primitive types
/// and many standard types implement `InHeap`.
///
/// Application code does not need to use this trait. It is only public so that
/// the public macros can use it. Use the friendly macros!
///
/// GC types come in pairs: an `InHeap` type, which is stored physically inside
/// the heap, and may be packed with pointer fields and unsafe methods; and an
/// `IntoHeap` type, which is safe, is used in application code, and lives on
/// the stack.
///
/// Users never get a direct `&` reference to any value stored in the heap. All
/// access is through safe `IntoHeap` types, like `GCRef`.
///
/// *   For primitive types, like `i32`, the two types are the same.
///
/// *   `GCRef<'a, T>` is an `IntoHeap` type; the corresponding `InHeap` type
///     is the pointer type `*mut T`.
///
/// *   For macro-generated structs and enums, the user specifies the names of
///     both types. Both types have identical fields or variants, but fields of
///     the `InHeap` type are `InHeap`, and fields of the `IntoHeap` type are
///     `IntoHeap`.
///
/// Unsafe to implement: `from_heap` is incredibly dangerous. It receives a
/// non-mut reference to a heap value. That value may contain gc-references to
/// itself, directly or indirectly, in which case `from_heap` (or other code it
/// calls) could *without using any unsafe code* modify the heap while this
/// direct, non-mut reference exists. This breaks Rust's aliasing rules and
/// could cause crashes.
///
/// Implementation note: every type with `'static` lifetime should be safe to
/// store in the heap, because ref types are never `'static`. Unfortunately I
/// can't make rustc understand this. It would be *legal* to write this:
///
/// ```ignore
/// unsafe impl<'a, T: Clone + 'static> InHeap<'a> for T { ...trivial... }
/// unsafe impl<'a, T: Clone + 'static> IntoHeap<'a> for T { ...trivial... }
/// ```
///
/// but alas, Rust thinks those impls conflict with almost all others, making
/// it impossible to get the macros to work. So instead we `impl InHeap for` a
/// lot of individual types by hand.
///
pub unsafe trait InHeap<'a>: Sized {
    type Out: IntoHeap<'a, In=Self>;

    unsafe fn mark(ptr: *mut Self);

    /// Extract the value from the heap. This turns any raw pointers in the
    /// `InHeap` value into safe references, so while it's an unsafe function,
    /// the result of a correct call can be safely handed out to user code.
    ///
    /// Unsafe to call: It is impossible for ordinary users to call this
    /// safely, because `self` must be a direct, unwrapped reference to a value
    /// stored in the GC heap, which ordinary users cannot obtain.
    ///
    unsafe fn from_heap(&self) -> Self::Out;
}

/// Non-inlined function that serves as an entry point to marking. This is used
/// for marking root set entries.
pub unsafe fn mark_entry_point<'a, T: InHeap<'a>>(addr: *mut ()) {
    InHeap::mark(addr as *mut T);
}

/// `IntoHeap` types live on the stack, in application code. They are the
/// safe, user-friendly analogues to pointer-filled `InHeap` types. When you
/// use `gc_ref_type!` to declare a new GC struct or enum, `IntoHeap` types are
/// the types you use for fields.
///
/// Application code does not need to use this trait. It is only public so that
/// the public macros can use it. Use the friendly macros!
///
/// "Safe to use" means they don't expose pointers or references to GC memory;
/// and they obey Rust's safety and aliasing rules. If an `IntoHeap` value
/// contains a pointer to a GC allocation, then that allocation (and everything
/// reachable from it) is protected from GC.
///
/// "Stored in a field of a GC struct" - This includes primitive types like
/// `i32`, but also GC structs and enums (they can nest).
///
/// Unsafe to implement: `InHeap` objects are full of pointers; if `into_heap`
/// puts garbage into them, GC will crash.
///
pub unsafe trait IntoHeap<'a>: Sized {
    /// The type of the value when it is physically stored in the heap.
    type In: InHeap<'a, Out=Self>;

    /// Convert the value to the form it should have in the heap.
    /// This is for macro-generated code to call.
    fn into_heap(self) -> Self::In;
}

pub fn heap_type_id<'a, T: InHeap<'a>>() -> usize {
    mark_entry_point::<T> as *const () as usize
}

/// Relate an `IntoHeap` type to the corresponding safe reference type.
///
/// Application code does not need to use this trait. It is only public so that
/// the public macros can use it. Use the friendly macros!
///
pub trait IntoHeapAllocation<'a>: IntoHeap<'a>
{
    type Ref: IntoHeap<'a>;

    fn wrap_gcref(gcref: GCRef<'a, Self::In>) -> Self::Ref;
}

// === Provided implmentations for primitive types

macro_rules! gc_trivial_impl {
    ($t:ty) => {
        unsafe impl<'a> InHeap<'a> for $t {
            type Out = $t;
            unsafe fn mark(_ptr: *mut $t) {}
            unsafe fn from_heap(&self) -> $t { self.clone() }
        }

        unsafe impl<'a> IntoHeap<'a> for $t {
            type In = $t;
            fn into_heap(self) -> $t { self }
        }
    }
}

macro_rules! gc_generic_trivial_impl {
    (#[as_item] $it:item) => { $it};
    ([$($x:tt)*] $t:ty) => {
        gc_generic_trivial_impl! {
            #[as_item]
            unsafe impl<'a, $($x)*> InHeap<'a> for $t {
                type Out = $t;
                unsafe fn mark(_ptr: *mut $t) {}
                unsafe fn from_heap(&self) -> $t { self.clone() }
            }
        }

        gc_generic_trivial_impl! {
            #[as_item]
            unsafe impl<'a, $($x)*> IntoHeap<'a> for $t {
                type In = $t;
                fn into_heap(self) -> $t { self }
            }
        }
    }
}

gc_trivial_impl!(bool);
gc_trivial_impl!(char);
gc_trivial_impl!(i8);
gc_trivial_impl!(u8);
gc_trivial_impl!(i16);
gc_trivial_impl!(u16);
gc_trivial_impl!(i32);
gc_trivial_impl!(u32);
gc_trivial_impl!(i64);
gc_trivial_impl!(u64);
gc_trivial_impl!(isize);
gc_trivial_impl!(usize);
gc_trivial_impl!(f32);
gc_trivial_impl!(f64);

gc_generic_trivial_impl!([T: ?Sized] &'static T);
gc_generic_trivial_impl!([T: Clone + 'static] Box<T>);
gc_generic_trivial_impl!([T: Clone + 'static] ::std::rc::Rc<T>);

// Transitive implementations ("this particular kind of struct/enum is InHeap
// if all its fields are") are slightly less trivial.

unsafe impl<'a, U: InHeap<'a>> InHeap<'a> for Option<U> {
    type Out = Option<U::Out>;

    unsafe fn mark(ptr: *mut Option<U>) {
        match *ptr {
            None => (),
            Some(ref mut u) => InHeap::mark(u as *mut U)
        }
    }

    unsafe fn from_heap(&self) -> Option<U::Out> {
        match self {
            &None => None,
            &Some(ref u) => Some(u.from_heap())
        }
    }
}

unsafe impl<'a, T: IntoHeap<'a>> IntoHeap<'a> for Option<T> {
    type In = Option<T::In>;
    fn into_heap(self) -> Option<T::In> {
        self.map(|t| t.into_heap())
    }
}

macro_rules! gc_trivial_tuple_impl {
    (#[as_item] $it:item) => { $it };
    ($($t:ident),*) => {
        gc_trivial_tuple_impl! {
            #[as_item]
            unsafe impl<'a $(, $t: InHeap<'a>)*> InHeap<'a> for ($($t,)*) {
                type Out = ($($t::Out,)*);

                #[allow(non_snake_case)]  // because we use the type names as variable names (!)
                unsafe fn mark(ptr: *mut Self) {
                    let ($(ref mut $t,)*) = *ptr;
                    $(InHeap::mark($t as *mut $t);)*
                }

                #[allow(non_snake_case)]
                unsafe fn from_heap(&self) -> Self::Out {
                    let ($(ref $t,)*) = *self;
                    ($($t.from_heap(),)*)
                }
            }
        }

        gc_trivial_tuple_impl! {
            #[as_item]
            unsafe impl<'a, $($t: IntoHeap<'a>,)*> IntoHeap<'a> for ($($t,)*) {
                type In = ($($t::In,)*);

                #[allow(non_snake_case)]
                fn into_heap(self) -> Self::In {
                    let ($($t,)*) = self;
                    ($($t.into_heap(),)*)
                }
            }
        }
    }
}

gc_trivial_tuple_impl!();
gc_trivial_tuple_impl!(T);
gc_trivial_tuple_impl!(T, U);
gc_trivial_tuple_impl!(T, U, V);
gc_trivial_tuple_impl!(T, U, V, W);
gc_trivial_tuple_impl!(T, U, V, W, X);
gc_trivial_tuple_impl!(T, U, V, W, X, Y);
gc_trivial_tuple_impl!(T, U, V, W, X, Y, Z);
<commit_msg>traits.rs: Comments.<commit_after>//! The traits defined here are implementation details of toy_gc.
//!
//! Application code does not need to use these traits. They are public only so
//! that the public macros can use it. Use the friendly macros!

use gcref::GCRef;

/// `InHeap` types can be stored directly in the GC heap. All primitive types
/// and many standard types implement `InHeap`.
///
/// GC types come in pairs: an `InHeap` type, which is stored physically inside
/// the heap, and may be packed with pointer fields and unsafe methods; and an
/// `IntoHeap` type, which is safe, is used in application code, and lives on
/// the stack.
///
/// Users never get a direct `&` reference to any value stored in the heap. All
/// access is through safe `IntoHeap` types, like `GCRef`.
///
/// *   For primitive types, like `i32`, the two types are the same.
///
/// *   `GCRef<'a, T>` is an `IntoHeap` type; the corresponding `InHeap` type
///     is the pointer type `*mut T`.
///
/// *   For macro-generated structs and enums, the user specifies the names of
///     both types. Both types have identical fields or variants, but fields of
///     the `InHeap` type are `InHeap`, and fields of the `IntoHeap` type are
///     `IntoHeap`.
///
/// Unsafe to implement: `from_heap` is incredibly dangerous. It receives a
/// non-mut reference to a heap value. That value may contain gc-references to
/// itself, directly or indirectly, in which case `from_heap` (or other code it
/// calls) could *without using any unsafe code* modify the heap while this
/// direct, non-mut reference exists. This breaks Rust's aliasing rules and
/// could cause crashes.
///
/// Implementation note: every type with `'static` lifetime should be safe to
/// store in the heap, because ref types are never `'static`. Unfortunately I
/// can't make rustc understand this. It would be *legal* to write this:
///
/// ```ignore
/// unsafe impl<'a, T: Clone + 'static> InHeap<'a> for T { ...trivial... }
/// unsafe impl<'a, T: Clone + 'static> IntoHeap<'a> for T { ...trivial... }
/// ```
///
/// but alas, Rust thinks those impls conflict with almost all others, making
/// it impossible to get the macros to work. So instead we `impl InHeap for` a
/// lot of individual types by hand.
pub unsafe trait InHeap<'a>: Sized {
    type Out: IntoHeap<'a, In=Self>;

    /// Unsafe to call: It is impossible for ordinary users to call this
    /// safely, because `ptr` must be a raw pointer to a value stored in the GC
    /// heap, which ordinary users cannot obtain.
    unsafe fn mark(ptr: *mut Self);

    /// Extract the value from the heap. This turns any raw pointers in the
    /// `InHeap` value into safe references, so while it's an unsafe function,
    /// the result of a correct call can be safely handed out to user code.
    ///
    /// Unsafe to call: It is impossible for ordinary users to call this
    /// safely, because `self` must be a direct, unwrapped reference to a value
    /// stored in the GC heap, which ordinary users cannot obtain.
    unsafe fn from_heap(&self) -> Self::Out;
}

/// Non-inlined function that serves as an entry point to marking. This is used
/// for marking root set entries.
pub unsafe fn mark_entry_point<'a, T: InHeap<'a>>(addr: *mut ()) {
    InHeap::mark(addr as *mut T);
}

/// `IntoHeap` types live on the stack, in application code. They are the
/// safe, user-friendly analogues to pointer-filled `InHeap` types. When you
/// use `gc_ref_type!` to declare a new GC struct or enum, `IntoHeap` types are
/// the types you use for fields.
///
/// "Safe to use" means they don't expose pointers or references to GC memory;
/// and they obey Rust's safety and aliasing rules. If an `IntoHeap` value
/// contains a pointer to a GC allocation, then that allocation (and everything
/// reachable from it) is protected from GC.
///
/// "Stored in a field of a GC struct" - This includes primitive types like
/// `i32`, but also GC structs and enums (they can nest).
///
/// Unsafe to implement: `InHeap` objects are full of pointers; if `into_heap`
/// puts garbage into them, GC will crash.
pub unsafe trait IntoHeap<'a>: Sized {
    /// The type of the value when it is physically stored in the heap.
    type In: InHeap<'a, Out=Self>;

    /// Convert the value to the form it should have in the heap.
    /// This is for macro-generated code to call.
    ///
    /// This method must not be called while any direct Rust references to
    /// heap objects exist. (However, user code never runs while such
    /// references exist, so the method is not marked `unsafe`.)
    fn into_heap(self) -> Self::In;
}

pub fn heap_type_id<'a, T: InHeap<'a>>() -> usize {
    mark_entry_point::<T> as *const () as usize
}

/// Relate an `IntoHeap` type to the corresponding safe reference type.
pub trait IntoHeapAllocation<'a>: IntoHeap<'a>
{
    type Ref: IntoHeap<'a>;

    fn wrap_gcref(gcref: GCRef<'a, Self::In>) -> Self::Ref;
}

// === Provided implmentations for primitive types

macro_rules! gc_trivial_impl {
    ($t:ty) => {
        unsafe impl<'a> InHeap<'a> for $t {
            type Out = $t;
            unsafe fn mark(_ptr: *mut $t) {}
            unsafe fn from_heap(&self) -> $t { self.clone() }
        }

        unsafe impl<'a> IntoHeap<'a> for $t {
            type In = $t;
            fn into_heap(self) -> $t { self }
        }
    }
}

macro_rules! gc_generic_trivial_impl {
    (#[as_item] $it:item) => { $it};
    ([$($x:tt)*] $t:ty) => {
        gc_generic_trivial_impl! {
            #[as_item]
            unsafe impl<'a, $($x)*> InHeap<'a> for $t {
                type Out = $t;
                unsafe fn mark(_ptr: *mut $t) {}
                unsafe fn from_heap(&self) -> $t { self.clone() }
            }
        }

        gc_generic_trivial_impl! {
            #[as_item]
            unsafe impl<'a, $($x)*> IntoHeap<'a> for $t {
                type In = $t;
                fn into_heap(self) -> $t { self }
            }
        }
    }
}

gc_trivial_impl!(bool);
gc_trivial_impl!(char);
gc_trivial_impl!(i8);
gc_trivial_impl!(u8);
gc_trivial_impl!(i16);
gc_trivial_impl!(u16);
gc_trivial_impl!(i32);
gc_trivial_impl!(u32);
gc_trivial_impl!(i64);
gc_trivial_impl!(u64);
gc_trivial_impl!(isize);
gc_trivial_impl!(usize);
gc_trivial_impl!(f32);
gc_trivial_impl!(f64);

gc_generic_trivial_impl!([T: ?Sized] &'static T);
gc_generic_trivial_impl!([T: Clone + 'static] Box<T>);
gc_generic_trivial_impl!([T: Clone + 'static] ::std::rc::Rc<T>);

// Transitive implementations ("this particular kind of struct/enum is InHeap
// if all its fields are") are slightly less trivial.

unsafe impl<'a, U: InHeap<'a>> InHeap<'a> for Option<U> {
    type Out = Option<U::Out>;

    unsafe fn mark(ptr: *mut Option<U>) {
        match *ptr {
            None => (),
            Some(ref mut u) => InHeap::mark(u as *mut U)
        }
    }

    unsafe fn from_heap(&self) -> Option<U::Out> {
        match self {
            &None => None,
            &Some(ref u) => Some(u.from_heap())
        }
    }
}

unsafe impl<'a, T: IntoHeap<'a>> IntoHeap<'a> for Option<T> {
    type In = Option<T::In>;
    fn into_heap(self) -> Option<T::In> {
        self.map(|t| t.into_heap())
    }
}

macro_rules! gc_trivial_tuple_impl {
    (#[as_item] $it:item) => { $it };
    ($($t:ident),*) => {
        gc_trivial_tuple_impl! {
            #[as_item]
            unsafe impl<'a $(, $t: InHeap<'a>)*> InHeap<'a> for ($($t,)*) {
                type Out = ($($t::Out,)*);

                #[allow(non_snake_case)]  // because we use the type names as variable names (!)
                unsafe fn mark(ptr: *mut Self) {
                    let ($(ref mut $t,)*) = *ptr;
                    $(InHeap::mark($t as *mut $t);)*
                }

                #[allow(non_snake_case)]
                unsafe fn from_heap(&self) -> Self::Out {
                    let ($(ref $t,)*) = *self;
                    ($($t.from_heap(),)*)
                }
            }
        }

        gc_trivial_tuple_impl! {
            #[as_item]
            unsafe impl<'a, $($t: IntoHeap<'a>,)*> IntoHeap<'a> for ($($t,)*) {
                type In = ($($t::In,)*);

                #[allow(non_snake_case)]
                fn into_heap(self) -> Self::In {
                    let ($($t,)*) = self;
                    ($($t.into_heap(),)*)
                }
            }
        }
    }
}

gc_trivial_tuple_impl!();
gc_trivial_tuple_impl!(T);
gc_trivial_tuple_impl!(T, U);
gc_trivial_tuple_impl!(T, U, V);
gc_trivial_tuple_impl!(T, U, V, W);
gc_trivial_tuple_impl!(T, U, V, W, X);
gc_trivial_tuple_impl!(T, U, V, W, X, Y);
gc_trivial_tuple_impl!(T, U, V, W, X, Y, Z);
<|endoftext|>


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

#[derive(Debug)]
pub enum GraphProperty {
    i64,
    float,
    String,
}

use edge::{Edge,EdgeProxy};

/*
* storing in & out edges seperately should cut down on the number of "things" i have to traverse
* if a vertex has 10k edges (5k in and out 5k out) then doing something like*   g(v).outV()
* should be ok
*/
#[derive(Debug)]
pub struct Vertex {
    pub id: i64,
    pub properties: HashMap<String, GraphProperty>,
    // pointers on both sides, yay
    pub out_edges: Vec<*mut Edge>,
    pub in_edges:  Vec<*mut Edge>,
}

impl Vertex {
    pub fn new(id: i64) -> Box<Vertex> {
        let mut props  = HashMap::new();
        Box::new(Vertex{id:id,
                        properties: props,
                        out_edges: Vec::new(),
                        in_edges: Vec::new()})
    }
}

pub struct VertexProxy {
    pub id: i64,
    pub v: *mut Vertex,
}

impl VertexProxy {
    pub fn add_edge(&mut self, to_vertex: &mut VertexProxy) -> EdgeProxy {
        let in_vertex: &mut Vertex;
        let out_vertex: &mut Vertex;

        unsafe {
            in_vertex =  &mut *(self.v);
            out_vertex = &mut *(to_vertex.v);
        }

        // create the edge
        let e = Box::new(Edge{from_vertex: self.v, to_vertex: to_vertex.v});

        let edge: *mut Edge = unsafe { mem::transmute(e) };

        in_vertex.out_edges.push(edge);
        out_vertex.in_edges.push(edge);
        EdgeProxy{edge:edge}
    }

    pub fn query(self) {
        unimplemented!()
    }
}

impl Deref for VertexProxy {
    type Target = Vertex;

    fn deref<'a>(&'a self) -> &'a Vertex {
        unsafe {
            &*(self.v)
        }
    }
}

enum GraphIterable {
    VertexProxy,
    EdgeProxy
}

struct GraphPath {
    path: GraphIterable
}
<commit_msg>set property<commit_after>use std::ops::Deref;
use std::mem;
use std::collections::HashMap;

#[derive(Debug)]
pub enum GraphProperty {
    i64,
    float,
    String,
}

use edge::{Edge,EdgeProxy};

/*
* storing in & out edges seperately should cut down on the number of "things" i have to traverse
* if a vertex has 10k edges (5k in and out 5k out) then doing something like*   g(v).outV()
* should be ok
*/
#[derive(Debug)]
pub struct Vertex {
    pub id: i64,
    pub properties: HashMap<String, GraphProperty>,
    // pointers on both sides, yay
    pub out_edges: Vec<*mut Edge>,
    pub in_edges:  Vec<*mut Edge>,
}

impl Vertex {
    pub fn new(id: i64) -> Box<Vertex> {
        let mut props  = HashMap::new();
        Box::new(Vertex{id:id,
                        properties: props,
                        out_edges: Vec::new(),
                        in_edges: Vec::new()})
    }

}

pub struct VertexProxy {
    pub id: i64,
    pub v: *mut Vertex,
}

impl VertexProxy {
    pub fn add_edge(&mut self, to_vertex: &mut VertexProxy) -> EdgeProxy {
        let in_vertex: &mut Vertex;
        let out_vertex: &mut Vertex;

        unsafe {
            in_vertex =  &mut *(self.v);
            out_vertex = &mut *(to_vertex.v);
        }

        // create the edge
        let e = Box::new(Edge{from_vertex: self.v, to_vertex: to_vertex.v});

        let edge: *mut Edge = unsafe { mem::transmute(e) };

        in_vertex.out_edges.push(edge);
        out_vertex.in_edges.push(edge);
        EdgeProxy{edge:edge}
    }

    pub fn set_property(&mut self, field: String, value: GraphProperty) {
        unimplemented!();
    }

    pub fn query(self) {
        unimplemented!()
    }
}

impl Deref for VertexProxy {
    type Target = Vertex;

    fn deref<'a>(&'a self) -> &'a Vertex {
        unsafe {
            &*(self.v)
        }
    }
}

enum GraphIterable {
    VertexProxy,
    EdgeProxy
}

struct GraphPath {
    path: GraphIterable
}
<|endoftext|>