Skip to main content

syslog_too/logger/
backend.rs

1//! Defines behavior for the logger backend.
2
3use std::fmt;
4use std::fmt::Arguments;
5use std::io::{self, BufWriter, Write};
6use std::net::{SocketAddr, TcpStream, UdpSocket};
7#[cfg(unix)]
8use std::os::unix::net::{UnixDatagram, UnixStream};
9
10pub enum LoggerBackend {
11    /// Unix socket, temp file path, log file path
12    #[cfg(unix)]
13    Unix(UnixDatagram),
14    #[cfg(not(unix))]
15    Unix(()),
16    #[cfg(unix)]
17    UnixStream(BufWriter<UnixStream>),
18    #[cfg(not(unix))]
19    UnixStream(()),
20    Udp(UdpSocket, SocketAddr),
21    Tcp(BufWriter<TcpStream>),
22}
23
24impl Write for LoggerBackend {
25    /// Sends a message directly, without any formatting
26    fn write(&mut self, message: &[u8]) -> io::Result<usize> {
27        match *self {
28            #[cfg(unix)]
29            LoggerBackend::Unix(ref dgram) => dgram.send(message),
30            #[cfg(unix)]
31            LoggerBackend::UnixStream(ref mut socket) => {
32                let null = [0; 1];
33                socket
34                    .write(message)
35                    .and_then(|sz| socket.write(&null).map(|_| sz))
36                    .and_then(|sz| socket.flush().map(|_| sz))
37            }
38            LoggerBackend::Udp(ref socket, ref addr) => socket.send_to(message, addr),
39            LoggerBackend::Tcp(ref mut socket) => socket
40                .write(message)
41                .and_then(|sz| socket.flush().map(|_| sz)),
42            #[cfg(not(unix))]
43            LoggerBackend::Unix(_) | LoggerBackend::UnixStream(_) => {
44                Err(io::Error::other("unsupported platform"))
45            }
46        }
47    }
48
49    fn flush(&mut self) -> io::Result<()> {
50        match *self {
51            #[cfg(unix)]
52            LoggerBackend::Unix(_) => Ok(()),
53            #[cfg(unix)]
54            LoggerBackend::UnixStream(ref mut socket) => socket.flush(),
55            LoggerBackend::Udp(_, _) => Ok(()),
56            LoggerBackend::Tcp(ref mut socket) => socket.flush(),
57            #[cfg(not(unix))]
58            LoggerBackend::Unix(_) | LoggerBackend::UnixStream(_) => {
59                Err(io::Error::other("unsupported platform"))
60            }
61        }
62    }
63
64    fn write_fmt(&mut self, args: Arguments) -> io::Result<()> {
65        match *self {
66            #[cfg(unix)]
67            LoggerBackend::Unix(ref dgram) => {
68                let message = fmt::format(args);
69                dgram.send(message.as_bytes()).map(|_| ())
70            }
71            #[cfg(unix)]
72            LoggerBackend::UnixStream(ref mut socket) => {
73                let null = [0; 1];
74                socket
75                    .write_fmt(args)
76                    .and_then(|_| socket.write(&null).map(|_| ()))
77                    .and_then(|sz| socket.flush().map(|_| sz))
78            }
79            LoggerBackend::Udp(ref socket, ref addr) => {
80                let message = fmt::format(args);
81                socket.send_to(message.as_bytes(), addr).map(|_| ())
82            }
83            LoggerBackend::Tcp(ref mut socket) => socket
84                .write_fmt(args)
85                .and_then(|sz| socket.flush().map(|_| sz)),
86            #[cfg(not(unix))]
87            LoggerBackend::Unix(_) | LoggerBackend::UnixStream(_) => {
88                Err(io::Error::other("unsupported platform"))
89            }
90        }
91    }
92}