// Unicode: байты, руны и подводные камни строк в Go
// Запуск: go run unicode_demo.go

package main

import (
	"fmt"
	"unicode/utf8"
)

func main() {
	// 1. Байты vs руны (code points)
	s := "Привет 🌍"
	fmt.Printf("«%s»\n", s)
	fmt.Printf("  len()      = %d (байт)\n", len(s))
	fmt.Printf("  RuneCount  = %d (code points)\n", utf8.RuneCountInString(s))

	// 2. Нормализация: предсоставленная vs разложенная «й»
	y1 := "й"       // U+0439 — одна руна
	y2 := "и\u0306" // U+0438 + U+0306 — две руны
	fmt.Println("\n--- Нормализация ---")
	fmt.Printf("Предсоставленная «%s»: %d байт, %d rune(s)\n", y1, len(y1), utf8.RuneCountInString(y1))
	fmt.Printf("Разложенная      «%s»: %d байт, %d rune(s)\n", y2, len(y2), utf8.RuneCountInString(y2))
	fmt.Printf("==  возвращает %v\n", y1 == y2)

	// 3. Эмодзи-семья: один глиф — семь рун
	family := "👨\u200D👩\u200D👧\u200D👦"
	fmt.Println("\n--- Эмодзи ---")
	fmt.Printf("Семья: %s\n", family)
	fmt.Printf("  len()      = %d байт\n", len(family))
	fmt.Printf("  RuneCount  = %d\n", utf8.RuneCountInString(family))
	fmt.Print("  Состав:")
	for _, r := range family {
		fmt.Printf(" U+%04X", r)
	}
	fmt.Println()

	// 4. Байтовый срез — тихая ошибка (Go не паникует)
	hello := "Здравствуйте"
	fmt.Println("\n--- Срезы ---")
	fmt.Printf("«%s» = %d байт, %d rune(s)\n", hello, len(hello), utf8.RuneCountInString(hello))
	fmt.Printf("hello[:2] = «%s» (первая буква — 2 байта)\n", hello[:2])
	fmt.Printf("hello[:1] = «%s» (половина буквы — невалидный UTF-8)\n", hello[:1])

	// 5. for range безопасно декодирует руны
	fmt.Println("\n--- Итерация ---")
	for i, r := range "Zig 🦎" {
		fmt.Printf("  [байт %d] U+%04X %c\n", i, r, r)
	}

	// 6. Гомоглифы
	latinA := 'a'    // U+0061
	cyrA := 'а'      // U+0430
	fmt.Println("\n--- Гомоглифы ---")
	fmt.Printf("Латинская  'a' = U+%04X\n", latinA)
	fmt.Printf("Кириллическая 'а' = U+%04X\n", cyrA)
	fmt.Printf("Выглядят одинаково, но == возвращает %v\n", latinA == cyrA)
}
