impl<const N: usize> std::fmt::Write for StaticCString<N> { fn write_str(&mutself, s: &str) -> std::fmt::Result { use std::convert::TryInto; let s = s.as_bytes(); let end = s.len().min(N.checked_sub(1).unwrap() - self.len);
debug_assert_eq!(s.len(), end, "message truncated"); unsafe {
std::ptr::copy_nonoverlapping(
s[..end].as_ptr(), self.buf
.as_mut_ptr()
.cast::<u8>()
.offset(self.len.try_into().unwrap()),
end,
)
}; self.len += end; self.buf[self.len].write(0);
Ok(())
}
}
/// Formats `$file:line: $msg\n` into an on-stack buffer of size `LOG_LIMIT`, /// then calls `log_callback` with a pointer to the formatted message. pubfn cubeb_log_internal_buf_fmt(
log_callback: unsafeextern"C"fn(*const c_char, ...),
file: &str,
line: u32,
msg: std::fmt::Arguments,
) { let filename = std::path::Path::new(file)
.file_name()
.unwrap()
.to_str()
.unwrap(); letmut buf = StaticCString::<LOG_LIMIT>::new(); let _ = std::fmt::write(&mut buf, format_args!("{filename}:{line}: {msg}\n")); unsafe { // Don't process this as a format string in C
log_callback(
CStr::from_bytes_with_nul_unchecked(b"%s\0").as_ptr(),
buf.as_cstr().as_ptr(),
);
};
}
#[cfg(test)] mod tests { usecrate::{set_logging, LogLevel}; externcrate regex; useself::regex::Regex; use std::sync::RwLock;
// Ensure that tests that modify the global log callback (e.g. to assert) // cannot run concurrently with others static LOG_MODIFIER: RwLock<()> = RwLock::new(());
#[test] fn test_normal_logging_sync() { let _guard = LOG_MODIFIER.read();
cubeb_log!("This is synchronous log output at normal level");
cubeb_log!("{} Formatted log", 1);
cubeb_log!("{} Formatted {} log {}", 1, 2, 3);
}
#[test] fn test_normal_logging_sync_format_specififer() { let _guard = LOG_MODIFIER.write();
set_logging(
LogLevel::Normal,
Some(|s| { let s = s.to_str().unwrap().trim();
println!("{}", s); let re = Regex::new(r"log.rs:\d+: This has a %s in it").unwrap();
assert!(re.is_match(s));
}),
)
.unwrap();
cubeb_log!("This has a %s in it");
set_logging(LogLevel::Disabled, None).unwrap();
}
#[test] fn test_normal_logging_inline() { let _guard = LOG_MODIFIER.write(); // log.rs:128: 1 log\n
set_logging(
LogLevel::Normal,
Some(|s| { let s = s.to_str().unwrap().trim();
println!("{}", s); let re = Regex::new(r"log.rs:\d+: 1 log").unwrap();
assert!(re.is_match(s));
}),
)
.unwrap(); let x = 1;
cubeb_log!("{x} log");
set_logging(LogLevel::Disabled, None).unwrap();
}
#[test] fn test_verbose_logging_sync() { let _guard = LOG_MODIFIER.read();
cubeb_logv!("This is synchronous log output at verbose level");
cubeb_logv!("{} Formatted log", 1);
cubeb_logv!("{} Formatted {} log {}", 1, 2, 3);
}
#[test] fn test_normal_logging_async() { let _guard = LOG_MODIFIER.read();
cubeb_alog!("This is asynchronous log output at normal level");
cubeb_alog!("{} Formatted log", 1);
cubeb_alog!("{} Formatted {} log {}", 1, 2, 3);
}
#[test] fn test_verbose_logging_async() { let _guard = LOG_MODIFIER.read();
cubeb_alogv!("This is asynchronous log output at verbose level");
cubeb_alogv!("{} Formatted log", 1);
cubeb_alogv!("{} Formatted {} log {}", 1, 2, 3);
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.