syslog-rs 6.6.1

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::{fmt::{self, Arguments}, io::{self, ErrorKind}, marker::PhantomData};


use crate::{Priority, SyslogDestination, error::SyRes, formatters::SyslogFormatter};

/// A limited version of `SyslogApi` which implements only necessary things
/// for streaming.
pub trait SyStreamSyslogApi<F: SyslogFormatter, D: SyslogDestination>
{
    /// A type which declared wither syslog instance can be mutable or not.
    type SYSLOG<'t>;

    /// Sends message to syslog server over channel.
    fn syslog<'t>(syslog: Self::SYSLOG<'t>, pri: Priority, fmt: F) -> SyRes<()>;
}

/// A struct which is created when user attempts to create a streamable instance, i.e
/// which can be used in [write!].
/// 
/// # Generics
/// 
/// `PRI` - a [SyStreamPri] which are:
/// 
///  [SyStreamPriErr], [SyStreamPriDebug], [SyStreamPriAlert], [SyStreamPriCrit],
///  [SyStreamPriEmerg], [SyStreamPriInfo], [SyStreamPriNotice], [SyStreamPriWarning]
/// 
/// # Example
/// 
/// ```ignore
/// let log = 
///     SingleSyslog::openlog(
///         Some("test1"), 
///         LogStat::LOG_CONS | LogStat::LOG_NDELAY | LogStat::LOG_PID, 
///         LogFacility::LOG_DAEMON,
///         SyslogLocal::new()
///     ).unwrap();
/// 
/// write!(log.get_stream::<SyStreamPriDebug>(), "test stream singlesyslog {}", i).unwrap();
/// ```
pub struct SyStream<'t, PRI, D, F, S>
where PRI: SyStreamPri, D: SyslogDestination, F: SyslogFormatter, S: SyStreamSyslogApi<F, D>
{
    pub(crate) s: Option<S::SYSLOG<'t>>,
    pub(crate) _p: PhantomData<PRI>,
    pub(crate) _p1: PhantomData<F>,
    pub(crate) _p2: PhantomData<D>,
}

impl<'t, PRI: SyStreamPri, D: SyslogDestination, F: SyslogFormatter, S: SyStreamSyslogApi<F, D>> fmt::Write 
for SyStream<'t, PRI, D, F, S>
{
    fn write_str(&mut self, s: &str) -> fmt::Result 
    {
        let s = s.to_string();

        return 
            S::syslog( self.s.take().unwrap() , PRI::PRIO, s.into())
                .map_err(|_e|
                    fmt::Error
                );
    }

    fn write_fmt(self: &mut Self, args: Arguments<'_>) -> fmt::Result
    {
        if let Some(s) = args.as_str() 
        {
            return
                S::syslog( self.s.take().unwrap() , PRI::PRIO, s.into())
                    .map_err(|_| fmt::Error );
        } 
        else 
        {
            return 
                S::syslog( self.s.take().unwrap() , PRI::PRIO, args.to_string().into())
                    .map_err(|_| fmt::Error );
        }
    }
}

impl<'t, PRI: SyStreamPri, D: SyslogDestination, F: SyslogFormatter, S: SyStreamSyslogApi<F, D>> io::Write 
for SyStream<'t, PRI, D, F, S>
{
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> 
    {
        let s = str::from_utf8(buf).unwrap().to_string();
        let n = s.len();

        return 
            S::syslog( self.s.take().unwrap() , PRI::PRIO, s.into())
                .map_err(|e|
                    io::Error::new(ErrorKind::Other, e.to_string())
                )
                .map(|_| n);
    }

    fn flush(&mut self) -> io::Result<()> 
    {
        return Ok(());
    }
}

/// A PRI tartic marker.
pub trait SyStreamPri
{
    const PRIO: Priority;
}

/// [Priority::LOG_ERR]
pub struct SyStreamPriErr;

impl SyStreamPri for SyStreamPriErr
{
    const PRIO: Priority = Priority::LOG_ERR;
}

/// [Priority::LOG_DEBUG]
pub struct SyStreamPriDebug;

impl SyStreamPri for SyStreamPriDebug
{
    const PRIO: Priority = Priority::LOG_DEBUG;
}

/// [Priority::LOG_ALERT]
pub struct SyStreamPriAlert;

impl SyStreamPri for SyStreamPriAlert
{
    const PRIO: Priority = Priority::LOG_ALERT;
}

/// [Priority::LOG_CRIT]
pub struct SyStreamPriCrit;

impl SyStreamPri for SyStreamPriCrit
{
    const PRIO: Priority = Priority::LOG_CRIT;
}

/// [Priority::LOG_EMERG]
pub struct SyStreamPriEmerg;

impl SyStreamPri for SyStreamPriEmerg
{
    const PRIO: Priority = Priority::LOG_EMERG;
}

/// [Priority::LOG_INFO]
pub struct SyStreamPriInfo;

impl SyStreamPri for SyStreamPriInfo
{
    const PRIO: Priority = Priority::LOG_INFO;
}

/// [Priority::LOG_NOTICE]
pub struct SyStreamPriNotice;

impl SyStreamPri for SyStreamPriNotice
{
    const PRIO: Priority = Priority::LOG_NOTICE;
}

/// [Priority::LOG_WARNING]
pub struct SyStreamPriWarning;

impl SyStreamPri for SyStreamPriWarning
{
    const PRIO: Priority = Priority::LOG_WARNING;
}