Fix vendored files.

This commit is contained in:
Adam Ierymenko 2022-06-08 12:16:09 -04:00
parent d5ca4e5f52
commit ef36acb970
No known key found for this signature in database
GPG Key ID: C8877CF2D7A5D7F3
20 changed files with 2248 additions and 178 deletions

2
.gitignore vendored
View File

@ -107,7 +107,6 @@ windows/ZeroTierOne/Debug/
*.swp *.swp
*~.nib *~.nib
DerivedData/ DerivedData/
build/
*.pbxuser *.pbxuser
*.mode1v3 *.mode1v3
*.mode2v3 *.mode2v3
@ -118,7 +117,6 @@ build/
!default.perspectivev3 !default.perspectivev3
*.xccheckout *.xccheckout
xcuserdata/ xcuserdata/
ext/librethinkdbxx/build
.vscode .vscode
__pycache__ __pycache__
*~ *~

4
zeroidc/Cargo.lock generated
View File

@ -1143,9 +1143,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
[[package]] [[package]]
name = "tracing" name = "tracing"
version = "0.1.34" version = "0.1.35"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09" checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"pin-project-lite", "pin-project-lite",

View File

@ -0,0 +1,88 @@
pub fn get(openssl_version: Option<u64>, libressl_version: Option<u64>) -> Vec<&'static str> {
let mut cfgs = vec![];
if let Some(libressl_version) = libressl_version {
cfgs.push("libressl");
if libressl_version >= 0x2_05_01_00_0 {
cfgs.push("libressl251");
}
if libressl_version >= 0x2_05_02_00_0 {
cfgs.push("libressl252");
}
if libressl_version >= 0x2_06_01_00_0 {
cfgs.push("libressl261");
}
if libressl_version >= 0x2_07_00_00_0 {
cfgs.push("libressl270");
}
if libressl_version >= 0x2_07_01_00_0 {
cfgs.push("libressl271");
}
if libressl_version >= 0x2_07_03_00_0 {
cfgs.push("libressl273");
}
if libressl_version >= 0x2_08_00_00_0 {
cfgs.push("libressl280");
}
if libressl_version >= 0x2_08_01_00_0 {
cfgs.push("libressl281");
}
if libressl_version >= 0x2_09_01_00_0 {
cfgs.push("libressl291");
}
if libressl_version >= 0x3_02_01_00_0 {
cfgs.push("libressl321");
}
if libressl_version >= 0x3_03_02_00_0 {
cfgs.push("libressl332");
}
if libressl_version >= 0x3_04_00_00_0 {
cfgs.push("libressl340");
}
if libressl_version >= 0x3_05_00_00_0 {
cfgs.push("libressl350");
}
} else {
let openssl_version = openssl_version.unwrap();
if openssl_version >= 0x3_00_00_00_0 {
cfgs.push("ossl300");
}
if openssl_version >= 0x1_00_01_00_0 {
cfgs.push("ossl101");
}
if openssl_version >= 0x1_00_02_00_0 {
cfgs.push("ossl102");
}
if openssl_version >= 0x1_00_02_06_0 {
cfgs.push("ossl102f");
}
if openssl_version >= 0x1_00_02_08_0 {
cfgs.push("ossl102h");
}
if openssl_version >= 0x1_01_00_00_0 {
cfgs.push("ossl110");
}
if openssl_version >= 0x1_01_00_06_0 {
cfgs.push("ossl110f");
}
if openssl_version >= 0x1_01_00_07_0 {
cfgs.push("ossl110g");
}
if openssl_version >= 0x1_01_00_08_0 {
cfgs.push("ossl110h");
}
if openssl_version >= 0x1_01_01_00_0 {
cfgs.push("ossl111");
}
if openssl_version >= 0x1_01_01_02_0 {
cfgs.push("ossl111b");
}
if openssl_version >= 0x1_01_01_03_0 {
cfgs.push("ossl111c");
}
}
cfgs
}

View File

@ -0,0 +1,104 @@
#include <openssl/opensslv.h>
#include <openssl/opensslconf.h>
#define VERSION2(n, v) RUST_VERSION_##n##_##v
#define VERSION(n, v) VERSION2(n, v)
#define NEW_VERSION2(a, b, c) RUST_VERSION_NEW_OPENSSL_##a##_##b##_##c
#define NEW_VERSION(a, b, c) NEW_VERSION2(a, b, c)
#ifdef LIBRESSL_VERSION_NUMBER
VERSION(LIBRESSL, LIBRESSL_VERSION_NUMBER)
#elif defined OPENSSL_VERSION_MAJOR
NEW_VERSION(OPENSSL_VERSION_MAJOR, OPENSSL_VERSION_MINOR, OPENSSL_VERSION_PATCH)
#else
VERSION(OPENSSL, OPENSSL_VERSION_NUMBER)
#endif
#ifdef OPENSSL_NO_BF
RUST_CONF_OPENSSL_NO_BF
#endif
#ifdef OPENSSL_NO_BUF_FREELISTS
RUST_CONF_OPENSSL_NO_BUF_FREELISTS
#endif
#ifdef OPENSSL_NO_CHACHA
RUST_CONF_OPENSSL_NO_CHACHA
#endif
#ifdef OPENSSL_NO_CMS
RUST_CONF_OPENSSL_NO_CMS
#endif
#ifdef OPENSSL_NO_COMP
RUST_CONF_OPENSSL_NO_COMP
#endif
#ifdef OPENSSL_NO_EC
RUST_CONF_OPENSSL_NO_EC
#endif
#ifdef OPENSSL_NO_EC2M
RUST_CONF_OPENSSL_NO_EC2M
#endif
#ifdef OPENSSL_NO_ENGINE
RUST_CONF_OPENSSL_NO_ENGINE
#endif
#ifdef OPENSSL_NO_KRB5
RUST_CONF_OPENSSL_NO_KRB5
#endif
#ifdef OPENSSL_NO_NEXTPROTONEG
RUST_CONF_OPENSSL_NO_NEXTPROTONEG
#endif
#ifdef OPENSSL_NO_OCSP
RUST_CONF_OPENSSL_NO_OCSP
#endif
#ifdef OPENSSL_NO_PSK
RUST_CONF_OPENSSL_NO_PSK
#endif
#ifdef OPENSSL_NO_RFC3779
RUST_CONF_OPENSSL_NO_RFC3779
#endif
#ifdef OPENSSL_NO_RMD160
RUST_CONF_OPENSSL_NO_RMD160
#endif
#ifdef OPENSSL_NO_SHA
RUST_CONF_OPENSSL_NO_SHA
#endif
#ifdef OPENSSL_NO_SRP
RUST_CONF_OPENSSL_NO_SRP
#endif
#ifdef OPENSSL_NO_SSL3_METHOD
RUST_CONF_OPENSSL_NO_SSL3_METHOD
#endif
#ifdef OPENSSL_NO_TLSEXT
RUST_CONF_OPENSSL_NO_TLSEXT
#endif
#ifdef OPENSSL_NO_STDIO
RUST_CONF_OPENSSL_NO_STDIO
#endif
#ifdef OPENSSL_NO_SM3
RUST_CONF_OPENSSL_NO_SM3
#endif
#ifdef OPENSSL_NO_DEPRECATED_3_0
RUST_CONF_OPENSSL_NO_DEPRECATED_3_0
#endif
#ifdef OPENSSL_NO_SEED
RUST_CONF_OPENSSL_NO_SEED
#endif

View File

@ -0,0 +1,276 @@
use pkg_config;
use std::ffi::OsString;
use std::path::{Path, PathBuf};
use std::process::{self, Command};
use super::env;
pub fn get_openssl(target: &str) -> (Vec<PathBuf>, PathBuf) {
let lib_dir = env("OPENSSL_LIB_DIR").map(PathBuf::from);
let include_dir = env("OPENSSL_INCLUDE_DIR").map(PathBuf::from);
match (lib_dir, include_dir) {
(Some(lib_dir), Some(include_dir)) => (vec![lib_dir], include_dir),
(lib_dir, include_dir) => {
let openssl_dir = env("OPENSSL_DIR").unwrap_or_else(|| find_openssl_dir(target));
let openssl_dir = Path::new(&openssl_dir);
let lib_dir = lib_dir.map(|d| vec![d]).unwrap_or_else(|| {
let mut lib_dirs = vec![];
// OpenSSL 3.0 now puts it's libraries in lib64/ by default,
// check for both it and lib/.
if openssl_dir.join("lib64").exists() {
lib_dirs.push(openssl_dir.join("lib64"));
}
if openssl_dir.join("lib").exists() {
lib_dirs.push(openssl_dir.join("lib"));
}
lib_dirs
});
let include_dir = include_dir.unwrap_or_else(|| openssl_dir.join("include"));
(lib_dir, include_dir)
}
}
}
fn resolve_with_wellknown_homebrew_location(dir: &str) -> Option<PathBuf> {
let versions = ["openssl@3", "openssl@1.1"];
// Check up default aarch 64 Homebrew installation location first
// for quick resolution if possible.
// `pkg-config` on brew doesn't necessarily contain settings for openssl apparently.
for version in &versions {
let homebrew = Path::new(dir).join(format!("opt/{}", version));
if homebrew.exists() {
return Some(homebrew);
}
}
for version in &versions {
// Calling `brew --prefix <package>` command usually slow and
// takes seconds, and will be used only as a last resort.
let output = execute_command_and_get_output("brew", &["--prefix", version]);
if let Some(ref output) = output {
let homebrew = Path::new(&output);
if homebrew.exists() {
return Some(homebrew.to_path_buf());
}
}
}
None
}
fn resolve_with_wellknown_location(dir: &str) -> Option<PathBuf> {
let root_dir = Path::new(dir);
let include_openssl = root_dir.join("include/openssl");
if include_openssl.exists() {
Some(root_dir.to_path_buf())
} else {
None
}
}
fn find_openssl_dir(target: &str) -> OsString {
let host = env::var("HOST").unwrap();
if host == target && target.ends_with("-apple-darwin") {
let homebrew_dir = match target {
"aarch64-apple-darwin" => "/opt/homebrew",
_ => "/usr/local",
};
if let Some(dir) = resolve_with_wellknown_homebrew_location(homebrew_dir) {
return dir.into();
} else if let Some(dir) = resolve_with_wellknown_location("/opt/pkg") {
// pkgsrc
return dir.into();
} else if let Some(dir) = resolve_with_wellknown_location("/opt/local") {
// MacPorts
return dir.into();
}
}
try_pkg_config();
try_vcpkg();
// FreeBSD ships with OpenSSL but doesn't include a pkg-config file :(
if host == target && target.contains("freebsd") {
return OsString::from("/usr");
}
// DragonFly has libressl (or openssl) in ports, but this doesn't include a pkg-config file
if host == target && target.contains("dragonfly") {
return OsString::from("/usr/local");
}
let mut msg = format!(
"
Could not find directory of OpenSSL installation, and this `-sys` crate cannot
proceed without this knowledge. If OpenSSL is installed and this crate had
trouble finding it, you can set the `OPENSSL_DIR` environment variable for the
compilation process.
Make sure you also have the development packages of openssl installed.
For example, `libssl-dev` on Ubuntu or `openssl-devel` on Fedora.
If you're in a situation where you think the directory *should* be found
automatically, please open a bug at https://github.com/sfackler/rust-openssl
and include information about your system as well as this message.
$HOST = {}
$TARGET = {}
openssl-sys = {}
",
host,
target,
env!("CARGO_PKG_VERSION")
);
if host.contains("apple-darwin") && target.contains("apple-darwin") {
let system = Path::new("/usr/lib/libssl.0.9.8.dylib");
if system.exists() {
msg.push_str(
"
openssl-sys crate build failed: no supported version of OpenSSL found.
Ways to fix it:
- Use the `vendored` feature of openssl-sys crate to build OpenSSL from source.
- Use Homebrew to install the `openssl` package.
",
);
}
}
if host.contains("unknown-linux")
&& target.contains("unknown-linux-gnu")
&& Command::new("pkg-config").output().is_err()
{
msg.push_str(
"
It looks like you're compiling on Linux and also targeting Linux. Currently this
requires the `pkg-config` utility to find OpenSSL but unfortunately `pkg-config`
could not be found. If you have OpenSSL installed you can likely fix this by
installing `pkg-config`.
",
);
}
if host.contains("windows") && target.contains("windows-gnu") {
msg.push_str(
"
It looks like you're compiling for MinGW but you may not have either OpenSSL or
pkg-config installed. You can install these two dependencies with:
pacman -S openssl-devel pkg-config
and try building this crate again.
",
);
}
if host.contains("windows") && target.contains("windows-msvc") {
msg.push_str(
"
It looks like you're compiling for MSVC but we couldn't detect an OpenSSL
installation. If there isn't one installed then you can try the rust-openssl
README for more information about how to download precompiled binaries of
OpenSSL:
https://github.com/sfackler/rust-openssl#windows
",
);
}
panic!("{}", msg);
}
/// Attempt to find OpenSSL through pkg-config.
///
/// Note that if this succeeds then the function does not return as pkg-config
/// typically tells us all the information that we need.
fn try_pkg_config() {
let target = env::var("TARGET").unwrap();
let host = env::var("HOST").unwrap();
// If we're going to windows-gnu we can use pkg-config, but only so long as
// we're coming from a windows host.
//
// Otherwise if we're going to windows we probably can't use pkg-config.
if target.contains("windows-gnu") && host.contains("windows") {
env::set_var("PKG_CONFIG_ALLOW_CROSS", "1");
} else if target.contains("windows") {
return;
}
let lib = match pkg_config::Config::new()
.print_system_libs(false)
.find("openssl")
{
Ok(lib) => lib,
Err(e) => {
println!("run pkg_config fail: {:?}", e);
return;
}
};
super::postprocess(&lib.include_paths);
for include in lib.include_paths.iter() {
println!("cargo:include={}", include.display());
}
process::exit(0);
}
/// Attempt to find OpenSSL through vcpkg.
///
/// Note that if this succeeds then the function does not return as vcpkg
/// should emit all of the cargo metadata that we need.
#[cfg(target_env = "msvc")]
fn try_vcpkg() {
// vcpkg will not emit any metadata if it can not find libraries
// appropriate for the target triple with the desired linkage.
let lib = match vcpkg::Config::new()
.emit_includes(true)
.find_package("openssl")
{
Ok(lib) => lib,
Err(e) => {
println!("note: vcpkg did not find openssl: {}", e);
return;
}
};
super::postprocess(&lib.include_paths);
println!("cargo:rustc-link-lib=user32");
println!("cargo:rustc-link-lib=gdi32");
println!("cargo:rustc-link-lib=crypt32");
process::exit(0);
}
#[cfg(not(target_env = "msvc"))]
fn try_vcpkg() {}
fn execute_command_and_get_output(cmd: &str, args: &[&str]) -> Option<String> {
let out = Command::new(cmd).args(args).output();
if let Ok(ref r1) = out {
if r1.status.success() {
let r2 = String::from_utf8(r1.stdout.clone());
if let Ok(r3) = r2 {
return Some(r3.trim().to_string());
}
}
}
None
}

