this byte ordering what the fuck

master
Jordan Orelli 8 years ago
parent 3b8ff04f04
commit bce9de8d19

@ -40,11 +40,11 @@ func (r *Reader) ReadBits(bits uint) (n uint64) {
r.err = err r.err = err
return 0 return 0
} }
r.n <<= 8 r.n |= uint64(b) << r.bits
r.n |= uint64(b)
r.bits += 8 r.bits += 8
} }
n = (r.n >> (r.bits - bits)) & ((1 << bits) - 1) n = r.n & (1<<bits - 1)
r.n >>= bits
r.bits -= bits r.bits -= bits
return return
} }
@ -77,20 +77,20 @@ func (r *Reader) Read(buf []byte) (int, error) {
// by the 4 least-significant bits, then a variable number of most-significant // by the 4 least-significant bits, then a variable number of most-significant
// bits based on the prefix. // bits based on the prefix.
// //
// 00 - 0 // 00 - 4
// 01 - 4 // 01 - 8
// 10 - 8 // 10 - 12 (why 12? this really baffles me)
// 11 - 28 // 11 - 32
func (r *Reader) ReadUBitVar() uint64 { func (r *Reader) ReadUBitVar() uint64 {
switch prefix := r.ReadBits(2); prefix { switch b := r.ReadBits(6); b >> 4 {
case 0: case 0:
return r.ReadBits(4) return b & 0xf
case 1: case 1:
return r.ReadBits(4) | r.ReadBits(4)<<4 return b&0xf | r.ReadBits(4)<<4
case 2: case 2:
return r.ReadBits(4) | r.ReadBits(8)<<4 return b&0xf | r.ReadBits(8)<<4
case 3: case 3:
return r.ReadBits(4) | r.ReadBits(28)<<4 return b&0xf | r.ReadBits(28)<<4
default: default:
panic("not reached") panic("not reached")
} }

@ -10,8 +10,8 @@ var (
// 1000 1011 1010 1101 1111 0000 0000 1101 // 1000 1011 1010 1101 1111 0000 0000 1101
badFood = []byte{0x8b, 0xad, 0xf0, 0x0d} badFood = []byte{0x8b, 0xad, 0xf0, 0x0d}
// 0000 1110 0001 1110 1110 0111 1011 1110 1110 1111 // 1110 1100 0111 0000 1100 0000 0000 0001 1110 0010
eLeetBeef = []byte{0x0e, 0x1e, 0xe7, 0xbe, 0xef} ectoCooler = []byte{0xec, 0x70, 0xc0, 0x01, 0xe2}
) )
// test the bit-level reads // test the bit-level reads
@ -32,28 +32,30 @@ func TestReadBits(t *testing.T) {
r = NewBytesReader(badFood) r = NewBytesReader(badFood)
// 1000 1011 1010 1101 1111 0000 0000 1101 // 1000 1011 1010 1101 1111 0000 0000 1101
// ^ // ^
assert.Equal(uint64(0x01), r.ReadBits(1)) assert.Equal(uint64(0x01), r.ReadBits(1))
// 1000 1011 1010 1101 1111 0000 0000 1101 // 1000 1011 1010 1101 1111 0000 0000 1101
// ^-^ // ^-^
assert.Equal(uint64(0), r.ReadBits(3)) assert.Equal(uint64(0x5), r.ReadBits(3))
// 1000 1011 1010 1101 1111 0000 0000 1101 // 1000 1011 1010 1101 1111 0000 0000 1101
// ^--^ // ^--^
assert.Equal(uint64(0xb), r.ReadBits(4)) assert.Equal(uint64(0x8), r.ReadBits(4))
// 1000 1011 1010 1101 1111 0000 0000 1101 // 1000 1011 1010 1101 1111 0000 0000 1101
// ^----^ // ^----^
assert.Equal(uint64(0x15), r.ReadBits(5)) assert.Equal(uint64(0xd), r.ReadBits(5))
// 1000 1011 1010 1101 1111 0000 0000 1101 // 1000 1011 1010 1101 1111 0000 0000 1101
// ^----+----^ // ^-^.........^-----^
assert.Equal(uint64(0x17c), r.ReadBits(9)) // data bits: 1 1000 0101
assert.Equal(uint64(0x185), r.ReadBits(9))
// 1000 1011 1010 1101 1111 0000 0000 1101 // 1000 1011 1010 1101 1111 0000 0000 1101
// ^----+----+^ // ^^........^-------^
assert.Equal(uint64(0xd), r.ReadBits(10)) // data bits: 00 0011 0111
assert.Equal(uint64(0x37), r.ReadBits(10))
} }
// test the Read calls, satisfying io.Reader // test the Read calls, satisfying io.Reader
@ -74,16 +76,18 @@ func TestRead(t *testing.T) {
assert.Equal(badFood, buf) assert.Equal(badFood, buf)
r = NewBytesReader(badFood) r = NewBytesReader(badFood)
// 1000 1011 1010 1101 1111 0000 0000 1101
r.ReadBits(1) r.ReadBits(1)
// 0001 0111 0101 1011 1110 0000 0001 101 // 1000 1011 1010 1101 1111 0000 0000 1101
// ^------^..........^ : 1100 0101
// ^------^..........^ : 0101 0110
// ^------^..........^ : 1111 1000
buf = make([]byte, 3) buf = make([]byte, 3)
n, err = r.Read(buf) n, err = r.Read(buf)
assert.NoError(err) assert.NoError(err)
assert.Equal(3, n) assert.Equal(3, n)
expected := []byte{0x17, 0x5b, 0xe0} expected := []byte{0xc5, 0x56, 0xf8}
assert.Equal(expected, buf) assert.Equal(expected, buf)
} }
@ -95,38 +99,61 @@ func TestUbitVar(t *testing.T) {
) )
// 1000 1011 1010 1101 1111 0000 0000 1101 // 1000 1011 1010 1101 1111 0000 0000 1101
// ||^---^ : data (0101)
// ^^ : prefix (00)
r = NewBytesReader(badFood) r = NewBytesReader(badFood)
// 1000 1011 1010 1101 1111 0000 0000 1101
// ^
r.ReadBits(1) r.ReadBits(1)
// 1000 1011 1010 1101 1111 0000 0000 1101
// ^^ : prefix 00
// ^---^ : data 0101
u = r.ReadUBitVar() u = r.ReadUBitVar()
assert.Equal(uint64(5), u) assert.Equal(uint64(5), u)
// 1000 1011 1010 1101 1111 0000 0000 1101
// ^.................^
r.ReadBits(2) r.ReadBits(2)
// 1000 1011 1010 1101 1111 0000 0000 1101 // 1000 1011 1010 1101 1111 0000 0000 1101
// ||| | ^--^ : msb (1111) // ^^ : prefix 01
// ||^---^ : lsb (0110) // ^...............^-^ : msb 0001
// ^^ : prefix (01) // ^---^ : lsb 0110
u = r.ReadUBitVar() u = r.ReadUBitVar()
assert.Equal(uint64(0xf6), u) assert.Equal(uint64(0x16), u)
// 1000 1011 1010 1101 1111 0000 0000 1101
r = NewBytesReader(badFood) r = NewBytesReader(badFood)
// 1000 1011 1010 1101 1111 0000 0000 1101 // 1000 1011 1010 1101 1111 0000 0000 1101
// ||| |^----+---^ : msb (1110 1011) // ^^
// ||^---^ : lsb (0010) r.ReadBits(2)
// ^^ : prefix (10)
// 1000 1011 1010 1101 1111 0000 0000 1101
// ^^ : prefix 10
// ^-------^ : msb 1010 1101
// ^---^ : lsb 0010
u = r.ReadUBitVar() u = r.ReadUBitVar()
assert.Equal(uint64(0xeb2), u) assert.Equal(uint64(0xad2), u)
r = NewBytesReader(eLeetBeef) // 1110 1100 0111 0000 1100 0000 0000 0001 1110 0010
r.ReadBits(4) r = NewBytesReader(ectoCooler)
// 0000 1110 0001 1110 1110 0111 1011 1110 1110 1111
// ||| |^----+----+----+----+----+----+---^ : msb (0111 1011 1001 1110 // 1110 1100 0111 0000 1100 0000 0000 0001 1110 0010
// ||| | 1111 1011 1011) // ^^
// ||^---^ : lsb (1000) r.ReadBits(2)
// ^^ : prefix (11)
// 1110 1100 0111 0000 1100 0000 0000 0001 1110 0010
// ^^ : prefix 11
// ^--^ : msb 0010
// ^-------^ : 0000 0001
// ^-------^ : 1110 0000
// ^-------^ : 0111 0000
// ^---^ : lsb 1011
// data bits:
// 0010 0000 0001 1110 0000 0111 0000 1011
u = r.ReadUBitVar() u = r.ReadUBitVar()
assert.Equal(uint64(0x7b9efbb8), u) assert.Equal(uint64(0x201c070b), u)
} }
func TestVarInt(t *testing.T) { func TestVarInt(t *testing.T) {
@ -139,7 +166,7 @@ func TestVarInt(t *testing.T) {
r = NewBytesReader(badFood) r = NewBytesReader(badFood)
r.ReadBits(24) r.ReadBits(24)
// 1000 1011 1010 1101 1111 0000 0000 1101 // 1000 1011 1010 1101 1111 0000 0000 1101
// |^------^ : data // ^------^ : data
// ^ : stop // ^ : stop
u = r.ReadVarInt() u = r.ReadVarInt()
assert.Equal(uint64(0xd), u) assert.Equal(uint64(0xd), u)
@ -147,9 +174,9 @@ func TestVarInt(t *testing.T) {
r = NewBytesReader(badFood) r = NewBytesReader(badFood)
r.ReadBits(16) r.ReadBits(16)
// 1000 1011 1010 1101 1111 0000 0000 1101 // 1000 1011 1010 1101 1111 0000 0000 1101
// || | |^------^ : msb // ^------^ : msb
// || | ^ : stop // ^ : stop
// |^------^ : lsb // ^------^ : lsb
// ^ : continue // ^ : continue
// data bits: // data bits:
// 0000 0110 1111 0000 // 0000 0110 1111 0000
@ -159,13 +186,13 @@ func TestVarInt(t *testing.T) {
r = NewBytesReader(badFood) r = NewBytesReader(badFood)
// 1000 1011 1010 1101 1111 0000 0000 1101 // 1000 1011 1010 1101 1111 0000 0000 1101
// || | || | || | |^------^ : msb (000 1101) // ^------^ : msb 000 1101
// || | || | || | ^ : stop // ^ : stop
// || | || | |^------^ : data (111 0000) // ^------^ : data 111 0000
// || | || | ^ : continue // ^ : continue
// || | |^------^ : data (010 1101) // ^------^ : data 010 1101
// || | ^ : continue // ^ : continue
// |^------^ : lsb (000 1011) // ^------^ : lsb 000 1011
// ^ : continue // ^ : continue
// data bits: // data bits:
// 0001 1011 1100 0001 0110 1000 1011 // 0001 1011 1100 0001 0110 1000 1011

6
glide.lock generated

@ -1,5 +1,5 @@
hash: 3f7fbcf64c0749e5f78dc8188c594871ab368257d8a05f238cb2ff901d76f8f8 hash: c605c7633cdbedcf0368949ea8ca09a624ed544c8f66d64b516c2cec557c1de6
updated: 2016-08-01T20:29:43.617478897-04:00 updated: 2016-08-02T09:04:53.517211263-04:00
imports: imports:
- name: github.com/golang/protobuf - name: github.com/golang/protobuf
version: c3cefd437628a0b7d31b34fe44b3a7a540e98527 version: c3cefd437628a0b7d31b34fe44b3a7a540e98527
@ -9,7 +9,7 @@ imports:
- name: github.com/golang/snappy - name: github.com/golang/snappy
version: d9eb7a3d35ec988b8585d4a0068e462c27d28380 version: d9eb7a3d35ec988b8585d4a0068e462c27d28380
- name: github.com/stretchr/testify - name: github.com/stretchr/testify
version: f390dcf405f7b83c997eac1b06768bb9f44dec18 version: d77da356e56a7428ad25149ca77381849a6a5232
subpackages: subpackages:
- assert - assert
testImports: testImports:

@ -3,4 +3,3 @@ import:
- package: github.com/golang/protobuf - package: github.com/golang/protobuf
- package: github.com/golang/snappy - package: github.com/golang/snappy
- package: github.com/stretchr/testify - package: github.com/stretchr/testify
version: ^1.1.3

@ -5,6 +5,7 @@ import (
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
"github.com/golang/snappy" "github.com/golang/snappy"
"github.com/jordanorelli/hyperstone/bit"
"github.com/jordanorelli/hyperstone/dota" "github.com/jordanorelli/hyperstone/dota"
) )
@ -22,6 +23,19 @@ func (m message) String() string {
return fmt.Sprintf("{cmd: %v tick: %v compressed: %t size: %d body: %q}", m.cmd, m.tick, m.compressed, len(m.body), m.body) return fmt.Sprintf("{cmd: %v tick: %v compressed: %t size: %d body: %q}", m.cmd, m.tick, m.compressed, len(m.body), m.body)
} }
type entity struct {
t uint32
size uint32
body []byte
}
func (e entity) String() string {
if len(e.body) < 32 {
return fmt.Sprintf("{%v %v %x}", e.t, e.size, e.body)
}
return fmt.Sprintf("{%v %v %x...}", e.t, e.size, e.body[:32])
}
func (m *message) check(dump bool) error { func (m *message) check(dump bool) error {
if m.cmd != dota.EDemoCommands_DEM_Packet { if m.cmd != dota.EDemoCommands_DEM_Packet {
return fmt.Errorf("wrong command type in openPacket: %v", m.cmd) return fmt.Errorf("wrong command type in openPacket: %v", m.cmd)
@ -42,7 +56,18 @@ func (m *message) check(dump bool) error {
} }
if dump { if dump {
fmt.Println("I broke packet dumping.") br := bit.NewBytesReader(packet.GetData())
for {
t := br.ReadUBitVar()
s := br.ReadVarInt()
b := make([]byte, s)
br.Read(b)
if br.Err() != nil {
break
}
e := entity{t: uint32(t), size: uint32(s), body: b}
fmt.Printf("\t%v\n", e)
}
} }
return nil return nil
} }

Loading…
Cancel
Save