Scott Baker | ed4efab | 2020-01-13 19:12:25 -0800 | [diff] [blame] | 1 | package ndr |
| 2 | |
| 3 | import ( |
| 4 | "bytes" |
| 5 | "encoding/binary" |
| 6 | "math" |
| 7 | ) |
| 8 | |
| 9 | // Byte sizes of primitive types |
| 10 | const ( |
| 11 | SizeBool = 1 |
| 12 | SizeChar = 1 |
| 13 | SizeUint8 = 1 |
| 14 | SizeUint16 = 2 |
| 15 | SizeUint32 = 4 |
| 16 | SizeUint64 = 8 |
| 17 | SizeEnum = 2 |
| 18 | SizeSingle = 4 |
| 19 | SizeDouble = 8 |
| 20 | SizePtr = 4 |
| 21 | ) |
| 22 | |
| 23 | // Bool is an NDR Boolean which is a logical quantity that assumes one of two values: TRUE or FALSE. |
| 24 | // NDR represents a Boolean as one octet. |
| 25 | // It represents a value of FALSE as a zero octet, an octet in which every bit is reset. |
| 26 | // It represents a value of TRUE as a non-zero octet, an octet in which one or more bits are set. |
| 27 | |
| 28 | // Char is an NDR character. |
| 29 | // NDR represents a character as one octet. |
| 30 | // Characters have two representation formats: ASCII and EBCDIC. |
| 31 | |
| 32 | // USmall is an unsigned 8 bit integer |
| 33 | |
| 34 | // UShort is an unsigned 16 bit integer |
| 35 | |
| 36 | // ULong is an unsigned 32 bit integer |
| 37 | |
| 38 | // UHyper is an unsigned 64 bit integer |
| 39 | |
| 40 | // Small is an signed 8 bit integer |
| 41 | |
| 42 | // Short is an signed 16 bit integer |
| 43 | |
| 44 | // Long is an signed 32 bit integer |
| 45 | |
| 46 | // Hyper is an signed 64 bit integer |
| 47 | |
| 48 | // Enum is the NDR representation of enumerated types as signed short integers (2 octets) |
| 49 | |
| 50 | // Single is an NDR defined single-precision floating-point data type |
| 51 | |
| 52 | // Double is an NDR defined double-precision floating-point data type |
| 53 | |
| 54 | // readBool reads a byte representing a boolean. |
| 55 | // NDR represents a Boolean as one octet. |
| 56 | // It represents a value of FALSE as a zero octet, an octet in which every bit is reset. |
| 57 | // It represents a value of TRUE as a non-zero octet, an octet in which one or more bits are set. |
| 58 | func (dec *Decoder) readBool() (bool, error) { |
| 59 | i, err := dec.readUint8() |
| 60 | if err != nil { |
| 61 | return false, err |
| 62 | } |
| 63 | if i != 0 { |
| 64 | return true, nil |
| 65 | } |
| 66 | return false, nil |
| 67 | } |
| 68 | |
| 69 | // readChar reads bytes representing a 8bit ASCII integer cast to a rune. |
| 70 | func (dec *Decoder) readChar() (rune, error) { |
| 71 | var r rune |
| 72 | a, err := dec.readUint8() |
| 73 | if err != nil { |
| 74 | return r, err |
| 75 | } |
| 76 | return rune(a), nil |
| 77 | } |
| 78 | |
| 79 | // readUint8 reads bytes representing a 8bit unsigned integer. |
| 80 | func (dec *Decoder) readUint8() (uint8, error) { |
| 81 | b, err := dec.r.ReadByte() |
| 82 | if err != nil { |
| 83 | return uint8(0), err |
| 84 | } |
| 85 | return uint8(b), nil |
| 86 | } |
| 87 | |
| 88 | // readUint16 reads bytes representing a 16bit unsigned integer. |
| 89 | func (dec *Decoder) readUint16() (uint16, error) { |
| 90 | dec.ensureAlignment(SizeUint16) |
| 91 | b, err := dec.readBytes(SizeUint16) |
| 92 | if err != nil { |
| 93 | return uint16(0), err |
| 94 | } |
| 95 | return dec.ch.Endianness.Uint16(b), nil |
| 96 | } |
| 97 | |
| 98 | // readUint32 reads bytes representing a 32bit unsigned integer. |
| 99 | func (dec *Decoder) readUint32() (uint32, error) { |
| 100 | dec.ensureAlignment(SizeUint32) |
| 101 | b, err := dec.readBytes(SizeUint32) |
| 102 | if err != nil { |
| 103 | return uint32(0), err |
| 104 | } |
| 105 | return dec.ch.Endianness.Uint32(b), nil |
| 106 | } |
| 107 | |
| 108 | // readUint32 reads bytes representing a 32bit unsigned integer. |
| 109 | func (dec *Decoder) readUint64() (uint64, error) { |
| 110 | dec.ensureAlignment(SizeUint64) |
| 111 | b, err := dec.readBytes(SizeUint64) |
| 112 | if err != nil { |
| 113 | return uint64(0), err |
| 114 | } |
| 115 | return dec.ch.Endianness.Uint64(b), nil |
| 116 | } |
| 117 | |
| 118 | func (dec *Decoder) readInt8() (int8, error) { |
| 119 | dec.ensureAlignment(SizeUint8) |
| 120 | b, err := dec.readBytes(SizeUint8) |
| 121 | if err != nil { |
| 122 | return 0, err |
| 123 | } |
| 124 | var i int8 |
| 125 | buf := bytes.NewReader(b) |
| 126 | err = binary.Read(buf, dec.ch.Endianness, &i) |
| 127 | if err != nil { |
| 128 | return 0, err |
| 129 | } |
| 130 | return i, nil |
| 131 | } |
| 132 | |
| 133 | func (dec *Decoder) readInt16() (int16, error) { |
| 134 | dec.ensureAlignment(SizeUint16) |
| 135 | b, err := dec.readBytes(SizeUint16) |
| 136 | if err != nil { |
| 137 | return 0, err |
| 138 | } |
| 139 | var i int16 |
| 140 | buf := bytes.NewReader(b) |
| 141 | err = binary.Read(buf, dec.ch.Endianness, &i) |
| 142 | if err != nil { |
| 143 | return 0, err |
| 144 | } |
| 145 | return i, nil |
| 146 | } |
| 147 | |
| 148 | func (dec *Decoder) readInt32() (int32, error) { |
| 149 | dec.ensureAlignment(SizeUint32) |
| 150 | b, err := dec.readBytes(SizeUint32) |
| 151 | if err != nil { |
| 152 | return 0, err |
| 153 | } |
| 154 | var i int32 |
| 155 | buf := bytes.NewReader(b) |
| 156 | err = binary.Read(buf, dec.ch.Endianness, &i) |
| 157 | if err != nil { |
| 158 | return 0, err |
| 159 | } |
| 160 | return i, nil |
| 161 | } |
| 162 | |
| 163 | func (dec *Decoder) readInt64() (int64, error) { |
| 164 | dec.ensureAlignment(SizeUint64) |
| 165 | b, err := dec.readBytes(SizeUint64) |
| 166 | if err != nil { |
| 167 | return 0, err |
| 168 | } |
| 169 | var i int64 |
| 170 | buf := bytes.NewReader(b) |
| 171 | err = binary.Read(buf, dec.ch.Endianness, &i) |
| 172 | if err != nil { |
| 173 | return 0, err |
| 174 | } |
| 175 | return i, nil |
| 176 | } |
| 177 | |
| 178 | // https://en.wikipedia.org/wiki/IEEE_754-1985 |
| 179 | func (dec *Decoder) readFloat32() (f float32, err error) { |
| 180 | dec.ensureAlignment(SizeSingle) |
| 181 | b, err := dec.readBytes(SizeSingle) |
| 182 | if err != nil { |
| 183 | return |
| 184 | } |
| 185 | bits := dec.ch.Endianness.Uint32(b) |
| 186 | f = math.Float32frombits(bits) |
| 187 | return |
| 188 | } |
| 189 | |
| 190 | func (dec *Decoder) readFloat64() (f float64, err error) { |
| 191 | dec.ensureAlignment(SizeDouble) |
| 192 | b, err := dec.readBytes(SizeDouble) |
| 193 | if err != nil { |
| 194 | return |
| 195 | } |
| 196 | bits := dec.ch.Endianness.Uint64(b) |
| 197 | f = math.Float64frombits(bits) |
| 198 | return |
| 199 | } |
| 200 | |
| 201 | // NDR enforces NDR alignment of primitive data; that is, any primitive of size n octets is aligned at a octet stream |
| 202 | // index that is a multiple of n. (In this version of NDR, n is one of {1, 2, 4, 8}.) An octet stream index indicates |
| 203 | // the number of an octet in an octet stream when octets are numbered, beginning with 0, from the first octet in the |
| 204 | // stream. Where necessary, an alignment gap, consisting of octets of unspecified value, precedes the representation |
| 205 | // of a primitive. The gap is of the smallest size sufficient to align the primitive. |
| 206 | func (dec *Decoder) ensureAlignment(n int) { |
| 207 | p := dec.size - dec.r.Buffered() |
| 208 | if s := p % n; s != 0 { |
| 209 | dec.r.Discard(n - s) |
| 210 | } |
| 211 | } |