String Parsing
Collect Unicode Graphemes
Collect individual Unicode graphemes from UTF-8 string using the
UnicodeSegmentation::graphemes function from the unicode-segmentation crate.
use unicode_segmentation::UnicodeSegmentation;
fn main() {
let name = "José Guimarães\r\n";
let graphemes = UnicodeSegmentation::graphemes(name, true)
.collect::<Vec<&str>>();
assert_eq!(graphemes[3], "é");
}
Implement the FromStr trait for a custom struct
Creates a custom struct RGB and implements the FromStr trait to convert a provided color hex code into its RGB color code.
use std::str::FromStr;
#[derive(Debug, PartialEq)]
struct RGB {
r: u8,
g: u8,
b: u8,
}
impl FromStr for RGB {
type Err = std::num::ParseIntError;
// Parses a color hex code of the form '#rRgGbB..' into an
// instance of 'RGB'
fn from_str(hex_code: &str) -> Result<Self, Self::Err> {
// u8::from_str_radix(src: &str, radix: u32) converts a string
// slice in a given base to u8
let r: u8 = u8::from_str_radix(&hex_code[1..3], 16)?;
let g: u8 = u8::from_str_radix(&hex_code[3..5], 16)?;
let b: u8 = u8::from_str_radix(&hex_code[5..7], 16)?;
Ok(RGB { r, g, b })
}
}
fn main() {
let code: &str = &r"#fa7268";
match RGB::from_str(code) {
Ok(rgb) => {
println!(
r"The RGB color code is: R: {} G: {} B: {}",
rgb.r, rgb.g, rgb.b
);
}
Err(_) => {
println!("{} is not a valid color hex code!", code);
}
}
// test whether from_str performs as expected
assert_eq!(
RGB::from_str(&r"#fa7268").unwrap(),
RGB {
r: 250,
g: 114,
b: 104
}
);
}
Implement Debug, Display, and Hash for a custom type
Manually implements the Debug and Display traits for a custom
struct with mixed field types, and derives Hash for it. A manual
Debug implementation is useful when the default output produced by
#[derive(Debug)] isn’t quite what’s needed; Formatter::debug_struct
builds output in that same Field { .. } style without having to format
the fields by hand.
use std::collections::hash_map::DefaultHasher;
use std::fmt;
use std::hash::{Hash, Hasher};
#[derive(Hash)]
struct Package {
name: String,
version: (u8, u8, u8),
downloads: u64,
}
impl fmt::Debug for Package {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Package")
.field("name", &self.name)
.field("version", &self.version)
.field("downloads", &self.downloads)
.finish()
}
}
impl fmt::Display for Package {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let (major, minor, patch) = self.version;
write!(
f,
"{} v{}.{}.{} ({} downloads)",
self.name, major, minor, patch, self.downloads
)
}
}
fn main() {
let package = Package {
name: "rust-cookbook".to_string(),
version: (1, 0, 0),
downloads: 42_017,
};
println!("Debug: {:?}", package);
println!("Display: {}", package);
let mut hasher = DefaultHasher::new();
package.hash(&mut hasher);
println!("Hash: {:x}", hasher.finish());
}