blob: 794fd89065169ad800f6e2b7fd064463c9b7bd98 [file] [edit]
/*
* SPDX-FileCopyrightText: Copyright OpenBMC Authors
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <bit>
#include <cerrno>
#include <concepts>
#include <cstdint>
#include <cstring>
#include <span>
class PackBuffer
{
public:
PackBuffer(std::span<uint8_t> buffer) : buffer(buffer) {}
template <typename T>
int pack(T data)
requires std::integral<T>;
int getError() const
{
return error;
}
private:
std::span<uint8_t> buffer;
int error = 0;
};
class UnpackBuffer
{
public:
UnpackBuffer(std::span<const uint8_t> buffer) : buffer(buffer) {}
template <typename T>
int unpack(T& data)
requires std::integral<T>;
int skip(size_t length);
std::span<const uint8_t> getRemaining() const
{
return buffer;
}
int getError() const
{
return error;
}
private:
std::span<const uint8_t> buffer;
int error = 0;
};
template <typename T>
int PackBuffer::pack(T data)
requires std::integral<T>
{
if (error != 0)
{
return error;
}
if (buffer.size() < sizeof(T))
{
error = EINVAL;
return error;
}
if constexpr (sizeof(T) > 1 && std::endian::native != std::endian::little)
{
data = std::byteswap(data);
}
std::memcpy(buffer.data(), &data, sizeof(T));
buffer = buffer.subspan<sizeof(T)>();
return 0;
}
template <typename T>
int UnpackBuffer::unpack(T& data)
requires std::integral<T>
{
if (error != 0)
{
return error;
}
if (buffer.size() < sizeof(T))
{
error = EINVAL;
return error;
}
std::memcpy(&data, buffer.data(), sizeof(T));
if constexpr (sizeof(T) > 1 && std::endian::native != std::endian::little)
{
data = std::byteswap(data);
}
buffer = buffer.subspan<sizeof(T)>();
return 0;
}
inline int UnpackBuffer::skip(const size_t length)
{
if (error != 0)
{
return error;
}
if (buffer.size() < length)
{
error = EINVAL;
return error;
}
buffer = buffer.subspan(length);
return 0;
}