Skip to content

Instantly share code, notes, and snippets.

@AnthonyMikh
Created August 5, 2021 23:06
Show Gist options
  • Save AnthonyMikh/58d6cd2e967f5b12ff615d169024fb2f to your computer and use it in GitHub Desktop.
Save AnthonyMikh/58d6cd2e967f5b12ff615d169024fb2f to your computer and use it in GitHub Desktop.
Automatic cleanup of resources wuth a specified operation
struct AutoDo<T, F> {
value: T,
action: F,
}
struct DoOnDrop<'a, T, F: FnMut(&mut T)>(&'a mut AutoDo<T, F>);
impl<T, F> AutoDo<T, F> {
fn new(value: T, action: F) -> Self {
Self { value, action }
}
fn get(&mut self) -> DoOnDrop<'_, T, F>
where
F: for<'a> FnMut(&'a mut T),
{
DoOnDrop(self)
}
fn into_inner(self) -> T {
self.value
}
}
impl<'a, T, F: FnMut(&mut T)> Drop for DoOnDrop<'a, T, F> {
fn drop(&mut self) {
(self.0.action)(&mut self.0.value)
}
}
impl<'a, T, F: FnMut(&mut T)> std::ops::Deref for DoOnDrop<'a, T, F> {
type Target = T;
fn deref(&self) -> &T {
&self.0.value
}
}
impl<'a, T, F: FnMut(&mut T)> std::ops::DerefMut for DoOnDrop<'a, T, F> {
fn deref_mut(&mut self) -> &mut T {
&mut self.0.value
}
}
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()); // буфер в итоге пустой
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment