package goja

import (
	
	
	
	
	
	
	

	
	

	
	
)

// Represents a string imported from Go. The idea is to delay the scanning for unicode characters and converting
// to unicodeString until necessary. This way strings that are merely passed through never get scanned which
// saves CPU and memory.
// Currently, importedString is created in 2 cases: Runtime.ToValue() for strings longer than 16 bytes and as a result
// of JSON.stringify() if it may contain unicode characters. More cases could be added in the future.
type importedString struct {
	s string
	u unicodeString

	scanned bool
}

func ( *importedString) () {
	.u = unistring.Scan(.s)
	.scanned = true
}

func ( *importedString) () {
	if !.scanned {
		.scan()
	}
}

func ( *importedString) () int64 {
	.ensureScanned()
	if .u != nil {
		return 0
	}
	return asciiString(.s).ToInteger()
}

func ( *importedString) () String {
	return 
}

func ( *importedString) () unistring.String {
	.ensureScanned()
	if .u != nil {
		return unistring.FromUtf16(.u)
	}
	return unistring.String(.s)
}

func ( *importedString) () Value {
	return 
}

func ( *importedString) () string {
	return .s
}

func ( *importedString) () float64 {
	.ensureScanned()
	if .u != nil {
		return math.NaN()
	}
	return asciiString(.s).ToFloat()
}

func ( *importedString) () Value {
	.ensureScanned()
	if .u != nil {
		return .u.ToNumber()
	}
	return asciiString(.s).ToNumber()
}

func ( *importedString) () bool {
	return len(.s) != 0
}

func ( *importedString) ( *Runtime) *Object {
	return ._newString(, .getStringPrototype())
}

func ( *importedString) ( Value) bool {
	return .StrictEquals()
}

func ( *importedString) ( Value) bool {
	if .StrictEquals() {
		return true
	}
	.ensureScanned()
	if .u != nil {
		return .u.Equals()
	}
	return asciiString(.s).Equals()
}

func ( *importedString) ( Value) bool {
	switch otherStr := .(type) {
	case asciiString:
		if .u != nil {
			return false
		}
		return .s == string()
	case unicodeString:
		.ensureScanned()
		if .u != nil && .u.equals() {
			return true
		}
	case *importedString:
		return .s == .s
	}
	return false
}

func ( *importedString) () interface{} {
	return .s
}

func ( *importedString) () reflect.Type {
	return reflectTypeString
}

func ( *importedString) ( *Runtime) *Object {
	.ensureScanned()
	if .u != nil {
		return .u.baseObject()
	}
	return asciiString(.s).baseObject()
}

func ( *importedString) ( *maphash.Hash) uint64 {
	.ensureScanned()
	if .u != nil {
		return .u.hash()
	}
	return asciiString(.s).hash()
}

func ( *importedString) ( int) uint16 {
	.ensureScanned()
	if .u != nil {
		return .u.CharAt()
	}
	return asciiString(.s).CharAt()
}

func ( *importedString) () int {
	.ensureScanned()
	if .u != nil {
		return .u.Length()
	}
	return asciiString(.s).Length()
}

func ( *importedString) ( String) String {
	if !.scanned {
		if ,  := .(*importedString);  {
			if !.scanned {
				return &importedString{s: .s + .s}
			}
		}
		.ensureScanned()
	}
	if .u != nil {
		return .u.Concat()
	}
	return asciiString(.s).Concat()
}

func ( *importedString) (,  int) String {
	.ensureScanned()
	if .u != nil {
		return .u.Substring(, )
	}
	return asciiString(.s).Substring(, )
}

func ( *importedString) ( String) int {
	return strings.Compare(.s, .String())
}

func ( *importedString) () io.RuneReader {
	if .scanned {
		if .u != nil {
			return .u.Reader()
		}
		return asciiString(.s).Reader()
	}
	return strings.NewReader(.s)
}

type stringUtf16Reader struct {
	s      string
	pos    int
	second uint16
}

func ( *stringUtf16Reader) () ( uint16,  error) {
	if .second != 0 {
		, .second = .second, 0
		return
	}
	if .pos < len(.s) {
		,  := utf8.DecodeRuneInString(.s[.pos:])
		.pos += 
		if  <= 0xFFFF {
			 = uint16()
		} else {
			,  := utf16.EncodeRune()
			, .second = uint16(), uint16()
		}
	} else {
		 = io.EOF
	}
	return
}

func ( *stringUtf16Reader) () ( rune,  int,  error) {
	,  := .readChar()
	if  != nil {
		return
	}
	 = rune()
	 = 1
	return
}

func ( *importedString) () utf16Reader {
	if .scanned {
		if .u != nil {
			return .u.utf16Reader()
		}
		return asciiString(.s).utf16Reader()
	}
	return &stringUtf16Reader{
		s: .s,
	}
}

func ( *importedString) () io.RuneReader {
	if .scanned {
		if .u != nil {
			return .u.utf16RuneReader()
		}
		return asciiString(.s).utf16RuneReader()
	}
	return &stringUtf16Reader{
		s: .s,
	}
}

func ( *importedString) () []rune {
	.ensureScanned()
	if .u != nil {
		return .u.utf16Runes()
	}
	return asciiString(.s).utf16Runes()
}

func ( *importedString) ( String,  int) int {
	.ensureScanned()
	if .u != nil {
		return .u.index(, )
	}
	return asciiString(.s).index(, )
}

func ( *importedString) ( String,  int) int {
	.ensureScanned()
	if .u != nil {
		return .u.lastIndex(, )
	}
	return asciiString(.s).lastIndex(, )
}

func ( *importedString) () String {
	.ensureScanned()
	if .u != nil {
		return toLower(.s)
	}
	return asciiString(.s).toLower()
}

func ( *importedString) () String {
	.ensureScanned()
	if .u != nil {
		 := cases.Upper(language.Und)
		return newStringValue(.String(.s))
	}
	return asciiString(.s).toUpper()
}

func ( *importedString) () string {
	return strings.Trim(.s, parser.WhitespaceChars)
}