summaryrefslogtreecommitdiff
path: root/src/rust
diff options
context:
space:
mode:
Diffstat (limited to 'src/rust')
-rw-r--r--src/rust/Cargo.toml9
-rw-r--r--src/rust/build.rs27
-rw-r--r--src/rust/crypto/Cargo.toml4
-rw-r--r--src/rust/crypto/digests/sha2.rs6
-rw-r--r--src/rust/external/external.rs4
-rw-r--r--src/rust/protover/ffi.rs68
-rw-r--r--src/rust/protover/lib.rs2
-rw-r--r--src/rust/protover/protover.rs14
-rw-r--r--src/rust/protover/tests/protover.rs2
-rw-r--r--src/rust/smartlist/lib.rs2
-rw-r--r--src/rust/smartlist/smartlist.rs2
-rw-r--r--src/rust/tor_allocate/lib.rs2
-rw-r--r--src/rust/tor_allocate/tor_allocate.rs14
-rw-r--r--src/rust/tor_log/lib.rs2
-rw-r--r--src/rust/tor_log/tor_log.rs4
-rw-r--r--src/rust/tor_rust/include.am8
-rw-r--r--src/rust/tor_util/ffi.rs2
-rw-r--r--src/rust/tor_util/lib.rs2
-rw-r--r--src/rust/tor_util/strings.rs2
19 files changed, 103 insertions, 73 deletions
diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml
index c3e44d2a79..4bbadbe535 100644
--- a/src/rust/Cargo.toml
+++ b/src/rust/Cargo.toml
@@ -14,3 +14,12 @@ members = [
debug = true
panic = "abort"
+[features]
+default = []
+# If this feature is enabled, test code which calls Tor C code from Rust will
+# execute with `cargo test`. Due to numerous linker issues (#25386), this is
+# currently disabled by default. Crates listed here are those which, in their
+# unittests, doctests, and/or integration tests, call C code.
+test-c-from-rust = [
+ "crypto/test-c-from-rust",
+]
diff --git a/src/rust/build.rs b/src/rust/build.rs
index b943aa5535..2ac24b334b 100644
--- a/src/rust/build.rs
+++ b/src/rust/build.rs
@@ -138,8 +138,7 @@ pub fn main() {
cfg.from_cflags("TOR_LDFLAGS_openssl");
cfg.from_cflags("TOR_LDFLAGS_libevent");
- cfg.link_relpath("src/common");
- cfg.link_relpath("src/ext/keccak-tiny");
+ cfg.link_relpath("src/lib");
cfg.link_relpath("src/ext/keccak-tiny");
cfg.link_relpath("src/ext/ed25519/ref10");
cfg.link_relpath("src/ext/ed25519/donna");
@@ -149,11 +148,25 @@ pub fn main() {
// will have dependencies on all the other rust packages that
// tor uses. We must be careful with factoring and dependencies
// moving forward!
- cfg.component("or-crypto-testing");
- cfg.component("or-ctime-testing");
- cfg.component("or-testing");
- cfg.component("or-event-testing");
- cfg.component("or-ctime-testing");
+ cfg.component("tor-crypt-ops-testing");
+ cfg.component("tor-sandbox-testing");
+ cfg.component("tor-encoding-testing");
+ cfg.component("tor-fs-testing");
+ cfg.component("tor-time-testing");
+ cfg.component("tor-net-testing");
+ cfg.component("tor-thread-testing");
+ cfg.component("tor-memarea-testing");
+ cfg.component("tor-log-testing");
+ cfg.component("tor-lock-testing");
+ cfg.component("tor-fdio-testing");
+ cfg.component("tor-container-testing");
+ cfg.component("tor-smartlist-core-testing");
+ cfg.component("tor-string-testing");
+ cfg.component("tor-malloc");
+ cfg.component("tor-wallclock");
+ cfg.component("tor-err-testing");
+ cfg.component("tor-intmath-testing");
+ cfg.component("tor-ctime-testing");
cfg.component("curve25519_donna");
cfg.component("keccak-tiny");
cfg.component("ed25519_ref10");
diff --git a/src/rust/crypto/Cargo.toml b/src/rust/crypto/Cargo.toml
index 869e0d6256..d68ac48e28 100644
--- a/src/rust/crypto/Cargo.toml
+++ b/src/rust/crypto/Cargo.toml
@@ -26,3 +26,7 @@ rand = { version = "=0.5.0-pre.2", default-features = false }
rand_core = { version = "=0.2.0-pre.0", default-features = false }
[features]
+# If this feature is enabled, test code which calls Tor C code from Rust will
+# execute with `cargo test`. Due to numerous linker issues (#25386), this is
+# currently disabled by default.
+test-c-from-rust = []
diff --git a/src/rust/crypto/digests/sha2.rs b/src/rust/crypto/digests/sha2.rs
index 03e0843dc0..d0246eeb94 100644
--- a/src/rust/crypto/digests/sha2.rs
+++ b/src/rust/crypto/digests/sha2.rs
@@ -165,15 +165,19 @@ impl FixedOutput for Sha512 {
#[cfg(test)]
mod test {
+ #[cfg(feature = "test-c-from-rust")]
use digest::Digest;
+ #[cfg(feature = "test-c-from-rust")]
use super::*;
+ #[cfg(feature = "test-c-from-rust")]
#[test]
fn sha256_default() {
let _: Sha256 = Sha256::default();
}
+ #[cfg(feature = "test-c-from-rust")]
#[test]
fn sha256_digest() {
let mut h: Sha256 = Sha256::new();
@@ -193,11 +197,13 @@ mod test {
assert_eq!(result, expected);
}
+ #[cfg(feature = "test-c-from-rust")]
#[test]
fn sha512_default() {
let _: Sha512 = Sha512::default();
}
+ #[cfg(feature = "test-c-from-rust")]
#[test]
fn sha512_digest() {
let mut h: Sha512 = Sha512::new();
diff --git a/src/rust/external/external.rs b/src/rust/external/external.rs
index b9e17f021d..059fdd0df7 100644
--- a/src/rust/external/external.rs
+++ b/src/rust/external/external.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017, The Tor Project, Inc. */
+// Copyright (c) 2016-2018, The Tor Project, Inc. */
// See LICENSE for licensing information */
use libc::{c_char, c_int};
@@ -11,7 +11,7 @@ extern "C" {
) -> c_int;
}
-/// Wrap calls to tor_version_as_new_as, defined in src/or/routerparse.c
+/// Wrap calls to tor_version_as_new_as, defined in routerparse.c
pub fn c_tor_version_as_new_as(platform: &str, cutoff: &str) -> bool {
// CHK: These functions should log a warning if an error occurs. This
// can be added when integration with tor's logger is added to rust
diff --git a/src/rust/protover/ffi.rs b/src/rust/protover/ffi.rs
index e3e545db75..91bd83addf 100644
--- a/src/rust/protover/ffi.rs
+++ b/src/rust/protover/ffi.rs
@@ -1,9 +1,9 @@
-// Copyright (c) 2016-2017, The Tor Project, Inc. */
+// Copyright (c) 2016-2018, The Tor Project, Inc. */
// See LICENSE for licensing information */
//! FFI functions, only to be called from C.
//!
-//! Equivalent C versions of this api are in `src/or/protover.c`
+//! Equivalent C versions of this api are in `protover.c`
use libc::{c_char, c_int, uint32_t};
use std::ffi::CStr;
@@ -18,7 +18,7 @@ use protover::*;
/// Translate C enums to Rust Proto enums, using the integer value of the C
/// enum to map to its associated Rust enum.
///
-/// C_RUST_COUPLED: src/or/protover.h `protocol_type_t`
+/// C_RUST_COUPLED: protover.h `protocol_type_t`
fn translate_to_rust(c_proto: uint32_t) -> Result<Protocol, ProtoverError> {
match c_proto {
0 => Ok(Protocol::Link),
@@ -42,7 +42,6 @@ pub extern "C" fn protover_all_supported(
c_relay_version: *const c_char,
missing_out: *mut *mut c_char,
) -> c_int {
-
if c_relay_version.is_null() {
return 1;
}
@@ -58,14 +57,13 @@ pub extern "C" fn protover_all_supported(
let relay_proto_entry: UnvalidatedProtoEntry =
match UnvalidatedProtoEntry::from_str_any_len(relay_version) {
- Ok(n) => n,
- Err(_) => return 1,
- };
- let maybe_unsupported: Option<UnvalidatedProtoEntry> = relay_proto_entry.all_supported();
+ Ok(n) => n,
+ Err(_) => return 1,
+ };
- if maybe_unsupported.is_some() {
- let unsupported: UnvalidatedProtoEntry = maybe_unsupported.unwrap();
- let c_unsupported: CString = match CString::new(unsupported.to_string()) {
+ if let Some(unsupported) = relay_proto_entry.all_supported() {
+ let c_unsupported: CString = match CString::new(unsupported.to_string())
+ {
Ok(n) => n,
Err(_) => return 1,
};
@@ -100,22 +98,23 @@ pub extern "C" fn protocol_list_supports_protocol(
Err(_) => return 1,
};
let proto_entry: UnvalidatedProtoEntry = match protocol_list.parse() {
- Ok(n) => n,
+ Ok(n) => n,
Err(_) => return 0,
};
let protocol: UnknownProtocol = match translate_to_rust(c_protocol) {
Ok(n) => n.into(),
Err(_) => return 0,
};
- match proto_entry.supports_protocol(&protocol, &version) {
- false => return 0,
- true => return 1,
+ if proto_entry.supports_protocol(&protocol, &version) {
+ 1
+ } else {
+ 0
}
}
#[no_mangle]
pub extern "C" fn protover_contains_long_protocol_names_(
- c_protocol_list: *const c_char
+ c_protocol_list: *const c_char,
) -> c_int {
if c_protocol_list.is_null() {
return 1;
@@ -127,13 +126,10 @@ pub extern "C" fn protover_contains_long_protocol_names_(
let protocol_list = match c_str.to_str() {
Ok(n) => n,
- Err(_) => return 1
+ Err(_) => return 1,
};
- let protocol_entry : Result<UnvalidatedProtoEntry,_> =
- protocol_list.parse();
-
- match protocol_entry {
+ match protocol_list.parse::<UnvalidatedProtoEntry>() {
Ok(_) => 0,
Err(_) => 1,
}
@@ -166,7 +162,7 @@ pub extern "C" fn protocol_list_supports_protocol_or_later(
};
let proto_entry: UnvalidatedProtoEntry = match protocol_list.parse() {
- Ok(n) => n,
+ Ok(n) => n,
Err(_) => return 1,
};
@@ -196,10 +192,8 @@ pub extern "C" fn protover_compute_vote(
threshold: c_int,
allow_long_proto_names: bool,
) -> *mut c_char {
-
if list.is_null() {
- let empty = String::new();
- return allocate_and_copy_string(&empty);
+ return allocate_and_copy_string("");
}
// Dereference of raw pointer requires an unsafe block. The pointer is
@@ -209,17 +203,21 @@ pub extern "C" fn protover_compute_vote(
let mut proto_entries: Vec<UnvalidatedProtoEntry> = Vec::new();
for datum in data {
- let entry: UnvalidatedProtoEntry = match allow_long_proto_names {
- true => match UnvalidatedProtoEntry::from_str_any_len(datum.as_str()) {
- Ok(n) => n,
- Err(_) => continue},
- false => match datum.parse() {
- Ok(n) => n,
- Err(_) => continue},
+ let entry: UnvalidatedProtoEntry = if allow_long_proto_names {
+ match UnvalidatedProtoEntry::from_str_any_len(datum.as_str()) {
+ Ok(n) => n,
+ Err(_) => continue,
+ }
+ } else {
+ match datum.parse() {
+ Ok(n) => n,
+ Err(_) => continue,
+ }
};
proto_entries.push(entry);
}
- let vote: UnvalidatedProtoEntry = ProtoverVote::compute(&proto_entries, &hold);
+ let vote: UnvalidatedProtoEntry =
+ ProtoverVote::compute(&proto_entries, &hold);
allocate_and_copy_string(&vote.to_string())
}
@@ -244,7 +242,9 @@ pub extern "C" fn protover_is_supported_here(
/// Provide an interface for C to translate arguments and return types for
/// protover::compute_for_old_tor
#[no_mangle]
-pub extern "C" fn protover_compute_for_old_tor(version: *const c_char) -> *const c_char {
+pub extern "C" fn protover_compute_for_old_tor(
+ version: *const c_char,
+) -> *const c_char {
let supported: &'static CStr;
let empty: &'static CStr;
diff --git a/src/rust/protover/lib.rs b/src/rust/protover/lib.rs
index ce964196fd..5da562c1e0 100644
--- a/src/rust/protover/lib.rs
+++ b/src/rust/protover/lib.rs
@@ -1,4 +1,4 @@
-//! Copyright (c) 2016-2017, The Tor Project, Inc. */
+//! Copyright (c) 2016-2018, The Tor Project, Inc. */
//! See LICENSE for licensing information */
//! Versioning information for different pieces of the Tor protocol.
diff --git a/src/rust/protover/protover.rs b/src/rust/protover/protover.rs
index d6ed2739fe..299e433722 100644
--- a/src/rust/protover/protover.rs
+++ b/src/rust/protover/protover.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017, The Tor Project, Inc. */
+// Copyright (c) 2016-2018, The Tor Project, Inc. */
// See LICENSE for licensing information */
use std::collections::HashMap;
@@ -19,13 +19,13 @@ use protoset::ProtoSet;
/// Authorities should use this to decide whether to guess proto lines.
///
/// C_RUST_COUPLED:
-/// src/or/protover.h `FIRST_TOR_VERSION_TO_ADVERTISE_PROTOCOLS`
+/// protover.h `FIRST_TOR_VERSION_TO_ADVERTISE_PROTOCOLS`
const FIRST_TOR_VERSION_TO_ADVERTISE_PROTOCOLS: &'static str = "0.2.9.3-alpha";
/// The maximum number of subprotocol version numbers we will attempt to expand
/// before concluding that someone is trying to DoS us
///
-/// C_RUST_COUPLED: src/or/protover.c `MAX_PROTOCOLS_TO_EXPAND`
+/// C_RUST_COUPLED: protover.c `MAX_PROTOCOLS_TO_EXPAND`
const MAX_PROTOCOLS_TO_EXPAND: usize = (1<<16);
/// The maximum size an `UnknownProtocol`'s name may be.
@@ -33,7 +33,7 @@ pub(crate) const MAX_PROTOCOL_NAME_LENGTH: usize = 100;
/// Known subprotocols in Tor. Indicates which subprotocol a relay supports.
///
-/// C_RUST_COUPLED: src/or/protover.h `protocol_type_t`
+/// C_RUST_COUPLED: protover.h `protocol_type_t`
#[derive(Clone, Hash, Eq, PartialEq, Debug)]
pub enum Protocol {
Cons,
@@ -57,7 +57,7 @@ impl fmt::Display for Protocol {
/// Translates a string representation of a protocol into a Proto type.
/// Error if the string is an unrecognized protocol name.
///
-/// C_RUST_COUPLED: src/or/protover.c `PROTOCOL_NAMES`
+/// C_RUST_COUPLED: protover.c `PROTOCOL_NAMES`
impl FromStr for Protocol {
type Err = ProtoverError;
@@ -130,7 +130,7 @@ impl From<Protocol> for UnknownProtocol {
/// Rust code can use the `&'static CStr` as a normal `&'a str` by
/// calling `protover::get_supported_protocols`.
///
-// C_RUST_COUPLED: src/or/protover.c `protover_get_supported_protocols`
+// C_RUST_COUPLED: protover.c `protover_get_supported_protocols`
pub(crate) fn get_supported_protocols_cstr() -> &'static CStr {
cstr!("Cons=1-2 \
Desc=1-2 \
@@ -601,7 +601,7 @@ impl ProtoverVote {
/// let vote = ProtoverVote::compute(protos, &2);
/// assert_eq!("Link=3", vote.to_string());
/// ```
- // C_RUST_COUPLED: /src/or/protover.c protover_compute_vote
+ // C_RUST_COUPLED: protover.c protover_compute_vote
pub fn compute(proto_entries: &[UnvalidatedProtoEntry], threshold: &usize) -> UnvalidatedProtoEntry {
let mut all_count: ProtoverVote = ProtoverVote::default();
let mut final_output: UnvalidatedProtoEntry = UnvalidatedProtoEntry::default();
diff --git a/src/rust/protover/tests/protover.rs b/src/rust/protover/tests/protover.rs
index 2db01a1634..ac78d34b7a 100644
--- a/src/rust/protover/tests/protover.rs
+++ b/src/rust/protover/tests/protover.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017, The Tor Project, Inc. */
+// Copyright (c) 2016-2018, The Tor Project, Inc. */
// See LICENSE for licensing information */
extern crate protover;
diff --git a/src/rust/smartlist/lib.rs b/src/rust/smartlist/lib.rs
index 14a8148315..2716842af2 100644
--- a/src/rust/smartlist/lib.rs
+++ b/src/rust/smartlist/lib.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017, The Tor Project, Inc. */
+// Copyright (c) 2016-2018, The Tor Project, Inc. */
// See LICENSE for licensing information */
extern crate libc;
diff --git a/src/rust/smartlist/smartlist.rs b/src/rust/smartlist/smartlist.rs
index 2a822d89f4..747d22f78c 100644
--- a/src/rust/smartlist/smartlist.rs
+++ b/src/rust/smartlist/smartlist.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017, The Tor Project, Inc. */
+// Copyright (c) 2016-2018, The Tor Project, Inc. */
// See LICENSE for licensing information */
use std::slice;
diff --git a/src/rust/tor_allocate/lib.rs b/src/rust/tor_allocate/lib.rs
index 937a5dcf63..5a355bc8d6 100644
--- a/src/rust/tor_allocate/lib.rs
+++ b/src/rust/tor_allocate/lib.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017, The Tor Project, Inc. */
+// Copyright (c) 2016-2018, The Tor Project, Inc. */
// See LICENSE for licensing information */
//! Allocation helper functions that allow data to be allocated in Rust
diff --git a/src/rust/tor_allocate/tor_allocate.rs b/src/rust/tor_allocate/tor_allocate.rs
index 3c0037f139..d0c0d79943 100644
--- a/src/rust/tor_allocate/tor_allocate.rs
+++ b/src/rust/tor_allocate/tor_allocate.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017, The Tor Project, Inc. */
+// Copyright (c) 2016-2018, The Tor Project, Inc. */
// See LICENSE for licensing information */
// No-op defined purely for testing at the module level
use libc::c_char;
@@ -9,9 +9,9 @@ use libc::c_void;
// Define a no-op implementation for testing Rust modules without linking to C
#[cfg(feature = "testing")]
-pub fn allocate_and_copy_string(s: &String) -> *mut c_char {
+pub fn allocate_and_copy_string(s: &str) -> *mut c_char {
use std::ffi::CString;
- CString::new(s.as_str()).unwrap().into_raw()
+ CString::new(s).unwrap().into_raw()
}
// Defined only for tests, used for testing purposes, so that we don't need
@@ -39,7 +39,7 @@ extern "C" {
/// A `*mut c_char` that should be freed by tor_free in C
///
#[cfg(not(feature = "testing"))]
-pub fn allocate_and_copy_string(src: &String) -> *mut c_char {
+pub fn allocate_and_copy_string(src: &str) -> *mut c_char {
let bytes: &[u8] = src.as_bytes();
let size = mem::size_of_val::<[u8]>(bytes);
@@ -77,8 +77,7 @@ mod test {
use tor_allocate::allocate_and_copy_string;
- let empty = String::new();
- let allocated_empty = allocate_and_copy_string(&empty);
+ let allocated_empty = allocate_and_copy_string("");
let allocated_empty_rust =
unsafe { CStr::from_ptr(allocated_empty).to_str().unwrap() };
@@ -95,8 +94,7 @@ mod test {
use tor_allocate::allocate_and_copy_string;
- let empty = String::from("foo bar biz");
- let allocated_empty = allocate_and_copy_string(&empty);
+ let allocated_empty = allocate_and_copy_string("foo bar biz");
let allocated_empty_rust =
unsafe { CStr::from_ptr(allocated_empty).to_str().unwrap() };
diff --git a/src/rust/tor_log/lib.rs b/src/rust/tor_log/lib.rs
index 72f9e38339..21855ae73b 100644
--- a/src/rust/tor_log/lib.rs
+++ b/src/rust/tor_log/lib.rs
@@ -1,4 +1,4 @@
-//! Copyright (c) 2016-2017, The Tor Project, Inc. */
+//! Copyright (c) 2016-2018, The Tor Project, Inc. */
//! See LICENSE for licensing information */
//! Logging wrapper for Rust to utilize Tor's logger, found at
diff --git a/src/rust/tor_log/tor_log.rs b/src/rust/tor_log/tor_log.rs
index ad6725f0f2..49a1e7b158 100644
--- a/src/rust/tor_log/tor_log.rs
+++ b/src/rust/tor_log/tor_log.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017, The Tor Project, Inc. */
+// Copyright (c) 2016-2018, The Tor Project, Inc. */
// See LICENSE for licensing information */
// Note that these functions are untested due to the fact that there are no
@@ -129,7 +129,7 @@ pub mod log {
}
/// The main entry point into Tor's logger. When in non-test mode, this
- /// will link directly with `tor_log_string` in /src/or/log.c
+ /// will link directly with `tor_log_string` in torlog.c
extern "C" {
pub fn tor_log_string(
severity: c_int,
diff --git a/src/rust/tor_rust/include.am b/src/rust/tor_rust/include.am
index 99f3ede653..ce673abbee 100644
--- a/src/rust/tor_rust/include.am
+++ b/src/rust/tor_rust/include.am
@@ -8,15 +8,15 @@ EXTRA_CARGO_OPTIONS=
( cd "$(abs_top_builddir)/src/rust" ; \
CARGO_TARGET_DIR="$(abs_top_builddir)/src/rust/target" \
$(CARGO) build --release $(EXTRA_CARGO_OPTIONS) \
- $(CARGO_ONLINE) \
- --manifest-path "$(abs_top_srcdir)/src/rust/tor_rust/Cargo.toml" )
+ $(CARGO_ONLINE) \
+ --manifest-path "$(abs_top_srcdir)/src/rust/tor_rust/Cargo.toml" )
distclean-rust:
( cd "$(abs_top_builddir)/src/rust" ; \
CARGO_TARGET_DIR="$(abs_top_builddir)/src/rust/target" \
$(CARGO) clean $(EXTRA_CARGO_OPTIONS) \
- $(CARGO_ONLINE) \
- --manifest-path "$(abs_top_srcdir)/src/rust/tor_rust/Cargo.toml" )
+ $(CARGO_ONLINE) \
+ --manifest-path "$(abs_top_srcdir)/src/rust/tor_rust/Cargo.toml" )
rm -rf "$(abs_top_builddir)/src/rust/registry"
if USE_RUST
diff --git a/src/rust/tor_util/ffi.rs b/src/rust/tor_util/ffi.rs
index 32779ed476..4be154ff1e 100644
--- a/src/rust/tor_util/ffi.rs
+++ b/src/rust/tor_util/ffi.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017, The Tor Project, Inc. */
+// Copyright (c) 2016-2018, The Tor Project, Inc. */
// See LICENSE for licensing information */
//! FFI functions to announce Rust support during tor startup, only to be
diff --git a/src/rust/tor_util/lib.rs b/src/rust/tor_util/lib.rs
index 94697b6069..4ce5fc9374 100644
--- a/src/rust/tor_util/lib.rs
+++ b/src/rust/tor_util/lib.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017, The Tor Project, Inc. */
+// Copyright (c) 2016-2018, The Tor Project, Inc. */
// See LICENSE for licensing information */
//! Small module to announce Rust support during startup for demonstration
diff --git a/src/rust/tor_util/strings.rs b/src/rust/tor_util/strings.rs
index 505191d913..c365564e97 100644
--- a/src/rust/tor_util/strings.rs
+++ b/src/rust/tor_util/strings.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-2017, The Tor Project, Inc. */
+// Copyright (c) 2016-2018, The Tor Project, Inc. */
// See LICENSE for licensing information */
//! Utilities for working with static strings.