bucky_raw_codec/protobuf/
protobuf_helper.rs

1use crate::*;
2
3use std::{convert::TryFrom, str::FromStr};
4use std::collections::HashMap;
5
6// 为了读取CodedOutputStream里面的position字段
7// TODO 确保protobuf的版本,如果此结构体发生变化,需要同步,否则会导致读取错误
8mod stream_pos_retreve_helper {
9    enum OutputTarget<'a> {
10        Write(&'a mut dyn std::io::Write, Vec<u8>),
11        Vec(&'a mut Vec<u8>),
12        Bytes,
13    }
14    /// Buffered write with handy utilities
15    pub struct CodedOutputStream<'a> {
16        target: OutputTarget<'a>,
17        // alias to buf from target
18        buffer: &'a mut [u8],
19        // within buffer
20        pub position: usize,
21    }
22}
23
24pub struct ProtobufMessageCodecHelper {}
25
26impl ProtobufMessageCodecHelper {
27    pub fn raw_measure(
28        value: impl ::protobuf::Message,
29        _purpose: &Option<RawEncodePurpose>,
30    ) -> CodecResult<usize> {
31        let size = value.compute_size() as usize;
32
33        Ok(size)
34    }
35
36    pub fn raw_encode<'a>(
37        value: impl ::protobuf::Message,
38        buf: &'a mut [u8],
39        _purpose: &Option<RawEncodePurpose>,
40    ) -> CodecResult<&'a mut [u8]> {
41        let size = value.compute_size() as usize;
42        let mut stream = ::protobuf::CodedOutputStream::bytes(buf);
43        value.write_to(&mut stream).map_err(|e| {
44            let msg = format!("encode protobuf::Message to stream error! {}", e);
45            error!("{}", msg);
46
47            CodecError::new(CodecErrorCode::OutOfLimit, msg)
48        })?;
49
50        //let stream_exposed: stream_pos_retreve_helper::CodedOutputStream =
51        //    unsafe { std::mem::transmute(stream) };
52
53        Ok(&mut buf[size..])
54    }
55
56    // 需要使用精确长度的buf来decode
57    pub fn raw_decode<'de, T>(buf: &'de [u8]) -> CodecResult<(T, &'de [u8])>
58    where
59        T: ::protobuf::Message,
60    {
61        // buffer的size就是整个body_content的长度
62        let size = buf.len();
63
64        // 必须截取精确大小的buffer
65        let mut stream = ::protobuf::CodedInputStream::from_bytes(buf);
66        let value = T::parse_from(&mut stream).map_err(|e| {
67            let msg = format!("decode protobuf::Message from stream error! {}", e);
68            error!("{}", msg);
69
70            CodecError::new(CodecErrorCode::InvalidFormat, msg)
71        })?;
72
73        assert_eq!(stream.pos() as usize, size);
74
75        Ok((value, &buf[size..]))
76    }
77}
78
79pub struct ProtobufCodecHelper {}
80
81impl ProtobufCodecHelper {
82    pub fn raw_measure<'a, T, P>(
83        value: &'a T,
84        purpose: &Option<RawEncodePurpose>,
85    ) -> CodecResult<usize>
86    where
87        P: TryFrom<&'a T>,
88        P: ::protobuf::Message,
89        <P as TryFrom<&'a T>>::Error: std::fmt::Display,
90    {
91        let value: P = P::try_from(value).map_err(|e: <P as TryFrom<&'a T>>::Error| {
92            let msg = format!("convert protobuf origin to protobuf::Message error! {}", e);
93            error!("{}", msg);
94
95            CodecError::new(CodecErrorCode::InvalidFormat, msg)
96        })?;
97
98        ProtobufMessageCodecHelper::raw_measure(value, purpose)
99    }
100
101    pub fn raw_encode<'a, 'b, T, P>(
102        value: &'b T,
103        buf: &'a mut [u8],
104        purpose: &Option<RawEncodePurpose>,
105    ) -> CodecResult<&'a mut [u8]>
106    where
107        P: TryFrom<&'b T>,
108        P: ::protobuf::Message,
109        <P as TryFrom<&'b T>>::Error: std::fmt::Display,
110    {
111        let value: P = P::try_from(value).map_err(|e: <P as TryFrom<&'b T>>::Error| {
112            let msg = format!("convert protobuf origin to protobuf::Message error! {}", e);
113            error!("{}", msg);
114
115            CodecError::new(CodecErrorCode::InvalidFormat, msg)
116        })?;
117
118        ProtobufMessageCodecHelper::raw_encode(value, buf, purpose)
119    }
120
121    pub fn raw_decode<'de, T, P>(buf: &'de [u8]) -> CodecResult<(T, &'de [u8])>
122    where
123        T: TryFrom<P>,
124        P: ::protobuf::Message,
125        <T as TryFrom<P>>::Error: std::fmt::Display,
126    {
127        let (msg, buf) = ProtobufMessageCodecHelper::raw_decode::<P>(buf)?;
128        let value: T = T::try_from(msg).map_err(|e: <T as TryFrom<P>>::Error| {
129            let msg = format!("convert protobuf message to type error! {}", e);
130            error!("{}", msg);
131
132            CodecError::new(CodecErrorCode::InvalidFormat, msg)
133        })?;
134
135        Ok((value, buf))
136    }
137
138    pub fn decode_buf<T>(buf: Vec<u8>) -> CodecResult<T>
139    where
140        T: for<'de> RawDecode<'de>,
141    {
142        let (item, _) = T::raw_decode(&buf)?;
143
144        Ok(item)
145    }
146
147    pub fn decode_string_list<T>(list: Vec<String>) -> CodecResult<Vec<T>>
148    where
149        T: FromStr,
150        <T as FromStr>::Err: std::fmt::Display,
151        CodecError: From<<T as FromStr>::Err>,
152    {
153        let mut result = Vec::with_capacity(list.len());
154        for s in list {
155            let item = T::from_str(&s)?;
156
157            result.push(item);
158        }
159
160        Ok(result)
161    }
162
163    pub fn encode_string_list<T>(list: &[T]) -> CodecResult<::protobuf::RepeatedField<String>>
164    where
165        T: ToString,
166    {
167        let mut result = Vec::with_capacity(list.len());
168        for item in list.iter() {
169            let buf = item.to_string();
170
171            result.push(buf);
172        }
173
174        Ok(result.into())
175    }
176
177    pub fn decode_buf_list<T>(list: impl Into<Vec<Vec<u8>>>) -> CodecResult<Vec<T>>
178    where
179        T: for<'de> RawDecode<'de>,
180    {
181        let list: Vec<Vec<u8>> = list.into();
182        let mut result = Vec::with_capacity(list.len());
183        for buf in list {
184            let (item, _) = T::raw_decode(&buf)?;
185
186            result.push(item);
187        }
188
189        Ok(result)
190    }
191
192    pub fn encode_buf_list<T>(list: &[T]) -> CodecResult<::protobuf::RepeatedField<Vec<u8>>>
193    where
194        T: RawEncode,
195    {
196        let mut result = Vec::with_capacity(list.len());
197        for item in list.iter() {
198            let buf = item.to_vec()?;
199
200            result.push(buf);
201        }
202
203        Ok(result.into())
204    }
205
206    // 解码嵌套Message结构
207    pub fn decode_nested_item<T, P>(item: P) -> CodecResult<T>
208    where
209        T: TryFrom<P>,
210        <T as TryFrom<P>>::Error: std::fmt::Display,
211        CodecError: From<<T as TryFrom<P>>::Error>,
212    {
213        let ret = T::try_from(item)?;
214
215        Ok(ret)
216    }
217
218    // 编码到嵌套的Message结构
219    pub fn encode_nested_item<'a, T, P>(item: &'a T) -> CodecResult<P>
220    where
221        P: TryFrom<&'a T>,
222        <P as TryFrom<&'a T>>::Error: std::fmt::Display,
223        CodecError: From<<P as TryFrom<&'a T>>::Error>,
224    {
225        let ret = P::try_from(item)?;
226
227        Ok(ret)
228    }
229
230    // 解码支持嵌套TryFrom的结构体数组
231    pub fn decode_nested_list<T, P>(list: impl Into<Vec<P>>) -> CodecResult<Vec<T>>
232    where
233        T: TryFrom<P>,
234        <T as TryFrom<P>>::Error: std::fmt::Display,
235        CodecError: From<<T as TryFrom<P>>::Error>,
236    {
237        let list: Vec<P> = list.into();
238        let mut result = Vec::with_capacity(list.len());
239        for v in list {
240            let item = T::try_from(v)?;
241
242            result.push(item);
243        }
244
245        Ok(result)
246    }
247
248    pub fn encode_nested_list<'a, T, P>(
249        list: &'a Vec<T>,
250    ) -> CodecResult<::protobuf::RepeatedField<P>>
251    where
252        T: 'a,
253        P: TryFrom<&'a T>,
254        <P as TryFrom<&'a T>>::Error: std::fmt::Display,
255        CodecError: From<<P as TryFrom<&'a T>>::Error>,
256    {
257        let mut result = Vec::with_capacity(list.len());
258        for v in list {
259            let item = P::try_from(v)?;
260
261            result.push(item);
262        }
263
264        Ok(result.into())
265    }
266
267    pub fn decode_value<T, P>(value: P) -> CodecResult<T>
268    where
269        T: TryFrom<P>,
270        <T as TryFrom<P>>::Error: std::fmt::Display,
271    {
272        T::try_from(value).map_err(|e| {
273            let msg = format!(
274                "decode value to target type failed! {} => {}, {}",
275                std::any::type_name::<P>(),
276                std::any::type_name::<T>(),
277                e
278            );
279
280            error!("{}", msg);
281            CodecError::new(CodecErrorCode::InvalidFormat, msg)
282        })
283    }
284
285    pub fn decode_value_list<T, P>(list: impl Into<Vec<P>>) -> CodecResult<Vec<T>>
286    where
287        T: TryFrom<P>,
288        <T as TryFrom<P>>::Error: std::fmt::Display,
289    {
290        let list = list.into();
291        let mut result = Vec::with_capacity(list.len());
292        for v in list {
293            let item = Self::decode_value(v)?;
294
295            result.push(item);
296        }
297
298        Ok(result)
299    }
300
301    pub fn decode_str_value<T>(value: &str) -> CodecResult<T>
302    where
303        T: FromStr,
304        <T as FromStr>::Err: std::fmt::Display,
305    {
306        T::from_str(value).map_err(|e| {
307            let msg = format!(
308                "decode string to target type failed! {} => {}, {}",
309                value,
310                std::any::type_name::<T>(),
311                e
312            );
313
314            error!("{}", msg);
315            CodecError::new(CodecErrorCode::InvalidFormat, msg)
316        })
317    }
318}
319
320pub trait ProtobufEncode {}
321pub trait ProtobufDecode {}
322
323pub trait ProtobufTransform<T>: Sized {
324    fn transform(value: T) -> CodecResult<Self>;
325}
326
327impl <T, U: ProtobufTransform<T>> ProtobufTransform<Vec<T>> for Vec<U> {
328    fn transform(value: Vec<T>) -> CodecResult<Self> {
329        let mut list = Vec::new();
330        for item in value.into_iter() {
331            list.push(ProtobufTransform::transform(item)?);
332        }
333        Ok(list)
334    }
335}
336
337impl <'a, T: 'a, U: ProtobufTransform<&'a T>> ProtobufTransform<&'a Vec<T>> for Vec<U> {
338    fn transform(value: &'a Vec<T>) -> CodecResult<Self> {
339        let mut list = Vec::new();
340        for item in value.into_iter() {
341            list.push(ProtobufTransform::transform(item)?);
342        }
343        Ok(list)
344    }
345}
346
347impl <K, T, Y: ProtobufTransform<K> + std::cmp::Eq + std::hash::Hash, U: ProtobufTransform<T>> ProtobufTransform<HashMap<K, T>> for HashMap<Y, U> {
348    fn transform(value: HashMap<K, T>) -> CodecResult<Self> {
349        let mut list = HashMap::new();
350        for (k, t) in value.into_iter() {
351            list.insert(ProtobufTransform::transform(k)?, ProtobufTransform::transform(t)?);
352        }
353        Ok(list)
354    }
355}
356
357impl <'a, K: 'a, T: 'a, Y: ProtobufTransform<&'a K> + std::cmp::Eq + std::hash::Hash, U: ProtobufTransform<&'a T>> ProtobufTransform<&'a HashMap<K, T>> for HashMap<Y, U> {
358    fn transform(value: &'a HashMap<K, T>) -> CodecResult<Self> {
359        let mut list = HashMap::new();
360        for (k, t) in value.into_iter() {
361            list.insert(ProtobufTransform::transform(k)?, ProtobufTransform::transform(t)?);
362        }
363        Ok(list)
364    }
365}
366
367impl<T, U: ProtobufTransform<T>> ProtobufTransform<Option<T>> for Option<U> {
368    fn transform(value: Option<T>) -> CodecResult<Self> {
369        match value {
370            Some(value) => Ok(Some(ProtobufTransform::transform(value)?)),
371            None => Ok(None)
372        }
373    }
374}
375
376impl<'a, T: 'a, U: ProtobufTransform<&'a T>> ProtobufTransform<&'a Option<T>> for Option<U> {
377    fn transform(value: &'a Option<T>) -> CodecResult<Self> {
378        match value {
379            Some(value) => Ok(Some(ProtobufTransform::transform(value)?)),
380            None => Ok(None)
381        }
382    }
383}
384
385impl ProtobufTransform<i32> for i8 {
386    fn transform(value: i32) -> CodecResult<Self> {
387        Ok(value as i8)
388    }
389}
390
391impl ProtobufTransform<i32> for u8 {
392    fn transform(value: i32) -> CodecResult<Self> {
393        Ok(value as u8)
394    }
395}
396
397impl ProtobufTransform<u32> for u8 {
398    fn transform(value: u32) -> CodecResult<Self> {
399        Ok(value as u8)
400    }
401}
402
403impl ProtobufTransform<i32> for i16 {
404    fn transform(value: i32) -> CodecResult<Self> {
405        Ok(value as i16)
406    }
407}
408
409impl ProtobufTransform<i32> for u16 {
410    fn transform(value: i32) -> CodecResult<Self> {
411        Ok(value as u16)
412    }
413}
414
415impl ProtobufTransform<u32> for u16 {
416    fn transform(value: u32) -> CodecResult<Self> {
417        Ok(value as u16)
418    }
419}
420
421impl ProtobufTransform<&i32> for i16 {
422    fn transform(value: &i32) -> CodecResult<Self> {
423        Ok(*value as i16)
424    }
425}
426
427impl ProtobufTransform<&u32> for u16 {
428    fn transform(value: &u32) -> CodecResult<Self> {
429        Ok(*value as u16)
430    }
431}
432
433impl ProtobufTransform<i32> for i32 {
434    fn transform(value: i32) -> CodecResult<Self> {
435        Ok(value)
436    }
437}
438
439impl ProtobufTransform<i8> for i32 {
440    fn transform(value: i8) -> CodecResult<Self> {
441        Ok(value as i32)
442    }
443}
444
445impl ProtobufTransform<u8> for i32 {
446    fn transform(value: u8) -> CodecResult<Self> {
447        Ok(value as i32)
448    }
449}
450
451impl ProtobufTransform<i16> for i32 {
452    fn transform(value: i16) -> CodecResult<Self> {
453        Ok(value as i32)
454    }
455}
456
457impl ProtobufTransform<u16> for i32 {
458    fn transform(value: u16) -> CodecResult<Self> {
459        Ok(value as i32)
460    }
461}
462
463impl ProtobufTransform<&i8> for i32 {
464    fn transform(value: &i8) -> CodecResult<Self> {
465        Ok(*value as i32)
466    }
467}
468
469impl ProtobufTransform<&i16> for i32 {
470    fn transform(value: &i16) -> CodecResult<Self> {
471        Ok(*value as i32)
472    }
473}
474
475impl ProtobufTransform<&u8> for i32 {
476    fn transform(value: &u8) -> CodecResult<Self> {
477        Ok(*value as i32)
478    }
479}
480
481impl ProtobufTransform<&u16> for i32 {
482    fn transform(value: &u16) -> CodecResult<Self> {
483        Ok(*value as i32)
484    }
485}
486
487impl ProtobufTransform<u32> for u32 {
488    fn transform(value: u32) -> CodecResult<Self> {
489        Ok(value)
490    }
491}
492
493impl ProtobufTransform<u8> for u32 {
494    fn transform(value: u8) -> CodecResult<Self> {
495        Ok(value as u32)
496    }
497}
498
499impl ProtobufTransform<u16> for u32 {
500    fn transform(value: u16) -> CodecResult<Self> {
501        Ok(value as u32)
502    }
503}
504
505impl ProtobufTransform<&u8> for u32 {
506    fn transform(value: &u8) -> CodecResult<Self> {
507        Ok(*value as u32)
508    }
509}
510
511impl ProtobufTransform<&u16> for u32 {
512    fn transform(value: &u16) -> CodecResult<Self> {
513        Ok(*value as u32)
514    }
515}
516
517impl ProtobufTransform<&i32> for i32 {
518    fn transform(value: &i32) -> CodecResult<Self> {
519        Ok(*value)
520    }
521}
522
523impl ProtobufTransform<&u32> for u32 {
524    fn transform(value: &u32) -> CodecResult<Self> {
525        Ok(*value)
526    }
527}
528
529impl ProtobufTransform<i64> for i64 {
530    fn transform(value: i64) -> CodecResult<Self> {
531        Ok(value)
532    }
533}
534
535impl ProtobufTransform<u64> for u64 {
536    fn transform(value: u64) -> CodecResult<Self> {
537        Ok(value)
538    }
539}
540
541impl ProtobufTransform<&i64> for i64 {
542    fn transform(value: &i64) -> CodecResult<Self> {
543        Ok(*value)
544    }
545}
546
547impl ProtobufTransform<&u64> for u64 {
548    fn transform(value: &u64) -> CodecResult<Self> {
549        Ok(*value)
550    }
551}
552
553impl ProtobufTransform<f32> for f32 {
554    fn transform(value: f32) -> CodecResult<Self> {
555        Ok(value)
556    }
557}
558
559impl ProtobufTransform<&f32> for f32 {
560    fn transform(value: &f32) -> CodecResult<Self> {
561        Ok(*value)
562    }
563}
564
565impl ProtobufTransform<f64> for f64 {
566    fn transform(value: f64) -> CodecResult<Self> {
567        Ok(value)
568    }
569}
570
571impl ProtobufTransform<&f64> for f64 {
572    fn transform(value: &f64) -> CodecResult<Self> {
573        Ok(*value)
574    }
575}
576
577impl ProtobufTransform<String> for String {
578    fn transform(value: String) -> CodecResult<Self> {
579        Ok(value)
580    }
581}
582
583impl ProtobufTransform<&String> for String {
584    fn transform(value: &String) -> CodecResult<Self> {
585        Ok(value.to_string())
586    }
587}
588
589impl ProtobufTransform<bool> for bool {
590    fn transform(value: bool) -> CodecResult<Self> {
591        Ok(value)
592    }
593}
594
595impl ProtobufTransform<&bool> for bool {
596    fn transform(value: &bool) -> CodecResult<Self> {
597        Ok(*value)
598    }
599}
600
601impl ProtobufTransform<u8> for u8 {
602    fn transform(value: u8) -> CodecResult<Self> {
603        Ok(value)
604    }
605}
606
607impl ProtobufTransform<&u8> for u8 {
608    fn transform(value: &u8) -> CodecResult<Self> {
609        Ok(*value)
610    }
611}
612
613impl ProtobufTransform<u16> for u16 {
614    fn transform(value: u16) -> CodecResult<Self> {
615        Ok(value)
616    }
617}
618
619impl ProtobufTransform<&u16> for u16 {
620    fn transform(value: &u16) -> CodecResult<Self> {
621        Ok(*value)
622    }
623}
624
625#[macro_export]
626macro_rules! impl_default_protobuf_raw_codec {
627    ($name:ty, $proto_name:ty) => {
628        impl bucky_raw_codec::RawEncode for $name {
629            fn raw_measure(
630                &self,
631                purpose: &Option<bucky_raw_codec::RawEncodePurpose>,
632            ) -> bucky_raw_codec::CodecResult<usize> {
633                // info!("desc content measure");
634                bucky_raw_codec::ProtobufCodecHelper::raw_measure::<$name, $proto_name>(&self, purpose)
635            }
636            fn raw_encode<'a>(
637                &self,
638                buf: &'a mut [u8],
639                purpose: &Option<bucky_raw_codec::RawEncodePurpose>,
640            ) -> bucky_raw_codec::CodecResult<&'a mut [u8]> {
641                // info!("desc content encode");
642                bucky_raw_codec::ProtobufCodecHelper::raw_encode::<$name, $proto_name>(self, buf, purpose)
643            }
644        }
645        impl<'de> bucky_raw_codec::RawDecode<'de> for $name {
646            fn raw_decode(buf: &'de [u8]) -> bucky_raw_codec::CodecResult<(Self, &'de [u8])> {
647                // info!("desc content decode");
648                bucky_raw_codec::ProtobufCodecHelper::raw_decode::<$name, $proto_name>(buf)
649            }
650        }
651    };
652
653    ($name:ident) => {
654        bucky_raw_codec::impl_default_protobuf_raw_codec!($name, protos::$name);
655    };
656}
657
658// cyfs_base工程内部使用
659#[macro_export]
660macro_rules! inner_impl_default_protobuf_raw_codec {
661    ($name:ty, $proto_name:ty) => {
662        impl crate::RawEncode for $name {
663            fn raw_measure(
664                &self,
665                purpose: &Option<crate::RawEncodePurpose>,
666            ) -> crate::CodecResult<usize> {
667                // info!("desc content measure");
668                crate::ProtobufCodecHelper::raw_measure::<$name, $proto_name>(&self, purpose)
669            }
670            fn raw_encode<'a>(
671                &self,
672                buf: &'a mut [u8],
673                purpose: &Option<crate::RawEncodePurpose>,
674            ) -> crate::CodecResult<&'a mut [u8]> {
675                // info!("desc content encode");
676                crate::ProtobufCodecHelper::raw_encode::<$name, $proto_name>(self, buf, purpose)
677            }
678        }
679        impl<'de> crate::RawDecode<'de> for $name {
680            fn raw_decode(buf: &'de [u8]) -> crate::CodecResult<(Self, &'de [u8])> {
681                // info!("desc content decode");
682                crate::ProtobufCodecHelper::raw_decode::<$name, $proto_name>(buf)
683            }
684        }
685    };
686
687    ($name:ident) => {
688        crate::inner_impl_default_protobuf_raw_codec!($name, protos::$name);
689    };
690}
691
692// 用以为空结构体实现基于protobuf的编解码
693#[macro_export]
694macro_rules! mod_impl_empty_protobuf_raw_codec {
695    ($m:ident, $name:ty, $proto_name:ty) => {
696        impl $m::RawEncode for $name {
697            fn raw_measure(
698                &self,
699                _purpose: &Option<$m::RawEncodePurpose>,
700            ) -> $m::CodecResult<usize> {
701                Ok(0)
702            }
703            fn raw_encode<'a>(
704                &self,
705                buf: &'a mut [u8],
706                _purpose: &Option<$m::RawEncodePurpose>,
707            ) -> $m::CodecResult<&'a mut [u8]> {
708                (Ok(buf))
709            }
710        }
711        impl<'de> $m::RawDecode<'de> for $name {
712            fn raw_decode(buf: &'de [u8]) -> $m::CodecResult<(Self, &'de [u8])> {
713                // info!("desc content decode");
714
715                let (msg, buf) = $m::ProtobufMessageCodecHelper::raw_decode::<$proto_name>(buf)?;
716
717                // 如果存在unknown fields,那么打印
718                use ::protobuf::Message;
719                if let Some(list) = &msg.get_unknown_fields().fields {
720                    warn!("got unknown fields! count={}", list.len());
721                }
722                Ok((Self {}, buf))
723            }
724        }
725    };
726
727    ($m:ident, $name:ident) => {
728        $m::mod_impl_empty_protobuf_raw_codec!($m, $name, $m::EmptyContent);
729    };
730}
731
732#[macro_export]
733macro_rules! impl_empty_protobuf_raw_codec {
734    ($name:ty, $proto_name:ty) => {
735        mod_impl_empty_protobuf_raw_codec!(bucky_raw_codec, $name, $proto_name);
736    };
737
738    ($name:ident) => {
739        mod_impl_empty_protobuf_raw_codec!(bucky_raw_codec, $name);
740    };
741}
742
743#[macro_export]
744macro_rules! inner_impl_empty_protobuf_raw_codec {
745    ($name:ty, $proto_name:ty) => {
746        crate::mod_impl_empty_protobuf_raw_codec!(crate, $name, $proto_name);
747    };
748
749    ($name:ident) => {
750        crate::mod_impl_empty_protobuf_raw_codec!(crate, $name);
751    };
752}
753
754#[cfg(test)]
755mod test {
756    use crate::*;
757    use crate as bucky_raw_codec;
758    use ::protobuf::Message;
759    use std::convert::TryFrom;
760
761    // 空结构体可以使用raw_codec,也可以使用protobuf辅助宏来实现
762    #[derive(Clone, Debug, RawEncode, RawDecode)]
763    struct EmptyContent {}
764
765    struct EmptyContent2 {}
766
767    inner_impl_empty_protobuf_raw_codec!(EmptyContent2);
768
769    struct EmptyContentV1 {
770        name: Option<String>,
771    }
772
773    impl TryFrom<protos::EmptyContentV1> for EmptyContentV1 {
774        type Error = CodecError;
775        fn try_from(mut value: protos::EmptyContentV1) -> CodecResult<Self> {
776            let mut ret = Self { name: None };
777
778            if value.has_name() {
779                ret.name = Some(value.take_name());
780            }
781
782            Ok(ret)
783        }
784    }
785    impl TryFrom<&EmptyContentV1> for protos::EmptyContentV1 {
786        type Error = CodecError;
787        fn try_from(value: &EmptyContentV1) -> CodecResult<Self> {
788            let mut ret = Self::new();
789            if let Some(name) = &value.name {
790                ret.set_name(name.to_owned());
791            }
792
793            Ok(ret)
794        }
795    }
796    inner_impl_default_protobuf_raw_codec!(EmptyContentV1);
797
798    #[test]
799    fn test_protobuf() {
800        // 新版本兼容老版本
801        {
802            let content = protos::EmptyContent::new();
803            let size = content.compute_size();
804            assert_eq!(size, 0);
805
806            let buf = vec![0u8; 0];
807            let (content_v1, _) = EmptyContentV1::raw_decode(&buf).unwrap();
808            assert!(content_v1.name.is_none());
809        }
810
811        // 老版本兼容新版本
812        {
813            let content_v1 = EmptyContentV1 {
814                name: Some("xxx".to_owned()),
815            };
816            let buf = content_v1.to_vec().unwrap();
817            assert!(buf.len() > 0);
818
819            // 如果是使用了默认的rawcodec,那么解码后buf长度不会变化
820            // 但我们在上层object_mut_body实际没使用返回的buf,所以可以完全兼容
821            let (_content, left_buf) = EmptyContent::raw_decode(&buf).unwrap();
822            assert!(left_buf.len() == buf.len());
823
824            // 如果是使用了protobuf编解码,那么就会消耗掉整个buf
825            let (_content, left_buf) = EmptyContent2::raw_decode(&buf).unwrap();
826            assert!(left_buf.len() == 0);
827        }
828
829        let content2 = EmptyContent {};
830        let buf = content2.to_vec().unwrap();
831        assert_eq!(buf.len(), 0);
832    }
833
834    #[test]
835    fn test_helper() {
836        let mut source: u32 = u32::MAX;
837        let ret = ProtobufCodecHelper::decode_value::<u8, u32>(source);
838        assert!(ret.is_err());
839
840        source = u8::MAX as u32;
841        let ret = ProtobufCodecHelper::decode_value::<u8, u32>(source);
842        assert!(ret.is_ok());
843        assert_eq!(ret.unwrap(), u8::MAX);
844    }
845}