View File

@ -0,0 +1,16 @@
use openssl_src;
use std::path::PathBuf;
pub fn get_openssl(_target: &str) -> (Vec<PathBuf>, PathBuf) {
let artifacts = openssl_src::Build::new().build();
println!("cargo:vendored=1");
println!(
"cargo:root={}",
artifacts.lib_dir().parent().unwrap().display()
);
(
vec![artifacts.lib_dir().to_path_buf()],
artifacts.include_dir().to_path_buf(),
)
}

399
zeroidc/vendor/openssl-sys/build/main.rs vendored Normal file
View File

@ -0,0 +1,399 @@
#![allow(clippy::inconsistent_digit_grouping, clippy::unusual_byte_groupings)]
extern crate autocfg;
#[cfg(feature = "bindgen")]
extern crate bindgen;
extern crate cc;
#[cfg(feature = "vendored")]
extern crate openssl_src;
extern crate pkg_config;
#[cfg(target_env = "msvc")]
extern crate vcpkg;
use std::collections::HashSet;
use std::env;
use std::ffi::OsString;
use std::path::{Path, PathBuf};
mod cfgs;
mod find_normal;
#[cfg(feature = "vendored")]
mod find_vendored;
#[cfg(feature = "bindgen")]
mod run_bindgen;
#[derive(PartialEq)]
enum Version {
Openssl3xx,
Openssl11x,
Openssl10x,
Libressl,
}
fn env_inner(name: &str) -> Option<OsString> {
let var = env::var_os(name);
println!("cargo:rerun-if-env-changed={}", name);
match var {
Some(ref v) => println!("{} = {}", name, v.to_string_lossy()),
None => println!("{} unset", name),
}
var
}
fn env(name: &str) -> Option<OsString> {
let prefix = env::var("TARGET").unwrap().to_uppercase().replace('-', "_");
let prefixed = format!("{}_{}", prefix, name);
env_inner(&prefixed).or_else(|| env_inner(name))
}
fn find_openssl(target: &str) -> (Vec<PathBuf>, PathBuf) {
#[cfg(feature = "vendored")]
{
// vendor if the feature is present, unless
// OPENSSL_NO_VENDOR exists and isn't `0`
if env("OPENSSL_NO_VENDOR").map_or(true, |s| s == "0") {
return find_vendored::get_openssl(target);
}
}
find_normal::get_openssl(target)
}
fn main() {
check_rustc_versions();
let target = env::var("TARGET").unwrap();
let (lib_dirs, include_dir) = find_openssl(&target);
if !lib_dirs.iter().all(|p| Path::new(p).exists()) {
panic!("OpenSSL library directory does not exist: {:?}", lib_dirs);
}
if !Path::new(&include_dir).exists() {
panic!(
"OpenSSL include directory does not exist: {}",
include_dir.to_string_lossy()
);
}
for lib_dir in lib_dirs.iter() {
println!(
"cargo:rustc-link-search=native={}",
lib_dir.to_string_lossy()
);
}
println!("cargo:include={}", include_dir.to_string_lossy());
let version = postprocess(&[include_dir]);
let libs_env = env("OPENSSL_LIBS");
let libs = match libs_env.as_ref().and_then(|s| s.to_str()) {
Some(v) => {
if v.is_empty() {
vec![]
} else {
v.split(':').collect()
}
}
None => match version {
Version::Openssl10x if target.contains("windows") => vec!["ssleay32", "libeay32"],
Version::Openssl3xx | Version::Openssl11x if target.contains("windows-msvc") => {
vec!["libssl", "libcrypto"]
}
_ => vec!["ssl", "crypto"],
},
};
let kind = determine_mode(&lib_dirs, &libs);
for lib in libs.into_iter() {
println!("cargo:rustc-link-lib={}={}", kind, lib);
}
// https://github.com/openssl/openssl/pull/15086
if version == Version::Openssl3xx
&& kind == "static"
&& (env::var("CARGO_CFG_TARGET_OS").unwrap() == "linux"
|| env::var("CARGO_CFG_TARGET_OS").unwrap() == "android")
&& env::var("CARGO_CFG_TARGET_POINTER_WIDTH").unwrap() == "32"
{
println!("cargo:rustc-link-lib=dylib=atomic");
}
if kind == "static" && target.contains("windows") {
println!("cargo:rustc-link-lib=dylib=gdi32");
println!("cargo:rustc-link-lib=dylib=user32");
println!("cargo:rustc-link-lib=dylib=crypt32");
println!("cargo:rustc-link-lib=dylib=ws2_32");
println!("cargo:rustc-link-lib=dylib=advapi32");
}
}
fn check_rustc_versions() {
let cfg = autocfg::new();
if cfg.probe_rustc_version(1, 31) {
println!("cargo:rustc-cfg=const_fn");
}
}
#[allow(clippy::let_and_return)]
fn postprocess(include_dirs: &[PathBuf]) -> Version {
let version = validate_headers(include_dirs);
#[cfg(feature = "bindgen")]
run_bindgen::run(&include_dirs);
version
}
/// Validates the header files found in `include_dir` and then returns the
/// version string of OpenSSL.
#[allow(clippy::manual_strip)] // we need to support pre-1.45.0
fn validate_headers(include_dirs: &[PathBuf]) -> Version {
// This `*-sys` crate only works with OpenSSL 1.0.1, 1.0.2, 1.1.0, 1.1.1 and 3.0.0.
// To correctly expose the right API from this crate, take a look at
// `opensslv.h` to see what version OpenSSL claims to be.
//
// OpenSSL has a number of build-time configuration options which affect
// various structs and such. Since OpenSSL 1.1.0 this isn't really a problem
// as the library is much more FFI-friendly, but 1.0.{1,2} suffer this problem.
//
// To handle all this conditional compilation we slurp up the configuration
// file of OpenSSL, `opensslconf.h`, and then dump out everything it defines
// as our own #[cfg] directives. That way the `ossl10x.rs` bindings can
// account for compile differences and such.
println!("cargo:rerun-if-changed=build/expando.c");
let mut gcc = cc::Build::new();
for include_dir in include_dirs {
gcc.include(include_dir);
}
let expanded = match gcc.file("build/expando.c").try_expand() {
Ok(expanded) => expanded,
Err(e) => {
panic!(
"
Header expansion error:
{:?}
Failed to find OpenSSL development headers.
You can try fixing this setting the `OPENSSL_DIR` environment variable
pointing to your OpenSSL installation or installing OpenSSL headers package
specific to your distribution:
# On Ubuntu
sudo apt-get install libssl-dev
# On Arch Linux
sudo pacman -S openssl
# On Fedora
sudo dnf install openssl-devel
# On Alpine Linux
apk add openssl-dev
See rust-openssl README for more information:
https://github.com/sfackler/rust-openssl#linux
",
e
);
}
};
let expanded = String::from_utf8(expanded).unwrap();
let mut enabled = vec![];
let mut openssl_version = None;
let mut libressl_version = None;
for line in expanded.lines() {
let line = line.trim();
let openssl_prefix = "RUST_VERSION_OPENSSL_";
let new_openssl_prefix = "RUST_VERSION_NEW_OPENSSL_";
let libressl_prefix = "RUST_VERSION_LIBRESSL_";
let conf_prefix = "RUST_CONF_";
if line.starts_with(openssl_prefix) {
let version = &line[openssl_prefix.len()..];
openssl_version = Some(parse_version(version));
} else if line.starts_with(new_openssl_prefix) {
let version = &line[new_openssl_prefix.len()..];
openssl_version = Some(parse_new_version(version));
} else if line.starts_with(libressl_prefix) {
let version = &line[libressl_prefix.len()..];
libressl_version = Some(parse_version(version));
} else if line.starts_with(conf_prefix) {
enabled.push(&line[conf_prefix.len()..]);
}
}
for enabled in &enabled {
println!("cargo:rustc-cfg=osslconf=\"{}\"", enabled);
}
println!("cargo:conf={}", enabled.join(","));
for cfg in cfgs::get(openssl_version, libressl_version) {
println!("cargo:rustc-cfg={}", cfg);
}
if let Some(libressl_version) = libressl_version {
println!("cargo:libressl_version_number={:x}", libressl_version);
let major = (libressl_version >> 28) as u8;
let minor = (libressl_version >> 20) as u8;
let fix = (libressl_version >> 12) as u8;
let (major, minor, fix) = match (major, minor, fix) {
(2, 5, 0) => ('2', '5', '0'),
(2, 5, 1) => ('2', '5', '1'),
(2, 5, 2) => ('2', '5', '2'),
(2, 5, _) => ('2', '5', 'x'),
(2, 6, 0) => ('2', '6', '0'),
(2, 6, 1) => ('2', '6', '1'),
(2, 6, 2) => ('2', '6', '2'),
(2, 6, _) => ('2', '6', 'x'),
(2, 7, _) => ('2', '7', 'x'),
(2, 8, 0) => ('2', '8', '0'),
(2, 8, 1) => ('2', '8', '1'),
(2, 8, _) => ('2', '8', 'x'),
(2, 9, 0) => ('2', '9', '0'),
(2, 9, _) => ('2', '9', 'x'),
(3, 0, 0) => ('3', '0', '0'),
(3, 0, 1) => ('3', '0', '1'),
(3, 0, _) => ('3', '0', 'x'),
(3, 1, 0) => ('3', '1', '0'),
(3, 1, _) => ('3', '1', 'x'),
(3, 2, 0) => ('3', '2', '0'),
(3, 2, 1) => ('3', '2', '1'),
(3, 2, _) => ('3', '2', 'x'),
(3, 3, 0) => ('3', '3', '0'),
(3, 3, 1) => ('3', '3', '1'),
(3, 3, _) => ('3', '3', 'x'),
(3, 4, 0) => ('3', '4', '0'),
(3, 4, _) => ('3', '4', 'x'),
(3, 5, _) => ('3', '5', 'x'),
_ => version_error(),
};
println!("cargo:libressl=true");
println!("cargo:libressl_version={}{}{}", major, minor, fix);
println!("cargo:version=101");
Version::Libressl
} else {
let openssl_version = openssl_version.unwrap();
println!("cargo:version_number={:x}", openssl_version);
if openssl_version >= 0x4_00_00_00_0 {
version_error()
} else if openssl_version >= 0x3_00_00_00_0 {
Version::Openssl3xx
} else if openssl_version >= 0x1_01_01_00_0 {
println!("cargo:version=111");
Version::Openssl11x
} else if openssl_version >= 0x1_01_00_06_0 {
println!("cargo:version=110");
println!("cargo:patch=f");
Version::Openssl11x
} else if openssl_version >= 0x1_01_00_00_0 {
println!("cargo:version=110");
Version::Openssl11x
} else if openssl_version >= 0x1_00_02_00_0 {
println!("cargo:version=102");
Version::Openssl10x
} else if openssl_version >= 0x1_00_01_00_0 {
println!("cargo:version=101");
Version::Openssl10x
} else {
version_error()
}
}
}
fn version_error() -> ! {
panic!(
"
This crate is only compatible with OpenSSL (version 1.0.1 through 1.1.1, or 3.0.0), or LibreSSL 2.5
through 3.5, but a different version of OpenSSL was found. The build is now aborting
due to this version mismatch.
"
);
}
// parses a string that looks like "0x100020cfL"
#[allow(deprecated)] // trim_right_matches is now trim_end_matches
#[allow(clippy::match_like_matches_macro)] // matches macro requires rust 1.42.0
fn parse_version(version: &str) -> u64 {
// cut off the 0x prefix
assert!(version.starts_with("0x"));
let version = &version[2..];
// and the type specifier suffix
let version = version.trim_right_matches(|c: char| match c {
'0'..='9' | 'a'..='f' | 'A'..='F' => false,
_ => true,
});
u64::from_str_radix(version, 16).unwrap()
}
// parses a string that looks like 3_0_0
fn parse_new_version(version: &str) -> u64 {
println!("version: {}", version);
let mut it = version.split('_');
let major = it.next().unwrap().parse::<u64>().unwrap();
let minor = it.next().unwrap().parse::<u64>().unwrap();
let patch = it.next().unwrap().parse::<u64>().unwrap();
(major << 28) | (minor << 20) | (patch << 4)
}
/// Given a libdir for OpenSSL (where artifacts are located) as well as the name
/// of the libraries we're linking to, figure out whether we should link them
/// statically or dynamically.
fn determine_mode(libdirs: &[PathBuf], libs: &[&str]) -> &'static str {
// First see if a mode was explicitly requested
let kind = env("OPENSSL_STATIC");
match kind.as_ref().and_then(|s| s.to_str()) {
Some("0") => return "dylib",
Some(_) => return "static",
None => {}
}
// Next, see what files we actually have to link against, and see what our
// possibilities even are.
let mut files = HashSet::new();
for dir in libdirs {
for path in dir
.read_dir()
.unwrap()
.map(|e| e.unwrap())
.map(|e| e.file_name())
.filter_map(|e| e.into_string().ok())
{
files.insert(path);
}
}
let can_static = libs
.iter()
.all(|l| files.contains(&format!("lib{}.a", l)) || files.contains(&format!("{}.lib", l)));
let can_dylib = libs.iter().all(|l| {
files.contains(&format!("lib{}.so", l))
|| files.contains(&format!("{}.dll", l))
|| files.contains(&format!("lib{}.dylib", l))
});
match (can_static, can_dylib) {
(true, false) => return "static",
(false, true) => return "dylib",
(false, false) => {
panic!(
"OpenSSL libdir at `{:?}` does not contain the required files \
to either statically or dynamically link OpenSSL",
libdirs
);
}
(true, true) => {}
}
// Ok, we've got not explicit preference and can *either* link statically or
// link dynamically. In the interest of "security upgrades" and/or "best
// practices with security libs", let's link dynamically.
"dylib"
}

