Skip to content

Commit ebeaf4c

Browse files
implementing decoder interface
1 parent 087770b commit ebeaf4c

File tree

2 files changed

+136
-0
lines changed

2 files changed

+136
-0
lines changed

src/cbor/CborDecoder.cpp

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
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 "CborDecoder.h"
11+
12+
static CBORMessageDecoderClass* singleton = nullptr;
13+
CBORMessageDecoderClass& CBORMessageDecoder = CBORMessageDecoderClass::getInstance();
14+
15+
Decoder::Status CBORMessageDecoderClass::decode(Message* msg, const uint8_t* const buf, size_t &len) { // TODO do we need to propagate the maximum length?
16+
// prepare cbor structure
17+
CborValue iter;
18+
CborTag tag;
19+
CborParser parser;
20+
21+
if (cbor_parser_init(buf, len, 0, &parser, &iter) != CborNoError) {
22+
return Decoder::Status::Error;
23+
}
24+
25+
if (iter.type != CborTagType) {
26+
return Decoder::Status::Error;
27+
}
28+
29+
if (cbor_value_get_tag(&iter, &tag) != CborNoError) {
30+
return Decoder::Status::Error;
31+
}
32+
33+
if (cbor_value_advance(&iter) != CborNoError) {
34+
return Decoder::Status::Error;
35+
}
36+
37+
auto decoder_it = decoders.find(tag);
38+
39+
// check if message.id exists on the decoders list or return error
40+
if(decoder_it == decoders.end()) {
41+
return Decoder::Status::Error;
42+
}
43+
44+
// encode the message
45+
if(decoder_it->second->_decode(&iter, msg) == Decoder::Status::Error) {
46+
return Decoder::Status::Error;
47+
}
48+
49+
return Decoder::Status::Complete;
50+
}
51+
52+
CBORMessageDecoderClass& CBORMessageDecoderClass::getInstance() {
53+
if(singleton == nullptr) {
54+
singleton = new CBORMessageDecoderClass();
55+
}
56+
return *singleton;
57+
}
58+
59+
CBORMessageDecoderInterface::CBORMessageDecoderInterface(const CBORTag tag, const MessageId id)
60+
: tag(tag), id(id) {
61+
// call singleton/global variable and insert this encoder
62+
CBORMessageDecoderClass::getInstance().append(tag, this);
63+
}
64+
65+
Decoder::Status CBORMessageDecoderInterface::_decode(CborValue* iter, Message *msg) {
66+
CborValue array_iter;
67+
msg->id = this->id;
68+
69+
if (cbor_value_get_type(iter) != CborArrayType) {
70+
return Decoder::Status::Error;
71+
}
72+
73+
if (cbor_value_enter_container(iter, &array_iter) != CborNoError) {
74+
return Decoder::Status::Error;
75+
}
76+
77+
return decode(&array_iter, msg);
78+
}

src/cbor/CborDecoder.h

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
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/Decoder.h"
14+
#include "CBOR.h"
15+
#include "../interfaces/message.h"
16+
#include "./tinycbor/cbor-lib.h"
17+
18+
class CBORMessageDecoderClass;
19+
20+
// TODO find a better name
21+
// TODO maybe a template<CBORTag tag, MessageId id> ?
22+
// TODO maybe template<resultStruct> that is also the parameter of encode
23+
// TODO in order to make this more extensible we should not pass Message* as a parameter, templated function may be better (or void*)
24+
// providing both id and tag gives the ability to convert and avoid using a conversion function
25+
class CBORMessageDecoderInterface {
26+
public:
27+
CBORMessageDecoderInterface(const CBORTag tag, const MessageId id);
28+
virtual ~CBORMessageDecoderInterface() {}
29+
30+
protected:
31+
virtual Decoder::Status decode(CborValue* iter, Message *msg) = 0;
32+
33+
private:
34+
const CBORTag tag;
35+
const MessageId id;
36+
37+
friend CBORMessageDecoderClass;
38+
39+
// wrapper for encode function that for the time being only writes the tag in the buffer
40+
Decoder::Status _decode(CborValue* iter, Message *msg);
41+
};
42+
43+
// TODO make a private constructor?
44+
class CBORMessageDecoderClass: public Decoder {
45+
public:
46+
CBORMessageDecoderClass() {}
47+
static CBORMessageDecoderClass& getInstance();
48+
49+
void append(CBORTag id, CBORMessageDecoderInterface* encoder) {
50+
decoders[id] = encoder;
51+
}
52+
53+
Decoder::Status decode(Message* msg, const uint8_t* const buf, size_t &len);
54+
private:
55+
std::map<CBORTag, CBORMessageDecoderInterface*> decoders;
56+
};
57+
58+
extern CBORMessageDecoderClass& CBORMessageDecoder;

0 commit comments

Comments
 (0)