@@ -24,27 +24,66 @@ use smallvec::SmallVec;
24
24
use bevy_ecs:: prelude:: { Entity , World } ;
25
25
26
26
use crate :: {
27
- add_listener_to_source, Accessed , AddOperation , AnyBuffer , AnyBufferKey , AnyMessageBox , Buffer ,
27
+ add_listener_to_source, Accessed , AddOperation , AnyBuffer , AnyBufferKey , AnyMessageBox , AsAnyBuffer ,
28
28
BufferKeyBuilder , Bufferable , Buffered , Builder , Chain , Gate , GateState , Join , Joined ,
29
29
OperationError , OperationResult , OperationRoster , Output , UnusedTarget ,
30
30
} ;
31
31
32
32
pub use bevy_impulse_derive:: JoinedValue ;
33
33
34
- #[ derive( Clone , Default ) ]
35
- pub struct BufferMap {
36
- inner : HashMap < Cow < ' static , str > , AnyBuffer > ,
34
+ /// Uniquely identify a buffer within a buffer map, either by name or by an
35
+ /// index value.
36
+ #[ derive( Debug , Clone , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
37
+ pub enum BufferIdentifier < ' a > {
38
+ /// Identify a buffer by name
39
+ Name ( Cow < ' a , str > ) ,
40
+ /// Identify a buffer by an index value
41
+ Index ( usize ) ,
37
42
}
38
43
39
- impl BufferMap {
40
- /// Insert a named buffer into the map .
41
- pub fn insert ( & mut self , name : impl Into < Cow < ' static , str > > , buffer : impl Into < AnyBuffer > ) {
42
- self . inner . insert ( name. into ( ) , buffer . into ( ) ) ;
44
+ impl BufferIdentifier < ' static > {
45
+ /// Clone a name to use as an identifier .
46
+ pub fn clone_name ( name : & str ) -> Self {
47
+ BufferIdentifier :: Name ( Cow :: Owned ( name. to_owned ( ) ) )
43
48
}
44
49
45
- /// Get one of the buffers from the map by its name.
46
- pub fn get ( & self , name : & str ) -> Option < & AnyBuffer > {
47
- self . inner . get ( name)
50
+ /// Borrow a string literal name to use as an identifier.
51
+ pub fn literal_name ( name : & ' static str ) -> Self {
52
+ BufferIdentifier :: Name ( Cow :: Borrowed ( name) )
53
+ }
54
+
55
+ /// Use an index as an identifier.
56
+ pub fn index ( index : usize ) -> Self {
57
+ BufferIdentifier :: Index ( index)
58
+ }
59
+ }
60
+
61
+ impl From < & ' static str > for BufferIdentifier < ' static > {
62
+ fn from ( value : & ' static str ) -> Self {
63
+ BufferIdentifier :: Name ( Cow :: Borrowed ( value) )
64
+ }
65
+ }
66
+
67
+ pub type BufferMap = HashMap < BufferIdentifier < ' static > , AnyBuffer > ;
68
+
69
+ /// Extension trait that makes it more convenient to insert buffers into a [`BufferMap`].
70
+ pub trait AddBufferToMap {
71
+ /// Convenience function for inserting items into a [`BufferMap`]. This
72
+ /// automatically takes care of converting the types.
73
+ fn insert_buffer < I : Into < BufferIdentifier < ' static > > , B : AsAnyBuffer > (
74
+ & mut self ,
75
+ identifier : I ,
76
+ buffer : B ,
77
+ ) ;
78
+ }
79
+
80
+ impl AddBufferToMap for BufferMap {
81
+ fn insert_buffer < I : Into < BufferIdentifier < ' static > > , B : AsAnyBuffer > (
82
+ & mut self ,
83
+ identifier : I ,
84
+ buffer : B ,
85
+ ) {
86
+ self . insert ( identifier. into ( ) , buffer. as_any_buffer ( ) ) ;
48
87
}
49
88
}
50
89
@@ -54,56 +93,57 @@ impl BufferMap {
54
93
#[ error( "the incoming buffer map is incompatible with the layout" ) ]
55
94
pub struct IncompatibleLayout {
56
95
/// Names of buffers that were missing from the incoming buffer map.
57
- pub missing_buffers : Vec < Cow < ' static , str > > ,
96
+ pub missing_buffers : Vec < BufferIdentifier < ' static > > ,
58
97
/// Buffers whose expected type did not match the received type.
59
98
pub incompatible_buffers : Vec < BufferIncompatibility > ,
60
99
}
61
100
62
101
impl IncompatibleLayout {
63
- /// Check whether a named buffer is compatible with a specific concrete message type.
64
- pub fn require_message_type < Message : ' static > (
102
+ /// Check whether a named buffer is compatible with a specialized buffer type,
103
+ /// such as `JsonBuffer`.
104
+ pub fn require_buffer_by_name < BufferType : ' static > (
65
105
& mut self ,
66
106
expected_name : & str ,
67
107
buffers : & BufferMap ,
68
- ) -> Result < Buffer < Message > , ( ) > {
69
- if let Some ( ( name, buffer) ) = buffers. inner . get_key_value ( expected_name) {
70
- if let Some ( buffer) = buffer. downcast_for_message :: < Message > ( ) {
108
+ ) -> Result < BufferType , ( ) > {
109
+ let identifier = BufferIdentifier :: Name ( Cow :: Borrowed ( expected_name) ) ;
110
+ if let Some ( buffer) = buffers. get ( & identifier) {
111
+ if let Some ( buffer) = buffer. downcast_buffer :: < BufferType > ( ) {
71
112
return Ok ( buffer) ;
72
113
} else {
73
114
self . incompatible_buffers . push ( BufferIncompatibility {
74
- name : name . clone ( ) ,
75
- expected : std:: any:: type_name :: < Buffer < Message > > ( ) ,
115
+ identifier : BufferIdentifier :: Name ( Cow :: Owned ( expected_name . to_owned ( ) ) ) ,
116
+ expected : std:: any:: type_name :: < BufferType > ( ) ,
76
117
received : buffer. message_type_name ( ) ,
77
118
} ) ;
78
119
}
79
120
} else {
80
- self . missing_buffers
81
- . push ( Cow :: Owned ( expected_name. to_owned ( ) ) ) ;
121
+ self . missing_buffers . push ( BufferIdentifier :: Name ( Cow :: Owned ( expected_name. to_owned ( ) ) ) ) ;
82
122
}
83
123
84
124
Err ( ( ) )
85
125
}
86
126
87
- /// Check whether a named buffer is compatible with a specialized buffer type,
88
- /// such as `JsonBuffer` .
89
- pub fn require_buffer_type < BufferType : ' static > (
127
+ /// Same as [`Self::require_buffer_by_name`] but more efficient for names
128
+ /// given by string literal values .
129
+ pub fn require_buffer_by_literal < BufferType : ' static > (
90
130
& mut self ,
91
- expected_name : & str ,
131
+ expected_name : & ' static str ,
92
132
buffers : & BufferMap ,
93
133
) -> Result < BufferType , ( ) > {
94
- if let Some ( ( name, buffer) ) = buffers. inner . get_key_value ( expected_name) {
134
+ let identifier = BufferIdentifier :: Name ( Cow :: Borrowed ( expected_name) ) ;
135
+ if let Some ( buffer) = buffers. get ( & identifier) {
95
136
if let Some ( buffer) = buffer. downcast_buffer :: < BufferType > ( ) {
96
137
return Ok ( buffer) ;
97
138
} else {
98
139
self . incompatible_buffers . push ( BufferIncompatibility {
99
- name : name . clone ( ) ,
140
+ identifier ,
100
141
expected : std:: any:: type_name :: < BufferType > ( ) ,
101
142
received : buffer. message_type_name ( ) ,
102
143
} ) ;
103
144
}
104
145
} else {
105
- self . missing_buffers
106
- . push ( Cow :: Owned ( expected_name. to_owned ( ) ) ) ;
146
+ self . missing_buffers . push ( identifier) ;
107
147
}
108
148
109
149
Err ( ( ) )
@@ -114,7 +154,7 @@ impl IncompatibleLayout {
114
154
#[ derive( Debug , Clone ) ]
115
155
pub struct BufferIncompatibility {
116
156
/// Name of the expected buffer
117
- pub name : Cow < ' static , str > ,
157
+ pub identifier : BufferIdentifier < ' static > ,
118
158
/// The type that was expected for this buffer
119
159
pub expected : & ' static str ,
120
160
/// The type that was received for this buffer
@@ -246,36 +286,36 @@ pub trait BufferKeyMap: 'static + Send + Sync + Sized + Clone {
246
286
247
287
impl BufferMapLayout for BufferMap {
248
288
fn buffer_list ( & self ) -> SmallVec < [ AnyBuffer ; 8 ] > {
249
- self . inner . values ( ) . cloned ( ) . collect ( )
289
+ self . values ( ) . cloned ( ) . collect ( )
250
290
}
251
291
fn try_from_buffer_map ( buffers : & BufferMap ) -> Result < Self , IncompatibleLayout > {
252
292
Ok ( buffers. clone ( ) )
253
293
}
254
294
}
255
295
256
296
impl Joined for BufferMap {
257
- type Item = HashMap < Cow < ' static , str > , AnyMessageBox > ;
297
+ type Item = HashMap < BufferIdentifier < ' static > , AnyMessageBox > ;
258
298
259
299
fn pull ( & self , session : Entity , world : & mut World ) -> Result < Self :: Item , OperationError > {
260
300
let mut value = HashMap :: new ( ) ;
261
- for ( name, buffer) in & self . inner {
301
+ for ( name, buffer) in self . iter ( ) {
262
302
value. insert ( name. clone ( ) , buffer. pull ( session, world) ?) ;
263
303
}
264
304
265
305
Ok ( value)
266
306
}
267
307
}
268
308
269
- impl JoinedValue for HashMap < Cow < ' static , str > , AnyMessageBox > {
309
+ impl JoinedValue for HashMap < BufferIdentifier < ' static > , AnyMessageBox > {
270
310
type Buffers = BufferMap ;
271
311
}
272
312
273
313
impl Accessed for BufferMap {
274
- type Key = HashMap < Cow < ' static , str > , AnyBufferKey > ;
314
+ type Key = HashMap < BufferIdentifier < ' static > , AnyBufferKey > ;
275
315
276
316
fn create_key ( & self , builder : & BufferKeyBuilder ) -> Self :: Key {
277
317
let mut keys = HashMap :: new ( ) ;
278
- for ( name, buffer) in & self . inner {
318
+ for ( name, buffer) in self . iter ( ) {
279
319
let key = AnyBufferKey {
280
320
tag : builder. make_tag ( buffer. id ( ) ) ,
281
321
interface : buffer. interface ,
@@ -286,7 +326,7 @@ impl Accessed for BufferMap {
286
326
}
287
327
288
328
fn add_accessor ( & self , accessor : Entity , world : & mut World ) -> OperationResult {
289
- for buffer in self . inner . values ( ) {
329
+ for buffer in self . values ( ) {
290
330
buffer. add_accessor ( accessor, world) ?;
291
331
}
292
332
Ok ( ( ) )
@@ -313,7 +353,7 @@ impl Accessed for BufferMap {
313
353
314
354
#[ cfg( test) ]
315
355
mod tests {
316
- use crate :: { prelude:: * , testing:: * , BufferMap } ;
356
+ use crate :: { prelude:: * , testing:: * , BufferMap , AddBufferToMap } ;
317
357
318
358
#[ derive( JoinedValue ) ]
319
359
struct TestJoinedValue < T : Send + Sync + ' static + Clone > {
@@ -337,11 +377,11 @@ mod tests {
337
377
let buffer_any = builder. create_buffer ( BufferSettings :: default ( ) ) ;
338
378
339
379
let mut buffers = BufferMap :: default ( ) ;
340
- buffers. insert ( "integer" , buffer_i64) ;
341
- buffers. insert ( "float" , buffer_f64) ;
342
- buffers. insert ( "string" , buffer_string) ;
343
- buffers. insert ( "generic" , buffer_generic) ;
344
- buffers. insert ( "any" , buffer_any) ;
380
+ buffers. insert_buffer ( "integer" , buffer_i64) ;
381
+ buffers. insert_buffer ( "float" , buffer_f64) ;
382
+ buffers. insert_buffer ( "string" , buffer_string) ;
383
+ buffers. insert_buffer ( "generic" , buffer_generic) ;
384
+ buffers. insert_buffer ( "any" , buffer_any) ;
345
385
346
386
scope. input . chain ( builder) . fork_unzip ( (
347
387
|chain : Chain < _ > | chain. connect ( buffer_i64. input_slot ( ) ) ,
0 commit comments