View File

@ -0,0 +1,129 @@
use bindgen::callbacks::{MacroParsingBehavior, ParseCallbacks};
use bindgen::RustTarget;
use std::env;
use std::path::PathBuf;
const INCLUDES: &str = "
#include <openssl/aes.h>
#include <openssl/asn1.h>
#include <openssl/bio.h>
#include <openssl/comp.h>
#include <openssl/conf.h>
#include <openssl/crypto.h>
#include <openssl/dh.h>
#include <openssl/dsa.h>
#include <openssl/ec.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/objects.h>
#include <openssl/ocsp.h>
#include <openssl/opensslv.h>
#include <openssl/pem.h>
#include <openssl/pkcs12.h>
#include <openssl/pkcs7.h>
#include <openssl/rand.h>
#include <openssl/rsa.h>
#include <openssl/safestack.h>
#include <openssl/sha.h>
#include <openssl/ssl.h>
#include <openssl/stack.h>
#include <openssl/x509.h>
#include <openssl/x509_vfy.h>
#include <openssl/x509v3.h>
// this must be included after ssl.h for libressl!
#include <openssl/srtp.h>
#if !defined(LIBRESSL_VERSION_NUMBER)
#include <openssl/cms.h>
#endif
#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000
#include <openssl/kdf.h>
#endif
#if OPENSSL_VERSION_NUMBER >= 0x30000000
#include <openssl/provider.h>
#endif
";
pub fn run(include_dirs: &[PathBuf]) {
let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
let mut builder = bindgen::builder()
.parse_callbacks(Box::new(OpensslCallbacks))
.rust_target(RustTarget::Stable_1_47)
.ctypes_prefix("::libc")
.raw_line("use libc::*;")
.raw_line("type evp_pkey_st = EVP_PKEY;")
.allowlist_file(".*/openssl/[^/]+\\.h")
.allowlist_recursively(false)
// libc is missing pthread_once_t on macOS
.blocklist_type("CRYPTO_ONCE")
.blocklist_function("CRYPTO_THREAD_run_once")
// we don't want to mess with va_list
.blocklist_function("BIO_vprintf")
.blocklist_function("BIO_vsnprintf")
.blocklist_function("ERR_vset_error")
.blocklist_function("ERR_add_error_vdata")
.blocklist_function("EVP_KDF_vctrl")
.blocklist_type("OSSL_FUNC_core_vset_error_fn")
.blocklist_type("OSSL_FUNC_BIO_vprintf_fn")
.blocklist_type("OSSL_FUNC_BIO_vsnprintf_fn")
// Maintain compatibility for existing enum definitions
.rustified_enum("point_conversion_form_t")
// Maintain compatibility for pre-union definitions
.blocklist_type("GENERAL_NAME")
.blocklist_type("GENERAL_NAME_st")
.blocklist_type("EVP_PKEY")
.blocklist_type("evp_pkey_st")
.layout_tests(false)
.header_contents("includes.h", INCLUDES);
for include_dir in include_dirs {
builder = builder
.clang_arg("-I")
.clang_arg(include_dir.display().to_string());
}
builder
.generate()
.unwrap()
.write_to_file(out_dir.join("bindgen.rs"))
.unwrap();
}
#[derive(Debug)]
struct OpensslCallbacks;
impl ParseCallbacks for OpensslCallbacks {
// for now we'll continue hand-writing constants
fn will_parse_macro(&self, _name: &str) -> MacroParsingBehavior {
MacroParsingBehavior::Ignore
}
fn item_name(&self, original_item_name: &str) -> Option<String> {
match original_item_name {
// Our original definitions of these are wrong, so rename to avoid breakage
"CRYPTO_EX_new"
| "CRYPTO_EX_dup"
| "CRYPTO_EX_free"
| "BIO_meth_set_write"
| "BIO_meth_set_read"
| "BIO_meth_set_puts"
| "BIO_meth_set_ctrl"
| "BIO_meth_set_create"
| "BIO_meth_set_destroy"
| "CRYPTO_set_locking_callback"
| "CRYPTO_set_id_callback"
| "SSL_CTX_set_tmp_dh_callback"
| "SSL_set_tmp_dh_callback"
| "SSL_CTX_set_tmp_ecdh_callback"
| "SSL_set_tmp_ecdh_callback"
| "SSL_CTX_callback_ctrl"
| "SSL_CTX_set_alpn_select_cb" => Some(format!("{}__fixed_rust", original_item_name)),
_ => None,
}
}
}

View File

