parent
71c3d42e70
commit
c454481967
21 changed files with 370 additions and 63 deletions
@ -1,3 +1,5 @@ |
|||||||
+++ |
+++ |
||||||
redirect_to = "home" |
redirect_to = "home" |
||||||
|
title = "Приветствую" |
||||||
+++ |
+++ |
||||||
|
Вы находитесь на самом ортёмном сайте во всей сети. Используйте меню для навигации. |
@ -1,4 +0,0 @@ |
|||||||
+++ |
|
||||||
title = "Curriculum vitae" |
|
||||||
+++ |
|
||||||
CV placeholder |
|
After Width: | Height: | Size: 418 KiB |
After Width: | Height: | Size: 580 KiB |
@ -0,0 +1,89 @@ |
|||||||
|
+++ |
||||||
|
title = "Резюме" |
||||||
|
+++ |
||||||
|
10 лет: первая книжка по программированию на Visual Basic. Первая графическая угадайка и огонь в глазах от рабочей программы с ползнуком загрузки. |
||||||
|
|
||||||
|
12-16 лет: после появления диска по сталкером появилось и желание расколупать его исходники и сделать весёлые штуки на потеху себе и друзьям-одноклассникам. |
||||||
|
Так в нём появилась портальная пушка, гравитационная граната, полёты на военном вертолёте и собственные карты для мультиплеера. |
||||||
|
|
||||||
|
![stalker1](mmap1.jpg) |
||||||
|
|
||||||
|
![stalker2](mmap2.jpg) |
||||||
|
|
||||||
|
![stalker3](otf.jpg) |
||||||
|
|
||||||
|
14-18 лет: Майнкрафт, электроцепи на двоичной логике из красного камня, C418 на фоне. |
||||||
|
Из большого родился 6-разрядный калькулятор со сложением и вычитанием вплоть до отрицательных чисел. |
||||||
|
|
||||||
|
![calc](calc.jpg) |
||||||
|
|
||||||
|
![calc1](calc1.jpg) |
||||||
|
|
||||||
|
14-20 лет: участие в различных олимпиадах по программированию/CTF: УрКОП, ICPC, QCTF. |
||||||
|
Без выдающихся результатов (но бесплатные пиццы того стоили). |
||||||
|
|
||||||
|
17-18 лет: поступление в Уральский федеральный университет на информационную безопасность. |
||||||
|
Активное изучение Python и использование его во многих местах: от курсовых до первых фрилансерских задач. |
||||||
|
Осознание неверности выбранного направления после первого курса: |
||||||
|
перекладывание бумажек и расчёты цепей не могли совмещаться с активной программистской деятельностью. |
||||||
|
Перевод на компьютерную безопасность. |
||||||
|
|
||||||
|
21 год: очередное осознание неверности выбранного направления, уход из университета на 5 курсе, полное погружение в работу. |
||||||
|
|
||||||
|
22 года: в 2020 открыл для себя Rust и решил перекатываться на него, как на самый идеальный для меня язык. |
||||||
|
|
||||||
|
За время обучения в университете и самоучества наработал себе неплохой фундамент: |
||||||
|
алгоритмы, структуры данных, О-нотация, сети на уровне CCNA, дискретка, криптография, опыт работы на нескольких языках программирования/разметки/etc: |
||||||
|
Python, Java, Javascript, MySQL, HTML, CSS, C, TASM. |
||||||
|
|
||||||
|
За время работы на разные компании профессионально развивался в сфере бэкенд-разработки изначально на Python, впоследствии (и сейчас) на Rust. |
||||||
|
|
||||||
|
## Salary transparency |
||||||
|
- kwork.ru |
||||||
|
Время работы: Апрель 2017 — Январь 2018 |
||||||
|
Должность: Junior python programmer |
||||||
|
Обязанности: Фриланс на kwork.ru |
||||||
|
З/п: 500-15000 ₽ / проект |
||||||
|
|
||||||
|
- Точка |
||||||
|
Время работы: Июнь 2018 — Сентябрь 2018 |
||||||
|
Должность: Junior python programmer |
||||||
|
Обязанности: Разработка автотестов для мобильного приложения банка с использованием python и appium |
||||||
|
З/п: 23000 ₽ |
||||||
|
|
||||||
|
- Крона-КС |
||||||
|
Время работы: Июнь 2019 — Сентябрь 2019 |
||||||
|
Должность: Программист Python |
||||||
|
Обязанности: Разработка SAAS-сервиса Retailiqa, рефакторинг кода на Python (django, mongo) и Javascript |
||||||
|
З/п: 30000 ₽ |
||||||
|
|
||||||
|
- Инанго-СВ |
||||||
|
Время работы: Сентябрь 2019 — Декабрь 2019 |
||||||
|
Должность: Программист С |
||||||
|
Обязанности: Разработка и рефакторинг прошивок для Intel Puma 6/7 на языке Си/С++ |
||||||
|
З/п: 35000 ₽ |
||||||
|
|
||||||
|
- Cloudlinux |
||||||
|
Время работы: Май 2020 — Июнь 2021 |
||||||
|
Должность: Программист Python |
||||||
|
Обязанности: Разработка клиентской части антивируса Imunify360 и различных внутренних инструментов на Python. Покрытие кода юнит-, функциональными и интеграционными тестами. Написание плейбуков для Ansible. |
||||||
|
З/п: $1000 |
||||||
|
|
||||||
|
- Waves.Exchange |
||||||
|
Время работы: Август 2021 — Май 2023 |
||||||
|
Должность: Rust-программист |
||||||
|
Обязанности: Разработка, поддержка, рефакторинг микросервисов бэкенда биржи waves.exchange на языке Rust. |
||||||
|
Переписывание легаси-кода с Typescript, Scala и Go на Rust. |
||||||
|
Проектирование архитектуры и создание новых микросервисов как в одиночку, так и в команде. |
||||||
|
Документирование и покрытие кода тестами. |
||||||
|
Проведение код-ревью коллег. |
||||||
|
Создание внешних опенсурс-библиотек для разделяемого использования в конечных сервисах и других отделах компании. |
||||||
|
Исследование и участие в обсуждении новых фич для оптимизации кода. |
||||||
|
Участие в расследовании инцидентов на продакшене. |
||||||
|
З/п: $2000 |
||||||
|
|
||||||
|
- Сбербанк-Технологии |
||||||
|
Время работы: 11 июля 2023 - н.в. |
||||||
|
Должность: Rust-программист |
||||||
|
Обязанности: Разработка личного кабинета для клиентов Platform V. |
||||||
|
З/п: :) |
After Width: | Height: | Size: 272 KiB |
After Width: | Height: | Size: 238 KiB |
After Width: | Height: | Size: 441 KiB |
@ -1,7 +1,7 @@ |
|||||||
+++ |
+++ |
||||||
title = "About me" |
title = "Обо мне" |
||||||
+++ |
+++ |
||||||
|
|
||||||
Are you an employer and looking for a Middle Rust Developer? Don't hesitate to check out my [CV](/about/cv) and [portfolio](/projects)! |
Вы HR и находитесь в поисках Middle Rust-разработчика? Предлагаю заглянуть в моё [портфолио](/projects) и [резюме](/about/cv)! |
||||||
|
|
||||||
Not enough? You wanna dig into my mind [deeper](/about/mind)? |
А ещё можно посмотреть [вглубь меня](/about/mind) |
@ -0,0 +1,88 @@ |
|||||||
|
+++ |
||||||
|
title = "Расттест 1" |
||||||
|
date = "2022-08-18" |
||||||
|
|
||||||
|
[taxonomies] |
||||||
|
tags = ["rust"] |
||||||
|
+++ |
||||||
|
|
||||||
|
### Какой тип имеет переменная `result`? |
||||||
|
```rust |
||||||
|
fn count_uppercase(s: &str) -> usize { |
||||||
|
let result = { |
||||||
|
let upper = s.chars().filter(|c| c.is_uppercase()).collect::<String>(); |
||||||
|
return upper.len(); |
||||||
|
}; |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
<details><summary>Ответ</summary> |
||||||
|
|
||||||
|
`result` имеет тип `!` (never type/никогдатый тип). |
||||||
|
В `result` записывается результат выполнения блока инструкций в фигурных скобочках. |
||||||
|
Блок `{ ... }` всегда возвращает значение, но как быть, если мы натыкаемся на `return`, |
||||||
|
прерывающий поток выполнения программы и возвращающий значение из **функции**, а не из блока? |
||||||
|
Для этого в раст завезли служебный тип `!`, показывающий, что тип данной переменной никогда не будет присвоен. |
||||||
|
|
||||||
|
Если бы мы переписали функцию следующим образом: |
||||||
|
```rust |
||||||
|
fn count_uppercase(s: &str) -> usize { |
||||||
|
let result = { |
||||||
|
let upper = s.chars().filter(|c| c.is_uppercase()).collect::<String>(); |
||||||
|
upper.len() |
||||||
|
}; |
||||||
|
return result |
||||||
|
} |
||||||
|
``` |
||||||
|
то `result` бы имел верный тип `usize`. |
||||||
|
|
||||||
|
[Почитать ещё](https://doc.rust-lang.org/book/ch19-04-advanced-types.html#the-never-type-that-never-returns) |
||||||
|
|
||||||
|
P.S.: обычно в расте принято опускать `return` и писать вместо него возвращаемое значение без `;`. |
||||||
|
Это трактуется как возврат значения из текущего блока (в том числе функции) |
||||||
|
|
||||||
|
</details> |
||||||
|
<br> |
||||||
|
|
||||||
|
### Ограничен ли дженерик-тип `T` какими-либо трейтами? |
||||||
|
```rust |
||||||
|
pub fn drop<T>(_x: T) { } |
||||||
|
``` |
||||||
|
|
||||||
|
<details><summary>Ответ</summary> |
||||||
|
|
||||||
|
Да, по умолчанию любые дженерики имеют ограничение `T: Sized`. |
||||||
|
Этот трейт реализован для всех типов, размер которых известен на момент компиляции. |
||||||
|
|
||||||
|
Для отмены ограничения используется следующий синтаксис: |
||||||
|
```rust |
||||||
|
pub fn drop<T: ?Sized>(_x: T) { } |
||||||
|
``` |
||||||
|
означающий, что функция может принимать безразмерные типы (DST), такие как `dyn Trait`, `[u8]`, `str` и т.д. |
||||||
|
|
||||||
|
</details> |
||||||
|
<br> |
||||||
|
|
||||||
|
### Есть ли отличия между следующими кусками кода? |
||||||
|
```rust |
||||||
|
const GLOBAL_MUTEX: Mutex<i32> = Mutex::new(0); |
||||||
|
``` |
||||||
|
и |
||||||
|
```rust |
||||||
|
static GLOBAL_MUTEX: Mutex<i32> = Mutex::new(0); |
||||||
|
``` |
||||||
|
|
||||||
|
<details><summary>Ответ</summary> |
||||||
|
|
||||||
|
`const` клонирует значение константы во все места её использования. |
||||||
|
В результате вместо изменения глобального мьютекса мы получаем несколько клонированных мьютексов и часы дебага. |
||||||
|
|
||||||
|
В случае со `static` программа действительно создаёт один глобальный мьютекс, который можно изменять из разных потоков. |
||||||
|
|
||||||
|
Это известная проблема, о которой не сигнализирует `rustc`, |
||||||
|
поэтому будет полезно дополнительно использовать `clippy` в вашем проекте. Он не только отловит неверное использование констант, |
||||||
|
но привьёт вам чувство прекрасного растового кода. |
||||||
|
[Почитать ещё](https://rust-lang.github.io/rust-clippy/master/index.html#/declare_interior_mutable_const) |
||||||
|
|
||||||
|
</details> |
||||||
|
<br> |
@ -1,24 +0,0 @@ |
|||||||
+++ |
|
||||||
title = "Tricky questions for any rust interview" |
|
||||||
draft = true |
|
||||||
date = "2022-08-18" |
|
||||||
|
|
||||||
[taxonomies] |
|
||||||
tags = ["rust"] |
|
||||||
+++ |
|
||||||
|
|
||||||
Which type has variable `result`? |
|
||||||
```rust |
|
||||||
fn count_uppercase(s: &str) -> usize { |
|
||||||
let result = { |
|
||||||
let upper = s.chars().filter(|c| c.is_uppercase()).collect::<String>(); |
|
||||||
return upper.len(); |
|
||||||
}; |
|
||||||
} |
|
||||||
``` |
|
||||||
|
|
||||||
<details><summary>Answer</summary> |
|
||||||
|
|
||||||
`result` has '!' type or 'never type'. . [Read more](https://doc.rust-lang.org/book/ch19-04-advanced-types.html#the-never-type-that-never-returns) |
|
||||||
|
|
||||||
</details> |
|
@ -0,0 +1,4 @@ |
|||||||
|
+++ |
||||||
|
title = "Welcome, stranger" |
||||||
|
+++ |
||||||
|
You're on ortem's website! Use top menu to navigate. |
@ -1,4 +1,4 @@ |
|||||||
+++ |
+++ |
||||||
title = "Welcome, stranger" |
title = "Приветствую" |
||||||
+++ |
+++ |
||||||
You're on ortem's website! Use top menu to navigate. |
Вы находитесь на самом ортёмном сайте во всей сети. Используйте меню для навигации. |
@ -1,4 +0,0 @@ |
|||||||
+++ |
|
||||||
title = "Приветствую" |
|
||||||
+++ |
|
||||||
Вы находитесь на самом ортёмном сайте во всей сети. Используйте меню для навигации. |
|
@ -1,15 +1,19 @@ |
|||||||
+++ |
+++ |
||||||
title = "My pet projects" |
title = "Примеры моего кода. Пет-проекты (🐕) и не очень." |
||||||
+++ |
+++ |
||||||
|
|
||||||
* [Source code of ortem.xyz](https://git.ortem.xyz/root/ortem.xyz) |
* [unki](https://git.ortem.xyz/root/unki): домашний RAT |
||||||
|
|
||||||
* [Yet another one brainfuck interpreter](https://github.com/plazmoid/brainfuck-rust) |
* [Примеры реального продакшен-кода](https://github.com/wavesplatform/blockchain-postgres-sync/pulls?q=is%3Apr+author%3Aplazmoid) |
||||||
|
|
||||||
* [unki](https://git.ortem.xyz/root/unki): cross-platform remote admin tool for not enough smart house |
* [Исходники ortem.xyz](https://git.ortem.xyz/root/ortem.xyz) |
||||||
|
|
||||||
* [sockser](https://git.ortem.xyz/root/sockser): small program to establish and maintain SOCKS5-tunnel via ssh client |
* [Очередной brainfuck-интерпретатор](https://github.com/plazmoid/brainfuck-rust) |
||||||
|
|
||||||
* [teeworlds](https://github.com/plazmoid/teeworlds): rough clone of original [game](https://www.teeworlds.com/) written in python+pygame |
* [sockser](https://git.ortem.xyz/root/sockser): |
||||||
|
демон для установки и поддержания SOCKS5-туннеля через ssh-соединение |
||||||
|
|
||||||
* [bind-it](https://github.com/plazmoid/bind_it): small nightly-rust crate that allows to write `let n: impl Trait = 1;` |
* [teeworlds](https://github.com/plazmoid/teeworlds): грубый клон [игры](https://www.teeworlds.com/) на python+pygame |
||||||
|
|
||||||
|
* [bind-it](https://github.com/plazmoid/bind_it): |
||||||
|
небольшой крейт для раста (nightly), позволяющий писать `let n: impl Trait = 1;` |
@ -0,0 +1,16 @@ |
|||||||
|
details { |
||||||
|
summary:hover { |
||||||
|
cursor: pointer; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
body { |
||||||
|
background: url("cartoon-computer-SEL.jpg") top right no-repeat; |
||||||
|
background-attachment: fixed; |
||||||
|
background-size: 100%; |
||||||
|
} |
||||||
|
|
||||||
|
.container { |
||||||
|
background-color: black; |
||||||
|
opacity: 0.93; |
||||||
|
} |
After Width: | Height: | Size: 1.2 MiB |
@ -0,0 +1,124 @@ |
|||||||
|
{% import "macros/date.html" as date_macros -%} |
||||||
|
{% import "macros/head.html" as head_macros -%} |
||||||
|
{% import "macros/menu.html" as menu_macros -%} |
||||||
|
{% import "macros/post.html" as post_macros -%} |
||||||
|
|
||||||
|
<!DOCTYPE html> |
||||||
|
<html lang="{%- if config.default_language -%}{{ config.default_language }}{%- else -%}en{%- endif -%}"> |
||||||
|
|
||||||
|
<head> |
||||||
|
<title>{%- block title %}{{ config.title }}{% endblock title -%}</title> |
||||||
|
{{ head_macros::head(config=config) }} |
||||||
|
|
||||||
|
{%- if config.generate_rss %} |
||||||
|
<link rel="alternate" type="application/rss+xml" title="RSS" href="{{ get_url(path='rss.xml') | safe }}"> |
||||||
|
{% endif -%} |
||||||
|
|
||||||
|
{%- if config.extra.favicon %} |
||||||
|
<link rel="shortcut icon" type="{{ config.extra.favicon_mimetype | default(value='image/x-icon') }}" |
||||||
|
href="{{ config.extra.favicon | safe }}"> |
||||||
|
{% endif -%} |
||||||
|
|
||||||
|
<link rel="stylesheet" href="{{ get_url(path='custom.css') | safe }}"> |
||||||
|
|
||||||
|
{%- block extra_head %} |
||||||
|
{% endblock extra_head -%} |
||||||
|
</head> |
||||||
|
|
||||||
|
<body class=""> |
||||||
|
<div class="container"> |
||||||
|
{% block header %} |
||||||
|
<header class="header"> |
||||||
|
<div class="header__inner"> |
||||||
|
<div class="header__logo"> |
||||||
|
{%- if config.extra.logo_home_link %} |
||||||
|
{% set logo_link = config.extra.logo_home_link %} |
||||||
|
{% else %} |
||||||
|
{% set logo_link = config.base_url %} |
||||||
|
{% endif -%} |
||||||
|
<a href="{{ logo_link | safe }}" style="text-decoration: none;"> |
||||||
|
<div class="logo"> |
||||||
|
{% block logo_content %} |
||||||
|
{%- if config.extra.logo_text %} |
||||||
|
{{ config.extra.logo_text }} |
||||||
|
{% else %} |
||||||
|
Terminimal theme |
||||||
|
{% endif -%} |
||||||
|
{% endblock logo_content %} |
||||||
|
</div> |
||||||
|
</a> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
{% block header_menu %} |
||||||
|
{{ menu_macros::menu(config=config, current_path=current_path) }} |
||||||
|
{% endblock header_menu %} |
||||||
|
</header> |
||||||
|
{% endblock header %} |
||||||
|
|
||||||
|
<div class="content"> |
||||||
|
{% block content %} |
||||||
|
<div class="posts"> |
||||||
|
{%- if paginator %} |
||||||
|
{%- set show_pages = paginator.pages -%} |
||||||
|
{% else %} |
||||||
|
{%- set show_pages = section.pages -%} |
||||||
|
{% endif -%} |
||||||
|
|
||||||
|
{%- for page in show_pages %} |
||||||
|
<div class="post on-list"> |
||||||
|
{{ post_macros::header(page=page) }} |
||||||
|
{{ post_macros::content(page=page, summary=true) }} |
||||||
|
</div> |
||||||
|
{% endfor -%} |
||||||
|
<div class="pagination"> |
||||||
|
<div class="pagination__buttons"> |
||||||
|
{%- if paginator.previous %} |
||||||
|
<span class="button previous"> |
||||||
|
<a href="{{ paginator.previous | safe }}"> |
||||||
|
<span class="button__icon">←</span> |
||||||
|
<span class="button__text">Newer posts</span> |
||||||
|
</a> |
||||||
|
</span> |
||||||
|
{% endif -%} |
||||||
|
{%- if paginator.next %} |
||||||
|
<span class="button next"> |
||||||
|
<a href="{{ paginator.next | safe }}"> |
||||||
|
<span class="button__text">Older posts</span> |
||||||
|
<span class="button__icon">→</span> |
||||||
|
</a> |
||||||
|
</span> |
||||||
|
{% endif -%} |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
{% endblock content %} |
||||||
|
</div> |
||||||
|
|
||||||
|
{% block footer %} |
||||||
|
<footer class="footer"> |
||||||
|
<div class="footer__inner"> |
||||||
|
{%- if config.extra.copyright_html %} |
||||||
|
<div class="copyright copyright--user">{{ config.extra.copyright_html | safe }}</div> |
||||||
|
{% else %} |
||||||
|
<div class="copyright"> |
||||||
|
{%- if config.extra.author %} |
||||||
|
<span>© {{ date_macros::now_year() }} {{ config.extra.author }}</span> |
||||||
|
{% else %} |
||||||
|
<span>© {{ date_macros::now_year() }} Powered by <a href="https://www.getzola.org/">Zola</a></span> |
||||||
|
{% endif -%} |
||||||
|
|
||||||
|
<span class="copyright-theme"> |
||||||
|
<span class="copyright-theme-sep">:: </span> |
||||||
|
Theme: <a href="https://github.com/pawroman/zola-theme-terminimal/">Terminimal</a> by pawroman |
||||||
|
</span> |
||||||
|
</div> |
||||||
|
{% endif -%} |
||||||
|
</div> |
||||||
|
</footer> |
||||||
|
{% endblock footer %} |
||||||
|
|
||||||
|
</div> |
||||||
|
</body> |
||||||
|
|
||||||
|
</html> |
@ -0,0 +1 @@ |
|||||||
|
Subproject commit 0cc423545a63a9bd6ea6fc66068d03625d574876 |
Loading…
Reference in new issue