Skip to content

Commit 493f175

Browse files
committed
Use *Protocol in Component
1 parent 55da517 commit 493f175

File tree

4 files changed

+63
-6
lines changed

4 files changed

+63
-6
lines changed

Diff for: codec.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,16 @@ func readComponent(b []byte) (int, Component, error) {
7979
if p.Code == 0 {
8080
return 0, Component{}, fmt.Errorf("no protocol with code %d", code)
8181
}
82+
pPtr := protocolPtrByCode[code]
83+
if pPtr == nil {
84+
return 0, Component{}, fmt.Errorf("no protocol with code %d", code)
85+
}
8286

8387
if p.Size == 0 {
8488
c, err := validateComponent(Component{
8589
bytes: string(b[:offset]),
8690
valueStartIdx: offset,
87-
protocol: p,
91+
protocol: pPtr,
8892
})
8993

9094
return offset, c, err
@@ -110,7 +114,7 @@ func readComponent(b []byte) (int, Component, error) {
110114

111115
c, err := validateComponent(Component{
112116
bytes: string(b[:offset+size]),
113-
protocol: p,
117+
protocol: pPtr,
114118
valueStartIdx: offset,
115119
})
116120

Diff for: component.go

+27-4
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ type Component struct {
1515
// bytes is the raw bytes of the component. It includes the protocol code as
1616
// varint, possibly the size of the value, and the value.
1717
bytes string // string for immutability.
18-
protocol Protocol
18+
protocol *Protocol
1919
valueStartIdx int // Index of the first byte of the Component's value in the bytes array
2020
}
2121

@@ -110,18 +110,27 @@ func (c Component) Compare(o Component) int {
110110
}
111111

112112
func (c Component) Protocols() []Protocol {
113-
return []Protocol{c.protocol}
113+
if c.protocol == nil {
114+
return nil
115+
}
116+
return []Protocol{*c.protocol}
114117
}
115118

116119
func (c Component) ValueForProtocol(code int) (string, error) {
120+
if c.protocol == nil {
121+
return "", fmt.Errorf("component has nil protocol")
122+
}
117123
if c.protocol.Code != code {
118124
return "", ErrProtocolNotFound
119125
}
120126
return c.Value(), nil
121127
}
122128

123129
func (c Component) Protocol() Protocol {
124-
return c.protocol
130+
if c.protocol == nil {
131+
return Protocol{}
132+
}
133+
return *c.protocol
125134
}
126135

127136
func (c Component) RawValue() []byte {
@@ -138,6 +147,9 @@ func (c Component) Value() string {
138147
}
139148

140149
func (c Component) valueAndErr() (string, error) {
150+
if c.protocol == nil {
151+
return "", fmt.Errorf("component has nil protocol")
152+
}
141153
if c.protocol.Transcoder == nil {
142154
return "", nil
143155
}
@@ -157,6 +169,9 @@ func (c Component) String() string {
157169
// writeTo is an efficient, private function for string-formatting a multiaddr.
158170
// Trust me, we tend to allocate a lot when doing this.
159171
func (c Component) writeTo(b *strings.Builder) {
172+
if c.protocol == nil {
173+
return
174+
}
160175
b.WriteByte('/')
161176
b.WriteString(c.protocol.Name)
162177
value := c.Value()
@@ -188,6 +203,11 @@ func NewComponent(protocol, value string) (Component, error) {
188203
}
189204

190205
func newComponent(protocol Protocol, bvalue []byte) (Component, error) {
206+
protocolPtr := protocolPtrByCode[protocol.Code]
207+
if protocolPtr == nil {
208+
protocolPtr = &protocol
209+
}
210+
191211
size := len(bvalue)
192212
size += len(protocol.VCode)
193213
if protocol.Size < 0 {
@@ -209,7 +229,7 @@ func newComponent(protocol Protocol, bvalue []byte) (Component, error) {
209229
return validateComponent(
210230
Component{
211231
bytes: string(maddr),
212-
protocol: protocol,
232+
protocol: protocolPtr,
213233
valueStartIdx: offset,
214234
})
215235
}
@@ -218,6 +238,9 @@ func newComponent(protocol Protocol, bvalue []byte) (Component, error) {
218238
// It ensures that we will be able to call all methods on Component without
219239
// error.
220240
func validateComponent(c Component) (Component, error) {
241+
if c.protocol == nil {
242+
return Component{}, fmt.Errorf("component is missing its protocol")
243+
}
221244
if c.valueStartIdx > len(c.bytes) {
222245
return Component{}, fmt.Errorf("component valueStartIdx is greater than the length of the component's bytes")
223246
}

Diff for: multiaddr_test.go

+26
Original file line numberDiff line numberDiff line change
@@ -1146,3 +1146,29 @@ func BenchmarkComponentValidation(b *testing.B) {
11461146
}
11471147
}
11481148
}
1149+
1150+
func FuzzComponents(f *testing.F) {
1151+
for _, v := range good {
1152+
m := StringCast(v)
1153+
for _, c := range m {
1154+
f.Add(c.Bytes())
1155+
}
1156+
}
1157+
f.Fuzz(func(t *testing.T, compBytes []byte) {
1158+
n, c, err := readComponent(compBytes)
1159+
if err != nil {
1160+
t.Skip()
1161+
}
1162+
if c.protocol == nil {
1163+
t.Fatal("component has nil protocol")
1164+
}
1165+
if c.protocol.Code == 0 {
1166+
t.Fatal("component has nil protocol code")
1167+
}
1168+
if !bytes.Equal(c.Bytes(), compBytes[:n]) {
1169+
t.Logf("component bytes: %v", c.Bytes())
1170+
t.Logf("original bytes: %v", compBytes[:n])
1171+
t.Fatal("component bytes are not equal to the original bytes")
1172+
}
1173+
})
1174+
}

Diff for: protocol.go

+4
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ type Protocol struct {
4747
var protocolsByName = map[string]Protocol{}
4848
var protocolsByCode = map[int]Protocol{}
4949

50+
// Keep a map of pointers so that we can reuse the same pointer for the same protocol.
51+
var protocolPtrByCode = map[int]*Protocol{}
52+
5053
// Protocols is the list of multiaddr protocols supported by this module.
5154
var Protocols = []Protocol{}
5255

@@ -72,6 +75,7 @@ func AddProtocol(p Protocol) error {
7275
Protocols = append(Protocols, p)
7376
protocolsByName[p.Name] = p
7477
protocolsByCode[p.Code] = p
78+
protocolPtrByCode[p.Code] = &p
7579
return nil
7680
}
7781

0 commit comments

Comments
 (0)