Fix endianness problems with new librustc ipv6 addresses

This commit is contained in:
Andrew Poelstra 2015-05-10 13:08:38 -05:00
parent 2975c91e37
commit 4b1b1c4a74
2 changed files with 32 additions and 72 deletions

View File

@ -33,15 +33,17 @@ pub struct Address {
pub port: u16 pub port: u16
} }
fn addr_to_be(addr: [u16; 8]) -> [u16; 8] {
[addr[0].to_be(), addr[1].to_be(), addr[2].to_be(), addr[3].to_be(),
addr[4].to_be(), addr[5].to_be(), addr[6].to_be(), addr[7].to_be()]
}
impl<S: SimpleEncoder> ConsensusEncodable<S> for Address { impl<S: SimpleEncoder> ConsensusEncodable<S> for Address {
#[inline] #[inline]
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
try!(self.services.consensus_encode(s)); try!(self.services.consensus_encode(s));
try!(self.address.consensus_encode(s)); try!(addr_to_be(self.address).consensus_encode(s));
// Explicitly code the port since it needs to be big-endian self.port.to_be().consensus_encode(s)
try!(((self.port / 0x100) as u8).consensus_encode(s));
try!(((self.port % 0x100) as u8).consensus_encode(s));
Ok(())
} }
} }
@ -50,13 +52,8 @@ impl<D: SimpleDecoder> ConsensusDecodable<D> for Address {
fn consensus_decode(d: &mut D) -> Result<Address, D::Error> { fn consensus_decode(d: &mut D) -> Result<Address, D::Error> {
Ok(Address { Ok(Address {
services: try!(ConsensusDecodable::consensus_decode(d)), services: try!(ConsensusDecodable::consensus_decode(d)),
address: try!(ConsensusDecodable::consensus_decode(d)), address: addr_to_be(try!(ConsensusDecodable::consensus_decode(d))),
// Explicitly code the port since it needs to be big-endian port: u16::from_be(try!(ConsensusDecodable::consensus_decode(d)))
port: {
let b1: u8 = try!(ConsensusDecodable::consensus_decode(d));
let b2: u8 = try!(ConsensusDecodable::consensus_decode(d));
(b1 as u16 * 0x100) + (b2 as u16)
}
}) })
} }
} }
@ -117,9 +114,9 @@ mod test {
0, 1, 0x20, 0x8d]); 0, 1, 0x20, 0x8d]);
assert!(addr.is_ok()); assert!(addr.is_ok());
let full = addr.unwrap(); let full = addr.unwrap();
assert!(full.services == 1); assert_eq!(full.services, 1);
assert!(full.address == [0, 0, 0, 0, 0, 0xffff, 0x0a00, 0x0001]); assert_eq!(full.address, [0, 0, 0, 0, 0, 0xffff, 0x0a00, 0x0001]);
assert!(full.port == 8333); assert_eq!(full.port, 8333);
addr = deserialize(&[1u8, 0, 0, 0, 0, 0, 0, 0, 0, addr = deserialize(&[1u8, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x0a, 0, 0, 1]); 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x0a, 0, 0, 1]);

View File

@ -59,35 +59,28 @@ pub struct VarInt(pub u64);
pub struct CheckedData(pub Vec<u8>); pub struct CheckedData(pub Vec<u8>);
// Primitive types // Primitive types
impl<S: SimpleEncoder> ConsensusEncodable<S> for u8 { macro_rules! impl_int_encodable{
($ty:ident, $meth_dec:ident, $meth_enc:ident) => (
impl<D: SimpleDecoder> ConsensusDecodable<D> for $ty {
#[inline] #[inline]
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_u8(*self) } fn consensus_decode(d: &mut D) -> Result<$ty, D::Error> { d.$meth_dec().map($ty::from_le) }
} }
impl<S: SimpleEncoder> ConsensusEncodable<S> for u16 { impl<S: SimpleEncoder> ConsensusEncodable<S> for $ty {
#[inline] #[inline]
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_u16(self.to_le()) } fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { s.$meth_enc(self.to_le()) }
}
)
} }
impl<S: SimpleEncoder> ConsensusEncodable<S> for u32 { impl_int_encodable!(u8, read_u8, emit_u8);
#[inline] impl_int_encodable!(u16, read_u16, emit_u16);
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_u32(self.to_le()) } impl_int_encodable!(u32, read_u32, emit_u32);
} impl_int_encodable!(u64, read_u64, emit_u64);
impl_int_encodable!(i8, read_i8, emit_i8);
impl<S: SimpleEncoder> ConsensusEncodable<S> for u64 { impl_int_encodable!(i16, read_i16, emit_i16);
#[inline] impl_int_encodable!(i32, read_i32, emit_i32);
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_u64(self.to_le()) } impl_int_encodable!(i64, read_i64, emit_i64);
}
impl<S: SimpleEncoder> ConsensusEncodable<S> for i32 {
#[inline]
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_i32(self.to_le()) }
}
impl<S: SimpleEncoder> ConsensusEncodable<S> for i64 {
#[inline]
fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_i64(self.to_le()) }
}
impl<S: SimpleEncoder> ConsensusEncodable<S> for VarInt { impl<S: SimpleEncoder> ConsensusEncodable<S> for VarInt {
#[inline] #[inline]
@ -101,36 +94,6 @@ impl<S: SimpleEncoder> ConsensusEncodable<S> for VarInt {
} }
} }
impl<D: SimpleDecoder> ConsensusDecodable<D> for u8 {
#[inline]
fn consensus_decode(d: &mut D) -> Result<u8, D::Error> { d.read_u8() }
}
impl<D: SimpleDecoder> ConsensusDecodable<D> for u16 {
#[inline]
fn consensus_decode(d: &mut D) -> Result<u16, D::Error> { d.read_u16().map(|n| u16::from_le(n)) }
}
impl<D: SimpleDecoder> ConsensusDecodable<D> for u32 {
#[inline]
fn consensus_decode(d: &mut D) -> Result<u32, D::Error> { d.read_u32().map(|n| u32::from_le(n)) }
}
impl<D: SimpleDecoder> ConsensusDecodable<D> for u64 {
#[inline]
fn consensus_decode(d: &mut D) -> Result<u64, D::Error> { d.read_u64().map(|n| u64::from_le(n)) }
}
impl<D: SimpleDecoder> ConsensusDecodable<D> for i32 {
#[inline]
fn consensus_decode(d: &mut D) -> Result<i32, D::Error> { d.read_i32().map(|n| i32::from_le(n)) }
}
impl<D: SimpleDecoder> ConsensusDecodable<D> for i64 {
#[inline]
fn consensus_decode(d: &mut D) -> Result<i64, D::Error> { d.read_i64().map(|n| i64::from_le(n)) }
}
impl<D: SimpleDecoder> ConsensusDecodable<D> for VarInt { impl<D: SimpleDecoder> ConsensusDecodable<D> for VarInt {
#[inline] #[inline]
fn consensus_decode(d: &mut D) -> Result<VarInt, D::Error> { fn consensus_decode(d: &mut D) -> Result<VarInt, D::Error> {