use chrono::Utc;
use std::{
io::{self, BufRead as _},
sync::mpsc::{self, RecvTimeoutError, Sender},
thread,
time::{Duration, Instant},
};
enum Op {
Add(String),
Del(String),
}
const PRINT_INTERVAL: Duration = Duration::from_secs(10);
fn main() {
println!("---\n{}\n---\n", Utc::now());
let (tx, rx) = mpsc::channel();
start_stdin_thread(tx);
let mut strings = Vec::new();
let mut last_print = Instant::now();
loop {
match rx.recv_timeout(PRINT_INTERVAL - last_print.elapsed()) {
Err(RecvTimeoutError::Disconnected) => break,
Err(RecvTimeoutError::Timeout) => {
println!("---\n{}\n{:?}\n---\n", Utc::now(), strings);
last_print = Instant::now();
}
Ok(Op::Add(s)) => {
strings.push(s);
}
Ok(Op::Del(s)) => {
strings.retain(|v| v != &s);
}
}
}
}
fn start_stdin_thread(tx: Sender<Op>) {
#[derive(Clone, Copy)]
enum OpRaw {
Add,
Del,
}
thread::spawn(move || {
let mut stdin = io::stdin().lock();
let mut buf = String::with_capacity(1024);
let mut read_line = |buf: &mut String| -> io::Result<()> {
buf.clear();
stdin.read_line(buf).map(|_| ()).inspect_err(|err| {
eprintln!("Ошибка чтения stdin: {err}");
})
};
loop {
println!("1. Добавить текст");
println!("2. Удалить текст");
print!("Введите номер операции: ");
if read_line(&mut buf).is_err() {
break;
}
let op = match buf.trim() {
"1" => OpRaw::Add,
"2" => OpRaw::Del,
_ => {
eprintln!("Некорректная операция");
continue;
}
};
println!(
"Введите текст на {}:",
match op {
OpRaw::Add => "добавление",
OpRaw::Del => "удаление",
}
);
if read_line(&mut buf).is_err() {
break;
}
let text = buf.trim().to_string();
let op = match op {
OpRaw::Add => Op::Add(text),
OpRaw::Del => Op::Del(text),
};
if tx.send(op).is_err() {
break;
}
}
});
}
Arc<RwLock<...>>
или Arc<Mutex<...>>
, заодно и памяти меньше сожрём и не будем греть проц бесполезными аллокациями памяти и копированием вектора.Receiver
канала помимо метода recv
, который блокирует поток до получения сообщения, есть ещё методы try_recv
(не блокирует поток вообще) и recv_timeout
(блокирует, но не дольше переданного таймаута).Duration::from_millis(10)
тут явно не 10 секунд...match, enum вместо u8if console.0 == 1 { h_add_del_txt.insert(1, console.1); } else if console.0 == 2 { h_add_del_txt.insert(2, console.1); } else { // ... }
WTF?et mut g = String::new(); io::stdin().read_line(&mut g).expect("Failed to read line"); let g: String = g.trim().parse().expect("Please type a ...");
systemctl enable --now my-unit.timer
T: Sized
, Box<T>
будет занимать 8 байт на стеке и размер T на куче, а Vec<T>
- 24 байта на стеке (указатель на начало, длина и фактически выделенная память) и размер T умноженный на capacity на куче.fn main() {
let a = Box::new(42);
println!("Stack address of a: {:p}", &a);
println!("Heap address of a: {:p}", &*a);
let b = a;
println!("Stack address of b: {:p}", &b);
println!("Heap address of b: {:p}", &*b);
}
Stack address of a: 0x7fff59586010
Heap address of a: 0x58cf76717b10
Stack address of b: 0x7fff59586018
Heap address of b: 0x58cf76717b10
mod db;
будет искать файл в разных местах, в зависимости от того, где оно написано:use std::sync::atomic::{AtomicU32, Ordering};
async fn create_user(
Json(payload): Json<FromBrowser>,
) -> (StatusCode, Json<User>) {
static COUNTER: AtomicU32 = AtomicU32::new(0);
// подготавливаю данные на отправку в браузер:
let user = User {
id: payload.id,
username: payload.username,
tm: payload.tm,
cnt: COUNTER.fetch_add(1, Ordering::SeqCst), // считаю отправки;
};
(StatusCode::CREATED, Json(user))
}
&mut [MaybeUninit<*mut State>]
, инициализируете элементы и после std::mem::transmute
в &mut [*mut State]