2016-08-24 11:41:48 -04:00
|
|
|
//! This is the logging system used by different CyberMages projects.
|
|
|
|
//! This is meant to work with both std and non std Rust programs.
|
2016-08-24 12:57:44 -04:00
|
|
|
#![doc(html_logo_url="",
|
|
|
|
html_favicon_url="http://cybermagesllc.com/favicon.ico",
|
|
|
|
html_root_url="http://cybermagesllc.com")]
|
|
|
|
#![warn(missing_docs)]
|
2016-08-24 11:41:48 -04:00
|
|
|
|
|
|
|
// Handle using the core or the std of Rust depending on the chosen feature.
|
|
|
|
#![cfg_attr(not(feature="use_std"), no_std)]
|
|
|
|
|
|
|
|
// This crate can only use parts of Rust that are in both the core
|
|
|
|
// and the standard library. This way the logging system will work for
|
|
|
|
// libraries that use either.
|
|
|
|
//
|
|
|
|
// This is handled by coding using the std library and referencing the core
|
|
|
|
// library as the std library if the core library is desired.
|
|
|
|
#[cfg(not(feature="use_std"))]
|
|
|
|
extern crate core as std;
|
|
|
|
|
2015-12-09 17:51:31 -05:00
|
|
|
|
|
|
|
|
|
|
|
// Define the modules that are a
|
|
|
|
// part of this library.
|
2016-08-24 11:41:48 -04:00
|
|
|
mod guard;
|
|
|
|
mod levels;
|
|
|
|
mod location;
|
|
|
|
mod logger;
|
|
|
|
mod logger_states;
|
2015-12-09 17:51:31 -05:00
|
|
|
mod macros;
|
2016-08-24 11:41:48 -04:00
|
|
|
mod faux_logger;
|
|
|
|
mod record;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
|
|
|
|
|
|
|
|
use self::faux_logger::FauxLogger;
|
|
|
|
use self::guard::Guard;
|
|
|
|
use self::logger_states::LoggerStates;
|
|
|
|
|
|
|
|
pub use self::levels::Levels;
|
|
|
|
pub use self::location::Location;
|
|
|
|
pub use self::logger::Logger;
|
|
|
|
pub use self::record::Record;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// This is the currently set global Logger.
|
|
|
|
/// It will default to a fake Logger that does nothing.
|
|
|
|
static mut GLOBAL_LOGGER: *const Logger = &FauxLogger;
|
|
|
|
|
|
|
|
/// The STATE of the GLOBAL_LOGGER.
|
|
|
|
static STATE: AtomicUsize = ATOMIC_USIZE_INIT;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Handles setting the GLOBAL_LOGGER and getting
|
|
|
|
/// it ready to log new Records.
|
|
|
|
fn set_logger_base<F>(create_logger: F)
|
|
|
|
-> Result<(), u8>
|
|
|
|
where F: FnOnce() -> *const Logger
|
|
|
|
{
|
|
|
|
if STATE.compare_and_swap(LoggerStates::Uninitialized.into(),
|
|
|
|
LoggerStates::Initializing.into(),
|
|
|
|
Ordering::SeqCst) !=
|
|
|
|
LoggerStates::Uninitialized.into()
|
|
|
|
{
|
|
|
|
return Err(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe
|
|
|
|
{
|
|
|
|
GLOBAL_LOGGER = create_logger();
|
|
|
|
}
|
|
|
|
STATE.store(LoggerStates::Initialized.into(), Ordering::SeqCst);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Handles clearing the GLOBAL_LOGGER.
|
|
|
|
/// This will return a pointer to the Logger that
|
|
|
|
/// was previously set.
|
|
|
|
fn clear_logger_base() -> Result<*const Logger, u8>
|
|
|
|
{
|
|
|
|
let logger: *const Logger;
|
|
|
|
|
|
|
|
// Set to INITIALIZING to prevent re-initialization after
|
|
|
|
if STATE.compare_and_swap(LoggerStates::Initialized.into(),
|
|
|
|
LoggerStates::Initializing.into(),
|
|
|
|
Ordering::SeqCst) !=
|
|
|
|
LoggerStates::Initialized.into()
|
|
|
|
{
|
|
|
|
return Err(2);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wait until there are no references alive to the
|
|
|
|
// current GLOBAL_LOGGER.
|
|
|
|
Guard::spin_until(0);
|
|
|
|
|
|
|
|
// Change the GLOBAL_LOGGER to the fake one to unset it.
|
|
|
|
unsafe
|
|
|
|
{
|
|
|
|
logger = GLOBAL_LOGGER;
|
|
|
|
GLOBAL_LOGGER = &FauxLogger;
|
|
|
|
Ok(logger)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Get the current logger.
|
|
|
|
///
|
|
|
|
/// This should be the FauxLogger if no logger has been set,
|
|
|
|
/// or whatever logger has been set. If a logger has been
|
|
|
|
/// cleared then this will return None.
|
|
|
|
fn get_logger() -> Option<Guard>
|
|
|
|
{
|
|
|
|
let guard: Guard;
|
|
|
|
|
2016-09-06 11:55:20 -04:00
|
|
|
if STATE.load(Ordering::SeqCst) == LoggerStates::Initializing.into()
|
2016-08-24 11:41:48 -04:00
|
|
|
{
|
|
|
|
None
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
unsafe
|
|
|
|
{
|
|
|
|
guard = Guard::new(GLOBAL_LOGGER);
|
|
|
|
}
|
|
|
|
|
|
|
|
Some(guard)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Set the Logger to use for logging.
|
|
|
|
#[cfg(not(feature="use_std"))]
|
|
|
|
pub fn set_logger<F>(create_logger: F)
|
|
|
|
-> Result<(), u8>
|
|
|
|
where F: FnOnce() -> *const Logger
|
|
|
|
{
|
|
|
|
set_logger_base(create_logger)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Clear the logger currently being used.
|
|
|
|
///
|
|
|
|
/// This will return a pointer to the Logger that
|
|
|
|
/// was previously set.
|
|
|
|
#[cfg(not(feature="use_std"))]
|
|
|
|
pub fn clear_logger() -> Result<*const Logger, u8>
|
|
|
|
{
|
|
|
|
clear_logger_base()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Set the Logger to use for logging.
|
|
|
|
#[cfg(feature="use_std")]
|
|
|
|
pub fn set_logger<F>(create_logger: F)
|
|
|
|
-> Result<(), u8>
|
|
|
|
where F: FnOnce() -> Box<Logger>
|
|
|
|
{
|
|
|
|
// I hate using closures, but it is the only way I
|
|
|
|
// can think of to handle this right now.
|
|
|
|
unsafe
|
|
|
|
{
|
|
|
|
set_logger_base(|| ::std::mem::transmute(create_logger()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Clear the logger currently being used.
|
|
|
|
///
|
|
|
|
/// This will return a pointer to the Logger that
|
|
|
|
/// was previously set.
|
|
|
|
#[cfg(feature="use_std")]
|
|
|
|
pub fn clear_logger() -> Result<Box<Logger>, u8>
|
|
|
|
{
|
|
|
|
match clear_logger_base()
|
|
|
|
{
|
|
|
|
Ok(logger) =>
|
|
|
|
{
|
|
|
|
unsafe
|
|
|
|
{
|
|
|
|
Ok(::std::mem::transmute(logger))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Err(error) =>
|
|
|
|
{
|
|
|
|
Err(error)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Do NOT use outside of this crate.
|
|
|
|
///
|
|
|
|
/// This records a log message.
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub fn log_record(domain: &str, lvl: Levels, module_path: &str,
|
|
|
|
file_name: &str, line_num: u32,
|
|
|
|
message: ::std::fmt::Arguments)
|
|
|
|
{
|
|
|
|
let mut record: Record;
|
|
|
|
|
|
|
|
match get_logger()
|
|
|
|
{
|
|
|
|
Some(logger) =>
|
|
|
|
{
|
|
|
|
record = Record::new(domain, lvl, message);
|
|
|
|
record.set_location(module_path, file_name, line_num);
|
2015-12-09 17:51:31 -05:00
|
|
|
|
2016-08-24 11:41:48 -04:00
|
|
|
logger.log(&record)
|
|
|
|
}
|
2015-12-09 17:51:31 -05:00
|
|
|
|
2016-08-24 11:41:48 -04:00
|
|
|
None =>
|
|
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|