1/*
2 *     Copyright 2019 Couchbase, Inc.
3 *
4 *   Licensed under the Apache License, Version 2.0 (the "License");
5 *   you may not use this file except in compliance with the License.
6 *   You may obtain a copy of the License at
7 *
8 *       http://www.apache.org/licenses/LICENSE-2.0
9 *
10 *   Unless required by applicable law or agreed to in writing, software
11 *   distributed under the License is distributed on an "AS IS" BASIS,
12 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 *   See the License for the specific language governing permissions and
14 *   limitations under the License.
15 */
16
17#include "frameinfo.h"
18
19#include <gsl.h>
20#include <mcbp/protocol/request.h>
21
22FrameInfo::~FrameInfo() = default;
23BarrierFrameInfo::~BarrierFrameInfo() = default;
24DurabilityFrameInfo::~DurabilityFrameInfo() = default;
25DcpStreamIdFrameInfo::~DcpStreamIdFrameInfo() = default;
26OpenTracingContextFrameInfo::~OpenTracingContextFrameInfo() = default;
27
28using cb::mcbp::request::FrameInfoId;
29
30std::vector<uint8_t> BarrierFrameInfo::encode() const {
31    std::vector<uint8_t> ret;
32    ret.push_back(uint8_t(FrameInfoId::Barrier) << 0x04U);
33    return ret;
34}
35
36std::vector<uint8_t> DurabilityFrameInfo::encode() const {
37    using cb::durability::Level;
38    using cb::durability::Timeout;
39
40    if (level == Level::None) {
41        return {};
42    }
43
44    std::vector<uint8_t> ret(2);
45    ret[0] = uint8_t(FrameInfoId::DurabilityRequirement) << 0x04U;
46    ret[1] = (uint8_t(0x0f) & uint8_t(level));
47
48    if (timeout.isDefault()) {
49        // Level is the only byte
50        ret[0] |= uint8_t(0x01);
51    } else {
52        // Level and timeout is present
53        ret[0] |= uint8_t(0x03);
54        auto value = htons(timeout.get());
55        const auto* ptr = reinterpret_cast<const char*>(&value);
56        ret.insert(ret.end(), ptr, ptr + sizeof(value));
57    }
58
59    return ret;
60}
61
62std::vector<uint8_t> DcpStreamIdFrameInfo::encode() const {
63    std::vector<uint8_t> ret(1);
64    ret[0] = uint8_t(FrameInfoId::DcpStreamId) << 0x04U;
65    ret[0] |= sizeof(id);
66    auto value = htons(id);
67    const auto* ptr = reinterpret_cast<const char*>(&value);
68    ret.insert(ret.end(), ptr, ptr + sizeof(value));
69
70    return ret;
71}
72
73std::vector<uint8_t> OpenTracingContextFrameInfo::encode() const {
74    std::vector<uint8_t> ret(1);
75    ret[0] = uint8_t(FrameInfoId::OpenTracingContext) << 0x04U;
76    if (ctx.size() < 0x0fU) {
77        // We may fit in a single byte
78        ret[0] |= uint8_t(ctx.size());
79    } else {
80        // we need an extra length byte to set the length
81        ret[0] |= 0x0fU;
82        ret.push_back(gsl::narrow<uint8_t>(ctx.size()));
83    }
84    ret.insert(ret.end(), ctx.cbegin(), ctx.cend());
85
86    return ret;
87}
88