एक प्रोजेक्ट में जहां कस्टम सर्डे (1.0) क्रमबद्धता और deserialization विधियां शामिल हैं, मैंने इस परीक्षण दिनचर्या पर भरोसा किया है कि यह जांचने के लिए कि किसी ऑब्जेक्ट को क्रमबद्ध करना और पीछे बराबर वस्तु उत्पन्न होगी या नहीं।सर्डे क्रमिकरण और deserialization की जांच के लिए हम एक सामान्य कार्य कैसे लिख सकते हैं?
// let o: T = ...;
let buf: Vec<u8> = to_vec(&o).unwrap();
let o2: T = from_slice(&buf).unwrap();
assert_eq!(o, o2);
इस इनलाइन को बहुत अच्छी तरह से काम करता है। पुन: प्रयोज्यता के लिए मेरा अगला कदम इस उद्देश्य के लिए check_serde
फ़ंक्शन बनाना था।
pub fn check_serde<T>(o: T)
where
T: Debug + PartialEq<T> + Serialize + DeserializeOwned,
{
let buf: Vec<u8> = to_vec(&o).unwrap();
let o2: T = from_slice(&buf).unwrap();
assert_eq!(o, o2);
}
इस प्रकार के मालिक के लिए अच्छी तरह से काम करता है, लेकिन जीवन सीमा के साथ प्रकार के लिए नहीं (Playground):
check_serde(5);
check_serde(vec![1, 2, 5]);
check_serde("five".to_string());
check_serde("wait"); // [E0279]
त्रुटि:
error[E0279]: the requirement `for<'de> 'de : ` is not satisfied (`expected bound lifetime parameter 'de, found concrete lifetime`)
--> src/main.rs:24:5
|
24 | check_serde("wait"); // [E0277]
| ^^^^^^^^^^^
|
= note: required because of the requirements on the impl of `for<'de> serde::Deserialize<'de>` for `&str`
= note: required because of the requirements on the impl of `serde::de::DeserializeOwned` for `&str`
= note: required by `check_serde`
मैं समारोह काम करना चाहते हैं के रूप में इन मामलों के साथ (स्ट्रिंग स्लाइस के साथ structs सहित), मैंने एक स्पष्ट वस्तु deserialization जीवनकाल के साथ एक नया संस्करण का प्रयास किया:
pub fn check_serde<'a, T>(o: &'a T)
where
T: Debug + PartialEq<T> + Serialize + Deserialize<'a>,
{
let buf: Vec<u8> = to_vec(o).unwrap();
let o2: T = from_slice(&buf).unwrap();
assert_eq!(o, &o2);
}
check_serde(&5);
check_serde(&vec![1, 2, 5]);
check_serde(&"five".to_string());
check_serde(&"wait"); // [E0405]
यह कार्यान्वयन एक और मुद्दा की ओर जाता है, और यह संकलित नहीं होगा (Playground)।
error[E0597]: `buf` does not live long enough
--> src/main.rs:14:29
|
14 | let o2: T = from_slice(&buf).unwrap();
| ^^^ does not live long enough
15 | assert_eq!(o, &o2);
16 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 10:1...
--> src/main.rs:10:1
|
10 |/pub fn check_serde<'a, T>(o: &'a T)
11 | | where T: Debug + PartialEq<T> + Serialize + Deserialize<'a>
12 | | {
13 | | let buf: Vec<u8> = to_vec(o).unwrap();
14 | | let o2: T = from_slice(&buf).unwrap();
15 | | assert_eq!(o, &o2);
16 | | }
| |_^
मैं पहले से ही इस एक की उम्मीद है: इस संस्करण का तात्पर्य है कि धारावाहिक सामग्री (और इसलिए deserialized वस्तु) के रूप में लंबे समय तक रहता है इनपुट वस्तु है, जो सच नहीं है के रूप में। बफर केवल कार्य के दायरे तक जीने के लिए है।
मेरा तीसरा प्रयास मूल इनपुट के स्वामित्व वाले संस्करणों का निर्माण करना चाहता है, इस प्रकार विभिन्न आजीवन सीमाओं के साथ एक deserialized वस्तु होने के मुद्दे को बचाना। इस उपयोग मामले के अनुरूप ToOwned
विशेषता दिखाई देती है।
pub fn check_serde<'a, T: ?Sized>(o: &'a T)
where
T: Debug + ToOwned + PartialEq<<T as ToOwned>::Owned> + Serialize,
<T as ToOwned>::Owned: Debug + DeserializeOwned,
{
let buf: Vec<u8> = to_vec(&o).unwrap();
let o2: T::Owned = from_slice(&buf).unwrap();
assert_eq!(o, &o2);
}
यह अब सादे स्ट्रिंग स्लाइस के लिए समारोह काम करता है, लेकिन समग्र वस्तुओं के लिए उन्हें शामिल नहीं (Playground):
check_serde(&5);
check_serde(&vec![1, 2, 5]);
check_serde(&"five".to_string());
check_serde("wait");
check_serde(&("There's more!", 36)); // [E0279]
फिर, हम पहले संस्करण के रूप में ही त्रुटि प्रकार पर आते हैं:
error[E0279]: the requirement `for<'de> 'de : ` is not satisfied (`expected bound lifetime parameter 'de, found concrete lifetime`)
--> src/main.rs:25:5
|
25 | check_serde(&("There's more!", 36)); // [E0279]
| ^^^^^^^^^^^
|
= note: required because of the requirements on the impl of `for<'de> serde::Deserialize<'de>` for `&str`
= note: required because of the requirements on the impl of `for<'de> serde::Deserialize<'de>` for `(&str, {integer})`
= note: required because of the requirements on the impl of `serde::de::DeserializeOwned` for `(&str, {integer})`
= note: required by `check_serde`
अनुमोदित, मुझे नुकसान हुआ है। हम एक जेनेरिक फ़ंक्शन कैसे बना सकते हैं, जो सेर्डे का उपयोग करते हुए, किसी ऑब्जेक्ट को क्रमबद्ध करता है और उसे वापस एक नई वस्तु में deserializes? विशेष रूप से, क्या यह कार्य जंग (स्थिर या रात में) में किया जा सकता है, और यदि हां, तो मेरे कार्यान्वयन में कौन से समायोजन गुम हैं?