Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020-2021 Project CHIP Authors
4 : * All rights reserved.
5 : *
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : */
18 :
19 : #pragma once
20 :
21 : #include <app/data-model/Decode.h>
22 : #include <app/data-model/Encode.h>
23 : #include <app/data-model/FabricScoped.h>
24 : #include <lib/core/TLV.h>
25 :
26 : namespace chip {
27 : namespace app {
28 : namespace DataModel {
29 :
30 : /*
31 : * Dedicated type for list<T> that is at its base, just a Span.
32 : *
33 : * Motivated by the need to create distinction between Lists that use Spans
34 : * vs. other data model types that use Spans (like octetstr). These have different
35 : * encodings. Consequently, there needs to be an actual C++ type distinction to ensure
36 : * correct specialization of the Encode/Decode methods.
37 : *
38 : */
39 : template <typename T>
40 : struct List : public Span<T>
41 : {
42 : //
43 : // The following 'using' statements are needed to make visible
44 : // all constructors of the base class within this derived class,
45 : // as well as introduce functions in the base class into the
46 : // derived class.
47 : //
48 : // This is needed to make it seamless to initialize and interact with
49 : // List<T> instances as though they were just Spans.
50 : //
51 : using Span<T>::Span;
52 :
53 : // Inherited copy constructors are _not_ imported by the using statement
54 : // above, though, so we need to implement that ourselves. This is templated
55 : // on the span's type to allow us to init a List<const Foo> from Span<Foo>.
56 : // Span's constructor handles the checks on the types for us.
57 : template <class U>
58 0 : constexpr List(const Span<U> & other) : Span<T>(other)
59 0 : {}
60 :
61 : template <size_t N>
62 : constexpr List & operator=(T (&databuf)[N])
63 : {
64 : Span<T>::operator=(databuf);
65 : return (*this);
66 : }
67 :
68 : //
69 : // A list is deemed fabric scoped if the type of its elements is as well.
70 : //
71 : static constexpr bool kIsFabricScoped = DataModel::IsFabricScoped<T>::value;
72 : };
73 :
74 : template <typename X>
75 0 : inline CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag, List<X> list)
76 : {
77 : TLV::TLVType type;
78 :
79 0 : ReturnErrorOnFailure(writer.StartContainer(tag, TLV::kTLVType_Array, type));
80 0 : for (auto & item : list)
81 : {
82 0 : ReturnErrorOnFailure(Encode(writer, TLV::AnonymousTag(), item));
83 : }
84 0 : ReturnErrorOnFailure(writer.EndContainer(type));
85 :
86 0 : return CHIP_NO_ERROR;
87 : }
88 :
89 : template <typename X, std::enable_if_t<DataModel::IsFabricScoped<X>::value, bool> = true>
90 : inline CHIP_ERROR EncodeForWrite(TLV::TLVWriter & writer, TLV::Tag tag, List<X> list)
91 : {
92 : TLV::TLVType type;
93 :
94 : ReturnErrorOnFailure(writer.StartContainer(tag, TLV::kTLVType_Array, type));
95 : for (auto & item : list)
96 : {
97 : ReturnErrorOnFailure(EncodeForWrite(writer, TLV::AnonymousTag(), item));
98 : }
99 : ReturnErrorOnFailure(writer.EndContainer(type));
100 :
101 : return CHIP_NO_ERROR;
102 : }
103 :
104 : template <typename X, std::enable_if_t<DataModel::IsFabricScoped<X>::value, bool> = true>
105 : inline CHIP_ERROR EncodeForRead(TLV::TLVWriter & writer, TLV::Tag tag, FabricIndex accessingFabricIndex, List<X> list)
106 : {
107 : TLV::TLVType type;
108 :
109 : ReturnErrorOnFailure(writer.StartContainer(tag, TLV::kTLVType_Array, type));
110 : for (auto & item : list)
111 : {
112 : ReturnErrorOnFailure(EncodeForRead(writer, TLV::AnonymousTag(), accessingFabricIndex, item));
113 : }
114 : ReturnErrorOnFailure(writer.EndContainer(type));
115 :
116 : return CHIP_NO_ERROR;
117 : }
118 :
119 : } // namespace DataModel
120 : } // namespace app
121 : } // namespace chip
|