Coverage Report

Created: 2026-11-03 08:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/prost-0.14.3/src/encoding.rs
Line
Count
Source
1
//! Utility functions and types for encoding and decoding Protobuf types.
2
//!
3
//! This module contains the encoding and decoding primitives for Protobuf as described in
4
//! <https://protobuf.dev/programming-guides/encoding/>.
5
//!
6
//! This module is `pub`, but is only for prost internal use. The `prost-derive` crate needs access for its `Message` implementations.
7
8
use alloc::collections::BTreeMap;
9
use alloc::string::String;
10
use alloc::vec::Vec;
11
use core::mem;
12
use core::str;
13
14
use ::bytes::{Buf, BufMut, Bytes};
15
16
use crate::error::DecodeErrorKind;
17
use crate::DecodeError;
18
use crate::Message;
19
20
pub mod varint;
21
pub use varint::{decode_varint, encode_varint, encoded_len_varint};
22
23
pub mod length_delimiter;
24
pub use length_delimiter::{
25
    decode_length_delimiter, encode_length_delimiter, length_delimiter_len,
26
};
27
28
pub mod wire_type;
29
pub use wire_type::{check_wire_type, WireType};
30
31
/// Additional information passed to every decode/merge function.
32
///
33
/// The context should be passed by value and can be freely cloned. When passing
34
/// to a function which is decoding a nested object, then use `enter_recursion`.
35
#[derive(Clone, Debug)]
36
#[cfg_attr(feature = "no-recursion-limit", derive(Default))]
37
pub struct DecodeContext {
38
    /// How many times we can recurse in the current decode stack before we hit
39
    /// the recursion limit.
40
    ///
41
    /// The recursion limit is defined by `RECURSION_LIMIT` and cannot be
42
    /// customized. The recursion limit can be ignored by building the Prost
43
    /// crate with the `no-recursion-limit` feature.
44
    #[cfg(not(feature = "no-recursion-limit"))]
45
    recurse_count: u32,
46
}
47
48
#[cfg(not(feature = "no-recursion-limit"))]
49
impl Default for DecodeContext {
50
    #[inline]
51
0
    fn default() -> DecodeContext {
52
0
        DecodeContext {
53
0
            recurse_count: crate::RECURSION_LIMIT,
54
0
        }
55
0
    }
56
}
57
58
impl DecodeContext {
59
    /// Call this function before recursively decoding.
60
    ///
61
    /// There is no `exit` function since this function creates a new `DecodeContext`
62
    /// to be used at the next level of recursion. Continue to use the old context
63
    // at the previous level of recursion.
64
    #[cfg(not(feature = "no-recursion-limit"))]
65
    #[inline]
66
0
    pub(crate) fn enter_recursion(&self) -> DecodeContext {
67
0
        DecodeContext {
68
0
            recurse_count: self.recurse_count - 1,
69
0
        }
70
0
    }
71
72
    #[cfg(feature = "no-recursion-limit")]
73
    #[inline]
74
    pub(crate) fn enter_recursion(&self) -> DecodeContext {
75
        DecodeContext {}
76
    }
77
78
    /// Checks whether the recursion limit has been reached in the stack of
79
    /// decodes described by the `DecodeContext` at `self.ctx`.
80
    ///
81
    /// Returns `Ok<()>` if it is ok to continue recursing.
82
    /// Returns `Err<DecodeError>` if the recursion limit has been reached.
83
    #[cfg(not(feature = "no-recursion-limit"))]
84
    #[inline]
85
0
    pub(crate) fn limit_reached(&self) -> Result<(), DecodeError> {
86
0
        if self.recurse_count == 0 {
87
0
            Err(DecodeErrorKind::RecursionLimitReached.into())
88
        } else {
89
0
            Ok(())
90
        }
91
0
    }
92
93
    #[cfg(feature = "no-recursion-limit")]
94
    #[inline]
95
    pub(crate) fn limit_reached(&self) -> Result<(), DecodeError> {
96
        Ok(())
97
    }
98
}
99
100
pub const MIN_TAG: u32 = 1;
101
pub const MAX_TAG: u32 = (1 << 29) - 1;
102
103
/// Encodes a Protobuf field key, which consists of a wire type designator and
104
/// the field tag.
105
#[inline]
106
0
pub fn encode_key(tag: u32, wire_type: WireType, buf: &mut impl BufMut) {
107
0
    debug_assert!((MIN_TAG..=MAX_TAG).contains(&tag));
108
0
    let key = (tag << 3) | wire_type as u32;
109
0
    encode_varint(u64::from(key), buf);
110
0
}
111
112
/// Decodes a Protobuf field key, which consists of a wire type designator and
113
/// the field tag.
114
#[inline(always)]
115
0
pub fn decode_key(buf: &mut impl Buf) -> Result<(u32, WireType), DecodeError> {
116
0
    let key = decode_varint(buf)?;
117
0
    if key > u64::from(u32::MAX) {
118
0
        return Err(DecodeErrorKind::InvalidKey { key }.into());
119
0
    }
120
0
    let wire_type = WireType::try_from(key & 0x07)?;
121
0
    let tag = key as u32 >> 3;
122
123
0
    if tag < MIN_TAG {
124
0
        return Err(DecodeErrorKind::InvalidTag.into());
125
0
    }
126
127
0
    Ok((tag, wire_type))
128
0
}
129
130
/// Returns the width of an encoded Protobuf field key with the given tag.
131
/// The returned width will be between 1 and 5 bytes (inclusive).
132
#[inline]
133
0
pub const fn key_len(tag: u32) -> usize {
134
0
    encoded_len_varint((tag << 3) as u64)
135
0
}
136
137
/// Helper function which abstracts reading a length delimiter prefix followed
138
/// by decoding values until the length of bytes is exhausted.
139
0
pub fn merge_loop<T, M, B>(
140
0
    value: &mut T,
141
0
    buf: &mut B,
142
0
    ctx: DecodeContext,
143
0
    mut merge: M,
144
0
) -> Result<(), DecodeError>
145
0
where
146
0
    M: FnMut(&mut T, &mut B, DecodeContext) -> Result<(), DecodeError>,
147
0
    B: Buf,
