blob: dab8bb257cb378ad31e9d1c48554ba8506a5a1f8 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
#pragma once
#include "mkql_computation_node_pack_impl.h"
#include <util/generic/bitmap.h>
#include <util/generic/buffer.h>
#include <cstring>
namespace NKikimr {
namespace NMiniKQL {
namespace NDetails {
class TOptionalUsageMask {
public:
TOptionalUsageMask() = default;
void Reset() {
CountOfOptional = 0U;
Mask.Clear();
}
void Reset(TChunkedInputBuffer& buf) {
Reset();
ui64 bytes = UnpackUInt64(buf);
if (bytes) {
Mask.Reserve(bytes << 3ULL);
buf.CopyTo(reinterpret_cast<char*>(const_cast<ui8*>(Mask.GetChunks())), bytes);
}
}
void SetNextEmptyOptional(bool empty) {
if (empty) {
Mask.Set(CountOfOptional);
}
++CountOfOptional;
}
bool IsNextEmptyOptional() {
return Mask.Test(CountOfOptional++);
}
bool IsEmptyMask() const {
return Mask.Empty();
}
size_t CalcSerializedSize() {
if (!CountOfOptional || Mask.Empty()) {
return 1ULL; // One byte for size=0
}
const size_t usedBits = Mask.ValueBitCount();
const size_t usedBytes = (usedBits + 7ULL) >> 3ULL;
return GetPack64Length(usedBytes) + usedBytes;
}
template<typename TBuf>
void Serialize(TBuf& buf) const {
if (!CountOfOptional || Mask.Empty()) {
return buf.Append(0);
}
const size_t usedBits = Mask.ValueBitCount();
const size_t usedBytes = (usedBits + 7ULL) >> 3ULL;
buf.Advance(MAX_PACKED64_SIZE);
// Note: usage of Pack64() is safe here - it won't overwrite useful data for small values of usedBytes
buf.EraseBack(MAX_PACKED64_SIZE - Pack64(usedBytes, buf.Pos() - MAX_PACKED64_SIZE));
buf.Append(reinterpret_cast<const char*>(Mask.GetChunks()), usedBytes);
}
private:
ui32 CountOfOptional = 0U;
TBitMapOps<TDynamicBitMapTraits<ui8>> Mask;
};
} // NDetails
}
}
|