package runtime

import (
	
	
	

	
	
)

// MIMEWildcard is the fallback MIME type used for requests which do not match
// a registered MIME type.
const MIMEWildcard = "*"

var (
	acceptHeader      = http.CanonicalHeaderKey("Accept")
	contentTypeHeader = http.CanonicalHeaderKey("Content-Type")

	defaultMarshaler = &HTTPBodyMarshaler{
		Marshaler: &JSONPb{
			MarshalOptions: protojson.MarshalOptions{
				EmitUnpopulated: true,
			},
			UnmarshalOptions: protojson.UnmarshalOptions{
				DiscardUnknown: true,
			},
		},
	}
)

// MarshalerForRequest returns the inbound/outbound marshalers for this request.
// It checks the registry on the ServeMux for the MIME type set by the Content-Type header.
// If it isn't set (or the request Content-Type is empty), checks for "*".
// If there are multiple Content-Type headers set, choose the first one that it can
// exactly match in the registry.
// Otherwise, it follows the above logic for "*"/InboundMarshaler/OutboundMarshaler.
func ( *ServeMux,  *http.Request) ( Marshaler,  Marshaler) {
	for ,  := range .Header[acceptHeader] {
		if ,  := .marshalers.mimeMap[];  {
			 = 
			break
		}
	}

	for ,  := range .Header[contentTypeHeader] {
		, ,  := mime.ParseMediaType()
		if  != nil {
			grpclog.Errorf("Failed to parse Content-Type %s: %v", , )
			continue
		}
		if ,  := .marshalers.mimeMap[];  {
			 = 
			break
		}
	}

	if  == nil {
		 = .marshalers.mimeMap[MIMEWildcard]
	}
	if  == nil {
		 = 
	}

	return , 
}

// marshalerRegistry is a mapping from MIME types to Marshalers.
type marshalerRegistry struct {
	mimeMap map[string]Marshaler
}

// add adds a marshaler for a case-sensitive MIME type string ("*" to match any
// MIME type).
func ( marshalerRegistry) ( string,  Marshaler) error {
	if len() == 0 {
		return errors.New("empty MIME type")
	}

	.mimeMap[] = 

	return nil
}

// makeMarshalerMIMERegistry returns a new registry of marshalers.
// It allows for a mapping of case-sensitive Content-Type MIME type string to runtime.Marshaler interfaces.
//
// For example, you could allow the client to specify the use of the runtime.JSONPb marshaler
// with an "application/jsonpb" Content-Type and the use of the runtime.JSONBuiltin marshaler
// with an "application/json" Content-Type.
// "*" can be used to match any Content-Type.
// This can be attached to a ServerMux with the marshaler option.
func makeMarshalerMIMERegistry() marshalerRegistry {
	return marshalerRegistry{
		mimeMap: map[string]Marshaler{
			MIMEWildcard: defaultMarshaler,
		},
	}
}

// WithMarshalerOption returns a ServeMuxOption which associates inbound and outbound
// Marshalers to a MIME type in mux.
func ( string,  Marshaler) ServeMuxOption {
	return func( *ServeMux) {
		if  := .marshalers.add(, );  != nil {
			panic()
		}
	}
}