1 #pragma once
2 
3 #include <cpp-pcp-client/protocol/v1/chunks.hpp>
4 #include <cpp-pcp-client/protocol/v1/errors.hpp>
5 #include <cpp-pcp-client/protocol/v1/serialization.hpp>
6 #include <cpp-pcp-client/validator/validator.hpp>
7 #include <cpp-pcp-client/export.h>
8 
9 #include <string>
10 #include <vector>
11 #include <map>
12 #include <initializer_list>
13 #include <stdint.h>  // uint8_t
14 
15 namespace PCPClient {
16 namespace v1 {
17 
18 //
19 // Message
20 //
21 
22 class LIBCPP_PCP_CLIENT_EXPORT Message {
23   public:
24     // The default ctor is deleted since, for the PCP protocol, a
25     // valid message must have an envelope chunk (invariant)
26     Message() = delete;
27 
28     // Construct a Message by parsing the payload delivered
29     // by the transport layer as a std::string.
30     // Throw an unsupported_version_error in case the indicated
31     // message format version is not supported.
32     // Throw a message_serialization_error in case of invalid message.
33     explicit Message(const std::string& transport_payload);
34 
35     // Create a new message with a given envelope.
36     // Throw a invalid_chunk_error in case of invalid chunk
37     // (unknown descriptor or wrong size).
38     explicit Message(MessageChunk envelope);
39 
40     // ... and a data chunk; throw a invalid_chunk_error as above
41     Message(MessageChunk envelope,
42             MessageChunk data_chunk);
43 
44     // ... and a debug chunk; throw a invalid_chunk_error as above
45     Message(MessageChunk envelope,
46             MessageChunk data_chunk,
47             MessageChunk debug_chunk);
48 
49     // Add optional chunks after validating it.
50     // Throw a invalid_chunk_error in case of invalid chunk (unknown
51     // descriptor or wrong size).
52     void setDataChunk(MessageChunk data_chunk);
53     void addDebugChunk(MessageChunk debug_chunk);
54 
55     // Getters
56     uint8_t getVersion() const;
57     MessageChunk getEnvelopeChunk() const;
58     MessageChunk getDataChunk() const;
59     std::vector<MessageChunk> getDebugChunks() const;
60 
61     // Inspectors
62     bool hasData() const;
63     bool hasDebug() const;
64 
65     // Return the buffer containing the bytes of the serialized
66     // message.
67     // Throw a message_processing_error in case it fails to allocate
68     // memory for the buffer.
69     SerializedMessage getSerialized() const;
70 
71     // Parse the content of all message chunks, validate, and return
72     // them as a ParsedChunks instance. The data chunk will be
73     // validated with the schema indicated in the envelope.
74     //
75     // Throw a data_parse_error in case the envelope content contains
76     // invalid JSON text.
77     // Throw a validation_error in case the envelope content does
78     // not match the envelope schema (as in pcp-specifications).
79     // Throw a schema_not_found_error in case the envelope schema
80     // was not registered.
81     //
82     // Note that bad debug/data chunks are reported in the returned
83     // ParsedChunks objects; no error will will be propagated.
84     ParsedChunks getParsedChunks(const Validator& validator) const;
85 
86     // Return a string representation of all message fields.
87     std::string toString() const;
88 
89   private:
90     uint8_t version_;
91     MessageChunk envelope_chunk_;
92     MessageChunk data_chunk_;
93     std::vector<MessageChunk> debug_chunks_;
94 
95     void parseMessage(const std::string& transport_msg);
96 
97     void validateVersion(const uint8_t& version) const;
98     void validateChunk(const MessageChunk& chunk) const;
99 };
100 
101 }  // namespace v1
102 }  // namespace PCPClient
103