type state pattern, который позволяет определить различные состояния, в которых может находиться объект, определить конкретные действия для каждого состояния и обеспечить допустимые переходы между состояниями.
На самом деле использовать вот такой способ не очень удобно, если нам вдруг понадобятся новые поля, специфичные для роли.
Лучше немного попотеть и написать отдельную структуру для каждого состояния с базовой структурой. Тогда мы не потеряем свойство "определить конкретные действия для каждого состояния и обеспечить допустимые переходы между состояниями", но при этом появляется гибкость в создании специфичных полей:
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(), который и будет гарантировать валидность содержимого.
Почему только у rust лямбда сохраняется в переменную? У вас какое-то особое отношение к нему?
преимущество синтаксиса Go - в том, что в нем лямбда-функции объявляются в точности также как и "обычные". ... В остальных же языках - зоопарк кто во что горазд.
Но ведь лямбда это не обычная функция. Она может захватывать значения из зоны видимости и даже менять их. Мне, кстати, наоборот лямбда через func не нравится в Go, но это дело вкуса.
Да, такой вариант уже приятнее глазу, но он всё еще не сравнится с оператором ?. А для него необходимо иметь возвращаемое значение вида как минимум Option<()> что воспринимается как: можем вернуть ничего либо ничего. Хотя мне кажется здесь лучше вернуть ошибку, если Ктулху не пришел и ее пробросить выше, но нужно смотреть на контекст.
Правильно. Если хочется избежать копирование можно использовать RefCell, но с ним уже нужно быть внимательным: он переносит проверки подсчёта ссылок из компиляции в рантайм и можно словить панику создав 2 ссылки на содержимое если одна из них мутабельная. Например так:
let val = std::cell::RefCell::new(42);
let a = val.borrow();. // ок
let b = val borrow();. // ок
let c = val borrow_mut(); // паника
Индикатор мигает, будто компьютер спит, при этом на видео отчётливо слышен шум вентиляторов, причём на высокой скорости.
Встречался с противоположной ситуацией на старом Toshiba satellite: при переходе в сон, вентилятор резко выключался, а лампочка продолжала показывать что ноут все ещё работает. И так мог минут 10 висеть и сильно греться. После какого-то обновления и лампочка стала показывать что ноут во сне, но все равно грелся. Накатил линь: там мог рандомно включиться (это было и на Винде), решилось выключением wake on lan в биосе.
Возможно я не правильно исползовал термин. Я имел ввиду использование памяти, которая вроде уже выделена для нашей программы, но физически она нигде не занимает место (ни в ram, ни в swap, ни на диске), до момента обращения к ней. Подозревал что подобный функционал реализован на железном уровне, но для его использования необходимы специальные вызовы. Ещё не копал в эту сторону, поэтому буду благодарен за какую-нибудь ссылку.
Изм: Быстрым гуглением ничего не нашел. Похоже придется реализовывать подобное на уровне программы.
Изм 2: нашел - называется overcommit, и похоже есть только на Линукс. Работает через обычный malloc, требуется настройка ядра. Вот и подводный камень.
Спасибо, отличный трюк. Сам хотел как-то сделать подобный хеш-мап, но на плюсах и с использованием виртуальной памяти. Не подскажете какие могут быть подводные камни при ее использовании?
А зачем использовать do { ... } while(0)? Разве нельзя просто обернуть в фигурные скобки? Это какой-то негласный стандарт или просто исторически сложилось?
Американские СА будут в доверенных до первого инцедента. А что будет в случае инцедента с неправомерным использованием Российского СА? Перевыпуск? Произошло один раз - произойдет снова.
Я считал, что это уже дорого для подобных брендов.
А вы берете телефон или бренд?
Второй момент с андроидом - ты не когда не знаешь, что конкретно у тебя будет установлено и насколько долго будет осуществляться поддержка.
Для меня, как никогда не использовавшему продукцию яблока, справедливо и в обратную сторону. И это все гуглится, как для яблока так и для конкретного бренда с андрюхой.
Lenovo на андроиде с 4й версией, только через пару лет появилась возможность установить 5ю, в то время, как она уже года 1,5 существовала. И все! Больше обновлений я не увидел.
Соглашусь такое часто бывает у бюджетных моделей. Их поддержка намного ниже приоритетом чем флагманы. Пользовательские прошивки в данном случае выход - можно найти вариант который работает стабильнее и имеет больше функционала чем официальная прошивка. Но это только если не страшно брать в руки бубен.
И при таком подходе тебе еще и рекламу показывают )))
Я вот никогда не видел рекламу в системе на своем телефоне - сразу шью, собранную на своем ноуте, прошивку, и не могу представить как можно жить с рекламой в системе.
вводя пароль в консоли его можно оставить в истории shell
Ничего подобного. В тексте данной статьи действительно есть такие слова, сбивающие с толку:
$ cryptsetup open /dev/sdX vaultdrive
Я придумал фразу (а точнее, просто пароль в одно слово) «vaultdrive».
Но в данном контексте "vaultdrive" — это не пароль (возможно автор статьи и использовал такой пароль, но это осталось за кадром). Это просто имя, которое будет задано для виртуального дешифрованного устройства в папке /dev/mapper/.
Пароль будет запрошен во время выполнения программы и в историю bash не попадет.
Дать пароль другу от своего домашнего файфая сюда относится?
Раздавать интернет с телефона друзьям?
Дать позвонить кому-то со своего телефона?
Наверно надо углубиться в оригинальный текст, чтобы понять, но там все на эльфийском для меня.
На самом деле использовать вот такой способ не очень удобно, если нам вдруг понадобятся новые поля, специфичные для роли.
Лучше немного попотеть и написать отдельную структуру для каждого состояния с базовой структурой. Тогда мы не потеряем свойство "определить конкретные действия для каждого состояния и обеспечить допустимые переходы между состояниями", но при этом появляется гибкость в создании специфичных полей:
А чтобы ими было удобно пользоваться, можно реализовать трейт
Deref
для каждого:Это позволит использовать поля и методы внутренней структуры
InnerUser
как их собственные:Для
User
иEmail
он будет сгенерирован компилятором с помощью#[derive(Debug)]
при объявлении, и их достаточно. А вот для скрытия пароля автоматический не подойдёт, и поэтому дляPassword
он был определен вручную.Лучше оставить, так как тип задумывался что будет содержать только валидное значение. В моем примере я опустил этот метод для простоты. Так как код находится в пределах одного файла, то есть доступ до приватных полей структур в этом файле. В реальном проекте структуры
User
,Email
иPassword
будут в отдельном файле, и создание будет возможно только через методparse()
, который и будет гарантировать валидность содержимого.Тогда я напишу. Это можно решить переопределением трейта
Debug
для типаPassword
:Почему только у rust лямбда сохраняется в переменную? У вас какое-то особое отношение к нему?
Но ведь лямбда это не обычная функция. Она может захватывать значения из зоны видимости и даже менять их. Мне, кстати, наоборот лямбда через
func
не нравится в Go, но это дело вкуса.Все относительно:
vs
Да, такой вариант уже приятнее глазу, но он всё еще не сравнится с оператором
?
. А для него необходимо иметь возвращаемое значение вида как минимумOption<()>
что воспринимается как: можем вернуть ничего либо ничего. Хотя мне кажется здесь лучше вернуть ошибку, если Ктулху не пришел и ее пробросить выше, но нужно смотреть на контекст.Как один из упоротых вариантов: можно распаковать перед использованием, и потом с распакованным значением работать. Но выглядит как-то так себе:
В таких случаях очень хорошо бы использовать
?
, но это не всегда возможноПравильно. Если хочется избежать копирование можно использовать
RefCell
, но с ним уже нужно быть внимательным: он переносит проверки подсчёта ссылок из компиляции в рантайм и можно словить панику создав 2 ссылки на содержимое если одна из них мутабельная. Например так:Можно завернуть поле
p
вstd::cell::Cell
. Вроде только оно изменяется, но если нет то и другие изменяемые поля завернуть.Встречался с противоположной ситуацией на старом Toshiba satellite: при переходе в сон, вентилятор резко выключался, а лампочка продолжала показывать что ноут все ещё работает. И так мог минут 10 висеть и сильно греться. После какого-то обновления и лампочка стала показывать что ноут во сне, но все равно грелся. Накатил линь: там мог рандомно включиться (это было и на Винде), решилось выключением wake on lan в биосе.
Нашел статью у себя в закладках, может кому-то пригодится: https://habr.com/p/537568
Возможно я не правильно исползовал термин. Я имел ввиду использование памяти, которая вроде уже выделена для нашей программы, но физически она нигде не занимает место (ни в ram, ни в swap, ни на диске), до момента обращения к ней. Подозревал что подобный функционал реализован на железном уровне, но для его использования необходимы специальные вызовы. Ещё не копал в эту сторону, поэтому буду благодарен за какую-нибудь ссылку.
Изм: Быстрым гуглением ничего не нашел. Похоже придется реализовывать подобное на уровне программы.
Изм 2: нашел - называется overcommit, и похоже есть только на Линукс. Работает через обычный malloc, требуется настройка ядра. Вот и подводный камень.
Спасибо, отличный трюк. Сам хотел как-то сделать подобный хеш-мап, но на плюсах и с использованием виртуальной памяти. Не подскажете какие могут быть подводные камни при ее использовании?
А зачем использовать
do { ... } while(0)
? Разве нельзя просто обернуть в фигурные скобки? Это какой-то негласный стандарт или просто исторически сложилось?Американские СА будут в доверенных до первого инцедента. А что будет в случае инцедента с неправомерным использованием Российского СА? Перевыпуск? Произошло один раз - произойдет снова.
А вы берете телефон или бренд?
Для меня, как никогда не использовавшему продукцию яблока, справедливо и в обратную сторону. И это все гуглится, как для яблока так и для конкретного бренда с андрюхой.
Соглашусь такое часто бывает у бюджетных моделей. Их поддержка намного ниже приоритетом чем флагманы. Пользовательские прошивки в данном случае выход - можно найти вариант который работает стабильнее и имеет больше функционала чем официальная прошивка. Но это только если не страшно брать в руки бубен.
Я вот никогда не видел рекламу в системе на своем телефоне - сразу шью, собранную на своем ноуте, прошивку, и не могу представить как можно жить с рекламой в системе.
Замените одну строку:
Будет работать. Только говорят что
std::function<T>
медленный. Ручаться не буду, но имейте ввиду.1) можно "забыть забыть"
2) а зачем использовать асимметричное шифрование, там где можно использовать хеширование?
Ничего подобного. В тексте данной статьи действительно есть такие слова, сбивающие с толку:
Но в данном контексте "vaultdrive" — это не пароль (возможно автор статьи и использовал такой пароль, но это осталось за кадром). Это просто имя, которое будет задано для виртуального дешифрованного устройства в папке
/dev/mapper/
.Пароль будет запрошен во время выполнения программы и в историю
bash
не попадет.