parsec_interface/requests/request/
request_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::ResponseStatus;
5use crate::requests::{AuthType, BodyType, Opcode, ProviderId};
6#[cfg(feature = "fuzz")]
7use arbitrary::Arbitrary;
8use num::FromPrimitive;
9use std::convert::TryFrom;
10
11/// A native representation of the request header.
12///
13/// Fields that are not relevant for application development (e.g. magic number) are
14/// not copied across from the raw header.
15#[cfg_attr(feature = "fuzz", derive(Arbitrary))]
16#[derive(Copy, Clone, Debug, PartialEq, Eq)]
17pub struct RequestHeader {
18    /// Provider ID value
19    pub provider: ProviderId,
20    /// Session handle
21    pub session: u64,
22    /// Content type: defines how the request body should be processed.
23    pub content_type: BodyType,
24    /// Accept type: defines how the service should provide its response.
25    pub accept_type: BodyType,
26    /// Authentication type.
27    pub auth_type: AuthType,
28    /// Opcode of the operation to perform.
29    pub opcode: Opcode,
30}
31
32impl RequestHeader {
33    /// Create a new request header with default field values.
34    /// Available for testing only.
35    #[cfg(feature = "testing")]
36    pub(crate) fn new() -> RequestHeader {
37        RequestHeader {
38            provider: ProviderId::Core,
39            session: 0,
40            content_type: BodyType::Protobuf,
41            accept_type: BodyType::Protobuf,
42            auth_type: AuthType::Direct,
43            opcode: Opcode::Ping,
44        }
45    }
46}
47
48/// Conversion from the raw to native request header.
49///
50/// This conversion must be done before a `Request` value can be populated.
51impl TryFrom<Raw> for RequestHeader {
52    type Error = ResponseStatus;
53
54    fn try_from(header: Raw) -> ::std::result::Result<Self, Self::Error> {
55        let content_type: BodyType = match FromPrimitive::from_u8(header.content_type) {
56            Some(content_type) => content_type,
57            None => return Err(ResponseStatus::ContentTypeNotSupported),
58        };
59
60        let accept_type: BodyType = match FromPrimitive::from_u8(header.accept_type) {
61            Some(accept_type) => accept_type,
62            None => return Err(ResponseStatus::AcceptTypeNotSupported),
63        };
64
65        let auth_type: AuthType = match FromPrimitive::from_u8(header.auth_type) {
66            Some(auth_type) => auth_type,
67            None => return Err(ResponseStatus::AuthenticatorDoesNotExist),
68        };
69
70        let opcode: Opcode = match FromPrimitive::from_u32(header.opcode) {
71            Some(opcode) => opcode,
72            None => return Err(ResponseStatus::OpcodeDoesNotExist),
73        };
74
75        Ok(RequestHeader {
76            provider: ProviderId::try_from(header.provider)?,
77            session: header.session,
78            content_type,
79            accept_type,
80            auth_type,
81            opcode,
82        })
83    }
84}
85
86/// Conversion from native to raw request header.
87///
88/// This is required in order to bring the contents of the header in a state
89/// which can be serialized.
90impl From<RequestHeader> for Raw {
91    fn from(header: RequestHeader) -> Self {
92        Raw {
93            flags: 0,
94            provider: header.provider as u8,
95            session: header.session,
96            content_type: header.content_type as u8,
97            accept_type: header.accept_type as u8,
98            auth_type: header.auth_type as u8,
99            body_len: 0,
100            auth_len: 0,
101            opcode: header.opcode as u32,
102            status: 0, // status field unused
103            reserved1: 0,
104            reserved2: 0,
105        }
106    }
107}