From 64106c4d3d4ddba8c7bc2af75376e6d3d3d75601 Mon Sep 17 00:00:00 2001 From: Date: Mon, 29 Jun 2015 20:16:15 +0000 Subject: Update documentation --- src/log/lib.rs.html | 1643 ++++++++++++++++++++++++++++++++++++++++++++++++ src/log/macros.rs.html | 387 ++++++++++++ 2 files changed, 2030 insertions(+) create mode 100644 src/log/lib.rs.html create mode 100644 src/log/macros.rs.html (limited to 'src/log') diff --git a/src/log/lib.rs.html b/src/log/lib.rs.html new file mode 100644 index 0000000..78cbf86 --- /dev/null +++ b/src/log/lib.rs.html @@ -0,0 +1,1643 @@ + + + + + + + + + + lib.rs.html -- source + + + + + + + + + + + + + + + +
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! A lightweight logging facade.
+//!
+//! A logging facade provides a single logging API that abstracts over the
+//! actual logging implementation. Libraries can use the logging API provided
+//! by this crate, and the consumer of those libraries can choose the logging
+//! framework that is most suitable for its use case.
+//!
+//! If no logging implementation is selected, the facade falls back to a "noop"
+//! implementation that ignores all log messages. The overhead in this case
+//! is very small - just an integer load, comparison and jump.
+//!
+//! A log request consists of a target, a level, and a body. A target is a
+//! string which defaults to the module path of the location of the log
+//! request, though that default may be overridden. Logger implementations
+//! typically use the target to filter requests based on some user
+//! configuration.
+//!
+//! # Use
+//!
+//! ## In libraries
+//!
+//! Libraries should link only to the `log` crate, and use the provided
+//! macros to log whatever information will be useful to downstream consumers.
+//!
+//! ### Examples
+//!
+//! ```rust
+//! # #![allow(unstable)]
+//! #[macro_use]
+//! extern crate log;
+//!
+//! # #[derive(Debug)] pub struct Yak(String);
+//! # impl Yak { fn shave(&self, _: u32) {} }
+//! # fn find_a_razor() -> Result<u32, u32> { Ok(1) }
+//! pub fn shave_the_yak(yak: &Yak) {
+//!     info!(target: "yak_events", "Commencing yak shaving for {:?}", yak);
+//!
+//!     loop {
+//!         match find_a_razor() {
+//!             Ok(razor) => {
+//!                 info!("Razor located: {}", razor);
+//!                 yak.shave(razor);
+//!                 break;
+//!             }
+//!             Err(err) => {
+//!                 warn!("Unable to locate a razor: {}, retrying", err);
+//!             }
+//!         }
+//!     }
+//! }
+//! # fn main() {}
+//! ```
+//!
+//! ## In executables
+//!
+//! Executables should chose a logging framework and initialize it early in the
+//! runtime of the program. Logging frameworks will typically include a
+//! function to do this. Any log messages generated before the framework is
+//! initialized will be ignored.
+//!
+//! The executable itself may use the `log` crate to log as well.
+//!
+//! ### Warning
+//!
+//! The logging system may only be initialized once.
+//!
+//! ### Examples
+//!
+//! ```rust,ignore
+//! #[macro_use]
+//! extern crate log;
+//! extern crate my_logger;
+//!
+//! fn main() {
+//!     my_logger::init();
+//!
+//!     info!("starting up");
+//!
+//!     // ...
+//! }
+//! ```
+//!
+//! # Logger implementations
+//!
+//! Loggers implement the `Log` trait. Here's a very basic example that simply
+//! logs all messages at the `Error`, `Warn` or `Info` levels to stdout:
+//!
+//! ```rust
+//! extern crate log;
+//!
+//! use log::{LogRecord, LogLevel, LogMetadata};
+//!
+//! struct SimpleLogger;
+//!
+//! impl log::Log for SimpleLogger {
+//!     fn enabled(&self, metadata: &LogMetadata) -> bool {
+//!         metadata.level() <= LogLevel::Info
+//!     }
+//!
+//!     fn log(&self, record: &LogRecord) {
+//!         if self.enabled(record.metadata()) {
+//!             println!("{} - {}", record.level(), record.args());
+//!         }
+//!     }
+//! }
+//!
+//! # fn main() {}
+//! ```
+//!
+//! Loggers are installed by calling the `set_logger` function. It takes a
+//! closure which is provided a `MaxLogLevel` token and returns a `Log` trait
+//! object. The `MaxLogLevel` token controls the global maximum log level. The
+//! logging facade uses this as an optimization to improve performance of log
+//! messages at levels that are disabled. In the case of our example logger,
+//! we'll want to set the maximum log level to `Info`, since we ignore any
+//! `Debug` or `Trace` level log messages. A logging framework should provide a
+//! function that wraps a call to `set_logger`, handling initialization of the
+//! logger:
+//!
+//! ```rust
+//! # extern crate log;
+//! # use log::{LogLevel, LogLevelFilter, SetLoggerError, LogMetadata};
+//! # struct SimpleLogger;
+//! # impl log::Log for SimpleLogger {
+//! #   fn enabled(&self, _: &LogMetadata) -> bool { false }
+//! #   fn log(&self, _: &log::LogRecord) {}
+//! # }
+//! # fn main() {}
+//! pub fn init() -> Result<(), SetLoggerError> {
+//!     log::set_logger(|max_log_level| {
+//!         max_log_level.set(LogLevelFilter::Info);
+//!         Box::new(SimpleLogger)
+//!     })
+//! }
+//! ```
+
+#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+       html_root_url = "http://doc.rust-lang.org/log/")]
+#![warn(missing_docs)]
+
+extern crate libc;
+
+use std::ascii::AsciiExt;
+use std::cmp;
+use std::error;
+use std::fmt;
+use std::mem;
+use std::ops::Deref;
+use std::str::FromStr;
+use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
+mod macros;
+
+// The setup here is a bit weird to make at_exit work.
+//
+// There are four different states that we care about: the logger's
+// uninitialized, the logger's initializing (set_logger's been called but
+// LOGGER hasn't actually been set yet), the logger's active, or the logger's
+// shutting down inside of at_exit.
+//
+// The LOGGER static is normally a Box<Box<Log>> with some special possible
+// values as well. The uninitialized and initializing states are represented by
+// the values 0 and 1 respectively. The shutting down state is also represented
+// by 1. Any other value is a valid pointer to the logger.
+//
+// The at_exit routine needs to make sure that no threads are actively logging
+// when it deallocates the logger. The number of actively logging threads is
+// tracked in the REFCOUNT static. The routine first sets LOGGER back to 1.
+// All logging calls past that point will immediately return without accessing
+// the logger. At that point, the at_exit routine just waits for the refcount
+// to reach 0 before deallocating the logger. Note that the refcount does not
+// necessarily monotonically decrease at this point, as new log calls still
+// increment and decrement it, but the interval in between is small enough that
+// the wait is really just for the active log calls to finish.
+static LOGGER: AtomicUsize = ATOMIC_USIZE_INIT;
+static REFCOUNT: AtomicUsize = ATOMIC_USIZE_INIT;
+
+const UNINITIALIZED: usize = 0;
+const INITIALIZING: usize = 1;
+
+static MAX_LOG_LEVEL_FILTER: AtomicUsize = ATOMIC_USIZE_INIT;
+
+static LOG_LEVEL_NAMES: [&'static str; 6] = ["OFF", "ERROR", "WARN", "INFO",
+                                             "DEBUG", "TRACE"];
+
+/// An enum representing the available verbosity levels of the logging framework
+///
+/// A `LogLevel` may be compared directly to a `LogLevelFilter`.
+#[repr(usize)]
+#[derive(Copy, Eq, Debug)]
+pub enum LogLevel {
+    /// The "error" level.
+    ///
+    /// Designates very serious errors.
+    Error = 1, // This way these line up with the discriminants for LogLevelFilter below
+    /// The "warn" level.
+    ///
+    /// Designates hazardous situations.
+    Warn,
+    /// The "info" level.
+    ///
+    /// Designates useful information.
+    Info,
+    /// The "debug" level.
+    ///
+    /// Designates lower priority information.
+    Debug,
+    /// The "trace" level.
+    ///
+    /// Designates very low priority, often extremely verbose, information.
+    Trace,
+}
+
+impl Clone for LogLevel {
+    #[inline]
+    fn clone(&self) -> LogLevel {
+        *self
+    }
+}
+
+impl PartialEq for LogLevel {
+    #[inline]
+    fn eq(&self, other: &LogLevel) -> bool {
+        *self as usize == *other as usize
+    }
+}
+
+impl PartialEq<LogLevelFilter> for LogLevel {
+    #[inline]
+    fn eq(&self, other: &LogLevelFilter) -> bool {
+        *self as usize == *other as usize
+    }
+}
+
+impl PartialOrd for LogLevel {
+    #[inline]
+    fn partial_cmp(&self, other: &LogLevel) -> Option<cmp::Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl PartialOrd<LogLevelFilter> for LogLevel {
+    #[inline]
+    fn partial_cmp(&self, other: &LogLevelFilter) -> Option<cmp::Ordering> {
+        Some((*self as usize).cmp(&(*other as usize)))
+    }
+}
+
+impl Ord for LogLevel {
+    #[inline]
+    fn cmp(&self, other: &LogLevel) -> cmp::Ordering {
+        (*self as usize).cmp(&(*other as usize))
+    }
+}
+
+fn ok_or<T, E>(t: Option<T>, e: E) -> Result<T, E> {
+    match t {
+        Some(t) => Ok(t),
+        None => Err(e),
+    }
+}
+
+impl FromStr for LogLevel {
+    type Err = ();
+    fn from_str(level: &str) -> Result<LogLevel, ()> {
+        ok_or(LOG_LEVEL_NAMES.iter()
+                    .position(|&name| name.eq_ignore_ascii_case(level))
+                    .into_iter()
+                    .filter(|&idx| idx != 0)
+                    .map(|idx| LogLevel::from_usize(idx).unwrap())
+                    .next(), ())
+    }
+}
+
+impl fmt::Display for LogLevel {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        fmt.pad(LOG_LEVEL_NAMES[*self as usize])
+    }
+}
+
+impl LogLevel {
+    fn from_usize(u: usize) -> Option<LogLevel> {
+        match u {
+            1 => Some(LogLevel::Error),
+            2 => Some(LogLevel::Warn),
+            3 => Some(LogLevel::Info),
+            4 => Some(LogLevel::Debug),
+            5 => Some(LogLevel::Trace),
+            _ => None
+        }
+    }
+
+    /// Returns the most verbose logging level.
+    #[inline]
+    pub fn max() -> LogLevel {
+        LogLevel::Trace
+    }
+
+    /// Converts the `LogLevel` to the equivalent `LogLevelFilter`.
+    #[inline]
+    pub fn to_log_level_filter(&self) -> LogLevelFilter {
+        LogLevelFilter::from_usize(*self as usize).unwrap()
+    }
+}
+
+/// An enum representing the available verbosity level filters of the logging
+/// framework.
+///
+/// A `LogLevelFilter` may be compared directly to a `LogLevel`.
+#[repr(usize)]
+#[derive(Copy, Eq, Debug)]
+pub enum LogLevelFilter {
+    /// A level lower than all log levels.
+    Off,
+    /// Corresponds to the `Error` log level.
+    Error,
+    /// Corresponds to the `Warn` log level.
+    Warn,
+    /// Corresponds to the `Trace` log level.
+    Info,
+    /// Corresponds to the `Debug` log level.
+    Debug,
+    /// Corresponds to the `Trace` log level.
+    Trace,
+}
+
+// Deriving generates terrible impls of these traits
+
+impl Clone for LogLevelFilter {
+    #[inline]
+    fn clone(&self) -> LogLevelFilter {
+        *self
+    }
+}
+
+impl PartialEq for LogLevelFilter {
+    #[inline]
+    fn eq(&self, other: &LogLevelFilter) -> bool {
+        *self as usize == *other as usize
+    }
+}
+
+impl PartialEq<LogLevel> for LogLevelFilter {
+    #[inline]
+    fn eq(&self, other: &LogLevel) -> bool {
+        other.eq(self)
+    }
+}
+
+impl PartialOrd for LogLevelFilter {
+    #[inline]
+    fn partial_cmp(&self, other: &LogLevelFilter) -> Option<cmp::Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl PartialOrd<LogLevel> for LogLevelFilter {
+    #[inline]
+    fn partial_cmp(&self, other: &LogLevel) -> Option<cmp::Ordering> {
+        other.partial_cmp(self).map(|x| x.reverse())
+    }
+}
+
+impl Ord for LogLevelFilter {
+    #[inline]
+    fn cmp(&self, other: &LogLevelFilter) -> cmp::Ordering {
+        (*self as usize).cmp(&(*other as usize))
+    }
+}
+
+impl FromStr for LogLevelFilter {
+    type Err = ();
+    fn from_str(level: &str) -> Result<LogLevelFilter, ()> {
+        ok_or(LOG_LEVEL_NAMES.iter()
+                    .position(|&name| name.eq_ignore_ascii_case(level))
+                    .map(|p| LogLevelFilter::from_usize(p).unwrap()), ())
+    }
+}
+
+impl fmt::Display for LogLevelFilter {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        write!(fmt, "{}", LOG_LEVEL_NAMES[*self as usize])
+    }
+}
+
+impl LogLevelFilter {
+    fn from_usize(u: usize) -> Option<LogLevelFilter> {
+        match u {
+            0 => Some(LogLevelFilter::Off),
+            1 => Some(LogLevelFilter::Error),
+            2 => Some(LogLevelFilter::Warn),
+            3 => Some(LogLevelFilter::Info),
+            4 => Some(LogLevelFilter::Debug),
+            5 => Some(LogLevelFilter::Trace),
+            _ => None
+        }
+    }
+    /// Returns the most verbose logging level filter.
+    #[inline]
+    pub fn max() -> LogLevelFilter {
+        LogLevelFilter::Trace
+    }
+
+    /// Converts `self` to the equivalent `LogLevel`.
+    ///
+    /// Returns `None` if `self` is `LogLevelFilter::Off`.
+    #[inline]
+    pub fn to_log_level(&self) -> Option<LogLevel> {
+        LogLevel::from_usize(*self as usize)
+    }
+}
+
+/// The "payload" of a log message.
+pub struct LogRecord<'a> {
+    metadata: LogMetadata<'a>,
+    location: &'a LogLocation,
+    args: fmt::Arguments<'a>,
+}
+
+impl<'a> LogRecord<'a> {
+    /// The message body.
+    pub fn args(&self) -> &fmt::Arguments<'a> {
+        &self.args
+    }
+
+    /// Metadata about the log directive.
+    pub fn metadata(&self) -> &LogMetadata {
+        &self.metadata
+    }
+
+    /// The location of the log directive.
+    pub fn location(&self) -> &LogLocation {
+        self.location
+    }
+
+    /// The verbosity level of the message.
+    pub fn level(&self) -> LogLevel {
+        self.metadata.level()
+    }
+
+    /// The name of the target of the directive.
+    pub fn target(&self) -> &str {
+        self.metadata.target()
+    }
+}
+
+/// Metadata about a log message.
+pub struct LogMetadata<'a> {
+    level: LogLevel,
+    target: &'a str,
+}
+
+impl<'a> LogMetadata<'a> {
+    /// The verbosity level of the message.
+    pub fn level(&self) -> LogLevel {
+        self.level
+    }
+
+    /// The name of the target of the directive.
+    pub fn target(&self) -> &str {
+        self.target
+    }
+}
+
+/// A trait encapsulating the operations required of a logger
+pub trait Log: Sync+Send {
+    /// Determines if a log message with the specified metadata would be
+    /// logged.
+    ///
+    /// This is used by the `log_enabled!` macro to allow callers to avoid
+    /// expensive computation of log message arguments if the message would be
+    /// discarded anyway.
+    fn enabled(&self, metadata: &LogMetadata) -> bool;
+
+    /// Logs the `LogRecord`.
+    ///
+    /// Note that `enabled` is *not* necessarily called before this method.
+    /// Implementations of `log` should perform all necessary filtering
+    /// internally.
+    fn log(&self, record: &LogRecord);
+}
+
+/// The location of a log message.
+///
+/// # Warning
+///
+/// The fields of this struct are public so that they may be initialized by the
+/// `log!` macro. They are subject to change at any time and should never be
+/// accessed directly.
+#[derive(Copy, Clone, Debug)]
+pub struct LogLocation {
+    #[doc(hidden)]
+    pub __module_path: &'static str,
+    #[doc(hidden)]
+    pub __file: &'static str,
+    #[doc(hidden)]
+    pub __line: u32,
+}
+
+impl LogLocation {
+    /// The module path of the message.
+    pub fn module_path(&self) -> &str {
+        self.__module_path
+    }
+
+    /// The source file containing the message.
+    pub fn file(&self) -> &str {
+        self.__file
+    }
+
+    /// The line containing the message.
+    pub fn line(&self) -> u32 {
+        self.__line
+    }
+}
+
+/// A token providing read and write access to the global maximum log level
+/// filter.
+///
+/// The maximum log level is used as an optimization to avoid evaluating log
+/// messages that will be ignored by the logger. Any message with a level
+/// higher than the maximum log level filter will be ignored. A logger should
+/// make sure to keep the maximum log level filter in sync with its current
+/// configuration.
+#[allow(missing_copy_implementations)]
+pub struct MaxLogLevelFilter(());
+
+impl fmt::Debug for MaxLogLevelFilter {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        write!(fmt, "MaxLogLevelFilter")
+    }
+}
+
+impl MaxLogLevelFilter {
+    /// Gets the current maximum log level filter.
+    pub fn get(&self) -> LogLevelFilter {
+        max_log_level()
+    }
+
+    /// Sets the maximum log level.
+    pub fn set(&self, level: LogLevelFilter) {
+        MAX_LOG_LEVEL_FILTER.store(level as usize, Ordering::SeqCst)
+    }
+}
+
+/// Returns the current maximum log level.
+///
+/// The `log!`, `error!`, `warn!`, `info!`, `debug!`, and `trace!` macros check
+/// this value and discard any message logged at a higher level. The maximum
+/// log level is set by the `MaxLogLevel` token passed to loggers.
+#[inline(always)]
+pub fn max_log_level() -> LogLevelFilter {
+    unsafe { mem::transmute(MAX_LOG_LEVEL_FILTER.load(Ordering::Relaxed)) }
+}
+
+/// Sets the global logger.
+///
+/// The `make_logger` closure is passed a `MaxLogLevel` object, which the
+/// logger should use to keep the global maximum log level in sync with the
+/// highest log level that the logger will not ignore.
+///
+/// This function may only be called once in the lifetime of a program. Any log
+/// events that occur before the call to `set_logger` completes will be
+/// ignored.
+///
+/// This function does not typically need to be called manually. Logger
+/// implementations should provide an initialization method that calls
+/// `set_logger` internally.
+pub fn set_logger<M>(make_logger: M) -> Result<(), SetLoggerError>
+        where M: FnOnce(MaxLogLevelFilter) -> Box<Log> {
+    if LOGGER.compare_and_swap(UNINITIALIZED, INITIALIZING,
+                               Ordering::SeqCst) != UNINITIALIZED {
+        return Err(SetLoggerError(()));
+    }
+
+    let logger = Box::new(make_logger(MaxLogLevelFilter(())));
+    let logger = unsafe { mem::transmute::<Box<Box<Log>>, usize>(logger) };
+    LOGGER.store(logger, Ordering::SeqCst);
+
+    unsafe {
+        assert_eq!(libc::atexit(shutdown), 0);
+    }
+    return Ok(());
+
+    extern fn shutdown() {
+        // Set to INITIALIZING to prevent re-initialization after
+        let logger = LOGGER.swap(INITIALIZING, Ordering::SeqCst);
+
+        while REFCOUNT.load(Ordering::SeqCst) != 0 {
+            // FIXME add a sleep here when it doesn't involve timers
+        }
+
+        unsafe { mem::transmute::<usize, Box<Box<Log>>>(logger); }
+    }
+}
+
+/// The type returned by `set_logger` if `set_logger` has already been called.
+#[allow(missing_copy_implementations)]
+#[derive(Debug)]
+pub struct SetLoggerError(());
+
+impl fmt::Display for SetLoggerError {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        write!(fmt, "attempted to set a logger after the logging system \
+                     was already initialized")
+    }
+}
+
+impl error::Error for SetLoggerError {
+    fn description(&self) -> &str { "set_logger() called multiple times" }
+}
+
+struct LoggerGuard(usize);
+
+impl Drop for LoggerGuard {
+    fn drop(&mut self) {
+        REFCOUNT.fetch_sub(1, Ordering::SeqCst);
+    }
+}
+
+impl Deref for LoggerGuard {
+    type Target = Box<Log>;
+
+    fn deref(&self) -> &Box<Log+'static> {
+        unsafe { mem::transmute(self.0) }
+    }
+}
+
+fn logger() -> Option<LoggerGuard> {
+    REFCOUNT.fetch_add(1, Ordering::SeqCst);
+    let logger = LOGGER.load(Ordering::SeqCst);
+    if logger == UNINITIALIZED || logger == INITIALIZING {
+        REFCOUNT.fetch_sub(1, Ordering::SeqCst);
+        None
+    } else {
+        Some(LoggerGuard(logger))
+    }
+}
+
+// WARNING
+// This is not considered part of the crate's public API. It is subject to
+// change at any time.
+#[doc(hidden)]
+pub fn __enabled(level: LogLevel, target: &str) -> bool {
+    if let Some(logger) = logger() {
+        logger.enabled(&LogMetadata { level: level, target: target })
+    } else {
+        false
+    }
+}
+
+// WARNING
+// This is not considered part of the crate's public API. It is subject to
+// change at any time.
+#[doc(hidden)]
+pub fn __log(level: LogLevel, target: &str, loc: &LogLocation,
+             args: fmt::Arguments) {
+    if let Some(logger) = logger() {
+        let record = LogRecord {
+            metadata: LogMetadata {
+                level: level,
+                target: target,
+            },
+            location: loc,
+            args: args
+        };
+        logger.log(&record)
+    }
+}
+
+#[cfg(test)]
+mod tests {
+     use std::error::Error;
+     use super::{LogLevel, LogLevelFilter, SetLoggerError};
+
+     #[test]
+     fn test_loglevelfilter_from_str() {
+         let tests = [
+             ("off",   Ok(LogLevelFilter::Off)),
+             ("error", Ok(LogLevelFilter::Error)),
+             ("warn",  Ok(LogLevelFilter::Warn)),
+             ("info",  Ok(LogLevelFilter::Info)),
+             ("debug", Ok(LogLevelFilter::Debug)),
+             ("trace", Ok(LogLevelFilter::Trace)),
+             ("OFF",   Ok(LogLevelFilter::Off)),
+             ("ERROR", Ok(LogLevelFilter::Error)),
+             ("WARN",  Ok(LogLevelFilter::Warn)),
+             ("INFO",  Ok(LogLevelFilter::Info)),
+             ("DEBUG", Ok(LogLevelFilter::Debug)),
+             ("TRACE", Ok(LogLevelFilter::Trace)),
+             ("asdf",  Err(())),
+         ];
+         for &(s, ref expected) in &tests {
+             assert_eq!(expected, &s.parse());
+         }
+     }
+
+     #[test]
+     fn test_loglevel_from_str() {
+         let tests = [
+             ("OFF",   Err(())),
+             ("error", Ok(LogLevel::Error)),
+             ("warn",  Ok(LogLevel::Warn)),
+             ("info",  Ok(LogLevel::Info)),
+             ("debug", Ok(LogLevel::Debug)),
+             ("trace", Ok(LogLevel::Trace)),
+             ("ERROR", Ok(LogLevel::Error)),
+             ("WARN",  Ok(LogLevel::Warn)),
+             ("INFO",  Ok(LogLevel::Info)),
+             ("DEBUG", Ok(LogLevel::Debug)),
+             ("TRACE", Ok(LogLevel::Trace)),
+             ("asdf",  Err(())),
+         ];
+         for &(s, ref expected) in &tests {
+             assert_eq!(expected, &s.parse());
+         }
+     }
+
+     #[test]
+     fn test_loglevel_show() {
+         assert_eq!("INFO", LogLevel::Info.to_string());
+         assert_eq!("ERROR", LogLevel::Error.to_string());
+     }
+
+     #[test]
+     fn test_loglevelfilter_show() {
+         assert_eq!("OFF", LogLevelFilter::Off.to_string());
+         assert_eq!("ERROR", LogLevelFilter::Error.to_string());
+     }
+
+     #[test]
+     fn test_cross_cmp() {
+         assert!(LogLevel::Debug > LogLevelFilter::Error);
+         assert!(LogLevelFilter::Warn < LogLevel::Trace);
+         assert!(LogLevelFilter::Off < LogLevel::Error);
+     }
+
+     #[test]
+     fn test_cross_eq() {
+         assert!(LogLevel::Error == LogLevelFilter::Error);
+         assert!(LogLevelFilter::Off != LogLevel::Error);
+         assert!(LogLevel::Trace == LogLevelFilter::Trace);
+     }
+
+     #[test]
+     fn test_to_log_level() {
+         assert_eq!(Some(LogLevel::Error), LogLevelFilter::Error.to_log_level());
+         assert_eq!(None, LogLevelFilter::Off.to_log_level());
+         assert_eq!(Some(LogLevel::Debug), LogLevelFilter::Debug.to_log_level());
+     }
+
+     #[test]
+     fn test_to_log_level_filter() {
+         assert_eq!(LogLevelFilter::Error, LogLevel::Error.to_log_level_filter());
+         assert_eq!(LogLevelFilter::Trace, LogLevel::Trace.to_log_level_filter());
+     }
+
+     #[test]
+     fn test_error_trait() {
+         let e = SetLoggerError(());
+         assert_eq!(e.description(), "set_logger() called multiple times");
+     }
+}
+
+
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/log/macros.rs.html b/src/log/macros.rs.html new file mode 100644 index 0000000..cd4dd2a --- /dev/null +++ b/src/log/macros.rs.html @@ -0,0 +1,387 @@ + + + + + + + + + + macros.rs.html -- source + + + + + + + + + + + + + + + +
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+/// The standard logging macro.
+///
+/// This macro will generically log with the specified `LogLevel` and `format!`
+/// based argument list.
+///
+/// The `log_level` cfg can be used to statically disable logging at various
+/// levels.
+#[macro_export]
+macro_rules! log {
+    (target: $target:expr, $lvl:expr, $($arg:tt)+) => ({
+        static LOC: $crate::LogLocation = $crate::LogLocation {
+            __line: line!(),
+            __file: file!(),
+            __module_path: module_path!(),
+        };
+        let lvl = $lvl;
+        if !cfg!(log_level = "off") &&
+                (lvl <= $crate::LogLevel::Error || !cfg!(log_level = "error")) &&
+                (lvl <= $crate::LogLevel::Warn || !cfg!(log_level = "warn")) &&
+                (lvl <= $crate::LogLevel::Debug || !cfg!(log_level = "debug")) &&
+                (lvl <= $crate::LogLevel::Info || !cfg!(log_level = "info")) &&
+                lvl <= $crate::max_log_level() {
+            $crate::__log(lvl, $target, &LOC, format_args!($($arg)+))
+        }
+    });
+    ($lvl:expr, $($arg:tt)+) => (log!(target: module_path!(), $lvl, $($arg)+))
+}
+
+/// Logs a message at the error level.
+///
+/// Logging at this level is disabled if the `log_level = "off"` cfg is
+/// present.
+#[macro_export]
+macro_rules! error {
+    (target: $target:expr, $($arg:tt)*) => (
+        log!(target: $target, $crate::LogLevel::Error, $($arg)*);
+    );
+    ($($arg:tt)*) => (
+        log!($crate::LogLevel::Error, $($arg)*);
+    )
+}
+
+/// Logs a message at the warn level.
+///
+/// Logging at this level is disabled if any of the following cfgs are present:
+/// `log_level = "off"` or `log_level = "error"`.
+#[macro_export]
+macro_rules! warn {
+    (target: $target:expr, $($arg:tt)*) => (
+        log!(target: $target, $crate::LogLevel::Warn, $($arg)*);
+    );
+    ($($arg:tt)*) => (
+        log!($crate::LogLevel::Warn, $($arg)*);
+    )
+}
+
+/// Logs a message at the info level.
+///
+/// Logging at this level is disabled if any of the following cfgs are present:
+/// `log_level = "off"`, `log_level = "error"`, or
+/// `log_level = "warn"`.
+#[macro_export]
+macro_rules! info {
+    (target: $target:expr, $($arg:tt)*) => (
+        log!(target: $target, $crate::LogLevel::Info, $($arg)*);
+    );
+    ($($arg:tt)*) => (
+        log!($crate::LogLevel::Info, $($arg)*);
+    )
+}
+
+/// Logs a message at the debug level.
+///
+/// Logging at this level is disabled if any of the following cfgs are present:
+/// `log_level = "off"`, `log_level = "error"`, `log_level = "warn"`,
+/// or `log_level = "info"`.
+#[macro_export]
+macro_rules! debug {
+    (target: $target:expr, $($arg:tt)*) => (
+        log!(target: $target, $crate::LogLevel::Debug, $($arg)*);
+    );
+    ($($arg:tt)*) => (
+        log!($crate::LogLevel::Debug, $($arg)*);
+    )
+}
+
+/// Logs a message at the trace level.
+///
+/// Logging at this level is disabled if any of the following cfgs are present:
+/// `log_level = "off"`, `log_level = "error"`, `log_level = "warn"`,
+/// `log_level = "info"`, or `log_level = "debug"`.
+#[macro_export]
+macro_rules! trace {
+    (target: $target:expr, $($arg:tt)*) => (
+        log!(target: $target, $crate::LogLevel::Trace, $($arg)*);
+    );
+    ($($arg:tt)*) => (
+        log!($crate::LogLevel::Trace, $($arg)*);
+    )
+}
+
+/// Determines if a message logged at the specified level in that module will
+/// be logged.
+///
+/// This can be used to avoid expensive computation of log message arguments if
+/// the message would be ignored anyway.
+///
+/// # Examples
+///
+/// ```rust
+/// # #[macro_use]
+/// # extern crate log;
+/// use log::LogLevel::Debug;
+///
+/// # fn foo() {
+/// if log_enabled!(Debug) {
+///     debug!("expensive debug data: {}", expensive_call());
+/// }
+/// # }
+/// # fn expensive_call() -> u32 { 0 }
+/// # fn main() {}
+/// ```
+#[macro_export]
+macro_rules! log_enabled {
+    (target: $target:expr, $lvl:expr) => ({
+        let lvl = $lvl;
+        !cfg!(log_level = "off") &&
+            (lvl <= $crate::LogLevel::Error || !cfg!(log_level = "error")) &&
+            (lvl <= $crate::LogLevel::Warn || !cfg!(log_level = "warn")) &&
+            (lvl <= $crate::LogLevel::Debug || !cfg!(log_level = "debug")) &&
+            (lvl <= $crate::LogLevel::Info || !cfg!(log_level = "info")) &&
+            lvl <= $crate::max_log_level() &&
+            $crate::__enabled(lvl, $target)
+    });
+    ($lvl:expr) => (log_enabled!(target: module_path!(), $lvl))
+}
+
+
+ + + + + + + + + + + + + + + \ No newline at end of file -- cgit v1.2.3