1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
/// Create a const [`ArcStr`](crate::ArcStr) from a string literal. The
/// resulting `ArcStr` require no heap allocation, can be freely cloned and used
/// interchangeably with `ArcStr`s from the heap, and are effectively "free".
///
/// The main downside is that it's a macro. Eventually it may be doable as a
/// `const fn`, which would be cleaner, but for now the drawbacks to this are
/// not overwhelming, and the functionality it provides is very useful.
///
/// # Usage
///
/// ```
/// # use arcstr::ArcStr;
/// // Works in const:
/// const MY_ARCSTR: ArcStr = arcstr::literal!("testing testing");
/// assert_eq!(MY_ARCSTR, "testing testing");
///
/// // Or, just in normal expressions.
/// assert_eq!("Wow!", arcstr::literal!("Wow!"));
/// ```
///
/// Another motivating use case is bundled files (eventually this will improve
/// when `arcstr::Substr` is implemented):
///
/// ```rust,ignore
/// use arcstr::ArcStr;
/// const VERY_IMPORTANT_FILE: ArcStr =
/// arcstr::literal!(include_str!("./very-important.txt"));
/// ```
#[macro_export]
macro_rules! literal {
($text:expr) => {{
// Note: extra scope to reduce the size of what's in `$text`'s scope
// (note that consts in macros dont have hygene the way let does).
const __TEXT: &$crate::_private::str = $text;
{
const SI: &$crate::_private::StaticArcStrInner<[$crate::_private::u8; __TEXT.len()]> = unsafe {
&$crate::_private::StaticArcStrInner {
len_flags: __TEXT.len() << 1,
count: 0,
// See comment for `_private::ConstPtrDeref` for what the hell's
// going on here.
data: *$crate::_private::ConstPtrDeref::<[$crate::_private::u8; __TEXT.len()]> {
p: __TEXT.as_ptr(),
}
.a,
}
};
const S: $crate::ArcStr = unsafe { $crate::ArcStr::_private_new_from_static_data(SI) };
S
}
}};
}
/// Conceptually equivalent to `ArcStr::from(format!("...", args...))`.
///
/// Currently, the only difference here is that when used with no formatting
/// args, this behaves equivalently to [`arcstr::literal!`](crate::literal).
///
/// In the future, this will be implemented in such a way to avoid an additional
/// string copy which is required by the `from` operation.
///
/// # Example
///
/// ```
/// let arcstr = arcstr::format!("testing {}", 123);
/// assert_eq!(arcstr, "testing 123");
/// ```
#[macro_export]
macro_rules! format {
($text:expr $(,)?) => {
// prevent use as const, but keep cheap.
$crate::ArcStr::from($crate::literal!($text))
};
($text:expr, $($toks:tt)+) => {
$crate::ArcStr::from($crate::alloc::fmt::format($crate::core::format_args!($text, $($toks)+)))
};
}
/// `feature = "substr"`: Create a `const` [`Substr`][crate::Substr].
///
/// This is a wrapper that initializes a `Substr` over the entire contents of a
/// `const` [`ArcStr`](crate::ArcStr) made using [arcstr::literal!](crate::literal).
///
/// As with `arcstr::literal`, these require no heap allocation, can be freely
/// cloned and used interchangeably with `ArcStr`s from the heap, and are
/// effectively "free".
///
/// The main use case here is in applications where `Substr` is a much more
/// common string type than `ArcStr`.
///
/// # Examples
///
/// ```
/// use arcstr::{Substr, literal_substr};
/// // Works in const:
/// const EXAMPLE_SUBSTR: Substr = literal_substr!("testing testing");
/// assert_eq!(EXAMPLE_SUBSTR, "testing testing");
///
/// // Or, just in normal expressions.
/// assert_eq!("Wow!", literal_substr!("Wow!"));
/// ```
#[macro_export]
#[cfg(feature = "substr")]
macro_rules! literal_substr {
($text:expr) => {{
const __S: &$crate::_private::str = $text;
{
const PARENT: $crate::ArcStr = $crate::literal!(__S);
const SUBSTR: $crate::Substr =
unsafe { $crate::Substr::from_parts_unchecked(PARENT, 0..__S.len()) };
SUBSTR
}
}};
}
#[cfg(test)]
mod test {
#[test]
fn ensure_no_import() {
let v = literal!("foo");
assert_eq!(v, "foo");
#[cfg(feature = "substr")]
{
let substr = literal_substr!("bar");
assert_eq!(substr, "bar");
}
// Loom doesn't like it if you do things outside `loom::model`, AFAICT.
// These calls produce error messages from inside `libstd` about
// accessing thread_locals that haven't been initialized.
#[cfg(not(loom))]
{
let test = crate::format!("foo");
assert_eq!(test, "foo");
let test2 = crate::format!("foo {}", 123);
assert_eq!(test2, "foo 123");
}
}
}