//! Parser registration functions and common interface
 
 use std;
-use crate::core::{DetectEngineState,Flow,AppLayerEventType,AppLayerDecoderEvents,AppProto};
+use crate::core::{self,DetectEngineState,Flow,AppLayerEventType,AppLayerDecoderEvents,AppProto};
 use crate::filecontainer::FileContainer;
 use crate::applayer;
 use std::os::raw::{c_void,c_char,c_int};
 use crate::core::SC;
+use std::ffi::CStr;
 
 #[repr(C)]
 #[derive(Default, Debug,PartialEq)]
     /// Convert the enum variant to a C-style string (suffixed with \0).
     fn to_cstring(&self) -> &str;
 
-    /// Return the enum variant for the given name (as a CStr).
-    fn from_cstring(s: &std::ffi::CStr) -> Option<Self> where Self: std::marker::Sized;
+    /// Return the enum variant for the given name.
+    fn from_string(s: &str) -> Option<Self> where Self: std::marker::Sized;
 
     /// Return the ID value of the enum variant.
     fn as_i32(&self) -> i32;
 }
+
+/// Generic `get_info_info` implementation for enums implementing
+/// AppLayerEvent.
+///
+/// Normally usage of this function will be generated by
+/// derive(AppLayerEvent), for example:
+///
+/// #[derive(AppLayerEvent)]
+/// enum AppEvent {
+///     EventOne,
+///     EventTwo,
+/// }
+///
+/// get_event_info::<AppEvent>(...)
+#[inline(always)]
+pub fn get_event_info<T: AppLayerEvent>(
+    event_name: *const std::os::raw::c_char,
+    event_id: *mut std::os::raw::c_int,
+    event_type: *mut core::AppLayerEventType,
+) -> std::os::raw::c_int {
+    if event_name == std::ptr::null() {
+        return -1;
+    }
+
+    unsafe {
+        let event = match CStr::from_ptr(event_name).to_str().map(T::from_string) {
+            Ok(Some(event)) => event.as_i32(),
+            _ => -1,
+        };
+        *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION;
+        *event_id = event as std::os::raw::c_int;
+        return 0;
+    }
+}
+
+/// Generic `get_info_info_by_id` implementation for enums implementing
+/// AppLayerEvent.
+#[inline(always)]
+pub fn get_event_info_by_id<T: AppLayerEvent>(
+    event_id: std::os::raw::c_int,
+    event_name: *mut *const std::os::raw::c_char,
+    event_type: *mut core::AppLayerEventType,
+) -> i8 {
+    if let Some(e) = T::from_id(event_id as i32) {
+        unsafe {
+            *event_name = e.to_cstring().as_ptr() as *const std::os::raw::c_char;
+            *event_type = core::APP_LAYER_EVENT_TYPE_TRANSACTION;
+        }
+        return 0;
+    }
+    return -1;
+}