#pragma once #include #include namespace BAN { template class ByteSpanGeneral { public: using value_type = maybe_const_t; using size_type = size_t; public: ByteSpanGeneral() = default; ByteSpanGeneral(value_type* data, size_type size) : m_data(data) , m_size(size) { } ByteSpanGeneral(ByteSpanGeneral& other) : m_data(other.data()) , m_size(other.size()) { } ByteSpanGeneral(ByteSpanGeneral&& other) : m_data(other.data()) , m_size(other.size()) { other.m_data = nullptr; other.m_size = 0; } template ByteSpanGeneral(const ByteSpanGeneral& other) requires(CONST) : m_data(other.data()) , m_size(other.size()) { } template ByteSpanGeneral(ByteSpanGeneral&& other) requires(CONST) : m_data(other.data()) , m_size(other.size()) { other.m_data = nullptr; other.m_size = 0; } ByteSpanGeneral(Span other) : m_data(other.data()) , m_size(other.size()) { } ByteSpanGeneral(const Span& other) requires(CONST) : m_data(other.data()) , m_size(other.size()) { } ByteSpanGeneral& operator=(ByteSpanGeneral other) { m_data = other.data(); m_size = other.size(); return *this; } template ByteSpanGeneral& operator=(const ByteSpanGeneral& other) requires(CONST) { m_data = other.data(); m_size = other.size(); return *this; } ByteSpanGeneral& operator=(Span other) { m_data = other.data(); m_size = other.size(); return *this; } ByteSpanGeneral& operator=(const Span& other) requires(CONST) { m_data = other.data(); m_size = other.size(); return *this; } template requires(CONST || !is_const_v) static ByteSpanGeneral from(S& value) { return ByteSpanGeneral(reinterpret_cast(&value), sizeof(S)); } template requires(!CONST && !is_const_v) S& as() { ASSERT(m_data); ASSERT(m_size >= sizeof(S)); return *reinterpret_cast(m_data); } template requires(is_const_v) S& as() const { ASSERT(m_data); ASSERT(m_size >= sizeof(S)); return *reinterpret_cast(m_data); } template requires(!CONST && !is_const_v) Span as_span() { ASSERT(m_data); return Span(reinterpret_cast(m_data), m_size / sizeof(S)); } template const Span as_span() const { ASSERT(m_data); return Span(reinterpret_cast(m_data), m_size / sizeof(S)); } ByteSpanGeneral slice(size_type offset, size_type length = size_type(-1)) { ASSERT(m_data); ASSERT(m_size >= offset); if (length == size_type(-1)) length = m_size - offset; ASSERT(m_size >= offset + length); return ByteSpanGeneral(m_data + offset, length); } value_type& operator[](size_type offset) { ASSERT(offset < m_size); return m_data[offset]; } const value_type& operator[](size_type offset) const { ASSERT(offset < m_size); return m_data[offset]; } value_type* data() { return m_data; } const value_type* data() const { return m_data; } size_type size() const { return m_size; } private: value_type* m_data { nullptr }; size_type m_size { 0 }; friend class ByteSpanGeneral; }; using ByteSpan = ByteSpanGeneral; using ConstByteSpan = ByteSpanGeneral; }