package sshfx

import (
	
	
)

// ExtendedData aliases the untyped interface composition of encoding.BinaryMarshaler and encoding.BinaryUnmarshaler.
type ExtendedData = interface {
	encoding.BinaryMarshaler
	encoding.BinaryUnmarshaler
}

// ExtendedDataConstructor defines a function that returns a new(ArbitraryExtendedPacket).
type ExtendedDataConstructor func() ExtendedData

var extendedPacketTypes = struct {
	mu           sync.RWMutex
	constructors map[string]ExtendedDataConstructor
}{
	constructors: make(map[string]ExtendedDataConstructor),
}

// RegisterExtendedPacketType defines a specific ExtendedDataConstructor for the given extension string.
func ( string,  ExtendedDataConstructor) {
	extendedPacketTypes.mu.Lock()
	defer extendedPacketTypes.mu.Unlock()

	if ,  := extendedPacketTypes.constructors[];  {
		panic("encoding/ssh/filexfer: multiple registration of extended packet type " + )
	}

	extendedPacketTypes.constructors[] = 
}

func newExtendedPacket( string) ExtendedData {
	extendedPacketTypes.mu.RLock()
	defer extendedPacketTypes.mu.RUnlock()

	if  := extendedPacketTypes.constructors[];  != nil {
		return ()
	}

	return new(Buffer)
}

// ExtendedPacket defines the SSH_FXP_CLOSE packet.
type ExtendedPacket struct {
	ExtendedRequest string

	Data ExtendedData
}

// Type returns the SSH_FXP_xy value associated with this packet type.
func ( *ExtendedPacket) () PacketType {
	return PacketTypeExtended
}

// MarshalPacket returns p as a two-part binary encoding of p.
//
// The Data is marshaled into binary, and returned as the payload.
func ( *ExtendedPacket) ( uint32,  []byte) (,  []byte,  error) {
	 := NewBuffer()
	if .Cap() < 9 {
		 := 4 + len(.ExtendedRequest) // string(extended-request)
		 = NewMarshalBuffer()
	}

	.StartPacket(PacketTypeExtended, )
	.AppendString(.ExtendedRequest)

	if .Data != nil {
		,  = .Data.MarshalBinary()
		if  != nil {
			return nil, nil, 
		}
	}

	return .Packet()
}

// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
// It is assumed that the uint32(request-id) has already been consumed.
//
// If p.Data is nil, and the extension has been registered, a new type will be made from the registration.
// If the extension has not been registered, then a new Buffer will be allocated.
// Then the request-specific-data will be unmarshaled from the rest of the buffer.
func ( *ExtendedPacket) ( *Buffer) ( error) {
	.ExtendedRequest = .ConsumeString()
	if .Err != nil {
		return .Err
	}

	if .Data == nil {
		.Data = newExtendedPacket(.ExtendedRequest)
	}

	return .Data.UnmarshalBinary(.Bytes())
}

// ExtendedReplyPacket defines the SSH_FXP_CLOSE packet.
type ExtendedReplyPacket struct {
	Data ExtendedData
}

// Type returns the SSH_FXP_xy value associated with this packet type.
func ( *ExtendedReplyPacket) () PacketType {
	return PacketTypeExtendedReply
}

// MarshalPacket returns p as a two-part binary encoding of p.
//
// The Data is marshaled into binary, and returned as the payload.
func ( *ExtendedReplyPacket) ( uint32,  []byte) (,  []byte,  error) {
	 := NewBuffer()
	if .Cap() < 9 {
		 = NewMarshalBuffer(0)
	}

	.StartPacket(PacketTypeExtendedReply, )

	if .Data != nil {
		,  = .Data.MarshalBinary()
		if  != nil {
			return nil, nil, 
		}
	}

	return .Packet()
}

// UnmarshalPacketBody unmarshals the packet body from the given Buffer.
// It is assumed that the uint32(request-id) has already been consumed.
//
// If p.Data is nil, and there is request-specific-data,
// then the request-specific-data will be wrapped in a Buffer and assigned to p.Data.
func ( *ExtendedReplyPacket) ( *Buffer) ( error) {
	if .Data == nil {
		.Data = new(Buffer)
	}

	return .Data.UnmarshalBinary(.Bytes())
}