1use core::fmt;
2
3use crate::parse;
4
5#[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}