1
0
mirror of https://github.com/facebookincubator/mvfst.git synced 2025-04-18 17:24:03 +03:00
mvfst/quic/common/BufUtil.h
Hani Damlaj 00e67c1bf9 mvfst License Header Update
Reviewed By: lnicco

Differential Revision: D33587012

fbshipit-source-id: 972eb440f0156c9c04aa6e8787561b18295c1a97
2022-01-18 13:56:12 -08:00

143 lines
3.4 KiB
C++

/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <folly/io/IOBuf.h>
namespace quic {
using Buf = std::unique_ptr<folly::IOBuf>;
class BufQueue {
public:
BufQueue() = default;
BufQueue(Buf chain) : chain_(std::move(chain)) {
if (chain_) {
chainLength_ = chain_->computeChainDataLength();
}
}
BufQueue(BufQueue&& other) noexcept
: chain_(std::move(other.chain_)), chainLength_(other.chainLength_) {
other.chainLength_ = 0;
}
BufQueue& operator=(BufQueue&& other) {
if (&other != this) {
chain_ = std::move(other.chain_);
chainLength_ = other.chainLength_;
other.chainLength_ = 0;
}
return *this;
}
BufQueue(const BufQueue&) = delete;
BufQueue& operator=(const BufQueue&) = delete;
size_t chainLength() const {
return chainLength_;
}
bool empty() const {
return chainLength_ == 0;
}
Buf move() {
chainLength_ = 0;
return std::move(chain_);
}
const folly::IOBuf* front() const {
return chain_.get();
}
Buf splitAtMost(size_t n);
size_t trimStartAtMost(size_t amount);
void trimStart(size_t amount);
void append(Buf&& buf);
private:
void appendToChain(Buf& dst, Buf&& src);
Buf chain_;
size_t chainLength_{0};
};
class BufAppender {
public:
BufAppender(folly::IOBuf* data, size_t appendLen);
template <class T>
void writeBE(T data) {
auto bigEndian = folly::Endian::big(data);
push((uint8_t*)(&bigEndian), sizeof(bigEndian));
}
void push(const uint8_t* data, size_t len);
void insert(std::unique_ptr<folly::IOBuf> data);
private:
folly::IOBuf* crtBuf_;
folly::IOBuf* head_;
size_t appendLen_;
bool lastBufShared_{false};
};
class BufWriter {
public:
explicit BufWriter(folly::IOBuf& iobuf, size_t most);
template <class T>
void writeBE(T data) {
auto dataSize = sizeof(T);
sizeCheck(dataSize);
auto bigEndian = folly::Endian::big(data);
push((uint8_t*)&bigEndian, dataSize);
}
void push(const uint8_t* data, size_t len);
/**
* Push len amound from data into the IOBuf, starting at IOBuf's destOffset
* position. Given this is a back fill, we don't increase the written bytes
* count for this API, since they should be already counted in a previous
* append() call.
*/
void backFill(const uint8_t* data, size_t len, size_t destOffset);
// TODO: OK, "insert" is a lie. Inside, we copy. But I'd like the BufWriter
// to have the same interface as BufAppender during the transition period.
void insert(const folly::IOBuf* data);
void insert(const folly::IOBuf* data, size_t limit);
void append(size_t len);
private:
// TODO: This is caller responsibility for now so the BufWriter conform with
// BufAppender interface. But once BufAppender is replaced by BufWriter, we
// should let BufWriter check the size and return error code if it fails to
// write.
void sizeCheck(size_t dataSize) {
DCHECK(iobuf_.tailroom() >= dataSize && written_ + dataSize <= most_)
<< "Buffer room=" << iobuf_.tailroom() << " inputSize=" << dataSize
<< " written=" << written_ << " limit=" << most_;
}
void copy(const folly::IOBuf* data, size_t limit);
private:
folly::IOBuf& iobuf_;
size_t most_;
size_t written_{0};
size_t appendCount_{0};
};
} // namespace quic