Enums
کلمه کلیدی enum
اجازه ایجاد نوع دادهای را می دهد که دارای چندین گونه مختلف است:
#[derive(Debug)] enum Direction { Left, Right, } #[derive(Debug)] enum PlayerMove { Pass, // Simple variant Run(Direction), // Tuple variant Teleport { x: u32, y: u32 }, // Struct variant } fn main() { let m: PlayerMove = PlayerMove::Run(Direction::Left); println!("در این پیچ: {:?}", m); }
نکات کلیدی:
Enum
ها به شما امکان می دهند مجموعهای از مقادیر مختلف با نوعهای مختلف را تحت یک نوع جمع آوری کنید.Direction
یک type با گونههای مختلف است. دو مقدارDirection
وجود دارد:Direction::Left
وDirection::Right
.PlayerMove
is a type with three variants. In addition to the payloads, Rust will store a discriminant so that it knows at runtime which variant is in aPlayerMove
value.- الان زمان خوبی برای مقایسه ساختارها و
Enum
هاست:- در هر دو، می توانید یک نسخه ساده بدون فیلد (unit struct) یا یکی با انواع مختلف فیلد (variant payloads) داشته باشید.
- شما حتی می توانید انواع مختلف یک
Enum
را با ساختارهای جداگانه پیاده سازی کنید، اما در آن صورت آنها از همان نوعی که در ابتدا تعریف کردید یعنیEnum
نخواهند بود.
- Rust از حداقل فضا برای ذخیرهسازی متمایزکننده (discriminant) استفاده میکند.
-
در صورت لزوم، یک عدد صحیح با کوچکترین اندازه مورد نیاز را ذخیره میکند
-
اگر مقادیر متغیر مجاز همه الگوهای bit را پوشش ندهند، از الگوهای bit نامعتبر برای رمزگذاری متمایز کننده (یک "niche optimization") استفاده میکند. برای مثال،
Option<&u8>
یک اشارهگر به یک عدد صحیح یاNULL
را برای نوعNone
ذخیره میکند. -
شما می توانید در صورت نیاز (به عنوان مثال، برای سازگاری با C) discriminant را کنترل کنید:
#[repr(u32)] enum Bar { A, // 0 B = 10000, C, // 10001 } fn main() { println!("A: {}", Bar::A as u32); println!("B: {}", Bar::B as u32); println!("C: {}", Bar::C as u32); }
بدون
repr
، نوع discriminant دو بایت حافظه اشغال میکند، زیرا 10001 در 2 بایت جا میشود.
-
برای کاوش بیشتر
زبان Rust دارای چندین بهینهسازی دارد که میتواند برای کاهش فضای اشغال شده توسطEnum
ها استفاده کند.
-
بهینهسازی اشارهگر
NULL
: برای برخی از انواع، Rust تضمین میکند کهsize_of::<T>()
برابر باsize_of::<Option<T>>()
است.کد نمونه, اگر میخواهید نشان دهید که نمایش بیت به بیت در عمل چگونه ممکن است به نظر برسد. مهم است توجه داشته باشید که کامپایلر هیچ تضمینی در مورد این نمایش نمیدهد، بنابراین این کاملاً ناایمن است.
use std::mem::transmute; macro_rules! dbg_bits { ($e:expr, $bit_type:ty) => { println!("- {}: {:#x}", stringify!($e), transmute::<_, $bit_type>($e)); }; } fn main() { unsafe { println!("bool:"); dbg_bits!(false, u8); dbg_bits!(true, u8); println!("Option<bool>:"); dbg_bits!(None::<bool>, u8); dbg_bits!(Some(false), u8); dbg_bits!(Some(true), u8); println!("Option<Option<bool>>:"); dbg_bits!(Some(Some(false)), u8); dbg_bits!(Some(Some(true)), u8); dbg_bits!(Some(None::<bool>), u8); dbg_bits!(None::<Option<bool>>, u8); println!("Option<&i32>:"); dbg_bits!(None::<&i32>, usize); dbg_bits!(Some(&0i32), usize); } }