package httphead

import (
	
	
)

// Option represents a header option.
type Option struct {
	Name       []byte
	Parameters Parameters
}

// Size returns number of bytes need to be allocated for use in opt.Copy.
func ( Option) () int {
	return len(.Name) + .Parameters.bytes
}

// Copy copies all underlying []byte slices into p and returns new Option.
// Note that p must be at least of opt.Size() length.
func ( Option) ( []byte) Option {
	 := copy(, .Name)
	.Name = [:]
	.Parameters,  = .Parameters.Copy([:])
	return 
}

// Clone is a shorthand for making slice of opt.Size() sequenced with Copy()
// call.
func ( Option) () Option {
	return .Copy(make([]byte, .Size()))
}

// String represents option as a string.
func ( Option) () string {
	return "{" + string(.Name) + " " + .Parameters.String() + "}"
}

// NewOption creates named option with given parameters.
func ( string,  map[string]string) Option {
	 := Parameters{}
	for ,  := range  {
		.Set([]byte(), []byte())
	}
	return Option{
		Name:       []byte(),
		Parameters: ,
	}
}

// Equal reports whether option is equal to b.
func ( Option) ( Option) bool {
	if bytes.Equal(.Name, .Name) {
		return .Parameters.Equal(.Parameters)
	}
	return false
}

// Parameters represents option's parameters.
type Parameters struct {
	pos   int
	bytes int
	arr   [8]pair
	dyn   []pair
}

// Equal reports whether a equal to b.
func ( Parameters) ( Parameters) bool {
	switch {
	case .dyn == nil && .dyn == nil:
	case .dyn != nil && .dyn != nil:
	default:
		return false
	}

	,  := .data(), .data()
	if len() != len() {
		return false
	}

	sort.Sort(pairs())
	sort.Sort(pairs())

	for  := 0;  < len(); ++ {
		,  := [], []
		if !bytes.Equal(.key, .key) || !bytes.Equal(.value, .value) {
			return false
		}
	}
	return true
}

// Size returns number of bytes that needed to copy p.
func ( *Parameters) () int {
	return .bytes
}

// Copy copies all underlying []byte slices into dst and returns new
// Parameters.
// Note that dst must be at least of p.Size() length.
func ( *Parameters) ( []byte) (Parameters, []byte) {
	 := Parameters{
		pos:   .pos,
		bytes: .bytes,
	}
	if .dyn != nil {
		.dyn = make([]pair, len(.dyn))
		for ,  := range .dyn {
			.dyn[],  = .copy()
		}
	} else {
		for ,  := range .arr {
			.arr[],  = .copy()
		}
	}
	return , 
}

// Get returns value by key and flag about existence such value.
func ( *Parameters) ( string) ( []byte,  bool) {
	for ,  := range .data() {
		if string(.key) ==  {
			return .value, true
		}
	}
	return nil, false
}

// Set sets value by key.
func ( *Parameters) (,  []byte) {
	.bytes += len() + len()

	if .pos < len(.arr) {
		.arr[.pos] = pair{, }
		.pos++
		return
	}

	if .dyn == nil {
		.dyn = make([]pair, len(.arr), len(.arr)+1)
		copy(.dyn, .arr[:])
	}
	.dyn = append(.dyn, pair{, })
}

// ForEach iterates over parameters key-value pairs and calls cb for each one.
func ( *Parameters) ( func(,  []byte) bool) {
	for ,  := range .data() {
		if !(.key, .value) {
			break
		}
	}
}

// String represents parameters as a string.
func ( *Parameters) () ( string) {
	 = "["
	for ,  := range .data() {
		if  > 0 {
			 += " "
		}
		 += string(.key) + ":" + string(.value)
	}
	return  + "]"
}

func ( *Parameters) () []pair {
	if .dyn != nil {
		return .dyn
	}
	return .arr[:.pos]
}

type pair struct {
	key, value []byte
}

func ( pair) ( []byte) (pair, []byte) {
	 := copy(, .key)
	.key = [:]
	 :=  + copy([:], .value)
	.value = [:]

	 = [:]

	return , 
}

type pairs []pair

func ( pairs) () int           { return len() }
func ( pairs) (,  int) bool { return bytes.Compare([].key, [].key) == -1 }
func ( pairs) (,  int)      { [], [] = [], [] }