You've already forked comprehensive-rust
mirror of
https://github.com/google/comprehensive-rust.git
synced 2025-07-14 18:14:29 +02:00
Add separate slide on API surface dangers
This commit is contained in:
@ -436,6 +436,7 @@
|
|||||||
- [Newtype Pattern](idiomatic/leveraging-the-type-system/newtype-pattern.md)
|
- [Newtype Pattern](idiomatic/leveraging-the-type-system/newtype-pattern.md)
|
||||||
- [Semantic Confusion](idiomatic/leveraging-the-type-system/newtype-pattern/semantic-confusion.md)
|
- [Semantic Confusion](idiomatic/leveraging-the-type-system/newtype-pattern/semantic-confusion.md)
|
||||||
- [Parse, Don't Validate](idiomatic/leveraging-the-type-system/newtype-pattern/parse-don-t-validate.md)
|
- [Parse, Don't Validate](idiomatic/leveraging-the-type-system/newtype-pattern/parse-don-t-validate.md)
|
||||||
|
- [Is It Encapsulated?](idiomatic/leveraging-the-type-system/newtype-pattern/is-it-encapsulated.md)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -0,0 +1,54 @@
|
|||||||
|
---
|
||||||
|
minutes: 5
|
||||||
|
---
|
||||||
|
|
||||||
|
# Is It Truly Encapsulated?
|
||||||
|
|
||||||
|
You must evaluate the entire API surface exposed by a newtype to determine if
|
||||||
|
invariants are indeed bullet-proof. It is crucial to consider all possible
|
||||||
|
interactions, including trait implementations, that may allow users to bypass
|
||||||
|
validation checks.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
pub struct Username(String);
|
||||||
|
|
||||||
|
impl Username {
|
||||||
|
pub fn new(username: String) -> Result<Self, InvalidUsername> {
|
||||||
|
// Validation checks...
|
||||||
|
Ok(Self(username))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DerefMut for Username {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# impl Deref for Username {
|
||||||
|
# type Target = str;
|
||||||
|
#
|
||||||
|
# fn deref(&self) -> &Self::Target {
|
||||||
|
# &self.0
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
# pub struct InvalidUsername;
|
||||||
|
```
|
||||||
|
|
||||||
|
<details>
|
||||||
|
|
||||||
|
- `DerefMut` allows users to get a mutable reference to the wrapped type.
|
||||||
|
|
||||||
|
The mutable reference can be used to modify the underlying data in ways that
|
||||||
|
may violate the invariants enforced by `Username::new`!
|
||||||
|
|
||||||
|
- When auditing the API surface of a newtype, you can narrow down the review
|
||||||
|
scope to methods and traits that provide mutable access to the underlying
|
||||||
|
data.
|
||||||
|
|
||||||
|
- Remind students of privacy boundaries.
|
||||||
|
|
||||||
|
In particular, functions and methods defined in the same module of the newtype
|
||||||
|
can access its underlying data directly. If possible, move the newtype
|
||||||
|
definition to its own separate module to reduce the scope of the audit.
|
||||||
|
|
||||||
|
</details>
|
Reference in New Issue
Block a user