Fix unit tests
[govpp.git] / vendor / github.com / google / gopacket / layertype.go
1 // Copyright 2012 Google, Inc. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the LICENSE file in the root of the source
5 // tree.
6
7 package gopacket
8
9 import (
10         "fmt"
11         "strconv"
12 )
13
14 // LayerType is a unique identifier for each type of layer.  This enumeration
15 // does not match with any externally available numbering scheme... it's solely
16 // usable/useful within this library as a means for requesting layer types
17 // (see Packet.Layer) and determining which types of layers have been decoded.
18 //
19 // New LayerTypes may be created by calling gopacket.RegisterLayerType.
20 type LayerType int64
21
22 // LayerTypeMetadata contains metadata associated with each LayerType.
23 type LayerTypeMetadata struct {
24         // Name is the string returned by each layer type's String method.
25         Name string
26         // Decoder is the decoder to use when the layer type is passed in as a
27         // Decoder.
28         Decoder Decoder
29 }
30
31 type layerTypeMetadata struct {
32         inUse bool
33         LayerTypeMetadata
34 }
35
36 // DecodersByLayerName maps layer names to decoders for those layers.
37 // This allows users to specify decoders by name to a program and have that
38 // program pick the correct decoder accordingly.
39 var DecodersByLayerName = map[string]Decoder{}
40
41 const maxLayerType = 2000
42
43 var ltMeta [maxLayerType]layerTypeMetadata
44 var ltMetaMap = map[LayerType]layerTypeMetadata{}
45
46 // RegisterLayerType creates a new layer type and registers it globally.
47 // The number passed in must be unique, or a runtime panic will occur.  Numbers
48 // 0-999 are reserved for the gopacket library.  Numbers 1000-1999 should be
49 // used for common application-specific types, and are very fast.  Any other
50 // number (negative or >= 2000) may be used for uncommon application-specific
51 // types, and are somewhat slower (they require a map lookup over an array
52 // index).
53 func RegisterLayerType(num int, meta LayerTypeMetadata) LayerType {
54         if 0 <= num && num < maxLayerType {
55                 if ltMeta[num].inUse {
56                         panic("Layer type already exists")
57                 }
58         } else {
59                 if ltMetaMap[LayerType(num)].inUse {
60                         panic("Layer type already exists")
61                 }
62         }
63         return OverrideLayerType(num, meta)
64 }
65
66 // OverrideLayerType acts like RegisterLayerType, except that if the layer type
67 // has already been registered, it overrides the metadata with the passed-in
68 // metadata intead of panicing.
69 func OverrideLayerType(num int, meta LayerTypeMetadata) LayerType {
70         if 0 <= num && num < maxLayerType {
71                 ltMeta[num] = layerTypeMetadata{
72                         inUse:             true,
73                         LayerTypeMetadata: meta,
74                 }
75         } else {
76                 ltMetaMap[LayerType(num)] = layerTypeMetadata{
77                         inUse:             true,
78                         LayerTypeMetadata: meta,
79                 }
80         }
81         DecodersByLayerName[meta.Name] = meta.Decoder
82         return LayerType(num)
83 }
84
85 // Decode decodes the given data using the decoder registered with the layer
86 // type.
87 func (t LayerType) Decode(data []byte, c PacketBuilder) error {
88         var d Decoder
89         if 0 <= int(t) && int(t) < maxLayerType {
90                 d = ltMeta[int(t)].Decoder
91         } else {
92                 d = ltMetaMap[t].Decoder
93         }
94         if d != nil {
95                 return d.Decode(data, c)
96         }
97         return fmt.Errorf("Layer type %v has no associated decoder", t)
98 }
99
100 // String returns the string associated with this layer type.
101 func (t LayerType) String() (s string) {
102         if 0 <= int(t) && int(t) < maxLayerType {
103                 s = ltMeta[int(t)].Name
104         } else {
105                 s = ltMetaMap[t].Name
106         }
107         if s == "" {
108                 s = strconv.Itoa(int(t))
109         }
110         return
111 }