برنامه نویسی پیشرفته Rust: از صفر تا قهرمان

مقدمه
Rust با ترکیب کنترل سطح پایین با انتزاعات سطح بالا انقلابی در برنامه نویسی سیستم ها ایجاد کرده است. در این راهنمای جامع، ما مفاهیم پیشرفته Rust را بررسی خواهیم کرد که مهارت های برنامه نویسی شما را به سطح بعدی ارتقا می دهد.
1. الگوهای مالکیت پیشرفته
اشاره گرهای هوشمند و انواع مرجع سفارشی
بیایید به پیاده سازی اشاره گرهای هوشمند سفارشی بپردازیم:
use std::ops::{Deref, DerefMut};
struct SmartPointer<T> {
value: T,
access_count: usize,
}
impl<T> SmartPointer<T> {
fn new(value: T) -> Self {
SmartPointer {
value,
access_count: 0,
}
}
fn access_count(&self) -> usize {
self.access_count
}
}
impl<T> Deref for SmartPointer<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.access_count += 1;
&self.value
}
}
impl<T> DerefMut for SmartPointer<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.access_count += 1;
&mut self.value
}
}
تجزیه صفر کپی با مدیریت مادام العمر
در اینجا یک مثال از تجزیه رشته کارآمد بدون تخصیص آورده شده است:
#[derive(Debug)]
struct Parser<'a> {
input: &'a str,
position: usize,
}
impl<'a> Parser<'a> {
fn new(input: &'a str) -> Self {
Parser {
input,
position: 0,
}
}
fn parse_until(&mut self, delimiter: char) -> Option<&'a str> {
let rest = &self.input[self.position..];
if let Some(index) = rest.find(delimiter) {
let result = &rest[..index];
self.position += index + 1;
Some(result)
} else {
None
}
}
}
2. الگوهای صفت پیشرفته
انواع مرتبط و صفات ژنریک
درک روابط پیچیده صفت:
trait Container {
type Item;
fn add(&mut self, item: Self::Item);
fn remove(&mut self) -> Option<Self::Item>;
fn is_empty(&self) -> bool;
}
trait ProcessableContainer: Container {
fn process_all<F>(&mut self, f: F)
where
F: FnMut(Self::Item) -> Self::Item;
}
struct Stack<T> {
items: Vec<T>,
}
impl<T> Container for Stack<T> {
type Item = T;
fn add(&mut self, item: Self::Item) {
self.items.push(item);
}
fn remove(&mut self) -> Option<Self::Item> {
self.items.pop()
}
fn is_empty(&self) -> bool {
self.items.is_empty()
}
}
impl<T> ProcessableContainer for Stack<T> {
fn process_all<F>(&mut self, mut f: F)
where
F: FnMut(Self::Item) -> Self::Item,
{
self.items = self.items
.drain(..)
.map(|item| f(item))
.collect();
}
}
3. همزمانی پیشرفته
الگوهای همگام/انتظار
برنامه نویسی ناهمزمان مدرن در Rust:
use tokio;
use std::time::Duration;
#[derive(Debug)]
struct AsyncProcessor {
name: String,
delay: Duration,
}
impl AsyncProcessor {
async fn process(&self, data: String) -> Result<String, Box<dyn std::error::Error>> {
println!("Processing started by {}", self.name);
tokio::time::sleep(self.delay).await;
Ok(format!("Processed by {}: {}", self.name, data))
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let processors = vec![
AsyncProcessor {
name: "Processor 1".to_string(),
delay: Duration::from_secs(1),
},
AsyncProcessor {
name: "Processor 2".to_string(),
delay: Duration::from_secs(2),
},
];
let mut handles = Vec::new();
for processor in processors {
let handle = tokio::spawn(async move {
processor.process("test data".to_string()).await
});
handles.push(handle);
}
for handle in handles {
match handle.await? {
Ok(result) => println!("Result: {}", result),
Err(e) => eprintln!("Error: {}", e),
}
}
Ok(())
}
4. مدیریت خطای پیشرفته
انواع خطاهای سفارشی
ایجاد انواع خطاهای غنی با مدیریت صحیح خطا:
use std::fmt;
use std::error::Error;
#[derive(Debug)]
enum CustomError {
IoError(std::io::Error),
ParseError { line: usize, column: usize },
ValidationError(String),
}
impl fmt::Display for CustomError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
CustomError::IoError(err) => write!(f, "IO error: {}", err),
CustomError::ParseError { line, column } => {
write!(f, "Parse error at line {}, column {}", line, column)
}
CustomError::ValidationError(msg) => write!(f, "Validation error: {}", msg),
}
}
}
impl Error for CustomError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
CustomError::IoError(err) => Some(err),
_ => None,
}
}
}
impl From<std::io::Error> for CustomError {
fn from(err: std::io::Error) -> CustomError {
CustomError::IoError(err)
}
}
5. زنگ ناامن و FFI
انتزاعات ایمن نسبت به کد ناامن
کار با کد ناامن به صورت ایمن:
use std::ptr::NonNull;
use std::alloc::{alloc, dealloc, Layout};
pub struct CustomVec<T> {
ptr: NonNull<T>,
len: usize,
capacity: usize,
}
impl<T> CustomVec<T> {
pub fn new() -> Self {
CustomVec {
ptr: NonNull::dangling(),
len: 0,
capacity: 0,
}
}
pub fn push(&mut self, item: T) {
if self.len == self.capacity {
self.grow();
}
unsafe {
std::ptr::write(self.ptr.as_ptr().add(self.len), item);
}
self.len += 1;
}
fn grow(&mut self) {
let new_capacity = if self.capacity == 0 { 1 } else { self.capacity * 2 };
let layout = Layout::array::<T>(new_capacity).unwrap();
unsafe {
let new_ptr = NonNull::new(alloc(layout) as *mut T)
.expect("Allocation failed");
if self.len > 0 {
std::ptr::copy_nonoverlapping(
self.ptr.as_ptr(),
new_ptr.as_ptr(),
self.len,
);
dealloc(
self.ptr.as_ptr() as *mut u8,
Layout::array::<T>(self.capacity).unwrap(),
);
}
self.ptr = new_ptr;
self.capacity = new_capacity;
}
}
}
impl<T> Drop for CustomVec<T> {
fn drop(&mut self) {
if self.capacity > 0 {
unsafe {
for i in 0..self.len {
std::ptr::drop_in_place(self.ptr.as_ptr().add(i));
}
dealloc(
self.ptr.as_ptr() as *mut u8,
Layout::array::<T>(self.capacity).unwrap(),
);
}
}
}
}
6. تست و محک گذاری پیشرفته
تست بر اساس اموال
استفاده از QuickCheck برای تست قوی:
use quickcheck::{quickcheck, TestResult};
#[derive(Clone, Debug)]
struct SortedVec<T: Ord>(Vec<T>);
impl<T: Ord> SortedVec<T> {
fn new() -> Self {
SortedVec(Vec::new())
}
fn insert(&mut self, value: T) {
let pos = self.0.binary_search(&value).unwrap_or_else(|p| p);
self.0.insert(pos, value);
}
fn is_sorted(&self) -> bool {
self.0.windows(2).all(|w| w[0] <= w[1])
}
}
quickcheck! {
fn prop_always_sorted(xs: Vec<i32>) -> TestResult {
let mut sorted = SortedVec::new();
for x in xs {
sorted.insert(x);
}
TestResult::from_bool(sorted.is_sorted())
}
}
نتیجه گیری
این الگوهای Rust پیشرفته ویژگیهای قدرتمند زبان را برای ساختن سیستمهای ایمن، همزمان و کارآمد به نمایش میگذارند. با تسلط بر این مفاهیم، برای نوشتن برنامه های Rust قوی که از پتانسیل کامل زبان استفاده می کنند، مجهزتر خواهید شد.
منابع اضافی
تجربیات خود را در مورد این الگوها در نظرات زیر به اشتراک بگذارید! چه ویژگیهای پیشرفته Rust را در پروژههای خود بیشتر مفید دانستهاید؟
برچسبها: #زنگ #برنامه_نویسی #سیستم-برنامه_نویسی #همزمان #حافظه-ایمنی