No Image

Язык rust для чайников

СОДЕРЖАНИЕ
0 просмотров
22 января 2020

Итак, хотим представить вашему вниманию недавнего именинника (15 мая 2016 года ему исполнился год) — Rust. Это универсальный язык программирования, разрабатываемый компанией Mozilla, три основных принципа которого: скорость, безопасность и эргономика. Сами создатели нескромно считают его одним наиболее вероятных наследников C/C++. Согласно опросу портала StackOverflow, именно Rust сегодня наиболее любимый разработчиками язык. Итак, давайте подробнее разбираться в том, что же он из себя представляет.

Rust для новичка

Не хочется никого обманывать, поэтому далее ответственное заявление: Rust довольно сложен для обучения. Во-первых, это обусловлено молодостью языка и, как следствие, малым количеством литературы. Во-вторых, выучить его человеку далёкому от программирования, возможно будет даже проще, чем знакомому с другими языками. Так, например, готового IT-специалиста будет сильно раздражать необходимость прописывать малейшие операции, а отсутствие как такового наследования в языке и просто поставит в тупик.

Впрочем, Rust быстро развивается (каждые 6 недель выходит новый релиз), сообщество растёт, а найти информацию в интернете уже не составляет никакого труда.

Как изучать

Почти всё необходимое вы можете найти на официальном сайте. Кроме того, сообщество последователей Rust весьма обширно и доброжелательно, поэтому за советом всегда можно обратиться в IRC (есть русский раздел) и официальный форум. Кроме того, понемногу стали появляться книги, в том числе электронные. Пока трудно оценить их качество, но факт такой имеется.

Для тех, кто прошёл начальную стадию знакомства, на GiHub можно найти уйму полезного материала, в том числе RFC и коммиты. Кроме того, вы можете посетить лично или хотя бы посмотреть интернет-трансляцию одной из конференций по Rust, намеченных на вторую половину года. Вот календарь:

  • 9-10 сентября конференция RustConf в Портленде, США;
  • 17 сентября конференция европейского сообществ RustFest в Берлине, Германия;
  • 27 октября конференция Rust Belt Rust в Питтсбурге, США;

Ну а чтобы познакомиться с теми, кто считает Rust своим призванием, и заодно спросить у них все премудрости, можете связаться с организаторами и участниками встреч поклонников языка в Москве.

Особенности

Немного дублируя то, о чём было сказано ранее, выделим основные плюсы и минусы языка Rust.

Плюсы:

  • Безопасная работа с памятью;
  • Высокое быстродействие;
  • Алгебраический тип данных;
  • Предсказуемость компиляции;

Минусы:

  • Некоторая избыточность кода;
  • Высокая интенсивность развития языка и, как следствие, отсутствие хорошей актуальной литературы для изучения;
  • Необходимость чётко и однозначно прописывать параметры для компиляции.

На самом деле к отличиям, вроде замены наследования на способности, быстро привыкаешь. Как только глаза привыкли, руки набились, Rust превращается во вполне рабочий язык, проще и функциональнее C++, но уступающий по «красивости» многим другим языкам программирования. Фактически же главное отличие Rust от конкурентов и предшественников — именно скорость и безопасность.

Востребованность

На сегодняшний день Rust популярен сред разработчиков игр, графики и операционных систем. Однако по понятным причинам количество стационарных мест, где бы требовались узкопрофильные знатоки Rust, в мире и уже тем более в России крайне невелико. Тем не менее, пока не видно никаких предпосылок, что язык канет в лету, больше похоже на планомерный захват мира. А значит хорошие навыки использования Rust в будущем помогут найти высокооплачиваемую интересную работу как в нашей стране, так и за рубежом.

Еще востребованного: профессия «Веб-разработчик».

Итак, хотим представить вашему вниманию недавнего именинника (15 мая 2016 года ему исполнился год) — Rust. Это универсальный язык программирования, разрабатываемый компанией Mozilla, три основных принципа которого: скорость, безопасность и эргономика. Сами создатели нескромно считают его одним наиболее вероятных наследников C/C++. Согласно опросу портала StackOverflow, именно Rust сегодня наиболее любимый разработчиками язык. Итак, давайте подробнее разбираться в том, что же он из себя представляет.

Rust для новичка

