-
Notifications
You must be signed in to change notification settings - Fork 50
Split things into different files, to optimize future work #85
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
use std::ffi::CStr; | ||
use std::mem::MaybeUninit; | ||
use crate::LOGGING_TAG_MAX_LEN; | ||
|
||
// FIXME: When `maybe_uninit_uninit_array ` is stabilized, use it instead of this helper | ||
pub fn uninit_array<const N: usize, T>() -> [MaybeUninit<T>; N] { | ||
// SAFETY: Array contains MaybeUninit, which is fine to be uninit | ||
unsafe { MaybeUninit::uninit().assume_init() } | ||
} | ||
|
||
// FIXME: Remove when maybe_uninit_slice is stabilized to provide MaybeUninit::slice_assume_init_ref() | ||
pub unsafe fn slice_assume_init_ref<T>(slice: &[MaybeUninit<T>]) -> &[T] { | ||
&*(slice as *const [MaybeUninit<T>] as *const [T]) | ||
} | ||
|
||
/// Fills up `storage` with `tag` and a necessary NUL terminator, optionally ellipsizing the input | ||
/// `tag` if it's too large. | ||
/// | ||
/// Returns a [`CStr`] containing the initialized portion of `storage`, including its NUL | ||
/// terminator. | ||
pub fn fill_tag_bytes<'a>( | ||
storage: &'a mut [MaybeUninit<u8>; LOGGING_TAG_MAX_LEN + 1], | ||
tag: &[u8], | ||
) -> &'a CStr { | ||
// FIXME: Simplify when maybe_uninit_fill with MaybeUninit::fill_from() is stabilized | ||
let initialized = if tag.len() > LOGGING_TAG_MAX_LEN { | ||
for (input, output) in tag | ||
.iter() | ||
// Elipsize the last two characters (TODO: use special … character)? | ||
.take(LOGGING_TAG_MAX_LEN - 2) | ||
.chain(b"..\0") | ||
.zip(storage.iter_mut()) | ||
{ | ||
output.write(*input); | ||
} | ||
storage.as_slice() | ||
} else { | ||
for (input, output) in tag.iter().chain(b"\0").zip(storage.iter_mut()) { | ||
output.write(*input); | ||
} | ||
&storage[..tag.len() + 1] | ||
}; | ||
|
||
// SAFETY: The above code ensures that `initialized` only refers to a portion of the `array` | ||
// slice that was initialized, thus it is safe to cast those `MaybeUninit<u8>`s to `u8`: | ||
let initialized = unsafe { slice_assume_init_ref(initialized) }; | ||
CStr::from_bytes_with_nul(initialized).expect("Unreachable: we wrote a nul terminator") | ||
} | ||
Nercury marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
use std::ffi::CString; | ||
use std::fmt; | ||
use log::{Level, LevelFilter, Record}; | ||
use crate::{FormatFn, LogId}; | ||
|
||
/// Filter for android logger. | ||
#[derive(Default)] | ||
pub struct Config { | ||
pub(crate) log_level: Option<LevelFilter>, | ||
pub(crate) buf_id: Option<LogId>, | ||
filter: Option<env_filter::Filter>, | ||
pub(crate) tag: Option<CString>, | ||
pub(crate) custom_format: Option<FormatFn>, | ||
} | ||
|
||
impl fmt::Debug for Config { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
f.debug_struct("Config") | ||
.field("log_level", &self.log_level) | ||
.field("buf_id", &self.buf_id) | ||
.field("filter", &self.filter) | ||
.field("tag", &self.tag) | ||
.field( | ||
"custom_format", | ||
match &self.custom_format { | ||
Some(_) => &"Some(_)", | ||
None => &"None", | ||
}, | ||
) | ||
.finish() | ||
} | ||
} | ||
|
||
impl Config { | ||
/// Changes the maximum log level. | ||
/// | ||
/// Note, that `Trace` is the maximum level, because it provides the | ||
/// maximum amount of detail in the emitted logs. | ||
/// | ||
/// If `Off` level is provided, then nothing is logged at all. | ||
/// | ||
/// [`log::max_level()`] is considered as the default level. | ||
pub fn with_max_level(mut self, level: LevelFilter) -> Self { | ||
self.log_level = Some(level); | ||
self | ||
} | ||
|
||
/// Changes the Android logging system buffer to be used. | ||
/// | ||
/// By default, logs are sent to the [`Main`] log. Other logging buffers may | ||
/// only be accessible to certain processes. | ||
/// | ||
/// [`Main`]: LogId::Main | ||
pub fn with_log_buffer(mut self, buf_id: LogId) -> Self { | ||
self.buf_id = Some(buf_id); | ||
self | ||
} | ||
|
||
pub(crate) fn filter_matches(&self, record: &Record) -> bool { | ||
if let Some(ref filter) = self.filter { | ||
filter.matches(record) | ||
} else { | ||
true | ||
} | ||
} | ||
|
||
pub(crate) fn is_loggable(&self, level: Level) -> bool { | ||
// todo: consider __android_log_is_loggable. | ||
level <= self.log_level.unwrap_or_else(log::max_level) | ||
} | ||
|
||
pub fn with_filter(mut self, filter: env_filter::Filter) -> Self { | ||
self.filter = Some(filter); | ||
self | ||
} | ||
|
||
pub fn with_tag<S: Into<Vec<u8>>>(mut self, tag: S) -> Self { | ||
self.tag = Some(CString::new(tag).expect("Can't convert tag to CString")); | ||
self | ||
} | ||
|
||
/// Sets the format function for formatting the log output. | ||
/// ``` | ||
/// # use android_logger::Config; | ||
/// android_logger::init_once( | ||
/// Config::default() | ||
/// .with_max_level(log::LevelFilter::Trace) | ||
/// .format(|f, record| write!(f, "my_app: {}", record.args())) | ||
/// ) | ||
/// ``` | ||
pub fn format<F>(mut self, format: F) -> Self | ||
where | ||
F: Fn(&mut dyn fmt::Write, &Record) -> fmt::Result + Sync + Send + 'static, | ||
{ | ||
self.custom_format = Some(Box::new(format)); | ||
self | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/// Possible identifiers of a specific buffer of Android logging system for | ||
/// logging a message. | ||
#[derive(Clone, Copy, Debug, Eq, PartialEq)] | ||
pub enum LogId { | ||
/// Main log buffer. | ||
/// | ||
/// This is the only log buffer available to apps. | ||
Main, | ||
|
||
/// Radio log buffer. | ||
Radio, | ||
|
||
/// Event log buffer. | ||
Events, | ||
|
||
/// System log buffer. | ||
System, | ||
|
||
/// Crash log buffer. | ||
Crash, | ||
|
||
/// Kernel log buffer. | ||
Kernel, | ||
|
||
/// Security log buffer. | ||
Security, | ||
|
||
/// Statistics log buffer. | ||
Stats, | ||
} | ||
|
||
#[cfg(target_os = "android")] | ||
impl LogId { | ||
pub(crate) const fn to_native(log_id: Option<Self>) -> Option<log_ffi::log_id_t> { | ||
match log_id { | ||
Some(Self::Main) => Some(log_ffi::log_id_t::MAIN), | ||
Some(Self::Radio) => Some(log_ffi::log_id_t::RADIO), | ||
Some(Self::Events) => Some(log_ffi::log_id_t::EVENTS), | ||
Some(Self::System) => Some(log_ffi::log_id_t::SYSTEM), | ||
Some(Self::Crash) => Some(log_ffi::log_id_t::CRASH), | ||
Some(Self::Kernel) => Some(log_ffi::log_id_t::KERNEL), | ||
Some(Self::Security) => Some(log_ffi::log_id_t::SECURITY), | ||
Some(Self::Stats) => Some(log_ffi::log_id_t::STATS), | ||
None => None, | ||
} | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.