From 0f7dacea15d6e22123c3290c52515a772fc7ee92 Mon Sep 17 00:00:00 2001 From: Kjetil Orbekk Date: Mon, 2 Jan 2023 16:57:00 -0500 Subject: Switch Table trait to use generics --- server/src/table.rs | 41 +++++++++++++++++++++-------------------- server/tests/table_test.rs | 37 ++++++++++++++++++++++--------------- 2 files changed, 43 insertions(+), 35 deletions(-) diff --git a/server/src/table.rs b/server/src/table.rs index 55fa8fb..1dc0fb7 100644 --- a/server/src/table.rs +++ b/server/src/table.rs @@ -20,14 +20,14 @@ pub trait Table { async fn bid( self: Box, bid: Bid, - ) -> Result, BridgeError>; + ) -> Result, BridgeError>; async fn play( self: Box, card: Card, - ) -> Result, BridgeError>; + ) -> Result, BridgeError>; async fn new_deal( self: Box, - ) -> Result, BridgeError>; + ) -> Result, BridgeError>; } pub struct InMemoryTable { @@ -51,7 +51,7 @@ impl Table for InMemoryTable { async fn bid( self: Box, bid: Bid, - ) -> Result, BridgeError> { + ) -> Result, BridgeError> { let game = match self.state { TableState::Game(game) => game, _ => { @@ -65,7 +65,7 @@ impl Table for InMemoryTable { async fn play( self: Box, card: Card, - ) -> Result, BridgeError> { + ) -> Result, BridgeError> { let game = match self.state { TableState::Game(game) => game, _ => { @@ -78,16 +78,16 @@ impl Table for InMemoryTable { async fn new_deal( self: Box, - ) -> Result, BridgeError> { + ) -> Result, BridgeError> { Ok(Box::new(Self { state: GameState::new(random(), random()).into(), })) } } -pub async fn advance_play( - table: Box, -) -> Result, BridgeError> { +pub async fn advance_play( + table: Box, +) -> Result, BridgeError> { let game = match table.state() { TableState::Game(game) => game, _ => return Err(BridgeError::InvalidRequest("no game".to_string())), @@ -115,21 +115,21 @@ pub async fn advance_play( table } -pub struct DbTable { +pub struct DbTable { db: PgPool, id: Uuid, - pub inner: Box, + pub inner: Box, } -impl DbTable { - pub async fn new(db: PgPool, id: Uuid) -> Result { +impl DbTable { + pub async fn new(db: PgPool, id: Uuid, inner: Inner) -> Result { let mut txn = db.begin().await?; if let Some(_) = sqlx::query!("select id from bridge_table where id = $1", id) .fetch_optional(&mut txn) .await? { - return Self::restore(db, txn, id).await; + return Self::restore(db, txn, id, inner).await; } sqlx::query!("insert into bridge_table (id) values($1)", id) @@ -140,7 +140,7 @@ impl DbTable { Ok(Self { db, id, - inner: Box::new(InMemoryTable::new()), + inner: Box::new(inner), }) } @@ -148,18 +148,19 @@ impl DbTable { db: PgPool, txn: Transaction<'_, Postgres>, id: Uuid, + inner: Inner, ) -> Result { txn.rollback().await?; Ok(Self { db, id, - inner: Box::new(InMemoryTable::new()), + inner: Box::new(inner), }) } } #[async_trait] -impl Table for DbTable { +impl Table for DbTable { fn state(&self) -> &TableState { self.inner.state() } @@ -167,7 +168,7 @@ impl Table for DbTable { async fn bid( self: Box, bid: Bid, - ) -> Result, BridgeError> { + ) -> Result, BridgeError> { Ok(Box::new(Self { inner: self.inner.bid(bid).await?, ..*self @@ -177,7 +178,7 @@ impl Table for DbTable { async fn play( self: Box, card: Card, - ) -> Result, BridgeError> { + ) -> Result, BridgeError> { Ok(Box::new(Self { inner: self.inner.play(card).await?, ..*self @@ -186,7 +187,7 @@ impl Table for DbTable { async fn new_deal( self: Box, - ) -> Result, BridgeError> { + ) -> Result, BridgeError> { let inner = self.inner.new_deal().await?; let deal: Deal = random(); diff --git a/server/tests/table_test.rs b/server/tests/table_test.rs index 87547c3..1db7aa8 100644 --- a/server/tests/table_test.rs +++ b/server/tests/table_test.rs @@ -8,9 +8,10 @@ use uuid::Uuid; mod common; -async fn table_basic_test( - mut table: Box, -) -> Result<(), anyhow::Error> { +async fn table_basic_test(mut table: Box) -> Result<(), anyhow::Error> +where + T: Table + Send, +{ assert!(matches!(table.state(), TableState::Unknown)); table = table.new_deal().await?; assert!(matches!(table.state(), TableState::Game(_))); @@ -24,13 +25,14 @@ async fn table_basic_test( Ok(()) } -async fn advance_table( - table: Box, -) -> Result, BridgeError> { +async fn advance_table(table: Box) -> Result, BridgeError> +where + T: Table + Send, +{ match table.state() { TableState::Unknown => panic!("unexpected state"), - TableState::Game(g) => server::table::advance_play(table).await, - TableState::Result(g) => table.new_deal().await, + TableState::Game(_) => server::table::advance_play(table).await, + TableState::Result(_) => table.new_deal().await, } } @@ -47,7 +49,8 @@ async fn in_memory_table() -> Result<(), anyhow::Error> { async fn db_table() -> Result<(), anyhow::Error> { let db = common::TestDb::new().await; table_basic_test(Box::new( - DbTable::new(db.db().clone(), Uuid::new_v4()).await?, + DbTable::new(db.db().clone(), Uuid::new_v4(), InMemoryTable::new()) + .await?, )) .await?; Ok(()) @@ -62,10 +65,12 @@ async fn db_table() -> Result<(), anyhow::Error> { async fn db_table_idempotent() -> Result<(), anyhow::Error> { let db = common::TestDb::new().await; let uuid = Uuid::new_v4(); - let table1: Box = - Box::new(DbTable::new(db.db().clone(), uuid).await?); - let table2: Box = - Box::new(DbTable::new(db.db().clone(), uuid).await?); + let table1 = Box::new( + DbTable::new(db.db().clone(), uuid, InMemoryTable::new()).await?, + ); + let table2 = Box::new( + DbTable::new(db.db().clone(), uuid, InMemoryTable::new()).await?, + ); assert_eq!(table1.state(), table2.state()); Ok(()) } @@ -74,8 +79,10 @@ async fn db_table_idempotent() -> Result<(), anyhow::Error> { #[ignore] async fn db_table_persistence() -> Result<(), anyhow::Error> { let db = common::TestDb::new().await; - let mut table: Box = - Box::new(DbTable::new(db.db().clone(), Uuid::new_v4()).await?); + let mut table = Box::new( + DbTable::new(db.db().clone(), Uuid::new_v4(), InMemoryTable::new()) + .await?, + ); table = table.new_deal().await?; for i in 0..(thread_rng().gen_range(0..200)) { table = advance_table(table).await?; -- cgit v1.2.3