Не хочется никого обманывать, поэтому далее ответственное заявление: Rust довольно сложен для обучения. Во-первых, это обусловлено молодостью языка и, как следствие, малым количеством литературы. Во-вторых, выучить его человеку далёкому от программирования, возможно будет даже проще, чем знакомому с другими языками. Так, например, готового IT-специалиста будет сильно раздражать необходимость прописывать малейшие операции, а отсутствие как такового наследования в языке и просто поставит в тупик.

Впрочем, Rust быстро развивается (каждые 6 недель выходит новый релиз), сообщество растёт, а найти информацию в интернете уже не составляет никакого труда.

Как изучать

Почти всё необходимое вы можете найти на официальном сайте. Кроме того, сообщество последователей Rust весьма обширно и доброжелательно, поэтому за советом всегда можно обратиться в IRC (есть русский раздел) и официальный форум. Кроме того, понемногу стали появляться книги, в том числе электронные. Пока трудно оценить их качество, но факт такой имеется.

Для тех, кто прошёл начальную стадию знакомства, на GiHub можно найти уйму полезного материала, в том числе RFC и коммиты. Кроме того, вы можете посетить лично или хотя бы посмотреть интернет-трансляцию одной из конференций по Rust, намеченных на вторую половину года. Вот календарь:

  • 9-10 сентября конференция RustConf в Портленде, США;
  • 17 сентября конференция европейского сообществ RustFest в Берлине, Германия;
  • 27 октября конференция Rust Belt Rust в Питтсбурге, США;

Ну а чтобы познакомиться с теми, кто считает Rust своим призванием, и заодно спросить у них все премудрости, можете связаться с организаторами и участниками встреч поклонников языка в Москве.

Особенности

Немного дублируя то, о чём было сказано ранее, выделим основные плюсы и минусы языка Rust.

Плюсы:

  • Безопасная работа с памятью;
  • Высокое быстродействие;
  • Алгебраический тип данных;
  • Предсказуемость компиляции;
Читайте также:  Сравнение зимней резины для внедорожников

Минусы:

  • Некоторая избыточность кода;
  • Высокая интенсивность развития языка и, как следствие, отсутствие хорошей актуальной литературы для изучения;
  • Необходимость чётко и однозначно прописывать параметры для компиляции.

На самом деле к отличиям, вроде замены наследования на способности, быстро привыкаешь. Как только глаза привыкли, руки набились, Rust превращается во вполне рабочий язык, проще и функциональнее C++, но уступающий по «красивости» многим другим языкам программирования. Фактически же главное отличие Rust от конкурентов и предшественников — именно скорость и безопасность.

Востребованность

На сегодняшний день Rust популярен сред разработчиков игр, графики и операционных систем. Однако по понятным причинам количество стационарных мест, где бы требовались узкопрофильные знатоки Rust, в мире и уже тем более в России крайне невелико. Тем не менее, пока не видно никаких предпосылок, что язык канет в лету, больше похоже на планомерный захват мира. А значит хорошие навыки использования Rust в будущем помогут найти высокооплачиваемую интересную работу как в нашей стране, так и за рубежом.

Еще востребованного: профессия «Веб-разработчик».

Rust
Семантика мультипарадигмальный: параллельное, функциональное, императивное, структурное программирование
Класс языка процедурный язык программирования [d] , язык функционального программирования , мультипарадигмальный язык программирования , императивный язык программирования [d] , язык системного программирования[d] , свободное программное обеспечение и компилируемый язык программирования
Тип исполнения компилируемый
Появился в 7 июля2010[4]
Автор Грэйдон Хор, разработчики проекта Rust
Разработчик Mozilla[1] и Graydon Hoare[d][1][2]
Расширение файлов .rs или .rlib
Выпуск
  • 1.40.0 ( 19 декабря2019 ) [3]
Система типов статическая, строгая, с выводом типов, номинальная, линейная, опционально динамическая
Основные реализации rustc
Испытал влияние Alef[d][5] , C++ , C# , Cyclone , Erlang , Haskell , Limbo , Newsqueak[d] , OCaml , Scheme , SML и Swift
Повлиял на Swift, Crystal
Лицензия Apache License 2.0[6] и лицензия MIT[6]
Сайт rust-lang.org​ (англ.)
ОС кроссплатформенность

