1use crate::{
2 header::{MessageClass, MessageType, ResponseType as Status},
3 packet::Packet,
4};
5
6#[derive(Clone, Debug, PartialEq)]
8pub struct CoapResponse {
9 pub message: Packet,
10}
11
12impl CoapResponse {
13 pub fn new(request: &Packet) -> Option<CoapResponse> {
15 let mut packet = Packet::new();
16
17 packet.header.set_version(1);
18 let response_type = match request.header.get_type() {
19 MessageType::Confirmable => MessageType::Acknowledgement,
20 MessageType::NonConfirmable => MessageType::NonConfirmable,
21 _ => return None,
22 };
23 packet.header.set_type(response_type);
24 packet.header.code = MessageClass::Response(Status::Content);
25 packet.header.message_id = request.header.message_id;
26 packet.set_token(request.get_token().to_vec());
27
28 Some(CoapResponse { message: packet })
29 }
30
31 pub fn set_status(&mut self, status: Status) {
33 self.message.header.code = MessageClass::Response(status);
34 }
35
36 pub fn get_status(&self) -> &Status {
38 match self.message.header.code {
39 MessageClass::Response(Status::Created) => &Status::Created,
40 MessageClass::Response(Status::Deleted) => &Status::Deleted,
41 MessageClass::Response(Status::Valid) => &Status::Valid,
42 MessageClass::Response(Status::Changed) => &Status::Changed,
43 MessageClass::Response(Status::Content) => &Status::Content,
44
45 MessageClass::Response(Status::BadRequest) => &Status::BadRequest,
46 MessageClass::Response(Status::Unauthorized) => {
47 &Status::Unauthorized
48 }
49 MessageClass::Response(Status::BadOption) => &Status::BadOption,
50 MessageClass::Response(Status::Forbidden) => &Status::Forbidden,
51 MessageClass::Response(Status::NotFound) => &Status::NotFound,
52 MessageClass::Response(Status::MethodNotAllowed) => {
53 &Status::MethodNotAllowed
54 }
55 MessageClass::Response(Status::NotAcceptable) => {
56 &Status::NotAcceptable
57 }
58 MessageClass::Response(Status::PreconditionFailed) => {
59 &Status::PreconditionFailed
60 }
61 MessageClass::Response(Status::RequestEntityTooLarge) => {
62 &Status::RequestEntityTooLarge
63 }
64 MessageClass::Response(Status::UnsupportedContentFormat) => {
65 &Status::UnsupportedContentFormat
66 }
67
68 MessageClass::Response(Status::InternalServerError) => {
69 &Status::InternalServerError
70 }
71 MessageClass::Response(Status::NotImplemented) => {
72 &Status::NotImplemented
73 }
74 MessageClass::Response(Status::BadGateway) => &Status::BadGateway,
75 MessageClass::Response(Status::ServiceUnavailable) => {
76 &Status::ServiceUnavailable
77 }
78 MessageClass::Response(Status::GatewayTimeout) => {
79 &Status::GatewayTimeout
80 }
81 MessageClass::Response(Status::ProxyingNotSupported) => {
82 &Status::ProxyingNotSupported
83 }
84 _ => &Status::UnKnown,
85 }
86 }
87}
88
89#[cfg(test)]
90mod test {
91 use super::*;
92
93 #[test]
94 fn test_new_response_valid() {
95 for mtyp in [MessageType::Confirmable, MessageType::NonConfirmable] {
96 let mut packet = Packet::new();
97 packet.header.set_type(mtyp);
98 let opt_resp = CoapResponse::new(&packet);
99 assert!(opt_resp.is_some());
100
101 let response = opt_resp.unwrap();
102 assert_eq!(packet.payload, response.message.payload);
103 }
104 }
105
106 #[test]
107 fn test_new_response_invalid() {
108 let mut packet = Packet::new();
109 packet.header.set_type(MessageType::Acknowledgement);
110 assert!(CoapResponse::new(&packet).is_none());
111 }
112}