parsec_interface/requests/response/
response_header.rs

1// Copyright 2019 Contributors to the Parsec project.
2// SPDX-License-Identifier: Apache-2.0
3use crate::requests::common::wire_header_1_0::WireHeader as Raw;
4use crate::requests::{BodyType, Opcode, ProviderId, ResponseStatus, Result};
5use num::FromPrimitive;
6use std::convert::TryFrom;
7
8/// A native representation of the response header.
9///
10/// Fields that are not relevant for application development (e.g. magic number) are
11/// not copied across from the raw header.
12#[derive(Copy, Clone, Debug, PartialEq, Eq)]
13pub struct ResponseHeader {
14    /// Provider ID value
15    pub provider: ProviderId,
16    /// Session handle
17    pub session: u64,
18    /// Content type: defines how the request body should be processed.
19    pub content_type: BodyType,
20    /// Opcode of the operation to perform.
21    pub opcode: Opcode,
22    /// Response status of the request.
23    pub status: ResponseStatus,
24}
25
26impl ResponseHeader {
27    /// Create a new response header with default field values.
28    pub(crate) fn new() -> ResponseHeader {
29        ResponseHeader {
30            provider: ProviderId::Core,
31            session: 0,
32            content_type: BodyType::Protobuf,
33            opcode: Opcode::Ping,
34            status: ResponseStatus::Success,
35        }
36    }
37}
38
39/// Conversion from the raw to native response header.
40///
41/// This conversion must be done before a `Response` value can be populated.
42impl TryFrom<Raw> for ResponseHeader {
43    type Error = ResponseStatus;
44
45    fn try_from(header: Raw) -> Result<ResponseHeader> {
46        let provider: ProviderId = match FromPrimitive::from_u8(header.provider) {
47            Some(provider_id) => provider_id,
48            None => return Err(ResponseStatus::ProviderDoesNotExist),
49        };
50
51        let content_type: BodyType = match FromPrimitive::from_u8(header.content_type) {
52            Some(content_type) => content_type,
53            None => return Err(ResponseStatus::ContentTypeNotSupported),
54        };
55
56        let opcode: Opcode = match FromPrimitive::from_u32(header.opcode) {
57            Some(opcode) => opcode,
58            None => return Err(ResponseStatus::OpcodeDoesNotExist),
59        };
60
61        let status: ResponseStatus = match FromPrimitive::from_u16(header.status) {
62            Some(status) => status,
63            None => return Err(ResponseStatus::InvalidEncoding),
64        };
65
66        Ok(ResponseHeader {
67            provider,
68            session: header.session,
69            content_type,
70            opcode,
71            status,
72        })
73    }
74}
75
76/// Conversion from native to raw response header.
77///
78/// This is required in order to bring the contents of the header in a state
79/// which can be serialized.
80impl From<ResponseHeader> for Raw {
81    fn from(header: ResponseHeader) -> Self {
82        Raw {
83            flags: 0,
84            provider: header.provider as u8,
85            session: header.session,
86            content_type: header.content_type as u8,
87            accept_type: 0,
88            auth_type: 0,
89            auth_len: 0,
90            body_len: 0,
91            opcode: header.opcode as u32,
92            status: header.status as u16,
93            reserved1: 0,
94            reserved2: 0,
95        }
96    }
97}