coap_server/app/
coap_utils.rs

1use std::collections::HashMap;
2
3use coap_lite::error::IncompatibleOptionValueFormat;
4use coap_lite::option_value::OptionValueType;
5use coap_lite::{CoapOption, CoapRequest, MessageClass, MessageType, Packet};
6
7use crate::app::CoapError;
8
9pub fn new_pong_message(ping: &Packet) -> Packet {
10    let mut pong = Packet::new();
11
12    pong.header.set_type(MessageType::Reset);
13    pong.header.code = MessageClass::Empty;
14    pong.header.message_id = ping.header.message_id;
15    pong
16}
17
18pub fn request_get_queries<Endpoint>(request: &CoapRequest<Endpoint>) -> HashMap<String, String> {
19    request
20        .message
21        .get_options_as::<OptionValueQuery>(CoapOption::UriQuery)
22        .map_or_else(
23            || HashMap::new(),
24            |options| {
25                options
26                    .into_iter()
27                    .filter_map(Result::ok)
28                    .map(|query| (query.key, query.value))
29                    .collect::<HashMap<_, _>>()
30            },
31        )
32}
33
34pub struct OptionValueQuery {
35    key: String,
36    value: String,
37}
38
39impl From<OptionValueQuery> for Vec<u8> {
40    fn from(option_value: OptionValueQuery) -> Self {
41        format!("{}={}", option_value.key, option_value.value).into_bytes()
42    }
43}
44
45impl TryFrom<Vec<u8>> for OptionValueQuery {
46    type Error = IncompatibleOptionValueFormat;
47
48    fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
49        Self::do_try_from(value).map_err(|e| IncompatibleOptionValueFormat {
50            message: e.to_string(),
51        })
52    }
53}
54
55impl OptionValueType for OptionValueQuery {}
56
57impl OptionValueQuery {
58    fn do_try_from(value: Vec<u8>) -> Result<Self, CoapError> {
59        let mut key_value_iter = value.split(|&c| c == b'=');
60        let key_vec = key_value_iter.next().unwrap().to_vec();
61        let value_vec = key_value_iter
62            .next()
63            .ok_or_else(|| CoapError::bad_request("Missing '=', not a valid query string"))?
64            .to_vec();
65        let key = String::from_utf8(key_vec)
66            .map_err(|e| CoapError::bad_request(format!("Key is not UTF-8: {e}")))?;
67        let value = String::from_utf8(value_vec)
68            .map_err(|e| CoapError::bad_request(format!("Value is not UTF-8: {e}")))?;
69
70        Ok(OptionValueQuery { key, value })
71    }
72}