1.83K subscribers
3.3K photos
132 videos
15 files
3.58K links
Блог со звёздочкой.

Много репостов, немножко программирования.

Небольшое прикольное комьюнити: @decltype_chat_ptr_t
Автор: @insert_reference_here
Download Telegram
Forwarded from XYZ
This media is not supported in your browser
VIEW IN TELEGRAM
Небольшой лайфхак по созданию анимаций в пиксель-арте.

Для начала просто запишите видео с собой, в котором вы выполняете необходимое для игры действие. Затем существенно понизьте разрешение и частоту кадров ролика, заодно зафиксируйте основные движущиеся точки.

Уберите с фона всё, кроме этих точек. А уже на их основе вы можете нарисовать любого персонажа — и получить требуемую анимацию непосредственно для игры.
Forwarded from Jem
Девелоперская док-ансейф-прокрастинация — ситуация, когда разработчик правит в коде мелкие огрехи вместо того, чтобы написать safety docs для unsafe блоков.

Это я сейчас, если что.
#itsec #article

Впечатляющая статья о многоходовочке, позволяющей выбраться из изоляции контейнера и получить root-права
Forwarded from Life of Tau
Как я дошла до того, что доказываю, что «шо» звучит очень няшно?..
#rust и тут просится ещё какой-то хештег, только я не знаю, какой
#meme

И ведь немного жаль, что такого не будет
Блог*
Что делает @insert_reference_here, когда у него освобождается свободное время в выходные? Ну разумеется решает заковыристую задачку с лайфтаймами с работы.
Что делает @insert_reference_here, когда у него освобождается свободное время в выходные? Ну разумеется решает чужую заковыристую задачку с macro_rules!.
Forwarded from Reactor Live
This media is not supported in your browser
VIEW IN TELEGRAM
joy/ #interestingasfuck
Извлечение электричества из катушки Теслы с помощью шприца
#prog #rust

Хозяйке на заметку

Как известно, в macro_rules! можно использовать спецификатор повтора ? в форме $(some complex pattern)?. Вопрос: что делать, если опицональный захват нужно развернуть в Some($захват), если он есть, и в None, если его нету? Очень просто: достаточно делегировать эту задачу очень простому макросу make_option!:

macro_rules! make_option {
() => { ::core::option::Option::None };
($($anything:tt)*) => { ::core::option::Option::Some($($anything)*) };
}

Разумеется, это будет работать без сбоев только в том случае, если захват не может соответствовать пустой последовательности лексем.
#itsec #article

И да, извините, что в этот раз не прочитал статью целиком (пока). Одним из уязвимых мест оказался парсер изображений. Сложный парсинг, который запускается на недоверенных данных и потому может стать вектором хакерской атаки — просто идеальный юзкейс для Rust.
Извините, что ночью, но исследователи утверждают, что Pegasus стабильно взламывает самую последнюю версию айфона (14.6). Без всяких кликов по ссылкам, просто посылают жертве «заряженную смску» (сообщение в iMessage) и всё, атакующий владеет телефоном.

Речь идет об использовании уязвимости нулевого дня, о которой пока не знает Apple. Благодаря этому, атакующие могут даже не сохранять взлом в долгосрочной памяти, так что после перезагрузки телефона почти все следы атаки стираются — будет нужно, взломают ещё раз. Это усложняет исследование.

Владельцы андроидов могут не радоваться, там всё настолько печально, что нет возможности даже определить, был ли взлом.

Подробная техническая статья и супер понятный пересказ в твиттере. Прям мурашки по коже, будто читаю сценарий кино, а не на самом деле.

Если вы интересны спецслужбам — выключите iMessage в настройках айфона.
Блог*
#prog Переписал по работе одну утилиту для анализа логов. Раньше для разбора строк использовались регулярные выражения, а я заменил на наколенный лексер. В результате утилита, которая почти 23 гигабайта перемалывает за чуть больше, чем за 5 минут, стала на…
#prog #rust #parsing #моё

