chiark / gitweb /
finish rework
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 26 Jul 2020 15:08:41 +0000 (16:08 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 26 Jul 2020 15:08:41 +0000 (16:08 +0100)
result of this and previous commit is to break out
PrepareUpdatesBuffer code

src/api.rs
src/gamestate.rs
src/updates.rs

index b99e1eac4924c290f4dd51ae49a379c04870c004..5924513737563ac9056ddfd406752d9e3f751bfd 100644 (file)
@@ -14,11 +14,11 @@ trait ApiPieceOp : Debug {
   #[throws(GameError)]
   fn op(&self, gs: &mut GameState, player: PlayerId, piece: PieceId,
         lens: &dyn Lens /* used for LogEntry and PieceId but not Pos */)
-        -> (PieceUpdateOp<(),()>, Vec<LogEntry>);
+        -> (PieceUpdateOp<()>, Vec<LogEntry>);
 }
 
 pub trait Lens {
-  fn visible_pieceid(&self, piece: PieceId) -> VisiblePieceId;
+  fn pieceid2visible(&self, piece: PieceId) -> VisiblePieceId;
   fn log_pri(&self, piece: PieceId, pc: &PieceState)
              -> PieceRenderInstructions;
   fn svg_pri(&self, piece: PieceId, pc: &PieceState, player: PlayerId)
@@ -29,13 +29,13 @@ pub trait Lens {
 }
 struct TransparentLens { }
 impl Lens for TransparentLens {
-  fn visible_pieceid(&self, piece: PieceId) -> VisiblePieceId {
+  fn pieceid2visible(&self, piece: PieceId) -> VisiblePieceId {
     let kd : slotmap::KeyData = piece.into();
-    VisiblePieceId(kd);
+    VisiblePieceId(kd)
   }
   fn log_pri(&self, piece: PieceId, pc: &PieceState)
              -> PieceRenderInstructions {
-    let id = self.make_piece_visible(piece);
+    let id = self.pieceid2visible(piece);
     PieceRenderInstructions { id, face : pc.face }
   }
   fn svg_pri(&self, piece: PieceId, pc: &PieceState, _player: PlayerId)
@@ -92,8 +92,8 @@ fn api_piece_op<O: ApiPieceOp>(form : Json<ApiPiece<O>>)
       let mut buf = PrepareUpdatesBuffer::new(g, client, form.cseq,
                                               1 + logents.len());
       
-      buf.piece_update(piece, update, &lens);
-      buf.log_updates(logents);
+      buf.piece_update(piece, update, &lens)?;
+      buf.log_updates(logents)?;
 
       eprintln!("API {:?} OK", &form);
     }
@@ -114,7 +114,7 @@ impl ApiPieceOp for ApiPieceGrab {
   #[throws(GameError)]
   fn op(&self, gs: &mut GameState, player: PlayerId, piece: PieceId,
         lens: &dyn Lens)
-        -> (PieceUpdateOp<(),()>, Vec<LogEntry>) {
+        -> (PieceUpdateOp<()>, Vec<LogEntry>) {
     let pl = gs.players.byid(player).unwrap();
     let pc = gs.pieces.byid_mut(piece).unwrap();
 
@@ -146,7 +146,7 @@ impl ApiPieceOp for ApiPieceUngrab {
   #[throws(GameError)]
   fn op(&self, gs: &mut GameState, player: PlayerId, piece: PieceId,
         lens: &dyn Lens)
-        -> (PieceUpdateOp<(),()>, Vec<LogEntry>) {
+        -> (PieceUpdateOp<()>, Vec<LogEntry>) {
     let pl = gs.players.byid(player).unwrap();
     let pc = gs.pieces.byid_mut(piece).unwrap();
 
@@ -179,7 +179,7 @@ impl ApiPieceOp for ApiPieceRaise {
   #[throws(GameError)]
   fn op(&self, gs: &mut GameState, _: PlayerId, piece: PieceId,
         _: &dyn Lens)
-        -> (PieceUpdateOp<(),()>, Vec<LogEntry>) {
+        -> (PieceUpdateOp<()>, Vec<LogEntry>) {
     let pc = gs.pieces.byid_mut(piece).unwrap();
     pc.zlevel = ZLevel { z : self.z, zg : gs.gen };
     let update = PieceUpdateOp::SetZLevel(pc.zlevel);
@@ -198,7 +198,7 @@ impl ApiPieceOp for ApiPieceMove {
   #[throws(GameError)]
   fn op(&self, gs: &mut GameState, _: PlayerId, piece: PieceId,
         _lens: &dyn Lens)
-        -> (PieceUpdateOp<(),()>, Vec<LogEntry>) {
+        -> (PieceUpdateOp<()>, Vec<LogEntry>) {
     let pc = gs.pieces.byid_mut(piece).unwrap();
 
     pc.pos = self.0;
index a3517c4989397130414fae547d310c5c50f5234d..ce6633e3336c2a961f6f3fddca6cd7b08f87deb9 100644 (file)
@@ -163,7 +163,6 @@ impl PieceState {
   pub fn prep_piecestate(&self, pri : &PieceRenderInstructions)
                          -> PreparedPieceState {
     PreparedPieceState {
-      piece      : pri.id,
       pos        : self.pos,
       held       : self.held,
       svg        : self.make_defs(pri)?,
index f17fc7a25a7b8c3fb5ccd0793d10e8fdd1cbd8f5..abcffdfa8d2a635812f65ef90efc4cf2df54fe9c 100644 (file)
@@ -29,14 +29,14 @@ pub enum PreparedUpdateEntry {
   Piece {
     client : ClientId,
     sameclient_cseq : ClientSequence,
-    op : PieceUpdateOp<VisiblePieceId,PreparedPieceState>,
+    piece : VisiblePieceId,
+    op : PieceUpdateOp<PreparedPieceState>,
   },
   Log (Arc<LogEntry>),
 }
 
 #[derive(Debug,Serialize)]
 pub struct PreparedPieceState {
-  pub piece : VisiblePieceId,
   pub pos : Pos,
   pub svg : String,
   pub held : Option<PlayerId>,
@@ -47,12 +47,12 @@ pub struct PreparedPieceState {
 // ---------- piece updates ----------
 
 #[derive(Debug,Serialize)]
-pub enum PieceUpdateOp<ID,NS> {
-  Delete(ID),
+pub enum PieceUpdateOp<NS> {
+  Delete(),
   Insert(NS),
   Modify(NS),
-  Move(ID,Pos),
-  SetZLevel(ID,ZLevel),
+  Move(Pos),
+  SetZLevel(ZLevel),
 }
 
 // ---------- for traansmission ----------
@@ -71,7 +71,8 @@ enum TransmitUpdateEntry<'u> {
     zg : Option<Generation>,
   },
   Piece {
-    op : &'u PieceUpdateOp<VisiblePieceId, PreparedPieceState>,
+    piece : VisiblePieceId,
+    op : &'u PieceUpdateOp<PreparedPieceState>,
   },
   Log (&'u LogEntry),
 }
@@ -110,59 +111,43 @@ impl PreparedUpdateEntry {
 
 // ---------- PieceUpdatesOp ----------
 
-impl<ID,NS> PieceUpdateOp<ID,NS> {
+impl<NS> PieceUpdateOp<NS> {
   pub fn new_state(&self) -> Option<&NS> {
     use PieceUpdateOp::*;
     match self {
-      Delete(_) => None,
+      Delete() => None,
       Insert(ns) => Some(ns),
       Modify(ns) => Some(ns),
-      Move(..) => None,
-      SetZLevel(..) => None,
+      Move(_) => None,
+      SetZLevel(_) => None,
     }
   }
-  pub fn try_map<ID2,NS2, E:Error,
-                 IDF: FnOnce(ID) -> Result<ID2,E>,
-                 NSF: FnOnce(NS) -> Result<NS2,E>>
-    (self, f:NSF, idf:IDF) -> Result<PieceUpdateOp<ID2,NS2>,E>
+  pub fn try_map_new_state<NS2,E:Error, F: FnOnce(NS) -> Result<NS2,E>>
+    (self, f:F) -> Result<PieceUpdateOp<NS2>,E>
   {
     use PieceUpdateOp::*;
     Ok(match self {
-      Delete(i) => Delete(idf(i)?),
+      Delete() => Delete(),
       Insert(ns) => Insert(f(ns)?),
       Modify(ns) => Modify(f(ns)?),
-      Move(i,pos) => Move(idf(i)?,pos),
-      SetZLevel(i,zl) => SetZLevel(idf(i)?,zl),
+      Move(pos) => Move(pos),
+      SetZLevel(zl) => SetZLevel(zl),
     })
   }
-  pub fn map<ID2,NS2,
-             IDF: FnOnce(ID) -> ID2,
-             NSF: FnOnce(NS) -> NS2>
-    (self, nsf:NSF, idf:IDF) -> PieceUpdateOp<ID2,NS2>
-  {
-    #[derive(Error,Debug)] enum Never { }
-    self.try_map(
-      |ns| <Result<_,Never>>::Ok(nsf(ns)),
-      |id| <Result<_,Never>>::Ok(idf(id)),
-    ).unwrap()
+  pub fn map_new_state<NS2,F: FnOnce(NS) -> NS2>(self, f:F)
+                            -> PieceUpdateOp<NS2> {
+    #[derive(Error,Debug)]
+    enum Never { }
+    self.try_map_new_state(|ns| <Result<_,Never>>::Ok(f(ns))).unwrap()
   }
   pub fn new_z_generation(&self) -> Option<Generation> {
     use PieceUpdateOp::*;
     match self {
-      Delete(_) => None,
+      Delete() => None,
       Insert(_) => None,
       Modify(_) => None,
-      Move(..) => None,
-      SetZLevel(_,ZLevel{zg,..}) => Some(*zg),
-    }
-  }
-  pub fn pieceid<'ns>(&'ns self) -> ID where &'ns NS : Into<ID>, ID : Copy {
-    use PieceUpdateOp::*;
-    match self {
-      Delete(i) => *i,
-      Insert(ns) | Modify(ns) => ns.into(),
-      Move(i,_) => *i,
-      SetZLevel(i,_) => *i,
+      Move(_) => None,
+      SetZLevel(ZLevel{zg,..}) => Some(*zg),
     }
   }
 }
@@ -187,12 +172,13 @@ impl<'r> PrepareUpdatesBuffer<'r> {
     }
   }
 
-  pub fn piece_update(&mut self, piece: PieceId, update: PieceUpdateOp<(),()>,
+  #[throws(SVGProcessingError)]
+  pub fn piece_update(&mut self, piece: PieceId, update: PieceUpdateOp<()>,
                       lens: &dyn Lens) {
     let gs = &mut self.g.gs;
 
-    let update = match gs.pieces.byid_mut(piece) {
-      Some(pc) => {
+    let (update, piece) = match gs.pieces.byid_mut(piece) {
+      Ok(pc) => {
         if self.by_client != pc.lastclient {
           pc.gen_before_lastclient = pc.gen;
           pc.lastclient = self.by_client;
@@ -202,31 +188,33 @@ impl<'r> PrepareUpdatesBuffer<'r> {
       
         let pri_for_all = lens.svg_pri(piece,pc,Default::default());
 
-        let update = update.try_map(
+        let update = update.try_map_new_state(
           |_|{
             let mut ns = pc.prep_piecestate(&pri_for_all)?;
             lens.massage_prep_piecestate(&mut ns);
             <Result<_,SVGProcessingError>>::Ok(ns)
           },
-          |_|{
-            <Result<_,SVGProcessingError>>::Ok(pri_for_all.id)
-          },
         )?;
 
-        update
+        (update, pri_for_all.id)
       },
-      None => {
-        PieceUpdateOp::Delete(lens.make_piece_visible(piece))
+      Err(GameError::PieceGone) => {
+        (PieceUpdateOp::Delete(), lens.pieceid2visible(piece))
+      }
+      Err(e) => {
+        panic!(format!("unexpected error {:?} from pices.byid_mut", &e));
       }
     };
 
     self.us.push(PreparedUpdateEntry::Piece {
+      piece,
       client : self.by_client,
       sameclient_cseq : self.cseq,
       op : update,
     });
   }
 
+  #[throws(SVGProcessingError)]
   pub fn log_updates(&mut self, logents: Vec<LogEntry>) {
     for logentry in logents {
       let logentry = Arc::new(logentry);
@@ -238,7 +226,10 @@ impl<'r> PrepareUpdatesBuffer<'r> {
 
 impl<'r> Drop for PrepareUpdatesBuffer<'r> {
   fn drop(&mut self) {
-    let update = PreparedUpdate { gen: self.gen, us: self.us.take(), };
+    let update = PreparedUpdate {
+      gen: self.gen,
+      us: mem::take(&mut self.us),
+    };
     let update = Arc::new(update);
     eprintln!("UPDATE {:?}", &update);