syslog_ng_common/logmsg/
mod.rs

1// Copyright (c) 2016 Tibor Benke <ihrwein@gmail.com>
2//
3// Licensed under the Apache License, Version 2.0
4// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
5// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. All files in the project carrying such notice may not be copied,
7// modified, or distributed except according to those terms.
8
9use syslog_ng_sys::{LogTagId, logmsg};
10use syslog_ng_sys::types::*;
11
12use std::collections::BTreeMap;
13use std::str;
14use std::mem;
15use std::slice::from_raw_parts;
16use std::ffi::{CStr, CString};
17
18#[cfg(test)]
19mod test;
20
21pub struct NVHandle(logmsg::NVHandle);
22pub struct LogMessage(*mut logmsg::LogMessage);
23
24impl Drop for LogMessage {
25    fn drop(&mut self) {
26        unsafe { logmsg::log_msg_unref(self.0) }
27    }
28}
29
30unsafe impl Send for LogMessage {}
31
32impl Clone for LogMessage {
33    fn clone(&self) -> LogMessage {
34        LogMessage::wrap_raw(self.0)
35    }
36}
37
38impl LogMessage {
39    pub fn new() -> LogMessage {
40        unsafe {
41            let msg = logmsg::log_msg_new_empty();
42            assert!(msg != ::std::ptr::null_mut());
43            LogMessage(msg)
44        }
45    }
46
47    pub fn wrap_raw(raw: *mut ::sys::LogMessage) -> LogMessage {
48        let referenced = unsafe {logmsg::log_msg_ref(raw)};
49        LogMessage(referenced)
50    }
51
52    pub fn into_raw(self) -> *mut ::sys::LogMessage {
53        // self will be destroyed by the end of this functions so we need to
54        // increment the refcount
55        unsafe {logmsg::log_msg_ref(self.0)}
56    }
57
58    unsafe fn c_char_to_str<'a>(value: *const c_char, len: ssize_t) -> &'a str {
59        let slce = from_raw_parts(value, len as usize);
60        str::from_utf8(mem::transmute(slce)).unwrap()
61    }
62
63    pub fn get_value_handle(value_name: &str) -> NVHandle {
64        unsafe {
65            let name = CString::new(value_name).unwrap();
66            NVHandle(logmsg::log_msg_get_value_handle(name.as_ptr()))
67        }
68    }
69
70    pub fn get<K: Into<NVHandle>>(&self, key: K) -> &str {
71        let handle = key.into();
72        unsafe {
73            let mut size: ssize_t = 0;
74            let value = logmsg::__log_msg_get_value(self.0, handle.0, &mut size);
75            LogMessage::c_char_to_str(value, size)
76        }
77    }
78
79    pub fn insert<K: Into<NVHandle>>(&mut self, key: K, value: &str) {
80        let handle = key.into();
81        unsafe {
82            logmsg::log_msg_set_value(self.0, handle.0, value.as_ptr() as *const i8, value.len() as isize);
83        }
84    }
85
86    pub fn set_tag(&mut self, tag: &str) {
87        unsafe {
88            let c_tag = CString::new(tag).unwrap();
89            logmsg::log_msg_set_tag_by_name(self.0, c_tag.as_ptr());
90        }
91    }
92
93    pub fn values(&self) -> BTreeMap<String, String> {
94        let mut values = BTreeMap::new();
95        unsafe {
96            let user_data = mem::transmute::<&mut BTreeMap<String, String>,
97                                             *mut c_void>(&mut values);
98            logmsg::log_msg_values_foreach(self.0, insert_kvpair_to_map, user_data);
99        }
100        values
101    }
102
103    pub fn tags(&self) -> Vec<String> {
104        let mut tags = Vec::new();
105        unsafe {
106            let user_data = mem::transmute::<&mut Vec<String>, *mut c_void>(&mut tags);
107            logmsg::log_msg_tags_foreach(self.0, insert_tag_to_vec, user_data);
108        }
109        tags
110    }
111}
112
113fn c_char_to_string(value: *const c_char) -> String {
114    let bytes = unsafe { CStr::from_ptr(value).to_bytes() };
115    let str_slice: &str = str::from_utf8(bytes).unwrap();
116    str_slice.to_owned()
117}
118
119extern "C" fn insert_tag_to_vec(_: *const logmsg::LogMessage,
120                                _: LogTagId,
121                                name: *const c_char,
122                                user_data: *mut c_void)
123                                -> bool {
124    unsafe {
125        let name = c_char_to_string(name);
126        let mut vec: &mut Vec<String> = mem::transmute(user_data);
127        vec.push(name);
128    }
129    false
130}
131
132extern "C" fn insert_kvpair_to_map(_: logmsg::NVHandle,
133                                   name: *const c_char,
134                                   value: *const c_char,
135                                   value_len: ssize_t,
136                                   user_data: *mut c_void)
137                                   -> bool {
138    unsafe {
139        let name = c_char_to_string(name);
140        let value = LogMessage::c_char_to_str(value, value_len).to_string();
141        let mut map: &mut BTreeMap<String, String> = mem::transmute(user_data);
142        map.insert(name, value);
143    }
144    false
145}
146
147impl<'a> Into<NVHandle> for &'a str {
148    fn into(self) -> NVHandle {
149        let name = CString::new(self).unwrap();
150        let handle = unsafe { logmsg::log_msg_get_value_handle(name.as_ptr()) };
151        NVHandle(handle)
152    }
153}