/* This file is part of Telegram Desktop, the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once #include "base/basic_types.h" #include #include namespace bytes { using type = gsl::byte; using span = gsl::span; using const_span = gsl::span; using vector = std::vector; template using array = std::array; inline span make_detached_span(QByteArray &container) { return gsl::as_writeable_bytes(gsl::make_span(container)); } template < typename Container, typename = std::enable_if_t< !std::is_const_v && !std::is_same_v>> inline span make_span(Container &container) { return gsl::as_writeable_bytes(gsl::make_span(container)); } template inline const_span make_span(const Container &container) { return gsl::as_bytes(gsl::make_span(container)); } template inline span make_span(gsl::span container) { return gsl::as_writeable_bytes(container); } template inline const_span make_span(gsl::span container) { return gsl::as_bytes(container); } template inline span make_span(Type *value, std::size_t count) { return gsl::as_writeable_bytes(gsl::make_span(value, count)); } template inline const_span make_span(const Type *value, std::size_t count) { return gsl::as_bytes(gsl::make_span(value, count)); } template inline span object_as_span(Type *value) { return bytes::make_span(value, 1); } template inline const_span object_as_span(const Type *value) { return bytes::make_span(value, 1); } template inline vector make_vector(const Container &container) { const auto buffer = bytes::make_span(container); return { buffer.begin(), buffer.end() }; } inline void copy(span destination, const_span source) { Expects(destination.size() >= source.size()); memcpy(destination.data(), source.data(), source.size()); } inline void move(span destination, const_span source) { Expects(destination.size() >= source.size()); memmove(destination.data(), source.data(), source.size()); } inline void set_with_const(span destination, type value) { memset( destination.data(), gsl::to_integer(value), destination.size()); } inline int compare(const_span a, const_span b) { const auto aSize = a.size(), bSize = b.size(); return (aSize > bSize) ? 1 : (aSize < bSize) ? -1 : memcmp(a.data(), b.data(), aSize); } namespace details { template std::size_t spansLength(Arg &&arg) { return bytes::make_span(arg).size(); } template std::size_t spansLength(Arg &&arg, Args &&...args) { return bytes::make_span(arg).size() + spansLength(args...); } template void spansAppend(span destination, Arg &&arg) { bytes::copy(destination, bytes::make_span(arg)); } template void spansAppend(span destination, Arg &&arg, Args &&...args) { const auto data = bytes::make_span(arg); bytes::copy(destination, data); spansAppend(destination.subspan(data.size()), args...); } } // namespace details template < typename ...Args, typename = std::enable_if_t<(sizeof...(Args) > 1)>> vector concatenate(Args &&...args) { const auto size = details::spansLength(args...); auto result = vector(size); details::spansAppend(make_span(result), args...); return result; } template < typename SpanRange> vector concatenate(SpanRange args) { auto size = std::size_t(0); for (const auto &arg : args) { size += bytes::make_span(arg).size(); } auto result = vector(size); auto buffer = make_span(result); for (const auto &arg : args) { const auto part = bytes::make_span(arg); bytes::copy(buffer, part); buffer = buffer.subspan(part.size()); } return result; } // Implemented in base/openssl_help.h void set_random(span destination); } // namespace bytes