1use std::collections::HashMap;
2
3pub type FieldIndex = usize;
4
5#[derive(Clone, Debug, PartialEq)]
7pub struct Hints {
8    pub skip_hint: Option<bool>,
9    pub current_field_index: Option<FieldIndex>,
10    pub known_field_lengths: HashMap<FieldIndex, FieldLength>,
13}
14
15#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
17pub struct FieldLength {
18    pub length: usize,
19    pub kind: LengthPrefixKind,
20}
21
22#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
24pub enum LengthPrefixKind {
25    Bytes,
27    Elements,
29    Pointers,
31}
32
33
34impl Default for Hints {
35    fn default() -> Self {
36        Hints {
37            skip_hint: None,
38            current_field_index: None,
39            known_field_lengths: HashMap::new(),
40        }
41    }
42}
43
44impl Hints {
45    pub fn current_field_length(&self) -> Option<FieldLength> {
48        self.current_field_index.and_then(|index| self.known_field_lengths.get(&index)).cloned()
49    }
50}
51
52mod protocol_derive_helpers {
54    use super::*;
55
56    impl Hints {
57        #[doc(hidden)]
59        pub fn begin_fields(&mut self) {
60            self.current_field_index = Some(0);
61        }
62
63        #[doc(hidden)]
65        pub fn next_field(&mut self) {
66            *self.current_field_index.as_mut()
67                .expect("cannot increment next field when not in a struct") += 1;
68        }
69
70        #[doc(hidden)]
72        pub fn set_field_length(&mut self,
73                                field_index: FieldIndex,
74                                length: usize,
75                                kind: LengthPrefixKind) {
76            self.known_field_lengths.insert(field_index, FieldLength { kind, length });
77        }
78
79        #[doc(hidden)]
82        pub fn set_skip(&mut self, do_skip: bool) {
83            self.skip_hint = Some(do_skip);
84        }
85    }
86}
87