Как стать автором
Поиск
Написать публикацию
Обновить
1
0

Пользователь

Отправить сообщение

Физлица, если они дают кому-то пользоваться связью в рамках своего договора, при этом, без признаков уголовки — штраф от 30 до 50 тыс. руб.

Дать пароль другу от своего домашнего файфая сюда относится?
Раздавать интернет с телефона друзьям?
Дать позвонить кому-то со своего телефона?

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

type state pattern, который позволяет определить различные состояния, в которых может находиться объект, определить конкретные действия для каждого состояния и обеспечить допустимые переходы между состояниями.

pub struct Viewer;
pub struct Editor;
pub struct Admin;

pub struct User<UserRole = Viewer> {
    pub email: Email,
    pub password: Password,
    state: PhantomData<UserRole>,
}

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

Лучше немного попотеть и написать отдельную структуру для каждого состояния с базовой структурой. Тогда мы не потеряем свойство "определить конкретные действия для каждого состояния и обеспечить допустимые переходы между состояниями", но при этом появляется гибкость в создании специфичных полей:

pub struct InnerUser {
    pub email: Email,
    pub password: Password,
}

pub struct UserViewer {
    inner: InnerUser,
    // .. специфичные поля для наблюдателя
}

pub struct UserEditor {
    inner: InnerUser,
    // .. специфичные поля для редактора
}

pub struct UserAdmin {
    inner: InnerUser,
    // .. специфичные поля для админа
}

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

impl core::ops::Deref for UserViewer {
    type Target = InnerUser;

    fn deref(&self) -> &InnerUser {
        &self.inner
    }
}

Это позволит использовать поля и методы внутренней структуры InnerUser как их собственные:

fn email_from_viewer(user: &UserViewer) -> String {
    user.email.as_str().to_string()
    //  ^
    // неявно вызывается `Deref::deref`
}

// Принимает все, что может дать ссылку на `InnerUser`, захватывая оригинальный объект.
fn email_from_any_user(user: impl core::ops::Deref<Target = InnerUser>) -> String {
    user.email.as_str().to_string()
    //  ^
    // неявно вызывается `Deref::deref`
}

добавить реализацию Debug для User, а не только для Password

Для User и Email он будет сгенерирован компилятором с помощью #[derive(Debug)] при объявлении, и их достаточно. А вот для скрытия пароля автоматический не подойдёт, и поэтому для Password он был определен вручную.

Хотя да, для валидации данных parse() лучше оставить.

Лучше оставить, так как тип задумывался что будет содержать только валидное значение. В моем примере я опустил этот метод для простоты. Так как код находится в пределах одного файла, то есть доступ до приватных полей структур в этом файле. В реальном проекте структуры User, Email и Password будут в отдельном файле, и создание будет возможно только через метод parse(), который и будет гарантировать валидность содержимого.

Но в итоге никто не показал как решить именно эту проблему.

Тогда я напишу. Это можно решить переопределением трейта Debug для типа Password:

#[derive(Debug)]
struct User {
    email: Email,
    password: Password,
}

#[derive(Debug)]
struct Email(String);

struct Password(String);

impl std::fmt::Debug for Password {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_str("[hidden]")
    }
}

fn main() {
    let user = User {
        email: Email("mail@example.com".to_string()),
        password: Password("my p@$$w0rD".to_string()),
    };

    println!("user = {user:?}");  // user = User { email: Email("mail@example.com"), password: [hidden] }
}

Почему только у rust лямбда сохраняется в переменную? У вас какое-то особое отношение к нему?

преимущество синтаксиса Go - в том, что в нем лямбда-функции объявляются в точности также как и "обычные". ... В остальных же языках - зоопарк кто во что горазд.

Но ведь лямбда это не обычная функция. Она может захватывать значения из зоны видимости и даже менять их. Мне, кстати, наоборот лямбда через func не нравится в Go, но это дело вкуса.

Все относительно:

template<typename T>
void func(const T &value);

vs

fn func<T>(value: &T);

Да, такой вариант уже приятнее глазу, но он всё еще не сравнится с оператором ?. А для него необходимо иметь возвращаемое значение вида как минимум Option<()> что воспринимается как: можем вернуть ничего либо ничего. Хотя мне кажется здесь лучше вернуть ошибку, если Ктулху не пришел и ее пробросить выше, но нужно смотреть на контекст.

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

let cthulhu = if let Some(cthulhu) = call_cthulhu() {
    cthulhu
} else {
    return;
};
// ...
tickle(cthulhu);