Rust (англ. rust — ржавчина, произносится [ rʌst ] — раст) — мультипарадигмальный компилируемый язык программирования общего назначения, спонсируемый Mozilla Research, сочетающий парадигмы функционального и процедурного программирования с объектной системой, основанной на типажах, и с управлением памятью через понятие «владения» (систему аффинных типов [en] [7] , позволяющую обходиться без сборки мусора). Объектно-ориентированное программирование как таковое языком не поддерживается, но язык позволяет реализовать большинство понятий ООП при помощи других абстракций [8] .

Ключевые особенности языка: безопасность, скорость и параллелизм. Rust пригоден для системного программирования, в частности, он рассматривается как перспективный язык для разработки ядер операционных систем [7] . Rust сопоставим по скорости и возможностям с C++, однако даёт большую безопасность при работе с памятью, что обеспечивается механизмами ограничения. Rust также направлен на достижение «абстракции с нулевой стоимостью» [9] .

После нескольких лет активной разработки первая стабильная версия (1.0) вышла 15 мая 2015 года, после чего новые версии выходят раз в 6 недель [10] . Для версий языка, вышедших после 1.0, заявлена обратная совместимость [11] .

Язык отчасти берёт своё название от грибов семейства ржавчинные (англ. rust fungi ) [12] .

Содержание

История [ править | править код ]

  • Работа над языком была начата Грэйдоном Хором в 2006 году, в 2009 [13] к разработке подключилась Mozilla, и в 2010 году язык был официально представлен на Mozilla Summit 2010 [14] . Также в 2010 году разработка языка была переведена с использования компилятора, написанного на OCaml, на компилятор, написанный на Rust, с использованием LLVM в качестве back-end [15] . В следующем году он успешно скомпилировал сам себя [16] .
  • Январь 2012 г.: выпуск альфа-версии (0.1) компилятора Rust [17] .
  • Апрель 2013 г.: выпуск версии 0.6. Одновременно с этим, Mozilla объявила о присоединении к проекту Servo — браузерному движку нового поколения — компании Samsung, при активном участии которой код движка был портирован на ARM архитектуру [18] .
  • Май 2015 г.: выпуск версии Rust 1.0. Программные интерфейсы и возможности языка подверглись значительной ревизии, после которой по умолчанию оставлены только полностью готовые к применению возможности, реализация которых не будет изменяться в дальнейшем. Все остальные функции переведены в разряд экспериментальных и вынесены из поставки по умолчанию. [19]
  • В 2016—2019 гг. в ежегодных опросах Stack Overflow Rust каждый раз занимает первое место в списке любимых языков [20] (в 2015 году — третье место [21] ).

Обзор [ править | править код ]

Система типов [ править | править код ]

