Skip to content

Commit 087770b

Browse files
implementing encoder interface
1 parent 6dd1bd7 commit 087770b

File tree

2 files changed

+122
-0
lines changed

2 files changed

+122
-0
lines changed

src/cbor/CborEncoder.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
This file is part of the Arduino_CloudUtils library.
3+
4+
Copyright (c) 2024 Arduino SA
5+
6+
This Source Code Form is subject to the terms of the Mozilla Public
7+
License, v. 2.0. If a copy of the MPL was not distributed with this
8+
file, You can obtain one at http://mozilla.org/MPL/2.0/.
9+
*/
10+
#include "CborEncoder.h"
11+
12+
static CBORMessageEncoderClass* singleton = nullptr;
13+
CBORMessageEncoderClass& CBORMessageEncoder = CBORMessageEncoderClass::getInstance();
14+
15+
Encoder::Status CBORMessageEncoderClass::encode(Message* message, uint8_t * data, size_t& len) { // TODO do we need to propagate the maximum length?
16+
// prepare cbor structure
17+
CborEncoder encoder;
18+
19+
cbor_encoder_init(&encoder, data, len, 0);
20+
21+
auto encoder_it = encoders.find(message->id);
22+
23+
// check if message.id exists on the encoders list or return error
24+
if(encoder_it == encoders.end()) {
25+
return Encoder::Status::Error;
26+
}
27+
28+
// encode the message
29+
if(encoder_it->second->_encode(&encoder, message) == Encoder::Status::Error) {
30+
return Encoder::Status::Error;
31+
}
32+
33+
len = cbor_encoder_get_buffer_size(&encoder, data);
34+
35+
return Encoder::Status::Complete;
36+
}
37+
38+
CBORMessageEncoderClass& CBORMessageEncoderClass::getInstance() {
39+
if(singleton == nullptr) {
40+
singleton = new CBORMessageEncoderClass();
41+
}
42+
return *singleton;
43+
}
44+
45+
CBORMessageEncoderInterface::CBORMessageEncoderInterface(const CBORTag tag, const MessageId id)
46+
: tag(tag), id(id) {
47+
// call singleton/global variable and insert this encoder
48+
CBORMessageEncoderClass::getInstance().append(id, this);
49+
}
50+
51+
Encoder::Status CBORMessageEncoderInterface::_encode(CborEncoder* encoder, Message *msg) {
52+
// this must always be true, it could mean that there are issues in the map of encoders
53+
assert(msg->id == id);
54+
55+
if (tag == cbor::tag::CBORUnknownCmdTag16b ||
56+
tag == cbor::tag::CBORUnknownCmdTag32b ||
57+
tag == cbor::tag::CBORUnknownCmdTag64b ||
58+
cbor_encode_tag(encoder, tag) != CborNoError) {
59+
return Encoder::Status::Error;
60+
}
61+
62+
return this->encode(encoder, msg);
63+
}

src/cbor/CborEncoder.h

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
This file is part of the Arduino_CloudUtils library.
3+
4+
Copyright (c) 2024 Arduino SA
5+
6+
This Source Code Form is subject to the terms of the Mozilla Public
7+
License, v. 2.0. If a copy of the MPL was not distributed with this
8+
file, You can obtain one at http://mozilla.org/MPL/2.0/.
9+
*/
10+
#pragma once
11+
12+
#include <map>
13+
#include "../interfaces/Encoder.h"
14+
#include "CBOR.h"
15+
#include "../interfaces/message.h"
16+
#include "./tinycbor/cbor-lib.h"
17+
18+
class CBORMessageEncoderClass;
19+
20+
21+
// TODO find a better name
22+
// TODO maybe a template<CBORTag tag, MessageId id> ?
23+
// TODO maybe template<resultStruct> that is also the parameter of encode
24+
// TODO in order to make this more extensible we should not pass Message* as a parameter, templated function may be better (or void*)
25+
// providing both id and tag gives the ability to convert and avoid using a conversion function
26+
class CBORMessageEncoderInterface {
27+
public:
28+
CBORMessageEncoderInterface(const CBORTag tag, const MessageId id);
29+
virtual ~CBORMessageEncoderInterface() {}
30+
31+
protected:
32+
virtual Encoder::Status encode(CborEncoder* encoder, Message *msg) = 0;
33+
34+
private:
35+
const CBORTag tag;
36+
const MessageId id;
37+
38+
friend CBORMessageEncoderClass;
39+
40+
// wrapper for encode function that for the time being only writes the tag in the buffer
41+
Encoder::Status _encode(CborEncoder* encoder, Message *msg);
42+
};
43+
44+
// TODO make a private constructor?
45+
class CBORMessageEncoderClass: public Encoder {
46+
public:
47+
CBORMessageEncoderClass() {}
48+
static CBORMessageEncoderClass& getInstance();
49+
50+
void append(CBORTag id, CBORMessageEncoderInterface* encoder) {
51+
encoders[id] = encoder;
52+
}
53+
54+
Encoder::Status encode(Message* message, uint8_t * data, size_t& len);
55+
private:
56+
std::map<MessageId, CBORMessageEncoderInterface*> encoders;
57+
};
58+
59+
extern CBORMessageEncoderClass& CBORMessageEncoder;

0 commit comments

Comments
 (0)