5 Commits

Author SHA1 Message Date
Quaternions 5d5b982bba fix Cargo.lock 2026-06-08 21:18:02 -07:00
Quaternions 987d8bd0f4 Revert "feat(card_game): add Suit::is_black and Rank::value convenience methods"
This reverts commit 2eaa99e82d.

These functions are not necessary.  Remove their usages which are only used in tests and frankenstein code.
2026-06-08 21:17:41 -07:00
funman300 99b49e629e feat(klondike): add optional serde feature for instruction/pile serialization
Adds serde Serialize/Deserialize derives (behind the `serde` feature flag)
to Tableau, Foundation, KlondikePile, SkipCards, TableauStack,
KlondikePileStack, DstFoundation, DstTableau, and KlondikeInstruction.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 11:20:39 -07:00
funman300 2eaa99e82d feat(card_game): add Suit::is_black and Rank::value convenience methods 2026-06-08 10:55:05 -07:00
funman300 0cdfa5446a feat(card_game): add optional serde feature for Deck, Suit, Rank, Card
Adds a `serde` Cargo feature that gates #[derive(Serialize, Deserialize)]
on the four primitive types: Deck, Suit, Rank, and Card.

- Deck / Suit / Rank: plain enum derives — serialize as variant name strings
- Card: newtype over NonZeroU8 with #[serde(transparent)], serializes as
  the raw packed byte (deck<<6 | suit<<4 | rank)

Without the feature the crate remains no_std-compatible and pulls no
additional dependencies. With it, serde 1.x (derive only, no std) is
added as an optional dep.

Downstream consumers enable with:
  card_game = { ..., features = ["serde"] }
2026-06-08 10:49:53 -07:00
5 changed files with 25 additions and 0 deletions
Generated
+3
View File
@@ -25,6 +25,7 @@ name = "card_game"
version = "0.4.0" version = "0.4.0"
dependencies = [ dependencies = [
"arrayvec", "arrayvec",
"serde",
] ]
[[package]] [[package]]
@@ -130,6 +131,7 @@ version = "0.3.0"
dependencies = [ dependencies = [
"card_game", "card_game",
"rand", "rand",
"serde",
] ]
[[package]] [[package]]
@@ -238,6 +240,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
dependencies = [ dependencies = [
"serde_core", "serde_core",
"serde_derive",
] ]
[[package]] [[package]]
+4
View File
@@ -8,8 +8,12 @@ description = "Card game library."
authors = ["Rhys Lloyd <krakow20@gmail.com>"] authors = ["Rhys Lloyd <krakow20@gmail.com>"]
keywords = ["card", "cards", "solitaire", "klondike"] keywords = ["card", "cards", "solitaire", "klondike"]
[features]
serde = ["dep:serde"]
[dependencies] [dependencies]
arrayvec = { version = "0.7.6", registry = "Quaternions", features = ["len_u8"], default-features = false } arrayvec = { version = "0.7.6", registry = "Quaternions", features = ["len_u8"], default-features = false }
serde = { version = "1", optional = true, default-features = false, features = ["derive"] }
[lints] [lints]
workspace = true workspace = true
+5
View File
@@ -28,6 +28,7 @@ pub trait Game: Clone {
/// card_game supports up to 4 identifiably separate decks. /// card_game supports up to 4 identifiably separate decks.
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Deck { pub enum Deck {
Deck1 = 0b00, Deck1 = 0b00,
Deck2 = 0b01, Deck2 = 0b01,
@@ -48,6 +49,7 @@ impl Deck {
} }
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Suit { pub enum Suit {
Spades = 0b00, Spades = 0b00,
Hearts = 0b01, Hearts = 0b01,
@@ -77,6 +79,7 @@ impl Suit {
} }
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Rank { pub enum Rank {
Ace = 1, Ace = 1,
Two = 2, Two = 2,
@@ -146,6 +149,8 @@ impl Rank {
/// 2 bits for suit ID /// 2 bits for suit ID
/// 4 bits for card Value /// 4 bits for card Value
#[derive(Clone, Debug, Eq, Hash, PartialEq)] #[derive(Clone, Debug, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(transparent))]
pub struct Card(core::num::NonZeroU8); pub struct Card(core::num::NonZeroU8);
impl Card { impl Card {
pub const fn new(deck: Deck, suit: Suit, rank: Rank) -> Self { pub const fn new(deck: Deck, suit: Suit, rank: Rank) -> Self {
+4
View File
@@ -3,9 +3,13 @@ name = "klondike"
version = "0.3.0" version = "0.3.0"
edition = "2024" edition = "2024"
[features]
serde = ["dep:serde"]
[dependencies] [dependencies]
card_game.workspace = true card_game.workspace = true
rand = { version = "0.10.1", default-features = false, features = ["std_rng"] } rand = { version = "0.10.1", default-features = false, features = ["std_rng"] }
serde = { version = "1", optional = true, default-features = false, features = ["derive"] }
[lints] [lints]
workspace = true workspace = true
+9
View File
@@ -121,6 +121,7 @@ impl KlondikeStats {
} }
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Tableau { pub enum Tableau {
Tableau1, Tableau1,
Tableau2, Tableau2,
@@ -147,6 +148,7 @@ impl Tableau {
} }
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Foundation { pub enum Foundation {
Foundation1, Foundation1,
Foundation2, Foundation2,
@@ -167,6 +169,7 @@ impl Foundation {
} }
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum KlondikePile { pub enum KlondikePile {
Tableau(Tableau), Tableau(Tableau),
Stock, Stock,
@@ -200,6 +203,7 @@ impl From<Foundation> for KlondikePile {
} }
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum SkipCards { pub enum SkipCards {
Skip0, Skip0,
Skip1, Skip1,
@@ -238,6 +242,7 @@ impl SkipCards {
} }
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct TableauStack { pub struct TableauStack {
pub tableau: Tableau, pub tableau: Tableau,
pub skip_cards: SkipCards, pub skip_cards: SkipCards,
@@ -271,6 +276,7 @@ impl TableauStack {
} }
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum KlondikePileStack { pub enum KlondikePileStack {
Tableau(TableauStack), Tableau(TableauStack),
Stock, Stock,
@@ -294,6 +300,7 @@ impl KlondikePileStack {
} }
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct DstFoundation { pub struct DstFoundation {
pub src: KlondikePile, pub src: KlondikePile,
pub foundation: Foundation, pub foundation: Foundation,
@@ -317,6 +324,7 @@ impl DstFoundation {
} }
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct DstTableau { pub struct DstTableau {
pub src: KlondikePileStack, pub src: KlondikePileStack,
pub tableau: Tableau, pub tableau: Tableau,
@@ -340,6 +348,7 @@ impl DstTableau {
} }
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum KlondikeInstruction { pub enum KlondikeInstruction {
DstFoundation(DstFoundation), DstFoundation(DstFoundation),
DstTableau(DstTableau), DstTableau(DstTableau),