Fix unit tests
[govpp.git] / vendor / github.com / google / gopacket / writer.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 )
12
13 // SerializableLayer allows its implementations to be written out as a set of bytes,
14 // so those bytes may be sent on the wire or otherwise used by the caller.
15 // SerializableLayer is implemented by certain Layer types, and can be encoded to
16 // bytes using the LayerWriter object.
17 type SerializableLayer interface {
18         // SerializeTo writes this layer to a slice, growing that slice if necessary
19         // to make it fit the layer's data.
20         //  Args:
21         //   b:  SerializeBuffer to write this layer on to.  When called, b.Bytes()
22         //     is the payload this layer should wrap, if any.  Note that this
23         //     layer can either prepend itself (common), append itself
24         //     (uncommon), or both (sometimes padding or footers are required at
25         //     the end of packet data). It's also possible (though probably very
26         //     rarely needed) to overwrite any bytes in the current payload.
27         //     After this call, b.Bytes() should return the byte encoding of
28         //     this layer wrapping the original b.Bytes() payload.
29         //   opts:  options to use while writing out data.
30         //  Returns:
31         //   error if a problem was encountered during encoding.  If an error is
32         //   returned, the bytes in data should be considered invalidated, and
33         //   not used.
34         //
35         // SerializeTo calls SHOULD entirely ignore LayerContents and
36         // LayerPayload.  It just serializes based on struct fields, neither
37         // modifying nor using contents/payload.
38         SerializeTo(b SerializeBuffer, opts SerializeOptions) error
39 }
40
41 // SerializeOptions provides options for behaviors that SerializableLayers may want to
42 // implement.
43 type SerializeOptions struct {
44         // FixLengths determines whether, during serialization, layers should fix
45         // the values for any length field that depends on the payload.
46         FixLengths bool
47         // ComputeChecksums determines whether, during serialization, layers
48         // should recompute checksums based on their payloads.
49         ComputeChecksums bool
50 }
51
52 // SerializeBuffer is a helper used by gopacket for writing out packet layers.
53 // SerializeBuffer starts off as an empty []byte.  Subsequent calls to PrependBytes
54 // return byte slices before the current Bytes(), AppendBytes returns byte
55 // slices after.
56 //
57 // Byte slices returned by PrependBytes/AppendBytes are NOT zero'd out, so if
58 // you want to make sure they're all zeros, set them as such.
59 //
60 // SerializeBuffer is specifically designed to handle packet writing, where unlike
61 // with normal writes it's easier to start writing at the inner-most layer and
62 // work out, meaning that we often need to prepend bytes.  This runs counter to
63 // typical writes to byte slices using append(), where we only write at the end
64 // of the buffer.
65 //
66 // It can be reused via Clear.  Note, however, that a Clear call will invalidate the
67 // byte slices returned by any previous Bytes() call (the same buffer is
68 // reused).
69 //
70 //  1) Reusing a write buffer is generally much faster than creating a new one,
71 //     and with the default implementation it avoids additional memory allocations.
72 //  2) If a byte slice from a previous Bytes() call will continue to be used,
73 //     it's better to create a new SerializeBuffer.
74 //
75 // The Clear method is specifically designed to minimize memory allocations for
76 // similar later workloads on the SerializeBuffer.  IE: if you make a set of
77 // Prepend/Append calls, then clear, then make the same calls with the same
78 // sizes, the second round (and all future similar rounds) shouldn't allocate
79 // any new memory.
80 type SerializeBuffer interface {
81         // Bytes returns the contiguous set of bytes collected so far by Prepend/Append
82         // calls.  The slice returned by Bytes will be modified by future Clear calls,
83         // so if you're planning on clearing this SerializeBuffer, you may want to copy
84         // Bytes somewhere safe first.
85         Bytes() []byte
86         // PrependBytes returns a set of bytes which prepends the current bytes in this
87         // buffer.  These bytes start in an indeterminate state, so they should be
88         // overwritten by the caller.  The caller must only call PrependBytes if they
89         // know they're going to immediately overwrite all bytes returned.
90         PrependBytes(num int) ([]byte, error)
91         // AppendBytes returns a set of bytes which appends the current bytes in this
92         // buffer.  These bytes start in an indeterminate state, so they should be
93         // overwritten by the caller.  The caller must only call AppendBytes if they
94         // know they're going to immediately overwrite all bytes returned.
95         AppendBytes(num int) ([]byte, error)
96         // Clear resets the SerializeBuffer to a new, empty buffer.  After a call to clear,
97         // the byte slice returned by any previous call to Bytes() for this buffer
98         // should be considered invalidated.
99         Clear() error
100 }
101
102 type serializeBuffer struct {
103         data                []byte
104         start               int
105         prepended, appended int
106 }
107
108 // NewSerializeBuffer creates a new instance of the default implementation of
109 // the SerializeBuffer interface.
110 func NewSerializeBuffer() SerializeBuffer {
111         return &serializeBuffer{}
112 }
113
114 // NewSerializeBufferExpectedSize creates a new buffer for serialization, optimized for an
115 // expected number of bytes prepended/appended.  This tends to decrease the
116 // number of memory allocations made by the buffer during writes.
117 func NewSerializeBufferExpectedSize(expectedPrependLength, expectedAppendLength int) SerializeBuffer {
118         return &serializeBuffer{
119                 data:      make([]byte, expectedPrependLength, expectedPrependLength+expectedAppendLength),
120                 start:     expectedPrependLength,
121                 prepended: expectedPrependLength,
122                 appended:  expectedAppendLength,
123         }
124 }
125
126 func (w *serializeBuffer) Bytes() []byte {
127         return w.data[w.start:]
128 }
129
130 func (w *serializeBuffer) PrependBytes(num int) ([]byte, error) {
131         if num < 0 {
132                 panic("num < 0")
133         }
134         if w.start < num {
135                 toPrepend := w.prepended
136                 if toPrepend < num {
137                         toPrepend = num
138                 }
139                 w.prepended += toPrepend
140                 length := cap(w.data) + toPrepend
141                 newData := make([]byte, length)
142                 newStart := w.start + toPrepend
143                 copy(newData[newStart:], w.data[w.start:])
144                 w.start = newStart
145                 w.data = newData[:toPrepend+len(w.data)]
146         }
147         w.start -= num
148         return w.data[w.start : w.start+num], nil
149 }
150
151 func (w *serializeBuffer) AppendBytes(num int) ([]byte, error) {
152         if num < 0 {
153                 panic("num < 0")
154         }
155         initialLength := len(w.data)
156         if cap(w.data)-initialLength < num {
157                 toAppend := w.appended
158                 if toAppend < num {
159                         toAppend = num
160                 }
161                 w.appended += toAppend
162                 newData := make([]byte, cap(w.data)+toAppend)
163                 copy(newData[w.start:], w.data[w.start:])
164                 w.data = newData[:initialLength]
165         }
166         // Grow the buffer.  We know it'll be under capacity given above.
167         w.data = w.data[:initialLength+num]
168         return w.data[initialLength:], nil
169 }
170
171 func (w *serializeBuffer) Clear() error {
172         w.start = w.prepended
173         w.data = w.data[:w.start]
174         return nil
175 }
176
177 // SerializeLayers clears the given write buffer, then writes all layers into it so
178 // they correctly wrap each other.  Note that by clearing the buffer, it
179 // invalidates all slices previously returned by w.Bytes()
180 //
181 // Example:
182 //   buf := gopacket.NewSerializeBuffer()
183 //   opts := gopacket.SerializeOptions{}
184 //   gopacket.SerializeLayers(buf, opts, a, b, c)
185 //   firstPayload := buf.Bytes()  // contains byte representation of a(b(c))
186 //   gopacket.SerializeLayers(buf, opts, d, e, f)
187 //   secondPayload := buf.Bytes()  // contains byte representation of d(e(f)). firstPayload is now invalidated, since the SerializeLayers call Clears buf.
188 func SerializeLayers(w SerializeBuffer, opts SerializeOptions, layers ...SerializableLayer) error {
189         w.Clear()
190         for i := len(layers) - 1; i >= 0; i-- {
191                 layer := layers[i]
192                 err := layer.SerializeTo(w, opts)
193                 if err != nil {
194                         return err
195                 }
196         }
197         return nil
198 }
199
200 // SerializePacket is a convenience function that calls SerializeLayers
201 // on packet's Layers().
202 // It returns an error if one of the packet layers is not a SerializebleLayer.
203 func SerializePacket(buf SerializeBuffer, opts SerializeOptions, packet Packet) error {
204         sls := []SerializableLayer{}
205         for _, layer := range packet.Layers() {
206                 sl, ok := layer.(SerializableLayer)
207                 if !ok {
208                         return fmt.Errorf("layer %s is not serializable", layer.LayerType().String())
209                 }
210                 sls = append(sls, sl)
211         }
212         return SerializeLayers(buf, opts, sls...)
213 }