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
//! JavaScript console consumer implementation.

use web_sys::console;

use crate::entry::Entry;
use crate::entry;
use crate::processor::consumer;
use wasm_bindgen::prelude::*;



mod js {
    use super::*;
    #[wasm_bindgen(inline_js = "
        export function console_group_end() {
            console.groupEnd()
        }
    ")]
    extern "C" {
        /// FIXME[WD]: Issue https://github.com/rustwasm/wasm-bindgen/issues/2376
        /// This is just the same as `wasm_bindgen::console::group_end` with one important
        /// difference. It seems that `wasm_bindgen` somehow caches all functions without args on
        /// initialization, and thus, as we are redefining what `console.group_end` is in JS, the
        /// function provided by the library, unlike this one, does not reflect the change.
        #[allow(unsafe_code)]
        pub fn console_group_end();
    }
}



// ==========================
// === JsConsole Consumer ===
// ==========================

/// A simple consumer which uses JavaScript console API to print hierarchical logs in a browser.
#[derive(Clone,Copy,Debug,Default)]
pub struct JsConsole;

impl<Levels> consumer::Definition<Levels,js_sys::Array> for JsConsole
where Levels:Writer {
    fn consume(&mut self, event:Entry<Levels>, message:Option<js_sys::Array>) {
        match &event.content {
            entry::Content::Message(_) => {
                if let Some(msg) = message {
                    event.level.write_by_level(&msg)
                }
            },
            entry::Content::GroupBegin(group) => {
                if let Some(msg) = message {
                    if group.collapsed { console::group_collapsed(&msg) }
                    else               { console::group(&msg) }
                }
            },
            entry::Content::GroupEnd => {
                js::console_group_end()
            }
        }
    }
}

/// Trait that is used to determine how the JS logging is dispatched for different log levels.
/// Default blanket implementation uses `console.log`.
pub trait Writer {
    /// Write message using the appropriate console method.
    fn write_by_level(&self, message:&js_sys::Array);
}

impl<T> Writer for T {
    default fn write_by_level(&self, message:&js_sys::Array) {
        console::log(message)
    }
}

impl Writer for crate::entry::level::DefaultLevels {
    fn write_by_level(&self, message:&js_sys::Array) {
        use crate::entry::level::DefaultLevels::*;
        match *self {
            Trace   => console::trace(message),
            Debug   => console::debug(message),
            Info    => console::info(message),
            Warning => console::warn(message),
            Error   => console::error(message),
        }
    }
}