github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/encoding/gob/encoder.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package gob 6 7 import ( 8 "bytes" 9 "io" 10 "reflect" 11 "sync" 12 ) 13 14 // An Encoder manages the transmission of type and data information to the 15 // other side of a connection. 16 type Encoder struct { 17 mutex sync.Mutex // each item must be sent atomically 18 w []io.Writer // where to send the data 19 sent map[reflect.Type]typeId // which types we've already sent 20 countState *encoderState // stage for writing counts 21 freeList *encoderState // list of free encoderStates; avoids reallocation 22 byteBuf bytes.Buffer // buffer for top-level encoderState 23 err error 24 } 25 26 // Before we encode a message, we reserve space at the head of the 27 // buffer in which to encode its length. This means we can use the 28 // buffer to assemble the message without another allocation. 29 const maxLength = 9 // Maximum size of an encoded length. 30 var spaceForLength = make([]byte, maxLength) 31 32 // NewEncoder returns a new encoder that will transmit on the io.Writer. 33 func NewEncoder(w io.Writer) *Encoder { 34 enc := new(Encoder) 35 enc.w = []io.Writer{w} 36 enc.sent = make(map[reflect.Type]typeId) 37 enc.countState = enc.newEncoderState(new(bytes.Buffer)) 38 return enc 39 } 40 41 // writer() returns the innermost writer the encoder is using 42 func (enc *Encoder) writer() io.Writer { 43 return enc.w[len(enc.w)-1] 44 } 45 46 // pushWriter adds a writer to the encoder. 47 func (enc *Encoder) pushWriter(w io.Writer) { 48 enc.w = append(enc.w, w) 49 } 50 51 // popWriter pops the innermost writer. 52 func (enc *Encoder) popWriter() { 53 enc.w = enc.w[0 : len(enc.w)-1] 54 } 55 56 func (enc *Encoder) setError(err error) { 57 if enc.err == nil { // remember the first. 58 enc.err = err 59 } 60 } 61 62 // writeMessage sends the data item preceded by a unsigned count of its length. 63 func (enc *Encoder) writeMessage(w io.Writer, b *bytes.Buffer) { 64 // Space has been reserved for the length at the head of the message. 65 // This is a little dirty: we grab the slice from the bytes.Buffer and massage 66 // it by hand. 67 message := b.Bytes() 68 messageLen := len(message) - maxLength 69 // Encode the length. 70 enc.countState.b.Reset() 71 enc.countState.encodeUint(uint64(messageLen)) 72 // Copy the length to be a prefix of the message. 73 offset := maxLength - enc.countState.b.Len() 74 copy(message[offset:], enc.countState.b.Bytes()) 75 // Write the data. 76 _, err := w.Write(message[offset:]) 77 // Drain the buffer and restore the space at the front for the count of the next message. 78 b.Reset() 79 b.Write(spaceForLength) 80 if err != nil { 81 enc.setError(err) 82 } 83 } 84 85 // sendActualType sends the requested type, without further investigation, unless 86 // it's been sent before. 87 func (enc *Encoder) sendActualType(w io.Writer, state *encoderState, ut *userTypeInfo, actual reflect.Type) (sent bool) { 88 if _, alreadySent := enc.sent[actual]; alreadySent { 89 return false 90 } 91 typeLock.Lock() 92 info, err := getTypeInfo(ut) 93 typeLock.Unlock() 94 if err != nil { 95 enc.setError(err) 96 return 97 } 98 // Send the pair (-id, type) 99 // Id: 100 state.encodeInt(-int64(info.id)) 101 // Type: 102 enc.encode(state.b, reflect.ValueOf(info.wire), wireTypeUserInfo) 103 enc.writeMessage(w, state.b) 104 if enc.err != nil { 105 return 106 } 107 108 // Remember we've sent this type, both what the user gave us and the base type. 109 enc.sent[ut.base] = info.id 110 if ut.user != ut.base { 111 enc.sent[ut.user] = info.id 112 } 113 // Now send the inner types 114 switch st := actual; st.Kind() { 115 case reflect.Struct: 116 for i := 0; i < st.NumField(); i++ { 117 if isExported(st.Field(i).Name) { 118 enc.sendType(w, state, st.Field(i).Type) 119 } 120 } 121 case reflect.Array, reflect.Slice: 122 enc.sendType(w, state, st.Elem()) 123 case reflect.Map: 124 enc.sendType(w, state, st.Key()) 125 enc.sendType(w, state, st.Elem()) 126 } 127 return true 128 } 129 130 // sendType sends the type info to the other side, if necessary. 131 func (enc *Encoder) sendType(w io.Writer, state *encoderState, origt reflect.Type) (sent bool) { 132 ut := userType(origt) 133 if ut.externalEnc != 0 { 134 // The rules are different: regardless of the underlying type's representation, 135 // we need to tell the other side that the base type is a GobEncoder. 136 return enc.sendActualType(w, state, ut, ut.base) 137 } 138 139 // It's a concrete value, so drill down to the base type. 140 switch rt := ut.base; rt.Kind() { 141 default: 142 // Basic types and interfaces do not need to be described. 143 return 144 case reflect.Slice: 145 // If it's []uint8, don't send; it's considered basic. 146 if rt.Elem().Kind() == reflect.Uint8 { 147 return 148 } 149 // Otherwise we do send. 150 break 151 case reflect.Array: 152 // arrays must be sent so we know their lengths and element types. 153 break 154 case reflect.Map: 155 // maps must be sent so we know their lengths and key/value types. 156 break 157 case reflect.Struct: 158 // structs must be sent so we know their fields. 159 break 160 case reflect.Chan, reflect.Func: 161 // If we get here, it's a field of a struct; ignore it. 162 return 163 } 164 165 return enc.sendActualType(w, state, ut, ut.base) 166 } 167 168 // Encode transmits the data item represented by the empty interface value, 169 // guaranteeing that all necessary type information has been transmitted first. 170 func (enc *Encoder) Encode(e interface{}) error { 171 return enc.EncodeValue(reflect.ValueOf(e)) 172 } 173 174 // sendTypeDescriptor makes sure the remote side knows about this type. 175 // It will send a descriptor if this is the first time the type has been 176 // sent. 177 func (enc *Encoder) sendTypeDescriptor(w io.Writer, state *encoderState, ut *userTypeInfo) { 178 // Make sure the type is known to the other side. 179 // First, have we already sent this type? 180 rt := ut.base 181 if ut.externalEnc != 0 { 182 rt = ut.user 183 } 184 if _, alreadySent := enc.sent[rt]; !alreadySent { 185 // No, so send it. 186 sent := enc.sendType(w, state, rt) 187 if enc.err != nil { 188 return 189 } 190 // If the type info has still not been transmitted, it means we have 191 // a singleton basic type (int, []byte etc.) at top level. We don't 192 // need to send the type info but we do need to update enc.sent. 193 if !sent { 194 typeLock.Lock() 195 info, err := getTypeInfo(ut) 196 typeLock.Unlock() 197 if err != nil { 198 enc.setError(err) 199 return 200 } 201 enc.sent[rt] = info.id 202 } 203 } 204 } 205 206 // sendTypeId sends the id, which must have already been defined. 207 func (enc *Encoder) sendTypeId(state *encoderState, ut *userTypeInfo) { 208 // Identify the type of this top-level value. 209 state.encodeInt(int64(enc.sent[ut.base])) 210 } 211 212 // EncodeValue transmits the data item represented by the reflection value, 213 // guaranteeing that all necessary type information has been transmitted first. 214 func (enc *Encoder) EncodeValue(value reflect.Value) error { 215 // Gobs contain values. They cannot represent nil pointers, which 216 // have no value to encode. 217 if value.Kind() == reflect.Ptr && value.IsNil() { 218 panic("gob: cannot encode nil pointer of type " + value.Type().String()) 219 } 220 221 // Make sure we're single-threaded through here, so multiple 222 // goroutines can share an encoder. 223 enc.mutex.Lock() 224 defer enc.mutex.Unlock() 225 226 // Remove any nested writers remaining due to previous errors. 227 enc.w = enc.w[0:1] 228 229 ut, err := validUserType(value.Type()) 230 if err != nil { 231 return err 232 } 233 234 enc.err = nil 235 enc.byteBuf.Reset() 236 enc.byteBuf.Write(spaceForLength) 237 state := enc.newEncoderState(&enc.byteBuf) 238 239 enc.sendTypeDescriptor(enc.writer(), state, ut) 240 enc.sendTypeId(state, ut) 241 if enc.err != nil { 242 return enc.err 243 } 244 245 // Encode the object. 246 enc.encode(state.b, value, ut) 247 if enc.err == nil { 248 enc.writeMessage(enc.writer(), state.b) 249 } 250 251 enc.freeEncoderState(state) 252 return enc.err 253 }