/* * Copyright (C) 2014-present ScyllaDB */ /* * SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0 */ #ifndef UTILS_DATA_INPUT_HH_ #define UTILS_DATA_INPUT_HH_ #include "bytes_fwd.hh" #include #include class data_input { public: data_input(const bytes_view& v) : _view(v) { } data_input(bytes_view&& v) : _view(std::move(v)) { } data_input(const bytes& b) : data_input(bytes_view(b)) { } data_input(const bytes& b, size_t off, size_t n = bytes::npos) : data_input( bytes_view(b.c_str() + off, std::min(b.size() - off, n))) { if (off > b.size()) { throw std::out_of_range("Offset out of range"); } } template data_input(const std::basic_string_view& view) : data_input( bytes_view(reinterpret_cast(view.data()), view.size() * sizeof(T))) { } template data_input(const temporary_buffer& buf) : data_input( std::basic_string_view(buf.get(), buf.size())) { } data_input(data_input&&) = default; data_input(const data_input&) = default; size_t avail() const { return _view.size(); } bool has_next() const { return !_view.empty(); } void ensure(size_t s) const { if (avail() < s) { throw std::out_of_range("Buffer underflow"); } } template T peek() const; template T read(); bytes_view read_view(size_t len) { ensure(len); bytes_view v(_view.begin(), len); _view.remove_prefix(len); return v; } template bytes_view read_view_to_blob() { auto len = read(); return read_view(len); } void skip(size_t s) { ensure(s); _view.remove_prefix(s); } private: template size_t ssize(const T &) const; template inline T peek_primitive() const { ensure(sizeof(T)); T t; std::copy_n(_view.begin(), sizeof(T), reinterpret_cast(&t)); return net::ntoh(t); } bytes_view _view; }; template<> inline sstring data_input::peek() const { auto len = peek(); ensure(sizeof(uint16_t) + len); return sstring(reinterpret_cast(_view.data()) + sizeof(uint16_t), len); } template<> inline size_t data_input::ssize(const sstring & s) const { return sizeof(uint16_t) + s.size(); } template<> inline bytes data_input::peek() const { auto len = peek(); ensure(sizeof(uint32_t) + len); return bytes(_view.data() + sizeof(uint32_t), len); } template<> inline size_t data_input::ssize(const bytes & s) const { return sizeof(uint32_t) + s.size(); } template<> inline bytes_view data_input::peek() const { auto len = peek(); ensure(sizeof(uint32_t) + len); return bytes_view(_view.data() + sizeof(uint32_t), len); } template<> inline size_t data_input::ssize(const bytes_view& v) const { return sizeof(uint32_t) + v.size(); } template<> inline size_t data_input::ssize(const bool &) const { return sizeof(uint8_t); } template<> inline bool data_input::peek() const { return peek() != 0; } template inline T data_input::peek() const { return peek_primitive(); } template inline T data_input::read() { auto t = peek(); _view.remove_prefix(ssize(t)); return std::move(t); } template inline size_t data_input::ssize(const T &) const { return sizeof(T); } #endif /* UTILS_DATA_INPUT_HH_ */