Skip to main content

libmaxminddb_rs/
traits.rs

1//! Traits used by derive macros and borrowed decoding.
2
3use std::collections::BTreeMap;
4
5use crate::decoder::RawDecoder;
6use crate::{Error, Result, Value, ValueRef};
7
8/// Trait implemented by `#[derive(MmdbDecode)]`.
9///
10/// Implement this trait manually for custom decoding behavior, or derive it
11/// for a typed MMDB map. Borrowed fields must not outlive the source bytes.
12pub trait MmdbDecode<'a>: Sized {
13    /// Decodes one already-parsed MMDB value into `Self`.
14    /// Returns a type-mismatch error if required fields are absent or invalid.
15    ///
16    /// # Examples
17    ///
18    /// ```rust
19    /// # #[cfg(feature = "derive")]
20    /// # fn main() -> Result<(), libmaxminddb_rs::Error> {
21    /// use libmaxminddb_rs::{MmdbDecode, ValueRef};
22    /// #[derive(MmdbDecode)]
23    /// struct Record<'a> { category: &'a str }
24    /// let value = ValueRef::Map(vec![("category", ValueRef::Utf8("example"))]);
25    /// let record = Record::decode(&value)?;
26    /// assert_eq!(record.category, "example");
27    /// # Ok(())
28    /// # }
29    /// # #[cfg(not(feature = "derive"))] fn main() {}
30    /// ```
31    fn decode(value: &ValueRef<'a>) -> Result<Self>;
32
33    /// Decodes `Self` straight from the encoded record under `decoder`.
34    ///
35    /// `Reader::lookup_borrowed` calls this method. The derive overrides it
36    /// with an allocation-free, single-pass decoder; the default keeps
37    /// hand-written implementations working by materializing a [`ValueRef`]
38    /// and delegating to [`MmdbDecode::decode`].
39    #[doc(hidden)]
40    #[inline]
41    fn decode_raw(decoder: &mut RawDecoder<'a>) -> Result<Self> {
42        let value = decoder.read_value()?;
43        Self::decode(&value)
44    }
45}
46
47/// Trait implemented by `#[derive(MmdbEncode)]`.
48pub trait MmdbEncode {
49    /// Encodes `Self` into the writer's owned MMDB value model.
50    /// Returns an encoding error for an unsupported field value.
51    ///
52    /// # Examples
53    ///
54    /// ```rust
55    /// # #[cfg(feature = "derive")]
56    /// # fn main() -> Result<(), libmaxminddb_rs::Error> {
57    /// use libmaxminddb_rs::{MmdbEncode, Value};
58    /// #[derive(MmdbEncode)]
59    /// struct Record { asn: u32 }
60    /// let value = Record { asn: 64512 }.encode()?;
61    /// assert!(matches!(value, Value::Map(_)));
62    /// # Ok(())
63    /// # }
64    /// # #[cfg(not(feature = "derive"))] fn main() {}
65    /// ```
66    fn encode(&self) -> Result<Value>;
67}
68
69/// Trait for a custom record that carries its own network/CIDR.
70///
71/// `#[derive(MmdbRecord)]` implements this trait when one field is annotated with
72/// `#[mmdb(network)]`. Pair it with `#[derive(MmdbEncode)]`; the network field is then
73/// excluded from the encoded MMDB payload.
74pub trait MmdbRecord: MmdbEncode {
75    /// Returns the network to which this record should be attached.
76    ///
77    /// # Examples
78    ///
79    /// ```rust
80    /// # #[cfg(feature = "derive")]
81    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
82    /// use libmaxminddb_rs::{IpNetwork, MmdbEncode, MmdbRecord};
83    /// #[derive(MmdbEncode, MmdbRecord)]
84    /// struct Record { #[mmdb(network)] network: IpNetwork, asn: u32 }
85    /// let record = Record { network: "198.51.100.0/24".parse()?, asn: 64512 };
86    /// assert_eq!(record.network().to_string(), "198.51.100.0/24");
87    /// # Ok(())
88    /// # }
89    /// # #[cfg(not(feature = "derive"))] fn main() {}
90    /// ```
91    fn network(&self) -> crate::IpNetwork;
92}
93
94/// Internal/public field decoder used by generated implementations.
95pub trait DecodeField<'a>: Sized {
96    /// Decodes an optional map field into this field type.
97    /// Returns an error when a required field is absent or has the wrong type.
98    ///
99    /// # Examples
100    ///
101    /// ```rust
102    /// use libmaxminddb_rs::{DecodeField, ValueRef};
103    /// let value = ValueRef::Utf8("example");
104    /// let category = <&str>::decode_field(Some(&value))?;
105    /// assert_eq!(category, "example");
106    /// # Ok::<(), libmaxminddb_rs::Error>(())
107    /// ```
108    fn decode_field(value: Option<&ValueRef<'a>>) -> Result<Self>;
109
110    /// Decodes a present field straight from the encoded value under
111    /// `decoder`, without building a [`ValueRef`].
112    ///
113    /// The built-in implementations never allocate (except `String`, `Vec`
114    /// and `BTreeMap`, which own their contents). The default materializes a
115    /// [`ValueRef`] and delegates to [`DecodeField::decode_field`].
116    #[doc(hidden)]
117    #[inline]
118    fn decode_raw(decoder: &mut RawDecoder<'a>) -> Result<Self> {
119        let value = decoder.read_value()?;
120        Self::decode_field(Some(&value))
121    }
122
123    /// Value for a field that is absent from the record.
124    #[doc(hidden)]
125    #[inline]
126    fn decode_missing() -> Result<Self> {
127        Self::decode_field(None)
128    }
129}
130
131/// Internal/public field encoder used by generated implementations.
132pub trait EncodeField {
133    /// Encodes one struct field into an MMDB value.
134    ///
135    /// # Examples
136    ///
137    /// ```rust
138    /// use libmaxminddb_rs::{EncodeField, Value};
139    /// assert_eq!(64512_u32.encode_field()?, Value::Uint32(64512));
140    /// # Ok::<(), libmaxminddb_rs::Error>(())
141    /// ```
142    fn encode_field(&self) -> Result<Value>;
143
144    /// Encodes a field for insertion into a struct map.
145    ///
146    /// Most field types return `Some(value)`. `Option<T>` overrides this hook so `None`
147    /// omits the field entirely, matching MMDB's lack of a null data type.
148    ///
149    /// # Examples
150    ///
151    /// ```rust
152    /// use libmaxminddb_rs::EncodeField;
153    /// assert!(Option::<u32>::None.encode_optional_field()?.is_none());
154    /// # Ok::<(), libmaxminddb_rs::Error>(())
155    /// ```
156    fn encode_optional_field(&self) -> Result<Option<Value>> {
157        self.encode_field().map(Some)
158    }
159}
160
161impl<'a> DecodeField<'a> for &'a str {
162    fn decode_field(value: Option<&ValueRef<'a>>) -> Result<Self> {
163        match value {
164            Some(ValueRef::Utf8(v)) => Ok(*v),
165            _ => Err(Error::DecodingError("expected UTF-8 string".into())),
166        }
167    }
168
169    #[inline]
170    fn decode_raw(decoder: &mut RawDecoder<'a>) -> Result<Self> {
171        decoder.read_str()
172    }
173}
174
175impl<'a> DecodeField<'a> for &'a [u8] {
176    fn decode_field(value: Option<&ValueRef<'a>>) -> Result<Self> {
177        match value {
178            Some(ValueRef::Bytes(v)) => Ok(*v),
179            _ => Err(Error::DecodingError("expected byte array".into())),
180        }
181    }
182
183    #[inline]
184    fn decode_raw(decoder: &mut RawDecoder<'a>) -> Result<Self> {
185        decoder.read_bytes()
186    }
187}
188
189impl<'a> DecodeField<'a> for String {
190    fn decode_field(value: Option<&ValueRef<'a>>) -> Result<Self> {
191        <&str as DecodeField<'a>>::decode_field(value).map(ToOwned::to_owned)
192    }
193
194    #[inline]
195    fn decode_raw(decoder: &mut RawDecoder<'a>) -> Result<Self> {
196        decoder.read_str().map(ToOwned::to_owned)
197    }
198}
199
200impl<'a, T: DecodeField<'a>> DecodeField<'a> for Option<T> {
201    fn decode_field(value: Option<&ValueRef<'a>>) -> Result<Self> {
202        value.map(|v| T::decode_field(Some(v))).transpose()
203    }
204
205    #[inline]
206    fn decode_raw(decoder: &mut RawDecoder<'a>) -> Result<Self> {
207        T::decode_raw(decoder).map(Some)
208    }
209
210    #[inline]
211    fn decode_missing() -> Result<Self> {
212        Ok(None)
213    }
214}
215
216impl<'a, T: DecodeField<'a>> DecodeField<'a> for Vec<T> {
217    fn decode_field(value: Option<&ValueRef<'a>>) -> Result<Self> {
218        match value {
219            Some(ValueRef::Array(values)) => values
220                .iter()
221                .map(|value| T::decode_field(Some(value)))
222                .collect(),
223            _ => Err(Error::DecodingError("expected array".into())),
224        }
225    }
226
227    #[inline]
228    fn decode_raw(decoder: &mut RawDecoder<'a>) -> Result<Self> {
229        let array = decoder.enter_array("expected array")?;
230        let mut values = Vec::with_capacity(decoder.capacity_hint(array));
231        for _ in 0..array.len() {
232            values.push(T::decode_raw(decoder)?);
233        }
234        decoder.leave(array);
235        Ok(values)
236    }
237}
238
239impl<'a, T: DecodeField<'a>> DecodeField<'a> for BTreeMap<String, T> {
240    fn decode_field(value: Option<&ValueRef<'a>>) -> Result<Self> {
241        match value {
242            Some(ValueRef::Map(values)) => values
243                .iter()
244                .map(|(key, value)| Ok(((*key).to_owned(), T::decode_field(Some(value))?)))
245                .collect(),
246            _ => Err(Error::DecodingError("expected map".into())),
247        }
248    }
249
250    fn decode_raw(decoder: &mut RawDecoder<'a>) -> Result<Self> {
251        let map = decoder.enter_map("expected map")?;
252        let mut entries = BTreeMap::new();
253        for _ in 0..map.len() {
254            let key = decoder.read_key_str()?.to_owned();
255            let value = T::decode_raw(decoder)?;
256            // `collect` into a BTreeMap keeps the last duplicate; match it.
257            entries.insert(key, value);
258        }
259        decoder.leave(map);
260        Ok(entries)
261    }
262}
263
264macro_rules! decode_num {
265    ($ty:ty, $($variant:ident),+ $(,)?) => {
266        impl<'a> DecodeField<'a> for $ty {
267            fn decode_field(value: Option<&ValueRef<'a>>) -> Result<Self> {
268                match value {
269                    $(Some(ValueRef::$variant(v)) => <$ty>::try_from(*v).map_err(|_| Error::DecodingError("numeric conversion failed".into())),)+
270                    _ => Err(Error::DecodingError("expected numeric value".into())),
271                }
272            }
273
274            #[inline]
275            fn decode_raw(decoder: &mut RawDecoder<'a>) -> Result<Self> {
276                let value = decoder.read_u64()?;
277                <$ty>::try_from(value).map_err(|_| conversion_error())
278            }
279        }
280    };
281}
282
283#[cold]
284#[inline(never)]
285fn conversion_error() -> Error {
286    Error::DecodingError("numeric conversion failed".into())
287}
288
289decode_num!(u16, Uint16, Uint32, Uint64);
290decode_num!(u32, Uint16, Uint32, Uint64);
291decode_num!(u64, Uint16, Uint32, Uint64);
292
293impl<'a> DecodeField<'a> for u128 {
294    fn decode_field(value: Option<&ValueRef<'a>>) -> Result<Self> {
295        match value {
296            Some(ValueRef::Uint16(v)) => Ok((*v).into()),
297            Some(ValueRef::Uint32(v)) => Ok((*v).into()),
298            Some(ValueRef::Uint64(v)) => Ok((*v).into()),
299            Some(ValueRef::Uint128(v)) => Ok(*v),
300            _ => Err(Error::DecodingError("expected unsigned integer".into())),
301        }
302    }
303
304    #[inline]
305    fn decode_raw(decoder: &mut RawDecoder<'a>) -> Result<Self> {
306        decoder.read_u128()
307    }
308}
309
310impl<'a> DecodeField<'a> for i32 {
311    fn decode_field(value: Option<&ValueRef<'a>>) -> Result<Self> {
312        match value {
313            Some(ValueRef::Int32(v)) => Ok(*v),
314            _ => Err(Error::DecodingError("expected int32".into())),
315        }
316    }
317
318    #[inline]
319    fn decode_raw(decoder: &mut RawDecoder<'a>) -> Result<Self> {
320        decoder.read_i32()
321    }
322}
323
324impl<'a> DecodeField<'a> for f64 {
325    fn decode_field(value: Option<&ValueRef<'a>>) -> Result<Self> {
326        match value {
327            Some(ValueRef::Double(v)) => Ok(*v),
328            Some(ValueRef::Float(v)) => Ok(f64::from(*v)),
329            _ => Err(Error::DecodingError("expected float/double".into())),
330        }
331    }
332
333    #[inline]
334    fn decode_raw(decoder: &mut RawDecoder<'a>) -> Result<Self> {
335        decoder.read_f64()
336    }
337}
338
339impl<'a> DecodeField<'a> for f32 {
340    fn decode_field(value: Option<&ValueRef<'a>>) -> Result<Self> {
341        match value {
342            Some(ValueRef::Float(v)) => Ok(*v),
343            _ => Err(Error::DecodingError("expected float".into())),
344        }
345    }
346
347    #[inline]
348    fn decode_raw(decoder: &mut RawDecoder<'a>) -> Result<Self> {
349        decoder.read_f32()
350    }
351}
352
353impl<'a> DecodeField<'a> for bool {
354    fn decode_field(value: Option<&ValueRef<'a>>) -> Result<Self> {
355        match value {
356            Some(ValueRef::Bool(v)) => Ok(*v),
357            _ => Err(Error::DecodingError("expected boolean".into())),
358        }
359    }
360
361    #[inline]
362    fn decode_raw(decoder: &mut RawDecoder<'a>) -> Result<Self> {
363        decoder.read_bool()
364    }
365}
366
367impl<T: EncodeField> EncodeField for Option<T> {
368    fn encode_field(&self) -> Result<Value> {
369        self.as_ref()
370            .map(EncodeField::encode_field)
371            .transpose()?
372            .ok_or_else(|| Error::EncodingError("MMDB has no null value".into()))
373    }
374
375    fn encode_optional_field(&self) -> Result<Option<Value>> {
376        self.as_ref().map(EncodeField::encode_field).transpose()
377    }
378}
379
380impl EncodeField for str {
381    fn encode_field(&self) -> Result<Value> {
382        Ok(Value::Utf8(self.to_owned()))
383    }
384}
385impl EncodeField for &str {
386    fn encode_field(&self) -> Result<Value> {
387        Ok(Value::Utf8((*self).to_owned()))
388    }
389}
390impl EncodeField for String {
391    fn encode_field(&self) -> Result<Value> {
392        Ok(Value::Utf8(self.clone()))
393    }
394}
395impl EncodeField for bool {
396    fn encode_field(&self) -> Result<Value> {
397        Ok(Value::Bool(*self))
398    }
399}
400impl EncodeField for f32 {
401    fn encode_field(&self) -> Result<Value> {
402        Ok(Value::Float(*self))
403    }
404}
405impl EncodeField for f64 {
406    fn encode_field(&self) -> Result<Value> {
407        Ok(Value::Double(*self))
408    }
409}
410macro_rules! encode_int {
411    ($ty:ty, $variant:ident) => {
412        impl EncodeField for $ty {
413            fn encode_field(&self) -> Result<Value> {
414                Ok(Value::$variant(*self as _))
415            }
416        }
417    };
418}
419encode_int!(u16, Uint16);
420encode_int!(u32, Uint32);
421encode_int!(u64, Uint64);
422encode_int!(u128, Uint128);
423encode_int!(i32, Int32);
424
425impl<T: EncodeField> EncodeField for Vec<T> {
426    fn encode_field(&self) -> Result<Value> {
427        Ok(Value::Array(
428            self.iter()
429                .map(EncodeField::encode_field)
430                .collect::<Result<_>>()?,
431        ))
432    }
433}
434
435impl<T: EncodeField> EncodeField for [T] {
436    fn encode_field(&self) -> Result<Value> {
437        Ok(Value::Array(
438            self.iter()
439                .map(EncodeField::encode_field)
440                .collect::<Result<_>>()?,
441        ))
442    }
443}
444
445impl<T: EncodeField> EncodeField for BTreeMap<String, T> {
446    fn encode_field(&self) -> Result<Value> {
447        Ok(Value::Map(
448            self.iter()
449                .map(|(k, v)| Ok((k.clone(), v.encode_field()?)))
450                .collect::<Result<_>>()?,
451        ))
452    }
453}
454
455#[cfg(test)]
456mod tests {
457    use std::collections::BTreeMap;
458
459    use super::*;
460
461    #[test]
462    fn string_and_byte_fields_decode_and_reject_wrong_types() {
463        assert_eq!(
464            <&str as DecodeField<'_>>::decode_field(Some(&ValueRef::Utf8("x"))).unwrap(),
465            "x"
466        );
467        assert!(<&str as DecodeField<'_>>::decode_field(Some(&ValueRef::Uint32(1))).is_err());
468        assert!(<&str as DecodeField<'_>>::decode_field(None).is_err());
469
470        assert_eq!(
471            <String as DecodeField<'_>>::decode_field(Some(&ValueRef::Utf8("x"))).unwrap(),
472            "x"
473        );
474        assert!(<String as DecodeField<'_>>::decode_field(None).is_err());
475
476        assert_eq!(
477            <&[u8] as DecodeField<'_>>::decode_field(Some(&ValueRef::Bytes(&[1, 2]))).unwrap(),
478            &[1, 2]
479        );
480        assert!(<&[u8] as DecodeField<'_>>::decode_field(Some(&ValueRef::Utf8("x"))).is_err());
481    }
482
483    #[test]
484    fn option_fields_delegate_and_transpose_errors() {
485        assert_eq!(
486            <Option<&str> as DecodeField<'_>>::decode_field(Some(&ValueRef::Utf8("x"))).unwrap(),
487            Some("x")
488        );
489        assert_eq!(
490            <Option<&str> as DecodeField<'_>>::decode_field(None).unwrap(),
491            None
492        );
493        assert!(
494            <Option<&str> as DecodeField<'_>>::decode_field(Some(&ValueRef::Bool(true))).is_err()
495        );
496    }
497
498    #[test]
499    fn vec_and_map_fields_decode_and_reject() {
500        let array = ValueRef::Array(vec![ValueRef::Uint16(1), ValueRef::Uint16(2)]);
501        assert_eq!(
502            <Vec<u16> as DecodeField<'_>>::decode_field(Some(&array)).unwrap(),
503            vec![1, 2]
504        );
505        let bad = ValueRef::Array(vec![ValueRef::Uint16(1), ValueRef::Utf8("x")]);
506        assert!(<Vec<u16> as DecodeField<'_>>::decode_field(Some(&bad)).is_err());
507        assert!(<Vec<u16> as DecodeField<'_>>::decode_field(Some(&ValueRef::Utf8("x"))).is_err());
508
509        let map = ValueRef::Map(vec![("a", ValueRef::Utf8("x"))]);
510        let decoded =
511            <BTreeMap<String, String> as DecodeField<'_>>::decode_field(Some(&map)).unwrap();
512        assert_eq!(decoded.get("a").map(String::as_str), Some("x"));
513        let bad_map = ValueRef::Map(vec![("a", ValueRef::Bool(true))]);
514        assert!(
515            <BTreeMap<String, String> as DecodeField<'_>>::decode_field(Some(&bad_map)).is_err()
516        );
517        assert!(
518            <BTreeMap<String, String> as DecodeField<'_>>::decode_field(Some(&ValueRef::Array(
519                vec![]
520            )))
521            .is_err()
522        );
523    }
524
525    #[test]
526    fn numeric_fields_decode_and_report_conversion_failures() {
527        assert_eq!(
528            <u16 as DecodeField<'_>>::decode_field(Some(&ValueRef::Uint16(7))).unwrap(),
529            7
530        );
531        assert_eq!(
532            <u16 as DecodeField<'_>>::decode_field(Some(&ValueRef::Uint32(7))).unwrap(),
533            7
534        );
535        assert_eq!(
536            <u16 as DecodeField<'_>>::decode_field(Some(&ValueRef::Uint64(7))).unwrap(),
537            7
538        );
539        assert!(matches!(
540            <u16 as DecodeField<'_>>::decode_field(Some(&ValueRef::Uint32(70_000))),
541            Err(Error::DecodingError(_))
542        ));
543        assert!(<u16 as DecodeField<'_>>::decode_field(Some(&ValueRef::Utf8("x"))).is_err());
544
545        assert_eq!(
546            <u32 as DecodeField<'_>>::decode_field(Some(&ValueRef::Uint16(3))).unwrap(),
547            3
548        );
549        assert_eq!(
550            <u32 as DecodeField<'_>>::decode_field(Some(&ValueRef::Uint32(3))).unwrap(),
551            3
552        );
553        assert_eq!(
554            <u32 as DecodeField<'_>>::decode_field(Some(&ValueRef::Uint64(3))).unwrap(),
555            3
556        );
557        assert!(<u32 as DecodeField<'_>>::decode_field(Some(&ValueRef::Int32(3))).is_err());
558
559        assert_eq!(
560            <u64 as DecodeField<'_>>::decode_field(Some(&ValueRef::Uint16(3))).unwrap(),
561            3
562        );
563        assert_eq!(
564            <u64 as DecodeField<'_>>::decode_field(Some(&ValueRef::Uint32(3))).unwrap(),
565            3
566        );
567        assert_eq!(
568            <u64 as DecodeField<'_>>::decode_field(Some(&ValueRef::Uint64(3))).unwrap(),
569            3
570        );
571        assert!(<u64 as DecodeField<'_>>::decode_field(Some(&ValueRef::Int32(3))).is_err());
572
573        assert_eq!(
574            <u128 as DecodeField<'_>>::decode_field(Some(&ValueRef::Uint16(1))).unwrap(),
575            1_u128
576        );
577        assert_eq!(
578            <u128 as DecodeField<'_>>::decode_field(Some(&ValueRef::Uint32(2))).unwrap(),
579            2_u128
580        );
581        assert_eq!(
582            <u128 as DecodeField<'_>>::decode_field(Some(&ValueRef::Uint64(3))).unwrap(),
583            3_u128
584        );
585        assert_eq!(
586            <u128 as DecodeField<'_>>::decode_field(Some(&ValueRef::Uint128(4))).unwrap(),
587            4_u128
588        );
589        assert!(<u128 as DecodeField<'_>>::decode_field(Some(&ValueRef::Bool(true))).is_err());
590
591        assert_eq!(
592            <i32 as DecodeField<'_>>::decode_field(Some(&ValueRef::Int32(-5))).unwrap(),
593            -5
594        );
595        assert!(<i32 as DecodeField<'_>>::decode_field(Some(&ValueRef::Uint16(5))).is_err());
596    }
597
598    #[test]
599    fn float_double_and_bool_fields_decode_and_reject() {
600        assert_eq!(
601            <f64 as DecodeField<'_>>::decode_field(Some(&ValueRef::Double(1.5))).unwrap(),
602            1.5
603        );
604        assert_eq!(
605            <f64 as DecodeField<'_>>::decode_field(Some(&ValueRef::Float(0.5))).unwrap(),
606            0.5
607        );
608        assert!(<f64 as DecodeField<'_>>::decode_field(Some(&ValueRef::Bool(true))).is_err());
609
610        assert_eq!(
611            <f32 as DecodeField<'_>>::decode_field(Some(&ValueRef::Float(0.5))).unwrap(),
612            0.5
613        );
614        assert!(<f32 as DecodeField<'_>>::decode_field(Some(&ValueRef::Double(0.5))).is_err());
615
616        assert!(<bool as DecodeField<'_>>::decode_field(Some(&ValueRef::Bool(true))).unwrap());
617        assert!(<bool as DecodeField<'_>>::decode_field(Some(&ValueRef::Utf8("x"))).is_err());
618    }
619
620    #[test]
621    fn encode_fields_produce_expected_values() {
622        assert_eq!("abc".encode_field().unwrap(), Value::Utf8("abc".into()));
623        assert_eq!(
624            String::from("abc").encode_field().unwrap(),
625            Value::Utf8("abc".into())
626        );
627        assert_eq!(
628            <str as EncodeField>::encode_field("abc").unwrap(),
629            Value::Utf8("abc".into())
630        );
631        assert_eq!(true.encode_field().unwrap(), Value::Bool(true));
632        assert_eq!(1.5f32.encode_field().unwrap(), Value::Float(1.5));
633        assert_eq!(1.5f64.encode_field().unwrap(), Value::Double(1.5));
634        assert_eq!(7u16.encode_field().unwrap(), Value::Uint16(7));
635        assert_eq!(7u32.encode_field().unwrap(), Value::Uint32(7));
636        assert_eq!(7u64.encode_field().unwrap(), Value::Uint64(7));
637        assert_eq!(7u128.encode_field().unwrap(), Value::Uint128(7));
638        assert_eq!((-7i32).encode_field().unwrap(), Value::Int32(-7));
639
640        assert_eq!(
641            vec![1u16, 2].encode_field().unwrap(),
642            Value::Array(vec![Value::Uint16(1), Value::Uint16(2)])
643        );
644        let slice: &[u16] = &[3, 4];
645        assert_eq!(
646            slice.encode_field().unwrap(),
647            Value::Array(vec![Value::Uint16(3), Value::Uint16(4)])
648        );
649        let mut map = BTreeMap::new();
650        map.insert("a".to_string(), 5u32);
651        assert_eq!(
652            map.encode_field().unwrap(),
653            Value::Map(BTreeMap::from([("a".to_string(), Value::Uint32(5))]))
654        );
655    }
656
657    #[test]
658    fn option_encode_fields_and_default_optional_hook() {
659        assert_eq!(Some(7u16).encode_field().unwrap(), Value::Uint16(7));
660        assert!(None::<u16>.encode_field().is_err());
661        assert_eq!(
662            Some(7u16).encode_optional_field().unwrap(),
663            Some(Value::Uint16(7))
664        );
665        assert_eq!(None::<u16>.encode_optional_field().unwrap(), None);
666        assert_eq!(
667            5u16.encode_optional_field().unwrap(),
668            Some(Value::Uint16(5))
669        );
670    }
671
672    #[cfg(feature = "writer")]
673    #[test]
674    fn raw_field_decoders_cover_supported_wire_types_and_conversion_errors() {
675        use crate::{decoder::RawDecoder, encoder::encode_value};
676
677        macro_rules! check_raw {
678            ($ty:ty, $value:expr, $expected:expr) => {{
679                let mut bytes = Vec::new();
680                encode_value(&$value, &mut bytes).unwrap();
681                let mut decoder = RawDecoder::new(&bytes, 0, bytes.len(), 0);
682                assert_eq!(
683                    <$ty as DecodeField<'_>>::decode_raw(&mut decoder).unwrap(),
684                    $expected
685                );
686            }};
687        }
688        check_raw!(&str, Value::Utf8("borrowed".into()), "borrowed");
689        check_raw!(String, Value::Utf8("owned".into()), "owned");
690        check_raw!(&[u8], Value::Bytes(vec![1, 2]), &[1, 2]);
691        check_raw!(Option<u32>, Value::Uint32(7), Some(7));
692        check_raw!(u16, Value::Uint32(7), 7);
693        check_raw!(u32, Value::Uint32(7), 7);
694        check_raw!(u64, Value::Uint64(1 << 40), 1 << 40);
695        check_raw!(u128, Value::Uint128(1 << 100), 1 << 100);
696        check_raw!(i32, Value::Int32(-7), -7);
697        check_raw!(f32, Value::Float(1.5), 1.5);
698        check_raw!(f64, Value::Double(1.5), 1.5);
699        check_raw!(bool, Value::Bool(true), true);
700        check_raw!(
701            Vec<u16>,
702            Value::Array(vec![Value::Uint16(1), Value::Uint16(2)]),
703            vec![1, 2]
704        );
705        check_raw!(
706            BTreeMap<String, u32>,
707            Value::Map(BTreeMap::from([("asn".into(), Value::Uint32(7))])),
708            BTreeMap::from([("asn".into(), 7)])
709        );
710
711        let mut bytes = Vec::new();
712        encode_value(&Value::Uint64(70_000), &mut bytes).unwrap();
713        let mut decoder = RawDecoder::new(&bytes, 0, bytes.len(), 0);
714        assert!(<u16 as DecodeField<'_>>::decode_raw(&mut decoder).is_err());
715        assert!(<u32 as DecodeField<'_>>::decode_missing().is_err());
716        assert_eq!(
717            <Option<u32> as DecodeField<'_>>::decode_missing().unwrap(),
718            None
719        );
720    }
721
722    #[cfg(feature = "writer")]
723    #[test]
724    fn default_field_decoder_materializes_custom_fields() {
725        use crate::{decoder::RawDecoder, encoder::encode_value};
726
727        struct Positive(u32);
728        impl<'a> DecodeField<'a> for Positive {
729            fn decode_field(value: Option<&ValueRef<'a>>) -> Result<Self> {
730                match value {
731                    Some(ValueRef::Uint32(n)) if *n > 0 => Ok(Self(*n)),
732                    _ => Err(Error::DecodingError("positive number required".into())),
733                }
734            }
735        }
736
737        let mut bytes = Vec::new();
738        encode_value(&Value::Uint32(7), &mut bytes).unwrap();
739        let mut decoder = RawDecoder::new(&bytes, 0, bytes.len(), 0);
740        assert_eq!(Positive::decode_raw(&mut decoder).unwrap().0, 7);
741        assert!(Positive::decode_missing().is_err());
742    }
743}