syslog-rs 6.5.0

A native Rust implementation of the glibc/libc/windows syslog client and windows native log for logging.
Documentation
/*-
 * syslog-rs - a syslog client translated from libc to rust
 * 
 * Copyright 2025 Aleksandr Morozov
 * 
 * The syslog-rs crate can be redistributed and/or modified
 * under the terms of either of the following licenses:
 *
 *   1. the Mozilla Public License Version 2.0 (the “MPL”) OR
 *
 *   2. The MIT License (MIT)
 *                     
 *   3. EUROPEAN UNION PUBLIC LICENCE v. 1.2 EUPL © the European Union 2007, 2016
 */

use std::{io::IoSlice, time::Duration};


use tokio::{fs::File, io::{AsyncWrite, AsyncWriteExt}, time::sleep};

use crate::{a_sync::syslog_async_internal::AsyncSyslogInternalIO, error::SyRes, map_error_os, LogStat, PATH_CONSOLE};

pub type DefaultIOs = TokioIOs;

#[derive(Debug, Clone)]
pub struct TokioIOs;

impl TokioIOs
{
    /// Sends to the FD i.e file of stderr, stdout or any which 
    /// implements [Write] `write_vectored` in async manner
    ///
    /// # Arguments
    /// 
    /// * `file_fd` - mutable consume of the container FD.
    ///
    /// * `msg` - a reference on array of data
    ///
    /// * `newline` - a new line string ref i.e "\n" or "\r\n"
    pub(crate) async 
    fn async_send_to_fd<W>(mut file_fd: W, msg: &str, newline: &str) -> SyRes<usize>
    where W: AsyncWrite + Unpin
    {
        return 
            file_fd
                .write_vectored(
                    &[IoSlice::new(msg.as_bytes()), IoSlice::new(newline.as_bytes())]
                )
                .await
                .map_err(|e|
                    map_error_os!(e, "async_send_to_fd() writev() failed")

                );
    }
}

#[cfg(target_family = "unix")]
impl AsyncSyslogInternalIO for TokioIOs
{
    #[inline]
    async 
    fn send_to_stderr(logstat: LogStat, msg: &str)
    {
        if logstat.intersects(LogStat::LOG_PERROR) == true
        {
            let stderr_lock = tokio::io::stderr();

            let newline = "\n";
            let _ = Self::async_send_to_fd(stderr_lock, msg, newline).await;
        }
    }

    #[inline]
    async 
    fn send_to_syscons(logstat: LogStat, msg_payload: &str)
    {
        use nix::libc;

        if logstat.intersects(LogStat::LOG_CONS)
        {
            let syscons = 
                File
                    ::options()
                        .create(false)
                        .read(false)
                        .write(true)
                        .custom_flags(libc::O_NONBLOCK | libc::O_CLOEXEC)
                        .open(*PATH_CONSOLE)
                        .await;

            if let Ok(file) = syscons
            {
                let newline = "\n";
                let _ = Self::async_send_to_fd(file, msg_payload, newline);
            }
        }
    }
    
    #[inline]
    async 
    fn sleep_micro(us: u64) 
    {
        sleep(Duration::from_micros(us)).await;
    }
}

#[cfg(target_family = "windows")]
impl AsyncSyslogInternalIO for TokioIOs
{
    #[inline]
    async 
    fn send_to_stderr(logstat: LogStat, msg: &str)
    {
        if logstat.intersects(LogStat::LOG_PERROR) == true
        {
           eprintln!("{}", msg);
        }
    }

    #[inline]
    async 
    fn send_to_syscons(logstat: LogStat, msg_payload: &str)
    {
        if logstat.intersects(LogStat::LOG_CONS)
        {
            eprintln!("{}", msg_payload);
        }
    }
    
    #[inline]
    async 
    fn sleep_micro(us: u64) 
    {
        sleep(Duration::from_micros(us)).await;
    }
}