aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/blockcodecs/core/codecs.cpp
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/blockcodecs/core/codecs.cpp
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/blockcodecs/core/codecs.cpp')
-rw-r--r--library/cpp/blockcodecs/core/codecs.cpp148
1 files changed, 148 insertions, 0 deletions
diff --git a/library/cpp/blockcodecs/core/codecs.cpp b/library/cpp/blockcodecs/core/codecs.cpp
new file mode 100644
index 0000000000..21506e812b
--- /dev/null
+++ b/library/cpp/blockcodecs/core/codecs.cpp
@@ -0,0 +1,148 @@
+#include "codecs.h"
+#include "common.h"
+#include "register.h"
+
+#include <util/ysaveload.h>
+#include <util/stream/null.h>
+#include <util/stream/mem.h>
+#include <util/string/cast.h>
+#include <util/string/join.h>
+#include <util/system/align.h>
+#include <util/system/unaligned_mem.h>
+#include <util/generic/hash.h>
+#include <util/generic/cast.h>
+#include <util/generic/deque.h>
+#include <util/generic/buffer.h>
+#include <util/generic/array_ref.h>
+#include <util/generic/singleton.h>
+#include <util/generic/algorithm.h>
+#include <util/generic/mem_copy.h>
+
+using namespace NBlockCodecs;
+
+namespace {
+
+ struct TCodecFactory {
+ inline TCodecFactory() {
+ Add(&Null);
+ }
+
+ inline const ICodec* Find(const TStringBuf& name) const {
+ auto it = Registry.find(name);
+
+ if (it == Registry.end()) {
+ ythrow TNotFound() << "can not found " << name << " codec";
+ }
+
+ return it->second;
+ }
+
+ inline void ListCodecs(TCodecList& lst) const {
+ for (const auto& it : Registry) {
+ lst.push_back(it.first);
+ }
+
+ Sort(lst.begin(), lst.end());
+ }
+
+ inline void Add(ICodec* codec) {
+ Registry[codec->Name()] = codec;
+ }
+
+ inline void Add(TCodecPtr codec) {
+ Codecs.push_back(std::move(codec));
+ Add(Codecs.back().Get());
+ }
+
+ inline void Alias(TStringBuf from, TStringBuf to) {
+ Tmp.emplace_back(from);
+ Registry[Tmp.back()] = Registry[to];
+ }
+
+ TDeque<TString> Tmp;
+ TNullCodec Null;
+ TVector<TCodecPtr> Codecs;
+ typedef THashMap<TStringBuf, ICodec*> TRegistry;
+ TRegistry Registry;
+
+ // SEARCH-8344: Global decompressed size limiter (to prevent remote DoS)
+ size_t MaxPossibleDecompressedLength = Max<size_t>();
+ };
+}
+
+const ICodec* NBlockCodecs::Codec(const TStringBuf& name) {
+ return Singleton<TCodecFactory>()->Find(name);
+}
+
+TCodecList NBlockCodecs::ListAllCodecs() {
+ TCodecList ret;
+
+ Singleton<TCodecFactory>()->ListCodecs(ret);
+
+ return ret;
+}
+
+TString NBlockCodecs::ListAllCodecsAsString() {
+ return JoinSeq(TStringBuf(","), ListAllCodecs());
+}
+
+void NBlockCodecs::RegisterCodec(TCodecPtr codec) {
+ Singleton<TCodecFactory>()->Add(std::move(codec));
+}
+
+void NBlockCodecs::RegisterAlias(TStringBuf from, TStringBuf to) {
+ Singleton<TCodecFactory>()->Alias(from, to);
+}
+
+void NBlockCodecs::SetMaxPossibleDecompressedLength(size_t maxPossibleDecompressedLength) {
+ Singleton<TCodecFactory>()->MaxPossibleDecompressedLength = maxPossibleDecompressedLength;
+}
+
+size_t NBlockCodecs::GetMaxPossibleDecompressedLength() {
+ return Singleton<TCodecFactory>()->MaxPossibleDecompressedLength;
+}
+
+size_t ICodec::GetDecompressedLength(const TData& in) const {
+ const size_t len = DecompressedLength(in);
+
+ Y_ENSURE(
+ len <= NBlockCodecs::GetMaxPossibleDecompressedLength(),
+ "Attempt to decompress the block that is larger than maximum possible decompressed length, "
+ "see SEARCH-8344 for details. "
+ );
+ return len;
+}
+
+void ICodec::Encode(const TData& in, TBuffer& out) const {
+ const size_t maxLen = MaxCompressedLength(in);
+
+ out.Reserve(maxLen);
+ out.Resize(Compress(in, out.Data()));
+}
+
+void ICodec::Decode(const TData& in, TBuffer& out) const {
+ const size_t len = GetDecompressedLength(in);
+
+ out.Reserve(len);
+ out.Resize(Decompress(in, out.Data()));
+}
+
+void ICodec::Encode(const TData& in, TString& out) const {
+ const size_t maxLen = MaxCompressedLength(in);
+ out.ReserveAndResize(maxLen);
+
+ size_t actualLen = Compress(in, out.begin());
+ Y_ASSERT(actualLen <= maxLen);
+ out.resize(actualLen);
+}
+
+void ICodec::Decode(const TData& in, TString& out) const {
+ const size_t maxLen = GetDecompressedLength(in);
+ out.ReserveAndResize(maxLen);
+
+ size_t actualLen = Decompress(in, out.begin());
+ Y_ASSERT(actualLen <= maxLen);
+ out.resize(actualLen);
+}
+
+ICodec::~ICodec() = default;