@@ -8,93 +8,151 @@ pub struct GeneratorParam {
88 /// Parameter type.
99 pub ty : GeneratorParamType ,
1010 /// Default value.
11- pub default : GeneratorParamValue ,
11+ pub default : CatalogIdValue ,
1212}
1313
1414impl GeneratorParam {
15- /// Converts a string to a value for this parameter and returns an error if
16- /// it is invalid.
17- pub fn value_from_arg (
15+ /// Converts a catalog ID value into a typed value for this parameter, or
16+ /// returns an error if it is invalid.
17+ pub fn typed_value (
1818 & self ,
19- arg : & CatalogArgValue ,
20- ) -> Result < GeneratorParamValue , GeneratorParamError > {
21- let make_error = || GeneratorParamError {
22- expected : self . clone ( ) ,
23- got : arg. to_string ( ) ,
24- } ;
25-
26- match self . ty {
27- GeneratorParamType :: Int { .. } => Ok ( GeneratorParamValue :: Int (
28- arg. to_int ( ) . ok_or_else ( make_error) ?,
29- ) ) ,
30- GeneratorParamType :: Puzzle => Ok ( GeneratorParamValue :: PuzzleId ( arg. to_id ( ) ) ) ,
19+ arg : CatalogIdValue ,
20+ ) -> Result < TypedCatalogIdValue , GeneratorParamError > {
21+ match & self . ty {
22+ GeneratorParamType :: Bool => arg. to_bool ( ) . map ( TypedCatalogIdValue :: Bool ) ,
23+ GeneratorParamType :: Int { .. } => arg. to_int ( ) . map ( TypedCatalogIdValue :: Int ) ,
24+ GeneratorParamType :: Puzzle { .. } => arg. into_id ( ) . map ( TypedCatalogIdValue :: Id ) ,
25+ GeneratorParamType :: List ( inner) => arg
26+ . into_list ( )
27+ . and_then ( |l| l. into_iter ( ) . map ( |e| inner. typed_value ( & e) ) . try_collect ( ) )
28+ . map ( TypedCatalogIdValue :: List ) ,
3129 }
30+ . map_err ( |inner| GeneratorParamError {
31+ param : self . clone ( ) ,
32+ inner,
33+ } )
3234 }
3335}
36+
3437/// Type of a parameter for a puzzle generator.
3538#[ derive( Debug , Clone , PartialEq ) ]
3639pub enum GeneratorParamType {
40+ /// Boolean.
41+ Bool ,
3742 /// Integer.
3843 Int {
3944 /// Minimum value (inclusive).
4045 min : i64 ,
4146 /// Maximum value (inclusive).
4247 max : i64 ,
4348 } ,
44- /// Puzzle ID.
45- Puzzle ,
49+ /// Puzzle ID with a menu name.
50+ Puzzle {
51+ /// Puzzle menu ID.
52+ menu : String ,
53+ } ,
54+ /// List of parameters.
55+ ///
56+ /// This must be the last parameter.
57+ List ( Box < GeneratorParamType > ) ,
4658}
4759
4860impl fmt:: Display for GeneratorParamType {
4961 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
5062 match self {
51- GeneratorParamType :: Int { min, max } => write ! ( f, "int ({min} to {max})" ) ,
52- GeneratorParamType :: Puzzle => write ! ( f, "puzzle" ) ,
63+ GeneratorParamType :: Bool => write ! ( f, "true or false" ) ,
64+ GeneratorParamType :: Int { min, max } => write ! ( f, "integer ({min} to {max})" ) ,
65+ GeneratorParamType :: Puzzle { menu } => write ! ( f, "puzzle from {menu:?} menu" ) ,
66+ GeneratorParamType :: List ( inner) => write ! ( f, "list of {inner}" ) ,
67+ }
68+ }
69+ }
70+
71+ impl GeneratorParamType {
72+ /// Converts a catalog ID value into a typed value for this parameter, or
73+ /// returns an error if it is invalid.
74+ pub fn typed_value ( & self , arg : & CatalogIdValue ) -> Result < TypedCatalogIdValue , CatalogIdError > {
75+ match self {
76+ GeneratorParamType :: Bool => arg. to_bool ( ) . map ( TypedCatalogIdValue :: Bool ) ,
77+ GeneratorParamType :: Int { .. } => arg. to_int ( ) . map ( TypedCatalogIdValue :: Int ) ,
78+ GeneratorParamType :: Puzzle { .. } => arg. clone ( ) . into_id ( ) . map ( TypedCatalogIdValue :: Id ) ,
79+ GeneratorParamType :: List ( inner) => arg
80+ . clone ( )
81+ . into_list ( )
82+ . and_then ( |l| l. into_iter ( ) . map ( |e| inner. typed_value ( & e) ) . try_collect ( ) )
83+ . map ( TypedCatalogIdValue :: List ) ,
5384 }
5485 }
5586}
5687
5788/// Value of a parameter for a puzzle generator.
5889#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
59- pub enum GeneratorParamValue {
90+ pub enum TypedCatalogIdValue {
91+ /// Catalog ID.
92+ Id ( CatalogId ) ,
93+ /// Boolean.
94+ Bool ( bool ) ,
6095 /// Integer.
6196 Int ( i64 ) ,
62- /// Puzzle ID .
63- PuzzleId ( CatalogId ) ,
97+ /// List of values .
98+ List ( Vec < TypedCatalogIdValue > ) ,
6499}
65100
66- impl fmt:: Display for GeneratorParamValue {
101+ impl fmt:: Display for TypedCatalogIdValue {
67102 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
68103 match self {
69- GeneratorParamValue :: Int ( i) => write ! ( f, "{i}" ) ,
70- GeneratorParamValue :: PuzzleId ( id) => write ! ( f, "{id}" ) ,
104+ TypedCatalogIdValue :: Id ( id) => write ! ( f, "{id}" ) ,
105+ TypedCatalogIdValue :: Bool ( b) => write ! ( f, "{b}" ) ,
106+ TypedCatalogIdValue :: Int ( i) => write ! ( f, "{i}" ) ,
107+ TypedCatalogIdValue :: List ( l) => {
108+ write ! ( f, "[" ) ?;
109+ let mut is_first = true ;
110+ for elem in l {
111+ if !std:: mem:: take ( & mut is_first) {
112+ write ! ( f, "," ) ?;
113+ }
114+ write ! ( f, "{elem}" ) ?;
115+ }
116+ write ! ( f, "]" ) ?;
117+ Ok ( ( ) )
118+ }
71119 }
72120 }
73121}
74122
75- impl From < GeneratorParamValue > for CatalogArgValue {
76- fn from ( value : GeneratorParamValue ) -> Self {
77- match value {
78- GeneratorParamValue :: Int ( i) => i. into ( ) ,
79- GeneratorParamValue :: PuzzleId ( id) => id. into ( ) ,
123+ impl From < TypedCatalogIdValue > for CatalogIdValue {
124+ fn from ( value : TypedCatalogIdValue ) -> Self {
125+ value. into_untyped ( )
126+ }
127+ }
128+
129+ impl TypedCatalogIdValue {
130+ /// Converts a [`TypedCatalogIdValue`] to a [`CatalogIdValue`], which loses
131+ /// the type information.
132+ pub fn into_untyped ( self ) -> CatalogIdValue {
133+ match self {
134+ Self :: Id ( id) => id. into ( ) ,
135+ Self :: Bool ( b) => b. into ( ) ,
136+ Self :: Int ( i) => i. into ( ) ,
137+ Self :: List ( l) => l. into_iter ( ) . map ( |e| e. into ( ) ) . collect_vec ( ) . into ( ) ,
80138 }
81139 }
82140}
83141
84142/// Error encountered when parsing a generator parameter.
85- #[ derive( Debug , Clone ) ]
143+ #[ derive( Debug ) ]
86144pub struct GeneratorParamError {
87145 /// Parameter requirements.
88- pub expected : GeneratorParam ,
89- /// Value supplied .
90- pub got : String ,
146+ pub param : GeneratorParam ,
147+ /// Underlying error .
148+ pub inner : CatalogIdError ,
91149}
92150
93151impl fmt:: Display for GeneratorParamError {
94152 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
95- let Self { expected , got } = self ;
96- let GeneratorParam { name, ty, .. } = expected ;
97- write ! ( f, "bad value {got:?} for param {name:?} (expected {ty})" )
153+ let Self { param , inner } = self ;
154+ let GeneratorParam { name, ty, .. } = param ;
155+ write ! ( f, "bad value for param {name:?} (expected {ty}): {inner} " )
98156 }
99157}
100158
0 commit comments