1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
pub trait MessageOption {
    fn number(&self) -> u16;
    // FIXME: This will be hard to implement for those that don't store serialized values; those
    // will have to have a buffer inside the iterator :-(
    fn value(&self) -> &[u8];
}

/// Helper mixin for ReadableMessage that allows using ReadableMessage without giving a lifetime
/// all the time.
pub trait OptionsIterableMessage<'a> {
    type MessageOption: 'a + MessageOption;
    type OptionsIter: Iterator<Item = Self::MessageOption>;

    /// Produce all options in arbitrary order as an iterator
    ///
    /// If your options are always produced in an ordered fashion, consider implementing the
    /// ``OptionsSortedIterableMessage`` trait as well. This should be the case for most CoAP
    /// message backends. Examples of backends where it is not implemented are single-pass reads
    /// over in-place decrypted OSCORE messages.
    fn options(&'a self) -> Self::OptionsIter;
}

/// Marker trait that indicates that OptionsIterableMessage::options are produced in ascending
/// sequence.
pub trait OptionsSortedIterableMessage<'a>: OptionsIterableMessage<'a> {
}

// Relaxing on the requirement as we don't need it for all 'a, just for the 'a that don't outlive
// Self
pub trait ReadableMessage // : for<'a> OptionsIterableMessage<'a>
{
    type Code: crate::numbers::Code;

    fn code(&self) -> Self::Code;

    fn payload(&self) -> &[u8];
}

// It would be nice to have more type state in here (for headers, last option number and whether
// payload has been set); this is a first step that can easily wrap jnet and maybe gcoap. Taking
// the next step is likely to happen soon, given that jnet coap has already moved to type state.
/// A message that needs to have its code, any options in ascending order and its payload set in
/// that very sequence.
///
/// This is the bare minimum a message needs to provide to be populated as a request or response by
/// a generic program; it is up to the program to ensure the valid sequence of operations, as
/// failure to do so may incur panics (FIXME: or errors).
pub trait MinimalWritableMessage {
    type Code: crate::numbers::Code;
    type OptionNumber: crate::numbers::OptionNumber;

    fn set_code(&mut self, code: Self::Code);

    // completely ignoring error handling here, pending typestateification
    fn add_option(&mut self, number: Self::OptionNumber, value: &[u8]);

    // error handling as in add_option
    fn set_payload(&mut self, data: &[u8]);

    /// Copy code, options and payload in from a readable message
    ///
    /// Implementations can override this for cases where it can be done more efficiently than
    /// iterating over the options and appending them.
    fn set_from_message<M>(&mut self, msg: &M)
    where
        M: ReadableMessage + for<'a> OptionsSortedIterableMessage<'a>
    {
        use core::convert::TryInto;

        self.set_code(msg.code()
                      .into()
                      .try_into()
                      .map_err(|_| "Code can not be expressed in target message")
                      .unwrap(),
                      );

        for opt in msg.options() {
            self.add_option(
                opt.number()
                    .try_into()
                    .map_err(|_| "Option can not be expressed in target message")
                    .unwrap(),
                opt.value())
        }
        self.set_payload(msg.payload());
    }
}

/// A message that allows later manipulation of a once set payload, and later truncation.
///
/// This is a bit of an unsorted bag that needs further cleanup (FIXME) -- most of this is
/// motivated by block-wise and write-in-place. Might need a bit of reshape, possibly something
/// like a once-callable ``.write_payload(|d: &mut [u8]| { write_to(d); Ok(bytes_written)})``. Does
/// this need a hint of the length to allocate for implementations that don't pre-allocate the
/// message? Is 1024 a good enough value to not pass it?
///
/// The available_space is only needed where applications want to use up the last byte by not
/// zero-padding the Block2 option to its szx=0 equivalent.
///
/// Can that be efficiently be replaced with something like this, and can it be optimized down to
/// the hand-written counting-of-option-bytes that's involved in the use of available_space?
///
/// ```ignore
/// let mut m = allocated_message;
/// for szx in 6..0 {
///     snap = m.snapshot();
///     m.add_option(BLOCK2, ...);
///     m.add_option(..., ...);
///
///     if let Ok(_) = m.write_payload(|p| {
///         if (p.len() < 1 << (4 + szx)) {
///             return Err(());
///         }
///
///         let written = write_block(...);
///
///         Ok(written)
///     }) {
///         break;
///     } else {
///         m = m.revert_to(snap);
///     }
/// } else {
///     panic!("Allocated space doesn't even suffice for 16 byte payload");
/// }
/// ```
///
pub trait MutableWritableMessage: MinimalWritableMessage {
    /// Number of bytes available for additional options, payload marker and payload
    fn available_space(&self) -> usize;

    // to be reevaluated, currently here for compatibility / easy migration
    fn payload_mut(&mut self) -> &mut [u8];

    fn truncate(&mut self, len: usize);

    fn mutate_options<F>(&mut self, callback: F)
    where
        F: FnMut(Self::OptionNumber, &mut [u8]);
}

/// Marker trait that indicates that the sequence of calling set_code, add_option and set_payload
/// is not fixed. The sequence of calls only has meaning in that later set_code and set_payload
/// calls override earlier ones, and that add_option on the same option number are stored in their
/// sequence.
// FIXME: Look into whether there's any implementation where it'd make sense to only have some of
// the relaxation but not all (eg. all options must be out, then comes the code).
pub trait SeekWritableMessage {
    // FIXME: Provide a more generic set_from_message that does not demand
    // OptionsSortedIterableMessage. It can even have just the same code.
}