chiark / gitweb /
hidden prep: Reorganise PieceUpdateFromOp
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 30 Jan 2021 12:11:33 +0000 (12:11 +0000)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 31 Jan 2021 18:38:28 +0000 (18:38 +0000)
We are going to want to allow an op to give different answers to
different clients.  The representation from an op is going to be
either basically what we have now, or a version where the
PieceUpdateOp is different for each player.

Prepare for this with some struct and type shuffling.  We laave a
convenience Into impl to allow ops to easily handle the simple case.

No functional change.

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
daemon/api.rs
daemon/cmdlistener.rs
src/global.rs
src/imports.rs
src/updates.rs

index 9fa897567b25021ecf08e4ae81467d219654931f..976d5dc75abf56ea86a1be9b5b110561aa9d3d0f 100644 (file)
@@ -45,7 +45,7 @@ struct ApiPieceOpArgs<'a> {
 
 trait ApiPieceOp : Debug {
   #[throws(ApiPieceOpError)]
-  fn op(&self, a: ApiPieceOpArgs) -> PieceUpdateFromOp;
+  fn op(&self, a: ApiPieceOpArgs) -> PieceUpdate;
 
   #[throws(OnlineError)]
   fn check_held(&self, pc: &PieceState, player: PlayerId) {
@@ -133,13 +133,13 @@ fn api_piece_op<O: ApiPieceOp>(form : Json<ApiPiece<O>>)
 
     if u_gen > q_gen { throw!(PieceOpError::Conflict) }
     form.op.check_held(pc,player)?;
-    let (wrc, update, logents) =
+    let update =
       form.op.op(ApiPieceOpArgs {
         gs, player, piece,
         p: p.as_ref(),
         lens: &lens,
       })?;
-    Ok::<_,ApiPieceOpError>((wrc, update, logents))
+    Ok::<_,ApiPieceOpError>(update)
   })() {
     Err(ReportViaUpdate(poe)) => {
       PrepareUpdatesBuffer::piece_report_error(
@@ -159,13 +159,13 @@ fn api_piece_op<O: ApiPieceOp>(form : Json<ApiPiece<O>>)
       warn!("api_piece_op ERROR {:?}: {:?}", &form, &err);
       Err(err)?;
     },
-    Ok((wrc, update, logents)) => {
+    Ok(PieceUpdate { wrc, log, ops }) => {
       let mut buf = PrepareUpdatesBuffer::new(g,
                                               Some((wrc, client, form.cseq)),
-                                              Some(1 + logents.len()));
+                                              Some(1 + log.len()));
       
-      buf.piece_update(piece, update, &lens);
-      buf.log_updates(logents);
+      buf.piece_update(piece, ops, &lens);
+      buf.log_updates(log);
 
       debug!("api_piece_op OK: {:?}", &form);
     }
@@ -221,7 +221,7 @@ api_route!{
   struct ApiPieceGrab {
   }
   #[throws(ApiPieceOpError)]
-  fn op(&self, a: ApiPieceOpArgs) -> PieceUpdateFromOp {
+  fn op(&self, a: ApiPieceOpArgs) -> PieceUpdate {
     let ApiPieceOpArgs { gs,player,piece,p,lens, .. } = a;
     let gpl = gs.players.byid(player)?;
     let pc = gs.pieces.byid_mut(piece)?;
@@ -233,7 +233,7 @@ api_route!{
     let logents = log_did_to_piece(gpl, lens, piece, pc, p, "grasped");
 
     (WhatResponseToClientOp::Predictable,
-     update, logents)
+     update, logents).into()
   }
 }
 
@@ -245,7 +245,7 @@ api_route!{
   fn check_held(&self, _pc: &PieceState, _player: PlayerId) { }
 
   #[throws(ApiPieceOpError)]
-  fn op(&self, a: ApiPieceOpArgs) -> PieceUpdateFromOp {
+  fn op(&self, a: ApiPieceOpArgs) -> PieceUpdate {
     let ApiPieceOpArgs { gs,player,piece,p,lens, .. } = a;
     let gpl = gs.players.byid(player)?;
     let pc = gs.pieces.byid_mut(piece)?;
@@ -266,7 +266,7 @@ api_route!{
     })};
 
     (WhatResponseToClientOp::Predictable,
-     update, vec![logent])
+     update, vec![logent]).into()
   }
 }
 
@@ -275,7 +275,7 @@ api_route!{
   struct ApiPieceUngrab {
   }
   #[throws(ApiPieceOpError)]
-  fn op(&self, a: ApiPieceOpArgs) -> PieceUpdateFromOp {
+  fn op(&self, a: ApiPieceOpArgs) -> PieceUpdate {
     let ApiPieceOpArgs { gs,player,piece,p,lens, .. } = a;
     let gpl = gs.players.byid(player).unwrap();
     let pc = gs.pieces.byid_mut(piece).unwrap();
@@ -287,7 +287,7 @@ api_route!{
     let logents = log_did_to_piece(gpl, lens, piece, pc, p, "released");
 
     (WhatResponseToClientOp::Predictable,
-     update, logents)
+     update, logents).into()
   }
 }
 
@@ -297,13 +297,13 @@ api_route!{
     z : ZCoord,
   }
   #[throws(ApiPieceOpError)]
-  fn op(&self, a: ApiPieceOpArgs) -> PieceUpdateFromOp {
+  fn op(&self, a: ApiPieceOpArgs) -> PieceUpdate {
     let ApiPieceOpArgs { gs,piece, .. } = a;
     let pc = gs.pieces.byid_mut(piece).unwrap();
     pc.zlevel = ZLevel { z : self.z.clone(), zg : gs.gen };
     let update = PieceUpdateOp::SetZLevel(());
     (WhatResponseToClientOp::Predictable,
-     update, vec![])
+     update, vec![]).into()
   }
 }
 
@@ -312,7 +312,7 @@ api_route!{
   struct ApiPieceMove(Pos);
 
   #[throws(ApiPieceOpError)]
-  fn op(&self, a: ApiPieceOpArgs) -> PieceUpdateFromOp {
+  fn op(&self, a: ApiPieceOpArgs) -> PieceUpdate {
     let ApiPieceOpArgs { gs,piece, .. } = a;
     let pc = gs.pieces.byid_mut(piece).unwrap();
     let (pos, clamped) = self.0.clamped(gs.table_size);
@@ -326,7 +326,7 @@ api_route!{
     }
     let update = PieceUpdateOp::Move(self.0);
     (WhatResponseToClientOp::Predictable,
-     update, logents)
+     update, logents).into()
   }
 }
 
@@ -335,7 +335,7 @@ api_route!{
   struct ApiPieceRotate(CompassAngle);
 
   #[throws(ApiPieceOpError)]
-  fn op(&self, a: ApiPieceOpArgs) -> PieceUpdateFromOp {
+  fn op(&self, a: ApiPieceOpArgs) -> PieceUpdate {
     let ApiPieceOpArgs { gs,player,piece,p,lens, .. } = a;
     let pc = gs.pieces.byid_mut(piece).unwrap();
     let gpl = gs.players.byid(player).unwrap();
@@ -343,7 +343,7 @@ api_route!{
     let logents = log_did_to_piece(gpl, lens, piece, pc, p, "rotated");
     let update = PieceUpdateOp::Modify(());
     (WhatResponseToClientOp::Predictable,
-     update, logents)
+     update, logents).into()
   }
 }
 
@@ -352,7 +352,7 @@ api_route!{
   struct ApiPiecePin (bool);
 
   #[throws(ApiPieceOpError)]
-  fn op(&self, a: ApiPieceOpArgs) -> PieceUpdateFromOp {
+  fn op(&self, a: ApiPieceOpArgs) -> PieceUpdate {
     let ApiPieceOpArgs { gs,player,piece,p,lens, .. } = a;
     let pc = gs.pieces.byid_mut(piece).unwrap();
     let gpl = gs.players.byid(player).unwrap();
@@ -363,7 +363,7 @@ api_route!{
       if pc.pinned { "pinned" } else { "unpinned" },
     );
     (WhatResponseToClientOp::Predictable,
-     update, logents)
+     update, logents).into()
   }
 }
 
@@ -376,7 +376,7 @@ api_route!{
     wrc: WhatResponseToClientOp,
   }
   #[throws(ApiPieceOpError)]
-  fn op(&self, a: ApiPieceOpArgs) -> PieceUpdateFromOp {
+  fn op(&self, a: ApiPieceOpArgs) -> PieceUpdate {
     let ApiPieceOpArgs { gs,player,piece,p,lens, .. } = a;
     '_normal_global_ops__not_loop: loop {
       let pc = gs.pieces.byid_mut(piece)?;
@@ -390,7 +390,7 @@ api_route!{
             wrc,
             PieceUpdateOp::Modify(()),
             log_did_to_piece(gpl, lens, piece, pc, p, "flipped"),
-          )
+          ).into()
         },
 
         _ => break,
index 82339ad66cc9d2df94b420f14ab7ef5f1d68fd96..2890dd2464e05a6b8d47b03a3ff814958213969e 100644 (file)
@@ -820,7 +820,7 @@ impl UpdateHandler {
         let mut buf = PrepareUpdatesBuffer::new(g, None, Some(estimate));
         for (upiece, uuop) in updates.pcs {
           let lens = TransparentLens { };
-          buf.piece_update(upiece, uuop, &lens);
+          buf.piece_update(upiece, PUO::Simple(uuop), &lens);
         }
         buf.log_updates(updates.log);
         buf.raw_updates(raw);
@@ -836,7 +836,7 @@ impl UpdateHandler {
         let mut buf = PrepareUpdatesBuffer::new(g, None, None);
         for (upiece, uuop) in bulk.pieces {
           let lens = TransparentLens { };
-          buf.piece_update(upiece, uuop, &lens);
+          buf.piece_update(upiece, PUO::Simple(uuop), &lens);
         }
 
         if bulk.logs {
index 9f9518904cb5f39bb36a510f18fc2c78246f4b62..3ee067f358dfc35505ee88cbdd7006ace1352396 100644 (file)
@@ -699,7 +699,7 @@ impl<'ig> InstanceGuard<'ig> {
       let estimate = updated_pieces.len() + 1;
       let mut buf = PrepareUpdatesBuffer::new(self, None , Some(estimate));
       for &piece in &updated_pieces {
-        buf.piece_update(piece, PieceUpdateOp::Modify(()), &lens);
+        buf.piece_update(piece, PieceUpdateOp::Modify(()).into(), &lens);
       }
       buf.finish();
 
index 72af04110d437eea78793f0ae9ae5705069e9e7a..b79258fdf97fca05b94a8d14f84de5031bcebaba 100644 (file)
@@ -118,3 +118,6 @@ display_as_debug!(Impossible);
 pub type AE = anyhow::Error;
 pub type OE = OnlineError;
 pub type POEPP = PieceOpErrorPartiallyProcessed;
+
+// updates.rs
+pub type PUO = PieceUpdateOps;
index 5ff170012df1dcd4c6a953ae86235b400155ab9d..fd60c67578ec157aa288645608a610ee6148dc2b 100644 (file)
@@ -100,9 +100,34 @@ pub enum PieceUpdateOp<NS,ZL> {
   SetZLevel(ZL),
 }
 
-pub type PieceUpdateFromOp = (WhatResponseToClientOp,
-                              PieceUpdateOp<(),()>, Vec<LogEntry>);
-pub type PieceUpdateResult = Result<PieceUpdateFromOp, ApiPieceOpError>;
+pub type PieceUpdateFromOpSimple = (
+  WhatResponseToClientOp,
+  PieceUpdateOp<(),()>,
+  Vec<LogEntry>,
+);
+pub type PieceUpdateResult = Result<PieceUpdate, ApiPieceOpError>;
+
+#[derive(Debug)]
+pub struct PieceUpdate {
+  pub wrc: WhatResponseToClientOp,
+  pub log: Vec<LogEntry>,
+  pub ops: PieceUpdateOps,
+}
+
+#[derive(Debug)]
+pub enum PieceUpdateOps {
+  Simple(PieceUpdateOp<(),()>),
+}
+
+impl From<PieceUpdateOp<(),()>> for PieceUpdateOps {
+  fn from(op: PieceUpdateOp<(),()>) -> Self { PUO::Simple(op) }
+}
+
+impl From<PieceUpdateFromOpSimple> for PieceUpdate {
+  fn from((wrc, op, log): PieceUpdateFromOpSimple) -> Self {
+    PieceUpdate { wrc, log, ops: op.into() }
+  }
+}
 
 // ---------- for traansmission ----------
 
@@ -462,11 +487,13 @@ impl<'r> PrepareUpdatesBuffer<'r> {
     }
   }
 
-  pub fn piece_update(&mut self, piece: PieceId, update: PieceUpdateOp<(),()>,
+  pub fn piece_update(&mut self, piece: PieceId, ops: PieceUpdateOps,
                       lens: &dyn Lens) {
     // Caller needs us to be infallible since it is too late by
     // this point to back out a game state change.
 
+    let PUO::Simple(update) = ops;
+
     let update = self.piece_update_fallible(
       piece, update, lens,
       |pc, gen, by_client|