1
+ extern crate hashbrown;
2
+
1
3
use crate :: prelude_std:: * ;
2
4
use crate :: num:: * ;
3
- use crate :: rc:: { RcStr , Counter } ;
5
+ use crate :: rc:: { RcStr , Counter , AtomicCounter } ;
6
+ use hashbrown:: HashSet ;
4
7
5
- pub mod store;
8
+ struct JewelStore < C : Counter = AtomicCounter > {
9
+ modifiers : HashSet < Modifier < C > > ,
10
+ jewels : Vec < Jewel < C > >
11
+ }
6
12
7
- struct Modifier < N : Name = String > {
8
- name : N ,
9
- ty : ModifierType ,
10
- value : ModifierValue
13
+ struct Jewel < C : Counter = AtomicCounter > {
14
+ level : u16 ,
15
+ size : i16 ,
16
+ modifiers : JewelModifiers < C >
11
17
}
12
18
13
- pub trait Name {
14
- fn as_str ( & self ) -> & str ;
19
+ enum JewelModifiers < C : Counter = AtomicCounter > {
20
+ Chipped ( [ ModifierInstance < C > ; 1 ] ) ,
21
+ Flawed ( [ ModifierInstance < C > ; 2 ] ) ,
22
+ Flawless ( [ ModifierInstance < C > ; 3 ] ) ,
23
+ Perfect ( [ ModifierInstance < C > ; 4 ] )
15
24
}
16
25
17
- macro_rules! impl_name_via_deref {
18
- { [ $( $generics: tt) * ] $( $stuff: tt) + } => {
19
- impl <$( $generics) * > Name for $( $stuff) + {
20
- #[ inline]
21
- fn as_str( & self ) -> & str { self }
22
- }
23
- }
26
+ struct ModifierInstance < C : Counter = AtomicCounter > {
27
+ modifier : Modifier < C > ,
28
+ value : ModifierValue
24
29
}
25
30
26
- impl_name_via_deref ! { [ ] String }
27
- impl_name_via_deref ! { [ ] & str }
28
- impl_name_via_deref ! { [ ] Box <str > }
29
- impl_name_via_deref ! { [ ] Rc <str > }
30
- impl_name_via_deref ! { [ C : Counter , M ] RcStr <C , M > }
31
+ struct Modifier < C : Counter = AtomicCounter > {
32
+ inner : RcStr < C , ModifierMeta < C > >
33
+ }
34
+
35
+ struct ModifierMeta < C : Counter = AtomicCounter > {
36
+ display_name : RcStr < C > ,
37
+ modifier_type : ModifierType
38
+ }
31
39
32
40
/// Type of modifier (flag or with numeric value, and associated
33
41
/// metadata if applicable)
@@ -51,27 +59,109 @@ enum ModifierType {
51
59
}
52
60
53
61
/// The value of a modifier, including whether or not the modifier is legendary
54
- pub struct ModifierValue {
62
+ struct ModifierValue {
55
63
/// The highest bit stores if the modifier is legendary, and the rest store
56
64
/// the modifier's value (if applicable)
57
65
raw : i32
58
66
}
59
67
68
+ impl JewelStore {
69
+ #[ inline]
70
+ fn new ( ) -> Self {
71
+ Self :: with_counter ( )
72
+ }
73
+
74
+ #[ inline]
75
+ fn with_counter < C : Counter > ( ) -> JewelStore < C > {
76
+ JewelStore {
77
+ modifiers : HashSet :: new ( ) ,
78
+ jewels : Vec :: new ( )
79
+ }
80
+ }
81
+ }
82
+
83
+ impl < C : Counter > JewelStore < C > {
84
+ /// Register a modifier by its identifier, return [`Ok`] if added and [`Err`]
85
+ /// if the modifier already exists
86
+ #[ inline]
87
+ fn add_modifier ( & mut self , id : & str , display_name : & str , modifier_type : ModifierType ) -> Result < ( ) , ( ) > {
88
+ if self . modifiers . get ( id) . is_none ( ) {
89
+ let modifier = Modifier :: new ( id, display_name, modifier_type) ;
90
+
91
+ // SAFETY: just checked `id` is not in set
92
+ unsafe {
93
+ self . modifiers . insert_unique_unchecked ( modifier) ;
94
+ }
95
+
96
+ Ok ( ( ) )
97
+ } else {
98
+ Err ( ( ) )
99
+ }
100
+ }
101
+ }
102
+
103
+ impl < C : Counter > Modifier < C > {
104
+ /// Create new modifier
105
+ ///
106
+ /// This will always allocate, as it has no knowledge of existing modifier
107
+ /// instances. Clone an existing modifier instance if you want to reuse
108
+ /// the allocation.
109
+ #[ inline]
110
+ fn new ( id : & str , display_name : & str , modifier_type : ModifierType ) -> Self {
111
+ Self {
112
+ inner : RcStr :: with_metadata ( id, ModifierMeta {
113
+ display_name : RcStr :: new ( display_name) ,
114
+ modifier_type
115
+ } )
116
+ }
117
+ }
118
+ }
119
+
120
+ impl < C : Counter > Borrow < str > for Modifier < C > {
121
+ #[ inline]
122
+ fn borrow ( & self ) -> & str {
123
+ & self . inner
124
+ }
125
+ }
126
+
127
+ impl < C : Counter > Clone for Modifier < C > {
128
+ #[ inline]
129
+ fn clone ( & self ) -> Self {
130
+ Self { inner : self . inner . clone ( ) }
131
+ }
132
+ }
133
+
134
+ impl < C : Counter , C2 : Counter > PartialEq < Modifier < C2 > > for Modifier < C > {
135
+ #[ inline]
136
+ fn eq ( & self , other : & Modifier < C2 > ) -> bool {
137
+ * self . inner == * other. inner
138
+ }
139
+ }
140
+
141
+ impl < C : Counter > Eq for Modifier < C > { }
142
+
143
+ impl < C : Counter > Hash for Modifier < C > {
144
+ #[ inline]
145
+ fn hash < H : Hasher > ( & self , state : & mut H ) {
146
+ Hash :: hash ( & * self . inner , state)
147
+ }
148
+ }
149
+
60
150
impl ModifierValue {
61
151
/// Maximum storable modifier value
62
- pub const MAX : i32 = i32:: MAX >> 1 ;
152
+ const MAX : i32 = i32:: MAX >> 1 ;
63
153
64
154
/// Minimum storable modifier value (negative)
65
- pub const MIN : i32 = i32:: MIN >> 1 ;
155
+ const MIN : i32 = i32:: MIN >> 1 ;
66
156
67
157
#[ inline]
68
- pub fn new ( value : i32 , is_legendary : bool ) -> Self {
158
+ fn new ( value : i32 , is_legendary : bool ) -> Self {
69
159
Self :: new_checked ( value, is_legendary)
70
160
. expect ( "modifier value out of bounds" )
71
161
}
72
162
73
163
#[ inline]
74
- pub fn new_checked ( value : i32 , is_legendary : bool ) -> Option < Self > {
164
+ fn new_checked ( value : i32 , is_legendary : bool ) -> Option < Self > {
75
165
( Self :: MIN ..=Self :: MAX ) . contains ( & value) . then ( || {
76
166
// SAFETY: we just checked we're within the allowed range
77
167
unsafe { Self :: new_unchecked ( value, is_legendary) }
@@ -82,19 +172,19 @@ impl ModifierValue {
82
172
///
83
173
/// `value` must be within the range `MIN..=MAX`
84
174
#[ inline]
85
- pub unsafe fn new_unchecked ( value : i32 , is_legendary : bool ) -> Self {
175
+ unsafe fn new_unchecked ( value : i32 , is_legendary : bool ) -> Self {
86
176
Self { raw : value | ( is_legendary. into_i32 ( ) << 31 ) }
87
177
}
88
178
89
179
#[ inline]
90
- pub fn value ( & self ) -> i32 {
180
+ fn value ( & self ) -> i32 {
91
181
// first shift left one to push out the legendary bit, then
92
182
// (arithmetic) shift right one to bring back the bit with correct sign
93
183
( self . raw << 1 ) >> 1
94
184
}
95
185
96
186
#[ inline]
97
- pub fn is_legendary ( & self ) -> bool {
187
+ fn is_legendary ( & self ) -> bool {
98
188
self . raw >> 31 == 1
99
189
}
100
190
}
0 commit comments