ext.go RawHistoryFolder
1package xturbo
2
3// ExtInfo is a negotiated extension's wire opcode and event/error bases.
4type ExtInfo struct {
5 Present bool
6 Major, FirstEvent, FirstError uint8
7}
8
9// ExtTable is populated during setup. Fixed arrays avoid lookup allocations.
10// Reverse maps store ExtID+1 so the zero value means "none".
11type ExtTable struct {
12 info [extCount]ExtInfo
13 byEvent [128]uint8
14 byError [256]uint8
15 byMajor [256]uint8
16}
17
18// Set records an extension's negotiated opcodes and fills the reverse maps
19// for the event and error codes the extension declares in the pinned XML.
20func (t *ExtTable) Set(id ExtID, major, firstEvent, firstError uint8) {
21 if id == ExtCore || id >= extCount {
22 return
23 }
24 tag := uint8(id) + 1
25 for i := range t.byEvent {
26 if t.byEvent[i] == tag {
27 t.byEvent[i] = 0
28 }
29 }
30 for i := range t.byError {
31 if t.byError[i] == tag {
32 t.byError[i] = 0
33 }
34 if t.byMajor[i] == tag {
35 t.byMajor[i] = 0
36 }
37 }
38 t.info[id] = ExtInfo{true, major, firstEvent, firstError}
39 if major != 0 {
40 t.byMajor[major] = tag
41 }
42 if firstEvent != 0 {
43 for i := 0; i < int(extEvents[id]) && int(firstEvent)+i < len(t.byEvent); i++ {
44 t.byEvent[int(firstEvent)+i] = tag
45 }
46 }
47 if firstError != 0 {
48 for i := 0; i < int(extErrors[id]) && int(firstError)+i < len(t.byError); i++ {
49 t.byError[int(firstError)+i] = tag
50 }
51 }
52}
53func (t *ExtTable) Info(id ExtID) ExtInfo {
54 if id >= extCount {
55 return ExtInfo{}
56 }
57 if id == ExtCore {
58 return ExtInfo{Present: true}
59 }
60 return t.info[id]
61}
62func (t *ExtTable) Major(id ExtID) uint8 { return t.Info(id).Major }
63
64// ByEvent maps an event code (raw[0]&0x7f) to its extension and the code
65// relative to the extension's first event.
66func (t *ExtTable) ByEvent(code uint8) (id ExtID, rel uint8, ok bool) {
67 if code >= 128 || t.byEvent[code] == 0 {
68 return ExtCore, 0, false
69 }
70 id = ExtID(t.byEvent[code] - 1)
71 return id, code - t.info[id].FirstEvent, true
72}
73
74// ByError maps a wire error code to its extension and relative error code.
75func (t *ExtTable) ByError(code uint8) (id ExtID, rel uint8, ok bool) {
76 if t.byError[code] == 0 {
77 return ExtCore, 0, false
78 }
79 id = ExtID(t.byError[code] - 1)
80 return id, code - t.info[id].FirstError, true
81}
82
83// ByMajor maps a major opcode to its extension.
84func (t *ExtTable) ByMajor(major uint8) (id ExtID, ok bool) {
85 if t.byMajor[major] == 0 {
86 return ExtCore, false
87 }
88 return ExtID(t.byMajor[major] - 1), true
89}