objc_encode/
encoding.rs

1use core::fmt;
2
3use crate::parse;
4
5/// An Objective-C type encoding.
6///
7/// For more information, see Apple's documentation:
8/// <https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html>
9#[derive(Clone, Copy, Debug, PartialEq, Eq)]
10pub enum Encoding<'a> {
11    Char,
12    Short,
13    Int,
14    Long,
15    LongLong,
16    UChar,
17    UShort,
18    UInt,
19    ULong,
20    ULongLong,
21    Float,
22    Double,
23    Bool,
24    Void,
25    String,
26    Object,
27    Block,
28    Class,
29    Sel,
30    Unknown,
31    BitField(u32),
32    Pointer(&'a Encoding<'a>),
33    Array(u32, &'a Encoding<'a>),
34    Struct(&'a str, &'a [Encoding<'a>]),
35    Union(&'a str, &'a [Encoding<'a>]),
36}
37
38impl fmt::Display for Encoding<'_> {
39    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
40        use Encoding::*;
41        let code = match *self {
42            Char      => "c",
43            Short     => "s",
44            Int       => "i",
45            Long      => "l",
46            LongLong  => "q",
47            UChar     => "C",
48            UShort    => "S",
49            UInt      => "I",
50            ULong     => "L",
51            ULongLong => "Q",
52            Float     => "f",
53            Double    => "d",
54            Bool      => "B",
55            Void      => "v",
56            String    => "*",
57            Object    => "@",
58            Block     => "@?",
59            Class     => "#",
60            Sel       => ":",
61            Unknown   => "?",
62            BitField(b) => {
63                return write!(formatter, "b{}", b);
64            }
65            Pointer(t) => {
66                return write!(formatter, "^{}", t);
67            }
68            Array(len, item) => {
69                return write!(formatter, "[{}{}]", len, item);
70            }
71            Struct(name, fields) => {
72                write!(formatter, "{{{}=", name)?;
73                for field in fields {
74                    fmt::Display::fmt(field, formatter)?;
75                }
76                return formatter.write_str("}");
77            }
78            Union(name, members) => {
79                write!(formatter, "({}=", name)?;
80                for member in members {
81                    fmt::Display::fmt(member, formatter)?;
82                }
83                return formatter.write_str(")");
84            }
85        };
86        formatter.write_str(code)
87    }
88}
89
90impl PartialEq<str> for Encoding<'_> {
91    fn eq(&self, other: &str) -> bool {
92        parse::eq_enc(other, self)
93    }
94}
95
96impl PartialEq<Encoding<'_>> for str {
97    fn eq(&self, other: &Encoding) -> bool {
98        parse::eq_enc(self, other)
99    }
100}
101
102#[cfg(test)]
103mod tests {
104    use std::string::ToString;
105    use super::Encoding;
106
107    #[test]
108    fn test_array_display() {
109        let e = Encoding::Array(12, &Encoding::Int);
110        assert_eq!(e.to_string(), "[12i]");
111        assert_eq!(&e, "[12i]");
112    }
113
114    #[test]
115    fn test_pointer_display() {
116        let e = Encoding::Pointer(&Encoding::Int);
117        assert_eq!(e.to_string(), "^i");
118        assert_eq!(&e, "^i");
119    }
120
121    #[test]
122    fn test_pointer_eq() {
123        let i = Encoding::Int;
124        let p = Encoding::Pointer(&Encoding::Int);
125
126        assert!(p == p);
127        assert!(p != i);
128    }
129
130    #[test]
131    fn test_int_display() {
132        assert_eq!(Encoding::Int.to_string(), "i");
133        assert_eq!(&Encoding::Int, "i");
134    }
135
136    #[test]
137    fn test_eq() {
138        let i = Encoding::Int;
139        let c = Encoding::Char;
140
141        assert!(i == i);
142        assert!(i != c);
143    }
144
145    #[test]
146    fn test_struct_display() {
147        let s = Encoding::Struct("CGPoint", &[Encoding::Char, Encoding::Int]);
148        assert_eq!(s.to_string(), "{CGPoint=ci}");
149        assert_eq!(&s, "{CGPoint=ci}");
150    }
151
152    #[test]
153    fn test_struct_eq() {
154        let s = Encoding::Struct("CGPoint", &[Encoding::Char, Encoding::Int]);
155        assert!(s == s);
156        assert!(s != Encoding::Int);
157    }
158
159    #[test]
160    fn test_union_display() {
161        let u = Encoding::Union("Onion", &[Encoding::Char, Encoding::Int]);
162        assert_eq!(u.to_string(), "(Onion=ci)");
163        assert_eq!(&u, "(Onion=ci)");
164    }
165
166    #[test]
167    fn test_union_eq() {
168        let u = Encoding::Union("Onion", &[Encoding::Char, Encoding::Int]);
169        assert!(u == u);
170        assert!(u != Encoding::Int);
171    }
172}