+++ /dev/null
-
-#[derive(Error)]
-enum Error {
- [error("attempt to create instance with same name as existing instance")]
- InstanceAlreadyExists,
- [error("attempt to create instance with same name as existing instance")]
- UnknownInstance,
-}
+++ /dev/null
-
-struct PlayerRecord {
- nick : String,
-}
-
-pub struct GameRef (InstanceGuard);
-impl Deref for GameRef {
- type Output = GamState;
- fn deref(&self) -> &GameState { self.0.read() }
-}
-
-struct LogMessage (HtmlString);
-
-impl PieceRecord {
- fn msg(&self) -> MsgPiece { self.p.svg(self) }
-}
-
-impl GameRef {
- fn piece_insert(&mut self, i : usize,
- p : Rc<PieceRecord>, msg : LogMessage) {
- self.0.action(|g| {
- g.pieces.insert(i, p);
- (msg, MsgPieceInsert(i, p))
- );
- fn piece_delete(&mut self, i : usize, msg : LogMessage) {
- self.0.action(|g| {
- let old = g.pieces.remove(i, p);
- (msg, MsgPieceDelete(i, old))
- }
- }
- fn piece_update(&mut self, i : usize, p : PieceRecord) {
- self.0.action(|g| {
- let new = p.clone();
- let old = replace(g.pieces[i], p);
- (msg, MsgPieceUpdate(i, old, new))
- }
- }
-}
+++ /dev/null
-
-#[throws(E)]
-fn create_instance_access(name : &str, i : Rc<Instance>) {
- let w = GLOBAL.instances().write();
- match w.entry(name) {
- Occupied(oe) => throw!(anyhow!("access key alreay defined"));
- Vacant(ve) => ve.insert(i);
- }
-}
-
-/*
-impl<'r> FromParam<'r> for InstanceGuard<'r> {
- type Error = AE;
- #[throws(E)]
- fn from_param(param: &'r RawStr) -> Self {
- let g = GLOBAL.instances().read();
- let iname = param.as_str();
- let i = g.get(iname);
- let i = i.ok_or(anyhow!("unnown instance"))?;
- i.lock(iname)
- }
-}
-*/
-
const RECENT_BUFFER : usize = 10;
-
-#[derive(Debug)]
-pub struct Instance {
- mod_token : RawToken,
- g : RwLock<Game>,
- g_notify : Condvar,
-}
-
-#[derive(Debug)]
-struct Game {
- log : VecDeque<LogEntry>,
-}
-
-struct LogEntry {
- game : Vec<GameUpdate>,
- msgs : Vec<LogMessage>,
-}
-
-impl From<(LogMessage, GameUpdate)> for LogEntry {
- fn from((msg, gu) : (LogMessage, GameUpdate)) -> LogEntry {
- LogEntry { game : vec![lm], msgs: vec![msg] }
- }
-}
-
-impl Instance {
- fn new(gs : GameState) -> Instance {
- Instance {
- g_notify : Condvar::new(),
- g : RwLock::new(Game {
- gen : 0,
- gs,
- recent : VecDequeue::with_capacity(RECENT_BUFFER),
- }),
- }
- }
-}
-
-pub struct InstanceGuard<'r> {
- iname : &'r str;
- g : RwLockWriteGuard<Game>,
- g_notify : &'r Condvar,
-}
-
-impl Instance {
- fn lock(&'r self, iname : &'r str) -> InstanceGuard<'r> {
- let g = self.g.lock();
- InstanceGuard { g, iname, g_notify : &self.g_notify }
- }
-}
-
-impl InstanceGuard {
- fn read(&self) -> &GameState { &self.g.deref().gs }
- fn iname(&self) -> &str { self.iname }
-
- fn<F,L> action(&mut self, f : F)
- where F : FnOnce(&mut GameState) -> L
- L : Into<LogEntry>
- {
- let msg = f(&mut self.gs.g),
- if let MsgNoUpdate = msg { return }
- self.gs.gen += 1,
- if self.gw.recent.len() >= RECENT_BUFFER { self.pop_front() }
- self.g.evenglog.push_back(msg);
- self.g_notify.notify_all();
- }
-}
+++ /dev/null
-
-#![feature(proc_macro_hygiene, decl_macro)]
-
-#[macro_use] extern crate rocket;
-
-extern crate rocket_contrib; // why do we need this ?
-extern crate serde;
-extern crate thiserror;
-extern crate anyhow;
-
-mod imports;
-use imports::*;
-
-type RE = E;
-
-pub type InstanceName = String;
-
-#[derive(Serialize,Debug)]
-struct TestRenderContext { }
-
-#[get("/")]
-fn index() -> Result<Template,RE> {
- let c = TestRenderContext { };
- Ok(Template::render("test",&c))
-}
-
-const RESOURCES : &[&'static str] = &["script.js", "style.css"];
-
-#[derive(Debug)]
-struct CheckedResourceLeaf { pub safe : &'static str }
-#[derive(Error,Debug)]
-#[error("not a valid resource path")]
-struct UnknownResource{}
-
-impl<'r> FromParam<'r> for CheckedResourceLeaf {
- type Error = UnknownResource;
- fn from_param(param: &'r RawStr) -> Result<Self, Self::Error> {
- for &safe in RESOURCES {
- if safe == param.as_str() { return Ok(CheckedResourceLeaf{ safe }) }
- }
- Err(UnknownResource{})
- }
-}
-
-type TestCounter = BufReader<TestCounterInner>;
-#[derive(Debug)]
-struct TestCounterInner { next : usize, }
-impl Read for TestCounterInner {
- fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
- thread::sleep(Duration::from_millis(500));
- let data = format!("data: {}\n\n", self.next);
- self.next += 1;
- buf[0..data.len()].copy_from_slice(data.as_bytes());
- Ok(buf.len())
- }
-}
-
-struct MainRenderContext { };
-
-struct GraspForm {
- a : InstanceAccess,
- pn : usize,
- grasped : bool,
-};
-#[post("/_/api/grasp")]
-fn mainpage(f : GraspForm) -> impl xxx json somehow response::Responder<'static> {
- let mut g = f.a.i.lock();
- let p = g.pieces.
-}
-
-#[post("/<access>")]
-fn mainpage(access : InstanceAccess) -> impl response::Responder<'static> {
- let c = MainRenderContext { };
- Template::render("main",&c)
-}
-
-/*
-
- let tc = TestCounterInner { next : 0 };
- let tc = BufReader::new(tc);
- let ch = response::Stream::chunked(tc, 1);
- let ct = ContentType::parse_flexible("text/event-stream; charset=utf-8").
- unwrap();
- response::content::Content(ct,ch)
-}
-*/
-
-#[get("/_/<leaf>")]
-fn resource(leaf : CheckedResourceLeaf) -> io::Result<NamedFile> {
- let template_dir = "templates"; // xxx
- NamedFile::open(format!("{}/{}", template_dir, leaf.safe))
-}
-
-fn main() {
- testload()?;
-
- let helmet = SpaceHelmet::default()
- .enable(NoSniff::Enable)
- .enable(Frame::Deny)
- .enable(Referrer::NoReferrer);
-
- rocket::ignite()
- .attach(helmet)
- .attach(Template::fairing())
- .mount("/", routes![
- index,
- resource,
- updates,
- ])
- .launch();
-}
+++ /dev/null
-
-struct Disc {
- colours : Vec<Colour>,
- size : Coord,
-}
-
-impl Piece for Disc {
- fn svg(&self, pr : &PiecedRecord) -> SvgData {
- format!(
- r#"<circle cs="{}" cy="{}" r="{}" style="fill: {};"/>"#,
- pr.pos[0], pr.pos[1], swlf.size, self.colour,
- ).into_bytes()
- }
-}
-
-fn xxx_testload_disc() -> Disc { Disc { colours :
-
-}
+++ /dev/null
-
-fn testload() -> E {
- let disc = Disc { size : 10, colours : vec![
- Colour::literal("red"),
- Colour::literal("pink"),
- ] };
- let pr = PieceRecord {
- pos : [40,40],
- p : Rc::new(disc),
- held : None,
- };
- let g = GameState {
- pieces : vec![ pr ],
- players : vec![
- PlayerRecord { nick : "alice".to_owned() },
- PlayerRecord { nick : "bob" .to_owned() },
- ],
- };
- create_instance_access("alice",
-