unsafe Rust का इस्तेमाल करके एक डबली लिंक्ड लिस्ट लिखिए, जिसमें लिस्ट पर इटरेशन करने वाला एक इटरेटर और कुशल बदलाव के लिए एक कर्सर भी शामिल हो।
डबली लिंक्ड लिस्ट कंप्यूटर साइंस की एक बुनियादी डेटा स्ट्रक्चर है।
डबली लिंक्ड लिस्ट के हर नोड में डेटा होता है, और अगर अगला तथा पिछला नोड मौजूद हों, तो उनके पॉइंटर भी होते हैं।
अगर किसी के पास पहले से उस जगह का रेफरेंस हो, तो लिस्ट में किसी भी जगह पर नए नोड कुशलता से जोड़े जा सकते हैं। इसी तरह, किसी दूसरी लिस्ट के सारे एलिमेंट लिस्ट में किसी भी जगह पर कॉन्स्टेंट टाइम में डाले जा सकते हैं।
Rust में लिंक्ड लिस्ट बहुत कम इस्तेमाल होती हैं, लेकिन जब नए लोग इसे बनाने की कोशिश करते हैं, तो कभी-कभी ये उन्हें उलझा देती हैं। अक्सर उन्हें अभी तक अनजान बॉरो चेकर के साथ काम करना उम्मीद से ज़्यादा मुश्किल लगता है।
unsafe के बारे में एक बातयाद रखिए, unsafe Rust का उद्देश्य ऐसे मामलों में सुरक्षित कोड लिखना है जहाँ कंपाइलर हमें सही होने की गारंटी देने में मदद नहीं कर सकता। हम जो सुरक्षित इंटरफेस बाहर दिखाते हैं, उनका इस्तेमाल करके किसी उपयोगकर्ता के लिए किसी भी तरह की मेमोरी असुरक्षा पैदा करना संभव नहीं होना चाहिए।
आपको जिन सुरक्षा-संबंधी इनवेरिएंट को बनाए रखना है, उनका दस्तावेज़ीकरण कीजिए, और हर unsafe ब्लॉक पर टिप्पणी कीजिए कि वह क्यों सुरक्षित है।
ऐसा हर फंक्शन, जहाँ कॉल करने वाले को सुरक्षा-संबंधी इनवेरिएंट बनाए रखने पड़ते हैं, unsafe चिह्नित किया जाना चाहिए। इसमें निजी फंक्शन भी शामिल हैं।
आगे और पीछे एलिमेंट जोड़ने और हटाने की सुविधा बनाइए (पुश करना और पॉप करना)। इतना ही काफी है कि इस लिस्ट को डबल-एंडेड क्यू की तरह इस्तेमाल किया जा सके। साथ ही len और is_empty फंक्शन भी बनाइए।
तैयार कोड में दोहराव कम से कम करने के लिए लिस्ट में सारे बदलाव कर्सर स्ट्रक्ट के ज़रिए ही होने चाहिए। LinkedList के push_* और pop_* मेथड, मॉड्यूल pre_implemented में दिए गए ज़रूरी कर्सर मेथड के आधार पर बनाए गए हैं। अगर आप चाहें, तो अभी के लिए Cursor स्ट्रक्ट छोड़ सकते हैं और इन मेथड को ओवरराइड कर सकते हैं, लेकिन अंत में कृपया उन्हें वापस पहले जैसा कर दीजिए।
Iter स्ट्रक्ट की मदद से लिस्ट पर आगे से पीछे तक इटरेशन की सुविधा बनाइए।
कर्सर की सुविधाएँ पूरी कीजिए। कर्सर किसी भी जगह पहुँच सके और वहाँ एलिमेंट जोड़ या हटा सके।
संसाधन साफ करने के लिए अपने LinkedList पर Drop ट्रेट लागू कीजिए।
इन अंतिम दो चीज़ों के टेस्ट, advanced फीचर फ्लैग के ज़रिए शर्त के साथ कंपाइल होते हैं। इन्हें चालू करने के लिए Cargo.toml फाइल में [features] के नीचे default = ["advanced"] की एंट्री जोड़िए।
अपनी स्ट्रक्चर के उपयोगकर्ताओं को अधिकतम लचीलापन देने के लिए यह सुनिश्चित कीजिए कि आपका LinkedList<T>, T पर कोवेरिएंट हो। इसका मतलब है, उदाहरण के लिए, कि एक LinkedList<&'static T> को LinkedList<&'a T> की तरह भी इस्तेमाल किया जा सकता है। Rust में वेरिएंस की समझ के लिए Rustonomicon देखिए।
यह सुनिश्चित कीजिए कि आपकी लिस्ट को थ्रेड की सीमाओं के आर-पार भेजना और साझा करना सुरक्षित है, और Send तथा Sync को खुद लागू करके यह बात टाइप सिस्टम को बताइए। ये ट्रेट आमतौर पर अपने आप बन जाते हैं, लेकिन रॉ पॉइंटर के इस्तेमाल की वजह से यहाँ वे अपने आप लागू नहीं होते। इनके महत्व की जानकारी के लिए Send और Sync का डॉक्यूमेंटेशन तथा इन पर Rustonomicon का अध्याय देखिए।