-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathcow.rs
More file actions
102 lines (90 loc) · 3.68 KB
/
Copy pathcow.rs
File metadata and controls
102 lines (90 loc) · 3.68 KB
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
//! # Cow (Clone on Write)
//!
//! Cow is a smart pointer that can be used to clone data only when necessary.
//! It is useful when you want to avoid unnecessary cloning of data,
//! especially when the data is large and expensive to clone.
//!
//! Cow can be used in situations where you want to share data between multiple
//! parts of your code without having to worry about ownership and borrowing
//! rules.
//!
//! Cow has 2 variants:
//!
//! - `Borrowed`: This variant holds a reference to the data. It does not own the data and does not clone it.
//! - `Owned`: This variant holds the owned data. It clones the data when it is created and owns it.
//!
//! ## When to use `Cow`?
//!
//! You generally use `Cow` when you want to write a function that:
//! - mainly reads data without modifying it.
//! - may need to modify the data, but only if certain conditions are met
//! (e.g., if the data contains whitespace that needs to be removed).
//! - when you want to accept both owned and borrowed data as input to a function,
//! and you want to avoid unnecessary cloning of data.
//!
//! ## When not to use `Cow`?
//! You should avoid using `Cow` when you always need to modify the data,
//! as it will always require cloning, which defeats the purpose of using `Cow`.
//! If you still use `Cow` in such cases, it may lead to unnecessary cloning and
//! performance overhead, as the data will always be cloned regardless of
//! whether it is needed or not.
//!
//! Ref: <https://doc.rust-lang.org/std/borrow/enum.Cow.html>
use std::borrow::Cow;
/// Sanitize String
///
/// The following example demonstrates a function to remove whitespace from a
/// string.
///
/// If the input string contains whitespace, we create an owned `Cow` variant by
/// replacing the whitespace with an empty string. If the input string does not
/// contain whitespace, we can simply return a borrowed `Cow` variant without
/// cloning the data. This approach allows us to avoid unnecessary cloning of
/// the string when it is not needed, while still providing the flexibility to
/// modify the string when necessary.
fn sanitize_string(data: &str) -> Cow<'_, str> {
if data.contains(' ') {
// only own the data when the data contains whitespaces.
Cow::Owned(data.replace(" ", ""))
} else {
// If no modification is needed, we can just borrow the data without cloning it.
Cow::Borrowed(data)
}
}
fn main() {
let input_1 = "Hello World";
let input_2 = "HelloWorld";
let output_1 = sanitize_string(input_1);
let output_2 = sanitize_string(input_2);
// here, `Cow` creates an owned variant and clones the data since it needs
// modification, hence input 1 and output 1 has different memory location.
println!("Input 1: '{}', Output 1: '{}'", input_1, output_1);
println!(
"address of Input 1: '{:p}', Output 1: '{:p}'",
input_1.as_ptr(),
output_1.as_ptr()
);
// here, cow borrows immutable reference since it does not contain any
// whitespace, hence input 2 and output 2 has same memory location
println!("Input 2: '{}', Output 2: '{}'", input_2, output_2);
println!(
"address of Input 2: '{:p}', Output 2: '{:p}'",
input_2.as_ptr(),
output_2.as_ptr()
);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_sanitize() {
let input_1 = "Hello World";
let input_2 = "HelloWorld";
let output_1 = sanitize_string(input_1);
let output_2 = sanitize_string(input_2);
assert_eq!(output_1, "HelloWorld");
assert_eq!(output_2, "HelloWorld");
assert_ne!(input_1.as_ptr(), output_1.as_ptr());
assert_eq!(input_2.as_ptr(), output_2.as_ptr());
}
}