
Size: a a a



impl VaultKeySet {
fn get_label(&self) -> String {
match self.key_data.label() {
Some(label) if !label.is_empty() => label.into(),
_ => format!("{}{}", KEY_LEGACY_PREFIX, self.legacy_number),
}
}
}label отсутствует, то последующий код не исполняется вовсе. И никаких причудливых танцев с .has_value() и оператором разыменования с неопределённым поведением.

На этом месте была статья, которая больно задела чувства большого числа наших покупателей, сотрудников, партнеров и поставщиков.
Мы сожалеем, что так получилось, и считаем эту публикацию своей ошибкой, ставшей проявлением непрофессионализма отдельных сотрудников.
Ожидаемо, на него обрушился шквал критики с противоположной стороны — на этот раз за то, что прогнулись под требования гомофобов (подавляющее большинство которых даже не были покупателями магазина). При этом надо отметить, что даже с сугубо с точки зрения бизнеса этот манёвр был проигрышным: Вкуссвилл потерял заметную долю лояльной аудитории и при этом не приобрёл новой.



read_to_string, но забывают очищать строку в конце итерации, из-за чего в строке остаётся то, что было прочитано на предыдущих операциях. Более того, просто воткнуть s.clear(); в конце тела может быть недостаточно: если в цикле есть оператор continue, то до исполнения этой строчки дело может и не дойти — в подобных случаях не только новички делают ошибки. Было бы хорошо иметь что-то, что выполняется автоматически в конце каждой итерации цикла вне зависимости то того, как она выполняется... И такая вещь в Rust есть: Drop::drop aka деструктор!struct AutoDo<T, F> {
value: T,
action: F,
}struct DoOnDrop<'a, T, F>(&'a mut AutoDo<T, F>);
F — которое неизбежно появится для описания того факта, что это функция — повторялось при определении структуры. Без выполнения этого требования компилятор выдаст ошибку. А как, собственно говоря, должно выглядеть это требование? Это должна быть функция, которая принимает мутабельную ссылку на значение, причём не с каким-то конкретным временем жизни, а с произвольным. В итоге определение выглядит так:struct DoOnDrop<'a, T, F: FnMut(&mut T)>(&'a mut AutoDo<T, F>);
struct DoOnDrop<'a, T, F: for<'val> FnMut(&'val mut T)>(&'a mut AutoDo<T, F>);
impl<'a, T, F: FnMut(&mut T)> Drop for DoOnDrop<'a, T, F> {
fn drop(&mut self) {
(self.0.action)(&mut self.0.value)
}
}self.0.action тут необходимы, поскольку иначе это будет проинтепретировано, как вызов метода AutoDo::action, коего, разумеется нет.DoOnDrop трейты Deref{, Mut}<Target = T>, а также метод AutoDo::get, который будет оборачивать ссылку в DoOnDrop. Реализацию, с вашего позволения, опущу в силу тривиальности.nope — их она будет просто отбрасывать:fn main() {
use std::io::Read;
let stdin = std::io::stdin();
let mut stdin = stdin.lock();
let mut buf = AutoDo::new(String::new(), String::clear);
loop {
let mut buf = buf.get();
if let Ok(0) | Err(_) = stdin.read_to_string(&mut buf) {
break;
}
if buf.contains("nope") {
continue; // работает и с continue
}
println!("{}", buf.to_uppercase());
}
let buf = buf.into_inner();
assert!(buf.is_empty()); // буфер в итоге пустой
}




std::variant — могли бы сделать нормальный паттерн-матчинг, а получилось какое-то дикое говно, которое невозможно читать, а написать корректно ещё сложнее. И ещё пачку новых способов инициализации, куда же без этого.