148
{
149
0
    let len = decode_varint(buf)?;
150
0
    let remaining = buf.remaining();
151
0
    if len > remaining as u64 {
152
0
        return Err(DecodeErrorKind::BufferUnderflow.into());
153
0
    }
154
155
0
    let limit = remaining - len as usize;
156
0
    while buf.remaining() > limit {
157
0
        merge(value, buf, ctx.clone())?;
158
    }
159
160
0
    if buf.remaining() != limit {
161
0
        return Err(DecodeErrorKind::DelimitedLengthExceeded.into());
162
0
    }
163
0
    Ok(())
164
0
}
165
166
0
pub fn skip_field(
167
0
    wire_type: WireType,
168
0
    tag: u32,
169
0
    buf: &mut impl Buf,
170
0
    ctx: DecodeContext,
171
0
) -> Result<(), DecodeError> {
172
0
    ctx.limit_reached()?;
173
0
    let len = match wire_type {
174
0
        WireType::Varint => decode_varint(buf).map(|_| 0)?,
175
0
        WireType::ThirtyTwoBit => 4,
176
0
        WireType::SixtyFourBit => 8,
177
0
        WireType::LengthDelimited => decode_varint(buf)?,
178
        WireType::StartGroup => loop {
179
0
            let (inner_tag, inner_wire_type) = decode_key(buf)?;
180
0
            match inner_wire_type {
181
                WireType::EndGroup => {
182
0
                    if inner_tag != tag {
183
0
                        return Err(DecodeErrorKind::UnexpectedEndGroupTag.into());
184
0
                    }
185
0
                    break 0;
186
                }
187
0
                _ => skip_field(inner_wire_type, inner_tag, buf, ctx.enter_recursion())?,
188
            }
189
        },
190
0
        WireType::EndGroup => return Err(DecodeErrorKind::UnexpectedEndGroupTag.into()),
191
    };
192
193
0
    if len > buf.remaining() as u64 {
194
0
        return Err(DecodeErrorKind::BufferUnderflow.into());
195
0
    }
196
197
0
    buf.advance(len as usize);
198
0
    Ok(())
199
0
}
200
201
/// Helper macro which emits an `encode_repeated` function for the type.
202
macro_rules! encode_repeated {
203
    ($ty:ty) => {
204
0
        pub fn encode_repeated(tag: u32, values: &[$ty], buf: &mut impl BufMut) {
205
0
            for value in values {
206
0
                encode(tag, value, buf);
207
0
            }
208
0
        }
Unexecuted instantiation: prost::encoding::bool::encode_repeated::<_>
Unexecuted instantiation: prost::encoding::bytes::encode_repeated::<_, _>
Unexecuted instantiation: prost::encoding::float::encode_repeated::<_>
Unexecuted instantiation: prost::encoding::int32::encode_repeated::<_>
Unexecuted instantiation: prost::encoding::int64::encode_repeated::<_>
Unexecuted instantiation: prost::encoding::double::encode_repeated::<_>
Unexecuted instantiation: prost::encoding::sint32::encode_repeated::<_>
Unexecuted instantiation: prost::encoding::sint64::encode_repeated::<_>
Unexecuted instantiation: prost::encoding::string::encode_repeated::<_>
Unexecuted instantiation: prost::encoding::uint32::encode_repeated::<_>
Unexecuted instantiation: prost::encoding::uint64::encode_repeated::<_>
Unexecuted instantiation: prost::encoding::fixed32::encode_repeated::<_>
Unexecuted instantiation: prost::encoding::fixed64::encode_repeated::<_>
Unexecuted instantiation: prost::encoding::sfixed32::encode_repeated::<_>
Unexecuted instantiation: prost::encoding::sfixed64::encode_repeated::<_>
209
    };
210
}
211
212
/// Helper macro which emits a `merge_repeated` function for the numeric type.
213
macro_rules! merge_repeated_numeric {
214
    ($ty:ty,
215
     $wire_type:expr,
216
     $merge:ident,
217
     $merge_repeated:ident) => {
218
0
        pub fn $merge_repeated(
219
0
            wire_type: WireType,
220
0
            values: &mut Vec<$ty>,
221
0
            buf: &mut impl Buf,
222
0
            ctx: DecodeContext,
223
0
        ) -> Result<(), DecodeError> {
224
0
            if wire_type == WireType::LengthDelimited {
225
                // Packed.
226
0
                merge_loop(values, buf, ctx, |values, buf, ctx| {
227
0
                    let mut value = Default::default();
228
0
                    $merge($wire_type, &mut value, buf, ctx)?;
229
0
                    values.push(value);
230
0
                    Ok(())
231
0
                })
Unexecuted instantiation: prost::encoding::bool::merge_repeated::<_>::{closure#0}
Unexecuted instantiation: prost::encoding::float::merge_repeated::<_>::{closure#0}
Unexecuted instantiation: prost::encoding::int32::merge_repeated::<_>::{closure#0}
Unexecuted instantiation: prost::encoding::int64::merge_repeated::<_>::{closure#0}
Unexecuted instantiation: prost::encoding::double::merge_repeated::<_>::{closure#0}
Unexecuted instantiation: prost::encoding::sint32::merge_repeated::<_>::{closure#0}
Unexecuted instantiation: prost::encoding::sint64::merge_repeated::<_>::{closure#0}
Unexecuted instantiation: prost::encoding::uint32::merge_repeated::<_>::{closure#0}
Unexecuted instantiation: prost::encoding::uint64::merge_repeated::<_>::{closure#0}
Unexecuted instantiation: prost::encoding::fixed32::merge_repeated::<_>::{closure#0}
Unexecuted instantiation: prost::encoding::fixed64::merge_repeated::<_>::{closure#0}
Unexecuted instantiation: prost::encoding::sfixed32::merge_repeated::<_>::{closure#0}
Unexecuted instantiation: prost::encoding::sfixed64::merge_repeated::<_>::{closure#0}
232
            } else {
233
                // Unpacked.
234
0
                check_wire_type($wire_type, wire_type)?;
235
0
                let mut value = Default::default();
236
0
                $merge(wire_type, &mut value, buf, ctx)?;
237
0
                values.push(value);
238
0
                Ok(())
239
            }
240
0
        }
Unexecuted instantiation: prost::encoding::bool::merge_repeated::<_>
Unexecuted instantiation: prost::encoding::float::merge_repeated::<_>
Unexecuted instantiation: prost::encoding::int32::merge_repeated::<_>
Unexecuted instantiation: prost::encoding::int64::merge_repeated::<_>
Unexecuted instantiation: prost::encoding::double::merge_repeated::<_>
Unexecuted instantiation: prost::encoding::sint32::merge_repeated::<_>
Unexecuted instantiation: prost::encoding::sint64::merge_repeated::<_>
Unexecuted instantiation: prost::encoding::uint32::merge_repeated::<_>
Unexecuted instantiation: prost::encoding::uint64::merge_repeated::<_>
Unexecuted instantiation: prost::encoding::fixed32::merge_repeated::<_>
Unexecuted instantiation: prost::encoding::fixed64::merge_repeated::<_>
Unexecuted instantiation: prost::encoding::sfixed32::merge_repeated::<_>
Unexecuted instantiation: prost::encoding::sfixed64::merge_repeated::<_>
241
    };
242
}
243
244
/// Macro which emits a module containing a set of encoding functions for a
245
/// variable width numeric type.
246
macro_rules! varint {
247
    ($ty:ty,
248
     $proto_ty:ident) => (
249
        varint!($ty,
250
                $proto_ty,
251
                to_uint64(value) { *value as u64 },
252
                from_uint64(value) { value as $ty });
253
    );
254
255
    ($ty:ty,
256
     $proto_ty:ident,
257
     to_uint64($to_uint64_value:ident) $to_uint64:expr,
258
     from_uint64($from_uint64_value:ident) $from_uint64:expr) => (
259
260
         pub mod $proto_ty {
261
            use crate::encoding::*;
262
263
0
            pub fn encode(tag: u32, $to_uint64_value: &$ty, buf: &mut impl BufMut) {
264
0
                encode_key(tag, WireType::Varint, buf);
265
0
                encode_varint($to_uint64, buf);
266
0
            }
Unexecuted instantiation: prost::encoding::bool::encode::<_>
Unexecuted instantiation: prost::encoding::int32::encode::<_>
Unexecuted instantiation: prost::encoding::int64::encode::<_>
Unexecuted instantiation: prost::encoding::sint32::encode::<_>
Unexecuted instantiation: prost::encoding::sint64::encode::<_>
Unexecuted instantiation: prost::encoding::uint32::encode::<_>
Unexecuted instantiation: prost::encoding::uint64::encode::<_>
267
268
0
            pub fn merge(wire_type: WireType, value: &mut $ty, buf: &mut impl Buf, _ctx: DecodeContext) -> Result<(), DecodeError> {
269
0
                check_wire_type(WireType::Varint, wire_type)?;
270
0
                let $from_uint64_value = decode_varint(buf)?;
271
0
                *value = $from_uint64;
272
0
                Ok(())
273
0
            }
Unexecuted instantiation: prost::encoding::bool::merge::<_>
Unexecuted instantiation: prost::encoding::int32::merge::<_>
Unexecuted instantiation: prost::encoding::int64::merge::<_>
Unexecuted instantiation: prost::encoding::sint32::merge::<_>
Unexecuted instantiation: prost::encoding::sint64::merge::<_>
Unexecuted instantiation: prost::encoding::uint32::merge::<_>
Unexecuted instantiation: prost::encoding::uint64::merge::<_>
274
275
            encode_repeated!($ty);
276
277
0
            pub fn encode_packed(tag: u32, values: &[$ty], buf: &mut impl BufMut) {
278
0
                if values.is_empty() { return; }
279
280
0
                encode_key(tag, WireType::LengthDelimited, buf);
281
0
                let len: usize = values.iter().map(|$to_uint64_value| {
282
0
                    encoded_len_varint($to_uint64)
283
0
                }).sum();
Unexecuted instantiation: prost::encoding::bool::encode_packed::<_>::{closure#0}
Unexecuted instantiation: prost::encoding::int32::encode_packed::<_>::{closure#0}
Unexecuted instantiation: prost::encoding::int64::encode_packed::<_>::{closure#0}
Unexecuted instantiation: prost::encoding::sint32::encode_packed::<_>::{closure#0}
Unexecuted instantiation: prost::encoding::sint64::encode_packed::<_>::{closure#0}
Unexecuted instantiation: prost::encoding::uint32::encode_packed::<_>::{closure#0}
Unexecuted instantiation: prost::encoding::uint64::encode_packed::<_>::{closure#0}
284
0
                encode_varint(len as u64, buf);
285
286
0
                for $to_uint64_value in values {
287
0
                    encode_varint($to_uint64, buf);
288
0
                }
289
0
            }
Unexecuted instantiation: prost::encoding::bool::encode_packed::<_>
Unexecuted instantiation: prost::encoding::int32::encode_packed::<_>
Unexecuted instantiation: prost::encoding::int64::encode_packed::<_>
Unexecuted instantiation: prost::encoding::sint32::encode_packed::<_>
Unexecuted instantiation: prost::encoding::sint64::encode_packed::<_>
Unexecuted instantiation: prost::encoding::uint32::encode_packed::<_>
Unexecuted instantiation: prost::encoding::uint64::encode_packed::<_>
290
291
            merge_repeated_numeric!($ty, WireType::Varint, merge, merge_repeated);
292
293
            #[inline]
294
0
            pub fn encoded_len(tag: u32, $to_uint64_value: &$ty) -> usize {
295
0
                key_len(tag) + encoded_len_varint($to_uint64)
296
0
            }
Unexecuted instantiation: prost::encoding::int32::encoded_len
Unexecuted instantiation: prost::encoding::int64::encoded_len
Unexecuted instantiation: prost::encoding::uint32::encoded_len
Unexecuted instantiation: prost::encoding::uint64::encoded_len
Unexecuted instantiation: prost::encoding::bool::encoded_len
Unexecuted instantiation: prost::encoding::sint32::encoded_len
Unexecuted instantiation: prost::encoding::sint64::encoded_len
297
298
            #[inline]
299
0
            pub fn encoded_len_repeated(tag: u32, values: &[$ty]) -> usize {
300
0
                key_len(tag) * values.len() + values.iter().map(|$to_uint64_value| {
301
0
                    encoded_len_varint($to_uint64)
302
0
                }).sum::<usize>()
Unexecuted instantiation: prost::encoding::bool::encoded_len_repeated::{closure#0}
Unexecuted instantiation: prost::encoding::int32::encoded_len_repeated::{closure#0}
Unexecuted instantiation: prost::encoding::int64::encoded_len_repeated::{closure#0}
Unexecuted instantiation: prost::encoding::sint32::encoded_len_repeated::{closure#0}
Unexecuted instantiation: prost::encoding::sint64::encoded_len_repeated::{closure#0}
Unexecuted instantiation: prost::encoding::uint32::encoded_len_repeated::{closure#0}
Unexecuted instantiation: prost::encoding::uint64::encoded_len_repeated::{closure#0}
303
0
            }
Unexecuted instantiation: prost::encoding::bool::encoded_len_repeated
Unexecuted instantiation: prost::encoding::int32::encoded_len_repeated
Unexecuted instantiation: prost::encoding::int64::encoded_len_repeated
Unexecuted instantiation: prost::encoding::sint32::encoded_len_repeated
Unexecuted instantiation: prost::encoding::sint64::encoded_len_repeated
Unexecuted instantiation: prost::encoding::uint32::encoded_len_repeated
Unexecuted instantiation: prost::encoding::uint64::encoded_len_repeated
304
305
            #[inline]
306
0
            pub fn encoded_len_packed(tag: u32, values: &[$ty]) -> usize {
307
0
                if values.is_empty() {
308
0
                    0
309
                } else {
310
0
                    let len = values.iter()
311
0
                                    .map(|$to_uint64_value| encoded_len_varint($to_uint64))
Unexecuted instantiation: prost::encoding::bool::encoded_len_packed::{closure#0}
Unexecuted instantiation: prost::encoding::int32::encoded_len_packed::{closure#0}
Unexecuted instantiation: prost::encoding::int64::encoded_len_packed::{closure#0}
Unexecuted instantiation: prost::encoding::sint32::encoded_len_packed::{closure#0}
Unexecuted instantiation: prost::encoding::sint64::encoded_len_packed::{closure#0}
Unexecuted instantiation: prost::encoding::uint32::encoded_len_packed::{closure#0}
Unexecuted instantiation: prost::encoding::uint64::encoded_len_packed::{closure#0}
312
0
                                    .sum::<usize>();
313
0
                    key_len(tag) + encoded_len_varint(len as u64) + len
314
                }
315
0
            }
Unexecuted instantiation: prost::encoding::bool::encoded_len_packed
Unexecuted instantiation: prost::encoding::int32::encoded_len_packed
Unexecuted instantiation: prost::encoding::int64::encoded_len_packed
Unexecuted instantiation: prost::encoding::sint32::encoded_len_packed
Unexecuted instantiation: prost::encoding::sint64::encoded_len_packed
Unexecuted instantiation: prost::encoding::uint32::encoded_len_packed
Unexecuted instantiation: prost::encoding::uint64::encoded_len_packed
316
317
            #[cfg(test)]
318
            mod test {
319
                use proptest::prelude::*;
320
321
                use crate::encoding::$proto_ty::*;
322
                use crate::encoding::test::{
323
                    check_collection_type,
324
                    check_type,
325
                };
326
327
                proptest! {
328
                    #[test]
329
                    fn check(value: $ty, tag in MIN_TAG..=MAX_TAG) {
330
                        check_type(value, tag, WireType::Varint,
331
                                   encode, merge, encoded_len)?;
332
                    }
333
                    #[test]
334
                    fn check_repeated(value: Vec<$ty>, tag in MIN_TAG..=MAX_TAG) {
335
                        check_collection_type(value, tag, WireType::Varint,
336
                                              encode_repeated, merge_repeated,
337
                                              encoded_len_repeated)?;
338
                    }
339
                    #[test]
340
                    fn check_packed(value: Vec<$ty>, tag in MIN_TAG..=MAX_TAG) {
341
                        check_type(value, tag, WireType::LengthDelimited,
342
                                   encode_packed, merge_repeated,
343
                                   encoded_len_packed)?;
344
                    }
345
                }
346
            }
347
         }
348
349
    );
350
}
351
varint!(bool, bool,
352
        to_uint64(value) u64::from(*value),
353
        from_uint64(value) value != 0);
354
varint!(i32, int32);
355
varint!(i64, int64);
356
varint!(u32, uint32);
357
varint!(u64, uint64);
358
varint!(i32, sint32,
359
to_uint64(value) {
360
    ((value << 1) ^ (value >> 31)) as u32 as u64
361
},
362
from_uint64(value) {
363
    let value = value as u32;
364
    ((value >> 1) as i32) ^ (-((value & 1) as i32))
365
});
366
varint!(i64, sint64,
367
to_uint64(value) {
368
    ((value << 1) ^ (value >> 63)) as u64
369
},
370
from_uint64(value) {
371
    ((value >> 1) as i64) ^ (-((value & 1) as i64))
372
});
373
374
/// Macro which emits a module containing a set of encoding functions for a
375
/// fixed width numeric type.
376
macro_rules! fixed_width {
377
    ($ty:ty,
378
     $width:expr,
379
     $wire_type:expr,
380
     $proto_ty:ident,
381
     $put:ident,
382
     $get:ident) => {
383
        pub mod $proto_ty {
384
            use crate::encoding::*;
385
386
0
            pub fn encode(tag: u32, value: &$ty, buf: &mut impl BufMut) {
387
0
                encode_key(tag, $wire_type, buf);
388
0
                buf.$put(*value);
389
0
            }
Unexecuted instantiation: prost::encoding::float::encode::<_>
Unexecuted instantiation: prost::encoding::double::encode::<_>
Unexecuted instantiation: prost::encoding::fixed32::encode::<_>
Unexecuted instantiation: prost::encoding::fixed64::encode::<_>
Unexecuted instantiation: prost::encoding::sfixed32::encode::<_>
Unexecuted instantiation: prost::encoding::sfixed64::encode::<_>
390
391
0
            pub fn merge(
392
0
                wire_type: WireType,
393
0
                value: &mut $ty,
394
0
                buf: &mut impl Buf,
395
0
                _ctx: DecodeContext,
396
0
            ) -> Result<(), DecodeError> {
397
0
                check_wire_type($wire_type, wire_type)?;
398
0
                if buf.remaining() < $width {
399
0
                    return Err(DecodeErrorKind::BufferUnderflow.into());
400
0
                }
401
0
                *value = buf.$get();
402
0
                Ok(())
403
0
            }
Unexecuted instantiation: prost::encoding::float::merge::<_>
Unexecuted instantiation: prost::encoding::double::merge::<_>
Unexecuted instantiation: prost::encoding::fixed32::merge::<_>
Unexecuted instantiation: prost::encoding::fixed64::merge::<_>
Unexecuted instantiation: prost::encoding::sfixed32::merge::<_>
Unexecuted instantiation: prost::encoding::sfixed64::merge::<_>
404
405
            encode_repeated!($ty);
406
407
0
            pub fn encode_packed(tag: u32, values: &[$ty], buf: &mut impl BufMut) {
408
0
                if values.is_empty() {
409
0
                    return;
410
0
                }
411
412
0
                encode_key(tag, WireType::LengthDelimited, buf);
413
0
                let len = values.len() as u64 * $width;
414
0
                encode_varint(len as u64, buf);
415
416
0
                for value in values {
417
0
                    buf.$put(*value);
418
0
                }
419
0
            }
Unexecuted instantiation: prost::encoding::float::encode_packed::<_>
Unexecuted instantiation: prost::encoding::double::encode_packed::<_>
Unexecuted instantiation: prost::encoding::fixed32::encode_packed::<_>
Unexecuted instantiation: prost::encoding::fixed64::encode_packed::<_>
Unexecuted instantiation: prost::encoding::sfixed32::encode_packed::<_>
Unexecuted instantiation: prost::encoding::sfixed64::encode_packed::<_>
420
421
            merge_repeated_numeric!($ty, $wire_type, merge, merge_repeated);
422
423
            #[inline]
424
0
            pub fn encoded_len(tag: u32, _: &$ty) -> usize {
425
0
                key_len(tag) + $width
426
0
            }
Unexecuted instantiation: prost::encoding::float::encoded_len
Unexecuted instantiation: prost::encoding::double::encoded_len
Unexecuted instantiation: prost::encoding::fixed32::encoded_len
Unexecuted instantiation: prost::encoding::fixed64::encoded_len
Unexecuted instantiation: prost::encoding::sfixed32::encoded_len
Unexecuted instantiation: prost::encoding::sfixed64::encoded_len
427
428
            #[inline]
429
0
            pub fn encoded_len_repeated(tag: u32, values: &[$ty]) -> usize {
430
0
                (key_len(tag) + $width) * values.len()
431
0
            }
Unexecuted instantiation: prost::encoding::float::encoded_len_repeated
Unexecuted instantiation: prost::encoding::double::encoded_len_repeated
Unexecuted instantiation: prost::encoding::fixed32::encoded_len_repeated
Unexecuted instantiation: prost::encoding::fixed64::encoded_len_repeated
Unexecuted instantiation: prost::encoding::sfixed32::encoded_len_repeated
Unexecuted instantiation: prost::encoding::sfixed64::encoded_len_repeated
432
433
            #[inline]
434
0
            pub fn encoded_len_packed(tag: u32, values: &[$ty]) -> usize {
435
0
                if values.is_empty() {
436
0
                    0
437
                } else {
438
0
                    let len = $width * values.len();
439
0
                    key_len(tag) + encoded_len_varint(len as u64) + len
440
                }
441
0
            }
Unexecuted instantiation: prost::encoding::float::encoded_len_packed
Unexecuted instantiation: prost::encoding::double::encoded_len_packed
Unexecuted instantiation: prost::encoding::fixed32::encoded_len_packed
Unexecuted instantiation: prost::encoding::fixed64::encoded_len_packed
Unexecuted instantiation: prost::encoding::sfixed32::encoded_len_packed
Unexecuted instantiation: prost::encoding::sfixed64::encoded_len_packed
442
443
            #[cfg(test)]
444
            mod test {
445
                use proptest::prelude::*;
446
447
                use super::super::test::{check_collection_type, check_type};
448
                use super::*;
449
450
                proptest! {
451
                    #[test]
452
                    fn check(value: $ty, tag in MIN_TAG..=MAX_TAG) {
453
                        check_type(value, tag, $wire_type,
454
                                   encode, merge, encoded_len)?;
455
                    }
456
                    #[test]
457
                    fn check_repeated(value: Vec<$ty>, tag in MIN_TAG..=MAX_TAG) {
458
                        check_collection_type(value, tag, $wire_type,
459
                                              encode_repeated, merge_repeated,
460
                                              encoded_len_repeated)?;
461
                    }
462
                    #[test]
463
                    fn check_packed(value: Vec<$ty>, tag in MIN_TAG..=MAX_TAG) {
464
                        check_type(value, tag, WireType::LengthDelimited,
465
                                   encode_packed, merge_repeated,
466
                                   encoded_len_packed)?;
467
                    }
468
                }
469
            }
470
        }
471
    };
472
}
473
fixed_width!(
474
    f32,
475
    4,
476
    WireType::ThirtyTwoBit,
477
    float,
478
    put_f32_le,
479
    get_f32_le
480
);
481
fixed_width!(
482
    f64,
483
    8,
484
    WireType::SixtyFourBit,
485
    double,
486
    put_f64_le,
487
    get_f64_le
488
);
489
fixed_width!(
490
    u32,
491
    4,
492
    WireType::ThirtyTwoBit,
493
    fixed32,
494
    put_u32_le,
495
    get_u32_le
496
);
497
fixed_width!(
498
    u64,
499
    8,
500
    WireType::SixtyFourBit,
501
    fixed64,
502
    put_u64_le,
503
    get_u64_le
504
);
505
fixed_width!(
506
    i32,
507
    4,
508
    WireType::ThirtyTwoBit,
509
    sfixed32,
510
    put_i32_le,
511
    get_i32_le
512
);
513
fixed_width!(
514
    i64,
515
    8,
516
    WireType::SixtyFourBit,
517
    sfixed64,
518
    put_i64_le,
519
    get_i64_le
520
);
521
522
/// Macro which emits encoding functions for a length-delimited type.
523
macro_rules! length_delimited {
524
    ($ty:ty) => {
525
        encode_repeated!($ty);
526
527
0
        pub fn merge_repeated(
528
0
            wire_type: WireType,
529
0
            values: &mut Vec<$ty>,
530
0
            buf: &mut impl Buf,
531
0
            ctx: DecodeContext,
532
0
        ) -> Result<(), DecodeError> {
533
0
            check_wire_type(WireType::LengthDelimited, wire_type)?;
534
0
            let mut value = Default::default();
535
0
            merge(wire_type, &mut value, buf, ctx)?;
536
0
            values.push(value);
537
0
            Ok(())
538
0
        }
Unexecuted instantiation: prost::encoding::bytes::merge_repeated::<_, _>
Unexecuted instantiation: prost::encoding::string::merge_repeated::<_>
539
540
        #[inline]
541
        #[allow(clippy::ptr_arg)]
542
0
        pub fn encoded_len(tag: u32, value: &$ty) -> usize {
543
0
            key_len(tag) + encoded_len_varint(value.len() as u64) + value.len()
544
0
        }
Unexecuted instantiation: prost::encoding::bytes::encoded_len::<alloc::vec::Vec<u8>>
Unexecuted instantiation: prost::encoding::bytes::encoded_len::<bytes::bytes::Bytes>
Unexecuted instantiation: prost::encoding::string::encoded_len
545
546
        #[inline]
547
0
        pub fn encoded_len_repeated(tag: u32, values: &[$ty]) -> usize {
548
0
            key_len(tag) * values.len()
549
0
                + values
550
0
                    .iter()
551
0
                    .map(|value| encoded_len_varint(value.len() as u64) + value.len())
Unexecuted instantiation: prost::encoding::bytes::encoded_len_repeated::<_>::{closure#0}
Unexecuted instantiation: prost::encoding::string::encoded_len_repeated::{closure#0}
552
0
                    .sum::<usize>()
553
0
        }
Unexecuted instantiation: prost::encoding::bytes::encoded_len_repeated::<_>
Unexecuted instantiation: prost::encoding::string::encoded_len_repeated
554
    };
555
}
556
557
pub mod string {
558
    use super::*;
559
560
0
    pub fn encode(tag: u32, value: &String, buf: &mut impl BufMut) {
561
0
        encode_key(tag, WireType::LengthDelimited, buf);
562
0
        encode_varint(value.len() as u64, buf);
563
0
        buf.put_slice(value.as_bytes());
564
0
    }
565
566
0
    pub fn merge(
567
0
        wire_type: WireType,
568
0
        value: &mut String,
569
0
        buf: &mut impl Buf,
570
0
        ctx: DecodeContext,
571
0
    ) -> Result<(), DecodeError> {
572
        // ## Unsafety
573
        //
574
        // `string::merge` reuses `bytes::merge`, with an additional check of utf-8
575
        // well-formedness. If the utf-8 is not well-formed, or if any other error occurs, then the
576
        // string is cleared, so as to avoid leaking a string field with invalid data.
577
        //
578
        // This implementation uses the unsafe `String::as_mut_vec` method instead of the safe
579
        // alternative of temporarily swapping an empty `String` into the field, because it results
580
        // in up to 10% better performance on the protobuf message decoding benchmarks.
581
        //
582
        // It's required when using `String::as_mut_vec` that invalid utf-8 data not be leaked into
583
        // the backing `String`. To enforce this, even in the event of a panic in `bytes::merge` or
584
        // in the buf implementation, a drop guard is used.
585
        unsafe {
586
            struct DropGuard<'a>(&'a mut Vec<u8>);
587
            impl Drop for DropGuard<'_> {
588
                #[inline]
589
0
                fn drop(&mut self) {
590
0
                    self.0.clear();
591
0
                }
592
            }
593
594
0
            let drop_guard = DropGuard(value.as_mut_vec());
595
0
            bytes::merge_one_copy(wire_type, drop_guard.0, buf, ctx)?;
596
0
            match str::from_utf8(drop_guard.0) {
597
                Ok(_) => {
598
                    // Success; do not clear the bytes.
599
0
                    mem::forget(drop_guard);
600
0
                    Ok(())
601
                }
602
0
                Err(_) => Err(DecodeErrorKind::InvalidString.into()),
603
            }
604
        }
605
0
    }
606
607
    length_delimited!(String);
608
609
    #[cfg(test)]
610
    mod test {
611
        use proptest::prelude::*;
612
613
        use super::super::test::{check_collection_type, check_type};
614
        use super::*;
615
616
        proptest! {
617
            #[test]
618
            fn check(value: String, tag in MIN_TAG..=MAX_TAG) {
619
                super::test::check_type(value, tag, WireType::LengthDelimited,
620
                                        encode, merge, encoded_len)?;
621
            }
622
            #[test]
623
            fn check_repeated(value: Vec<String>, tag in MIN_TAG..=MAX_TAG) {
624
                super::test::check_collection_type(value, tag, WireType::LengthDelimited,
625
                                                   encode_repeated, merge_repeated,
626
                                                   encoded_len_repeated)?;
627
            }
628
        }
629
    }
630
}
631
632
pub trait BytesAdapter: sealed::BytesAdapter {}
633
634
mod sealed {
635
    use super::{Buf, BufMut};
636
637
    pub trait BytesAdapter: Default + Sized + 'static {
638
        fn len(&self) -> usize;
639
640
        /// Replace contents of this buffer with the contents of another buffer.
641
        fn replace_with(&mut self, buf: impl Buf);
642
643
        /// Appends this buffer to the (contents of) other buffer.
644
        fn append_to(&self, buf: &mut impl BufMut);
645
646
0
        fn is_empty(&self) -> bool {
647
0
            self.len() == 0
648
0
        }
649
    }
650
}
651
652
impl BytesAdapter for Bytes {}
653
654
impl sealed::BytesAdapter for Bytes {
655
0
    fn len(&self) -> usize {
656
0
        Buf::remaining(self)
657
0
    }
658
659
0
    fn replace_with(&mut self, mut buf: impl Buf) {
660
0
        *self = buf.copy_to_bytes(buf.remaining());
661
0
    }
662
663
0
    fn append_to(&self, buf: &mut impl BufMut) {
664
0
        buf.put(self.clone())
665
0
    }
666
}
667
668
impl BytesAdapter for Vec<u8> {}
669
670
impl sealed::BytesAdapter for Vec<u8> {
671
0
    fn len(&self) -> usize {
672
0
        Vec::len(self)
673
0
    }
674
675
0
    fn replace_with(&mut self, buf: impl Buf) {
676
0
        self.clear();
677
0
        self.reserve(buf.remaining());
678
0
        self.put(buf);
679
0
    }
680
681
0
    fn append_to(&self, buf: &mut impl BufMut) {
682
0
        buf.put(self.as_slice())
683
0
    }
684
}
685
686
pub mod bytes {
687
    use crate::error::DecodeErrorKind;
688
689
    use super::*;
690
691
0
    pub fn encode(tag: u32, value: &impl BytesAdapter, buf: &mut impl BufMut) {
692
0
        encode_key(tag, WireType::LengthDelimited, buf);
693
0
        encode_varint(value.len() as u64, buf);
694
0
        value.append_to(buf);
695
0
    }
696
697
0
    pub fn merge(
698
0
        wire_type: WireType,
699
0
        value: &mut impl BytesAdapter,
700
0
        buf: &mut impl Buf,
701
0
        _ctx: DecodeContext,
702
0
    ) -> Result<(), DecodeError> {
703
0
        check_wire_type(WireType::LengthDelimited, wire_type)?;
704
0
        let len = decode_varint(buf)?;
705
0
        if len > buf.remaining() as u64 {
706
0
            return Err(DecodeErrorKind::BufferUnderflow.into());
707
0
        }
708
0
        let len = len as usize;
709
710
        // Clear the existing value. This follows from the following rule in the encoding guide[1]:
711
        //
712
        // > Normally, an encoded message would never have more than one instance of a non-repeated
713
        // > field. However, parsers are expected to handle the case in which they do. For numeric
714
        // > types and strings, if the same field appears multiple times, the parser accepts the
715
        // > last value it sees.
716
        //
717
        // [1]: https://protobuf.dev/programming-guides/encoding/#last-one-wins
718
        //
719
        // This is intended for A and B both being Bytes so it is zero-copy.
720
        // Some combinations of A and B types may cause a double-copy,
721
        // in which case merge_one_copy() should be used instead.
722
0
        value.replace_with(buf.copy_to_bytes(len));
723
0
        Ok(())
724
0
    }
725
726
0
    pub(super) fn merge_one_copy(
727
0
        wire_type: WireType,
728
0
        value: &mut impl BytesAdapter,
729
0
        buf: &mut impl Buf,
730
0
        _ctx: DecodeContext,
731
0
    ) -> Result<(), DecodeError> {
732
0
        check_wire_type(WireType::LengthDelimited, wire_type)?;
733
0
        let len = decode_varint(buf)?;
734
0
        if len > buf.remaining() as u64 {
735
0
            return Err(DecodeErrorKind::BufferUnderflow.into());
736
0
        }
737
0
        let len = len as usize;
738
739
        // If we must copy, make sure to copy only once.
740
0
        value.replace_with(buf.take(len));
741
0
        Ok(())
742
0
    }
743
744
    length_delimited!(impl BytesAdapter);
745
746
    #[cfg(test)]
747
    mod test {
748
        use proptest::prelude::*;
749
750
        use super::super::test::{check_collection_type, check_type};
751
        use super::*;
752
753
        proptest! {
754
            #[test]
755
            fn check_vec(value: Vec<u8>, tag in MIN_TAG..=MAX_TAG) {
756
                super::test::check_type::<Vec<u8>, Vec<u8>>(value, tag, WireType::LengthDelimited,
757
                                                            encode, merge, encoded_len)?;
758
            }
759
760
            #[test]
761
            fn check_bytes(value: Vec<u8>, tag in MIN_TAG..=MAX_TAG) {
762
                let value = Bytes::from(value);
763
                super::test::check_type::<Bytes, Bytes>(value, tag, WireType::LengthDelimited,
764
                                                        encode, merge, encoded_len)?;
765
            }
766
767
            #[test]
768
            fn check_repeated_vec(value: Vec<Vec<u8>>, tag in MIN_TAG..=MAX_TAG) {
769
                super::test::check_collection_type(value, tag, WireType::LengthDelimited,
770
                                                   encode_repeated, merge_repeated,
771
                                                   encoded_len_repeated)?;
772
            }
773
774
            #[test]
775
            fn check_repeated_bytes(value: Vec<Vec<u8>>, tag in MIN_TAG..=MAX_TAG) {
776
                let value = value.into_iter().map(Bytes::from).collect();
777
                super::test::check_collection_type(value, tag, WireType::LengthDelimited,
778
                                                   encode_repeated, merge_repeated,
779
                                                   encoded_len_repeated)?;
780
            }
781
        }
782
    }
783
}
784
785
pub mod message {
786
    use super::*;
787
788
0
    pub fn encode<M>(tag: u32, msg: &M, buf: &mut impl BufMut)
789
0
    where
790
0
        M: Message,
791
    {
792
0
        encode_key(tag, WireType::LengthDelimited, buf);
793
0
        encode_varint(msg.encoded_len() as u64, buf);
794
0
        msg.encode_raw(buf);
795
0
    }
796
797
0
    pub fn merge<M, B>(
798
0
        wire_type: WireType,
799
0
        msg: &mut M,
800
0
        buf: &mut B,
801
0
        ctx: DecodeContext,
802
0
    ) -> Result<(), DecodeError>
803
0
    where
804
0
        M: Message,
805
0
        B: Buf,
806
    {
807
0
        check_wire_type(WireType::LengthDelimited, wire_type)?;
808
0
        ctx.limit_reached()?;
809
0
        merge_loop(
810
0
            msg,
811
0
            buf,
812
0
            ctx.enter_recursion(),
813
0
            |msg: &mut M, buf: &mut B, ctx| {
814
0
                let (tag, wire_type) = decode_key(buf)?;
815
0
                msg.merge_field(tag, wire_type, buf, ctx)
816
0
            },
817
        )
818
0
    }
819
820
0
    pub fn encode_repeated<M>(tag: u32, messages: &[M], buf: &mut impl BufMut)
821
0
    where
822
0
        M: Message,
823
    {
824
0
        for msg in messages {
825
0
            encode(tag, msg, buf);
826
0
        }
827
0
    }
828
829
0
    pub fn merge_repeated<M>(
830
0
        wire_type: WireType,
831
0
        messages: &mut Vec<M>,
832
0
        buf: &mut impl Buf,
833
0
        ctx: DecodeContext,
834
0
    ) -> Result<(), DecodeError>
835
0
    where
836
0
        M: Message + Default,
837
    {
838
0
        check_wire_type(WireType::LengthDelimited, wire_type)?;
839
0
        let mut msg = M::default();
840
0
        merge(WireType::LengthDelimited, &mut msg, buf, ctx)?;
841
0
        messages.push(msg);
842
0
        Ok(())
843
0
    }
844
845
    #[inline]
846
0
    pub fn encoded_len<M>(tag: u32, msg: &M) -> usize
847
0
    where
848
0
        M: Message,
849
    {
850
0
        let len = msg.encoded_len();
851
0
        key_len(tag) + encoded_len_varint(len as u64) + len
852
0
    }
853
854
    #[inline]
855
0
    pub fn encoded_len_repeated<M>(tag: u32, messages: &[M]) -> usize
856
0
    where
857
0
        M: Message,
858
    {
859
0
        key_len(tag) * messages.len()
860
0
            + messages
861
0
                .iter()
862
0
                .map(Message::encoded_len)
863
0
                .map(|len| len + encoded_len_varint(len as u64))
864
0
                .sum::<usize>()
865
0
    }
866
}
867
868
pub mod group {
869
    use crate::error::DecodeErrorKind;
870
871
    use super::*;
872
873
0
    pub fn encode<M>(tag: u32, msg: &M, buf: &mut impl BufMut)
874
0
    where
875
0
        M: Message,
876
    {
877
0
        encode_key(tag, WireType::StartGroup, buf);
878
0
        msg.encode_raw(buf);
879
0
        encode_key(tag, WireType::EndGroup, buf);
880
0
    }
881
882
0
    pub fn merge<M>(
883
0
        tag: u32,
884
0
        wire_type: WireType,
885
0
        msg: &mut M,
886
0
        buf: &mut impl Buf,
887
0
        ctx: DecodeContext,
888
0
    ) -> Result<(), DecodeError>
889
0
    where
890
0
        M: Message,
891
    {
892
0
        check_wire_type(WireType::StartGroup, wire_type)?;
893
894
0
        ctx.limit_reached()?;
895
        loop {
896
0
            let (field_tag, field_wire_type) = decode_key(buf)?;
897
0
            if field_wire_type == WireType::EndGroup {
898
0
                if field_tag != tag {
899
0
                    return Err(DecodeErrorKind::UnexpectedEndGroupTag.into());
900
0
                }
901
0
                return Ok(());
902
0
            }
903
904
0
            M::merge_field(msg, field_tag, field_wire_type, buf, ctx.enter_recursion())?;
905
        }
906
0
    }
907
908
0
    pub fn encode_repeated<M>(tag: u32, messages: &[M], buf: &mut impl BufMut)
909
0
    where
910
0
        M: Message,
911
    {
912
0
        for msg in messages {
913
0
            encode(tag, msg, buf);
914
0
        }
915
0
    }
916
917
0
    pub fn merge_repeated<M>(
918
0
        tag: u32,
919
0
        wire_type: WireType,
920
0
        messages: &mut Vec<M>,
921
0
        buf: &mut impl Buf,
922
0
        ctx: DecodeContext,
923
0
    ) -> Result<(), DecodeError>
924
0
    where
925
0
        M: Message + Default,
926
    {
927
0
        check_wire_type(WireType::StartGroup, wire_type)?;
928
0
        let mut msg = M::default();
929
0
        merge(tag, WireType::StartGroup, &mut msg, buf, ctx)?;
930
0
        messages.push(msg);
931
0
        Ok(())
932
0
    }
933
934
    #[inline]
935
0
    pub fn encoded_len<M>(tag: u32, msg: &M) -> usize
936
0
    where
937
0
        M: Message,
938
    {
939
0
        2 * key_len(tag) + msg.encoded_len()
940
0
    }
941
942
    #[inline]
943
0
    pub fn encoded_len_repeated<M>(tag: u32, messages: &[M]) -> usize
944
0
    where
945
0
        M: Message,
946
    {
947
0
        2 * key_len(tag) * messages.len() + messages.iter().map(Message::encoded_len).sum::<usize>()
948
0
    }
949
}
950
951
/// Rust doesn't have a `Map` trait, so macros are currently the best way to be
952
/// generic over `HashMap` and `BTreeMap`.
953
macro_rules! map {
954
    ($map_ty:ident) => {
955
        use crate::encoding::*;
956
        use core::hash::Hash;
957
958
        /// Generic protobuf map encode function.
959
0
        pub fn encode<K, V, B, KE, KL, VE, VL>(
960
0
            key_encode: KE,
961
0
            key_encoded_len: KL,
962
0
            val_encode: VE,
963
0
            val_encoded_len: VL,
964
0
            tag: u32,
965
0
            values: &$map_ty<K, V>,
966
0
            buf: &mut B,
967
0
        ) where
968
0
            K: Default + Eq + Hash + Ord,
969
0
            V: Default + PartialEq,
970
0
            B: BufMut,
971
0
            KE: Fn(u32, &K, &mut B),
972
0
            KL: Fn(u32, &K) -> usize,
973
0
            VE: Fn(u32, &V, &mut B),
974
0
            VL: Fn(u32, &V) -> usize,
975
        {
976
0
            encode_with_default(
977
0
                key_encode,
978
0
                key_encoded_len,
979
0
                val_encode,
980
0
                val_encoded_len,
981
0
                &V::default(),
982
0
                tag,
983
0
                values,
984
0
                buf,
985
            )
986
0
        }
Unexecuted instantiation: prost::encoding::hash_map::encode::<_, _, _, _, _, _, _>
Unexecuted instantiation: prost::encoding::btree_map::encode::<_, _, _, _, _, _, _>
987
988
        /// Generic protobuf map merge function.
989
0
        pub fn merge<K, V, B, KM, VM>(
990
0
            key_merge: KM,
991
0
            val_merge: VM,
992
0
            values: &mut $map_ty<K, V>,
993
0
            buf: &mut B,
994
0
            ctx: DecodeContext,
995
0
        ) -> Result<(), DecodeError>
996
0
        where
997
0
            K: Default + Eq + Hash + Ord,
998
0
            V: Default,
999
0
            B: Buf,
1000
0
            KM: Fn(WireType, &mut K, &mut B, DecodeContext) -> Result<(), DecodeError>,
1001
0
            VM: Fn(WireType, &mut V, &mut B, DecodeContext) -> Result<(), DecodeError>,
1002
        {
1003
0
            merge_with_default(key_merge, val_merge, V::default(), values, buf, ctx)
1004
0
        }
Unexecuted instantiation: prost::encoding::hash_map::merge::<_, _, _, _, _>
Unexecuted instantiation: prost::encoding::btree_map::merge::<_, _, _, _, _>
1005
1006
        /// Generic protobuf map encode function.
1007
0
        pub fn encoded_len<K, V, KL, VL>(
1008
0
            key_encoded_len: KL,
1009
0
            val_encoded_len: VL,
1010
0
            tag: u32,
1011
0
            values: &$map_ty<K, V>,
1012
0
        ) -> usize
1013
0
        where
1014
0
            K: Default + Eq + Hash + Ord,
1015
0
            V: Default + PartialEq,
1016
0
            KL: Fn(u32, &K) -> usize,
1017
0
            VL: Fn(u32, &V) -> usize,
1018
        {
1019
0
            encoded_len_with_default(key_encoded_len, val_encoded_len, &V::default(), tag, values)
1020
0
        }
Unexecuted instantiation: prost::encoding::hash_map::encoded_len::<_, _, _, _>
Unexecuted instantiation: prost::encoding::btree_map::encoded_len::<_, _, _, _>
1021
1022
        /// Generic protobuf map encode function with an overridden value default.
1023
        ///
1024
        /// This is necessary because enumeration values can have a default value other
1025
        /// than 0 in proto2.
1026
0
        pub fn encode_with_default<K, V, B, KE, KL, VE, VL>(
1027
0
            key_encode: KE,
1028
0
            key_encoded_len: KL,
1029
0
            val_encode: VE,
1030
0
            val_encoded_len: VL,
1031
0
            val_default: &V,
1032
0
            tag: u32,
1033
0
            values: &$map_ty<K, V>,
1034
0
            buf: &mut B,
1035
0
        ) where
1036
0
            K: Default + Eq + Hash + Ord,
1037
0
            V: PartialEq,
1038
0
            B: BufMut,
1039
0
            KE: Fn(u32, &K, &mut B),
1040
0
            KL: Fn(u32, &K) -> usize,
1041
0
            VE: Fn(u32, &V, &mut B),
1042
0
            VL: Fn(u32, &V) -> usize,
1043
        {
1044
0
            for (key, val) in values.iter() {
1045
0
                let skip_key = key == &K::default();
1046
0
                let skip_val = val == val_default;
1047
1048
0
                let len = (if skip_key { 0 } else { key_encoded_len(1, key) })
1049
0
                    + (if skip_val { 0 } else { val_encoded_len(2, val) });
1050
1051
0
                encode_key(tag, WireType::LengthDelimited, buf);
1052
0
                encode_varint(len as u64, buf);
1053
0
                if !skip_key {
1054
0
                    key_encode(1, key, buf);
1055
0
                }
1056
0
                if !skip_val {
1057
0
                    val_encode(2, val, buf);
1058
0
                }
1059
            }
1060
0
        }
Unexecuted instantiation: prost::encoding::hash_map::encode_with_default::<_, _, _, _, _, _, _>
Unexecuted instantiation: prost::encoding::btree_map::encode_with_default::<_, _, _, _, _, _, _>
1061
1062
        /// Generic protobuf map merge function with an overridden value default.
1063
        ///
1064
        /// This is necessary because enumeration values can have a default value other
1065
        /// than 0 in proto2.
1066
0
        pub fn merge_with_default<K, V, B, KM, VM>(
1067
0
            key_merge: KM,
1068
0
            val_merge: VM,
1069
0
            val_default: V,
1070
0
            values: &mut $map_ty<K, V>,
1071
0
            buf: &mut B,
1072
0
            ctx: DecodeContext,
1073
0
        ) -> Result<(), DecodeError>
1074
0
        where
1075
0
            K: Default + Eq + Hash + Ord,
1076
0
            B: Buf,
1077
0
            KM: Fn(WireType, &mut K, &mut B, DecodeContext) -> Result<(), DecodeError>,
1078
0
            VM: Fn(WireType, &mut V, &mut B, DecodeContext) -> Result<(), DecodeError>,
1079
        {
1080
0
            let mut key = Default::default();
1081
0
            let mut val = val_default;
1082
0
            ctx.limit_reached()?;
1083
0
            merge_loop(
1084
0
                &mut (&mut key, &mut val),
1085
0
                buf,
1086
0
                ctx.enter_recursion(),
1087
0
                |&mut (ref mut key, ref mut val), buf, ctx| {
1088
0
                    let (tag, wire_type) = decode_key(buf)?;
1089
0
                    match tag {
1090
0
                        1 => key_merge(wire_type, key, buf, ctx),
1091
0
                        2 => val_merge(wire_type, val, buf, ctx),
1092
0
                        _ => skip_field(wire_type, tag, buf, ctx),
1093
                    }
1094
0
                },
Unexecuted instantiation: prost::encoding::hash_map::merge_with_default::<_, _, _, _, _>::{closure#0}
Unexecuted instantiation: prost::encoding::btree_map::merge_with_default::<_, _, _, _, _>::{closure#0}
1095
0
            )?;
1096
0
            values.insert(key, val);
1097
1098
0
            Ok(())
1099
0
        }
Unexecuted instantiation: prost::encoding::hash_map::merge_with_default::<_, _, _, _, _>
Unexecuted instantiation: prost::encoding::btree_map::merge_with_default::<_, _, _, _, _>
1100
1101
        /// Generic protobuf map encode function with an overridden value default.
1102
        ///
1103
        /// This is necessary because enumeration values can have a default value other
1104
        /// than 0 in proto2.
1105
0
        pub fn encoded_len_with_default<K, V, KL, VL>(
1106
0
            key_encoded_len: KL,
1107
0
            val_encoded_len: VL,
1108
0
            val_default: &V,
1109
0
            tag: u32,
1110
0
            values: &$map_ty<K, V>,
1111
0
        ) -> usize
1112
0
        where
1113
0
            K: Default + Eq + Hash + Ord,
1114
0
            V: PartialEq,
1115
0
            KL: Fn(u32, &K) -> usize,
1116
0
            VL: Fn(u32, &V) -> usize,
1117
        {
1118
0
            key_len(tag) * values.len()
1119
0
                + values
1120
0
                    .iter()
1121
0
                    .map(|(key, val)| {
1122
0
                        let len = (if key == &K::default() {
1123
0
                            0
1124
                        } else {
1125
0
                            key_encoded_len(1, key)
1126
0
                        }) + (if val == val_default {
1127
0
                            0
1128
                        } else {
1129
0
                            val_encoded_len(2, val)
1130
                        });
1131
0
                        encoded_len_varint(len as u64) + len
1132
0
                    })
Unexecuted instantiation: prost::encoding::hash_map::encoded_len_with_default::<_, _, _, _>::{closure#0}
Unexecuted instantiation: prost::encoding::btree_map::encoded_len_with_default::<_, _, _, _>::{closure#0}
1133
0
                    .sum::<usize>()
1134
0
        }
Unexecuted instantiation: prost::encoding::hash_map::encoded_len_with_default::<_, _, _, _>
Unexecuted instantiation: prost::encoding::btree_map::encoded_len_with_default::<_, _, _, _>
1135
    };
1136
}
1137
1138
#[cfg(feature = "std")]
1139
pub mod hash_map {
1140
    use std::collections::HashMap;
1141
    map!(HashMap);
1142
}
1143
1144
pub mod btree_map {
1145
    map!(BTreeMap);
1146
}
1147
1148
#[cfg(test)]
1149
mod test {
1150
    #[cfg(not(feature = "std"))]
1151
    use alloc::string::ToString;
1152
    use core::borrow::Borrow;
1153
    use core::fmt::Debug;
1154
1155
    use ::bytes::BytesMut;
1156
    use proptest::{prelude::*, test_runner::TestCaseResult};
1157
1158
    use super::*;
1159
1160
    pub fn check_type<T, B>(
1161
        value: T,
1162
        tag: u32,
1163
        wire_type: WireType,
1164
        encode: fn(u32, &B, &mut BytesMut),
1165
        merge: fn(WireType, &mut T, &mut Bytes, DecodeContext) -> Result<(), DecodeError>,
1166
        encoded_len: fn(u32, &B) -> usize,
1167
    ) -> TestCaseResult
1168
    where
1169
        T: Debug + Default + PartialEq + Borrow<B>,
1170
        B: ?Sized,
1171
    {
1172
        prop_assume!((MIN_TAG..=MAX_TAG).contains(&tag));
1173
1174
        let expected_len = encoded_len(tag, value.borrow());
1175
1176
        let mut buf = BytesMut::with_capacity(expected_len);
1177
        encode(tag, value.borrow(), &mut buf);
1178
1179
        let mut buf = buf.freeze();
1180
1181
        prop_assert_eq!(
1182
            buf.remaining(),
1183
            expected_len,
1184
            "encoded_len wrong; expected: {}, actual: {}",
1185
            expected_len,
1186
            buf.remaining()
1187
        );
1188
1189
        if !buf.has_remaining() {
1190
            // Short circuit for empty packed values.
1191
            return Ok(());
1192
        }
1193
1194
        let (decoded_tag, decoded_wire_type) =
1195
            decode_key(&mut buf).map_err(|error| TestCaseError::fail(error.to_string()))?;
1196
        prop_assert_eq!(
1197
            tag,
1198
            decoded_tag,
1199
            "decoded tag does not match; expected: {}, actual: {}",
1200
            tag,
1201
            decoded_tag
1202
        );
1203
1204
        prop_assert_eq!(
1205
            wire_type,
1206
            decoded_wire_type,
1207
            "decoded wire type does not match; expected: {:?}, actual: {:?}",
1208
            wire_type,
1209
            decoded_wire_type,
1210
        );
1211
1212
        match wire_type {
1213
            WireType::SixtyFourBit if buf.remaining() != 8 => Err(TestCaseError::fail(format!(
1214
                "64bit wire type illegal remaining: {}, tag: {}",
1215
                buf.remaining(),
1216
                tag
1217
            ))),
1218
            WireType::ThirtyTwoBit if buf.remaining() != 4 => Err(TestCaseError::fail(format!(
1219
                "32bit wire type illegal remaining: {}, tag: {}",
1220
                buf.remaining(),
1221
                tag
1222
            ))),
1223
            _ => Ok(()),
1224
        }?;
1225
1226
        let mut roundtrip_value = T::default();
1227
        merge(
1228
            wire_type,
1229
            &mut roundtrip_value,
1230
            &mut buf,
1231
            DecodeContext::default(),
1232
        )
1233
        .map_err(|error| TestCaseError::fail(error.to_string()))?;
1234
1235
        prop_assert!(
1236
            !buf.has_remaining(),
1237
            "expected buffer to be empty, remaining: {}",
1238
            buf.remaining()
1239
        );
1240
1241
        prop_assert_eq!(value, roundtrip_value);
1242
1243
        Ok(())
1244
    }
1245
1246
    pub fn check_collection_type<T, B, E, M, L>(
1247
        value: T,
1248
        tag: u32,
1249
        wire_type: WireType,
1250
        encode: E,
1251
        mut merge: M,
1252
        encoded_len: L,
1253
    ) -> TestCaseResult
1254
    where
1255
        T: Debug + Default + PartialEq + Borrow<B>,
1256
        B: ?Sized,
1257
        E: FnOnce(u32, &B, &mut BytesMut),
1258
        M: FnMut(WireType, &mut T, &mut Bytes, DecodeContext) -> Result<(), DecodeError>,
1259
        L: FnOnce(u32, &B) -> usize,
1260
    {
1261
        prop_assume!((MIN_TAG..=MAX_TAG).contains(&tag));
1262
1263
        let expected_len = encoded_len(tag, value.borrow());
1264
1265
        let mut buf = BytesMut::with_capacity(expected_len);
1266
        encode(tag, value.borrow(), &mut buf);
1267
1268
        let mut buf = buf.freeze();
1269
1270
        prop_assert_eq!(
1271
            buf.remaining(),
1272
            expected_len,
1273
            "encoded_len wrong; expected: {}, actual: {}",
1274
            expected_len,
1275
            buf.remaining()
1276
        );
1277
1278
        let mut roundtrip_value = Default::default();
1279
        while buf.has_remaining() {
1280
            let (decoded_tag, decoded_wire_type) =
1281
                decode_key(&mut buf).map_err(|error| TestCaseError::fail(error.to_string()))?;
1282
1283
            prop_assert_eq!(
1284
                tag,
1285
                decoded_tag,
1286
                "decoded tag does not match; expected: {}, actual: {}",
1287
                tag,
1288
                decoded_tag
1289
            );
1290
1291
            prop_assert_eq!(
1292
                wire_type,
1293
                decoded_wire_type,
1294
                "decoded wire type does not match; expected: {:?}, actual: {:?}",
1295
                wire_type,
1296
                decoded_wire_type
1297
            );
1298
1299
            merge(
1300
                wire_type,
1301
                &mut roundtrip_value,
1302
                &mut buf,
1303
                DecodeContext::default(),
1304
            )
1305
            .map_err(|error| TestCaseError::fail(error.to_string()))?;
1306
        }
1307
1308
        prop_assert_eq!(value, roundtrip_value);
1309
1310
        Ok(())
1311
    }
1312
1313
    #[test]
1314
    fn string_merge_invalid_utf8() {
1315
        let mut s = String::new();
1316
        let buf = b"\x02\x80\x80";
1317
1318
        let r = string::merge(
1319
            WireType::LengthDelimited,
1320
            &mut s,
1321
            &mut &buf[..],
1322
            DecodeContext::default(),
1323
        );
1324
        r.expect_err("must be an error");
1325
        assert!(s.is_empty());
1326
    }
1327
1328
    /// This big bowl o' macro soup generates an encoding property test for each combination of map
1329
    /// type, scalar map key, and value type.
1330
    /// TODO: these tests take a long time to compile, can this be improved?
1331
    #[cfg(feature = "std")]
1332
    macro_rules! map_tests {
1333
        (keys: $keys:tt,
1334
         vals: $vals:tt) => {
1335
            mod hash_map {
1336
                map_tests!(@private HashMap, hash_map, $keys, $vals);
1337
            }
1338
            mod btree_map {
1339
                map_tests!(@private BTreeMap, btree_map, $keys, $vals);
1340
            }
1341
        };
1342
1343
        (@private $map_type:ident,
1344
                  $mod_name:ident,
1345
                  [$(($key_ty:ty, $key_proto:ident)),*],
1346
                  $vals:tt) => {
1347
            $(
1348
                mod $key_proto {
1349
                    use std::collections::$map_type;
1350
1351
                    use proptest::prelude::*;
1352
1353
                    use crate::encoding::*;
1354
                    use crate::encoding::test::check_collection_type;
1355
1356
                    map_tests!(@private $map_type, $mod_name, ($key_ty, $key_proto), $vals);
1357
                }
1358
            )*
1359
        };
1360
1361
        (@private $map_type:ident,
1362
                  $mod_name:ident,
1363
                  ($key_ty:ty, $key_proto:ident),
1364
                  [$(($val_ty:ty, $val_proto:ident)),*]) => {
1365
            $(
1366
                proptest! {
1367
                    #[test]
1368
                    fn $val_proto(values: $map_type<$key_ty, $val_ty>, tag in MIN_TAG..=MAX_TAG) {
1369
                        check_collection_type(values, tag, WireType::LengthDelimited,
1370
                                              |tag, values, buf| {
1371
                                                  $mod_name::encode($key_proto::encode,
1372
                                                                    $key_proto::encoded_len,
1373
                                                                    $val_proto::encode,
1374
                                                                    $val_proto::encoded_len,
1375
                                                                    tag,
1376
                                                                    values,
1377
                                                                    buf)
1378
                                              },
1379
                                              |wire_type, values, buf, ctx| {
1380
                                                  check_wire_type(WireType::LengthDelimited, wire_type)?;
1381
                                                  $mod_name::merge($key_proto::merge,
1382
                                                                   $val_proto::merge,
1383
                                                                   values,
1384
                                                                   buf,
1385
                                                                   ctx)
1386
                                              },
1387
                                              |tag, values| {
1388
                                                  $mod_name::encoded_len($key_proto::encoded_len,
1389
                                                                         $val_proto::encoded_len,
1390
                                                                         tag,
1391
                                                                         values)
1392
                                              })?;
1393
                    }
1394
                }
1395
             )*
1396
        };
1397
    }
1398
1399
    #[cfg(feature = "std")]
1400
    map_tests!(keys: [
1401
        (i32, int32),
1402
        (i64, int64),
1403
        (u32, uint32),
1404
        (u64, uint64),
1405
        (i32, sint32),
1406
        (i64, sint64),
1407
        (u32, fixed32),
1408
        (u64, fixed64),
1409
        (i32, sfixed32),
1410
        (i64, sfixed64),
1411
        (bool, bool),
1412
        (String, string)
1413
    ],
1414
    vals: [
1415
        (f32, float),
1416
        (f64, double),
1417
        (i32, int32),
1418
        (i64, int64),
1419
        (u32, uint32),
1420
        (u64, uint64),
1421
        (i32, sint32),
1422
        (i64, sint64),
1423
        (u32, fixed32),
1424
        (u64, fixed64),
1425
        (i32, sfixed32),
1426
        (i64, sfixed64),
1427
        (bool, bool),
1428
        (String, string),
1429
        (Vec<u8>, bytes)
1430
    ]);
1431
1432
    #[test]
1433
    /// `decode_varint` accepts a `Buf`, which can be multiple concatenated buffers.
1434
    /// This test ensures that future optimizations don't break the
1435
    /// `decode_varint` for non-continuous memory.
1436
    fn split_varint_decoding() {
1437
        let mut test_values = Vec::<u64>::with_capacity(10 * 2);
1438
        test_values.push(128);
1439
        for i in 2..9 {
1440
            test_values.push((1 << (7 * i)) - 1);
1441
            test_values.push(1 << (7 * i));
1442
        }
1443
1444
        for v in test_values {
1445
            let mut buf = BytesMut::with_capacity(10);
1446
            encode_varint(v, &mut buf);
1447
            let half_len = buf.len() / 2;
1448
            let len = buf.len();
1449
            // this weird sequence here splits the buffer into two instances of Bytes
1450
            // which we then stitch together with `bytes::buf::Buf::chain`
1451
            // which ensures the varint bytes are not in a single chunk
1452
            let b2 = buf.split_off(half_len);
1453
            let mut c = buf.chain(b2);
1454
1455
            // make sure all the bytes are inside
1456
            assert_eq!(c.remaining(), len);
1457
            // make sure the first chunk is split as we expected
1458
            assert_eq!(c.chunk().len(), half_len);
1459
            assert_eq!(v, decode_varint(&mut c).unwrap());
1460
        }
1461
    }
1462
}