DCCL v4
Loading...
Searching...
No Matches
field_codec_presence.h
1// Copyright 2019-2023:
2// GobySoft, LLC (2013-)
3// Community contributors (see AUTHORS file)
4// File authors:
5// Toby Schneider <toby@gobysoft.org>
6// Kyle Guilbert <kguilbert@aphysci.com>
7//
8//
9// This file is part of the Dynamic Compact Control Language Library
10// ("DCCL").
11//
12// DCCL is free software: you can redistribute it and/or modify
13// it under the terms of the GNU Lesser General Public License as published by
14// the Free Software Foundation, either version 2.1 of the License, or
15// (at your option) any later version.
16//
17// DCCL is distributed in the hope that it will be useful,
18// but WITHOUT ANY WARRANTY; without even the implied warranty of
19// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20// GNU Lesser General Public License for more details.
21//
22// You should have received a copy of the GNU Lesser General Public License
23// along with DCCL. If not, see <http://www.gnu.org/licenses/>.
24#ifndef FIELD_CODEC_PRESENCE_20190722H
25#define FIELD_CODEC_PRESENCE_20190722H
26
27#include "../field_codec_typed.h"
28
29namespace dccl
30{
31namespace v3
32{
43template <typename WrappedType>
45 : public TypedFieldCodec<typename WrappedType::wire_type, typename WrappedType::field_type>
46{
47 public:
49
51 using wrapped_type = WrappedType;
52
54 using wire_type = typename Base::wire_type;
55
57 using field_type = typename Base::field_type;
58
59 private:
61 WrappedType _inner_codec;
62
63 public:
64 PresenceBitCodec() { _inner_codec.set_force_use_required(true); }
65
66 // required when wire_type != field_type
67 wire_type pre_encode(const field_type& field_value) override
68 {
69 return _inner_codec.pre_encode(field_value);
70 }
71
72 // required when wire_type != field_type
73 field_type post_decode(const wire_type& wire_value) override
74 {
75 return _inner_codec.post_decode(wire_value);
76 }
77
79 void validate() override { _inner_codec.validate(); }
80
82 Bitset encode() override
83 {
84 return Bitset(1, 0); // presence bit == false
85 }
86
88 Bitset encode(const wire_type& value) override
89 {
90 Bitset encoded = _inner_codec.encode(value);
91
92 if (!this->use_required())
93 {
94 encoded.push_front(true);
95 }
96 return encoded;
97 }
98
100 wire_type decode(Bitset* bits) override
101 {
102 if (!this->use_required())
103 {
104 // optional field: bits contains only the presence bit
105 bool present = bits->front();
106 if (!present)
107 {
108 throw NullValueException();
109 }
110 // the single bit was the presence bit; consume it and get the rest
111 bits->pop_front();
112 bits->get_more_bits(_inner_codec.size());
113 }
114
115 return _inner_codec.decode(bits);
116 }
117
119 unsigned size() override
120 {
121 // empty field is always 1 bit (only occurs for optional fields)
122 return 1;
123 }
124
126 unsigned size(const wire_type& wire_value) override
127 {
128 int presence_bits = this->use_required() ? 0 : 1;
129 return presence_bits + _inner_codec.size(wire_value);
130 }
131
132 unsigned max_size() override
133 {
134 if (this->use_required())
135 {
136 // def to "wrapped" codec
137 return _inner_codec.max_size();
138 }
139 else
140 {
141 // optional fields have the extra presence bit
142 return _inner_codec.max_size() + 1;
143 }
144 }
145
146 unsigned min_size() override
147 {
148 if (this->use_required())
149 {
150 // defer to "wrapped" codec
151 return _inner_codec.min_size();
152 }
153 else
154 {
155 // optional fields encode as 1 bit minimum
156 return 1;
157 }
158 }
159
160 void set_manager(FieldCodecManagerLocal* manager) override
161 {
162 _inner_codec.set_manager(manager);
163 FieldCodecBase::set_manager(manager);
164 }
165};
166} // namespace v3
167} // namespace dccl
168
169#endif /* FIELD_CODEC_PRESENCE_20190722H */
A variable size container of bits (subclassed from std::deque<bool>) with an optional hierarchy....
Definition bitset.h:43
void get_more_bits(size_type num_bits)
Retrieve more bits from the parent Bitset.
Definition bitset.h:420
void set_force_use_required(bool force_required=true)
Force the codec to always use the "required" field encoding, regardless of the FieldDescriptor settin...
bool use_required()
Whether to use the required or optional encoding.
A class for managing the various field codecs. Here you can add and remove field codecs....
Exception used to signal null (non-existent) value within field codecs during decode.
Definition exception.h:62
Base class for static-typed (no dccl::any) field encoders/decoders. Most single-valued user defined v...
Encodes empty optional fields with a single "presence" bit.
void validate() override
Calls _inner_codec.validate()
unsigned size(const wire_type &wire_value) override
Size of a non-empty field; gets size from "wrapped" codec, adds 1 for optional fields.
unsigned size() override
Size of an empty field (1 bit)
wire_type pre_encode(const field_type &field_value) override
Convert from the FieldType representation (used in the Google Protobuf message) to the WireType repre...
unsigned min_size() override
Calculate minimum size of the field in bits.
Bitset encode() override
Encodes an empty field as a single 0 bit.
WrappedType wrapped_type
The codec type of the "wrapped" codec.
typename Base::wire_type wire_type
The wire_type of the "wrapped" codec.
unsigned max_size() override
Calculate maximum size of the field in bits.
typename Base::field_type field_type
The field_type of the "wrapped" codec.
wire_type decode(Bitset *bits) override
Decodes a field, first evaluating the presence bit if necessary.
Bitset encode(const wire_type &value) override
Encodes a non-empty field, adding a 1 bit to the front for optional fields.
field_type post_decode(const wire_type &wire_value) override
Convert from the WireType representation (used with encode() and decode(), i.e. "on the wire") to the...
Dynamic Compact Control Language namespace.
Definition any.h:47