Line data Source code
1 : /*
2 : * Copyright (c) 2024 Project CHIP Authors
3 : * All rights reserved.
4 : *
5 : * Licensed under the Apache License, Version 2.0 (the "License");
6 : * you may not use this file except in compliance with the License.
7 : * You may obtain a copy of the License at
8 : *
9 : * http://www.apache.org/licenses/LICENSE-2.0
10 : *
11 : * Unless required by applicable law or agreed to in writing, software
12 : * distributed under the License is distributed on an "AS IS" BASIS,
13 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 : * See the License for the specific language governing permissions and
15 : * limitations under the License.
16 : */
17 : #pragma once
18 :
19 : #include "lib/core/TLVWriter.h"
20 : #include <app/util/attribute-metadata.h>
21 : #include <app/util/ember-io-storage.h>
22 : #include <lib/core/TLVReader.h>
23 : #include <lib/core/TLVTypes.h>
24 : #include <lib/support/BufferReader.h>
25 : #include <lib/support/BufferWriter.h>
26 : #include <lib/support/Span.h>
27 :
28 : namespace chip {
29 : namespace app {
30 : namespace Ember {
31 :
32 : /// This class represents a pointer to an ember-encoded attribute in a specific memory location.
33 : ///
34 : /// Ember attributes are stored as raw bytes for numeric types (i.e. memcpy-like storage except
35 : /// unaligned) and strings are Pascal-like (short with 1-byte length prefix or long with 2-byte length
36 : /// prefix).
37 : ///
38 : /// Class is to be used as a one-shot:
39 : /// - create it out of metadata + data span
40 : /// - call Decode (which modifies the input data span)
41 : class EmberAttributeDataBuffer
42 : {
43 : public:
44 : #if CHIP_CONFIG_BIG_ENDIAN_TARGET
45 : using EndianWriter = Encoding::BigEndian::BufferWriter;
46 : using EndianReader = Encoding::BigEndian::Reader;
47 : #else
48 : using EndianWriter = Encoding::LittleEndian::BufferWriter;
49 : using EndianReader = Encoding::LittleEndian::Reader;
50 : #endif
51 :
52 : enum class PascalStringType
53 : {
54 : kShort,
55 : kLong,
56 : };
57 :
58 : static constexpr bool kIsFabricScoped = false;
59 :
60 476 : EmberAttributeDataBuffer(const EmberAfAttributeMetadata * meta, MutableByteSpan & data) :
61 476 : mIsNullable(meta->IsNullable()), mAttributeType(chip::app::Compatibility::Internal::AttributeBaseType(meta->attributeType)),
62 476 : mDataBuffer(data)
63 476 : {}
64 :
65 : /// Reads the data pointed into by `reader` and updates the data
66 : /// internally into mDataBuffer (which is then reflected outwards)
67 : ///
68 : /// Generally should be called ONLY ONCE as the internal mutable byte span gets
69 : /// modified by this call.
70 : CHIP_ERROR Decode(chip::TLV::TLVReader & reader);
71 :
72 : /// Writes the data encoded in the underlying buffer into the given `writer`
73 : ///
74 : /// The data in the internal data buffer is assumed to be already formatted correctly
75 : /// HOWEVER the size inside it will not be fully considered (i.e. encoding will use
76 : /// the data encoding line integer or string sizes and NOT the databuffer max size)
77 : CHIP_ERROR Encode(chip::TLV::TLVWriter & writer, TLV::Tag tag) const;
78 :
79 : private:
80 : /// Decodes the UNSIGNED integer stored in `reader` and places its content into `writer`
81 : /// Takes into account internal mIsNullable.
82 : CHIP_ERROR DecodeUnsignedInteger(chip::TLV::TLVReader & reader, EndianWriter & writer);
83 :
84 : /// Decodes the SIGNED integer stored in `reader` and places its content into `writer`
85 : /// Takes into account internal mIsNullable.
86 : CHIP_ERROR DecodeSignedInteger(chip::TLV::TLVReader & reader, EndianWriter & writer);
87 :
88 : /// Encodes the given integer into `writer`.
89 : /// Takes into account internal mIsNullable.
90 : CHIP_ERROR EncodeInteger(chip::TLV::TLVWriter & writer, TLV::Tag tag, EndianReader & reader) const;
91 :
92 : /// Decodes the string/byte string contained in `reader` and stores it into `writer`.
93 : /// String is encoded using a pascal-prefix of size `stringType`.
94 : /// Takes into account internal mIsNullable.
95 : ///
96 : /// The string in `reader` is expected to be of type `tlvType`
97 : CHIP_ERROR DecodeAsString(chip::TLV::TLVReader & reader, PascalStringType stringType, TLV::TLVType tlvType,
98 : EndianWriter & writer);
99 :
100 : const bool mIsNullable; // Contains if the attribute metadata marks the field as NULLABLE
101 : const EmberAfAttributeType mAttributeType; // Initialized with the attribute type from the metadata
102 : MutableByteSpan & mDataBuffer; // output buffer, modified by `Decode`
103 : };
104 :
105 : } // namespace Ember
106 :
107 : namespace DataModel {
108 :
109 : /// Helper method to forward the decode of this type to the class specific implementation
110 : inline CHIP_ERROR Decode(TLV::TLVReader & reader, Ember::EmberAttributeDataBuffer & buffer)
111 : {
112 : return buffer.Decode(reader);
113 : }
114 :
115 : inline CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag, Ember::EmberAttributeDataBuffer & buffer)
116 : {
117 : return buffer.Encode(writer, tag);
118 : }
119 :
120 : } // namespace DataModel
121 : } // namespace app
122 : } // namespace chip
|