@ -1 +1 @@
{"files":{"CHANGELOG.md":"1d82f1ac1540d9606314c56d1701d10fff72688b0bf458398846fa837a6b8209","Cargo.toml":"c924c5dd3ad8b58b4d65ec40f10a44b5352f89145c419d82dab9c647b5d363f3","LICENSE":"898b1ae9821e98daf8964c8d6c7f61641f5f5aa78ad500020771c0939ee0dea1","README.md":"39a30e68fd06cd90cdf232fb87cba82168797c9861739e9529fee68e72c26868","benches/global_subscriber.rs":"271213baed0e02054e506c1ec9c47b58696c78aaa46f0969a147f4c369f80e3d","benches/no_subscriber.rs":"495c9a91fb972ec61ced31ef8e19d2cca02ec8ffae4e98e3316e55f6a0074578","benches/subscriber.rs":"c609be119ed6e4d3fb79df77f15aa14effbd3e2f77c627a49229a50091d3ee6a","src/dispatcher.rs":"5732b1f228328cd41e77b04a27faf3b6054a8ed5cd5034a0dad8e1e694ca3889","src/field.rs":"55c7a2798b9ad0269e7c738c3f15a5d0281bf34ac3a6196a3f0b15801e5278bd","src/instrument.rs":"1fe4de5c13b5ba048e9872d78d1fa4e85655f9f2ed10f79b72b5da881c9b8b45","src/level_filters.rs":"baae8e797897bae9cdd9ec64b8e9a3d71156e9c03261be17b5b18acba034e154","src/lib.rs":"c794108f5f37b5dc1609498afad5ebbb25ad5f80bf9e362c032a63d327429937","src/macros.rs":"1bf35f17cbb50fb92f60e5e60190faf5eeba03c328f754631fff6df183509491","src/span.rs":"e7c16999e8702bf1ff82aaa6803c81ac5b77ab96b754cac6e686acfc6adc14f9","src/stdlib.rs":"248514a9bae6106e436358aee44c92abf8e7f79022895c4a25136ddef211d198","src/subscriber.rs":"ae879c373be7ee4935f7b02a345f92ccbeb7879d61c5d37e3cc1277b3d51ddb2","tests/enabled.rs":"1333339aace87ea9d701f2f76a1985820cc513a75013a7ed89669f7a2c635479","tests/event.rs":"c4ec3ac338475e9e61675551eb99df1d8a7cbefb05a0d60203994f5c1df7c784","tests/filter_caching_is_lexically_scoped.rs":"5487a37db5fbdf3d57020ab1f01185d928c45d967d99d723ffc434540459d8dc","tests/filters_are_not_reevaluated_for_the_same_span.rs":"251abbc000dddd298448958a1f0e5be71da527ac6c1a368d57837c83a5467329","tests/filters_are_reevaluated_for_different_call_sites.rs":"e0fdd8e930c043674702831b4d96f331e63aba824576bbac50b3f53bb0241cc7","tests/filters_dont_leak.rs":"d594266818a3461886da33bfcc76937d89a433ed6980226fc428706b216c093c","tests/future_send.rs":"3e9c9193219d12e342c18bbedb2f6ec940334202feb3cffba91601d6001b8575","tests/macro_imports.rs":"d5de857162185d4a2384f3cb644bfcf76c7f5c1a3b5f72bfa0d2620ac6e3873c","tests/macros.rs":"fa83397181d73d2cae09c16d9647a63d1e3bad0f2dbc5b3280f69f3d0180c488","tests/macros_incompatible_concat.rs":"5f3bcbb65e4ae39db1cfc2def62fc913c20bab0fb769c8f731504e2615585ee5","tests/macros_redefined_core.rs":"a6eac60522f71fe6c9a040b8b869d596f7eb9e907f5b49f4be4413a40c387676","tests/max_level_hint.rs":"9b366591d947ca0202fa0bdf797e1bb14534d3c896cf8b9674660cd2807c32ef","tests/multiple_max_level_hints.rs":"4d9ef0de9cccc787da8f5e3f6c233ac9db42a2a99cfe5e39997e1f4aa9df0c00","tests/no_subscriber.rs":"2f8f2ada5089d8e2e503394dfe8206598a11895907c53bf940b892f1e6afdd2f","tests/scoped_clobbers_default.rs":"806480a74c15e4d68bb7576050662b1e53ee765fd583d003f8b349f17ea63a4b","tests/span.rs":"f84ead5b1dad9b91e5cec9d8378ab932a942936374ba928fb381e67fab52cda0","tests/subscriber.rs":"1617c098f4fa6abed174fe062111444c7b67fa0f377d2b342176998e572480e3"},"package":"5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09"} {"files":{"CHANGELOG.md":"7d5517e1ac705d5d8574915b59a37bbd0ba5aa6e663fc272b75e5792eca572a9","Cargo.toml":"f6290faffd0bf079845dbd6c3c1ddb6c728bcf7225e3b56a4ba5a9478dc72a8b","LICENSE":"898b1ae9821e98daf8964c8d6c7f61641f5f5aa78ad500020771c0939ee0dea1","README.md":"a83e1a8287e3eca752383ae849872707dddfbd07b918806cc7c027a0824872c6","benches/global_subscriber.rs":"271213baed0e02054e506c1ec9c47b58696c78aaa46f0969a147f4c369f80e3d","benches/no_subscriber.rs":"495c9a91fb972ec61ced31ef8e19d2cca02ec8ffae4e98e3316e55f6a0074578","benches/subscriber.rs":"c609be119ed6e4d3fb79df77f15aa14effbd3e2f77c627a49229a50091d3ee6a","src/dispatcher.rs":"a8158e1901c50dc83d2f15b1773e6b9e31985d9af65e460be52dbf8be6874cd2","src/field.rs":"55c7a2798b9ad0269e7c738c3f15a5d0281bf34ac3a6196a3f0b15801e5278bd","src/instrument.rs":"1fe4de5c13b5ba048e9872d78d1fa4e85655f9f2ed10f79b72b5da881c9b8b45","src/level_filters.rs":"baae8e797897bae9cdd9ec64b8e9a3d71156e9c03261be17b5b18acba034e154","src/lib.rs":"a8ab6b578f93b5fb833942fc59642e67caca8d343670d64fb52d47d5507a67e4","src/macros.rs":"f1a83930cea322f1f2000548d91800c22a9e28d2daf3f178c7c7c3ac8da5a02d","src/span.rs":"96b6c86be09c97b15b2ab5c607013abc5b388c2870eb648bee2cfc07837fa6e9","src/stdlib.rs":"248514a9bae6106e436358aee44c92abf8e7f79022895c4a25136ddef211d198","src/subscriber.rs":"ae879c373be7ee4935f7b02a345f92ccbeb7879d61c5d37e3cc1277b3d51ddb2","tests/enabled.rs":"1333339aace87ea9d701f2f76a1985820cc513a75013a7ed89669f7a2c635479","tests/event.rs":"c4ec3ac338475e9e61675551eb99df1d8a7cbefb05a0d60203994f5c1df7c784","tests/filter_caching_is_lexically_scoped.rs":"5487a37db5fbdf3d57020ab1f01185d928c45d967d99d723ffc434540459d8dc","tests/filters_are_not_reevaluated_for_the_same_span.rs":"251abbc000dddd298448958a1f0e5be71da527ac6c1a368d57837c83a5467329","tests/filters_are_reevaluated_for_different_call_sites.rs":"e0fdd8e930c043674702831b4d96f331e63aba824576bbac50b3f53bb0241cc7","tests/filters_dont_leak.rs":"d594266818a3461886da33bfcc76937d89a433ed6980226fc428706b216c093c","tests/future_send.rs":"3e9c9193219d12e342c18bbedb2f6ec940334202feb3cffba91601d6001b8575","tests/macro_imports.rs":"d5de857162185d4a2384f3cb644bfcf76c7f5c1a3b5f72bfa0d2620ac6e3873c","tests/macros.rs":"fa83397181d73d2cae09c16d9647a63d1e3bad0f2dbc5b3280f69f3d0180c488","tests/macros_incompatible_concat.rs":"5f3bcbb65e4ae39db1cfc2def62fc913c20bab0fb769c8f731504e2615585ee5","tests/macros_redefined_core.rs":"a6eac60522f71fe6c9a040b8b869d596f7eb9e907f5b49f4be4413a40c387676","tests/max_level_hint.rs":"9b366591d947ca0202fa0bdf797e1bb14534d3c896cf8b9674660cd2807c32ef","tests/multiple_max_level_hints.rs":"4d9ef0de9cccc787da8f5e3f6c233ac9db42a2a99cfe5e39997e1f4aa9df0c00","tests/no_subscriber.rs":"2f8f2ada5089d8e2e503394dfe8206598a11895907c53bf940b892f1e6afdd2f","tests/register_callsite_deadlock.rs":"c0b3142543e7a10065c7583a8ee0b6bc978ea4f3979599651101c5a28966e7c8","tests/scoped_clobbers_default.rs":"806480a74c15e4d68bb7576050662b1e53ee765fd583d003f8b349f17ea63a4b","tests/span.rs":"f84ead5b1dad9b91e5cec9d8378ab932a942936374ba928fb381e67fab52cda0","tests/subscriber.rs":"1617c098f4fa6abed174fe062111444c7b67fa0f377d2b342176998e572480e3"},"package":"a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160"}

View File

