2023-01-26 15:04:39 +01:00
use serde ::{ de ::Visitor , Deserialize , Deserializer } ;
2022-11-11 15:00:07 +01:00
fn main ( ) -> Result < ( ) , Box < dyn std ::error ::Error > > {
2023-01-26 15:04:39 +01:00
let cards : CardInfo =
serde_json ::from_reader ( std ::io ::BufReader ::new ( std ::fs ::File ::open ( " cards.json " ) ? ) ) ? ;
println! ( " {} cards read " , cards . data . len ( ) ) ;
2022-11-11 15:00:07 +01:00
Ok ( ( ) )
2022-10-05 17:57:01 +02:00
}
2023-01-26 15:04:39 +01:00
#[ derive(Debug, Deserialize, PartialEq, Eq, Clone) ]
struct CardInfo {
data : Vec < Card > ,
2022-10-05 17:57:01 +02:00
}
2023-01-26 15:04:39 +01:00
#[ derive(Debug, Deserialize, PartialEq, Eq, Clone) ]
struct CardBase {
//#[serde(rename = "type", deserialize_with = "split_types")]
//card_type: Vec<String>,
name : String ,
#[ serde(rename = " desc " ) ]
text : String ,
}
fn split_types < ' de , D : Deserializer < ' de > > ( deserializer : D ) -> Result < Vec < String > , D ::Error > {
struct SplittingVisitor ;
impl < ' de > Visitor < ' de > for SplittingVisitor {
type Value = Vec < String > ;
fn expecting ( & self , formatter : & mut std ::fmt ::Formatter ) -> std ::fmt ::Result {
formatter . write_str ( " a string " )
}
fn visit_str < E : serde ::de ::Error > ( self , v : & str ) -> Result < Self ::Value , E > {
Ok ( v . split_whitespace ( )
. filter ( | t | t ! = & " Card " )
. map ( str ::to_owned )
. collect ( ) )
}
}
deserializer . deserialize_any ( SplittingVisitor )
}
#[ derive(Debug, Deserialize, PartialEq, Eq, Clone) ]
struct Monster {
// None for ?
atk : Option < i32 > ,
attribute : String ,
#[ serde(rename = " race " ) ]
r#type : String ,
// None for ? or link monsters
def : Option < i32 > ,
// also includes rank
level : Option < u8 > ,
2022-10-05 17:57:01 +02:00
}
2022-11-11 15:00:07 +01:00
#[ derive(Debug, Deserialize, PartialEq, Eq, Clone) ]
2022-10-05 17:57:01 +02:00
#[ serde(tag = " type " ) ]
enum Card {
2023-01-26 15:04:39 +01:00
#[ serde(alias = " Spell Card " , alias = " Trap Card " ) ]
Backrow {
#[ serde(flatten) ]
base : CardBase ,
} ,
#[ serde(rename = " Skill Card " ) ]
Skill {
#[ serde(flatten) ]
base : CardBase ,
2022-10-05 17:57:01 +02:00
} ,
#[ serde(
2023-01-26 15:04:39 +01:00
alias = " Effect Monster " ,
2022-10-05 17:57:01 +02:00
alias = " Flip Effect Monster " ,
2023-01-26 15:04:39 +01:00
alias = " Fusion Monster " ,
alias = " Gemini Monster " ,
alias = " Link Monster " ,
alias = " Normal Monster " ,
alias = " Normal Tuner Monster " ,
alias = " Pendulum Effect Fusion Monster " ,
alias = " Pendulum Effect Monster " ,
alias = " Pendulum Effect Ritual Monster " ,
alias = " Pendulum Flip Effect Monster " ,
alias = " Pendulum Normal Monster " ,
alias = " Pendulum Tuner Effect Monster " ,
alias = " Ritual Effect Monster " ,
alias = " Ritual Monster " ,
alias = " Spirit Monster " ,
alias = " Synchro Monster " ,
alias = " Synchro Pendulum Effect Monster " ,
alias = " Synchro Tuner Monster " ,
alias = " Token " ,
alias = " Toon Monster " ,
alias = " Tuner Monster " ,
alias = " Union Effect Monster " ,
alias = " XYZ Monster " ,
alias = " XYZ Pendulum Effect Monster "
2022-10-05 17:57:01 +02:00
) ]
2023-01-26 15:04:39 +01:00
Monster {
#[ serde(flatten) ]
base : CardBase ,
#[ serde(flatten) ]
monster : Monster ,
#[ serde(default, rename = " linkval " ) ]
link_rating : u8 ,
#[ serde(default) ]
linkmarkers : Vec < String > ,
2022-10-05 17:57:01 +02:00
} ,
}
2023-01-26 15:04:39 +01:00
#[ cfg(test) ]
mod tests {
use super ::* ;
2022-10-05 17:57:01 +02:00
2023-01-26 15:04:39 +01:00
#[ test ]
fn test_spell ( ) {
let s = r #"
{
" id " : 41142615 ,
" name " : " The Cheerful Coffin " ,
" type " : " Spell Card " ,
" desc " : " Discard up to 3 Monster Cards from your hand to the Graveyard. " ,
" race " : " Normal "
} " #;
let coffin : Card = serde_json ::from_str ( s ) . unwrap ( ) ;
assert_eq! (
coffin ,
Card ::Backrow {
base : CardBase {
card_type : vec ! [ " Spell " . to_owned ( ) ] ,
name : " The Cheerful Coffin " . to_owned ( ) ,
text : " Discard up to 3 Monster Cards from your hand to the Graveyard. "
. to_owned ( )
}
}
)
}
#[ test ]
fn test_monster ( ) {
let s = r #"
{
" id " : 2326738 ,
" name " : " Des Lacooda " ,
" type " : " Effect Monster " ,
" desc " : " Once per turn: You can change this card to face-down Defense Position. When this card is Flip Summoned: Draw 1 card. " ,
" atk " : 500 ,
" def " : 600 ,
" level " : 3 ,
" race " : " Zombie " ,
" attribute " : " EARTH "
} " #;
let munch : Card = serde_json ::from_str ( s ) . unwrap ( ) ;
assert_eq! (
munch ,
Card ::Monster {
base : CardBase {
card_type : vec ! [ " Effect " . to_owned ( ) , " Monster " . to_owned ( ) ] ,
name : " Des Lacooda " . to_owned ( ) ,
text : " Once per turn: You can change this card to face-down Defense Position. When this card is Flip Summoned: Draw 1 card. " . to_owned ( ) ,
} ,
monster : Monster {
atk : Some ( 500 ) ,
def : Some ( 600 ) ,
level : Some ( 3 ) ,
r#type : " Zombie " . to_owned ( ) ,
attribute : " EARTH " . to_owned ( ) ,
} ,
link_rating : 0 ,
linkmarkers : vec ! [ ]
} ,
)
}
2022-10-05 17:57:01 +02:00
}