parent
71c3d42e70
commit
c454481967
21 changed files with 370 additions and 63 deletions
@ -1,3 +1,5 @@ |
||||
+++ |
||||
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