syslog_rs/a_sync/async_tokio/
async_internal.rs

1/*-
2 * syslog-rs - a syslog client translated from libc to rust
3 * 
4 * Copyright 2025 Aleksandr Morozov
5 * 
6 * The syslog-rs crate can be redistributed and/or modified
7 * under the terms of either of the following licenses:
8 *
9 *   1. the Mozilla Public License Version 2.0 (the “MPL”) OR
10 *                     
11 *   2. EUROPEAN UNION PUBLIC LICENCE v. 1.2 EUPL © the European Union 2007, 2016
12 */
13
14use std::{borrow::Cow, io::IoSlice, time::Duration};
15
16use nix::libc;
17use tokio::{fs::File, io::{AsyncWrite, AsyncWriteExt}, time::sleep};
18
19use crate::{a_sync::syslog_async_internal::AsyncSyslogInternalIO, error::SyRes, map_error_os, LogStat, PATH_CONSOLE};
20
21pub type DefaultIOs = TokioIOs;
22
23#[derive(Debug, Clone)]
24pub struct TokioIOs;
25
26impl TokioIOs
27{
28    /// Sends to the FD i.e file of stderr, stdout or any which 
29    /// implements [Write] `write_vectored` in async manner
30    ///
31    /// # Arguments
32    /// 
33    /// * `file_fd` - mutable consume of the container FD.
34    ///
35    /// * `msg` - a reference on array of data
36    ///
37    /// * `newline` - a new line string ref i.e "\n" or "\r\n"
38    pub(crate) async 
39    fn async_send_to_fd<W>(mut file_fd: W, msg: &[Cow<'_, str>], newline: &str) -> SyRes<usize>
40    where W: AsyncWrite + Unpin
41    {
42        let mut iov_list: Vec<IoSlice<'_>> = Vec::with_capacity(msg.len() + 1);
43
44        msg.iter().for_each(|v| iov_list.push(IoSlice::new(v.as_bytes())));
45        iov_list.push(IoSlice::new(newline.as_bytes()));
46
47
48        return 
49            file_fd
50                .write_vectored(&iov_list)
51                .await
52                .map_err(|e|
53                    map_error_os!(e, "async_send_to_fd() writev() failed")
54                );
55    }
56}
57impl AsyncSyslogInternalIO for TokioIOs
58{
59    #[inline]
60    async 
61    fn send_to_stderr(logstat: LogStat, msg: &[Cow<'_, str>])
62    {
63        if logstat.intersects(LogStat::LOG_PERROR) == true
64        {
65            let stderr_lock = tokio::io::stderr();
66
67            let newline = "\n";
68            let _ = Self::async_send_to_fd(stderr_lock, msg, newline).await;
69        }
70    }
71
72    #[inline]
73    async 
74    fn send_to_syscons(logstat: LogStat, msg_payload: &[Cow<'_, str>])
75    {
76        if logstat.intersects(LogStat::LOG_CONS)
77        {
78            let syscons = 
79                File
80                    ::options()
81                        .create(false)
82                        .read(false)
83                        .write(true)
84                        .custom_flags(libc::O_NONBLOCK | libc::O_CLOEXEC)
85                        .open(*PATH_CONSOLE)
86                        .await;
87
88            if let Ok(file) = syscons
89            {
90                let newline = "\n";
91                let _ = Self::async_send_to_fd(file, msg_payload, newline);
92            }
93        }
94    }
95    
96    #[inline]
97    async 
98    fn sleep_micro(us: u64) 
99    {
100        sleep(Duration::from_micros(us)).await;
101    }
102}