Особенности [ править | править код ]

  • Сильнаястатическая типизация.
  • Обобщённое программирование с поддержкой параметрического полиморфизма[23] .
  • Автоматический вывод типов для локальных переменных (это не относится к переменным — параметрам функций).
  • Поддержка единичных типов[en] данных — типов, которые имеют ровно один экземпляр и не занимают места в памяти [24] . Примеры:
  • пустой кортеж () ;
  • пустой массив (напр. [u8; 0] );
  • структура без полей (напр. struct Foo ).
  • Поддержка пустых типов[en] данных — типов, экземпляры которых не могут быть созданы [25] . Реализованы в виде перечисляемых типов, не имеющих вариантов: enum Void <> .
  • Основные типы [ править | править код ]

    В Rust все типы можно разделить на две основные группы:

    • Простые типы (типы постоянной длины, встроенные в сам язык): Числовой, Булев, Символ, Массив, Срез, Строковый срез, Кортеж, Ссылка, Указатель на функцию [26][27] . Из простых типов можно выделить «Машинные» типы (реализованные непосредственно в современных процессорах): Числовой, Булев, Символ.
    • Типы, предоставляемые стандартной библиотекой std (переменной длины): Вектор, Строка, Хеш-таблица и т. д.

    Числовой

    • Целое (integer). i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, а также isize и usize, имеющие размер указателя на данной платформе. u8 применяется для «байтовых» значений. Примеры значений: -5i8 , 0x400_u16 , 0o100i16 , 20_922_789_888u64 , b’*’ (байтовый литерал), b’x1b’ , 42 (тип этого значения будет выведен автоматически), 0xfff_fc00usize ,
    • Число с плавающей запятой (float). f32, f64. Примеры: 3.14f32 , 6.0221e23f64 , 2. ,
    Читайте также:  Яндекс браузер дзен установить

    Булев (bool) true , false . Символ (char) Тип, представляющий символ Unicode (внутреннее представление данных как u32). Примеры значений: ‘₽’ , ‘
    ‘ , ‘x7f’ , ‘u‘ , Указатель на функцию (function pointer) Объекты-функции имеют тип, определяемый их сигнатурой, то есть параметрами и возвращаемым значением. Пример: let f: fn(i32) -> i32 = plus_one; Ссылка

    • Ссылка (разделяемое заимствование — shared borrow) &T (разделяемая, не изменяемая, не владеющая ресурсом), вместо того, чтобы забирать владение ресурсом, она его заимствует. Имена, которые заимствуют что-то, не освобождают ресурс, когда они выходят из области видимости. Кроме того, имена-владельцы переходят в заимствованное состояние [28] .
    • Ссылка изменяемая (изменяемое заимствование — mutable borrow) &mut T (не владеющая ресурсом). Позволяет изменять ресурс, который заимствуется.

    Коллекция

    • Массив (array) [T; N] — последовательность элементов одного и того же типа, имеющая фиксированный размер. Примеры: [1, 2, 3] , [true; 10000] .
    • Вектор (vec, vector) Vec — это динамический, или расширяемый массив, реализованный в виде стандартного библиотечного типа Vec . Примеры: vec![0; 10]; , Vec::with_capacity(10)
    • Срез (slice, view) &[T] — это ссылка (или «проекция») на другую структуру данных. Они полезны, когда нужно обеспечить безопасный, эффективный доступ к части массива без копирования. Пример: &a[1..4] ,
    • Кортеж (tuple) (T1, T2, T3, …). Подобно структуре, содержит произвольное количество разнотипных полей, но поля безымянны, обращение к полям возможно по индексу (t.0, t.1). Кортежи — безымянные типы: кортежи с одинаковым количеством и типами полей являются совместимыми по типу. С помощью ключевого слова type можно задать псевдоним, который, однако, не задаёт нового типа. Пример: ("Age", 22) , ("Europe",) ,
    • Кортеж нулевой длины ((); пустой кортеж) часто называют «единичным значением». Соответственно, тип такого значения — «единичный тип». Если функция не возвращает значение, то считается, что она возвращает ().
    • Хеш-таблица ключ-значение (HashMap) HashMap — это структура данных, реализующая интерфейс ассоциативного массива, а именно, она позволяет хранить пары (ключ, значение) и выполнять три операции: операцию добавления новой пары, операцию поиска и операцию удаления пары по ключу. Хеш-таблицы в Rust похожи на векторы, и хранят свои значения не по индексу, а по ключу. Пример: HashMap::new();
    • Хеш-таблица — множество (HashSet) HashSet — множество уникальных значений типа T. Добавление и удаление элементов, а также поиск элементов происходит быстрее, чем в других коллекциях [каких?] .

    Строка

    • Строка (String) (имеет внутреннее представление данных в виде Vec ) — тип, владеющий содержимым. String представляет собой строку, размещённую в куче. Эта строка расширяема, и она гарантированно является корректной последовательностью байтов с точки зрения UTF-8. String обычно создаётся путём преобразования из строкового среза с использованием метода to_string. Примеры: "строковый срез".to_string() , String::new() .
    • «Строковый срез» (string slice, string literal) &str, &’static str. Частный случай среза. Строковые срезы имеют фиксированный размер и не могут быть изменены. Они представляют собой ссылку на последовательность байтов UTF-8. Пример: "строковый срез" . &’static str — строка, введённая символами в коде самой программы, — тот же строковый срез, только статически размещённый (сохраняемый в скомпилированной программе).
    • «Сырой строковый срез» (или сырой строковый литерал), в котором не работают управляющие последовательности: r"d<0,5>.*" .
    • «Байтовая строка» &[u8] — строковый литерал с префиксом «b»: b"white" .

    Возможности объявления пользовательских (составных) типов [ править | править код ]

    При выборе следует отдавать предпочтение const , так как зачастую для константы не нужен конкретный адрес в памяти и const позволяет делать оптимизации вроде Свёртки констант [29] .

    Управление памятью [ править | править код ]

    В Rust реализована «умная» модель памяти [ источник не указан 40 дней ] , поддерживающая эффективные структуры данных и безопасные шаблоны параллельного выполнения, а также полностью запрещающая некорректный доступ к памяти, который обычно является источником критических ошибок сегментации в других языках программирования. Отсутствие нулевых указателей; контроль за использованием неинициализированных и деинициализированных переменных; невозможность совместного использования разделяемых состояний несколькими задачами; статический анализ времени жизни указателей; проверка на выход за пределы массива (автоматически и всегда).

    Модель памяти Rust можно охарактеризовать следующими терминами.

    Move-семантика По умолчанию Rust «переносит» (move) указатель на объект в куче новому владельцу при присваивании, делая старую переменную недействительной. Этого не происходит, если тип реализует типаж Copy, поскольку данные в стеке копируются.

    Связывания неизменяемы по умолчанию, а чтобы объявить переменную изменяемой, необходимо ключевое слово mut.

    Синтаксис [ править | править код ]

    Синтаксис Rust похож на Си и C++; язык регистро-зависимый, блоки кода ограничиваются фигурными скобками; используются стандартные наименования управляющих конструкций if, else, while, и for; комментарии также пишутся в С-формате; имена модулей разделяются двумя символами двоеточия ( :: ). Идентификаторы могут содержать латинские буквы, цифры и знак подчёркивания. В строковых литералах допускается использование любых символов unicode в кодировке UTF-8.

    Набор операторов в Rust: арифметические ( * — умножение, / — деление, % — взятие остатка от деления, + — сложение, — — вычитание и унарный префиксный оператор — для смены знака числа), битовые ( >> , , & , | и ^ ), операторы сравнения ( == , != , , > , , >= ), логические ( && и || ). Для приведения типов в Rust используется бинарный оператор as . Неявное приведение типов происходит в очень небольшом наборе ситуаций [30] ; отсутствует неявное приведение чисел или строк к булевому значению.

    Читайте также:  Топ лучших игр для мощных пк

    Rust поддерживает макроопределения — средства подстановки с использованием регулярных выражений, выполняющиеся во время этапа подготовки к компиляции, более развитые и безопасные, чем в Си. Макроопределения (макрокоманды) — это определяемые пользователем простые расширения синтаксиса, выполняемые с помощью команды macro_rules! Макрокоманды определяются в том же стиле, что и конструкция сопоставления с образцом. Признак макроса — восклицательный знак в конце имени.

    Связывание имён [ править | править код ]

    Ключевое слово let определяет связывание (локальную переменную).

    Данная запись обозначает: « x — это связывание типа i32 (32-битное целое) со значением пять».

    Сопоставление с образцом (match) [ править | править код ]

    В языке Rust конструкция match представляет собой обобщённую и усовершенствованную версию конструкции switch языка C. Более того, match является самым мощным, универсальным и, можно даже сказать, ключевым элементом управления не только потоком выполнения, но и структурами данных в языке.

    Деструктуризация. При работе с составным типом данных, вроде struct, можно разобрать его на части («деструктурировать») внутри шаблона:

    unsafe [ править | править код ]

    В блоках и функциях, помеченных unsafe (англ. unsafe — небезопасный), компилятор разрешает делать лишь четыре дополнительные вещи [31] :

    • читать и обновлять изменяемые статические ( static mut ) переменные;
    • разыменовывать сырые указатели;
    • вызывать небезопасные ( unsafe ) функции;
    • реализовывать небезопасные типажи.

    К unsafe приходится прибегать для создании низкоуровневых абстракций, в частности — при разработке стандартной библиотеки Rust; обычный код рекомендуется писать без unsafe [32] .

    Объектная система [ править | править код ]

    В Rust объектная система основана на типажах (traits) и структурах данных. Типажи определяют методы, которые должны быть реализованы для типов. Типаж может содержать реализации методов, принимаемые по умолчанию. Реализация типажей для данной структуры, а также реализация собственных методов структуры обозначается ключевым словом impl . Язык содержит несколько десятков встроенных типажей, большая часть которых используется для перегрузки операторов, а некоторые имеют специальное значение.

    Rust поддерживает обобщённые типы (generics). Помимо функций, обобщёнными в Rust могут быть комплексные типы данных, структуры и перечисления. Компилятор Rust компилирует обобщённые функции весьма эффективно, применяя к ним мономорфизацию (генерация отдельной копии каждой обобщённой функции непосредственно в каждой точке её вызова). Таким образом, копия может быть адаптирована под конкретные типы аргументов, а следовательно, и оптимизирована для этих типов. В этом отношении обобщённые функции Rust сравнимы по производительности с шаблонами языка C++.

    Параллельные вычисления [ править | править код ]

    В более ранних версиях языка поддерживались легковесные потоки, но потом от них отказались в пользу нативных потоков операционной системы. При этом рекомендуемым методом обмена данными между потоками является отправка сообщений, а не использование общей памяти. Для достижения высокой производительности возможно отправлять данные не через копирование, а используя собственные указатели ( Box ). Они гарантируют только одного владельца.

    Другие особенности [ править | править код ]

    Примеры программ [ править | править код ]

    Hello, world! [ править | править код ]

    Сравнение с другими языками [ править | править код ]

    • Принципы работы с памятью Rust ощутимо отличаются как от языков с полным доступом к памяти, так и от языков с полным контролем за памятью со стороны сборщика мусора. Модель памяти Rust построена таким образом, что, с одной стороны, предоставляет разработчику возможность контролировать, где размещать данные, вводя разделение по типам указателей и обеспечивая контроль за их использованием на этапе компиляции. C другой стороны, механизм подсчёта ссылок Rust старается выдавать ошибки компиляции в тех случаях, в которых использование прочих языков приводит к ошибкам времени выполнения или аварийному завершению программ.
    • Rust позволяет объявлять функции и блоки кода как «небезопасные» ( unsafe ). В области такого небезопасного кода не применяются некоторые ограничения, таким образом можно выполнять операции на более низком уровне, но разработчик должен полностью понимать, что он делает.

    Применение [ править | править код ]

    Среди компаний, активно использующих Rust, можно отметить Mozilla и Dropbox. [39] В качестве примеров разработок на Rust можно привести [ источник не указан 292 дня ] :

    • Redox — операционная система в стадии разработки.
    • Servo — экспериментальный браузерный движок.
    • Stratis — файловая система для Fedora, похожая на ZFS[40][41][42]
    • Firecracker — гипервизор, развиваемый Amazon [43]
    • Xi[44] — открытый текстовый редактор для операционной системы Фуксия, разрабатываемой в Google[45]
    • Rocket — Каркас веб-приложений[46]
    • Figma — онлайн-сервис для разработки интерфейсов и прототипирования [47]
    • Tock — многозадачная открытая встраиваемая операционная система для микроконтроллеров и интернета вещей (IoT) [48][49][50][51]
    • raf1e[52] — экспериментальный быстрый [53] [источник не указан 292 дня] и безопасный видеокодек для формата AV1, разрабатываемый Mozilla и Xiph[54][55]
    • Piston[56] — модульный открытый игровой движок[57][58]
    • Cloud Hypervisor — гипервизор от Intel [59]

    Всем привет!
    Дело в том, что я JavaScript разработчик. Но меня очень заинтересовал язык Rust, я начал знакомиться с статьями про Rust, но там много непонятных терминов. Возможно есть какая-то общая литература без сильной завязки на языке (Не хочу учить плюсы, чтобы учить Rust)?

    • Вопрос задан более трёх лет назад
    • 15179 просмотров

    Содержание:
    1 Установка Rust
    2 Hello, world!
    3 Hello, Cargo!
    4 Объявление переменных
    5 Условные операторы
    6 Функции
    7 Комментарии в коде
    8 Составные типы данных
    9 Оператор Match
    10 Циклы
    11 Строки
    12 Массивы
    13 Стандартный ввод
    14 Игра угадайка
    15 Ящики и модули
    16 Тестирование кода
    17 Указатели
    18 Паттерны
    19 Синтаксис методов
    20 Замыкания(closures)
    21 Итераторы
    22 Дженерики(Generics) — похоже на шаблоны в С++
    23 Трейты(Traits) — куски кода
    24 Задания
    25 Макросы
    26 Небезопасный код
    27 Заключение

    Комментировать
    0 просмотров
    Комментариев нет, будьте первым кто его оставит

    Это интересно
    No Image Компьютеры
    0 комментариев
    No Image Компьютеры
    0 комментариев
    No Image Компьютеры
    0 комментариев
    No Image Компьютеры
    0 комментариев
    Adblock detector