rusteron_code_genConstant COMMON_CODE
Source pub const COMMON_CODE: &str = "use crate::AeronErrorType::Unknown;\n#[cfg(debug_assertions)]\nuse std::backtrace::Backtrace;\nuse std::fmt::{Debug, Formatter};\nuse std::ops::{Deref, DerefMut};\nuse std::{any, fmt, ptr};\n\n/// A custom struct for managing C resources with automatic cleanup.\n///\n/// It handles initialisation and clean-up of the resource and ensures that resources\n/// are properly released when they go out of scope.\npub struct ManagedCResource<T> {\n resource: *mut T,\n cleanup: Option<Box<dyn FnMut(*mut *mut T) -> i32>>,\n cleanup_struct: bool,\n borrowed: bool,\n}\n\nimpl<T> Debug for ManagedCResource<T> {\n fn fmt(&self, f: &mut Formatter<\'_>) -> fmt::Result {\n f.debug_struct(\"ManagedCResource\")\n .field(\"resource\", &self.resource)\n .field(\"type\", &any::type_name::<T>())\n .finish()\n }\n}\n\nimpl<T> ManagedCResource<T> {\n /// Creates a new ManagedCResource with a given initializer and cleanup function.\n ///\n /// The initializer is a closure that attempts to initialize the resource.\n /// If initialization fails, the initializer should return an error code.\n /// The cleanup function is used to release the resource when it\'s no longer needed.\n /// `cleanup_struct` where it should clean up the struct in rust\n pub fn new(\n init: impl FnOnce(*mut *mut T) -> i32,\n cleanup: Option<Box<dyn FnMut(*mut *mut T) -> i32>>,\n cleanup_struct: bool,\n ) -> Result<Self, AeronCError> {\n let mut resource: *mut T = ptr::null_mut();\n let result = init(&mut resource);\n if result < 0 || resource.is_null() {\n return Err(AeronCError::from_code(result));\n }\n\n let result = Self {\n resource,\n cleanup,\n cleanup_struct,\n borrowed: false,\n };\n #[cfg(debug_assertions)]\n log::debug!(\"created c resource: {:?}\", result);\n Ok(result)\n }\n\n pub fn new_borrowed(value: *const T) -> Self {\n Self {\n resource: value as *mut _,\n cleanup: None,\n cleanup_struct: false,\n borrowed: true,\n }\n }\n\n /// Gets a raw pointer to the resource.\n #[inline(always)]\n pub fn get(&self) -> *mut T {\n self.resource\n }\n\n #[inline(always)]\n pub fn get_mut(&self) -> &mut T {\n unsafe { &mut *self.resource }\n }\n\n /// Closes the resource by calling the cleanup function.\n ///\n /// If cleanup fails, it returns an `AeronError`.\n pub fn close(&mut self) -> Result<(), AeronCError> {\n if let Some(mut cleanup) = self.cleanup.take() {\n if !self.resource.is_null() {\n let result = cleanup(&mut self.resource);\n if result < 0 {\n return Err(AeronCError::from_code(result));\n }\n self.resource = std::ptr::null_mut();\n }\n }\n\n Ok(())\n }\n}\n\nimpl<T> Drop for ManagedCResource<T> {\n fn drop(&mut self) {\n if !self.resource.is_null() && !self.borrowed {\n let resource = self.resource.clone();\n // Ensure the clean-up function is called when the resource is dropped.\n #[cfg(debug_assertions)]\n log::debug!(\"closing c resource: {:?}\", self);\n let _ = self.close(); // Ignore errors during an automatic drop to avoid panics.\n\n if self.cleanup_struct {\n #[cfg(debug_assertions)]\n log::debug!(\"closing rust struct resource: {:?}\", resource);\n unsafe {\n let _ = Box::from_raw(resource);\n }\n }\n }\n }\n}\n\n#[derive(Debug)]\npub enum AeronErrorType {\n NullOrNotConnected,\n ClientErrorDriverTimeout,\n ClientErrorClientTimeout,\n ClientErrorConductorServiceTimeout,\n ClientErrorBufferFull,\n PublicationBackPressured,\n PublicationAdminAction,\n PublicationClosed,\n PublicationMaxPositionExceeded,\n PublicationError,\n TimedOut,\n Unknown(i32),\n}\n\nimpl From<AeronErrorType> for AeronCError {\n fn from(value: AeronErrorType) -> Self {\n AeronCError::from_code(value.code())\n }\n}\n\nimpl AeronErrorType {\n pub fn code(&self) -> i32 {\n match self {\n AeronErrorType::NullOrNotConnected => -1,\n AeronErrorType::ClientErrorDriverTimeout => -1000,\n AeronErrorType::ClientErrorClientTimeout => -1001,\n AeronErrorType::ClientErrorConductorServiceTimeout => -1002,\n AeronErrorType::ClientErrorBufferFull => -1003,\n AeronErrorType::PublicationBackPressured => -2,\n AeronErrorType::PublicationAdminAction => -3,\n AeronErrorType::PublicationClosed => -4,\n AeronErrorType::PublicationMaxPositionExceeded => -5,\n AeronErrorType::PublicationError => -6,\n AeronErrorType::TimedOut => -234324,\n AeronErrorType::Unknown(code) => *code,\n }\n }\n\n pub fn from_code(code: i32) -> Self {\n match code {\n -1 => AeronErrorType::NullOrNotConnected,\n -1000 => AeronErrorType::ClientErrorDriverTimeout,\n -1001 => AeronErrorType::ClientErrorClientTimeout,\n -1002 => AeronErrorType::ClientErrorConductorServiceTimeout,\n -1003 => AeronErrorType::ClientErrorBufferFull,\n -2 => AeronErrorType::PublicationBackPressured,\n -3 => AeronErrorType::PublicationAdminAction,\n -4 => AeronErrorType::PublicationClosed,\n -5 => AeronErrorType::PublicationMaxPositionExceeded,\n -6 => AeronErrorType::PublicationError,\n -234324 => AeronErrorType::TimedOut,\n _ => Unknown(code),\n }\n }\n\n pub fn to_string(&self) -> &\'static str {\n match self {\n AeronErrorType::NullOrNotConnected => \"Null Value or Not Connected\",\n AeronErrorType::ClientErrorDriverTimeout => \"Client Error Driver Timeout\",\n AeronErrorType::ClientErrorClientTimeout => \"Client Error Client Timeout\",\n AeronErrorType::ClientErrorConductorServiceTimeout => {\n \"Client Error Conductor Service Timeout\"\n }\n AeronErrorType::ClientErrorBufferFull => \"Client Error Buffer Full\",\n AeronErrorType::PublicationBackPressured => \"Publication Back Pressured\",\n AeronErrorType::PublicationAdminAction => \"Publication Admin Action\",\n AeronErrorType::PublicationClosed => \"Publication Closed\",\n AeronErrorType::PublicationMaxPositionExceeded => \"Publication Max Position Exceeded\",\n AeronErrorType::PublicationError => \"Publication Error\",\n AeronErrorType::TimedOut => \"Timed Out\",\n AeronErrorType::Unknown(_) => \"Unknown Error\",\n }\n }\n}\n\n/// Represents an Aeron-specific error with a code and an optional message.\n///\n/// The error code is derived from Aeron C API calls.\n/// Use `get_message()` to retrieve a human-readable message, if available.\n#[derive(Eq, PartialEq)]\npub struct AeronCError {\n pub code: i32,\n}\n\nimpl AeronCError {\n /// Creates an AeronError from the error code returned by Aeron.\n ///\n /// Error codes below zero are considered failure.\n pub fn from_code(code: i32) -> Self {\n #[cfg(debug_assertions)]\n {\n if code < 0 {\n let backtrace = Backtrace::capture();\n let backtrace = format!(\"{:?}\", backtrace);\n\n let re =\n regex::Regex::new(r#\"fn: \"([^\"]+)\", file: \"([^\"]+)\", line: (\\d+)\"#).unwrap();\n let mut lines = String::new();\n re.captures_iter(&backtrace).for_each(|cap| {\n let function = &cap[1];\n let mut file = cap[2].to_string();\n let line = &cap[3];\n if file.starts_with(\"./\") {\n file = format!(\"{}/{}\", env!(\"CARGO_MANIFEST_DIR\"), &file[2..]);\n } else if file.starts_with(\"/rustc/\") {\n file = file.split(\"/\").last().unwrap().to_string();\n }\n // log in intellij friendly error format so can hyperlink to source code in stack trace\n lines.push_str(&format!(\" {file}:{line} in {function}\\n\"));\n });\n\n log::error!(\n \"Aeron C error code: {}, kind: \'{:?}\'\\n{}\",\n code,\n AeronErrorType::from_code(code),\n lines\n );\n }\n }\n AeronCError { code }\n }\n\n pub fn kind(&self) -> AeronErrorType {\n AeronErrorType::from_code(self.code)\n }\n}\n\nimpl fmt::Display for AeronCError {\n fn fmt(&self, f: &mut fmt::Formatter<\'_>) -> fmt::Result {\n write!(f, \"Aeron error {}: {:?}\", self.code, self.kind())\n }\n}\n\nimpl fmt::Debug for AeronCError {\n fn fmt(&self, f: &mut fmt::Formatter<\'_>) -> fmt::Result {\n f.debug_struct(\"AeronCError\")\n .field(\"code\", &self.code)\n .field(\"kind\", &self.kind())\n .finish()\n }\n}\n\nimpl std::error::Error for AeronCError {}\n\n/// # Handler\n///\n/// `Handler` is a struct that wraps a raw pointer and a drop flag.\n///\n/// **Important:** `Handler` does not get dropped automatically.\n/// You need to call the `release` method if you want to clear the memory manually.\n///\n/// ## Example\n///\n/// ```no_compile\n/// use rusteron_code_gen::Handler;\n/// let handler = Handler::leak(your_value);\n/// // When you are done with the handler\n/// handler.release();\n/// ```\npub struct Handler<T> {\n raw_ptr: *mut T,\n should_drop: bool,\n}\n\n/// Utility method for setting empty handlers\npub struct Handlers;\n\nimpl<T> Handler<T> {\n pub fn leak(handler: T) -> Self {\n let raw_ptr = Box::into_raw(Box::new(handler)) as *mut _;\n Self {\n raw_ptr,\n should_drop: true,\n }\n }\n\n pub fn is_none(&self) -> bool {\n self.raw_ptr.is_null()\n }\n\n pub fn as_raw(&self) -> *mut std::os::raw::c_void {\n self.raw_ptr as *mut std::os::raw::c_void\n }\n\n pub fn release(self) {\n if self.should_drop && !self.raw_ptr.is_null() {\n unsafe {\n let _ = Box::from_raw(self.raw_ptr as *mut Box<T>);\n }\n }\n }\n}\n\nimpl<T> Deref for Handler<T> {\n type Target = T;\n\n fn deref(&self) -> &Self::Target {\n unsafe { &*self.raw_ptr as &T }\n }\n}\n\nimpl<T> DerefMut for Handler<T> {\n fn deref_mut(&mut self) -> &mut Self::Target {\n unsafe { &mut *self.raw_ptr as &mut T }\n }\n}\n\npub fn find_unused_udp_port(start_port: u16) -> Option<u16> {\n let end_port = u16::MAX;\n\n for port in start_port..=end_port {\n if is_udp_port_available(port) {\n return Some(port);\n }\n }\n\n None\n}\n\npub fn is_udp_port_available(port: u16) -> bool {\n std::net::UdpSocket::bind((\"127.0.0.1\", port)).is_ok()\n}\n\n/// Represents the Aeron URI parser and handler.\npub struct ChannelUri {}\n\nimpl ChannelUri {\n pub const AERON_SCHEME: &\'static str = \"aeron\";\n pub const SPY_QUALIFIER: &\'static str = \"aeron-spy\";\n pub const MAX_URI_LENGTH: usize = 4095;\n}\n\npub const DRIVER_TIMEOUT_MS_DEFAULT: u64 = 10_000;\npub const AERON_DIR_PROP_NAME: &str = \"aeron.dir\";\npub const AERON_IPC_MEDIA: &str = \"aeron:ipc\";\npub const AERON_UDP_MEDIA: &str = \"aeron:udp\";\npub const SPY_PREFIX: &str = \"aeron-spy:\";\npub const TAG_PREFIX: &str = \"tag:\";\n\n/// Enum for media types.\n#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]\npub enum Media {\n Ipc,\n Udp,\n}\n\nimpl Media {\n pub fn as_str(&self) -> &\'static str {\n match self {\n Media::Ipc => \"ipc\",\n Media::Udp => \"udp\",\n }\n }\n}\n\n/// Enum for control modes.\n#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]\npub enum ControlMode {\n Manual,\n Dynamic,\n /// this is a beta feature useful when dealing with docker containers and networking\n Response,\n}\n\nimpl ControlMode {\n pub fn as_str(&self) -> &\'static str {\n match self {\n ControlMode::Manual => \"manual\",\n ControlMode::Dynamic => \"dynamic\",\n ControlMode::Response => \"response\",\n }\n }\n}\n";