برنامه نویسی

برنامه نویسی پیشرفته 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 را در پروژه‌های خود بیشتر مفید دانسته‌اید؟


برچسب‌ها: #زنگ #برنامه_نویسی #سیستم-برنامه_نویسی #همزمان #حافظه-ایمنی

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا