1
- use std:: fmt;
2
- use std:: os:: raw:: { c_char, c_void} ;
3
- use std:: str;
4
-
5
- use malloc_buf:: Malloc ;
6
-
7
1
use runtime:: { Class , Object , Sel } ;
2
+ use { Encode , Encoding } ;
8
3
9
- const QUALIFIERS : & ' static [ char ] = & [
10
- 'r' , // const
11
- 'n' , // in
12
- 'N' , // inout
13
- 'o' , // out
14
- 'O' , // bycopy
15
- 'R' , // byref
16
- 'V' , // oneway
17
- ] ;
18
-
19
- #[ cfg( target_pointer_width = "64" ) ]
20
- const CODE_INLINE_CAP : usize = 30 ;
21
-
22
- #[ cfg( target_pointer_width = "32" ) ]
23
- const CODE_INLINE_CAP : usize = 14 ;
24
-
25
- enum Code {
26
- Slice ( & ' static str ) ,
27
- Owned ( String ) ,
28
- Inline ( u8 , [ u8 ; CODE_INLINE_CAP ] ) ,
29
- Malloc ( Malloc < str > )
30
- }
31
-
32
- /// An Objective-C type encoding.
33
- ///
34
- /// For more information, see Apple's documentation:
35
- /// <https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html>
36
- pub struct Encoding {
37
- code : Code ,
38
- }
39
-
40
- impl Encoding {
41
- /// Constructs an `Encoding` from its string representation.
42
- /// Unsafe because the caller must ensure the string is a valid encoding.
43
- pub unsafe fn from_str ( code : & str ) -> Encoding {
44
- from_str ( code)
45
- }
46
-
47
- /// Returns self as a `str`.
48
- pub fn as_str ( & self ) -> & str {
49
- match self . code {
50
- Code :: Slice ( code) => code,
51
- Code :: Owned ( ref code) => code,
52
- Code :: Inline ( len, ref bytes) => unsafe {
53
- str:: from_utf8_unchecked ( & bytes[ ..len as usize ] )
54
- } ,
55
- Code :: Malloc ( ref buf) => & * buf,
56
- }
57
- }
58
- }
59
-
60
- impl Clone for Encoding {
61
- fn clone ( & self ) -> Encoding {
62
- if let Code :: Slice ( code) = self . code {
63
- from_static_str ( code)
64
- } else {
65
- from_str ( self . as_str ( ) )
66
- }
67
- }
68
- }
69
-
70
- impl PartialEq for Encoding {
71
- fn eq ( & self , other : & Encoding ) -> bool {
72
- // strip qualifiers when comparing
73
- let s = self . as_str ( ) . trim_left_matches ( QUALIFIERS ) ;
74
- let o = other. as_str ( ) . trim_left_matches ( QUALIFIERS ) ;
75
- s == o
76
- }
77
- }
78
-
79
- impl fmt:: Debug for Encoding {
80
- fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
81
- write ! ( f, "{}" , self . as_str( ) )
82
- }
83
- }
84
-
85
- pub fn from_static_str ( code : & ' static str ) -> Encoding {
86
- Encoding { code : Code :: Slice ( code) }
87
- }
88
-
89
- pub fn from_str ( code : & str ) -> Encoding {
90
- if code. len ( ) > CODE_INLINE_CAP {
91
- Encoding { code : Code :: Owned ( code. to_owned ( ) ) }
92
- } else {
93
- let mut bytes = [ 0 ; CODE_INLINE_CAP ] ;
94
- for ( dst, byte) in bytes. iter_mut ( ) . zip ( code. bytes ( ) ) {
95
- * dst = byte;
96
- }
97
- Encoding { code : Code :: Inline ( code. len ( ) as u8 , bytes) }
98
- }
99
- }
100
-
101
- pub unsafe fn from_malloc_str ( ptr : * mut c_char ) -> Encoding {
102
- let buf = Malloc :: from_c_str ( ptr) ;
103
- Encoding { code : Code :: Malloc ( buf. unwrap ( ) ) }
104
- }
105
-
106
- /// Types that have an Objective-C type encoding.
107
- ///
108
- /// Unsafe because Objective-C will make assumptions about the type (like its
109
- /// size and alignment) from its encoding, so the implementer must verify that
110
- /// the encoding is accurate.
111
- pub unsafe trait Encode {
112
- /// Returns the Objective-C type encoding for Self.
113
- fn encode ( ) -> Encoding ;
4
+ unsafe impl Encode for Sel {
5
+ const ENCODING : Encoding < ' static > = Encoding :: Sel ;
114
6
}
115
7
116
- macro_rules! encode_impls {
117
- ( $( $t: ty : $s: expr, ) * ) => ( $(
118
- unsafe impl Encode for $t {
119
- fn encode( ) -> Encoding { from_static_str( $s) }
120
- }
121
- ) * ) ;
8
+ unsafe impl < ' a > Encode for & ' a Object {
9
+ const ENCODING : Encoding < ' static > = Encoding :: Object ;
122
10
}
123
11
124
- encode_impls ! (
125
- i8 : "c" ,
126
- i16 : "s" ,
127
- i32 : "i" ,
128
- i64 : "q" ,
129
- u8 : "C" ,
130
- u16 : "S" ,
131
- u32 : "I" ,
132
- u64 : "Q" ,
133
- f32 : "f" ,
134
- f64 : "d" ,
135
- bool : "B" ,
136
- ( ) : "v" ,
137
- * mut c_char: "*" ,
138
- * const c_char: "r*" ,
139
- * mut c_void: "^v" ,
140
- * const c_void: "r^v" ,
141
- Sel : ":" ,
142
- ) ;
143
-
144
- unsafe impl Encode for isize {
145
- #[ cfg( target_pointer_width = "32" ) ]
146
- fn encode ( ) -> Encoding { i32:: encode ( ) }
147
-
148
- #[ cfg( target_pointer_width = "64" ) ]
149
- fn encode ( ) -> Encoding { i64:: encode ( ) }
12
+ unsafe impl < ' a > Encode for & ' a mut Object {
13
+ const ENCODING : Encoding < ' static > = Encoding :: Object ;
150
14
}
151
15
152
- unsafe impl Encode for usize {
153
- #[ cfg( target_pointer_width = "32" ) ]
154
- fn encode ( ) -> Encoding { u32:: encode ( ) }
155
-
156
- #[ cfg( target_pointer_width = "64" ) ]
157
- fn encode ( ) -> Encoding { u64:: encode ( ) }
16
+ unsafe impl < ' a > Encode for & ' a Class {
17
+ const ENCODING : Encoding < ' static > = Encoding :: Class ;
158
18
}
159
19
160
- macro_rules! encode_message_impl {
161
- ( $code: expr, $name: ident) => (
162
- encode_message_impl!( $code, $name, ) ;
163
- ) ;
164
- ( $code: expr, $name: ident, $( $t: ident) ,* ) => (
165
- unsafe impl <' a $( , $t) * > $crate:: Encode for & ' a $name<$( $t) ,* > {
166
- fn encode( ) -> Encoding { from_static_str( $code) }
167
- }
168
-
169
- unsafe impl <' a $( , $t) * > $crate:: Encode for & ' a mut $name<$( $t) ,* > {
170
- fn encode( ) -> Encoding { from_static_str( $code) }
171
- }
172
-
173
- unsafe impl <' a $( , $t) * > $crate:: Encode for Option <& ' a $name<$( $t) ,* >> {
174
- fn encode( ) -> Encoding { from_static_str( $code) }
175
- }
176
-
177
- unsafe impl <' a $( , $t) * > $crate:: Encode for Option <& ' a mut $name<$( $t) ,* >> {
178
- fn encode( ) -> Encoding { from_static_str( $code) }
179
- }
180
-
181
- unsafe impl <$( $t) ,* > $crate:: Encode for * const $name<$( $t) ,* > {
182
- fn encode( ) -> Encoding { from_static_str( $code) }
183
- }
184
-
185
- unsafe impl <$( $t) ,* > $crate:: Encode for * mut $name<$( $t) ,* > {
186
- fn encode( ) -> Encoding { from_static_str( $code) }
187
- }
188
- ) ;
20
+ unsafe impl < ' a > Encode for & ' a mut Class {
21
+ const ENCODING : Encoding < ' static > = Encoding :: Class ;
189
22
}
190
23
191
- encode_message_impl ! ( "@" , Object ) ;
192
-
193
- encode_message_impl ! ( "#" , Class ) ;
194
-
195
24
/// Types that represent a group of arguments, where each has an Objective-C
196
25
/// type encoding.
197
26
pub trait EncodeArguments {
198
27
/// The type as which the encodings for Self will be returned.
199
- type Encs : AsRef < [ Encoding ] > ;
200
-
201
- /// Returns the Objective-C type encodings for Self.
202
- fn encodings ( ) -> Self :: Encs ;
203
- }
204
-
205
- macro_rules! count_idents {
206
- ( ) => ( 0 ) ;
207
- ( $a: ident) => ( 1 ) ;
208
- ( $a: ident, $( $b: ident) ,+) => ( 1 + count_idents!( $( $b) ,* ) ) ;
28
+ const ENCODINGS : & ' static [ Encoding < ' static > ] ;
209
29
}
210
30
211
31
macro_rules! encode_args_impl {
212
32
( $( $t: ident) ,* ) => (
213
33
impl <$( $t: Encode ) ,* > EncodeArguments for ( $( $t, ) * ) {
214
- type Encs = [ Encoding ; count_idents!( $( $t) ,* ) ] ;
215
-
216
- fn encodings( ) -> Self :: Encs {
217
- [
218
- $( $t:: encode( ) ) ,*
219
- ]
220
- }
34
+ const ENCODINGS : & ' static [ Encoding <' static >] = & [
35
+ $( $t:: ENCODING ) ,*
36
+ ] ;
221
37
}
222
38
) ;
223
39
}
@@ -238,37 +54,14 @@ encode_args_impl!(A, B, C, D, E, F, G, H, I, J, K, L);
238
54
239
55
#[ cfg( test) ]
240
56
mod tests {
57
+ use objc_encode:: Encode ;
241
58
use runtime:: { Class , Object , Sel } ;
242
- use super :: { Encode , Encoding } ;
243
59
244
60
#[ test]
245
61
fn test_encode ( ) {
246
- assert ! ( u32 :: encode( ) . as_str( ) == "I" ) ;
247
- assert ! ( <( ) >:: encode( ) . as_str( ) == "v" ) ;
248
- assert ! ( <& Object >:: encode( ) . as_str( ) == "@" ) ;
249
- assert ! ( <* mut Object >:: encode( ) . as_str( ) == "@" ) ;
250
- assert ! ( <& Class >:: encode( ) . as_str( ) == "#" ) ;
251
- assert ! ( Sel :: encode( ) . as_str( ) == ":" ) ;
252
- }
253
-
254
- #[ test]
255
- fn test_inline_encoding ( ) {
256
- let enc = unsafe { Encoding :: from_str ( "C" ) } ;
257
- assert ! ( enc. as_str( ) == "C" ) ;
258
-
259
- let enc2 = enc. clone ( ) ;
260
- assert ! ( enc2 == enc) ;
261
- assert ! ( enc2. as_str( ) == "C" ) ;
262
- }
263
-
264
- #[ test]
265
- fn test_owned_encoding ( ) {
266
- let s = "{Test=CCCCCCCCCCCCCCCCCCCCCCCCC}" ;
267
- let enc = unsafe { Encoding :: from_str ( s) } ;
268
- assert ! ( enc. as_str( ) == s) ;
269
-
270
- let enc2 = enc. clone ( ) ;
271
- assert ! ( enc2 == enc) ;
272
- assert ! ( enc2. as_str( ) == s) ;
62
+ assert ! ( <& Object >:: ENCODING . to_string( ) == "@" ) ;
63
+ assert ! ( <* mut Object >:: ENCODING . to_string( ) == "@" ) ;
64
+ assert ! ( <& Class >:: ENCODING . to_string( ) == "#" ) ;
65
+ assert ! ( Sel :: ENCODING . to_string( ) == ":" ) ;
273
66
}
274
67
}
0 commit comments