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 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
//! Stringing things along
//!
//! - **Date:** April 24, 2016
//! - **Subject:** `Strings` `&str`s and `Vec`s and slices (and Unicode) --
//! oh, my!
//! - [**Audio**][mp3]
//!
//! [mp3]: https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e014.mp3
//!
//! <audio style="width: 100%" title="e014: Stringing things along" controls preload=metadata><source src="https://www.podtrac.com/pts/redirect.mp3/cdn.newrustacean.com/file/newrustacean/e014.mp3"></audio>
//!
//!
//! Notes
//! -----
//!
//! This episode, I take a deep dive on strings in Rust, looking at the
//! differences between `String` and `&str`, discussing Unicode a bit, and then
//! expanding the discussion to think about how these types relate to the types
//! they're built on (like `Vec`).
//!
//! ### Corrigenda
//!
//! Listener Nev pointed out to me that I got it wrong when describing how
//! `&str` data is stored. It is *not* stack-allocated, but rather goes in the
//! [data segment]. I should have said *statically*-allocated, not
//! *stack*-allocated. Thanks to Nev for the correction!
//!
//! [data segment]: https://en.wikipedia.org/wiki/Data_segment
//!
//!
//! Links
//! -----
//!
//! - Strings:
//! + [The Rust Book]
//! + [Rust by Example]
//! + `str` docs:
//! * [module][strmod]
//! * [primitive type]
//! + `String`
//! * [module][stringmod]
//! * [type definition]
//! - Dereferencing
//! + [coercions]
//! + [`std::ops::Deref`]
//!
//! [The Rust Book]: https://doc.rust-lang.org/book/strings.html
//! [Rust by Example]: http://rustbyexample.com/std/str.html
//! [strmod]: http://doc.rust-lang.org/std/str/
//! [primitive type]: http://doc.rust-lang.org/std/primitive.str.html
//! [stringmod]: http://doc.rust-lang.org/std/string/index.html
//! [type definition]: http://doc.rust-lang.org/std/string/struct.String.html
//! [coercions]: http://doc.rust-lang.org/book/deref-coercions.html
//! [`std::ops::Deref`]: http://doc.rust-lang.org/std/ops/trait.Deref.html
//!
//! Sponsors
//! --------
//!
//! - Aleksey Pirogov
//! - [Chris Palmer]
//! - [Derek Morr]
//! - Hamza Sheikh
//! - Lachlan Collins
//! - Leif Arne Storset
//! - Luca Schmid
//! - Micael Bergeron
//! - [Pascal Hertleif]
//! - Ralph Giles ("rillian")
//! - Ralph "FriarTech" Loizzo
//! - reddraggone9
//! - Ryan Ollos
//! - Vesa Kaihlavirta
//! - [William Roe]
//!
//! [Chris Palmer]: http://red-oxide.org/
//! [Derek Morr]: https://twitter.com/derekmorr
//! [Pascal Hertleif]: https://pascalhertleif.de/
//! [William Roe]: http://willroe.me
//!
//! (Thanks to the couple people donating who opted out of the reward tier, as
//! well. You know who you are!)
//!
//! ### Become a sponsor
//!
//! - <a href="https://www.patreon.com/newrustacean" rel="payment">Patreon</a>
//! - [Venmo](https://venmo.com/chriskrycho)
//! - [Dwolla](https://www.dwolla.com/hub/chriskrycho)
//! - [Cash.me](https://cash.me/$chriskrycho)
//! - [Flattr](https://flattr.com/profile/chriskrycho)
//!
//!
//! Contact
//! -------
//!
//! - New Rustacean:
//! + Twitter: [@newrustacean](https://www.twitter.com/newrustacean)
//! + Email: [hello@newrustacean.com](mailto:hello@newrustacean.com)
//! - Chris Krycho
//! + GitHub: [chriskrycho](https://github.com/chriskrycho)
//! + Twitter: [@chriskrycho](https://www.twitter.com/chriskrycho)
/// Get a string *slice*. Note the required lifetime specifier on the type!
///
/// String slices are pointers to a given chunk of data.
pub fn get_a_slice() -> &'static str {
"this is a statically allocated slice"
}
/// Get a `String` instance. Note there's no lifetime.
pub fn get_a_string() -> String {
let mut a_string = String::new();
a_string += "this is a heap-allocated String";
a_string
}
/// It's easy enough to get a `String` from a `str`.
pub fn show_from_behavior() -> String {
String::from("any old slice will do")
}
/// Print a 🚀, just because we can.
pub fn demonstrate_unicode() {
println!("🚀");
}
pub fn get_back_some_unicode(desc: &str) -> String {
match desc {
"rocket" => "🚀".to_string(),
"hearts" => "💕".to_string(),
_ => " ".to_string(),
}
}
/// Get a `String` with a specified capacity.
///
/// Strings are heap-allocated, so we can simply build them to hold a certain
/// number of characters by default if we know how big they are, allowing them
/// to expand later *if necessary*.
pub fn get_a_string_with_capacity(capacity: usize) -> String {
let mut string = String::with_capacity(capacity);
string += "few";
string
}
/// Demonstrate dereferencing. (You'll want to read this example carefully.)
///
/// Note that here we have two types which are empty of values, which makes the
/// dereferencing operation quite straightforward. If the types had contents,
/// this would be a bit more involved!
///
/// Note as well that the dereference in this case recurses. This is a
/// consequence of having the empty types---so it's not exactly recommended to
/// do this in that case! (In fact, it's *usually*, though not always, pointless
/// to do that.)
pub mod demo_deref {
use std::ops::Deref;
/// A no-content struct to serve as the type to dereference from.
pub struct Origin;
/// A no-content struct to serve as the target to dereference to.
pub struct DerefTarget;
impl Deref for Origin {
type Target = DerefTarget;
// This is broken: that is the *point*.
#[allow(unconditional_recursion)]
fn deref(&self) -> &DerefTarget {
self
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn show_string_capacity() {
let capacity: usize = 4;
let mut the_str = get_a_string_with_capacity(capacity);
assert_eq!(the_str.capacity(), capacity);
the_str += "this is more than 4";
assert!(the_str.capacity() > capacity);
}
}