2.6 - שונות וסמני טיפוס בתכנון מצבים - פתרון
פתרון מעבר מצב שצורך את הקודם¶
הערך נשאר מספר רגיל בזיכרון, אבל סוג המעטפת קובע אילו פעולות זמינות. שגיאה אינה מחזירה Config מאומתת.
use std::marker::PhantomData;
struct Unchecked;
struct Checked;
struct Config<State> { limit: usize, state: PhantomData<State> }
impl Config<Unchecked> {
fn new(limit: usize) -> Self { Self { limit, state: PhantomData } }
fn validate(self) -> Result<Config<Checked>, &'static str> {
if !(1..=1024).contains(&self.limit) { return Err("invalid limit"); }
Ok(Config { limit: self.limit, state: PhantomData })
}
}
impl Config<Checked> {
fn limit(&self) -> usize { self.limit }
}
fn main() {
match Config::new(64).validate() {
Ok(config) => assert_eq!(config.limit(), 64),
Err(error) => panic!("unexpected: {error}"),
}
assert!(Config::new(0).validate().is_err());
}
הקריאה Config::new(64).limit() מיועדת להיכשל בבדיקה נפרדת, משום שהמתודה אינה מוגדרת עבור Unchecked. המצב Checked מעיד שהערך עבר את בדיקת הטווח שלנו, ולא שהמערכת יכולה לספק בכל רגע כמות כזאת של משאבים. בקשת הקצאה עדיין יכולה להיכשל ותדרוש טיפול מתאים.