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. The MIT License (MIT)
12 *                     
13 *   3. EUROPEAN UNION PUBLIC LICENCE v. 1.2 EUPL © the European Union 2007, 2016
14 */
15
16use std::{io::IoSlice, time::Duration};
17
18
19use tokio::{fs::File, io::{AsyncWrite, AsyncWriteExt}, time::sleep};
20
21use crate::{a_sync::syslog_async_internal::AsyncSyslogInternalIO, error::SyRes, map_error_os, LogStat, PATH_CONSOLE};
22
23pub type DefaultIOs = TokioIOs;
24
25#[derive(Debug, Clone)]
26pub struct TokioIOs;
27
28impl TokioIOs
29{
30    /// Sends to the FD i.e file of stderr, stdout or any which 
31    /// implements [Write] `write_vectored` in async manner
32    ///
33    /// # Arguments
34    /// 
35    /// * `file_fd` - mutable consume of the container FD.
36    ///
37    /// * `msg` - a reference on array of data
38    ///
39    /// * `newline` - a new line string ref i.e "\n" or "\r\n"
40    pub(crate) async 
41    fn async_send_to_fd<W>(mut file_fd: W, msg: &str, newline: &str) -> SyRes<usize>
42    where W: AsyncWrite + Unpin
43    {
44        return 
45            file_fd
46                .write_vectored(
47                    &[IoSlice::new(msg.as_bytes()), IoSlice::new(newline.as_bytes())]
48                )
49                .await
50                .map_err(|e|
51                    map_error_os!(e, "async_send_to_fd() writev() failed")
52                );
53    }
54}
55
56#[cfg(target_family = "unix")]
57impl AsyncSyslogInternalIO for TokioIOs
58{
59    #[inline]
60    async 
61    fn send_to_stderr(logstat: LogStat, msg: &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: &str)
75    {
76        use nix::libc;
77
78        if logstat.intersects(LogStat::LOG_CONS)
79        {
80            let syscons = 
81                File
82                    ::options()
83                        .create(false)
84                        .read(false)
85                        .write(true)
86                        .custom_flags(libc::O_NONBLOCK | libc::O_CLOEXEC)
87                        .open(*PATH_CONSOLE)
88                        .await;
89
90            if let Ok(file) = syscons
91            {
92                let newline = "\n";
93                let _ = Self::async_send_to_fd(file, msg_payload, newline);
94            }
95        }
96    }
97    
98    #[inline]
99    async 
100    fn sleep_micro(us: u64) 
101    {
102        sleep(Duration::from_micros(us)).await;
103    }
104}
105
106#[cfg(target_family = "windows")]
107impl AsyncSyslogInternalIO for TokioIOs
108{
109    #[inline]
110    async 
111    fn send_to_stderr(logstat: LogStat, msg: &str)
112    {
113        if logstat.intersects(LogStat::LOG_PERROR) == true
114        {
115           eprintln!("{}", msg);
116        }
117    }
118
119    #[inline]
120    async 
121    fn send_to_syscons(logstat: LogStat, msg_payload: &str)
122    {
123        if logstat.intersects(LogStat::LOG_CONS)
124        {
125            eprintln!("{}", msg_payload);
126        }
127    }
128    
129    #[inline]
130    async 
131    fn sleep_micro(us: u64) 
132    {
133        sleep(Duration::from_micros(us)).await;
134    }
135}