use core::fmt;
use {Encoding, Encodings};
use encoding::Primitive;
#[derive(Debug)]
pub enum Descriptor<'a,
T: 'a + ?Sized,
I: 'a + ?Sized,
F: 'a + ?Sized,
M: 'a + ?Sized> {
Primitive(Primitive),
Pointer(&'a T),
Array(u32, &'a I),
Struct(&'a str, &'a F),
Union(&'a str, &'a M),
}
impl<'a,
T: 'a + ?Sized,
I: 'a + ?Sized,
F: 'a + ?Sized,
M: 'a + ?Sized>
Copy for Descriptor<'a, T, I, F, M> { }
impl<'a,
T: 'a + ?Sized,
I: 'a + ?Sized,
F: 'a + ?Sized,
M: 'a + ?Sized>
Clone for Descriptor<'a, T, I, F, M> {
fn clone(&self) -> Descriptor<'a, T, I, F, M> {
*self
}
}
pub fn encodings_eq<T: ?Sized, U: ?Sized>(e1: &T, e2: &U) -> bool
where T: Encoding, U: Encoding {
use Descriptor::*;
match (e1.descriptor(), e2.descriptor()) {
(Primitive(p1), Primitive(p2)) => primitives_eq(p1, p2),
(Pointer(t1), Pointer(t2)) => t1.eq_encoding(t2),
(Array(l1, i1), Array(l2, i2)) =>
l1 == l2 && i1.eq_encoding(i2),
(Struct(n1, f1), Struct(n2, f2)) =>
n1 == n2 && f1.eq_encodings(f2),
(Union(n1, m1), Union(n2, m2)) =>
n1 == n2 && m1.eq_encodings(m2),
_ => false,
}
}
fn primitives_eq(p1: Primitive, p2: Primitive) -> bool {
use encoding::Primitive::*;
match (p1, p2) {
(Char , Char ) => true,
(Short , Short ) => true,
(Int , Int ) => true,
(Long , Long ) => true,
(LongLong , LongLong ) => true,
(UChar , UChar ) => true,
(UShort , UShort ) => true,
(UInt , UInt ) => true,
(ULong , ULong ) => true,
(ULongLong, ULongLong) => true,
(Float , Float ) => true,
(Double , Double ) => true,
(Bool , Bool ) => true,
(Void , Void ) => true,
(String , String ) => true,
(Object , Object ) => true,
(Block , Block ) => true,
(Class , Class ) => true,
(Sel , Sel ) => true,
(Unknown , Unknown ) => true,
(BitField(b1), BitField(b2)) => b1 == b2,
_ => false,
}
}
pub fn write_encoding<W, T: ?Sized>(writer: &mut W, encoding: &T) -> fmt::Result
where W: fmt::Write, T: Encoding {
use Descriptor::*;
match encoding.descriptor() {
Primitive(p) => write_primitive(writer, p),
Pointer(t) => {
try!(writer.write_char('^'));
t.write(writer)
}
Array(len, item) => {
try!(write!(writer, "[{}", len));
try!(item.write(writer));
writer.write_char(']')
}
Struct(name, fields) => {
try!(write!(writer, "{{{}=", name));
try!(fields.write_all(writer));
writer.write_char('}')
}
Union(name, members) => {
try!(write!(writer, "({}=", name));
try!(members.write_all(writer));
writer.write_char(')')
}
}
}
fn write_primitive<W: fmt::Write>(writer: &mut W, p: Primitive) -> fmt::Result {
use encoding::Primitive::*;
let code = match p {
Char => "c",
Short => "s",
Int => "i",
Long => "l",
LongLong => "q",
UChar => "C",
UShort => "S",
UInt => "I",
ULong => "L",
ULongLong => "Q",
Float => "f",
Double => "d",
Bool => "B",
Void => "v",
String => "*",
Object => "@",
Block => "@?",
Class => "#",
Sel => ":",
Unknown => "?",
BitField(b) => {
return write!(writer, "b{}", b);
}
};
writer.write_str(code)
}