В таких случаях очень хорошо бы использовать ?, но это не всегда возможно

Правильно. Если хочется избежать копирование можно использовать RefCell, но с ним уже нужно быть внимательным: он переносит проверки подсчёта ссылок из компиляции в рантайм и можно словить панику создав 2 ссылки на содержимое если одна из них мутабельная. Например так:

let val = std::cell::RefCell::new(42);
let a = val.borrow();.    // ок
let b = val borrow();.    // ок
let c = val borrow_mut(); // паника

Можно завернуть поле p в std::cell::Cell. Вроде только оно изменяется, но если нет то и другие изменяемые поля завернуть.

Индикатор мигает, будто компьютер спит, при этом на видео отчётливо слышен шум вентиляторов, причём на высокой скорости.

Встречался с противоположной ситуацией на старом Toshiba satellite: при переходе в сон, вентилятор резко выключался, а лампочка продолжала показывать что ноут все ещё работает. И так мог минут 10 висеть и сильно греться. После какого-то обновления и лампочка стала показывать что ноут во сне, но все равно грелся. Накатил линь: там мог рандомно включиться (это было и на Винде), решилось выключением wake on lan в биосе.

Нашел статью у себя в закладках, может кому-то пригодится: https://habr.com/p/537568

Возможно я не правильно исползовал термин. Я имел ввиду использование памяти, которая вроде уже выделена для нашей программы, но физически она нигде не занимает место (ни в ram, ни в swap, ни на диске), до момента обращения к ней. Подозревал что подобный функционал реализован на железном уровне, но для его использования необходимы специальные вызовы. Ещё не копал в эту сторону, поэтому буду благодарен за какую-нибудь ссылку.

Изм: Быстрым гуглением ничего не нашел. Похоже придется реализовывать подобное на уровне программы.

Изм 2: нашел - называется overcommit, и похоже есть только на Линукс. Работает через обычный malloc, требуется настройка ядра. Вот и подводный камень.

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

А зачем использовать do { ... } while(0)? Разве нельзя просто обернуть в фигурные скобки? Это какой-то негласный стандарт или просто исторически сложилось?

Американские СА будут в доверенных до первого инцедента. А что будет в случае инцедента с неправомерным использованием Российского СА? Перевыпуск? Произошло один раз - произойдет снова.

Я считал, что это уже дорого для подобных брендов.

А вы берете телефон или бренд?

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

Для меня, как никогда не использовавшему продукцию яблока, справедливо и в обратную сторону. И это все гуглится, как для яблока так и для конкретного бренда с андрюхой.

Lenovo на андроиде с 4й версией, только через пару лет появилась возможность установить 5ю, в то время, как она уже года 1,5 существовала. И все! Больше обновлений я не увидел.

Соглашусь такое часто бывает у бюджетных моделей. Их поддержка намного ниже приоритетом чем флагманы. Пользовательские прошивки в данном случае выход - можно найти вариант который работает стабильнее и имеет больше функционала чем официальная прошивка. Но это только если не страшно брать в руки бубен.

И при таком подходе тебе еще и рекламу показывают )))

Я вот никогда не видел рекламу в системе на своем телефоне - сразу шью, собранную на своем ноуте, прошивку, и не могу представить как можно жить с рекламой в системе.

Замените одну строку:

using TT = std::function<void()>;

Будет работать. Только говорят что std::function<T> медленный. Ручаться не буду, но имейте ввиду.

1) можно "забыть забыть"

2) а зачем использовать асимметричное шифрование, там где можно использовать хеширование?

вводя пароль в консоли его можно оставить в истории shell

Ничего подобного. В тексте данной статьи действительно есть такие слова, сбивающие с толку:


$ cryptsetup open /dev/sdX vaultdrive


Я придумал фразу (а точнее, просто пароль в одно слово) «vaultdrive».

Но в данном контексте "vaultdrive" — это не пароль (возможно автор статьи и использовал такой пароль, но это осталось за кадром). Это просто имя, которое будет задано для виртуального дешифрованного устройства в папке /dev/mapper/.
Пароль будет запрошен во время выполнения программы и в историю bash не попадет.

1

Информация

В рейтинге
10 172-й
Откуда
Барнаул, Алтайский край, Россия
Дата рождения
Зарегистрирован
Активность

Специализация

Software Developer
Senior
C++
Qt
Linux
Git
Python
Golang
JavaScript
Vue.js
TypeScript