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.PlayerMoveis 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 aPlayerMovevalue.- الان زمان خوبی برای مقایسه ساختارها و
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); } }