Хочу поделиться своей техникой написания наколеночного парсера, которую я применил для этой утилиты. Она очень простая и потому не очень мощная, но для разбора простых форматов хватает. При этом, как показала практика, она может быть быстрее регулярок. Сразу скажу, что этот подход не подойдёт, если требуются детальные сообщения об ошибках.

Начнём с определения центральной структуры для разбора:

#[derive(Clone)]
struct Lexer<'a> {
s: &'a str,
}

impl<'a> Lexer<'a> {
fn of(s: &'a str) -> Self {
Self { s }
}
}

Да, всё верно, это буквально обёртка над строковым слайсом. Все последующие методы будут принимать мутабельную ссылку на Lexer и будут возвращать Option<Something>, где Some означает, что нечто удалось распарсить, а None будет обозначать ошибку. При этом все эти методы будут следовать одному правилу: если что-то распарсить не удалось, то Lexer остаётся ровно в том же состоянии, что был до вызова.

Начнём с метода, который будет обозначать конец разбора — он пригодится нам, чтобы удостовериться, что мы не оставили никакого мусора:

fn end(&mut self) -> Option<()> {
if self.s.is_empty() {
Some(())
} else {
None
}
}

Следующий метод не очень полезен сам по себе, но он потребуется для других методов. Он просто будет сдвигать позицию, с которой производится парсинг:

fn shift(&mut self, pos: usize) {
self.s = &self.s[pos..];
}

Что ж, теперь напишем самый простой метод, который действительно что-то парсит, а именно — конкретную переданную строку:

fn literal(&mut self, literal: &str) -> Option<()> {
self.s = self.s.strip_prefix(literal)?;
Some(())
}

Не менее полезным будет метод, который возвращает то, что находится до переданной строки:

fn before_literal(&mut self, literal: &str) -> Option<&'a str> {
let pos = self.s.find(literal)?;
let ret = &self.s[..pos];
self.shift(pos + literal.len());
Some(ret)
}

Ну и первый метод, который делает по настоящему нетривиальный разбор: парсинг беззнакового числа:

fn number<Num: std::str::FromStr>(&mut self) -> Option<Num> {
let pos = self
.s
.as_bytes()
.iter()
.position(|ch| !ch.is_ascii_digit())
.unwrap_or(self.s.len());
let ret = self.s[..pos].parse().ok()?;
self.shift(pos);
Some(ret)
}

Clippy тут, к сожалению, ругается на вызов .unwrap_or(self.s.len())... Точнее, ругался раньше, теперь это исправили. Отлично!

Казалось бы, что можно сделать с таким набором методов? Ну, этого уже достаточно, чтобы распарсить IPv4-адрес:

#[derive(PartialEq, Debug)]
struct Ip4Addr([u8; 4]);

fn parse_ip(s: &str) -> Option<Ip4Addr> {
let mut p = Lexer::of(s);
let a = p.number()?;
p.literal(".")?;
let b = p.number()?;
p.literal(".")?;
let c = p.number()?;
p.literal(".")?;
let d = p.number()?;
p.end()?;
Some(Ip4Addr([a, b, c, d]))
}

fn main() {
assert_eq!(parse_ip("12.32.200.21"), Some(Ip4Addr([12, 32, 200, 21])));
}

Обратите внимание, благодаря выводу типов нам не пришлось уточнять тип для p.number().

Но далеко не все форматы являются столь же простыми и линейными. Добавим чуточку больше возможностей, а именно — возможность распарсить что-то опционально. В отличие от предыдущих методов, тут None не будет фатальной ошибкой:

fn optional<T, F: FnOnce(&mut Self) -> Option<T>>(&mut self, f: F) -> Option<T> {
let backtrack = self.clone();
let ret = f(self);
if ret.is_none() {
*self = backtrack;
}
ret
}

В принципе, теперь мы можем распарсить IP4-адрес с опциональной маской подсети, но я покажу кое-что более интересное: парсинг из задачи Advent of Code 2020.