Bug 1879857 - Update Glean to v57.0.0. r=chutten,supply-chain-reviewers,mach-reviewers

Differential Revision: https://phabricator.services.mozilla.com/D201621
This commit is contained in:
Travis Long 2024-02-13 20:47:02 +00:00
parent 568a508562
commit 05240e93a7
50 changed files with 5768 additions and 5703 deletions

21
Cargo.lock generated
View File

@ -2291,9 +2291,9 @@ dependencies = [
[[package]]
name = "glean"
version = "56.1.0"
version = "57.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e12e51799c1e40ba51f24e0ff232d35ea321403920bea31dc11de1afaeb541ef"
checksum = "ae5847ad58b7f925c984de7f4dffcad67d7d0befa59a5a888cf93741b5ef1e6a"
dependencies = [
"chrono",
"crossbeam-channel",
@ -2311,9 +2311,9 @@ dependencies = [
[[package]]
name = "glean-core"
version = "56.1.0"
version = "57.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f7570206325e7a20c45b60bf63f1f5b69c2ce0ee79ca0dc774e7c39eaab19aa"
checksum = "6831cadd28b625bc296732d71dc7c978f208ba27911cad072785f87f23b1e634"
dependencies = [
"android_logger",
"bincode",
@ -3304,12 +3304,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.17"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if 1.0.0",
]
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
[[package]]
name = "mach"
@ -4748,13 +4745,13 @@ dependencies = [
[[package]]
name = "rkv"
version = "0.18.4"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f0ea3af1393b22f8fe25615b6fa5d13072b7b622e66acffc8b12b2baa0342b1"
checksum = "2c6d906922d99c677624d2042a93f89b2b7df0f6411032237d5d99a602c2487c"
dependencies = [
"arrayref",
"bincode",
"bitflags 1.999.999",
"bitflags 2.4.1",
"byteorder",
"id-arena",
"lazy_static",

View File

@ -60,7 +60,7 @@ allprojects {
topsrcdir = gradle.mozconfig.topsrcdir
topobjdir = gradle.mozconfig.topobjdir
gleanVersion = "56.1.0"
gleanVersion = "57.0.0"
if (gleanVersion != getRustVersionFor("glean")) {
throw new StopExecutionException("Mismatched Glean version, expected: ${gleanVersion}," +
" found ${getRustVersionFor("glean")}")

31
gfx/wr/Cargo.lock generated
View File

@ -180,9 +180,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.4.0"
version = "2.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
dependencies = [
"serde",
]
@ -996,9 +996,9 @@ dependencies = [
[[package]]
name = "glean"
version = "56.1.0"
version = "57.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e12e51799c1e40ba51f24e0ff232d35ea321403920bea31dc11de1afaeb541ef"
checksum = "ae5847ad58b7f925c984de7f4dffcad67d7d0befa59a5a888cf93741b5ef1e6a"
dependencies = [
"chrono",
"crossbeam-channel",
@ -1016,9 +1016,9 @@ dependencies = [
[[package]]
name = "glean-core"
version = "56.1.0"
version = "57.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f7570206325e7a20c45b60bf63f1f5b69c2ce0ee79ca0dc774e7c39eaab19aa"
checksum = "6831cadd28b625bc296732d71dc7c978f208ba27911cad072785f87f23b1e634"
dependencies = [
"android_logger",
"bincode",
@ -1556,12 +1556,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.16"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8"
dependencies = [
"cfg-if 1.0.0",
]
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
[[package]]
name = "malloc_buf"
@ -2262,13 +2259,13 @@ checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
[[package]]
name = "rkv"
version = "0.18.4"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f0ea3af1393b22f8fe25615b6fa5d13072b7b622e66acffc8b12b2baa0342b1"
checksum = "2c6d906922d99c677624d2042a93f89b2b7df0f6411032237d5d99a602c2487c"
dependencies = [
"arrayref",
"bincode",
"bitflags 1.3.2",
"bitflags 2.4.2",
"byteorder",
"id-arena",
"lazy_static",
@ -3072,7 +3069,7 @@ name = "webrender"
version = "0.62.0"
dependencies = [
"bincode",
"bitflags 2.4.0",
"bitflags 2.4.2",
"build-parallel",
"byteorder",
"derive_more",
@ -3127,7 +3124,7 @@ name = "webrender_api"
version = "0.62.0"
dependencies = [
"app_units",
"bitflags 2.4.0",
"bitflags 2.4.2",
"byteorder",
"crossbeam-channel",
"euclid",
@ -3144,7 +3141,7 @@ dependencies = [
name = "webrender_build"
version = "0.0.2"
dependencies = [
"bitflags 2.4.0",
"bitflags 2.4.2",
"lazy_static",
"serde",
]

View File

@ -52,7 +52,7 @@ svg_fmt = "0.4"
tracy-rs = "0.1.2"
derive_more = { version = "0.99", default-features = false, features = ["add_assign"] }
etagere = "0.2.6"
glean = "56.1.0"
glean = "57.0.0"
firefox-on-glean = { version = "0.1.0", optional = true }
swgl = { path = "../swgl", optional = true }
topological-sort = "0.1"

View File

@ -25,7 +25,7 @@ tracy-rs = "0.1.2"
log = "0.4"
lazy_static = "1"
fxhash = "0.2.1"
glean = { version = "56.1.0", optional = true }
glean = { version = "57.0.0", optional = true }
firefox-on-glean = { version = "0.1.0", optional = true }
serde = { optional = true, version = "1.0", features = ["serde_derive"] }

View File

@ -93,7 +93,7 @@ vendored:third_party/python/wheel
vendored:third_party/python/zipp
# glean-sdk may not be installable if a wheel isn't available
# and it has to be built from source.
pypi-optional:glean-sdk==56.1.0:telemetry will not be collected
pypi-optional:glean-sdk==57.0.0:telemetry will not be collected
# Mach gracefully handles the case where `psutil` is unavailable.
# We aren't (yet) able to pin packages in automation, so we have to
# support down to the oldest locally-installed version (5.4.2).

View File

@ -13,7 +13,7 @@ log = "0.4"
moz_task = { path = "../../../../xpcom/rust/moz_task" }
nserror = { path = "../../../../xpcom/rust/nserror" }
nsstring = { path = "../../../../xpcom/rust/nsstring" }
rkv = { version = "0.18", default-features = false }
rkv = { version = "0.19", default-features = false }
rust_cascade = "1.4.0"
sha2 = "0.10.2"
storage_variant = { path = "../../../../storage/variant" }

View File

@ -226,17 +226,31 @@ who = "Chris H-C <chutten@mozilla.com>"
criteria = "safe-to-deploy"
user-id = 48 # Jan-Erik Rediger (badboy)
start = "2020-11-10"
end = "2024-02-24"
end = "2025-02-12"
notes = "The Glean SDKs are maintained by the Glean Team at Mozilla."
[[wildcard-audits.glean]]
who = "Travis Long <tlong@mozilla.com>"
criteria = "safe-to-deploy"
user-id = 66068 # Travis Long (travis79)
start = "2024-02-12"
end = "2025-02-13"
[[wildcard-audits.glean-core]]
who = "Chris H-C <chutten@mozilla.com>"
criteria = "safe-to-deploy"
user-id = 48 # Jan-Erik Rediger (badboy)
start = "2019-09-24"
end = "2024-02-24"
end = "2025-02-12"
notes = "The Glean SDKs are maintained by the Glean Team at Mozilla."
[[wildcard-audits.glean-core]]
who = "Travis Long <tlong@mozilla.com>"
criteria = "safe-to-deploy"
user-id = 66068 # Travis Long (travis79)
start = "2020-07-10"
end = "2025-02-13"
[[wildcard-audits.glslopt]]
who = "Jamie Nicol <jnicol@mozilla.com>"
criteria = "safe-to-deploy"

View File

@ -36,13 +36,6 @@ user-id = 2915
user-login = "Amanieu"
user-name = "Amanieu d'Antras"
[[publisher.audio_thread_priority]]
version = "0.30.0"
when = "2023-11-06"
user-id = 1258
user-login = "padenot"
user-name = "Paul Adenot"
[[publisher.audio_thread_priority]]
version = "0.31.0"
when = "2024-01-17"
@ -225,6 +218,13 @@ user-id = 48
user-login = "badboy"
user-name = "Jan-Erik Rediger"
[[publisher.glean]]
version = "57.0.0"
when = "2024-02-12"
user-id = 66068
user-login = "travis79"
user-name = "Travis Long"
[[publisher.glean-core]]
version = "56.1.0"
when = "2024-01-17"
@ -232,6 +232,13 @@ user-id = 48
user-login = "badboy"
user-name = "Jan-Erik Rediger"
[[publisher.glean-core]]
version = "57.0.0"
when = "2024-02-12"
user-id = 66068
user-login = "travis79"
user-name = "Travis Long"
[[publisher.glslopt]]
version = "0.1.9"
when = "2021-03-17"
@ -295,13 +302,6 @@ user-id = 1
user-login = "alexcrichton"
user-name = "Alex Crichton"
[[publisher.libc]]
version = "0.2.150"
when = "2023-11-05"
user-id = 51017
user-login = "JohnTitor"
user-name = "Yuki Okushi"
[[publisher.libc]]
version = "0.2.152"
when = "2024-01-07"
@ -309,13 +309,6 @@ user-id = 51017
user-login = "JohnTitor"
user-name = "Yuki Okushi"
[[publisher.linux-raw-sys]]
version = "0.4.7"
when = "2023-09-10"
user-id = 6825
user-login = "sunfishcode"
user-name = "Dan Gohman"
[[publisher.linux-raw-sys]]
version = "0.4.12"
when = "2023-11-30"
@ -386,13 +379,6 @@ user-id = 2915
user-login = "Amanieu"
user-name = "Amanieu d'Antras"
[[publisher.parking_lot_core]]
version = "0.9.8"
when = "2023-06-05"
user-id = 2915
user-login = "Amanieu"
user-name = "Amanieu d'Antras"
[[publisher.parking_lot_core]]
version = "0.9.9"
when = "2023-10-17"
@ -468,13 +454,6 @@ user-id = 57462
user-login = "mozkeeler"
user-name = "Dana Keeler"
[[publisher.rustix]]
version = "0.38.13"
when = "2023-09-10"
user-id = 6825
user-login = "sunfishcode"
user-name = "Dan Gohman"
[[publisher.rustix]]
version = "0.38.28"
when = "2023-12-09"
@ -559,13 +538,6 @@ user-id = 3618
user-login = "dtolnay"
user-name = "David Tolnay"
[[publisher.termcolor]]
version = "1.4.0"
when = "2023-11-14"
user-id = 189
user-login = "BurntSushi"
user-name = "Andrew Gallant"
[[publisher.termcolor]]
version = "1.4.1"
when = "2024-01-10"
@ -711,20 +683,6 @@ user-id = 1
user-login = "alexcrichton"
user-name = "Alex Crichton"
[[publisher.wasm-encoder]]
version = "0.38.0"
when = "2023-11-20"
user-id = 1
user-login = "alexcrichton"
user-name = "Alex Crichton"
[[publisher.wasm-encoder]]
version = "0.39.0"
when = "2024-01-09"
user-id = 1
user-login = "alexcrichton"
user-name = "Alex Crichton"
[[publisher.wasm-encoder]]
version = "0.40.0"
when = "2024-01-24"
@ -732,20 +690,6 @@ user-id = 1
user-login = "alexcrichton"
user-name = "Alex Crichton"
[[publisher.wasm-smith]]
version = "0.13.0"
when = "2023-11-20"
user-id = 1
user-login = "alexcrichton"
user-name = "Alex Crichton"
[[publisher.wasm-smith]]
version = "0.14.0"
when = "2024-01-09"
user-id = 1
user-login = "alexcrichton"
user-name = "Alex Crichton"
[[publisher.wasm-smith]]
version = "0.15.0"
when = "2024-01-24"
@ -753,20 +697,6 @@ user-id = 1
user-login = "alexcrichton"
user-name = "Alex Crichton"
[[publisher.wast]]
version = "69.0.0"
when = "2023-11-20"
user-id = 1
user-login = "alexcrichton"
user-name = "Alex Crichton"
[[publisher.wast]]
version = "70.0.0"
when = "2024-01-09"
user-id = 1
user-login = "alexcrichton"
user-name = "Alex Crichton"
[[publisher.wast]]
version = "70.0.1"
when = "2024-01-24"
@ -795,13 +725,6 @@ user-id = 64539
user-login = "kennykerr"
user-name = "Kenny Kerr"
[[publisher.windows-sys]]
version = "0.48.0"
when = "2023-03-31"
user-id = 64539
user-login = "kennykerr"
user-name = "Kenny Kerr"
[[publisher.windows-sys]]
version = "0.52.0"
when = "2023-11-15"
@ -858,19 +781,6 @@ I am employed by a member of the Bytecode Alliance and plan to continue doing
so and will actively maintain this crate over time.
"""
[[audits.bytecode-alliance.wildcard-audits.wasmparser]]
who = "Alex Crichton <alex@alexcrichton.com>"
criteria = "safe-to-deploy"
user-id = 1 # Alex Crichton (alexcrichton)
start = "2020-07-13"
end = "2024-04-14"
notes = """
This is a Bytecode Alliance authored crate maintained in the `wasm-tools`
repository of which I'm one of the primary maintainers and publishers for.
I am employed by a member of the Bytecode Alliance and plan to continue doing
so and will actively maintain this crate over time.
"""
[[audits.bytecode-alliance.wildcard-audits.wast]]
who = "Alex Crichton <alex@alexcrichton.com>"
criteria = "safe-to-deploy"
@ -982,24 +892,6 @@ who = "Benjamin Bouvier <public@benj.me>"
criteria = "safe-to-deploy"
version = "0.1.3"
[[audits.bytecode-alliance.audits.errno]]
who = "Dan Gohman <dev@sunfishcode.online>"
criteria = "safe-to-deploy"
version = "0.3.0"
notes = "This crate uses libc and windows-sys APIs to get and set the raw OS error value."
[[audits.bytecode-alliance.audits.errno]]
who = "Dan Gohman <dev@sunfishcode.online>"
criteria = "safe-to-deploy"
delta = "0.3.0 -> 0.3.1"
notes = "Just a dependency version bump and a bug fix for redox"
[[audits.bytecode-alliance.audits.errno-dragonfly]]
who = "Jamey Sharp <jsharp@fastly.com>"
criteria = "safe-to-deploy"
version = "0.1.2"
notes = "This should be portable to any POSIX system and seems like it should be part of the libc crate, but at any rate it's safe as is."
[[audits.bytecode-alliance.audits.fallible-iterator]]
who = "Alex Crichton <alex@alexcrichton.com>"
criteria = "safe-to-deploy"
@ -1116,12 +1008,6 @@ criteria = "safe-to-deploy"
delta = "0.31.1 -> 0.32.0"
notes = "Various new features and refactorings as one would expect from an object parsing crate, all looks good."
[[audits.bytecode-alliance.audits.peeking_take_while]]
who = "Nick Fitzgerald <fitzgen@gmail.com>"
criteria = "safe-to-deploy"
version = "1.0.0"
notes = "I am the author of this crate."
[[audits.bytecode-alliance.audits.percent-encoding]]
who = "Alex Crichton <alex@alexcrichton.com>"
criteria = "safe-to-deploy"
@ -1551,3 +1437,24 @@ criteria = "safe-to-deploy"
version = "1.4.0"
notes = "I have read over the macros, and audited the unsafe code."
aggregated-from = "https://raw.githubusercontent.com/mozilla/cargo-vet/main/supply-chain/audits.toml"
[[audits.mozilla.audits.log]]
who = "Jan-Erik Rediger <jrediger@mozilla.com>"
criteria = "safe-to-deploy"
delta = "0.4.17 -> 0.4.18"
notes = "One dependency removed, others updated (which we don't rely on), some APIs (which we don't use) changed."
aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml"
[[audits.mozilla.audits.log]]
who = "Kagami Sascha Rosylight <krosylight@mozilla.com>"
criteria = "safe-to-deploy"
delta = "0.4.18 -> 0.4.20"
notes = "Only cfg attribute and internal macro changes and module refactorings"
aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml"
[[audits.mozilla.audits.rkv]]
who = "Kagami Sascha Rosylight <krosylight@mozilla.com>"
criteria = "safe-to-deploy"
delta = "0.18.4 -> 0.19.0"
notes = "Maintained by Mozilla, no addition of unsafe blocks"
aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml"

File diff suppressed because one or more lines are too long

View File

@ -13,7 +13,7 @@
edition = "2021"
rust-version = "1.66"
name = "glean-core"
version = "56.1.0"
version = "57.0.0"
authors = [
"Jan-Erik Rediger <jrediger@mozilla.com>",
"The Glean Team <glean-team@mozilla.com>",
@ -62,7 +62,7 @@ version = "0.4.8"
version = "1.18.0"
[dependencies.rkv]
version = "0.18.4"
version = "0.19.0"
features = ["lmdb"]
default-features = false

View File

@ -33,8 +33,19 @@ namespace glean {
RecordedExperiment? glean_test_get_experiment_data(string experiment_id);
// Experimentation ID API
void glean_set_experimentation_id(string experimentation_id);
string? glean_test_get_experimentation_id();
// EXPERIMENTAL: Register a listener to receive notification of event recordings
//
// tag: String value used later to unregister the listener
// listener: An object which implements the GleanEventListener interface
void glean_register_event_listener(string tag, GleanEventListener listener);
// EXPERIMENTAL: Unregister a previously registered event listener
//
// tag: The tag used when registering the listener
void glean_unregister_event_listener(string tag);
// Server Knobs API
void glean_set_metrics_enabled_config(string json);
@ -163,6 +174,12 @@ callback interface OnGleanEvents {
void shutdown();
};
// A callback handler that receives the IDs of recorded events
callback interface GleanEventListener {
// Called when an event is recorded, indicating the id of the event
void on_event_recorded(string id);
};
// Deserialized experiment data.
dictionary RecordedExperiment {
// The experiment's branch.

View File

@ -229,6 +229,25 @@ fn setup_state(state: State) {
}
}
/// A global singleton that stores listener callbacks registered with Glean
/// to receive event recording notifications.
static EVENT_LISTENERS: OnceCell<Mutex<HashMap<String, Box<dyn GleanEventListener>>>> =
OnceCell::new();
fn event_listeners() -> &'static Mutex<HashMap<String, Box<dyn GleanEventListener>>> {
EVENT_LISTENERS.get_or_init(|| Mutex::new(HashMap::new()))
}
fn register_event_listener(tag: String, listener: Box<dyn GleanEventListener>) {
let mut lock = event_listeners().lock().unwrap();
lock.insert(tag, listener);
}
fn unregister_event_listener(tag: String) {
let mut lock = event_listeners().lock().unwrap();
lock.remove(&tag);
}
/// An error returned from callbacks.
#[derive(Debug)]
pub enum CallbackError {
@ -285,6 +304,13 @@ pub trait OnGleanEvents: Send {
}
}
/// A callback handler that receives the base identifier of recorded events
/// The identifier is in the format: <category>.<name>
pub trait GleanEventListener: Send {
/// Called when an event is recorded, indicating the id of the event
fn on_event_recorded(&self, id: String);
}
/// Initializes Glean.
///
/// # Arguments
@ -869,6 +895,18 @@ pub fn glean_test_get_experiment_data(experiment_id: String) -> Option<RecordedE
core::with_glean(|glean| glean.test_get_experiment_data(experiment_id.to_owned()))
}
/// Set an experimentation identifier dynamically.
///
/// Note: it's probably a good idea to unenroll from any experiments when identifiers change.
pub fn glean_set_experimentation_id(experimentation_id: String) {
launch_with_glean(move |glean| {
glean
.additional_metrics
.experimentation_id
.set(experimentation_id);
});
}
/// TEST ONLY FUNCTION.
/// Gets stored experimentation id annotation.
pub fn glean_test_get_experimentation_id() -> Option<String> {
@ -1054,6 +1092,27 @@ pub fn glean_submit_ping_by_name_sync(ping_name: String, reason: Option<String>)
core::with_glean(|glean| glean.submit_ping_by_name(&ping_name, reason.as_deref()))
}
/// EXPERIMENTAL: Register a listener object to recieve notifications of event recordings.
///
/// # Arguments
///
/// * `tag` - A string identifier used to later unregister the listener
/// * `listener` - Implements the `GleanEventListener` trait
pub fn glean_register_event_listener(tag: String, listener: Box<dyn GleanEventListener>) {
register_event_listener(tag, listener);
}
/// Unregister an event listener from recieving notifications.
///
/// Does not panic if the listener doesn't exist.
///
/// # Arguments
///
/// * `tag` - The tag used when registering the listener to be unregistered
pub fn glean_unregister_event_listener(tag: String) {
unregister_event_listener(tag);
}
/// **TEST-ONLY Method**
///
/// Set test mode

View File

@ -84,6 +84,14 @@ impl EventMetric {
}
}
});
let id = self.meta().base_identifier();
crate::launch_with_glean(move |_| {
let event_listeners = crate::event_listeners().lock().unwrap();
event_listeners
.iter()
.for_each(|(_, listener)| listener.on_event_recorded(id.clone()));
});
}
/// Validate that extras are empty or all extra keys are allowed.

View File

@ -1 +1 @@
{"files":{"Cargo.toml":"2e86b801bfa27e59ddbe046a773d7ba937df8cef968e6d0c55ed7f534a77806e","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","README.md":"5627cc81e6187ab6c2b4dff061af16d559edcab64ba786bac39daa69c703c595","src/common_test.rs":"de47b53dcca37985c0a2b8c02daecbf32309aa54f5a4dd9290719c2c1fd0fa55","src/configuration.rs":"186b9d92e48f2f34f1ea51023ad83c9d7abec97bcb0b862641bcb79a93c97d9e","src/core_metrics.rs":"fef8fb4e5fa57c179836c6eb2cf59278fe3b8b036dbe57b0ff02971b4acd822f","src/lib.rs":"ffbfb09082bc7c758fcfa974226c7b7da75c88f259526a9ba085c511e1db1fa1","src/net/http_uploader.rs":"43812a70d19a38e8d7a093c8076c2b6345372c3c861b0f3511428762700a65e0","src/net/mod.rs":"612a9f13ade0b202c8762bccc7b5dc288101cb3820e47be2755331911a221c55","src/private/event.rs":"d7c70c02648584c19c73af89e5180d3c6153c911f2c6830f7d1599b18d6150eb","src/private/mod.rs":"eb8fe4e588bb32a54617324db39319920c627e6fc23c23cf4da5c17c63e0afed","src/private/ping.rs":"da7545b8fc3b8cbaa8f598dc18fa4ba7c499573c360e8de6e1714d38dd4a665d","src/system.rs":"6eae5b41c15eba9cad6dbd116abe3519ee3e1fe034e79bdd692b029829a8c384","src/test.rs":"3ff6cf151f416e7a8d0f1b54ff28360ad7ebd3dcf47df02c08a8039702d636d9","tests/common/mod.rs":"08fb9483d9b6ed9fe873b4395245166ae8a15263be750c7a8e298c41d9604745","tests/init_fails.rs":"96bbb67ec64976f505fc05eb2c2e101f06c11bd2eaf6a0c6383b1a3e05a1cf4b","tests/never_init.rs":"2cf13a67b34cda8447f489cf3755eba0595978d242d29025670f9bb7c1025937","tests/no_time_to_init.rs":"5fd92258e3fb0302c7f8ab1dee374ece7343cc727206d9da134442bca746b88d","tests/overflowing_preinit.rs":"7ad4b2274dd9240b53430859a4eb1d2597cf508a5a678333f3d3abbadd2ed4a7","tests/persist_ping_lifetime.rs":"81415dc1d74743f02269f0d0dfa524003147056853f080276972e64a0b761d3c","tests/persist_ping_lifetime_nopanic.rs":"18379d3ffbf4a2c8c684c04ff7a0660b86dfbbb447db2d24dfed6073cb7ddf8f","tests/schema.rs":"e611cc168b648b5f515c54873c71b3e5e86431afa2aaff94581eeeb4f1d4935d","tests/simple.rs":"3a762995c06c0adc5adb94ad9c37e41dbbcf08a96b87bc20a449240fa0d93b0c","tests/test-shutdown-blocking.sh":"9b16a01c190c7062474dd92182298a3d9a27928c8fa990340fdd798e6cdb7ab2","tests/test-thread-crashing.sh":"ff1bc8e5d7e4ba3a10d0d38bef222db8bfba469e7d30e45b1053d177a4084f09","tests/upload_timing.rs":"4100ddba97cad28e1abfeb1492dfff61d151a67360392393d6f90d891b3e86be"},"package":"e12e51799c1e40ba51f24e0ff232d35ea321403920bea31dc11de1afaeb541ef"}
{"files":{"Cargo.toml":"13aebaf3dc74c32fa745410731828cf3b8d27025f5d3371b31178531bf49b009","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","README.md":"5627cc81e6187ab6c2b4dff061af16d559edcab64ba786bac39daa69c703c595","src/common_test.rs":"de47b53dcca37985c0a2b8c02daecbf32309aa54f5a4dd9290719c2c1fd0fa55","src/configuration.rs":"186b9d92e48f2f34f1ea51023ad83c9d7abec97bcb0b862641bcb79a93c97d9e","src/core_metrics.rs":"fef8fb4e5fa57c179836c6eb2cf59278fe3b8b036dbe57b0ff02971b4acd822f","src/lib.rs":"c0229403026edc22ddf53ea60ea92cdd2eb820c06f63a6057b3ef10050800279","src/net/http_uploader.rs":"43812a70d19a38e8d7a093c8076c2b6345372c3c861b0f3511428762700a65e0","src/net/mod.rs":"612a9f13ade0b202c8762bccc7b5dc288101cb3820e47be2755331911a221c55","src/private/event.rs":"d7c70c02648584c19c73af89e5180d3c6153c911f2c6830f7d1599b18d6150eb","src/private/mod.rs":"eb8fe4e588bb32a54617324db39319920c627e6fc23c23cf4da5c17c63e0afed","src/private/ping.rs":"da7545b8fc3b8cbaa8f598dc18fa4ba7c499573c360e8de6e1714d38dd4a665d","src/system.rs":"6eae5b41c15eba9cad6dbd116abe3519ee3e1fe034e79bdd692b029829a8c384","src/test.rs":"3ff6cf151f416e7a8d0f1b54ff28360ad7ebd3dcf47df02c08a8039702d636d9","tests/common/mod.rs":"08fb9483d9b6ed9fe873b4395245166ae8a15263be750c7a8e298c41d9604745","tests/init_fails.rs":"96bbb67ec64976f505fc05eb2c2e101f06c11bd2eaf6a0c6383b1a3e05a1cf4b","tests/never_init.rs":"2cf13a67b34cda8447f489cf3755eba0595978d242d29025670f9bb7c1025937","tests/no_time_to_init.rs":"5fd92258e3fb0302c7f8ab1dee374ece7343cc727206d9da134442bca746b88d","tests/overflowing_preinit.rs":"7ad4b2274dd9240b53430859a4eb1d2597cf508a5a678333f3d3abbadd2ed4a7","tests/persist_ping_lifetime.rs":"81415dc1d74743f02269f0d0dfa524003147056853f080276972e64a0b761d3c","tests/persist_ping_lifetime_nopanic.rs":"18379d3ffbf4a2c8c684c04ff7a0660b86dfbbb447db2d24dfed6073cb7ddf8f","tests/schema.rs":"e611cc168b648b5f515c54873c71b3e5e86431afa2aaff94581eeeb4f1d4935d","tests/simple.rs":"3a762995c06c0adc5adb94ad9c37e41dbbcf08a96b87bc20a449240fa0d93b0c","tests/test-shutdown-blocking.sh":"9b16a01c190c7062474dd92182298a3d9a27928c8fa990340fdd798e6cdb7ab2","tests/test-thread-crashing.sh":"ff1bc8e5d7e4ba3a10d0d38bef222db8bfba469e7d30e45b1053d177a4084f09","tests/upload_timing.rs":"4100ddba97cad28e1abfeb1492dfff61d151a67360392393d6f90d891b3e86be"},"package":"ae5847ad58b7f925c984de7f4dffcad67d7d0befa59a5a888cf93741b5ef1e6a"}

View File

@ -13,7 +13,7 @@
edition = "2021"
rust-version = "1.66"
name = "glean"
version = "56.1.0"
version = "57.0.0"
authors = [
"Jan-Erik Rediger <jrediger@mozilla.com>",
"The Glean Team <glean-team@mozilla.com>",
@ -42,7 +42,7 @@ features = ["serde"]
version = "0.5"
[dependencies.glean-core]
version = "56.1.0"
version = "57.0.0"
[dependencies.inherent]
version = "1"

View File

@ -172,6 +172,12 @@ pub fn set_experiment_inactive(experiment_id: String) {
glean_core::glean_set_experiment_inactive(experiment_id)
}
/// Dynamically set the experimentation identifier, as opposed to setting it through the configuration
/// during initialization.
pub fn set_experimentation_id(experimentation_id: String) {
glean_core::glean_set_experimentation_id(experimentation_id);
}
/// TEST ONLY FUNCTION.
/// Gets stored experimentation id.
pub fn test_get_experimentation_id() -> Option<String> {

View File

@ -1 +1 @@
{"files":{"CHANGELOG.md":"d96bb13d82aab1b8f01a077167eb3968fe27c4fbb7aa4933f0e257d42794eb76","Cargo.toml":"e0ff3b07a36ad23348c9cc7113ad787aefbc0c7b75517f5a68247863a4994e1c","LICENSE-APACHE":"7cfd738c53d61c79f07e348f622bf7707c9084237054d37fbe07788a75f5881c","LICENSE-MIT":"705aaaaecefa087c187bd2eacdb01b8ac1c5ee95b1d5d04d8d7efe0363207df8","README.md":"bd6ed9b3c1cf3329d7afca04eb03f5c36e75cf9cb0bbbffddb7f07f3f36f2ea0","benches/value.rs":"55bd5f795a524f0699b2858eb14cc456abebeb43d50c90d2bfc77cd7856e8050","build.rs":"91dd121dd1aa749c8c0c24bda658309d1313baa022afbc5af1fabd1104622376","src/kv/error.rs":"01d37bb1ecbb2ba1145cd6df0b0b9a3ea3f1a2c9586a4908d3256cb865365b7e","src/kv/key.rs":"e74b489cde28960f76d4038b02867b4cb724c206d31abd461abeaa04e73cf7ef","src/kv/mod.rs":"9d916f43fd9c2829991fcff6db32f23bb7864e1113a622d49e59f110e2f290cf","src/kv/source.rs":"3f7aadc5f30c0c821fd20d899d8529eba8088eeda0c8603814de689da25dd4e8","src/kv/value.rs":"3387875f0ffd5f4747f181c3bc5134974358993981e54b1f203d6dd835a50245","src/lib.rs":"69dd3c57d9c6438d2e5bda9dc657827dcd73561faff708358f2e6854f47a2a3d","src/macros.rs":"642640f48a9d61efed0213b3a61a2864e80e8f8ffb9541b7c44d3028d3a7f08c","src/serde.rs":"d8190561ed64398fe45142b261000255ea1bcda8707e6f1b07ef4b805da6829b","triagebot.toml":"2d1d46d069bc4e3739069676707ca2801e0e0ba58a784a264392362ff9ac4a77"},"package":"abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"}
{"files":{"CHANGELOG.md":"4cf5d5c08ecf2cca9bfc6c0393fb06375675e1a712cd0da17426d54dd6b26281","Cargo.toml":"400053190237140d908218465ab8942fe65196c43925be6faef37e284b5817ff","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"788bda1deb337541be7ddaf8a7483d1c315f008aeab72374973135ad490e06c4","benches/value.rs":"6ce7689c8c714c93fa58afa984aefe54f0fc279fdd69e1582d013c97d1688eba","src/__private_api.rs":"de6799f0772181878a2fbfb93146641243a86f1115f2e8234a255d70105e2e65","src/kv/error.rs":"5dea46a9eb2128442a60f7f8a0e0b9e5f155bc0e9ecc5134f91e466cb04c8a31","src/kv/key.rs":"941979c92db5f9b999b9eba4f96a8d43da034da80849fbfa65277f122b5fc39f","src/kv/mod.rs":"3592b750c206d5a36545d0c5f2e5db79c499c3f96dced13c5aeeacc7409b4ff6","src/kv/source.rs":"4fd7f0083caef44094984c02bd3d15d7e5fd6b95e809b2d6abab31aa8d01f5c3","src/kv/value.rs":"7f0ee0327dcfbb3df3ed4f0c8caed4bebd4b76bb7407f32f100d660f2a10eabd","src/lib.rs":"1332fb825d498244bf068ce929d744c7316888c7f99e4711149af69ed028730c","src/macros.rs":"f0604416b1a839ba84509c17bff3741766cfa401cb09c0b00e33c36ae1c710ad","src/serde.rs":"1f8614b42ffb1b34bdf58ce3ab6584b760a8a9e9aa6e00b27dc229cbc46f0a2b","triagebot.toml":"a135e10c777cd13459559bdf74fb704c1379af7c9b0f70bc49fa6f5a837daa81"},"package":"b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"}

View File

@ -1,241 +1,273 @@
# Change Log
## [Unreleased]
## [0.4.17] - 2022-04-29
* Update `kv_unstable` internal dependencies.
## [0.4.16] - 2022-03-22
* Fix a conflict with unqualified `Option` use in macros.
## [0.4.15] - 2022-02-23
* Silence a warning about the deprecated `spin_loop_hint`.
* Relax ordering in the atomic `set_max_level` call.
* Add thumbv4t-none-eabi to targets that don't support atomics
* Allow levels to be iterated over.
* Implement `Log` on some common wrapper types.
* Improvements to test coverage.
* Improvements to documentation.
* Add key-value support to the `log!` macros.
* Tighten `kv_unstable` internal dependencies so they don't bump past their current alpha.
* Add a simple visit API to `kv_unstable`.
* Support `NonZero*` integers as values in structured logging
* Support static strings as keys in structured logging
## [0.4.14] - 2021-01-27
* Remove the `__private_api_log_lit` special case.
* Fixed incorrect combination of `kv_unstable` and `std` features causing compile failures.
* Remove unstable `Value::to_*` conversions that were incorrectly using `as`.
* Rename unstable `Value::to_error` to `Value::to_borrowed_error`.
## [0.4.13] - 2021-01-11
* This is the same as `0.4.11`, except with a `kv_unstable_std` feature added to aid migrating current dependents to `0.4.14` (which was originally going to be `0.4.13` until it was decided to create a patch from `0.4.11` to minimize disruption).
## [0.4.12] - 2020-12-24
### New
* Support platforms without atomics by racing instead of failing to compile
* Implement `Log` for `Box<T: Log>`
* Update `cfg-if` to `1.0`
* Internal reworks of the structured logging API. Removed the `Fill` API
and added `source::as_map` and `source::as_list` to easily serialize a `Source`
as either a map of `{key: value, ..}` or as a list of `[(key, value), ..]`.
### Fixed
* Fixed deserialization of `LevelFilter` to use their `u64` index variants
## [0.4.11] - 2020-07-09
### New
* Support coercing structured values into concrete types.
* Reference the `win_dbg_logger` in the readme.
### Fixed
* Updates a few deprecated items used internally.
* Fixed issues in docs and expands sections.
* Show the correct build badge in the readme.
* Fix up a possible inference breakage with structured value errors.
* Respect formatting flags in structured value formatting.
## [0.4.10] - 2019-12-16 (yanked)
### Fixed
* Fixed the `log!` macros so they work in expression context (this regressed in `0.4.9`, which has been yanked).
## [0.4.9] - 2019-12-12 (yanked)
### Minimum Supported Rust Version
This release bumps the minimum compiler version to `1.31.0`. This was mainly needed for `cfg-if`,
but between `1.16.0` and `1.31.0` there are a lot of language and library improvements we now
take advantage of.
### New
* Unstable support for capturing key-value pairs in a record using the `log!` macros
### Improved
* Better documentation for max level filters.
* Internal updates to line up with bumped MSRV
## [0.4.8] - 2019-07-28
### New
* Support attempting to get `Record` fields as static strings.
## [0.4.7] - 2019-07-06
### New
* Support for embedded environments with thread-unsafe initialization.
* Initial unstable support for capturing structured data under the `kv_unstable`
feature gate. This new API doesn't affect existing users and may change in future
patches (so those changes may not appear in the changelog until it stabilizes).
### Improved
* Docs for using `log` with the 2018 edition.
* Error messages for macros missing arguments.
## [0.4.6] - 2018-10-27
### Improved
* Support 2018-style macro import for the `log_enabled!` macro.
## [0.4.5] - 2018-09-03
### Improved
* Make `log`'s internal helper macros less likely to conflict with user-defined
macros.
## [0.4.4] - 2018-08-17
### Improved
* Support 2018-style imports of the log macros.
## [0.4.3] - 2018-06-29
### Improved
* More code generation improvements.
## [0.4.2] - 2018-06-05
### Improved
* Log invocations now generate less code.
### Fixed
* Example Logger implementations now properly set the max log level.
## [0.4.1] - 2017-12-30
### Fixed
* Some doc links were fixed.
## [0.4.0] - 2017-12-24
The changes in this release include cleanup of some obscure functionality and a more robust public
API designed to support bridges to other logging systems, and provide more flexibility to new
features in the future.
### Compatibility
Vast portions of the Rust ecosystem use the 0.3.x release series of log, and we don't want to force
the community to go through the pain of upgrading every crate to 0.4.x at the exact same time. Along
with 0.4.0, we've published a new 0.3.9 release which acts as a "shim" over 0.4.0. This will allow
crates using either version to coexist without losing messages from one side or the other.
There is one caveat - a log message generated by a crate using 0.4.x but consumed by a logging
implementation using 0.3.x will not have a file name or module path. Applications affected by this
can upgrade their logging implementations to one using 0.4.x to avoid losing this information. The
other direction does not lose any information, fortunately!
**TL;DR** Libraries should feel comfortable upgrading to 0.4.0 without treating that as a breaking
change. Applications may need to update their logging implementation (e.g. env-logger) to a newer
version using log 0.4.x to avoid losing module and file information.
### New
* The crate is now `no_std` by default.
* `Level` and `LevelFilter` now implement `Serialize` and `Deserialize` when the `serde` feature is
enabled.
* The `Record` and `Metadata` types can now be constructed by third-party code via a builder API.
* The `logger` free function returns a reference to the logger implementation. This, along with the
ability to construct `Record`s, makes it possible to bridge from another logging framework to
this one without digging into the private internals of the crate. The standard `error!` `warn!`,
etc, macros now exclusively use the public API of the crate rather than "secret" internal APIs.
* `Log::flush` has been added to allow crates to tell the logging implementation to ensure that all
"in flight" log events have been persisted. This can be used, for example, just before an
application exits to ensure that asynchronous log sinks finish their work.
### Removed
* The `shutdown` and `shutdown_raw` functions have been removed. Supporting shutdown significantly
complicated the implementation and imposed a performance cost on each logging operation.
* The `log_panics` function and its associated `nightly` Cargo feature have been removed. Use the
[log-panics](https://crates.io/crates/log-panics) instead.
### Changed
* The `Log` prefix has been removed from type names. For example, `LogLevelFilter` is now
`LevelFilter`, and `LogRecord` is now `Record`.
* The `MaxLogLevelFilter` object has been removed in favor of a `set_max_level` free function.
* The `set_logger` free functions have been restructured. The logger is now directly passed to the
functions rather than a closure which returns the logger. `set_logger` now takes a `&'static
Log` and is usable in `no_std` contexts in place of the old `set_logger_raw`. `set_boxed_logger`
is a convenience function which takes a `Box<Log>` but otherwise acts like `set_logger`. It
requires the `std` feature.
* The `file` and `module_path` values in `Record` no longer have the `'static` lifetime to support
integration with other logging frameworks that don't provide a `'static` lifetime for the
equivalent values.
* The `file`, `line`, and `module_path` values in `Record` are now `Option`s to support integration
with other logging frameworks that don't provide those values.
### In the Future
* We're looking to add support for *structured* logging - the inclusion of extra key-value pairs of
information in a log event in addition to the normal string message. This should be able to be
added in a backwards compatible manner to the 0.4.x series when the design is worked out.
## Older
Look at the [release tags] for information about older releases.
[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.17...HEAD
[0.4.17]: https://github.com/rust-lang-nursery/log/compare/0.4.16...0.4.17
[0.4.16]: https://github.com/rust-lang-nursery/log/compare/0.4.15...0.4.16
[0.4.15]: https://github.com/rust-lang-nursery/log/compare/0.4.13...0.4.15
[0.4.14]: https://github.com/rust-lang-nursery/log/compare/0.4.13...0.4.14
[0.4.13]: https://github.com/rust-lang-nursery/log/compare/0.4.11...0.4.13
[0.4.12]: https://github.com/rust-lang-nursery/log/compare/0.4.11...0.4.12
[0.4.11]: https://github.com/rust-lang-nursery/log/compare/0.4.10...0.4.11
[0.4.10]: https://github.com/rust-lang-nursery/log/compare/0.4.9...0.4.10
[0.4.9]: https://github.com/rust-lang-nursery/log/compare/0.4.8...0.4.9
[0.4.8]: https://github.com/rust-lang-nursery/log/compare/0.4.7...0.4.8
[0.4.7]: https://github.com/rust-lang-nursery/log/compare/0.4.6...0.4.7
[0.4.6]: https://github.com/rust-lang-nursery/log/compare/0.4.5...0.4.6
[0.4.5]: https://github.com/rust-lang-nursery/log/compare/0.4.4...0.4.5
[0.4.4]: https://github.com/rust-lang-nursery/log/compare/0.4.3...0.4.4
[0.4.3]: https://github.com/rust-lang-nursery/log/compare/0.4.2...0.4.3
[0.4.2]: https://github.com/rust-lang-nursery/log/compare/0.4.1...0.4.2
[0.4.1]: https://github.com/rust-lang-nursery/log/compare/0.4.0...0.4.1
[0.4.0]: https://github.com/rust-lang-nursery/log/compare/0.3.8...0.4.0
[release tags]: https://github.com/rust-lang-nursery/log/releases
# Change Log
## [Unreleased]
## [0.4.20] - 2023-07-11
* Remove rustversion dev-dependency by @Thomasdezeeuw in https://github.com/rust-lang/log/pull/568
* Remove `local_inner_macros` usage by @EFanZh in https://github.com/rust-lang/log/pull/570
## [0.4.19] - 2023-06-10
* Use target_has_atomic instead of the old atomic_cas cfg by @GuillaumeGomez in https://github.com/rust-lang/log/pull/555
* Put MSRV into Cargo.toml by @est31 in https://github.com/rust-lang/log/pull/557
## [0.4.18] - 2023-05-28
* fix markdown links (again) by @hellow554 in https://github.com/rust-lang/log/pull/513
* add cargo doc to workflow by @hellow554 in https://github.com/rust-lang/log/pull/515
* Apply Clippy lints by @hellow554 in https://github.com/rust-lang/log/pull/516
* Replace ad-hoc eq_ignore_ascii_case with slice::eq_ignore_ascii_case by @glandium in https://github.com/rust-lang/log/pull/519
* fix up windows targets by @KodrAus in https://github.com/rust-lang/log/pull/528
* typo fix by @jiangying000 in https://github.com/rust-lang/log/pull/529
* Remove dependency on cfg_if by @EriKWDev in https://github.com/rust-lang/log/pull/536
* GitHub Workflows security hardening by @sashashura in https://github.com/rust-lang/log/pull/538
* Fix build status badge by @atouchet in https://github.com/rust-lang/log/pull/539
* Add call_logger to the documentation by @a1ecbr0wn in https://github.com/rust-lang/log/pull/547
* Use stable internals for key-value API by @KodrAus in https://github.com/rust-lang/log/pull/550
* Change wording of list of implementations by @Thomasdezeeuw in https://github.com/rust-lang/log/pull/553
* Add std-logger to list of implementations by @Thomasdezeeuw in https://github.com/rust-lang/log/pull/554
* Add `set_max_level_racy` and gate `set_max_level` by @djkoloski in https://github.com/rust-lang/log/pull/544
* [doc] src/lib.rs : prefix an unused variable with an underscore by @OccupyMars2025 in https://github.com/rust-lang/log/pull/561
* [doc] src/macros.rs : correct grammar errors of an example in lib documentation by @OccupyMars2025 in https://github.com/rust-lang/log/pull/562
## [0.4.17] - 2022-04-29
* Update `kv_unstable` internal dependencies.
## [0.4.16] - 2022-03-22
* Fix a conflict with unqualified `Option` use in macros.
## [0.4.15] - 2022-02-23
* Silence a warning about the deprecated `spin_loop_hint`.
* Relax ordering in the atomic `set_max_level` call.
* Add thumbv4t-none-eabi to targets that don't support atomics
* Allow levels to be iterated over.
* Implement `Log` on some common wrapper types.
* Improvements to test coverage.
* Improvements to documentation.
* Add key-value support to the `log!` macros.
* Tighten `kv_unstable` internal dependencies so they don't bump past their current alpha.
* Add a simple visit API to `kv_unstable`.
* Support `NonZero*` integers as values in structured logging
* Support static strings as keys in structured logging
## [0.4.14] - 2021-01-27
* Remove the `__private_api_log_lit` special case.
* Fixed incorrect combination of `kv_unstable` and `std` features causing compile failures.
* Remove unstable `Value::to_*` conversions that were incorrectly using `as`.
* Rename unstable `Value::to_error` to `Value::to_borrowed_error`.
## [0.4.13] - 2021-01-11
* This is the same as `0.4.11`, except with a `kv_unstable_std` feature added to aid migrating current dependents to `0.4.14` (which was originally going to be `0.4.13` until it was decided to create a patch from `0.4.11` to minimize disruption).
## [0.4.12] - 2020-12-24
### New
* Support platforms without atomics by racing instead of failing to compile
* Implement `Log` for `Box<T: Log>`
* Update `cfg-if` to `1.0`
* Internal reworks of the structured logging API. Removed the `Fill` API
and added `source::as_map` and `source::as_list` to easily serialize a `Source`
as either a map of `{key: value, ..}` or as a list of `[(key, value), ..]`.
### Fixed
* Fixed deserialization of `LevelFilter` to use their `u64` index variants
## [0.4.11] - 2020-07-09
### New
* Support coercing structured values into concrete types.
* Reference the `win_dbg_logger` in the readme.
### Fixed
* Updates a few deprecated items used internally.
* Fixed issues in docs and expands sections.
* Show the correct build badge in the readme.
* Fix up a possible inference breakage with structured value errors.
* Respect formatting flags in structured value formatting.
## [0.4.10] - 2019-12-16 (yanked)
### Fixed
* Fixed the `log!` macros so they work in expression context (this regressed in `0.4.9`, which has been yanked).
## [0.4.9] - 2019-12-12 (yanked)
### Minimum Supported Rust Version
This release bumps the minimum compiler version to `1.31.0`. This was mainly needed for `cfg-if`,
but between `1.16.0` and `1.31.0` there are a lot of language and library improvements we now
take advantage of.
### New
* Unstable support for capturing key-value pairs in a record using the `log!` macros
### Improved
* Better documentation for max level filters.
* Internal updates to line up with bumped MSRV
## [0.4.8] - 2019-07-28
### New
* Support attempting to get `Record` fields as static strings.
## [0.4.7] - 2019-07-06
### New
* Support for embedded environments with thread-unsafe initialization.
* Initial unstable support for capturing structured data under the `kv_unstable`
feature gate. This new API doesn't affect existing users and may change in future
patches (so those changes may not appear in the changelog until it stabilizes).
### Improved
* Docs for using `log` with the 2018 edition.
* Error messages for macros missing arguments.
## [0.4.6] - 2018-10-27
### Improved
* Support 2018-style macro import for the `log_enabled!` macro.
## [0.4.5] - 2018-09-03
### Improved
* Make `log`'s internal helper macros less likely to conflict with user-defined
macros.
## [0.4.4] - 2018-08-17
### Improved
* Support 2018-style imports of the log macros.
## [0.4.3] - 2018-06-29
### Improved
* More code generation improvements.
## [0.4.2] - 2018-06-05
### Improved
* Log invocations now generate less code.
### Fixed
* Example Logger implementations now properly set the max log level.
## [0.4.1] - 2017-12-30
### Fixed
* Some doc links were fixed.
## [0.4.0] - 2017-12-24
The changes in this release include cleanup of some obscure functionality and a more robust public
API designed to support bridges to other logging systems, and provide more flexibility to new
features in the future.
### Compatibility
Vast portions of the Rust ecosystem use the 0.3.x release series of log, and we don't want to force
the community to go through the pain of upgrading every crate to 0.4.x at the exact same time. Along
with 0.4.0, we've published a new 0.3.9 release which acts as a "shim" over 0.4.0. This will allow
crates using either version to coexist without losing messages from one side or the other.
There is one caveat - a log message generated by a crate using 0.4.x but consumed by a logging
implementation using 0.3.x will not have a file name or module path. Applications affected by this
can upgrade their logging implementations to one using 0.4.x to avoid losing this information. The
other direction does not lose any information, fortunately!
**TL;DR** Libraries should feel comfortable upgrading to 0.4.0 without treating that as a breaking
change. Applications may need to update their logging implementation (e.g. env-logger) to a newer
version using log 0.4.x to avoid losing module and file information.
### New
* The crate is now `no_std` by default.
* `Level` and `LevelFilter` now implement `Serialize` and `Deserialize` when the `serde` feature is
enabled.
* The `Record` and `Metadata` types can now be constructed by third-party code via a builder API.
* The `logger` free function returns a reference to the logger implementation. This, along with the
ability to construct `Record`s, makes it possible to bridge from another logging framework to
this one without digging into the private internals of the crate. The standard `error!` `warn!`,
etc, macros now exclusively use the public API of the crate rather than "secret" internal APIs.
* `Log::flush` has been added to allow crates to tell the logging implementation to ensure that all
"in flight" log events have been persisted. This can be used, for example, just before an
application exits to ensure that asynchronous log sinks finish their work.
### Removed
* The `shutdown` and `shutdown_raw` functions have been removed. Supporting shutdown significantly
complicated the implementation and imposed a performance cost on each logging operation.
* The `log_panics` function and its associated `nightly` Cargo feature have been removed. Use the
[log-panics](https://crates.io/crates/log-panics) instead.
### Changed
* The `Log` prefix has been removed from type names. For example, `LogLevelFilter` is now
`LevelFilter`, and `LogRecord` is now `Record`.
* The `MaxLogLevelFilter` object has been removed in favor of a `set_max_level` free function.
* The `set_logger` free functions have been restructured. The logger is now directly passed to the
functions rather than a closure which returns the logger. `set_logger` now takes a `&'static
Log` and is usable in `no_std` contexts in place of the old `set_logger_raw`. `set_boxed_logger`
is a convenience function which takes a `Box<Log>` but otherwise acts like `set_logger`. It
requires the `std` feature.
* The `file` and `module_path` values in `Record` no longer have the `'static` lifetime to support
integration with other logging frameworks that don't provide a `'static` lifetime for the
equivalent values.
* The `file`, `line`, and `module_path` values in `Record` are now `Option`s to support integration
with other logging frameworks that don't provide those values.
### In the Future
* We're looking to add support for *structured* logging - the inclusion of extra key-value pairs of
information in a log event in addition to the normal string message. This should be able to be
added in a backwards compatible manner to the 0.4.x series when the design is worked out.
## Older
Look at the [release tags] for information about older releases.
[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.18...HEAD
[0.4.20]: https://github.com/rust-lang-nursery/log/compare/0.4.19...0.4.20
[0.4.19]: https://github.com/rust-lang-nursery/log/compare/0.4.18...0.4.19
[0.4.18]: https://github.com/rust-lang-nursery/log/compare/0.4.17...0.4.18
[0.4.17]: https://github.com/rust-lang-nursery/log/compare/0.4.16...0.4.17
[0.4.16]: https://github.com/rust-lang-nursery/log/compare/0.4.15...0.4.16
[0.4.15]: https://github.com/rust-lang-nursery/log/compare/0.4.13...0.4.15
[0.4.14]: https://github.com/rust-lang-nursery/log/compare/0.4.13...0.4.14
[0.4.13]: https://github.com/rust-lang-nursery/log/compare/0.4.11...0.4.13
[0.4.12]: https://github.com/rust-lang-nursery/log/compare/0.4.11...0.4.12
[0.4.11]: https://github.com/rust-lang-nursery/log/compare/0.4.10...0.4.11
[0.4.10]: https://github.com/rust-lang-nursery/log/compare/0.4.9...0.4.10
[0.4.9]: https://github.com/rust-lang-nursery/log/compare/0.4.8...0.4.9
[0.4.8]: https://github.com/rust-lang-nursery/log/compare/0.4.7...0.4.8
[0.4.7]: https://github.com/rust-lang-nursery/log/compare/0.4.6...0.4.7
[0.4.6]: https://github.com/rust-lang-nursery/log/compare/0.4.5...0.4.6
[0.4.5]: https://github.com/rust-lang-nursery/log/compare/0.4.4...0.4.5
[0.4.4]: https://github.com/rust-lang-nursery/log/compare/0.4.3...0.4.4
[0.4.3]: https://github.com/rust-lang-nursery/log/compare/0.4.2...0.4.3
[0.4.2]: https://github.com/rust-lang-nursery/log/compare/0.4.1...0.4.2
[0.4.1]: https://github.com/rust-lang-nursery/log/compare/0.4.0...0.4.1
[0.4.0]: https://github.com/rust-lang-nursery/log/compare/0.3.8...0.4.0
[release tags]: https://github.com/rust-lang-nursery/log/releases

View File

@ -10,10 +10,10 @@
# See Cargo.toml.orig for the original contents.
[package]
rust-version = "1.60.0"
name = "log"
version = "0.4.17"
version = "0.4.20"
authors = ["The Rust Project Developers"]
build = "build.rs"
exclude = ["rfcs/**/*"]
description = """
A lightweight logging facade for Rust
@ -44,26 +44,29 @@ name = "macros"
path = "tests/macros.rs"
harness = true
[dependencies.cfg-if]
version = "1.0"
[dependencies.serde]
version = "1.0"
optional = true
default-features = false
[dependencies.sval]
version = "=1.0.0-alpha.5"
version = "2.1"
optional = true
default-features = false
[dependencies.sval_ref]
version = "2.1"
optional = true
default-features = false
[dependencies.value-bag]
version = "=1.0.0-alpha.9"
version = "1.4"
optional = true
default-features = false
[dev-dependencies.rustversion]
version = "1.0"
[dev-dependencies.proc-macro2]
version = "1.0.63"
default-features = false
[dev-dependencies.serde]
version = "1.0"
@ -73,11 +76,13 @@ features = ["derive"]
version = "1.0"
[dev-dependencies.sval]
version = "=1.0.0-alpha.5"
features = ["derive"]
version = "2.1"
[dev-dependencies.sval_derive]
version = "2.1"
[dev-dependencies.value-bag]
version = "=1.0.0-alpha.9"
version = "1.4"
features = ["test"]
[features]
@ -96,6 +101,7 @@ kv_unstable_sval = [
"kv_unstable",
"value-bag/sval",
"sval",
"sval_ref",
]
max_level_debug = []
max_level_error = []

View File

@ -1,201 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1,25 +1,25 @@
Copyright (c) 2014 The Rust Project Developers
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
Copyright (c) 2014 The Rust Project Developers
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

View File

@ -1,117 +1,121 @@
log
===
A Rust library providing a lightweight logging *facade*.
[![Build status](https://img.shields.io/github/workflow/status/rust-lang/log/CI/master)](https://github.com/rust-lang/log/actions)
[![Latest version](https://img.shields.io/crates/v/log.svg)](https://crates.io/crates/log)
[![Documentation](https://docs.rs/log/badge.svg)](https://docs.rs/log)
![License](https://img.shields.io/crates/l/log.svg)
* [`log` documentation](https://docs.rs/log)
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
implementation that is most suitable for its use case.
## Minimum supported `rustc`
`1.31.0+`
This version is explicitly tested in CI and may be bumped in any release as needed. Maintaining compatibility with older compilers is a priority though, so the bar for bumping the minimum supported version is set very high. Any changes to the supported minimum version will be called out in the release notes.
## Usage
### 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:
```toml
[dependencies]
log = "0.4"
```
```rust
use log::{info, trace, warn};
pub fn shave_the_yak(yak: &mut Yak) {
trace!("Commencing yak shaving");
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);
}
}
}
}
```
### In executables
In order to produce log output, executables have to use a logger implementation compatible with the facade.
There are many available implementations to choose from, here are some of the most popular ones:
* Simple minimal loggers:
* [`env_logger`](https://docs.rs/env_logger/*/env_logger/)
* [`simple_logger`](https://docs.rs/simple_logger/*/simple_logger/)
* [`simplelog`](https://docs.rs/simplelog/*/simplelog/)
* [`pretty_env_logger`](https://docs.rs/pretty_env_logger/*/pretty_env_logger/)
* [`stderrlog`](https://docs.rs/stderrlog/*/stderrlog/)
* [`flexi_logger`](https://docs.rs/flexi_logger/*/flexi_logger/)
* Complex configurable frameworks:
* [`log4rs`](https://docs.rs/log4rs/*/log4rs/)
* [`fern`](https://docs.rs/fern/*/fern/)
* Adaptors for other facilities:
* [`syslog`](https://docs.rs/syslog/*/syslog/)
* [`systemd-journal-logger`](https://docs.rs/systemd-journal-logger/*/systemd_journal_logger/)
* [`slog-stdlog`](https://docs.rs/slog-stdlog/*/slog_stdlog/)
* [`android_log`](https://docs.rs/android_log/*/android_log/)
* [`win_dbg_logger`](https://docs.rs/win_dbg_logger/*/win_dbg_logger/)
* [`db_logger`](https://docs.rs/db_logger/*/db_logger/)
* For WebAssembly binaries:
* [`console_log`](https://docs.rs/console_log/*/console_log/)
* For dynamic libraries:
* You may need to construct [an FFI-safe wrapper over `log`](https://github.com/rust-lang/log/issues/421) to initialize in your libraries.
* Utilities:
* [`log_err`](https://docs.rs/log_err/*/log_err/)
Executables should choose a logger implementation and initialize it early in the
runtime of the program. Logger implementations will typically include a
function to do this. Any log messages generated before the logger is
initialized will be ignored.
The executable itself may use the `log` crate to log as well.
## Structured logging
If you enable the `kv_unstable` feature, you can associate structured data with your log records:
```rust
use log::{info, trace, warn, as_serde, as_error};
pub fn shave_the_yak(yak: &mut Yak) {
trace!(target = "yak_events", yak = as_serde!(yak); "Commencing yak shaving");
loop {
match find_a_razor() {
Ok(razor) => {
info!(razor = razor; "Razor located");
yak.shave(razor);
break;
}
Err(err) => {
warn!(err = as_error!(err); "Unable to locate a razor, retrying");
}
}
}
}
```
log
===
A Rust library providing a lightweight logging *facade*.
[![Build status](https://img.shields.io/github/actions/workflow/status/rust-lang/log/main.yml?branch=master)](https://github.com/rust-lang/log/actions)
[![Latest version](https://img.shields.io/crates/v/log.svg)](https://crates.io/crates/log)
[![Documentation](https://docs.rs/log/badge.svg)](https://docs.rs/log)
![License](https://img.shields.io/crates/l/log.svg)
* [`log` documentation](https://docs.rs/log)
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
implementation that is most suitable for its use case.
## Minimum supported `rustc`
`1.60.0+`
This version is explicitly tested in CI and may be bumped in any release as needed. Maintaining compatibility with older compilers is a priority though, so the bar for bumping the minimum supported version is set very high. Any changes to the supported minimum version will be called out in the release notes.
## Usage
### 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:
```toml
[dependencies]
log = "0.4"
```
```rust
use log::{info, trace, warn};
pub fn shave_the_yak(yak: &mut Yak) {
trace!("Commencing yak shaving");
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);
}
}
}
}
```
### In executables
In order to produce log output, executables have to use a logger implementation compatible with the facade.
There are many available implementations to choose from, here are some options:
* Simple minimal loggers:
* [`env_logger`](https://docs.rs/env_logger/*/env_logger/)
* [`simple_logger`](https://docs.rs/simple_logger/*/simple_logger/)
* [`simplelog`](https://docs.rs/simplelog/*/simplelog/)
* [`pretty_env_logger`](https://docs.rs/pretty_env_logger/*/pretty_env_logger/)
* [`stderrlog`](https://docs.rs/stderrlog/*/stderrlog/)
* [`flexi_logger`](https://docs.rs/flexi_logger/*/flexi_logger/)
* [`call_logger`](https://docs.rs/call_logger/*/call_logger/)
* [`std-logger`](https://docs.rs/std-logger/*/std_logger/)
* [`structured-logger`](https://docs.rs/structured-logger/latest/structured_logger/)
* Complex configurable frameworks:
* [`log4rs`](https://docs.rs/log4rs/*/log4rs/)
* [`fern`](https://docs.rs/fern/*/fern/)
* Adaptors for other facilities:
* [`syslog`](https://docs.rs/syslog/*/syslog/)
* [`systemd-journal-logger`](https://docs.rs/systemd-journal-logger/*/systemd_journal_logger/)
* [`slog-stdlog`](https://docs.rs/slog-stdlog/*/slog_stdlog/)
* [`android_log`](https://docs.rs/android_log/*/android_log/)
* [`win_dbg_logger`](https://docs.rs/win_dbg_logger/*/win_dbg_logger/)
* [`db_logger`](https://docs.rs/db_logger/*/db_logger/)
* [`log-to-defmt`](https://docs.rs/log-to-defmt/*/log_to_defmt/)
* For WebAssembly binaries:
* [`console_log`](https://docs.rs/console_log/*/console_log/)
* For dynamic libraries:
* You may need to construct [an FFI-safe wrapper over `log`](https://github.com/rust-lang/log/issues/421) to initialize in your libraries.
* Utilities:
* [`log_err`](https://docs.rs/log_err/*/log_err/)
Executables should choose a logger implementation and initialize it early in the
runtime of the program. Logger implementations will typically include a
function to do this. Any log messages generated before the logger is
initialized will be ignored.
The executable itself may use the `log` crate to log as well.
## Structured logging
If you enable the `kv_unstable` feature, you can associate structured data with your log records:
```rust
use log::{info, trace, warn, as_serde, as_error};
pub fn shave_the_yak(yak: &mut Yak) {
trace!(target = "yak_events", yak = as_serde!(yak); "Commencing yak shaving");
loop {
match find_a_razor() {
Ok(razor) => {
info!(razor = razor; "Razor located");
yak.shave(razor);
break;
}
Err(err) => {
warn!(err = as_error!(err); "Unable to locate a razor, retrying");
}
}
}
}
```

View File

@ -1,30 +1,30 @@
#![cfg(feature = "kv_unstable")]
#![feature(test)]
extern crate log;
extern crate test;
use log::kv::Value;
#[bench]
fn u8_to_value(b: &mut test::Bencher) {
b.iter(|| Value::from(1u8))
}
#[bench]
fn u8_to_value_debug(b: &mut test::Bencher) {
b.iter(|| Value::from_debug(&1u8))
}
#[bench]
fn str_to_value_debug(b: &mut test::Bencher) {
b.iter(|| Value::from_debug(&"a string"))
}
#[bench]
fn custom_to_value_debug(b: &mut test::Bencher) {
#[derive(Debug)]
struct A;
b.iter(|| Value::from_debug(&A))
}
#![cfg(feature = "kv_unstable")]
#![feature(test)]
extern crate log;
extern crate test;
use log::kv::Value;
#[bench]
fn u8_to_value(b: &mut test::Bencher) {
b.iter(|| Value::from(1u8))
}
#[bench]
fn u8_to_value_debug(b: &mut test::Bencher) {
b.iter(|| Value::from_debug(&1u8))
}
#[bench]
fn str_to_value_debug(b: &mut test::Bencher) {
b.iter(|| Value::from_debug(&"a string"))
}
#[bench]
fn custom_to_value_debug(b: &mut test::Bencher) {
#[derive(Debug)]
struct A;
b.iter(|| Value::from_debug(&A))
}

View File

@ -1,46 +0,0 @@
//! This build script detects target platforms that lack proper support for
//! atomics and sets `cfg` flags accordingly.
use std::env;
use std::str;
fn main() {
let target = match rustc_target() {
Some(target) => target,
None => return,
};
if target_has_atomic_cas(&target) {
println!("cargo:rustc-cfg=atomic_cas");
}
if target_has_atomics(&target) {
println!("cargo:rustc-cfg=has_atomics");
}
println!("cargo:rerun-if-changed=build.rs");
}
fn target_has_atomic_cas(target: &str) -> bool {
match &target[..] {
"thumbv6m-none-eabi"
| "msp430-none-elf"
| "riscv32i-unknown-none-elf"
| "riscv32imc-unknown-none-elf" => false,
_ => true,
}
}
fn target_has_atomics(target: &str) -> bool {
match &target[..] {
"thumbv4t-none-eabi"
| "msp430-none-elf"
| "riscv32i-unknown-none-elf"
| "riscv32imc-unknown-none-elf" => false,
_ => true,
}
}
fn rustc_target() -> Option<String> {
env::var("TARGET").ok()
}

View File

@ -0,0 +1,57 @@
//! WARNING: this is not part of the crate's public API and is subject to change at any time
use crate::{Level, Metadata, Record};
use std::fmt::Arguments;
pub use std::option::Option;
pub use std::{file, format_args, line, module_path, stringify};
#[cfg(not(feature = "kv_unstable"))]
pub fn log(
args: Arguments,
level: Level,
&(target, module_path, file): &(&str, &'static str, &'static str),
line: u32,
kvs: Option<&[(&str, &str)]>,
) {
if kvs.is_some() {
panic!(
"key-value support is experimental and must be enabled using the `kv_unstable` feature"
)
}
crate::logger().log(
&Record::builder()
.args(args)
.level(level)
.target(target)
.module_path_static(Some(module_path))
.file_static(Some(file))
.line(Some(line))
.build(),
);
}
#[cfg(feature = "kv_unstable")]
pub fn log(
args: Arguments,
level: Level,
&(target, module_path, file): &(&str, &'static str, &'static str),
line: u32,
kvs: Option<&[(&str, &dyn crate::kv::ToValue)]>,
) {
crate::logger().log(
&Record::builder()
.args(args)
.level(level)
.target(target)
.module_path_static(Some(module_path))
.file_static(Some(file))
.line(Some(line))
.key_values(&kvs)
.build(),
);
}
pub fn enabled(level: Level, target: &str) -> bool {
crate::logger().enabled(&Metadata::builder().level(level).target(target).build())
}

View File

@ -1,90 +1,90 @@
use std::fmt;
/// An error encountered while working with structured data.
#[derive(Debug)]
pub struct Error {
inner: Inner,
}
#[derive(Debug)]
enum Inner {
#[cfg(feature = "std")]
Boxed(std_support::BoxedError),
Msg(&'static str),
Value(value_bag::Error),
Fmt,
}
impl Error {
/// Create an error from a message.
pub fn msg(msg: &'static str) -> Self {
Error {
inner: Inner::Msg(msg),
}
}
// Not public so we don't leak the `value_bag` API
pub(super) fn from_value(err: value_bag::Error) -> Self {
Error {
inner: Inner::Value(err),
}
}
// Not public so we don't leak the `value_bag` API
pub(super) fn into_value(self) -> value_bag::Error {
match self.inner {
Inner::Value(err) => err,
#[cfg(feature = "kv_unstable_std")]
_ => value_bag::Error::boxed(self),
#[cfg(not(feature = "kv_unstable_std"))]
_ => value_bag::Error::msg("error inspecting a value"),
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::Inner::*;
match &self.inner {
#[cfg(feature = "std")]
&Boxed(ref err) => err.fmt(f),
&Value(ref err) => err.fmt(f),
&Msg(ref msg) => msg.fmt(f),
&Fmt => fmt::Error.fmt(f),
}
}
}
impl From<fmt::Error> for Error {
fn from(_: fmt::Error) -> Self {
Error { inner: Inner::Fmt }
}
}
#[cfg(feature = "std")]
mod std_support {
use super::*;
use std::{error, io};
pub(super) type BoxedError = Box<dyn error::Error + Send + Sync>;
impl Error {
/// Create an error from a standard error type.
pub fn boxed<E>(err: E) -> Self
where
E: Into<BoxedError>,
{
Error {
inner: Inner::Boxed(err.into()),
}
}
}
impl error::Error for Error {}
impl From<io::Error> for Error {
fn from(err: io::Error) -> Self {
Error::boxed(err)
}
}
}
use std::fmt;
/// An error encountered while working with structured data.
#[derive(Debug)]
pub struct Error {
inner: Inner,
}
#[derive(Debug)]
enum Inner {
#[cfg(feature = "std")]
Boxed(std_support::BoxedError),
Msg(&'static str),
Value(value_bag::Error),
Fmt,
}
impl Error {
/// Create an error from a message.
pub fn msg(msg: &'static str) -> Self {
Error {
inner: Inner::Msg(msg),
}
}
// Not public so we don't leak the `value_bag` API
pub(super) fn from_value(err: value_bag::Error) -> Self {
Error {
inner: Inner::Value(err),
}
}
// Not public so we don't leak the `value_bag` API
pub(super) fn into_value(self) -> value_bag::Error {
match self.inner {
Inner::Value(err) => err,
#[cfg(feature = "kv_unstable_std")]
_ => value_bag::Error::boxed(self),
#[cfg(not(feature = "kv_unstable_std"))]
_ => value_bag::Error::msg("error inspecting a value"),
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::Inner::*;
match &self.inner {
#[cfg(feature = "std")]
&Boxed(ref err) => err.fmt(f),
&Value(ref err) => err.fmt(f),
&Msg(ref msg) => msg.fmt(f),
&Fmt => fmt::Error.fmt(f),
}
}
}
impl From<fmt::Error> for Error {
fn from(_: fmt::Error) -> Self {
Error { inner: Inner::Fmt }
}
}
#[cfg(feature = "std")]
mod std_support {
use super::*;
use std::{error, io};
pub(super) type BoxedError = Box<dyn error::Error + Send + Sync>;
impl Error {
/// Create an error from a standard error type.
pub fn boxed<E>(err: E) -> Self
where
E: Into<BoxedError>,
{
Error {
inner: Inner::Boxed(err.into()),
}
}
}
impl error::Error for Error {}
impl From<io::Error> for Error {
fn from(err: io::Error) -> Self {
Error::boxed(err)
}
}
}

View File

@ -1,172 +1,157 @@
//! Structured keys.
use std::borrow::Borrow;
use std::cmp;
use std::fmt;
use std::hash;
/// A type that can be converted into a [`Key`](struct.Key.html).
pub trait ToKey {
/// Perform the conversion.
fn to_key(&self) -> Key;
}
impl<'a, T> ToKey for &'a T
where
T: ToKey + ?Sized,
{
fn to_key(&self) -> Key {
(**self).to_key()
}
}
impl<'k> ToKey for Key<'k> {
fn to_key(&self) -> Key {
Key { key: self.key }
}
}
impl ToKey for str {
fn to_key(&self) -> Key {
Key::from_str(self)
}
}
/// A key in a structured key-value pair.
#[derive(Clone)]
pub struct Key<'k> {
key: &'k str,
}
impl<'k> Key<'k> {
/// Get a key from a borrowed string.
pub fn from_str(key: &'k str) -> Self {
Key { key: key }
}
/// Get a borrowed string from this key.
pub fn as_str(&self) -> &str {
self.key
}
}
impl<'k> fmt::Debug for Key<'k> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.key.fmt(f)
}
}
impl<'k> fmt::Display for Key<'k> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.key.fmt(f)
}
}
impl<'k> hash::Hash for Key<'k> {
fn hash<H>(&self, state: &mut H)
where
H: hash::Hasher,
{
self.as_str().hash(state)
}
}
impl<'k, 'ko> PartialEq<Key<'ko>> for Key<'k> {
fn eq(&self, other: &Key<'ko>) -> bool {
self.as_str().eq(other.as_str())
}
}
impl<'k> Eq for Key<'k> {}
impl<'k, 'ko> PartialOrd<Key<'ko>> for Key<'k> {
fn partial_cmp(&self, other: &Key<'ko>) -> Option<cmp::Ordering> {
self.as_str().partial_cmp(other.as_str())
}
}
impl<'k> Ord for Key<'k> {
fn cmp(&self, other: &Self) -> cmp::Ordering {
self.as_str().cmp(other.as_str())
}
}
impl<'k> AsRef<str> for Key<'k> {
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl<'k> Borrow<str> for Key<'k> {
fn borrow(&self) -> &str {
self.as_str()
}
}
impl<'k> From<&'k str> for Key<'k> {
fn from(s: &'k str) -> Self {
Key::from_str(s)
}
}
#[cfg(feature = "std")]
mod std_support {
use super::*;
use std::borrow::Cow;
impl ToKey for String {
fn to_key(&self) -> Key {
Key::from_str(self)
}
}
impl<'a> ToKey for Cow<'a, str> {
fn to_key(&self) -> Key {
Key::from_str(self)
}
}
}
#[cfg(feature = "kv_unstable_sval")]
mod sval_support {
use super::*;
extern crate sval;
use self::sval::value::{self, Value};
impl<'a> Value for Key<'a> {
fn stream(&self, stream: &mut value::Stream) -> value::Result {
self.key.stream(stream)
}
}
}
#[cfg(feature = "kv_unstable_serde")]
mod serde_support {
use super::*;
extern crate serde;
use self::serde::{Serialize, Serializer};
impl<'a> Serialize for Key<'a> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.key.serialize(serializer)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn key_from_string() {
assert_eq!("a key", Key::from_str("a key").as_str());
}
}
//! Structured keys.
use std::borrow::Borrow;
use std::fmt;
/// A type that can be converted into a [`Key`](struct.Key.html).
pub trait ToKey {
/// Perform the conversion.
fn to_key(&self) -> Key;
}
impl<'a, T> ToKey for &'a T
where
T: ToKey + ?Sized,
{
fn to_key(&self) -> Key {
(**self).to_key()
}
}
impl<'k> ToKey for Key<'k> {
fn to_key(&self) -> Key {
Key { key: self.key }
}
}
impl ToKey for str {
fn to_key(&self) -> Key {
Key::from_str(self)
}
}
/// A key in a structured key-value pair.
// These impls must only be based on the as_str() representation of the key
// If a new field (such as an optional index) is added to the key they must not affect comparison
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Key<'k> {
key: &'k str,
}
impl<'k> Key<'k> {
/// Get a key from a borrowed string.
pub fn from_str(key: &'k str) -> Self {
Key { key }
}
/// Get a borrowed string from this key.
pub fn as_str(&self) -> &str {
self.key
}
/// Try get a string borrowed for the `'k` lifetime from this key.
pub fn to_borrowed_str(&self) -> Option<&'k str> {
// NOTE: This API leaves room for keys to be owned
Some(self.key)
}
}
impl<'k> fmt::Display for Key<'k> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.key.fmt(f)
}
}
impl<'k> AsRef<str> for Key<'k> {
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl<'k> Borrow<str> for Key<'k> {
fn borrow(&self) -> &str {
self.as_str()
}
}
impl<'k> From<&'k str> for Key<'k> {
fn from(s: &'k str) -> Self {
Key::from_str(s)
}
}
#[cfg(feature = "std")]
mod std_support {
use super::*;
use std::borrow::Cow;
impl ToKey for String {
fn to_key(&self) -> Key {
Key::from_str(self)
}
}
impl<'a> ToKey for Cow<'a, str> {
fn to_key(&self) -> Key {
Key::from_str(self)
}
}
}
#[cfg(feature = "kv_unstable_sval")]
mod sval_support {
use super::*;
extern crate sval;
extern crate sval_ref;
use self::sval::Value;
use self::sval_ref::ValueRef;
impl<'a> Value for Key<'a> {
fn stream<'sval, S: sval::Stream<'sval> + ?Sized>(
&'sval self,
stream: &mut S,
) -> sval::Result {
self.key.stream(stream)
}
}
impl<'a> ValueRef<'a> for Key<'a> {
fn stream_ref<S: self::sval::Stream<'a> + ?Sized>(
&self,
stream: &mut S,
) -> self::sval::Result {
self.key.stream(stream)
}
}
}
#[cfg(feature = "kv_unstable_serde")]
mod serde_support {
use super::*;
extern crate serde;
use self::serde::{Serialize, Serializer};
impl<'a> Serialize for Key<'a> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.key.serialize(serializer)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn key_from_string() {
assert_eq!("a key", Key::from_str("a key").as_str());
}
}

View File

@ -1,26 +1,26 @@
//! **UNSTABLE:** Structured key-value pairs.
//!
//! This module is unstable and breaking changes may be made
//! at any time. See [the tracking issue](https://github.com/rust-lang-nursery/log/issues/328)
//! for more details.
//!
//! Add the `kv_unstable` feature to your `Cargo.toml` to enable
//! this module:
//!
//! ```toml
//! [dependencies.log]
//! features = ["kv_unstable"]
//! ```
mod error;
mod key;
pub mod source;
pub mod value;
pub use self::error::Error;
pub use self::key::{Key, ToKey};
pub use self::source::{Source, Visitor};
#[doc(inline)]
pub use self::value::{ToValue, Value};
//! **UNSTABLE:** Structured key-value pairs.
//!
//! This module is unstable and breaking changes may be made
//! at any time. See [the tracking issue](https://github.com/rust-lang-nursery/log/issues/328)
//! for more details.
//!
//! Add the `kv_unstable` feature to your `Cargo.toml` to enable
//! this module:
//!
//! ```toml
//! [dependencies.log]
//! features = ["kv_unstable"]
//! ```
mod error;
mod key;
pub mod source;
pub mod value;
pub use self::error::Error;
pub use self::key::{Key, ToKey};
pub use self::source::{Source, Visitor};
#[doc(inline)]
pub use self::value::{ToValue, Value};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,280 +1,240 @@
// 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 `Level` and `format!`
/// based argument list.
///
/// # Examples
///
/// ```edition2018
/// use log::{log, Level};
///
/// # fn main() {
/// let data = (42, "Forty-two");
/// let private_data = "private";
///
/// log!(Level::Error, "Received errors: {}, {}", data.0, data.1);
/// log!(target: "app_events", Level::Warn, "App warning: {}, {}, {}",
/// data.0, data.1, private_data);
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! log {
// log!(target: "my_target", Level::Info; key1 = 42, key2 = true; "a {} event", "log");
(target: $target:expr, $lvl:expr, $($key:tt = $value:expr),+; $($arg:tt)+) => ({
let lvl = $lvl;
if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() {
$crate::__private_api_log(
__log_format_args!($($arg)+),
lvl,
&($target, __log_module_path!(), __log_file!(), __log_line!()),
$crate::__private_api::Option::Some(&[$((__log_key!($key), &$value)),+])
);
}
});
// log!(target: "my_target", Level::Info; "a {} event", "log");
(target: $target:expr, $lvl:expr, $($arg:tt)+) => ({
let lvl = $lvl;
if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() {
$crate::__private_api_log(
__log_format_args!($($arg)+),
lvl,
&($target, __log_module_path!(), __log_file!(), __log_line!()),
$crate::__private_api::Option::None,
);
}
});
// log!(Level::Info, "a log event")
($lvl:expr, $($arg:tt)+) => (log!(target: __log_module_path!(), $lvl, $($arg)+));
}
/// Logs a message at the error level.
///
/// # Examples
///
/// ```edition2018
/// use log::error;
///
/// # fn main() {
/// let (err_info, port) = ("No connection", 22);
///
/// error!("Error: {} on port {}", err_info, port);
/// error!(target: "app_events", "App Error: {}, Port: {}", err_info, 22);
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! error {
// error!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log")
// error!(target: "my_target", "a {} event", "log")
(target: $target:expr, $($arg:tt)+) => (log!(target: $target, $crate::Level::Error, $($arg)+));
// error!("a {} event", "log")
($($arg:tt)+) => (log!($crate::Level::Error, $($arg)+))
}
/// Logs a message at the warn level.
///
/// # Examples
///
/// ```edition2018
/// use log::warn;
///
/// # fn main() {
/// let warn_description = "Invalid Input";
///
/// warn!("Warning! {}!", warn_description);
/// warn!(target: "input_events", "App received warning: {}", warn_description);
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! warn {
// warn!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log")
// warn!(target: "my_target", "a {} event", "log")
(target: $target:expr, $($arg:tt)+) => (log!(target: $target, $crate::Level::Warn, $($arg)+));
// warn!("a {} event", "log")
($($arg:tt)+) => (log!($crate::Level::Warn, $($arg)+))
}
/// Logs a message at the info level.
///
/// # Examples
///
/// ```edition2018
/// use log::info;
///
/// # fn main() {
/// # struct Connection { port: u32, speed: f32 }
/// let conn_info = Connection { port: 40, speed: 3.20 };
///
/// info!("Connected to port {} at {} Mb/s", conn_info.port, conn_info.speed);
/// info!(target: "connection_events", "Successfull connection, port: {}, speed: {}",
/// conn_info.port, conn_info.speed);
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! info {
// info!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log")
// info!(target: "my_target", "a {} event", "log")
(target: $target:expr, $($arg:tt)+) => (log!(target: $target, $crate::Level::Info, $($arg)+));
// info!("a {} event", "log")
($($arg:tt)+) => (log!($crate::Level::Info, $($arg)+))
}
/// Logs a message at the debug level.
///
/// # Examples
///
/// ```edition2018
/// use log::debug;
///
/// # fn main() {
/// # struct Position { x: f32, y: f32 }
/// let pos = Position { x: 3.234, y: -1.223 };
///
/// debug!("New position: x: {}, y: {}", pos.x, pos.y);
/// debug!(target: "app_events", "New position: x: {}, y: {}", pos.x, pos.y);
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! debug {
// debug!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log")
// debug!(target: "my_target", "a {} event", "log")
(target: $target:expr, $($arg:tt)+) => (log!(target: $target, $crate::Level::Debug, $($arg)+));
// debug!("a {} event", "log")
($($arg:tt)+) => (log!($crate::Level::Debug, $($arg)+))
}
/// Logs a message at the trace level.
///
/// # Examples
///
/// ```edition2018
/// use log::trace;
///
/// # fn main() {
/// # struct Position { x: f32, y: f32 }
/// let pos = Position { x: 3.234, y: -1.223 };
///
/// trace!("Position is: x: {}, y: {}", pos.x, pos.y);
/// trace!(target: "app_events", "x is {} and y is {}",
/// if pos.x >= 0.0 { "positive" } else { "negative" },
/// if pos.y >= 0.0 { "positive" } else { "negative" });
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! trace {
// trace!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log")
// trace!(target: "my_target", "a {} event", "log")
(target: $target:expr, $($arg:tt)+) => (log!(target: $target, $crate::Level::Trace, $($arg)+));
// trace!("a {} event", "log")
($($arg:tt)+) => (log!($crate::Level::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
///
/// ```edition2018
/// use log::Level::Debug;
/// use log::{debug, log_enabled};
///
/// # fn foo() {
/// if log_enabled!(Debug) {
/// let data = expensive_call();
/// debug!("expensive debug data: {} {}", data.x, data.y);
/// }
/// if log_enabled!(target: "Global", Debug) {
/// let data = expensive_call();
/// debug!(target: "Global", "expensive debug data: {} {}", data.x, data.y);
/// }
/// # }
/// # struct Data { x: u32, y: u32 }
/// # fn expensive_call() -> Data { Data { x: 0, y: 0 } }
/// # fn main() {}
/// ```
#[macro_export(local_inner_macros)]
macro_rules! log_enabled {
(target: $target:expr, $lvl:expr) => {{
let lvl = $lvl;
lvl <= $crate::STATIC_MAX_LEVEL
&& lvl <= $crate::max_level()
&& $crate::__private_api_enabled(lvl, $target)
}};
($lvl:expr) => {
log_enabled!(target: __log_module_path!(), $lvl)
};
}
// The log macro above cannot invoke format_args directly because it uses
// local_inner_macros. A format_args invocation there would resolve to
// $crate::format_args which does not exist. Instead invoke format_args here
// outside of local_inner_macros so that it resolves (probably) to
// core::format_args or std::format_args. Same for the several macros that
// follow.
//
// This is a workaround until we drop support for pre-1.30 compilers. At that
// point we can remove use of local_inner_macros, use $crate:: when invoking
// local macros, and invoke format_args directly.
#[doc(hidden)]
#[macro_export]
macro_rules! __log_format_args {
($($args:tt)*) => {
format_args!($($args)*)
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __log_module_path {
() => {
module_path!()
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __log_file {
() => {
file!()
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __log_line {
() => {
line!()
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __log_key {
// key1 = 42
($($args:ident)*) => {
stringify!($($args)*)
};
// "key1" = 42
($($args:expr)*) => {
$($args)*
};
}
// 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 `Level` and `format!`
/// based argument list.
///
/// # Examples
///
/// ```edition2018
/// use log::{log, Level};
///
/// # fn main() {
/// let data = (42, "Forty-two");
/// let private_data = "private";
///
/// log!(Level::Error, "Received errors: {}, {}", data.0, data.1);
/// log!(target: "app_events", Level::Warn, "App warning: {}, {}, {}",
/// data.0, data.1, private_data);
/// # }
/// ```
#[macro_export]
macro_rules! log {
// log!(target: "my_target", Level::Info, key1 = 42, key2 = true; "a {} event", "log");
(target: $target:expr, $lvl:expr, $($key:tt = $value:expr),+; $($arg:tt)+) => ({
let lvl = $lvl;
if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() {
$crate::__private_api::log(
$crate::__private_api::format_args!($($arg)+),
lvl,
&($target, $crate::__private_api::module_path!(), $crate::__private_api::file!()),
$crate::__private_api::line!(),
$crate::__private_api::Option::Some(&[$(($crate::__log_key!($key), &$value)),+])
);
}
});
// log!(target: "my_target", Level::Info, "a {} event", "log");
(target: $target:expr, $lvl:expr, $($arg:tt)+) => ({
let lvl = $lvl;
if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() {
$crate::__private_api::log(
$crate::__private_api::format_args!($($arg)+),
lvl,
&($target, $crate::__private_api::module_path!(), $crate::__private_api::file!()),
$crate::__private_api::line!(),
$crate::__private_api::Option::None,
);
}
});
// log!(Level::Info, "a log event")
($lvl:expr, $($arg:tt)+) => ($crate::log!(target: $crate::__private_api::module_path!(), $lvl, $($arg)+));
}
/// Logs a message at the error level.
///
/// # Examples
///
/// ```edition2018
/// use log::error;
///
/// # fn main() {
/// let (err_info, port) = ("No connection", 22);
///
/// error!("Error: {} on port {}", err_info, port);
/// error!(target: "app_events", "App Error: {}, Port: {}", err_info, 22);
/// # }
/// ```
#[macro_export]
macro_rules! error {
// error!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log")
// error!(target: "my_target", "a {} event", "log")
(target: $target:expr, $($arg:tt)+) => ($crate::log!(target: $target, $crate::Level::Error, $($arg)+));
// error!("a {} event", "log")
($($arg:tt)+) => ($crate::log!($crate::Level::Error, $($arg)+))
}
/// Logs a message at the warn level.
///
/// # Examples
///
/// ```edition2018
/// use log::warn;
///
/// # fn main() {
/// let warn_description = "Invalid Input";
///
/// warn!("Warning! {}!", warn_description);
/// warn!(target: "input_events", "App received warning: {}", warn_description);
/// # }
/// ```
#[macro_export]
macro_rules! warn {
// warn!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log")
// warn!(target: "my_target", "a {} event", "log")
(target: $target:expr, $($arg:tt)+) => ($crate::log!(target: $target, $crate::Level::Warn, $($arg)+));
// warn!("a {} event", "log")
($($arg:tt)+) => ($crate::log!($crate::Level::Warn, $($arg)+))
}
/// Logs a message at the info level.
///
/// # Examples
///
/// ```edition2018
/// use log::info;
///
/// # fn main() {
/// # struct Connection { port: u32, speed: f32 }
/// let conn_info = Connection { port: 40, speed: 3.20 };
///
/// info!("Connected to port {} at {} Mb/s", conn_info.port, conn_info.speed);
/// info!(target: "connection_events", "Successful connection, port: {}, speed: {}",
/// conn_info.port, conn_info.speed);
/// # }
/// ```
#[macro_export]
macro_rules! info {
// info!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log")
// info!(target: "my_target", "a {} event", "log")
(target: $target:expr, $($arg:tt)+) => ($crate::log!(target: $target, $crate::Level::Info, $($arg)+));
// info!("a {} event", "log")
($($arg:tt)+) => ($crate::log!($crate::Level::Info, $($arg)+))
}
/// Logs a message at the debug level.
///
/// # Examples
///
/// ```edition2018
/// use log::debug;
///
/// # fn main() {
/// # struct Position { x: f32, y: f32 }
/// let pos = Position { x: 3.234, y: -1.223 };
///
/// debug!("New position: x: {}, y: {}", pos.x, pos.y);
/// debug!(target: "app_events", "New position: x: {}, y: {}", pos.x, pos.y);
/// # }
/// ```
#[macro_export]
macro_rules! debug {
// debug!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log")
// debug!(target: "my_target", "a {} event", "log")
(target: $target:expr, $($arg:tt)+) => ($crate::log!(target: $target, $crate::Level::Debug, $($arg)+));
// debug!("a {} event", "log")
($($arg:tt)+) => ($crate::log!($crate::Level::Debug, $($arg)+))
}
/// Logs a message at the trace level.
///
/// # Examples
///
/// ```edition2018
/// use log::trace;
///
/// # fn main() {
/// # struct Position { x: f32, y: f32 }
/// let pos = Position { x: 3.234, y: -1.223 };
///
/// trace!("Position is: x: {}, y: {}", pos.x, pos.y);
/// trace!(target: "app_events", "x is {} and y is {}",
/// if pos.x >= 0.0 { "positive" } else { "negative" },
/// if pos.y >= 0.0 { "positive" } else { "negative" });
/// # }
/// ```
#[macro_export]
macro_rules! trace {
// trace!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log")
// trace!(target: "my_target", "a {} event", "log")
(target: $target:expr, $($arg:tt)+) => ($crate::log!(target: $target, $crate::Level::Trace, $($arg)+));
// trace!("a {} event", "log")
($($arg:tt)+) => ($crate::log!($crate::Level::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
///
/// ```edition2018
/// use log::Level::Debug;
/// use log::{debug, log_enabled};
///
/// # fn foo() {
/// if log_enabled!(Debug) {
/// let data = expensive_call();
/// debug!("expensive debug data: {} {}", data.x, data.y);
/// }
/// if log_enabled!(target: "Global", Debug) {
/// let data = expensive_call();
/// debug!(target: "Global", "expensive debug data: {} {}", data.x, data.y);
/// }
/// # }
/// # struct Data { x: u32, y: u32 }
/// # fn expensive_call() -> Data { Data { x: 0, y: 0 } }
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! log_enabled {
(target: $target:expr, $lvl:expr) => {{
let lvl = $lvl;
lvl <= $crate::STATIC_MAX_LEVEL
&& lvl <= $crate::max_level()
&& $crate::__private_api::enabled(lvl, $target)
}};
($lvl:expr) => {
$crate::log_enabled!(target: $crate::__private_api::module_path!(), $lvl)
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __log_key {
// key1 = 42
($($args:ident)*) => {
$crate::__private_api::stringify!($($args)*)
};
// "key1" = 42
($($args:expr)*) => {
$($args)*
};
}

View File

@ -1,400 +1,400 @@
#![cfg(feature = "serde")]
extern crate serde;
use self::serde::de::{
Deserialize, DeserializeSeed, Deserializer, EnumAccess, Error, Unexpected, VariantAccess,
Visitor,
};
use self::serde::ser::{Serialize, Serializer};
use {Level, LevelFilter, LOG_LEVEL_NAMES};
use std::fmt;
use std::str::{self, FromStr};
// The Deserialize impls are handwritten to be case insensitive using FromStr.
impl Serialize for Level {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match *self {
Level::Error => serializer.serialize_unit_variant("Level", 0, "ERROR"),
Level::Warn => serializer.serialize_unit_variant("Level", 1, "WARN"),
Level::Info => serializer.serialize_unit_variant("Level", 2, "INFO"),
Level::Debug => serializer.serialize_unit_variant("Level", 3, "DEBUG"),
Level::Trace => serializer.serialize_unit_variant("Level", 4, "TRACE"),
}
}
}
impl<'de> Deserialize<'de> for Level {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct LevelIdentifier;
impl<'de> Visitor<'de> for LevelIdentifier {
type Value = Level;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("log level")
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: Error,
{
// Case insensitive.
FromStr::from_str(s).map_err(|_| Error::unknown_variant(s, &LOG_LEVEL_NAMES[1..]))
}
fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
where
E: Error,
{
let variant = str::from_utf8(value)
.map_err(|_| Error::invalid_value(Unexpected::Bytes(value), &self))?;
self.visit_str(variant)
}
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
where
E: Error,
{
let variant = LOG_LEVEL_NAMES[1..]
.get(v as usize)
.ok_or_else(|| Error::invalid_value(Unexpected::Unsigned(v), &self))?;
self.visit_str(variant)
}
}
impl<'de> DeserializeSeed<'de> for LevelIdentifier {
type Value = Level;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_identifier(LevelIdentifier)
}
}
struct LevelEnum;
impl<'de> Visitor<'de> for LevelEnum {
type Value = Level;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("log level")
}
fn visit_enum<A>(self, value: A) -> Result<Self::Value, A::Error>
where
A: EnumAccess<'de>,
{
let (level, variant) = value.variant_seed(LevelIdentifier)?;
// Every variant is a unit variant.
variant.unit_variant()?;
Ok(level)
}
}
deserializer.deserialize_enum("Level", &LOG_LEVEL_NAMES[1..], LevelEnum)
}
}
impl Serialize for LevelFilter {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match *self {
LevelFilter::Off => serializer.serialize_unit_variant("LevelFilter", 0, "OFF"),
LevelFilter::Error => serializer.serialize_unit_variant("LevelFilter", 1, "ERROR"),
LevelFilter::Warn => serializer.serialize_unit_variant("LevelFilter", 2, "WARN"),
LevelFilter::Info => serializer.serialize_unit_variant("LevelFilter", 3, "INFO"),
LevelFilter::Debug => serializer.serialize_unit_variant("LevelFilter", 4, "DEBUG"),
LevelFilter::Trace => serializer.serialize_unit_variant("LevelFilter", 5, "TRACE"),
}
}
}
impl<'de> Deserialize<'de> for LevelFilter {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct LevelFilterIdentifier;
impl<'de> Visitor<'de> for LevelFilterIdentifier {
type Value = LevelFilter;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("log level filter")
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: Error,
{
// Case insensitive.
FromStr::from_str(s).map_err(|_| Error::unknown_variant(s, &LOG_LEVEL_NAMES))
}
fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
where
E: Error,
{
let variant = str::from_utf8(value)
.map_err(|_| Error::invalid_value(Unexpected::Bytes(value), &self))?;
self.visit_str(variant)
}
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
where
E: Error,
{
let variant = LOG_LEVEL_NAMES
.get(v as usize)
.ok_or_else(|| Error::invalid_value(Unexpected::Unsigned(v), &self))?;
self.visit_str(variant)
}
}
impl<'de> DeserializeSeed<'de> for LevelFilterIdentifier {
type Value = LevelFilter;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_identifier(LevelFilterIdentifier)
}
}
struct LevelFilterEnum;
impl<'de> Visitor<'de> for LevelFilterEnum {
type Value = LevelFilter;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("log level filter")
}
fn visit_enum<A>(self, value: A) -> Result<Self::Value, A::Error>
where
A: EnumAccess<'de>,
{
let (level_filter, variant) = value.variant_seed(LevelFilterIdentifier)?;
// Every variant is a unit variant.
variant.unit_variant()?;
Ok(level_filter)
}
}
deserializer.deserialize_enum("LevelFilter", &LOG_LEVEL_NAMES, LevelFilterEnum)
}
}
#[cfg(test)]
mod tests {
extern crate serde_test;
use self::serde_test::{assert_de_tokens, assert_de_tokens_error, assert_tokens, Token};
use {Level, LevelFilter};
fn level_token(variant: &'static str) -> Token {
Token::UnitVariant {
name: "Level",
variant: variant,
}
}
fn level_bytes_tokens(variant: &'static [u8]) -> [Token; 3] {
[
Token::Enum { name: "Level" },
Token::Bytes(variant),
Token::Unit,
]
}
fn level_variant_tokens(variant: u32) -> [Token; 3] {
[
Token::Enum { name: "Level" },
Token::U32(variant),
Token::Unit,
]
}
fn level_filter_token(variant: &'static str) -> Token {
Token::UnitVariant {
name: "LevelFilter",
variant: variant,
}
}
fn level_filter_bytes_tokens(variant: &'static [u8]) -> [Token; 3] {
[
Token::Enum {
name: "LevelFilter",
},
Token::Bytes(variant),
Token::Unit,
]
}
fn level_filter_variant_tokens(variant: u32) -> [Token; 3] {
[
Token::Enum {
name: "LevelFilter",
},
Token::U32(variant),
Token::Unit,
]
}
#[test]
fn test_level_ser_de() {
let cases = [
(Level::Error, [level_token("ERROR")]),
(Level::Warn, [level_token("WARN")]),
(Level::Info, [level_token("INFO")]),
(Level::Debug, [level_token("DEBUG")]),
(Level::Trace, [level_token("TRACE")]),
];
for &(s, expected) in &cases {
assert_tokens(&s, &expected);
}
}
#[test]
fn test_level_case_insensitive() {
let cases = [
(Level::Error, [level_token("error")]),
(Level::Warn, [level_token("warn")]),
(Level::Info, [level_token("info")]),
(Level::Debug, [level_token("debug")]),
(Level::Trace, [level_token("trace")]),
];
for &(s, expected) in &cases {
assert_de_tokens(&s, &expected);
}
}
#[test]
fn test_level_de_bytes() {
let cases = [
(Level::Error, level_bytes_tokens(b"ERROR")),
(Level::Warn, level_bytes_tokens(b"WARN")),
(Level::Info, level_bytes_tokens(b"INFO")),
(Level::Debug, level_bytes_tokens(b"DEBUG")),
(Level::Trace, level_bytes_tokens(b"TRACE")),
];
for &(value, tokens) in &cases {
assert_de_tokens(&value, &tokens);
}
}
#[test]
fn test_level_de_variant_index() {
let cases = [
(Level::Error, level_variant_tokens(0)),
(Level::Warn, level_variant_tokens(1)),
(Level::Info, level_variant_tokens(2)),
(Level::Debug, level_variant_tokens(3)),
(Level::Trace, level_variant_tokens(4)),
];
for &(value, tokens) in &cases {
assert_de_tokens(&value, &tokens);
}
}
#[test]
fn test_level_de_error() {
let msg = "unknown variant `errorx`, expected one of \
`ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`";
assert_de_tokens_error::<Level>(&[level_token("errorx")], msg);
}
#[test]
fn test_level_filter_ser_de() {
let cases = [
(LevelFilter::Off, [level_filter_token("OFF")]),
(LevelFilter::Error, [level_filter_token("ERROR")]),
(LevelFilter::Warn, [level_filter_token("WARN")]),
(LevelFilter::Info, [level_filter_token("INFO")]),
(LevelFilter::Debug, [level_filter_token("DEBUG")]),
(LevelFilter::Trace, [level_filter_token("TRACE")]),
];
for &(s, expected) in &cases {
assert_tokens(&s, &expected);
}
}
#[test]
fn test_level_filter_case_insensitive() {
let cases = [
(LevelFilter::Off, [level_filter_token("off")]),
(LevelFilter::Error, [level_filter_token("error")]),
(LevelFilter::Warn, [level_filter_token("warn")]),
(LevelFilter::Info, [level_filter_token("info")]),
(LevelFilter::Debug, [level_filter_token("debug")]),
(LevelFilter::Trace, [level_filter_token("trace")]),
];
for &(s, expected) in &cases {
assert_de_tokens(&s, &expected);
}
}
#[test]
fn test_level_filter_de_bytes() {
let cases = [
(LevelFilter::Off, level_filter_bytes_tokens(b"OFF")),
(LevelFilter::Error, level_filter_bytes_tokens(b"ERROR")),
(LevelFilter::Warn, level_filter_bytes_tokens(b"WARN")),
(LevelFilter::Info, level_filter_bytes_tokens(b"INFO")),
(LevelFilter::Debug, level_filter_bytes_tokens(b"DEBUG")),
(LevelFilter::Trace, level_filter_bytes_tokens(b"TRACE")),
];
for &(value, tokens) in &cases {
assert_de_tokens(&value, &tokens);
}
}
#[test]
fn test_level_filter_de_variant_index() {
let cases = [
(LevelFilter::Off, level_filter_variant_tokens(0)),
(LevelFilter::Error, level_filter_variant_tokens(1)),
(LevelFilter::Warn, level_filter_variant_tokens(2)),
(LevelFilter::Info, level_filter_variant_tokens(3)),
(LevelFilter::Debug, level_filter_variant_tokens(4)),
(LevelFilter::Trace, level_filter_variant_tokens(5)),
];
for &(value, tokens) in &cases {
assert_de_tokens(&value, &tokens);
}
}
#[test]
fn test_level_filter_de_error() {
let msg = "unknown variant `errorx`, expected one of \
`OFF`, `ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`";
assert_de_tokens_error::<LevelFilter>(&[level_filter_token("errorx")], msg);
}
}
#![cfg(feature = "serde")]
extern crate serde;
use self::serde::de::{
Deserialize, DeserializeSeed, Deserializer, EnumAccess, Error, Unexpected, VariantAccess,
Visitor,
};
use self::serde::ser::{Serialize, Serializer};
use {Level, LevelFilter, LOG_LEVEL_NAMES};
use std::fmt;
use std::str::{self, FromStr};
// The Deserialize impls are handwritten to be case insensitive using FromStr.
impl Serialize for Level {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match *self {
Level::Error => serializer.serialize_unit_variant("Level", 0, "ERROR"),
Level::Warn => serializer.serialize_unit_variant("Level", 1, "WARN"),
Level::Info => serializer.serialize_unit_variant("Level", 2, "INFO"),
Level::Debug => serializer.serialize_unit_variant("Level", 3, "DEBUG"),
Level::Trace => serializer.serialize_unit_variant("Level", 4, "TRACE"),
}
}
}
impl<'de> Deserialize<'de> for Level {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct LevelIdentifier;
impl<'de> Visitor<'de> for LevelIdentifier {
type Value = Level;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("log level")
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: Error,
{
// Case insensitive.
FromStr::from_str(s).map_err(|_| Error::unknown_variant(s, &LOG_LEVEL_NAMES[1..]))
}
fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
where
E: Error,
{
let variant = str::from_utf8(value)
.map_err(|_| Error::invalid_value(Unexpected::Bytes(value), &self))?;
self.visit_str(variant)
}
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
where
E: Error,
{
let variant = LOG_LEVEL_NAMES[1..]
.get(v as usize)
.ok_or_else(|| Error::invalid_value(Unexpected::Unsigned(v), &self))?;
self.visit_str(variant)
}
}
impl<'de> DeserializeSeed<'de> for LevelIdentifier {
type Value = Level;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_identifier(LevelIdentifier)
}
}
struct LevelEnum;
impl<'de> Visitor<'de> for LevelEnum {
type Value = Level;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("log level")
}
fn visit_enum<A>(self, value: A) -> Result<Self::Value, A::Error>
where
A: EnumAccess<'de>,
{
let (level, variant) = value.variant_seed(LevelIdentifier)?;
// Every variant is a unit variant.
variant.unit_variant()?;
Ok(level)
}
}
deserializer.deserialize_enum("Level", &LOG_LEVEL_NAMES[1..], LevelEnum)
}
}
impl Serialize for LevelFilter {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match *self {
LevelFilter::Off => serializer.serialize_unit_variant("LevelFilter", 0, "OFF"),
LevelFilter::Error => serializer.serialize_unit_variant("LevelFilter", 1, "ERROR"),
LevelFilter::Warn => serializer.serialize_unit_variant("LevelFilter", 2, "WARN"),
LevelFilter::Info => serializer.serialize_unit_variant("LevelFilter", 3, "INFO"),
LevelFilter::Debug => serializer.serialize_unit_variant("LevelFilter", 4, "DEBUG"),
LevelFilter::Trace => serializer.serialize_unit_variant("LevelFilter", 5, "TRACE"),
}
}
}
impl<'de> Deserialize<'de> for LevelFilter {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct LevelFilterIdentifier;
impl<'de> Visitor<'de> for LevelFilterIdentifier {
type Value = LevelFilter;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("log level filter")
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where
E: Error,
{
// Case insensitive.
FromStr::from_str(s).map_err(|_| Error::unknown_variant(s, &LOG_LEVEL_NAMES))
}
fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
where
E: Error,
{
let variant = str::from_utf8(value)
.map_err(|_| Error::invalid_value(Unexpected::Bytes(value), &self))?;
self.visit_str(variant)
}
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
where
E: Error,
{
let variant = LOG_LEVEL_NAMES
.get(v as usize)
.ok_or_else(|| Error::invalid_value(Unexpected::Unsigned(v), &self))?;
self.visit_str(variant)
}
}
impl<'de> DeserializeSeed<'de> for LevelFilterIdentifier {
type Value = LevelFilter;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_identifier(LevelFilterIdentifier)
}
}
struct LevelFilterEnum;
impl<'de> Visitor<'de> for LevelFilterEnum {
type Value = LevelFilter;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("log level filter")
}
fn visit_enum<A>(self, value: A) -> Result<Self::Value, A::Error>
where
A: EnumAccess<'de>,
{
let (level_filter, variant) = value.variant_seed(LevelFilterIdentifier)?;
// Every variant is a unit variant.
variant.unit_variant()?;
Ok(level_filter)
}
}
deserializer.deserialize_enum("LevelFilter", &LOG_LEVEL_NAMES, LevelFilterEnum)
}
}
#[cfg(test)]
mod tests {
extern crate serde_test;
use self::serde_test::{assert_de_tokens, assert_de_tokens_error, assert_tokens, Token};
use {Level, LevelFilter};
fn level_token(variant: &'static str) -> Token {
Token::UnitVariant {
name: "Level",
variant: variant,
}
}
fn level_bytes_tokens(variant: &'static [u8]) -> [Token; 3] {
[
Token::Enum { name: "Level" },
Token::Bytes(variant),
Token::Unit,
]
}
fn level_variant_tokens(variant: u32) -> [Token; 3] {
[
Token::Enum { name: "Level" },
Token::U32(variant),
Token::Unit,
]
}
fn level_filter_token(variant: &'static str) -> Token {
Token::UnitVariant {
name: "LevelFilter",
variant: variant,
}
}
fn level_filter_bytes_tokens(variant: &'static [u8]) -> [Token; 3] {
[
Token::Enum {
name: "LevelFilter",
},
Token::Bytes(variant),
Token::Unit,
]
}
fn level_filter_variant_tokens(variant: u32) -> [Token; 3] {
[
Token::Enum {
name: "LevelFilter",
},
Token::U32(variant),
Token::Unit,
]
}
#[test]
fn test_level_ser_de() {
let cases = [
(Level::Error, [level_token("ERROR")]),
(Level::Warn, [level_token("WARN")]),
(Level::Info, [level_token("INFO")]),
(Level::Debug, [level_token("DEBUG")]),
(Level::Trace, [level_token("TRACE")]),
];
for &(s, expected) in &cases {
assert_tokens(&s, &expected);
}
}
#[test]
fn test_level_case_insensitive() {
let cases = [
(Level::Error, [level_token("error")]),
(Level::Warn, [level_token("warn")]),
(Level::Info, [level_token("info")]),
(Level::Debug, [level_token("debug")]),
(Level::Trace, [level_token("trace")]),
];
for &(s, expected) in &cases {
assert_de_tokens(&s, &expected);
}
}
#[test]
fn test_level_de_bytes() {
let cases = [
(Level::Error, level_bytes_tokens(b"ERROR")),
(Level::Warn, level_bytes_tokens(b"WARN")),
(Level::Info, level_bytes_tokens(b"INFO")),
(Level::Debug, level_bytes_tokens(b"DEBUG")),
(Level::Trace, level_bytes_tokens(b"TRACE")),
];
for &(value, tokens) in &cases {
assert_de_tokens(&value, &tokens);
}
}
#[test]
fn test_level_de_variant_index() {
let cases = [
(Level::Error, level_variant_tokens(0)),
(Level::Warn, level_variant_tokens(1)),
(Level::Info, level_variant_tokens(2)),
(Level::Debug, level_variant_tokens(3)),
(Level::Trace, level_variant_tokens(4)),
];
for &(value, tokens) in &cases {
assert_de_tokens(&value, &tokens);
}
}
#[test]
fn test_level_de_error() {
let msg = "unknown variant `errorx`, expected one of \
`ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`";
assert_de_tokens_error::<Level>(&[level_token("errorx")], msg);
}
#[test]
fn test_level_filter_ser_de() {
let cases = [
(LevelFilter::Off, [level_filter_token("OFF")]),
(LevelFilter::Error, [level_filter_token("ERROR")]),
(LevelFilter::Warn, [level_filter_token("WARN")]),
(LevelFilter::Info, [level_filter_token("INFO")]),
(LevelFilter::Debug, [level_filter_token("DEBUG")]),
(LevelFilter::Trace, [level_filter_token("TRACE")]),
];
for &(s, expected) in &cases {
assert_tokens(&s, &expected);
}
}
#[test]
fn test_level_filter_case_insensitive() {
let cases = [
(LevelFilter::Off, [level_filter_token("off")]),
(LevelFilter::Error, [level_filter_token("error")]),
(LevelFilter::Warn, [level_filter_token("warn")]),
(LevelFilter::Info, [level_filter_token("info")]),
(LevelFilter::Debug, [level_filter_token("debug")]),
(LevelFilter::Trace, [level_filter_token("trace")]),
];
for &(s, expected) in &cases {
assert_de_tokens(&s, &expected);
}
}
#[test]
fn test_level_filter_de_bytes() {
let cases = [
(LevelFilter::Off, level_filter_bytes_tokens(b"OFF")),
(LevelFilter::Error, level_filter_bytes_tokens(b"ERROR")),
(LevelFilter::Warn, level_filter_bytes_tokens(b"WARN")),
(LevelFilter::Info, level_filter_bytes_tokens(b"INFO")),
(LevelFilter::Debug, level_filter_bytes_tokens(b"DEBUG")),
(LevelFilter::Trace, level_filter_bytes_tokens(b"TRACE")),
];
for &(value, tokens) in &cases {
assert_de_tokens(&value, &tokens);
}
}
#[test]
fn test_level_filter_de_variant_index() {
let cases = [
(LevelFilter::Off, level_filter_variant_tokens(0)),
(LevelFilter::Error, level_filter_variant_tokens(1)),
(LevelFilter::Warn, level_filter_variant_tokens(2)),
(LevelFilter::Info, level_filter_variant_tokens(3)),
(LevelFilter::Debug, level_filter_variant_tokens(4)),
(LevelFilter::Trace, level_filter_variant_tokens(5)),
];
for &(value, tokens) in &cases {
assert_de_tokens(&value, &tokens);
}
}
#[test]
fn test_level_filter_de_error() {
let msg = "unknown variant `errorx`, expected one of \
`OFF`, `ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`";
assert_de_tokens_error::<LevelFilter>(&[level_filter_token("errorx")], msg);
}
}

View File

@ -1 +1 @@
[assign]
[assign]

File diff suppressed because one or more lines are too long

256
third_party/rust/rkv/Cargo.lock generated vendored
View File

@ -4,9 +4,9 @@ version = 3
[[package]]
name = "arrayref"
version = "0.3.6"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545"
[[package]]
name = "autocfg"
@ -30,16 +30,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "byteorder"
version = "1.4.3"
name = "bitflags"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
dependencies = [
"serde",
]
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cc"
version = "1.0.76"
version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76a284da2e6fe2092f2353e51713435363112dfd60030e22add80be333fb928f"
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
dependencies = [
"libc",
]
[[package]]
name = "cfg-if"
@ -48,19 +60,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "fastrand"
version = "1.8.0"
name = "errno"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860"
dependencies = [
"instant",
"libc",
"windows-sys",
]
[[package]]
name = "form_urlencoded"
version = "1.1.0"
name = "fastrand"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
[[package]]
name = "form_urlencoded"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652"
dependencies = [
"percent-encoding",
]
@ -73,23 +92,14 @@ checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005"
[[package]]
name = "idna"
version = "0.3.0"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
dependencies = [
"unicode-bidi",
"unicode-normalization",
]
[[package]]
name = "instant"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
@ -98,9 +108,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.137"
version = "0.2.149"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b"
[[package]]
name = "linux-raw-sys"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f"
[[package]]
name = "lmdb-rkv"
@ -108,7 +124,7 @@ version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "447a296f7aca299cfbb50f4e4f3d49451549af655fb7215d7f8c0c3d64bad42b"
dependencies = [
"bitflags",
"bitflags 1.3.2",
"byteorder",
"libc",
"lmdb-rkv-sys",
@ -127,92 +143,80 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.17"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
[[package]]
name = "num-traits"
version = "0.2.15"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
dependencies = [
"autocfg",
]
[[package]]
name = "ordered-float"
version = "3.4.0"
version = "3.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d84eb1409416d254e4a9c8fa56cc24701755025b458f0fcd8e59e1f5f40c23bf"
checksum = "f1e1c390732d15f1d48471625cd92d154e66db2c56645e29a9cd26f4699f72dc"
dependencies = [
"num-traits",
]
[[package]]
name = "paste"
version = "1.0.9"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1"
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
[[package]]
name = "percent-encoding"
version = "2.2.0"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
[[package]]
name = "pkg-config"
version = "0.3.26"
version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
[[package]]
name = "proc-macro2"
version = "1.0.47"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.21"
version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
version = "0.2.16"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
dependencies = [
"bitflags",
]
[[package]]
name = "remove_dir_all"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
dependencies = [
"winapi",
"bitflags 1.3.2",
]
[[package]]
name = "rkv"
version = "0.18.4"
version = "0.19.0"
dependencies = [
"arrayref",
"bincode",
"bitflags",
"bitflags 2.4.1",
"byteorder",
"id-arena",
"lazy_static",
@ -229,19 +233,32 @@ dependencies = [
]
[[package]]
name = "serde"
version = "1.0.147"
name = "rustix"
version = "0.38.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3"
dependencies = [
"bitflags 2.4.1",
"errno",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]]
name = "serde"
version = "1.0.190"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.147"
version = "1.0.190"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852"
checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3"
dependencies = [
"proc-macro2",
"quote",
@ -250,9 +267,9 @@ dependencies = [
[[package]]
name = "syn"
version = "1.0.103"
version = "2.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d"
checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b"
dependencies = [
"proc-macro2",
"quote",
@ -261,32 +278,31 @@ dependencies = [
[[package]]
name = "tempfile"
version = "3.3.0"
version = "3.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5"
dependencies = [
"cfg-if",
"fastrand",
"libc",
"redox_syscall",
"remove_dir_all",
"winapi",
"rustix",
"windows-sys",
]
[[package]]
name = "thiserror"
version = "1.0.37"
version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e"
checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.37"
version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
dependencies = [
"proc-macro2",
"quote",
@ -304,21 +320,21 @@ dependencies = [
[[package]]
name = "tinyvec_macros"
version = "0.1.0"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "unicode-bidi"
version = "0.3.8"
version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
[[package]]
name = "unicode-ident"
version = "1.0.5"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-normalization"
@ -331,9 +347,9 @@ dependencies = [
[[package]]
name = "url"
version = "2.3.1"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5"
dependencies = [
"form_urlencoded",
"idna",
@ -342,28 +358,72 @@ dependencies = [
[[package]]
name = "uuid"
version = "1.2.2"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "422ee0de9031b5b948b97a8fc04e3aa35230001a722ddd27943e0be31564ce4c"
checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc"
[[package]]
name = "winapi"
version = "0.3.9"
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
"windows-targets",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"

View File

@ -11,9 +11,9 @@
[package]
edition = "2018"
rust-version = "1.58"
rust-version = "1.66"
name = "rkv"
version = "0.18.4"
version = "0.19.0"
authors = [
"Richard Newman <rnewman@twinql.com>",
"Nan Jiang <najiang@mozilla.com>",
@ -63,7 +63,8 @@ version = "0.3"
version = "1.0"
[dependencies.bitflags]
version = "1.2"
version = "2.4.1"
features = ["serde"]
[dependencies.byteorder]
version = "1"
@ -79,7 +80,7 @@ version = "0.14"
optional = true
[dependencies.log]
version = "0.4.4"
version = "0.4.20"
[dependencies.ordered-float]
version = "3.0.0"

0
third_party/rust/rkv/run-all-examples.sh vendored Executable file → Normal file
View File

View File

@ -42,3 +42,16 @@ pub enum WriteFlags {
APPEND,
APPEND_DUP,
}
/// Strategy to use when corrupted data is detected while opening a database.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum RecoveryStrategy {
/// Bubble up the error on detecting a corrupted data file. The default.
Error,
/// Discard the corrupted data and start with an empty database.
Discard,
/// Move the corrupted data file to `$file.corrupt` and start with an empty database.
Rename,
}

View File

@ -83,7 +83,7 @@ const MAGIC: [u8; 4] = [0xDE, 0xC0, 0xEF, 0xBE];
pub type MigrateResult<T> = Result<T, MigrateError>;
bitflags! {
#[derive(Default)]
#[derive(Default, PartialEq, Eq, Debug, Clone, Copy)]
struct PageFlags: u16 {
const BRANCH = 0x01;
const LEAF = 0x02;
@ -98,7 +98,7 @@ bitflags! {
}
bitflags! {
#[derive(Default)]
#[derive(Default, PartialEq, Eq, Debug, Clone, Copy)]
struct NodeFlags: u16 {
const BIGDATA = 0x01;
const SUBDATA = 0x02;

View File

@ -19,6 +19,7 @@ use super::{
DatabaseFlagsImpl, DatabaseImpl, EnvironmentFlagsImpl, ErrorImpl, InfoImpl, RoTransactionImpl,
RwTransactionImpl, StatImpl,
};
use crate::backend::common::RecoveryStrategy;
use crate::backend::traits::{
BackendEnvironment, BackendEnvironmentBuilder, BackendInfo, BackendIter, BackendRoCursor,
BackendRoCursorTransaction, BackendStat,
@ -86,7 +87,8 @@ impl<'b> BackendEnvironmentBuilder<'b> for EnvironmentBuilderImpl {
self
}
fn set_discard_if_corrupted(&mut self, _discard_if_corrupted: bool) -> &mut Self {
/// **UNIMPLEMENTED.** Will panic at runtime.
fn set_corruption_recovery_strategy(&mut self, _strategy: RecoveryStrategy) -> &mut Self {
// Unfortunately, when opening a database, LMDB doesn't handle all the ways it could have
// been corrupted. Prefer using the `SafeMode` backend if this is important.
unimplemented!();

View File

@ -24,9 +24,11 @@ use super::{
database::Database, DatabaseFlagsImpl, DatabaseImpl, EnvironmentFlagsImpl, ErrorImpl, InfoImpl,
RoTransactionImpl, RwTransactionImpl, StatImpl,
};
use crate::backend::common::RecoveryStrategy;
use crate::backend::traits::{BackendEnvironment, BackendEnvironmentBuilder};
const DEFAULT_DB_FILENAME: &str = "data.safe.bin";
const DEFAULT_CORRUPT_DB_EXTENSION: &str = "bin.corrupt";
type DatabaseArena = Arena<Database>;
type DatabaseNameMap = HashMap<Option<String>, DatabaseImpl>;
@ -38,7 +40,7 @@ pub struct EnvironmentBuilderImpl {
max_dbs: Option<usize>,
map_size: Option<usize>,
make_dir_if_needed: bool,
discard_if_corrupted: bool,
corruption_recovery_strategy: RecoveryStrategy,
}
impl<'b> BackendEnvironmentBuilder<'b> for EnvironmentBuilderImpl {
@ -53,7 +55,7 @@ impl<'b> BackendEnvironmentBuilder<'b> for EnvironmentBuilderImpl {
max_dbs: None,
map_size: None,
make_dir_if_needed: false,
discard_if_corrupted: false,
corruption_recovery_strategy: RecoveryStrategy::Error,
}
}
@ -85,8 +87,8 @@ impl<'b> BackendEnvironmentBuilder<'b> for EnvironmentBuilderImpl {
self
}
fn set_discard_if_corrupted(&mut self, discard_if_corrupted: bool) -> &mut Self {
self.discard_if_corrupted = discard_if_corrupted;
fn set_corruption_recovery_strategy(&mut self, strategy: RecoveryStrategy) -> &mut Self {
self.corruption_recovery_strategy = strategy;
self
}
@ -106,7 +108,7 @@ impl<'b> BackendEnvironmentBuilder<'b> for EnvironmentBuilderImpl {
self.max_dbs,
self.map_size,
)?;
env.read_from_disk(self.discard_if_corrupted)?;
env.read_from_disk(self.corruption_recovery_strategy)?;
Ok(env)
}
}
@ -152,16 +154,32 @@ impl EnvironmentImpl {
Ok(bincode::serialize(&data)?)
}
fn deserialize(
bytes: &[u8],
discard_if_corrupted: bool,
fn load(
path: &Path,
strategy: RecoveryStrategy,
) -> Result<(DatabaseArena, DatabaseNameMap), ErrorImpl> {
let bytes = fs::read(path)?;
match Self::deserialize(&bytes) {
Ok((arena, name_map)) => Ok((arena, name_map)),
Err(err) => match strategy {
RecoveryStrategy::Error => Err(err),
RecoveryStrategy::Discard => Ok((DatabaseArena::new(), HashMap::new())),
RecoveryStrategy::Rename => {
let corrupted_path = path.with_extension(DEFAULT_CORRUPT_DB_EXTENSION);
fs::rename(path, corrupted_path)?;
Ok((DatabaseArena::new(), HashMap::new()))
}
},
}
}
fn deserialize(bytes: &[u8]) -> Result<(DatabaseArena, DatabaseNameMap), ErrorImpl> {
let mut arena = DatabaseArena::new();
let mut name_map = HashMap::new();
let data: HashMap<_, _> = match bincode::deserialize(bytes) {
Err(_) if discard_if_corrupted => Ok(HashMap::new()),
result => result,
}?;
let data: HashMap<_, _> = bincode::deserialize(bytes)?;
for (name, db) in data {
name_map.insert(name, DatabaseImpl(arena.alloc(db)));
}
@ -199,7 +217,7 @@ impl EnvironmentImpl {
})
}
pub(crate) fn read_from_disk(&mut self, discard_if_corrupted: bool) -> Result<(), ErrorImpl> {
pub(crate) fn read_from_disk(&mut self, strategy: RecoveryStrategy) -> Result<(), ErrorImpl> {
let mut path = Cow::from(&self.path);
if fs::metadata(&path)?.is_dir() {
path.to_mut().push(DEFAULT_DB_FILENAME);
@ -207,7 +225,7 @@ impl EnvironmentImpl {
if fs::metadata(&path).is_err() {
return Ok(());
};
let (arena, name_map) = Self::deserialize(&fs::read(&path)?, discard_if_corrupted)?;
let (arena, name_map) = Self::load(&path, strategy)?;
self.dbs = RwLock::new(EnvironmentDbs { arena, name_map });
Ok(())
}
@ -272,7 +290,8 @@ impl<'e> BackendEnvironment<'e> for EnvironmentImpl {
// TOOD: don't reallocate `name`.
let key = name.map(String::from);
let mut dbs = self.dbs.write().map_err(|_| ErrorImpl::EnvPoisonError)?;
if dbs.name_map.keys().filter_map(|k| k.as_ref()).count() >= self.max_dbs && name.is_some() {
if dbs.name_map.keys().filter_map(|k| k.as_ref()).count() >= self.max_dbs && name.is_some()
{
return Err(ErrorImpl::DbsFull);
}
let parts = EnvironmentDbsRefMut::from(dbs.deref_mut());

View File

@ -17,7 +17,7 @@ use crate::backend::{
};
bitflags! {
#[derive(Default, Serialize, Deserialize)]
#[derive(Default, Serialize, Deserialize, PartialEq, Eq, Debug, Clone, Copy)]
pub struct EnvironmentFlagsImpl: u32 {
const NIL = 0b0000_0000;
}
@ -54,7 +54,7 @@ impl Into<EnvironmentFlagsImpl> for EnvironmentFlags {
}
bitflags! {
#[derive(Default, Serialize, Deserialize)]
#[derive(Default, Serialize, Deserialize, PartialEq, Eq, Debug, Clone, Copy)]
pub struct DatabaseFlagsImpl: u32 {
const NIL = 0b0000_0000;
#[cfg(feature = "db-dup-sort")]
@ -93,7 +93,7 @@ impl Into<DatabaseFlagsImpl> for DatabaseFlags {
}
bitflags! {
#[derive(Default, Serialize, Deserialize)]
#[derive(Default, Serialize, Deserialize, PartialEq, Eq, Debug, Clone, Copy)]
pub struct WriteFlagsImpl: u32 {
const NIL = 0b0000_0000;
}

View File

@ -14,7 +14,7 @@ use std::{
};
use crate::{
backend::common::{DatabaseFlags, EnvironmentFlags, WriteFlags},
backend::common::{DatabaseFlags, EnvironmentFlags, RecoveryStrategy, WriteFlags},
error::StoreError,
};
@ -83,7 +83,8 @@ pub trait BackendEnvironmentBuilder<'b>: Debug + Eq + PartialEq + Copy + Clone {
fn set_make_dir_if_needed(&mut self, make_dir_if_needed: bool) -> &mut Self;
fn set_discard_if_corrupted(&mut self, discard_if_corrupted: bool) -> &mut Self;
/// Set the corruption recovery strategy. See [`RecoveryStrategy`] for details.
fn set_corruption_recovery_strategy(&mut self, strategy: RecoveryStrategy) -> &mut Self;
fn open(&self, path: &Path) -> Result<Self::Environment, Self::Error>;
}

View File

@ -15,7 +15,7 @@ use tempfile::Builder;
#[cfg(feature = "lmdb")]
use rkv::backend::{Lmdb, LmdbEnvironment};
use rkv::{
backend::{BackendEnvironmentBuilder, SafeMode, SafeModeEnvironment},
backend::{BackendEnvironmentBuilder, RecoveryStrategy, SafeMode, SafeModeEnvironment},
CloseOptions, Rkv, StoreOptions, Value,
};
@ -247,7 +247,7 @@ fn test_safe_mode_corrupt_while_open_1() {
// But we can use a builder and pass `discard_if_corrupted` to deal with it.
let mut builder = Rkv::environment_builder::<SafeMode>();
builder.set_discard_if_corrupted(true);
builder.set_corruption_recovery_strategy(RecoveryStrategy::Discard);
manager
.get_or_create_from_builder(root.path(), builder, Rkv::from_builder::<SafeMode>)
.expect("created");
@ -378,3 +378,94 @@ fn test_safe_mode_corrupt_while_open_2() {
Some(Value::Str("byé, yöu"))
);
}
/// Test how the manager can discard corrupted databases, while moving the corrupted one aside for
/// later inspection.
#[test]
fn test_safe_mode_corrupt_while_open_3() {
type Manager = rkv::Manager<SafeModeEnvironment>;
let root = Builder::new()
.prefix("test_safe_mode_corrupt_while_open_3")
.tempdir()
.expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let mut safebin = root.path().to_path_buf();
safebin.push("data.safe.bin");
// Oops, corruption.
fs::write(&safebin, "bogus").expect("dbfile corrupted");
assert!(safebin.exists(), "Corrupted database file was written to");
// Create environment.
let mut manager = Manager::singleton().write().unwrap();
// Recreating environment fails.
manager
.get_or_create(root.path(), Rkv::new::<SafeMode>)
.expect_err("not created");
assert!(manager.get(root.path()).expect("success").is_none());
// But we can use a builder and pass `RecoveryStrategy::Rename` to deal with it.
let mut builder = Rkv::environment_builder::<SafeMode>();
builder.set_corruption_recovery_strategy(RecoveryStrategy::Rename);
manager
.get_or_create_from_builder(root.path(), builder, Rkv::from_builder::<SafeMode>)
.expect("created");
assert!(manager.get(root.path()).expect("success").is_some());
assert!(!safebin.exists(), "Database file was moved out of the way");
let mut corruptbin = root.path().to_path_buf();
corruptbin.push("data.safe.bin.corrupt");
assert!(corruptbin.exists(), "Corrupted database file exists");
let shared_env = manager
.get_or_create(root.path(), Rkv::new::<SafeMode>)
.expect("created");
let env = shared_env.read().unwrap();
// Writing still works.
let store = env
.open_single("store", StoreOptions::create())
.expect("opened");
let reader = env.read().expect("reader");
assert_eq!(store.get(&reader, "foo").expect("read"), None, "Nothing to be read");
// We can write.
let mut writer = env.write().expect("writer");
store
.put(&mut writer, "foo", &Value::I64(5678))
.expect("wrote");
writer.commit().expect("committed");
env.sync(true).expect("synced");
assert!(safebin.exists(), "Database file exists");
// Close everything.
drop(env);
drop(shared_env);
manager
.try_close(root.path(), CloseOptions::default())
.expect("closed without deleting");
assert!(manager.get(root.path()).expect("success").is_none());
// Recreate environment.
let shared_env = manager
.get_or_create(root.path(), Rkv::new::<SafeMode>)
.expect("created");
let env = shared_env.read().unwrap();
// Verify that the dbfile is not corrupted.
let store = env
.open_single("store", StoreOptions::default())
.expect("opened");
let reader = env.read().expect("reader");
assert_eq!(
store.get(&reader, "foo").expect("read"),
Some(Value::I64(5678)),
"Database contains expected value"
);
}

View File

@ -6,7 +6,7 @@ edition = "2018"
license = "MPL-2.0"
[dependencies]
glean = "56.1.0"
glean = "57.0.0"
log = "0.4"
nserror = { path = "../../../xpcom/rust/nserror" }
nsstring = { path = "../../../xpcom/rust/nsstring" }

View File

@ -9,7 +9,7 @@ license = "MPL-2.0"
[dependencies]
bincode = "1.0"
chrono = "0.4.10"
glean = "56.1.0"
glean = "57.0.0"
inherent = "1.0.0"
log = "0.4"
nsstring = { path = "../../../../xpcom/rust/nsstring", optional = true }

View File

@ -14,7 +14,7 @@ log = "0.4"
moz_task = { path = "../../../xpcom/rust/moz_task" }
nserror = { path = "../../../xpcom/rust/nserror" }
nsstring = { path = "../../../xpcom/rust/nsstring" }
rkv = { version = "0.18", default-features = false, features=["no-canonicalize-path"] }
rkv = { version = "0.19", default-features = false, features=["no-canonicalize-path"] }
storage_variant = { path = "../../../storage/variant" }
xpcom = { path = "../../../xpcom/rust/xpcom" }
tempfile = "3"

View File

@ -7,5 +7,5 @@ authors = ["fuzzing@mozilla.com"]
libc = "0.2"
tempfile = "3"
lazy_static = "1.4.0"
rkv = { version = "0.18", features = ["with-fuzzer-no-link"] }
rkv = { version = "0.19", features = ["with-fuzzer-no-link"] }
lmdb-rkv = { version = "0.14", features = ["with-fuzzer-no-link"] }