// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gob

import (
	
	
	
	
)

// An Encoder manages the transmission of type and data information to the
// other side of a connection.  It is safe for concurrent use by multiple
// goroutines.
type Encoder struct {
	mutex      sync.Mutex              // each item must be sent atomically
	w          []io.Writer             // where to send the data
	sent       map[reflect.Type]typeId // which types we've already sent
	countState *encoderState           // stage for writing counts
	freeList   *encoderState           // list of free encoderStates; avoids reallocation
	byteBuf    encBuffer               // buffer for top-level encoderState
	err        error
}

// Before we encode a message, we reserve space at the head of the
// buffer in which to encode its length. This means we can use the
// buffer to assemble the message without another allocation.
const maxLength = 9 // Maximum size of an encoded length.
var spaceForLength = make([]byte, maxLength)

// NewEncoder returns a new encoder that will transmit on the [io.Writer].
func ( io.Writer) *Encoder {
	 := new(Encoder)
	.w = []io.Writer{}
	.sent = make(map[reflect.Type]typeId)
	.countState = .newEncoderState(new(encBuffer))
	return 
}

// writer returns the innermost writer the encoder is using.
func ( *Encoder) () io.Writer {
	return .w[len(.w)-1]
}

// pushWriter adds a writer to the encoder.
func ( *Encoder) ( io.Writer) {
	.w = append(.w, )
}

// popWriter pops the innermost writer.
func ( *Encoder) () {
	.w = .w[0 : len(.w)-1]
}

func ( *Encoder) ( error) {
	if .err == nil { // remember the first.
		.err = 
	}
}

// writeMessage sends the data item preceded by an unsigned count of its length.
func ( *Encoder) ( io.Writer,  *encBuffer) {
	// Space has been reserved for the length at the head of the message.
	// This is a little dirty: we grab the slice from the bytes.Buffer and massage
	// it by hand.
	 := .Bytes()
	 := len() - maxLength
	// Length cannot be bigger than the decoder can handle.
	if  >= tooBig {
		.setError(errors.New("gob: encoder: message too big"))
		return
	}
	// Encode the length.
	.countState.b.Reset()
	.countState.encodeUint(uint64())
	// Copy the length to be a prefix of the message.
	 := maxLength - .countState.b.Len()
	copy([:], .countState.b.Bytes())
	// Write the data.
	,  := .Write([:])
	// Drain the buffer and restore the space at the front for the count of the next message.
	.Reset()
	.Write(spaceForLength)
	if  != nil {
		.setError()
	}
}

// sendActualType sends the requested type, without further investigation, unless
// it's been sent before.
func ( *Encoder) ( io.Writer,  *encoderState,  *userTypeInfo,  reflect.Type) ( bool) {
	if ,  := .sent[];  {
		return false
	}
	,  := getTypeInfo()
	if  != nil {
		.setError()
		return
	}
	// Send the pair (-id, type)
	// Id:
	.encodeInt(-int64(.id))
	// Type:
	.encode(.b, reflect.ValueOf(.wire), wireTypeUserInfo)
	.writeMessage(, .b)
	if .err != nil {
		return
	}

	// Remember we've sent this type, both what the user gave us and the base type.
	.sent[.base] = .id
	if .user != .base {
		.sent[.user] = .id
	}
	// Now send the inner types
	switch  := ; .Kind() {
	case reflect.Struct:
		for  := 0;  < .NumField(); ++ {
			if isExported(.Field().Name) {
				.sendType(, , .Field().Type)
			}
		}
	case reflect.Array, reflect.Slice:
		.sendType(, , .Elem())
	case reflect.Map:
		.sendType(, , .Key())
		.sendType(, , .Elem())
	}
	return true
}

// sendType sends the type info to the other side, if necessary.
func ( *Encoder) ( io.Writer,  *encoderState,  reflect.Type) ( bool) {
	 := userType()
	if .externalEnc != 0 {
		// The rules are different: regardless of the underlying type's representation,
		// we need to tell the other side that the base type is a GobEncoder.
		return .sendActualType(, , , .base)
	}

	// It's a concrete value, so drill down to the base type.
	switch  := .base; .Kind() {
	default:
		// Basic types and interfaces do not need to be described.
		return
	case reflect.Slice:
		// If it's []uint8, don't send; it's considered basic.
		if .Elem().Kind() == reflect.Uint8 {
			return
		}
		// Otherwise we do send.
		break
	case reflect.Array:
		// arrays must be sent so we know their lengths and element types.
		break
	case reflect.Map:
		// maps must be sent so we know their lengths and key/value types.
		break
	case reflect.Struct:
		// structs must be sent so we know their fields.
		break
	case reflect.Chan, reflect.Func:
		// If we get here, it's a field of a struct; ignore it.
		return
	}

	return .sendActualType(, , , .base)
}

// Encode transmits the data item represented by the empty interface value,
// guaranteeing that all necessary type information has been transmitted first.
// Passing a nil pointer to Encoder will panic, as they cannot be transmitted by gob.
func ( *Encoder) ( any) error {
	return .EncodeValue(reflect.ValueOf())
}

// sendTypeDescriptor makes sure the remote side knows about this type.
// It will send a descriptor if this is the first time the type has been
// sent.
func ( *Encoder) ( io.Writer,  *encoderState,  *userTypeInfo) {
	// Make sure the type is known to the other side.
	// First, have we already sent this type?
	 := .base
	if .externalEnc != 0 {
		 = .user
	}
	if ,  := .sent[]; ! {
		// No, so send it.
		 := .sendType(, , )
		if .err != nil {
			return
		}
		// If the type info has still not been transmitted, it means we have
		// a singleton basic type (int, []byte etc.) at top level. We don't
		// need to send the type info but we do need to update enc.sent.
		if ! {
			,  := getTypeInfo()
			if  != nil {
				.setError()
				return
			}
			.sent[] = .id
		}
	}
}

// sendTypeId sends the id, which must have already been defined.
func ( *Encoder) ( *encoderState,  *userTypeInfo) {
	// Identify the type of this top-level value.
	.encodeInt(int64(.sent[.base]))
}

// EncodeValue transmits the data item represented by the reflection value,
// guaranteeing that all necessary type information has been transmitted first.
// Passing a nil pointer to EncodeValue will panic, as they cannot be transmitted by gob.
func ( *Encoder) ( reflect.Value) error {
	if .Kind() == reflect.Invalid {
		return errors.New("gob: cannot encode nil value")
	}
	if .Kind() == reflect.Pointer && .IsNil() {
		panic("gob: cannot encode nil pointer of type " + .Type().String())
	}

	// Make sure we're single-threaded through here, so multiple
	// goroutines can share an encoder.
	.mutex.Lock()
	defer .mutex.Unlock()

	// Remove any nested writers remaining due to previous errors.
	.w = .w[0:1]

	,  := validUserType(.Type())
	if  != nil {
		return 
	}

	.err = nil
	.byteBuf.Reset()
	.byteBuf.Write(spaceForLength)
	 := .newEncoderState(&.byteBuf)

	.sendTypeDescriptor(.writer(), , )
	.sendTypeId(, )
	if .err != nil {
		return .err
	}

	// Encode the object.
	.encode(.b, , )
	if .err == nil {
		.writeMessage(.writer(), .b)
	}

	.freeEncoderState()
	return .err
}