• Вызов drop в вызове drop?

    bingo347
    @bingo347
    Crazy on performance...
    Почему drop принимает ссылку, а не значение?

    Потому что метод drop трейта Drop вызывается компилятором, каждый раз когда переменная владеющая чем-либо выходит из области видимости. И сам метод drop тут не исключение. То есть если бы self тут был по значению, компилятор был бы обязан его дропнуть в конце функции, что вызвало бы бесконечную рекурсию.

    Причём если вызывать drop() руками
    Функция core::mem::drop никакого отношения к трейту Drop не имеет. Если Вы глянете на её реализацию, то это просто пустая функция, которая принимает аргумент по значению, а он уже дропается на общих основаниях, так как выходит из области видимости в ней.

    Почему сначала вызывается drop для A, а потом для B? По логике drop должен сначала вызываться для полей.
    У Вас неверная логика. В метод трейта Drop приходит ссылка, а значит должна быть гарантия того что данные по ней полностью валидные. Всегда дропается сначала внешняя структура,а затем её поля. Более того компилятор не даст Вам даже мувнуть части структуры имплиментирующей Drop.

    Если очень нужно, то владение из поля можно забрать через std::mem::swap/std::mem::replace/std::mem::take
    Хотя проще это сделать обернув такое поле в Option и забирая владение его методом take
    Ответ написан
    2 комментария
  • Как установить bspwm на Arch'е?

    bingo347
    @bingo347
    Crazy on performance...
    В арч вики же всё подробно расписано:
    https://wiki.archlinux.org/title/Bspwm_(%D0%A0%D1%...

    Так же советую поставить polybar:
    https://wiki.archlinux.org/title/Polybar_(%D0%A0%D...

    И rofi:
    https://wiki.archlinux.org/title/Rofi_(%D0%A0%D1%8...

    В уже установленной системе, чтоб прописать что-то в конфиг, зайдите в консольную сессию (Ctrl+Alt+F3) и сделайте базовые настройки через консольные редакторы (vim/neovim/nano). Как минимум пропишите сочетание на запуск терминала для начала. (Терминал тоже нужно установить, тут уж на своё усмотрение, могу порекомендовать Allacritty)
    Ответ написан
    5 комментариев
  • Почему Vite.createServer не дожидается асинхронного кода?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    У vite внутри есть собственный обработчик события request, который отвечает раньше Вашего.

    Скорее всего Вам поможет вот это:
    https://vitejs.dev/config/server-options.html#serv...
    Ответ написан
  • Как написать такой макрос?

    bingo347
    @bingo347
    Crazy on performance...
    Я бы тут не парился, и превращал бы это:
    #[r]
    fn bar(a: usize) -> usize {
        if a % 2 == 0 {
            return 0;
        }
        1
    }


    В это:
    fn bar(a: usize, res: *mut usize) {
        fn bar_impl(a: usize) -> usize {
            if a % 2 == 0 {
                return 0;
            }
            1
        }
        unsafe { *res = bar_impl(a); }
    }
    Главная фишка в том, что исходный код оставляем без изменений, парсить надо только сигнатуру (что с использованием syn - легко).
    По сути просто генерируем обёртку. Для универсальности стоит учесть async fn.

    Ну и если совсем по хорошему, то тут легко UB поймать с сырым указателем, и генерируемую функцию имеет смысл делать unsafe.
    Ответ написан
    Комментировать
  • Возврат собственного типа ошибки из main с печатью сообщения об ошибке?

    bingo347
    @bingo347
    Crazy on performance...
    fn main() -> MainResultWrapper {
        MainResultWrapper(main_inner())
    }
    
    #[inline(always)]
    fn main_inner() -> Result<(), GlobalError> {
        let config = read_config_from_file()?;
        Ok(())
    }
    Ответ написан
    Комментировать
  • Как в Intersection Observer узнать, что элемент пропал из поля зрения?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Ответ написан
    Комментировать
  • Как внести в массив символы, которым соответствует диапазон u8?

    bingo347
    @bingo347
    Crazy on performance...
    fn main() {
        let src: Vec<[u8; 1]> = (0..u8::MAX).map(|i| [i]).collect();
        let mut info =  Vec::<&str>::with_capacity(u8::MAX.into());
        for u in &src {
            let t = std::str::from_utf8(&*u).unwrap_or("Err");
            info.push(t);
        }
        println!("\n{:#?}", info);
    }

    но надо понимать, что info будет связан лайфтаймом с src, чтоб избавится от этого нужно хранить в нём не &str а String или Box<str>
    fn main() {
        let info: Vec<Box<str>> = (0..u8::MAX).map(|i| {
            let u = [i];
            let t = std::str::from_utf8(&u).unwrap_or("Err");
            t.into()
        }).collect();
        println!("\n{:#?}", info);
    }
    Ответ написан
    1 комментарий
  • Как использовать модуль Win32 крейта windows в раст?

    bingo347
    @bingo347
    Crazy on performance...
    Попробуйте фичу Win32_System_Threading
    Ну и вот тут можно поискать если ещё что-то потребуется: https://microsoft.github.io/windows-rs/features/#/...
    Ответ написан
    Комментировать
  • Адаптация видео и фото под планшеты и телефоны, какой вариант лучше использовать?

    bingo347
    @bingo347
    Crazy on performance...
    Не нужно ничего колхозить, используйте аттрибут srcset у img и предоставьте несколько картинок. Бразуер сам разберётся какую из них лучше загружать на основе предоставленной информации в аттрибуте.
    Ответ написан
  • По какой логике bind принимает только первый контекст?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Метод bind возвращает новую функцию, которая уже игнорирует свой контекст и передаёт тот, который запомнила.
    Если в коде, то это примерно так работает:
    Function.prototype.bind = function bind(ctx, ...args) {
        const originalFunction = this;
        return function (...args2) {
            return originalFunction.apply(ctx, args.concat(args2));
        };
    }
    Как видите, возвращаемая функция уже никак не использует свой this.
    Соответственно второй вызов bind его будет передавать в пустоту, однако может добавить аргументы.
    Ответ написан
    4 комментария
  • Как исправиться ошибку lifetime?

    bingo347
    @bingo347
    Crazy on performance...
    impl<'a> List<'a> {
        fn add(&mut self, val: String, referenced_node: &'a Node) {
            self.node = Some(Node {
                data: String::from(String::from(val)),
                next: Some(referenced_node),
            });
        }
    }
    правда скорее всего будут траблы уже в месте вызова этого метода, но что бы поправить недостаточно контекста

    Вообще думаю тут имеет смысл использовать Box/Rc/Arc вместо ссылок
    Ответ написан
    Комментировать
  • Как работает этот код?

    bingo347
    @bingo347
    Crazy on performance...
    Очень упрощенно HashMap можно представить следующим образом:
    pub struct HashMap<K, V> {
        table: Table<(K, V)>,
    }
    
    struct Table<T> {
        // битовая маска занятых ячеек в items
        mask: u64,
        items: Box<[std::mem::MaybeUninit<Item<T>>; 64]>,
        len: usize,
    }
    
    struct Item<T> {
        data: T,
        next: Option<std::ptr::NonNull<Item<T>>>,
    }


    А Entry так:
    pub enum Entry<'a, K, V> {
        Vacant(VacantEntry<'a, K, V>),
        Occupied(OccupiedEntry<'a, K, V>),
    }
    
    pub struct VacantEntry<'a, K, V> {
        hash: u64,
        key: K,
        table: &'a mut Table<(K, V)>,
    }
    
    pub struct OccupiedEntry<'a, K, V> {
        elem: Bucket<(K, V)>,
        table: &'a mut Table<(K, V)>,
    }
    
    // указатель на Item.data
    struct Bucket<T> {
        ptr: std::ptr::NonNull<T>,
    }


    Как можно заметить у Entry есть лайфтайм, который связывает его с HashMap от которой он создан. А внутри есть мутабельная ссылка с этим лайфтаймом на таблицу с данными HashMap.
    Метод entry упрощенно выглядит примерно так:
    impl<K, V> HashMap<K, V> {
        pub fn entry<'a>(&'a mut self, key: K) -> Entry<'a, K, V>
        where
            K: Eq + std::hash::Hash,
        {
            use std::hash::Hasher as _;
            let mut hasher = self.get_hasher();
            key.hash(&mut hasher);
            let hash = hasher.finish();
    
            if let Some(elem) = self.table.find(hash, |(k, _)| key == *k) {
                Entry::Occupied(OccupiedEntry {
                    elem,
                    table: &mut self.table,
                })
            } else {
                Entry::Vacant(VacantEntry {
                    hash,
                    key,
                    table: &mut self.table,
                })
            }
        }
    
        fn get_hasher(&self) -> impl std::hash::Hasher {
            todo!()
        }
    }
    
    impl<T> Table<T> {
        fn find(&self, hash: u64, is_match: impl FnMut(&T) -> bool) -> Option<Bucket<T>> {
            todo!()
        }
    }

    Как видим мутабельная ссылка всё же есть, только она завернута в структуру, так как одной этой ссылки не достаточно, так как в случае свободной Entry нам нужно хранить ещё и ключ, а заодно и хэш (чтоб не считать его снова), а в случае занятой - указатель на бакет (область памяти где храниться пара ключ и значение).
    Ответ написан
    Комментировать
  • Как работают пакеты и крейты?

    bingo347
    @bingo347
    Crazy on performance...
    Крэйт - это в первую очередь дерево модулей. Каждый крэйт содержит как минимум 1 корневой модуль (обычно это main.rs или lib.rs, но так же это могут быть модули доп бинарников, модули интеграционных тестов, модули примеров). Так же к крэйту относятся модули, которые объявили в других модулях этого крейта (ключевое слово mod).
    Помимо этого крэйт - это сущность которой оперирует компилятор rustc, крэйт является единицей компиляции, то есть в rustc на компиляцию попадает крэйт целиком (на вход подаём корневой модуль, а он уже сам бегает по всему дереву согласно объявлениям mod).

    Пакет - это сущность которой оперирует cargo. Компилятор rustc ничего не знает про пакеты. По простому пакет это папка с файлом Cargo.toml, в котором есть секция package (бывают ещё Cargo.toml объявляющие только workspace). Пакет состоит из крейтов, притом должен быть как минимум 1 крейт бинарника или библиотеки, а библиотечный крейт может быть только 1 или отсутствовать вовсе.
    Пакет - это то, что публикуется в registry (такие как crates.io).
    Так же в зависимостях мы указываем именно пакеты (но только те, что содержат крэйт-библиотеку).
    Так же именно пакеты указываются в команде cargo install, при этом будут собраны все бинарные крейты входящие в пакет, а получившиеся исполняемые файлы будут помещены .cargo/bin
    Ответ написан
    2 комментария
  • Как правильно разбивать функции в javascript?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Результат вот этого будет потерян:
    let logMessage = type
        .replace('[playerKick]', name1)
        .replace('[playerDefence]', name2);


    Я бы ожидал, что функция с именем generate мне что-то вернёт, а не сделает сайд эффект.

    Можно как то так:
    export const generateLogs = (type, player1, player2, damage = 0) => {
        const { name: name1 } = player1;
        const { name: name2 } = player2;
    
        const logMessage = type
            .replace('[playerKick]', name1)
            .replace('[playerDefence]', name2);
    
        switch (type) {
            case 'start':
                return logMessage + LOGS.start
                    .replace('[time]', getTime())
                    .replace('[player1]', name1)
                    .replace('[player2]', name2);
            case 'hit':
                return logMessage + `${LOGS.hit[getRandom(0, LOGS.hit.length - 1)]
                    .replace('[playerKick]', name1)
                    .replace('[playerDefence]', name2)} -${damage} 
                    [${player2.hp} / 100]
                `;
            case 'defence':
                return logMessage + LOGS.defence[getRandom(0, LOGS.defence.length - 1)]
                    .replace('[playerKick]', name2)
                    .replace('[playerDefence]', name1);
            case 'end':
                return logMessage + LOGS.end[getRandom(0, LOGS.end.length - 1)]
                    .replace('[playerWins]', name1)
                    .replace('[playerLose]', name2);
            case 'draw':
                return logMessage + LOGS.draw;
            default:
                return logMessage + '...';
        }
    };
    
    export const insertLogs = (logMessage) => {
        const el = `<p>${logMessage}</p>`;
        chat.insertAdjacentHTML('afterbegin', el);
    };
    Ответ написан
    1 комментарий
  • Возможно ли запускать виртуальные машины с Linux Live CD с помощью Qemu?

    bingo347
    @bingo347
    Crazy on performance...
    Готовый live образ скорее всего не найдёте, но никто не мешает сделать свой.
    Типичный live образ содержит squashfs образ и загрузчик (например grub), настроенный монтировать этот образ и грузить ядро с него.
    Образ в принципе не обязан быть в squashfs и может содержать слепок любой fs пригодной для linux (ext4, btrfs, ...), но у последнего есть преимущество в виде сжатия и возможности монтирования только в ro режиме (образ не сломают).

    Сделать такой образ проще простого:
    - Собираете систему с нужными установками, например можете воспользоваться утилитой debootstrap или скачать archlinux bootstrap, разверните систему в директорию, сделайте chroot туда и доустановите необходимы софт.
    - С помощью mksquashfs соберите из папки образ.
    - Прикиньте сколько примерно нужно место под образ + grub, возьмите с запасом, сгенерируйте файлик нужного размера (например через dd if=/dev/null)
    - Натравите на файлик утилиту parted (или аналоги), сделайте в нём таблицу разделов gpt и fat32 раздел на всё место, переименуйте файлик в .iso и смонтируйте с него созданый раздел
    - закиньте туда свой образ squashfs и установите grub с настройками грузится с образа
    Ответ написан
  • Как правильно задать тип события мыши?

    bingo347
    @bingo347 Куратор тега TypeScript
    Crazy on performance...
    React.MouseEvent - это события реакта, их нельзя передавать в addEventListener, только в ноды реакта.
    Event - это наиболее обобщенный тип события.
    Вам нужен тип MouseEvent, в нём будет соответствующее свойство.
    Ну и сам element должен иметь тип HTMLElement или производные по идее.
    Ответ написан
    2 комментария
  • Как собрать свой Linux дистрибутив с grub?

    bingo347
    @bingo347
    Crazy on performance...
    Ну вот ещё туториал:
    https://habr.com/ru/articles/709528/

    А вообще адекватный туториал вот:
    https://linuxfromscratch.ru/

    А если честно, чем не угодили alpine, arch, artix, gentoo?

    получается на выходе файл .img
    Со слепком root-fs получившейся ОС? Тогда достаточно флешки форматированной в fat32, заливаете этот образ туда и делаете туда же grub-install с монтированием этого образа.
    Ответ написан
  • Чем записать возможности программы, чтобы показать на собеседовании?

    bingo347
    @bingo347
    Crazy on performance...
    - записать экран с программой
    OBS Studio
    - нанести надписи - тут такой компонент, тут делал то
    Kdenlive или DaVinci Resolve
    Ответ написан
    Комментировать
  • Как проверять линтом только измененные файлы при pre-push?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Что-то вроде такого:
    git ls-tree --name-only -r origin/HEAD | egrep '\.(js|ts)$' | xargs npx eslint
    Ответ написан
    Комментировать