"""ОДНА ЗАДАЧА НА ЧЕТЫРЁХ ЯЗЫКАХ — 4/4: Python.

Задача: скопировать строку в буфер размером ровно 16 символов.

Запуск:
    py copy_name.py
"""

import sys

BUFFER_SIZE = 16
SOURCE = "Иванова Анна Петровна, отдел информационной безопасности"


def unsafe_copy() -> None:
    """Тот же цикл и та же логическая ошибка, что и в трёх других файлах."""
    buffer = [""] * BUFFER_SIZE

    for i in range(len(SOURCE)):
        buffer[i] = SOURCE[i]   # на i == 16 здесь возникнет IndexError

    print("Скопировано без ошибок — этого не произойдёт.")


def safe_copy() -> str:
    """Правильный вариант: цикл ограничен МЕНЬШЕЙ из двух длин."""
    buffer = [""] * BUFFER_SIZE
    limit = min(len(SOURCE), BUFFER_SIZE)

    for i in range(limit):
        buffer[i] = SOURCE[i]

    return "".join(buffer[:limit])


def pythonic_copy() -> str:
    """А так эту задачу пишут на Python в реальной жизни — одной строкой.

    Срез никогда не выходит за границы: если элементов меньше, чем
    запрошено, срез просто вернёт то, что есть. Ошибиться негде.
    """
    return SOURCE[:BUFFER_SIZE]


if __name__ == "__main__":
    sys.stdout.reconfigure(encoding="utf-8")

    print(f"Длина исходной строки: {len(SOURCE)}")
    print(f"Размер буфера:         {BUFFER_SIZE}")
    print()

    try:
        unsafe_copy()
    except IndexError as error:
        print("Интерпретатор остановил запись за границу списка:")
        print(f"    IndexError: {error}")

    print()
    print(f"Безопасная копия:  «{safe_copy()}»")
    print(f"То же самое срезом: «{pythonic_copy()}»")

# ===========================================================================
#  ЧТО ЗДЕСЬ ВАЖНО УВИДЕТЬ
#
#  1. Ошибка выхода за границу обнаруживается всегда и отключить проверку
#     нельзя — как в C#, в отличие от Pascal.
#
#  2. У строк в Python вообще нет фиксированного размера. «Буфер на 16
#     символов» пришлось изображать списком: сама задача в этом языке
#     обычно не возникает. Целый класс уязвимостей исчезает вместе
#     с ручным управлением памятью.
#
#  3. Плата за это — производительность и потеря контроля над тем, где
#     и как размещаются данные. Поэтому загрузчики, драйверы и ядра
#     операционных систем на Python не пишут.
#
#  ГЛАВНЫЙ ВЫВОД ПАРЫ.
#  Выбор языка — это архитектурное решение по безопасности, принятое
#  до написания первой строки кода. Оно определяет, какие классы
#  уязвимостей вообще возможны в вашей программе:
#
#      ассемблер / C / C++  — безопасность памяти на программисте
#      Object Pascal        — на программисте плюс настройка компилятора
#      C# / Java / Python   — на среде выполнения
#      Rust                 — на компиляторе, проверка до запуска
#
#  Но ни один язык не защищает от SQL-инъекции, от дефекта логики доступа
#  и от секрета, закоммиченного в репозиторий. Это ровно те дефекты,
#  которые мы разбираем на следующей паре в файле step3_defect.py.
# ===========================================================================
