package zapjournal

import (
	
)

// appendVarName appends sanitized variable names to the dst and returns the
// resulting byte slice.
func ( []byte,  ...string) []byte {
	var  bool
	for ,  := range  {
		 = sanitizeVarName()
		if  == "" {
			continue
		}
		if  {
			 = append(, '_')
		}
		 = appendUpperSnakeVarName(, )
		 = true
	}
	if ! {
		 = append(, defaultPrefix...)
	}
	return 
}

// sanitizeVarName sanitizes the variable name to be a valid input for
// appendUpperSnakeVarName. It also trims characters that would be converted to
// underscore.
func ( string) string {
	// Trim invalid bytes and underscore. Check whether the trimmed string
	// has invalid characters. If so, we need to allocate a copy with these
	// characters removed.
	 := 0
	 := len()
	 := 0
	for  := 0;  < len(); ++ {
		 := []
		if isAllowedVarNameByte() {
			break
		}
		++
	}
	for  := 0;  < len(); ++ {
		 := [len()-1-]
		if isAllowedVarNameByte() {
			break
		}
		--
	}
	for  := ;  < ; ++ {
		 := []
		if shouldConvertToUnderscore() || isAllowedVarNameByte() {
			++
		}
	}
	 = [:]
	if  == len() ||  == 0 {
		return 
	}

	var  strings.Builder
	.Grow()
	for  := 0;  < len(); ++ {
		 := []
		if !shouldConvertToUnderscore() && !isAllowedVarNameByte() {
			continue
		}
		_ = .WriteByte()
	}
	return .String()
}

// isAllowedVarNameByte checks whether c is allowed variable name character
// before converting to upper case snake.
func ( byte) bool {
	switch {
	case isDigitASCII():
	case isUpperASCII():
	case isLowerASCII():
	default:
		return false
	}
	return true
}

// shouldConvertToUnderscore checks whether c should be converted to underscore.
func ( byte) bool {
	switch  {
	case '_': // underscore
	case '@': // at sign
	case '$': // dollar
	case '%': // percent
	case '#': // hash
	case ':': // colon
	case '+': // plus
	case '-': // dash
	case '.': // dot
	case ' ': // space
	default:
		return false
	}
	return true
}

// appendUpperSnakeVarName appends s in upper snake case to dst.
func ( []byte,  string) []byte {
	for  := 0;  < len(); ++ {
		 := []

		var  bool
		if  > 0 && !isDigitASCII() {
			 = isDigitASCII([-1])
		}

		switch {
		case isDigitASCII():
			// No-op.
		case isLowerASCII():
			 = lowerToUpperASCII()
		case shouldConvertToUnderscore():
			 = '_'
			for +1 < len() && shouldConvertToUnderscore([+1]) {
				++
			}
		case isUpperASCII():
			if  == 0 ||  {
				break
			}
			 := [-1]

			if isLowerASCII() {
				 = true
				break
			}

			if !isUpperASCII() {
				break
			}

			if +1 == len() {
				break
			}
			 := [+1]

			if !isLowerASCII() {
				break
			}
			 = true
		default:
			continue // unreachable
		}
		if  {
			 = append(, '_')
		}
		 = append(, )
	}
	return 
}

// isLowerASCII checks whether c is a lower case ASCII letter.
func ( byte) bool {
	return 'a' <=  &&  <= 'z'
}

// isUpperASCII checks whether c is an upper case ASCII letter.
func ( byte) bool {
	return 'A' <=  &&  <= 'Z'
}

// isDigitASCII checks whether c is an ASCII digit.
func ( byte) bool {
	return '0' <=  &&  <= '9'
}

// lowerToUpperASCII converts c to an upper case ASCII character, assuming that c is
// a lower case letter.
func ( byte) byte {
	const  = 'a' - 'A'
	return  - 
}