Skip to content

Commit 3fe1476

Browse files
Add separate slide on API surface dangers
1 parent 0745d65 commit 3fe1476

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,7 @@
436436
- [Newtype Pattern](idiomatic/leveraging-the-type-system/newtype-pattern.md)
437437
- [Semantic Confusion](idiomatic/leveraging-the-type-system/newtype-pattern/semantic-confusion.md)
438438
- [Parse, Don't Validate](idiomatic/leveraging-the-type-system/newtype-pattern/parse-don-t-validate.md)
439+
- [Is It Encapsulated?](idiomatic/leveraging-the-type-system/newtype-pattern/is-it-encapsulated.md)
439440

440441
---
441442

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
---
2+
minutes: 5
3+
---
4+
5+
# Is It Truly Encapsulated?
6+
7+
You must evaluate the entire API surface exposed by a newtype to determine if
8+
invariants are indeed bullet-proof. It is crucial to consider all possible
9+
interactions, including trait implementations, that may allow users to bypass
10+
validation checks.
11+
12+
```rust
13+
pub struct Username(String);
14+
15+
impl Username {
16+
pub fn new(username: String) -> Result<Self, InvalidUsername> {
17+
// Validation checks...
18+
Ok(Self(username))
19+
}
20+
}
21+
22+
impl DerefMut for Username {
23+
fn deref_mut(&mut self) -> &mut Self::Target {
24+
&mut self.0
25+
}
26+
}
27+
# impl Deref for Username {
28+
# type Target = str;
29+
#
30+
# fn deref(&self) -> &Self::Target {
31+
# &self.0
32+
# }
33+
# }
34+
# pub struct InvalidUsername;
35+
```
36+
37+
<details>
38+
39+
- `DerefMut` allows users to get a mutable reference to the wrapped type.
40+
41+
The mutable reference can be used to modify the underlying data in ways that
42+
may violate the invariants enforced by `Username::new`!
43+
44+
- When auditing the API surface of a newtype, you can narrow down the review
45+
scope to methods and traits that provide mutable access to the underlying
46+
data.
47+
48+
- Remind students of privacy boundaries.
49+
50+
In particular, functions and methods defined in the same module of the newtype
51+
can access its underlying data directly. If possible, move the newtype
52+
definition to its own separate module to reduce the scope of the audit.
53+
54+
</details>

0 commit comments

Comments
 (0)