@ -1,3 +1,19 @@
# 0.1.35 (June 8, 2022)
This release reduces the overhead of callsite registration by using new
`tracing-core` APIs.
### Added
- Use `DefaultCallsite` to reduce callsite registration overhead ([#2083])
### Changed
- `tracing-core`: updated to [0.1.27][core-0.1.27]
[core-0.1.27]: https://github.com/tokio-rs/tracing/releases/tag/tracing-core-0.1.27
[#2088]: https://github.com/tokio-rs/tracing/pull/2083
# 0.1.34 (April 14, 2022) # 0.1.34 (April 14, 2022)
This release includes bug fixes for the "log" support feature and for the use of This release includes bug fixes for the "log" support feature and for the use of

View File

@ -13,7 +13,7 @@
edition = "2018" edition = "2018"
rust-version = "1.49.0" rust-version = "1.49.0"
name = "tracing" name = "tracing"
version = "0.1.34" version = "0.1.35"
authors = [ authors = [
"Eliza Weisman <eliza@buoyant.io>", "Eliza Weisman <eliza@buoyant.io>",
"Tokio Contributors <team@tokio.rs>", "Tokio Contributors <team@tokio.rs>",
@ -74,7 +74,7 @@ version = "0.1.20"
optional = true optional = true
[dependencies.tracing-core] [dependencies.tracing-core]
version = "0.1.22" version = "0.1.27"
default-features = false default-features = false
[dev-dependencies.criterion] [dev-dependencies.criterion]

View File

@ -16,9 +16,9 @@ Application-level tracing for Rust.
[Documentation][docs-url] | [Chat][discord-url] [Documentation][docs-url] | [Chat][discord-url]
[crates-badge]: https://img.shields.io/crates/v/tracing.svg [crates-badge]: https://img.shields.io/crates/v/tracing.svg
[crates-url]: https://crates.io/crates/tracing/0.1.34 [crates-url]: https://crates.io/crates/tracing/0.1.35
[docs-badge]: https://docs.rs/tracing/badge.svg [docs-badge]: https://docs.rs/tracing/badge.svg
[docs-url]: https://docs.rs/tracing/0.1.34 [docs-url]: https://docs.rs/tracing/0.1.35
[docs-master-badge]: https://img.shields.io/badge/docs-master-blue [docs-master-badge]: https://img.shields.io/badge/docs-master-blue
[docs-master-url]: https://tracing-rs.netlify.com/tracing [docs-master-url]: https://tracing-rs.netlify.com/tracing
[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg [mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
@ -250,7 +250,7 @@ my_future
is as long as the future's. is as long as the future's.
The second, and preferred, option is through the The second, and preferred, option is through the
[`#[instrument]`](https://docs.rs/tracing/0.1.34/tracing/attr.instrument.html) [`#[instrument]`](https://docs.rs/tracing/0.1.35/tracing/attr.instrument.html)
attribute: attribute:
```rust ```rust
@ -297,7 +297,7 @@ span.in_scope(|| {
// Dropping the span will close it, indicating that it has ended. // Dropping the span will close it, indicating that it has ended.
``` ```
The [`#[instrument]`](https://docs.rs/tracing/0.1.34/tracing/attr.instrument.html) attribute macro The [`#[instrument]`](https://docs.rs/tracing/0.1.35/tracing/attr.instrument.html) attribute macro
can reduce some of this boilerplate: can reduce some of this boilerplate:
```rust ```rust

View File

@ -123,10 +123,6 @@
//! instrumentation. //! instrumentation.
//! //!
//! [`Subscriber`]: crate::Subscriber //! [`Subscriber`]: crate::Subscriber
//! [`with_default`]: with_default
//! [`set_global_default`]: set_global_default
//! [`get_default`]: get_default
//! [`Dispatch`]: Dispatch
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))] #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
pub use tracing_core::dispatcher::set_default; pub use tracing_core::dispatcher::set_default;

View File

@ -119,8 +119,6 @@
//! tracing = "0.1" //! tracing = "0.1"
//! ``` //! ```
//! //!
//! *Compiler support: [requires `rustc` 1.42+][msrv]*
//!
//! ## Recording Spans and Events //! ## Recording Spans and Events
//! //!
//! Spans and events are recorded using macros. //! Spans and events are recorded using macros.
@ -437,9 +435,9 @@
//! [target]: Metadata::target //! [target]: Metadata::target
//! [parent span]: span::Attributes::parent //! [parent span]: span::Attributes::parent
//! [determined contextually]: span::Attributes::is_contextual //! [determined contextually]: span::Attributes::is_contextual
//! [`fmt::Debug`]: https://doc.rust-lang.org/std/fmt/trait.Debug.html //! [`fmt::Debug`]: std::fmt::Debug
//! [`fmt::Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html //! [`fmt::Display`]: std::fmt::Display
//! [fmt]: https://doc.rust-lang.org/std/fmt/#usage //! [fmt]: std::fmt#usage
//! [`Empty`]: field::Empty //! [`Empty`]: field::Empty
//! //!
//! ### Shorthand Macros //! ### Shorthand Macros
@ -466,7 +464,6 @@
//! [`info_span!`]: info_span! //! [`info_span!`]: info_span!
//! [`warn_span!`]: warn_span! //! [`warn_span!`]: warn_span!
//! [`error_span!`]: error_span! //! [`error_span!`]: error_span!
//! [`Level`]: Level
//! //!
//! ### For `log` Users //! ### For `log` Users
//! //!
@ -812,7 +809,7 @@
//! //!
//! ```toml //! ```toml
//! [dependencies] //! [dependencies]
//! tracing = { version = "0.1.34", default-features = false } //! tracing = { version = "0.1.35", default-features = false }
//! ``` //! ```
//! //!
//! <pre class="ignore" style="white-space:normal;font:inherit;"> //! <pre class="ignore" style="white-space:normal;font:inherit;">
@ -895,7 +892,7 @@
//! [flags]: #crate-feature-flags //! [flags]: #crate-feature-flags
#![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(docsrs, feature(doc_cfg), deny(rustdoc::broken_intra_doc_links))] #![cfg_attr(docsrs, feature(doc_cfg), deny(rustdoc::broken_intra_doc_links))]
#![doc(html_root_url = "https://docs.rs/tracing/0.1.34")] #![doc(html_root_url = "https://docs.rs/tracing/0.1.35")]
#![doc( #![doc(
html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png", html_logo_url = "https://raw.githubusercontent.com/tokio-rs/tracing/master/assets/logo-type.png",
issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/" issue_tracker_base_url = "https://github.com/tokio-rs/tracing/issues/"
@ -968,13 +965,8 @@ pub mod subscriber;
#[doc(hidden)] #[doc(hidden)]
pub mod __macro_support { pub mod __macro_support {
pub use crate::callsite::Callsite; pub use crate::callsite::Callsite;
use crate::stdlib::{
fmt,
sync::atomic::{AtomicUsize, Ordering},
};
use crate::{subscriber::Interest, Metadata}; use crate::{subscriber::Interest, Metadata};
pub use core::concat; pub use core::concat;
use tracing_core::Once;
/// Callsite implementation used by macro-generated code. /// Callsite implementation used by macro-generated code.
/// ///
@ -984,138 +976,70 @@ pub mod __macro_support {
/// by the `tracing` macros, but it is not part of the stable versioned API. /// by the `tracing` macros, but it is not part of the stable versioned API.
/// Breaking changes to this module may occur in small-numbered versions /// Breaking changes to this module may occur in small-numbered versions
/// without warning. /// without warning.
pub struct MacroCallsite { pub use tracing_core::callsite::DefaultCallsite as MacroCallsite;
interest: AtomicUsize,
meta: &'static Metadata<'static>, /// /!\ WARNING: This is *not* a stable API! /!\
registration: Once, /// This function, and all code contained in the `__macro_support` module, is
/// a *private* API of `tracing`. It is exposed publicly because it is used
/// by the `tracing` macros, but it is not part of the stable versioned API.
/// Breaking changes to this module may occur in small-numbered versions
/// without warning.
pub fn __is_enabled(meta: &Metadata<'static>, interest: Interest) -> bool {
interest.is_always() || crate::dispatcher::get_default(|default| default.enabled(meta))
} }
impl MacroCallsite { /// /!\ WARNING: This is *not* a stable API! /!\
/// Returns a new `MacroCallsite` with the specified `Metadata`. /// This function, and all code contained in the `__macro_support` module, is
/// /// a *private* API of `tracing`. It is exposed publicly because it is used
/// /!\ WARNING: This is *not* a stable API! /!\ /// by the `tracing` macros, but it is not part of the stable versioned API.
/// This method, and all code contained in the `__macro_support` module, is /// Breaking changes to this module may occur in small-numbered versions
/// a *private* API of `tracing`. It is exposed publicly because it is used /// without warning.
/// by the `tracing` macros, but it is not part of the stable versioned API. #[inline]
/// Breaking changes to this module may occur in small-numbered versions #[cfg(feature = "log")]
/// without warning. pub fn __disabled_span(meta: &'static Metadata<'static>) -> crate::Span {
pub const fn new(meta: &'static Metadata<'static>) -> Self { crate::Span::new_disabled(meta)
Self {
interest: AtomicUsize::new(0xDEAD),
meta,
registration: Once::new(),
}
}
/// Registers this callsite with the global callsite registry.
///
/// If the callsite is already registered, this does nothing.
///
/// /!\ WARNING: This is *not* a stable API! /!\
/// This method, and all code contained in the `__macro_support` module, is
/// a *private* API of `tracing`. It is exposed publicly because it is used
/// by the `tracing` macros, but it is not part of the stable versioned API.
/// Breaking changes to this module may occur in small-numbered versions
/// without warning.
#[inline(never)]
// This only happens once (or if the cached interest value was corrupted).
#[cold]
pub fn register(&'static self) -> Interest {
self.registration
.call_once(|| crate::callsite::register(self));
match self.interest.load(Ordering::Relaxed) {
0 => Interest::never(),
2 => Interest::always(),
_ => Interest::sometimes(),
}
}
/// Returns the callsite's cached Interest, or registers it for the
/// first time if it has not yet been registered.
///
/// /!\ WARNING: This is *not* a stable API! /!\
/// This method, and all code contained in the `__macro_support` module, is
/// a *private* API of `tracing`. It is exposed publicly because it is used
/// by the `tracing` macros, but it is not part of the stable versioned API.
/// Breaking changes to this module may occur in small-numbered versions
/// without warning.
#[inline]
pub fn interest(&'static self) -> Interest {
match self.interest.load(Ordering::Relaxed) {
0 => Interest::never(),
1 => Interest::sometimes(),
2 => Interest::always(),
_ => self.register(),
}
}
pub fn is_enabled(&self, interest: Interest) -> bool {
interest.is_always()
|| crate::dispatcher::get_default(|default| default.enabled(self.meta))
}
#[inline]
#[cfg(feature = "log")]
pub fn disabled_span(&self) -> crate::Span {
crate::Span::new_disabled(self.meta)
}
#[inline]
#[cfg(not(feature = "log"))]
pub fn disabled_span(&self) -> crate::Span {
crate::Span::none()
}
#[cfg(feature = "log")]
pub fn log(
&self,
logger: &'static dyn log::Log,
log_meta: log::Metadata<'_>,
values: &tracing_core::field::ValueSet<'_>,
) {
let meta = self.metadata();
logger.log(
&crate::log::Record::builder()
.file(meta.file())
.module_path(meta.module_path())
.line(meta.line())
.metadata(log_meta)
.args(format_args!(
"{}",
crate::log::LogValueSet {
values,
is_first: true
}
))
.build(),
);
}
} }
impl Callsite for MacroCallsite { /// /!\ WARNING: This is *not* a stable API! /!\
fn set_interest(&self, interest: Interest) { /// This function, and all code contained in the `__macro_support` module, is
let interest = match () { /// a *private* API of `tracing`. It is exposed publicly because it is used
_ if interest.is_never() => 0, /// by the `tracing` macros, but it is not part of the stable versioned API.
_ if interest.is_always() => 2, /// Breaking changes to this module may occur in small-numbered versions
_ => 1, /// without warning.
}; #[inline]
self.interest.store(interest, Ordering::SeqCst); #[cfg(not(feature = "log"))]
} pub fn __disabled_span(_: &'static Metadata<'static>) -> crate::Span {
crate::Span::none()
#[inline(always)]
fn metadata(&self) -> &Metadata<'static> {
self.meta
}
} }
impl fmt::Debug for MacroCallsite { /// /!\ WARNING: This is *not* a stable API! /!\
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// This function, and all code contained in the `__macro_support` module, is
f.debug_struct("MacroCallsite") /// a *private* API of `tracing`. It is exposed publicly because it is used
.field("interest", &self.interest) /// by the `tracing` macros, but it is not part of the stable versioned API.
.field("meta", &self.meta) /// Breaking changes to this module may occur in small-numbered versions
.field("registration", &self.registration) /// without warning.
.finish() #[cfg(feature = "log")]
} pub fn __tracing_log(
meta: &Metadata<'static>,
logger: &'static dyn log::Log,
log_meta: log::Metadata<'_>,
values: &tracing_core::field::ValueSet<'_>,
) {
logger.log(
&crate::log::Record::builder()
.file(meta.file())
.module_path(meta.module_path())
.line(meta.line())
.metadata(log_meta)
.args(format_args!(
"{}",
crate::log::LogValueSet {
values,
is_first: true
}
))
.build(),
);
} }
} }

View File

@ -24,7 +24,7 @@ macro_rules! span {
(target: $target:expr, parent: $parent:expr, $lvl:expr, $name:expr, $($fields:tt)*) => { (target: $target:expr, parent: $parent:expr, $lvl:expr, $name:expr, $($fields:tt)*) => {
{ {
use $crate::__macro_support::Callsite as _; use $crate::__macro_support::Callsite as _;
static CALLSITE: $crate::__macro_support::MacroCallsite = $crate::callsite2! { static CALLSITE: $crate::callsite::DefaultCallsite = $crate::callsite2! {
name: $name, name: $name,
kind: $crate::metadata::Kind::SPAN, kind: $crate::metadata::Kind::SPAN,
target: $target, target: $target,
@ -34,7 +34,7 @@ macro_rules! span {
let mut interest = $crate::subscriber::Interest::never(); let mut interest = $crate::subscriber::Interest::never();
if $crate::level_enabled!($lvl) if $crate::level_enabled!($lvl)
&& { interest = CALLSITE.interest(); !interest.is_never() } && { interest = CALLSITE.interest(); !interest.is_never() }
&& CALLSITE.is_enabled(interest) && $crate::__macro_support::__is_enabled(CALLSITE.metadata(), interest)
{ {
let meta = CALLSITE.metadata(); let meta = CALLSITE.metadata();
// span with explicit parent // span with explicit parent
@ -44,7 +44,7 @@ macro_rules! span {
&$crate::valueset!(meta.fields(), $($fields)*), &$crate::valueset!(meta.fields(), $($fields)*),
) )
} else { } else {
let span = CALLSITE.disabled_span(); let span = $crate::__macro_support::__disabled_span(CALLSITE.metadata());
$crate::if_log_enabled! { $lvl, { $crate::if_log_enabled! { $lvl, {
span.record_all(&$crate::valueset!(CALLSITE.metadata().fields(), $($fields)*)); span.record_all(&$crate::valueset!(CALLSITE.metadata().fields(), $($fields)*));
}}; }};
@ -55,7 +55,7 @@ macro_rules! span {
(target: $target:expr, $lvl:expr, $name:expr, $($fields:tt)*) => { (target: $target:expr, $lvl:expr, $name:expr, $($fields:tt)*) => {
{ {
use $crate::__macro_support::Callsite as _; use $crate::__macro_support::Callsite as _;
static CALLSITE: $crate::__macro_support::MacroCallsite = $crate::callsite2! { static CALLSITE: $crate::callsite::DefaultCallsite = $crate::callsite2! {
name: $name, name: $name,
kind: $crate::metadata::Kind::SPAN, kind: $crate::metadata::Kind::SPAN,
target: $target, target: $target,
@ -65,7 +65,7 @@ macro_rules! span {
let mut interest = $crate::subscriber::Interest::never(); let mut interest = $crate::subscriber::Interest::never();
if $crate::level_enabled!($lvl) if $crate::level_enabled!($lvl)
&& { interest = CALLSITE.interest(); !interest.is_never() } && { interest = CALLSITE.interest(); !interest.is_never() }
&& CALLSITE.is_enabled(interest) && $crate::__macro_support::__is_enabled(CALLSITE.metadata(), interest)
{ {
let meta = CALLSITE.metadata(); let meta = CALLSITE.metadata();
// span with contextual parent // span with contextual parent
@ -74,7 +74,7 @@ macro_rules! span {
&$crate::valueset!(meta.fields(), $($fields)*), &$crate::valueset!(meta.fields(), $($fields)*),
) )
} else { } else {
let span = CALLSITE.disabled_span(); let span = $crate::__macro_support::__disabled_span(CALLSITE.metadata());
$crate::if_log_enabled! { $lvl, { $crate::if_log_enabled! { $lvl, {
span.record_all(&$crate::valueset!(CALLSITE.metadata().fields(), $($fields)*)); span.record_all(&$crate::valueset!(CALLSITE.metadata().fields(), $($fields)*));
}}; }};
@ -584,7 +584,7 @@ macro_rules! error_span {
macro_rules! event { macro_rules! event {
(target: $target:expr, parent: $parent:expr, $lvl:expr, { $($fields:tt)* } )=> ({ (target: $target:expr, parent: $parent:expr, $lvl:expr, { $($fields:tt)* } )=> ({
use $crate::__macro_support::Callsite as _; use $crate::__macro_support::Callsite as _;
static CALLSITE: $crate::__macro_support::MacroCallsite = $crate::callsite2! { static CALLSITE: $crate::callsite::DefaultCallsite = $crate::callsite2! {
name: $crate::__macro_support::concat!( name: $crate::__macro_support::concat!(
"event ", "event ",
file!(), file!(),
@ -599,7 +599,7 @@ macro_rules! event {
let enabled = $crate::level_enabled!($lvl) && { let enabled = $crate::level_enabled!($lvl) && {
let interest = CALLSITE.interest(); let interest = CALLSITE.interest();
!interest.is_never() && CALLSITE.is_enabled(interest) !interest.is_never() && $crate::__macro_support::__is_enabled(CALLSITE.metadata(), interest)
}; };
if enabled { if enabled {
(|value_set: $crate::field::ValueSet| { (|value_set: $crate::field::ValueSet| {
@ -641,7 +641,7 @@ macro_rules! event {
); );
(target: $target:expr, $lvl:expr, { $($fields:tt)* } )=> ({ (target: $target:expr, $lvl:expr, { $($fields:tt)* } )=> ({
use $crate::__macro_support::Callsite as _; use $crate::__macro_support::Callsite as _;
static CALLSITE: $crate::__macro_support::MacroCallsite = $crate::callsite2! { static CALLSITE: $crate::callsite::DefaultCallsite = $crate::callsite2! {
name: $crate::__macro_support::concat!( name: $crate::__macro_support::concat!(
"event ", "event ",
file!(), file!(),
@ -655,7 +655,7 @@ macro_rules! event {
}; };
let enabled = $crate::level_enabled!($lvl) && { let enabled = $crate::level_enabled!($lvl) && {
let interest = CALLSITE.interest(); let interest = CALLSITE.interest();
!interest.is_never() && CALLSITE.is_enabled(interest) !interest.is_never() && $crate::__macro_support::__is_enabled(CALLSITE.metadata(), interest)
}; };
if enabled { if enabled {
(|value_set: $crate::field::ValueSet| { (|value_set: $crate::field::ValueSet| {
@ -832,6 +832,8 @@ macro_rules! event {
/// } /// }
/// ``` /// ```
/// ///
/// [`enabled!`]: crate::enabled
/// [`span_enabled!`]: crate::span_enabled
#[macro_export] #[macro_export]
macro_rules! event_enabled { macro_rules! event_enabled {
($($rest:tt)*)=> ( ($($rest:tt)*)=> (
@ -864,6 +866,8 @@ macro_rules! event_enabled {
/// } /// }
/// ``` /// ```
/// ///
/// [`enabled!`]: crate::enabled
/// [`span_enabled!`]: crate::span_enabled
#[macro_export] #[macro_export]
macro_rules! span_enabled { macro_rules! span_enabled {
($($rest:tt)*)=> ( ($($rest:tt)*)=> (
@ -959,13 +963,14 @@ macro_rules! span_enabled {
/// [`Metadata`]: crate::Metadata /// [`Metadata`]: crate::Metadata
/// [`is_event`]: crate::Metadata::is_event /// [`is_event`]: crate::Metadata::is_event
/// [`is_span`]: crate::Metadata::is_span /// [`is_span`]: crate::Metadata::is_span
/// /// [`enabled!`]: crate::enabled
/// [`span_enabled!`]: crate::span_enabled
#[macro_export] #[macro_export]
macro_rules! enabled { macro_rules! enabled {
(kind: $kind:expr, target: $target:expr, $lvl:expr, { $($fields:tt)* } )=> ({ (kind: $kind:expr, target: $target:expr, $lvl:expr, { $($fields:tt)* } )=> ({
if $crate::level_enabled!($lvl) { if $crate::level_enabled!($lvl) {
use $crate::__macro_support::Callsite as _; use $crate::__macro_support::Callsite as _;
static CALLSITE: $crate::__macro_support::MacroCallsite = $crate::callsite2! { static CALLSITE: $crate::callsite::DefaultCallsite = $crate::callsite2! {
name: $crate::__macro_support::concat!( name: $crate::__macro_support::concat!(
"enabled ", "enabled ",
file!(), file!(),
@ -978,7 +983,7 @@ macro_rules! enabled {
fields: $($fields)* fields: $($fields)*
}; };
let interest = CALLSITE.interest(); let interest = CALLSITE.interest();
if !interest.is_never() && CALLSITE.is_enabled(interest) { if !interest.is_never() && $crate::__macro_support::__is_enabled(CALLSITE.metadata(), interest) {
let meta = CALLSITE.metadata(); let meta = CALLSITE.metadata();
$crate::dispatcher::get_default(|current| current.enabled(meta)) $crate::dispatcher::get_default(|current| current.enabled(meta))
} else { } else {
@ -2096,7 +2101,6 @@ macro_rules! callsite {
level: $lvl:expr, level: $lvl:expr,
fields: $($fields:tt)* fields: $($fields:tt)*
) => {{ ) => {{
use $crate::__macro_support::MacroCallsite;
static META: $crate::Metadata<'static> = { static META: $crate::Metadata<'static> = {
$crate::metadata! { $crate::metadata! {
name: $name, name: $name,
@ -2107,7 +2111,7 @@ macro_rules! callsite {
kind: $kind, kind: $kind,
} }
}; };
static CALLSITE: MacroCallsite = MacroCallsite::new(&META); static CALLSITE: $crate::callsite::DefaultCallsite = $crate::callsite::DefaultCallsite::new(&META);
CALLSITE.register(); CALLSITE.register();
&CALLSITE &CALLSITE
}}; }};
@ -2147,7 +2151,6 @@ macro_rules! callsite2 {
level: $lvl:expr, level: $lvl:expr,
fields: $($fields:tt)* fields: $($fields:tt)*
) => {{ ) => {{
use $crate::__macro_support::MacroCallsite;
static META: $crate::Metadata<'static> = { static META: $crate::Metadata<'static> = {
$crate::metadata! { $crate::metadata! {
name: $name, name: $name,
@ -2158,7 +2161,7 @@ macro_rules! callsite2 {
kind: $kind, kind: $kind,
} }
}; };
MacroCallsite::new(&META) $crate::callsite::DefaultCallsite::new(&META)
}}; }};
} }
@ -2428,13 +2431,14 @@ macro_rules! __tracing_log {
use $crate::log; use $crate::log;
let level = $crate::level_to_log!($level); let level = $crate::level_to_log!($level);
if level <= log::max_level() { if level <= log::max_level() {
let meta = $callsite.metadata();
let log_meta = log::Metadata::builder() let log_meta = log::Metadata::builder()
.level(level) .level(level)
.target(CALLSITE.metadata().target()) .target(meta.target())
.build(); .build();
let logger = log::logger(); let logger = log::logger();
if logger.enabled(&log_meta) { if logger.enabled(&log_meta) {
$callsite.log(logger, log_meta, $value_set) $crate::__macro_support::__tracing_log(meta, logger, log_meta, $value_set)
} }
} }
}} }}

View File

@ -718,8 +718,8 @@ impl Span {
/// ``` /// ```
/// ///
/// [syntax]: https://rust-lang.github.io/async-book/01_getting_started/04_async_await_primer.html /// [syntax]: https://rust-lang.github.io/async-book/01_getting_started/04_async_await_primer.html
/// [`Span::in_scope`]: #method.in_scope /// [`Span::in_scope`]: Span::in_scope()
/// [instrument]: https://docs.rs/tracing/latest/tracing/trait.Instrument.html /// [instrument]: crate::Instrument
/// [attr]: macro@crate::instrument /// [attr]: macro@crate::instrument
/// ///
/// # Examples /// # Examples
@ -1239,7 +1239,7 @@ impl Span {
/// ///
/// See also [`is_none`]. /// See also [`is_none`].
/// ///
/// [`is_none`]: #method.is_none /// [`is_none`]: Span::is_none()
#[inline] #[inline]
pub fn is_disabled(&self) -> bool { pub fn is_disabled(&self) -> bool {
self.inner.is_none() self.inner.is_none()
@ -1253,8 +1253,8 @@ impl Span {
/// rather than constructed by `Span::none`, this method will return /// rather than constructed by `Span::none`, this method will return
/// `false`, while `is_disabled` will return `true`. /// `false`, while `is_disabled` will return `true`.
/// ///
/// [`Span::none`]: #method.none /// [`Span::none`]: Span::none()
/// [`is_disabled`]: #method.is_disabled /// [`is_disabled`]: Span::is_disabled()
#[inline] #[inline]
pub fn is_none(&self) -> bool { pub fn is_none(&self) -> bool {
self.is_disabled() && self.meta.is_none() self.is_disabled() && self.meta.is_none()

View File

@ -0,0 +1,47 @@
use std::{sync::mpsc, thread, time::Duration};
use tracing::{
metadata::Metadata,
span,
subscriber::{self, Interest, Subscriber},
Event,
};
#[test]
fn register_callsite_doesnt_deadlock() {
pub struct EvilSubscriber;
impl Subscriber for EvilSubscriber {
fn register_callsite(&self, meta: &'static Metadata<'static>) -> Interest {
tracing::info!(?meta, "registered a callsite");
Interest::always()
}
fn enabled(&self, _: &Metadata<'_>) -> bool {
true
}
fn new_span(&self, _: &span::Attributes<'_>) -> span::Id {
span::Id::from_u64(1)
}
fn record(&self, _: &span::Id, _: &span::Record<'_>) {}
fn record_follows_from(&self, _: &span::Id, _: &span::Id) {}
fn event(&self, _: &Event<'_>) {}
fn enter(&self, _: &span::Id) {}
fn exit(&self, _: &span::Id) {}
}
subscriber::set_global_default(EvilSubscriber).unwrap();
// spawn a thread, and assert it doesn't hang...
let (tx, didnt_hang) = mpsc::channel();
let th = thread::spawn(move || {
tracing::info!("hello world!");
tx.send(()).unwrap();
});
didnt_hang
// Note: 60 seconds is *way* more than enough, but let's be generous in
// case of e.g. slow CI machines.
.recv_timeout(Duration::from_secs(60))
.expect("the thread must not have hung!");
th.join().expect("thread should join successfully");
}

186
zeroidc/vendor/typenum/build/main.rs vendored Normal file
View File

@ -0,0 +1,186 @@
use std::env;
use std::fmt;
use std::fs::File;
use std::io::Write;
use std::path::Path;
mod op;
mod tests;
pub enum UIntCode {
Term,
Zero(Box<UIntCode>),
One(Box<UIntCode>),
}
pub enum IntCode {
Zero,
Pos(Box<UIntCode>),
Neg(Box<UIntCode>),
}
impl fmt::Display for UIntCode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
UIntCode::Term => write!(f, "UTerm"),
UIntCode::Zero(ref inner) => write!(f, "UInt<{}, B0>", inner),
UIntCode::One(ref inner) => write!(f, "UInt<{}, B1>", inner),
}
}
}
impl fmt::Display for IntCode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
IntCode::Zero => write!(f, "Z0"),
IntCode::Pos(ref inner) => write!(f, "PInt<{}>", inner),
IntCode::Neg(ref inner) => write!(f, "NInt<{}>", inner),
}
}
}
pub fn gen_uint(u: u64) -> UIntCode {
let mut result = UIntCode::Term;
let mut x = 1u64 << 63;
while x > u {
x >>= 1
}
while x > 0 {
result = if x & u > 0 {
UIntCode::One(Box::new(result))
} else {
UIntCode::Zero(Box::new(result))
};
x >>= 1;
}
result
}
pub fn gen_int(i: i64) -> IntCode {
use std::cmp::Ordering::{Equal, Greater, Less};
match i.cmp(&0) {
Greater => IntCode::Pos(Box::new(gen_uint(i as u64))),
Less => IntCode::Neg(Box::new(gen_uint(i.abs() as u64))),
Equal => IntCode::Zero,
}
}
#[cfg_attr(
feature = "no_std",
deprecated(
since = "1.3.0",
note = "the `no_std` flag is no longer necessary and will be removed in the future"
)
)]
pub fn no_std() {}
// fixme: get a warning when testing without this
#[allow(dead_code)]
fn main() {
let highest: u64 = 1024;
// Use hardcoded values to avoid issues with cross-compilation.
// See https://github.com/paholg/typenum/issues/162
let first2: u32 = 11; // (highest as f64).log(2.0).round() as u32 + 1;
let first10: u32 = 4; // (highest as f64).log(10.0) as u32 + 1;
let uints = (0..(highest + 1))
.chain((first2..64).map(|i| 2u64.pow(i)))
.chain((first10..20).map(|i| 10u64.pow(i)));
let out_dir = env::var("OUT_DIR").unwrap();
let dest = Path::new(&out_dir).join("consts.rs");
println!("cargo:rustc-env=TYPENUM_BUILD_CONSTS={}", dest.display());
let mut f = File::create(&dest).unwrap();
no_std();
// Header stuff here!
write!(
f,
"
/**
Type aliases for many constants.
This file is generated by typenum's build script.
For unsigned integers, the format is `U` followed by the number. We define aliases for
- Numbers 0 through {highest}
- Powers of 2 below `u64::MAX`
- Powers of 10 below `u64::MAX`
These alias definitions look like this:
```rust
use typenum::{{B0, B1, UInt, UTerm}};
# #[allow(dead_code)]
type U6 = UInt<UInt<UInt<UTerm, B1>, B1>, B0>;
```
For positive signed integers, the format is `P` followed by the number and for negative
signed integers it is `N` followed by the number. For the signed integer zero, we use
`Z0`. We define aliases for
- Numbers -{highest} through {highest}
- Powers of 2 between `i64::MIN` and `i64::MAX`
- Powers of 10 between `i64::MIN` and `i64::MAX`
These alias definitions look like this:
```rust
use typenum::{{B0, B1, UInt, UTerm, PInt, NInt}};
# #[allow(dead_code)]
type P6 = PInt<UInt<UInt<UInt<UTerm, B1>, B1>, B0>>;
# #[allow(dead_code)]
type N6 = NInt<UInt<UInt<UInt<UTerm, B1>, B1>, B0>>;
```
# Example
```rust
# #[allow(unused_imports)]
use typenum::{{U0, U1, U2, U3, U4, U5, U6}};
# #[allow(unused_imports)]
use typenum::{{N3, N2, N1, Z0, P1, P2, P3}};
# #[allow(unused_imports)]
use typenum::{{U774, N17, N10000, P1024, P4096}};
```
We also define the aliases `False` and `True` for `B0` and `B1`, respectively.
*/
#[allow(missing_docs)]
pub mod consts {{
use crate::uint::{{UInt, UTerm}};
use crate::int::{{PInt, NInt}};
pub use crate::bit::{{B0, B1}};
pub use crate::int::Z0;
pub type True = B1;
pub type False = B0;
",
highest = highest
)
.unwrap();
for u in uints {
writeln!(f, " pub type U{} = {};", u, gen_uint(u)).unwrap();
if u <= ::std::i64::MAX as u64 && u != 0 {
let i = u as i64;
writeln!(
f,
" pub type P{i} = PInt<U{i}>; pub type N{i} = NInt<U{i}>;",
i = i
)
.unwrap();
}
}
write!(f, "}}").unwrap();
tests::build_tests().unwrap();
op::write_op_macro().unwrap();
}

559
zeroidc/vendor/typenum/build/op.rs vendored Normal file
View File

@ -0,0 +1,559 @@
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
enum OpType {
Operator,
Function,
}
use self::OpType::*;
struct Op {
token: &'static str,
operator: &'static str,
example: (&'static str, &'static str),
precedence: u8,
n_args: u8,
op_type: OpType,
}
pub fn write_op_macro() -> ::std::io::Result<()> {
let out_dir = ::std::env::var("OUT_DIR").unwrap();
let dest = ::std::path::Path::new(&out_dir).join("op.rs");
println!("cargo:rustc-env=TYPENUM_BUILD_OP={}", dest.display());
let mut f = ::std::fs::File::create(&dest).unwrap();
// Operator precedence is taken from
// https://doc.rust-lang.org/reference.html#operator-precedence
//
// We choose 16 as the highest precedence (functions are set to 255 but it doesn't matter
// for them). We also only use operators that are left associative so we don't have to worry
// about that.
let ops = &[
Op {
token: "*",
operator: "Prod",
example: ("P2 * P3", "P6"),
precedence: 16,
n_args: 2,
op_type: Operator,
},
Op {
token: "/",
operator: "Quot",
example: ("P6 / P2", "P3"),
precedence: 16,
n_args: 2,
op_type: Operator,
},
Op {
token: "%",
operator: "Mod",
example: ("P5 % P3", "P2"),
precedence: 16,
n_args: 2,
op_type: Operator,
},
Op {
token: "+",
operator: "Sum",
example: ("P2 + P3", "P5"),
precedence: 15,
n_args: 2,
op_type: Operator,
},
Op {
token: "-",
operator: "Diff",
example: ("P2 - P3", "N1"),
precedence: 15,
n_args: 2,
op_type: Operator,
},
Op {
token: "<<",
operator: "Shleft",
example: ("U1 << U5", "U32"),
precedence: 14,
n_args: 2,
op_type: Operator,
},
Op {
token: ">>",
operator: "Shright",
example: ("U32 >> U5", "U1"),
precedence: 14,
n_args: 2,
op_type: Operator,
},
Op {
token: "&",
operator: "And",
example: ("U5 & U3", "U1"),
precedence: 13,
n_args: 2,
op_type: Operator,
},
Op {
token: "^",
operator: "Xor",
example: ("U5 ^ U3", "U6"),
precedence: 12,
n_args: 2,
op_type: Operator,
},
Op {
token: "|",
operator: "Or",
example: ("U5 | U3", "U7"),
precedence: 11,
n_args: 2,
op_type: Operator,
},
Op {
token: "==",
operator: "Eq",
example: ("P5 == P3 + P2", "True"),
precedence: 10,
n_args: 2,
op_type: Operator,
},
Op {
token: "!=",
operator: "NotEq",
example: ("P5 != P3 + P2", "False"),
precedence: 10,
n_args: 2,
op_type: Operator,
},
Op {
token: "<=",
operator: "LeEq",
example: ("P6 <= P3 + P2", "False"),
precedence: 10,
n_args: 2,
op_type: Operator,
},
Op {
token: ">=",
operator: "GrEq",
example: ("P6 >= P3 + P2", "True"),
precedence: 10,
n_args: 2,
op_type: Operator,
},
Op {
token: "<",
operator: "Le",
example: ("P4 < P3 + P2", "True"),
precedence: 10,
n_args: 2,
op_type: Operator,
},
Op {
token: ">",
operator: "Gr",
example: ("P5 < P3 + P2", "False"),
precedence: 10,
n_args: 2,
op_type: Operator,
},
Op {
token: "cmp",
operator: "Compare",
example: ("cmp(P2, P3)", "Less"),
precedence: !0,
n_args: 2,
op_type: Function,
},
Op {
token: "sqr",
operator: "Square",
example: ("sqr(P2)", "P4"),
precedence: !0,
n_args: 1,
op_type: Function,
},
Op {
token: "sqrt",
operator: "Sqrt",
example: ("sqrt(U9)", "U3"),
precedence: !0,
n_args: 1,
op_type: Function,
},
Op {
token: "abs",
operator: "AbsVal",
example: ("abs(N2)", "P2"),
precedence: !0,
n_args: 1,
op_type: Function,
},
Op {
token: "cube",
operator: "Cube",
example: ("cube(P2)", "P8"),
precedence: !0,
n_args: 1,
op_type: Function,
},
Op {
token: "pow",
operator: "Exp",
example: ("pow(P2, P3)", "P8"),
precedence: !0,
n_args: 2,
op_type: Function,
},
Op {
token: "min",
operator: "Minimum",
example: ("min(P2, P3)", "P2"),
precedence: !0,
n_args: 2,
op_type: Function,
},
Op {
token: "max",
operator: "Maximum",
example: ("max(P2, P3)", "P3"),
precedence: !0,
n_args: 2,
op_type: Function,
},
Op {
token: "log2",
operator: "Log2",
example: ("log2(U9)", "U3"),
precedence: !0,
n_args: 1,
op_type: Function,
},
Op {
token: "gcd",
operator: "Gcf",
example: ("gcd(U9, U21)", "U3"),
precedence: !0,
n_args: 2,
op_type: Function,
},
];
use std::io::Write;
write!(
f,
"
/**
Convenient type operations.
Any types representing values must be able to be expressed as `ident`s. That means they need to be
in scope.
For example, `P5` is okay, but `typenum::P5` is not.
You may combine operators arbitrarily, although doing so excessively may require raising the
recursion limit.
# Example
```rust
#![recursion_limit=\"128\"]
#[macro_use] extern crate typenum;
use typenum::consts::*;
fn main() {{
assert_type!(
op!(min((P1 - P2) * (N3 + N7), P5 * (P3 + P4)) == P10)
);
}}
```
Operators are evaluated based on the operator precedence outlined
[here](https://doc.rust-lang.org/reference.html#operator-precedence).
The full list of supported operators and functions is as follows:
{}
They all expand to type aliases defined in the `operator_aliases` module. Here is an expanded list,
including examples:
",
ops.iter()
.map(|op| format!("`{}`", op.token))
.collect::<Vec<_>>()
.join(", ")
)?;
//write!(f, "Token | Alias | Example\n ===|===|===\n")?;
for op in ops.iter() {
write!(
f,
"---\nOperator `{token}`. Expands to `{operator}`.
```rust
# #[macro_use] extern crate typenum;
# use typenum::*;
# fn main() {{
assert_type_eq!(op!({ex0}), {ex1});
# }}
```\n
",
token = op.token,
operator = op.operator,
ex0 = op.example.0,
ex1 = op.example.1
)?;
}
write!(
f,
"*/
#[macro_export(local_inner_macros)]
macro_rules! op {{
($($tail:tt)*) => ( __op_internal__!($($tail)*) );
}}
#[doc(hidden)]
#[macro_export(local_inner_macros)]
macro_rules! __op_internal__ {{
"
)?;
// We first us the shunting-yard algorithm to produce our tokens in Polish notation.
// See: https://en.wikipedia.org/wiki/Shunting-yard_algorithm
// Note: Due to macro asymmetry, "the top of the stack" refers to the first element, not the
// last
// -----------------------------------------------------------------------------------------
// Stage 1: There are tokens to be read:
// -------
// Case 1: Token is a function => Push it onto the stack:
for fun in ops.iter().filter(|f| f.op_type == Function) {
write!(
f,
"
(@stack[$($stack:ident,)*] @queue[$($queue:ident,)*] @tail: {f_token} $($tail:tt)*) => (
__op_internal__!(@stack[{f_op}, $($stack,)*] @queue[$($queue,)*] @tail: $($tail)*)
);",
f_token = fun.token,
f_op = fun.operator
)?;
}
// -------
// Case 2: Token is a comma => Until the top of the stack is a LParen,
// Pop operators from stack to queue
// Base case: Top of stack is LParen, ditch comma and continue
write!(
f,
"
(@stack[LParen, $($stack:ident,)*] @queue[$($queue:ident,)*] @tail: , $($tail:tt)*) => (
__op_internal__!(@stack[LParen, $($stack,)*] @queue[$($queue,)*] @tail: $($tail)*)
);"
)?;
// Recursive case: Not LParen, pop from stack to queue
write!(
f,
"
(@stack[$stack_top:ident, $($stack:ident,)*] @queue[$($queue:ident,)*] @tail: , $($tail:tt)*) => (
__op_internal__!(@stack[$($stack,)*] @queue[$stack_top, $($queue,)*] @tail: , $($tail)*)
);"
)?;
// -------
// Case 3: Token is an operator, o1:
for o1 in ops.iter().filter(|op| op.op_type == Operator) {
// If top of stack is operator o2 with o1.precedence <= o2.precedence,
// Then pop o2 off stack onto queue:
for o2 in ops
.iter()
.filter(|op| op.op_type == Operator)
.filter(|o2| o1.precedence <= o2.precedence)
{
write!(
f,
"
(@stack[{o2_op}, $($stack:ident,)*] @queue[$($queue:ident,)*] @tail: {o1_token} $($tail:tt)*) => (
__op_internal__!(@stack[$($stack,)*] @queue[{o2_op}, $($queue,)*] @tail: {o1_token} $($tail)*)
);",
o2_op = o2.operator,
o1_token = o1.token
)?;
}
// Base case: push o1 onto stack
write!(
f,
"
(@stack[$($stack:ident,)*] @queue[$($queue:ident,)*] @tail: {o1_token} $($tail:tt)*) => (
__op_internal__!(@stack[{o1_op}, $($stack,)*] @queue[$($queue,)*] @tail: $($tail)*)
);",
o1_op = o1.operator,
o1_token = o1.token
)?;
}
// -------
// Case 4: Token is "(": push it onto stack as "LParen". Also convert the ")" to "RParen" to
// appease the macro gods:
write!(
f,
"
(@stack[$($stack:ident,)*] @queue[$($queue:ident,)*] @tail: ( $($stuff:tt)* ) $($tail:tt)* )
=> (
__op_internal__!(@stack[LParen, $($stack,)*] @queue[$($queue,)*]
@tail: $($stuff)* RParen $($tail)*)
);"
)?;
// -------
// Case 5: Token is "RParen":
// 1. Pop from stack to queue until we see an "LParen",
// 2. Kill the "LParen",
// 3. If the top of the stack is a function, pop it onto the queue
// 2. Base case:
write!(
f,
"
(@stack[LParen, $($stack:ident,)*] @queue[$($queue:ident,)*] @tail: RParen $($tail:tt)*) => (
__op_internal__!(@rp3 @stack[$($stack,)*] @queue[$($queue,)*] @tail: $($tail)*)
);"
)?;
// 1. Recursive case:
write!(
f,
"
(@stack[$stack_top:ident, $($stack:ident,)*] @queue[$($queue:ident,)*] @tail: RParen $($tail:tt)*)
=> (
__op_internal__!(@stack[$($stack,)*] @queue[$stack_top, $($queue,)*] @tail: RParen $($tail)*)
);"
)?;
// 3. Check for function:
for fun in ops.iter().filter(|f| f.op_type == Function) {
write!(
f,
"
(@rp3 @stack[{fun_op}, $($stack:ident,)*] @queue[$($queue:ident,)*] @tail: $($tail:tt)*) => (
__op_internal__!(@stack[$($stack,)*] @queue[{fun_op}, $($queue,)*] @tail: $($tail)*)
);",
fun_op = fun.operator
)?;
}
// 3. If no function found:
write!(
f,
"
(@rp3 @stack[$($stack:ident,)*] @queue[$($queue:ident,)*] @tail: $($tail:tt)*) => (
__op_internal__!(@stack[$($stack,)*] @queue[$($queue,)*] @tail: $($tail)*)
);"
)?;
// -------
// Case 6: Token is a number: Push it onto the queue
write!(
f,
"
(@stack[$($stack:ident,)*] @queue[$($queue:ident,)*] @tail: $num:ident $($tail:tt)*) => (
__op_internal__!(@stack[$($stack,)*] @queue[$num, $($queue,)*] @tail: $($tail)*)
);"
)?;
// -------
// Case 7: Out of tokens:
// Base case: Stack empty: Start evaluating
write!(
f,
"
(@stack[] @queue[$($queue:ident,)*] @tail: ) => (
__op_internal__!(@reverse[] @input: $($queue,)*)
);"
)?;
// Recursive case: Pop stack to queue
write!(
f,
"
(@stack[$stack_top:ident, $($stack:ident,)*] @queue[$($queue:ident,)*] @tail:) => (
__op_internal__!(@stack[$($stack,)*] @queue[$stack_top, $($queue,)*] @tail: )
);"
)?;
// -----------------------------------------------------------------------------------------
// Stage 2: Reverse so we have RPN
write!(
f,
"
(@reverse[$($revved:ident,)*] @input: $head:ident, $($tail:ident,)* ) => (
__op_internal__!(@reverse[$head, $($revved,)*] @input: $($tail,)*)
);"
)?;
write!(
f,
"
(@reverse[$($revved:ident,)*] @input: ) => (
__op_internal__!(@eval @stack[] @input[$($revved,)*])
);"
)?;
// -----------------------------------------------------------------------------------------
// Stage 3: Evaluate in Reverse Polish Notation
// Operators / Operators with 2 args:
for op in ops.iter().filter(|op| op.n_args == 2) {
// Note: We have to switch $a and $b here, otherwise non-commutative functions are backwards
write!(
f,
"
(@eval @stack[$a:ty, $b:ty, $($stack:ty,)*] @input[{op}, $($tail:ident,)*]) => (
__op_internal__!(@eval @stack[$crate::{op}<$b, $a>, $($stack,)*] @input[$($tail,)*])
);",
op = op.operator
)?;
}
// Operators with 1 arg:
for op in ops.iter().filter(|op| op.n_args == 1) {
write!(
f,
"
(@eval @stack[$a:ty, $($stack:ty,)*] @input[{op}, $($tail:ident,)*]) => (
__op_internal__!(@eval @stack[$crate::{op}<$a>, $($stack,)*] @input[$($tail,)*])
);",
op = op.operator
)?;
}
// Wasn't a function or operator, so must be a value => push onto stack
write!(
f,
"
(@eval @stack[$($stack:ty,)*] @input[$head:ident, $($tail:ident,)*]) => (
__op_internal__!(@eval @stack[$head, $($stack,)*] @input[$($tail,)*])
);"
)?;
// No input left:
write!(
f,
"
(@eval @stack[$stack:ty,] @input[]) => (
$stack
);"
)?;
// -----------------------------------------------------------------------------------------
// Stage 0: Get it started
write!(
f,
"
($($tail:tt)* ) => (
__op_internal__!(@stack[] @queue[] @tail: $($tail)*)
);"
)?;
write!(
f,
"
}}"
)?;
Ok(())
}

328
zeroidc/vendor/typenum/build/tests.rs vendored Normal file
View File

@ -0,0 +1,328 @@
use std::{env, fmt, fs, io, path};
use super::{gen_int, gen_uint};
/// Computes the greatest common divisor of two integers.
fn gcdi(mut a: i64, mut b: i64) -> i64 {
a = a.abs();
b = b.abs();
while a != 0 {
let tmp = b % a;
b = a;
a = tmp;
}
b
}
fn gcdu(mut a: u64, mut b: u64) -> u64 {
while a != 0 {
let tmp = b % a;
b = a;
a = tmp;
}
b
}
fn sign(i: i64) -> char {
use std::cmp::Ordering::*;
match i.cmp(&0) {
Greater => 'P',
Less => 'N',
Equal => '_',
}
}
struct UIntTest {
a: u64,
op: &'static str,
b: Option<u64>,
r: u64,
}
impl fmt::Display for UIntTest {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.b {
Some(b) => write!(
f,
"
#[test]
#[allow(non_snake_case)]
fn test_{a}_{op}_{b}() {{
type A = {gen_a};
type B = {gen_b};
type U{r} = {result};
#[allow(non_camel_case_types)]
type U{a}{op}U{b} = <<A as {op}<B>>::Output as Same<U{r}>>::Output;
assert_eq!(<U{a}{op}U{b} as Unsigned>::to_u64(), <U{r} as Unsigned>::to_u64());
}}",
gen_a = gen_uint(self.a),
gen_b = gen_uint(b),
r = self.r,
result = gen_uint(self.r),
a = self.a,
b = b,
op = self.op
),
None => write!(
f,
"
#[test]
#[allow(non_snake_case)]
fn test_{a}_{op}() {{
type A = {gen_a};
type U{r} = {result};
#[allow(non_camel_case_types)]
type {op}U{a} = <<A as {op}>::Output as Same<U{r}>>::Output;
assert_eq!(<{op}U{a} as Unsigned>::to_u64(), <U{r} as Unsigned>::to_u64());
}}",
gen_a = gen_uint(self.a),
r = self.r,
result = gen_uint(self.r),
a = self.a,
op = self.op
),
}
}
}
fn uint_binary_test(left: u64, operator: &'static str, right: u64, result: u64) -> UIntTest {
UIntTest {
a: left,
op: operator,
b: Option::Some(right),
r: result,
}
}
// fn uint_unary_test(op: &'static str, a: u64, result: u64) -> UIntTest {
// UIntTest { a: a, op: op, b: Option::None, r: result }
// }
struct IntBinaryTest {
a: i64,
op: &'static str,
b: i64,
r: i64,
}
impl fmt::Display for IntBinaryTest {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"
#[test]
#[allow(non_snake_case)]
fn test_{sa}{a}_{op}_{sb}{b}() {{
type A = {gen_a};
type B = {gen_b};
type {sr}{r} = {result};
#[allow(non_camel_case_types)]
type {sa}{a}{op}{sb}{b} = <<A as {op}<B>>::Output as Same<{sr}{r}>>::Output;
assert_eq!(<{sa}{a}{op}{sb}{b} as Integer>::to_i64(), <{sr}{r} as Integer>::to_i64());
}}",
gen_a = gen_int(self.a),
gen_b = gen_int(self.b),
r = self.r.abs(),
sr = sign(self.r),
result = gen_int(self.r),
a = self.a.abs(),
b = self.b.abs(),
sa = sign(self.a),
sb = sign(self.b),
op = self.op
)
}
}
fn int_binary_test(left: i64, operator: &'static str, right: i64, result: i64) -> IntBinaryTest {
IntBinaryTest {
a: left,
op: operator,
b: right,
r: result,
}
}
struct IntUnaryTest {
op: &'static str,
a: i64,
r: i64,
}
impl fmt::Display for IntUnaryTest {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"
#[test]
#[allow(non_snake_case)]
fn test_{sa}{a}_{op}() {{
type A = {gen_a};
type {sr}{r} = {result};
#[allow(non_camel_case_types)]
type {op}{sa}{a} = <<A as {op}>::Output as Same<{sr}{r}>>::Output;
assert_eq!(<{op}{sa}{a} as Integer>::to_i64(), <{sr}{r} as Integer>::to_i64());
}}",
gen_a = gen_int(self.a),
r = self.r.abs(),
sr = sign(self.r),
result = gen_int(self.r),
a = self.a.abs(),
sa = sign(self.a),
op = self.op
)
}
}
fn int_unary_test(operator: &'static str, num: i64, result: i64) -> IntUnaryTest {
IntUnaryTest {
op: operator,
a: num,
r: result,
}
}
fn uint_cmp_test(a: u64, b: u64) -> String {
format!(
"
#[test]
#[allow(non_snake_case)]
fn test_{a}_Cmp_{b}() {{
type A = {gen_a};
type B = {gen_b};
#[allow(non_camel_case_types)]
type U{a}CmpU{b} = <A as Cmp<B>>::Output;
assert_eq!(<U{a}CmpU{b} as Ord>::to_ordering(), Ordering::{result:?});
}}",
a = a,
b = b,
gen_a = gen_uint(a),
gen_b = gen_uint(b),
result = a.cmp(&b)
)
}
fn int_cmp_test(a: i64, b: i64) -> String {
format!(
"
#[test]
#[allow(non_snake_case)]
fn test_{sa}{a}_Cmp_{sb}{b}() {{
type A = {gen_a};
type B = {gen_b};
#[allow(non_camel_case_types)]
type {sa}{a}Cmp{sb}{b} = <A as Cmp<B>>::Output;
assert_eq!(<{sa}{a}Cmp{sb}{b} as Ord>::to_ordering(), Ordering::{result:?});
}}",
a = a.abs(),
b = b.abs(),
sa = sign(a),
sb = sign(b),
gen_a = gen_int(a),
gen_b = gen_int(b),
result = a.cmp(&b)
)
}
// Allow for rustc 1.22 compatibility.
#[allow(bare_trait_objects)]
pub fn build_tests() -> Result<(), Box<::std::error::Error>> {
// will test all permutations of number pairs up to this (and down to its opposite for ints)
let high: i64 = 5;
let uints = (0u64..high as u64 + 1).flat_map(|a| (a..a + 1).cycle().zip(0..high as u64 + 1));
let ints = (-high..high + 1).flat_map(|a| (a..a + 1).cycle().zip(-high..high + 1));
let out_dir = env::var("OUT_DIR")?;
let dest = path::Path::new(&out_dir).join("tests.rs");
let f = fs::File::create(&dest)?;
let mut writer = io::BufWriter::new(&f);
use std::io::Write;
writer.write_all(
b"
extern crate typenum;
use std::ops::*;
use std::cmp::Ordering;
use typenum::*;
",
)?;
use std::cmp;
// uint operators:
for (a, b) in uints {
write!(writer, "{}", uint_binary_test(a, "BitAnd", b, a & b))?;
write!(writer, "{}", uint_binary_test(a, "BitOr", b, a | b))?;
write!(writer, "{}", uint_binary_test(a, "BitXor", b, a ^ b))?;
write!(writer, "{}", uint_binary_test(a, "Shl", b, a << b))?;
write!(writer, "{}", uint_binary_test(a, "Shr", b, a >> b))?;
write!(writer, "{}", uint_binary_test(a, "Add", b, a + b))?;
write!(writer, "{}", uint_binary_test(a, "Min", b, cmp::min(a, b)))?;
write!(writer, "{}", uint_binary_test(a, "Max", b, cmp::max(a, b)))?;
write!(writer, "{}", uint_binary_test(a, "Gcd", b, gcdu(a, b)))?;
if a >= b {
write!(writer, "{}", uint_binary_test(a, "Sub", b, a - b))?;
}
write!(writer, "{}", uint_binary_test(a, "Mul", b, a * b))?;
if b != 0 {
write!(writer, "{}", uint_binary_test(a, "Div", b, a / b))?;
write!(writer, "{}", uint_binary_test(a, "Rem", b, a % b))?;
if a % b == 0 {
write!(writer, "{}", uint_binary_test(a, "PartialDiv", b, a / b))?;
}
}
write!(writer, "{}", uint_binary_test(a, "Pow", b, a.pow(b as u32)))?;
write!(writer, "{}", uint_cmp_test(a, b))?;
}
// int operators:
for (a, b) in ints {
write!(writer, "{}", int_binary_test(a, "Add", b, a + b))?;
write!(writer, "{}", int_binary_test(a, "Sub", b, a - b))?;
write!(writer, "{}", int_binary_test(a, "Mul", b, a * b))?;
write!(writer, "{}", int_binary_test(a, "Min", b, cmp::min(a, b)))?;
write!(writer, "{}", int_binary_test(a, "Max", b, cmp::max(a, b)))?;
write!(writer, "{}", int_binary_test(a, "Gcd", b, gcdi(a, b)))?;
if b != 0 {
write!(writer, "{}", int_binary_test(a, "Div", b, a / b))?;
write!(writer, "{}", int_binary_test(a, "Rem", b, a % b))?;
if a % b == 0 {
write!(writer, "{}", int_binary_test(a, "PartialDiv", b, a / b))?;
}
}
if b >= 0 || a.abs() == 1 {
let result = if b < 0 {
if a == 1 {
a
} else if a == -1 {
a.pow((-b) as u32)
} else {
unreachable!()
}
} else {
a.pow(b as u32)
};
write!(writer, "{}", int_binary_test(a, "Pow", b, result))?;
}
write!(writer, "{}", int_cmp_test(a, b))?;
}
// int unary operators:
for n in -high..high + 1 {
write!(writer, "{}", int_unary_test("Neg", n, -n))?;
write!(writer, "{}", int_unary_test("Abs", n, n.abs()))?;
}
writer.flush()?;
Ok(())
}