@@ -172,3 +172,75 @@ macro_rules! msg_send {
172
172
result
173
173
} ) ;
174
174
}
175
+
176
+ /// TODO
177
+ #[ macro_export]
178
+ macro_rules! msg_send_id {
179
+ ( $obj: expr, $name: ident) => ( {
180
+ const NAME : & [ u8 ] = stringify!( $name) . as_bytes( ) ;
181
+ $crate:: msg_send_id!( @ $obj, NAME , $name)
182
+ } ) ;
183
+ ( $obj: expr, $( $name: ident: $arg: expr) ,+ $( , ) ?) => ( {
184
+ const NAME : & [ u8 ] = concat!( $( stringify!( $name) , ':' ) ,+) . as_bytes( ) ;
185
+ $crate:: msg_send_id!( @ $obj, NAME , $( $name: $arg) ,+)
186
+ } ) ;
187
+ ( @ $obj: expr, $name: ident, $( $sel: tt) +) => { {
188
+ const IS_INIT : bool = $crate:: __starts_with_str( $name, b"init" ) ;
189
+ const IS_RETAINED : bool = {
190
+ $crate:: __starts_with_str( $name, b"alloc" )
191
+ || $crate:: __starts_with_str( $name, b"new" )
192
+ || $crate:: __starts_with_str( $name, b"copy" )
193
+ || $crate:: __starts_with_str( $name, b"mutableCopy" )
194
+ || $crate:: __starts_with_str( $name, b"init" )
195
+ } ;
196
+
197
+ :: std:: println!( "IS_INIT: {}" , IS_INIT ) ;
198
+ :: std:: println!( "IS_RETAINED: {}" , IS_RETAINED ) ;
199
+
200
+ let result = if IS_INIT {
201
+ // TODO: Ensure `obj` is Id here
202
+ let obj = :: core:: mem:: ManuallyDrop :: new( $obj) ;
203
+ $crate:: msg_send![ obj, $( $sel) +]
204
+ } else {
205
+ $crate:: msg_send![ $obj, $( $sel) +]
206
+ } ;
207
+ if IS_RETAINED {
208
+ $crate:: rc:: Id :: new( result)
209
+ } else {
210
+ // All code between the `msg_send!` and the `retain_autoreleased` must
211
+ // be able to be optimized away for this to work.
212
+ $crate:: rc:: Id :: retain_autoreleased( result)
213
+ }
214
+ } } ;
215
+ }
216
+
217
+ #[ doc( hidden) ]
218
+ pub const fn __starts_with_str ( haystack : & [ u8 ] , needle : & [ u8 ] ) -> bool {
219
+ if needle. len ( ) > haystack. len ( ) {
220
+ return false ;
221
+ }
222
+ let mut i = 0 ;
223
+ while i < needle. len ( ) {
224
+ if needle[ i] != haystack[ i] {
225
+ return false ;
226
+ }
227
+ i += 1 ;
228
+ }
229
+ true
230
+ }
231
+
232
+ #[ cfg( test) ]
233
+ mod tests {
234
+ use super :: * ;
235
+
236
+ #[ test]
237
+ fn test_starts_with_str ( ) {
238
+ assert ! ( __starts_with_str( b"abcdef" , b"abc" ) ) ;
239
+ assert ! ( __starts_with_str( b"a" , b"" ) ) ;
240
+ assert ! ( __starts_with_str( b"" , b"" ) ) ;
241
+
242
+ assert ! ( !__starts_with_str( b"abcdef" , b"def" ) ) ;
243
+ assert ! ( !__starts_with_str( b"abcdef" , b"abb" ) ) ;
244
+ assert ! ( !__starts_with_str( b"" , b"a" ) ) ;
245
+ }
246
+ }
0 commit comments