mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-27 02:01:42 +00:00
[wpiutil] Change Struct to allow non-constexpr implementation (#5992)
This required changing the constant values (e.g. kSize) into functions (e.g. GetSize()). Fixed implementations of ForEachNested to be inline (as these are actually templates). Also added a ntcore Struct test.
This commit is contained in:
@@ -7,9 +7,9 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <ranges>
|
||||
#include <span>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -121,16 +121,17 @@ class StructArraySubscriber : public Subscriber {
|
||||
#endif
|
||||
TimestampedValueType GetAtomic(U&& defaultValue) const {
|
||||
wpi::SmallVector<uint8_t, 128> buf;
|
||||
size_t size = S::GetSize();
|
||||
TimestampedRawView view = ::nt::GetAtomicRaw(m_subHandle, buf, {});
|
||||
if (view.value.size() == 0 || (view.value.size() % S::kSize) != 0) {
|
||||
if (view.value.size() == 0 || (view.value.size() % size) != 0) {
|
||||
return {0, 0, std::forward<U>(defaultValue)};
|
||||
}
|
||||
TimestampedValueType rv{view.time, view.serverTime, {}};
|
||||
rv.value.reserve(view.value.size() / S::kSize);
|
||||
rv.value.reserve(view.value.size() / size);
|
||||
for (auto in = view.value.begin(), end = view.value.end(); in != end;
|
||||
in += S::kSize) {
|
||||
in += size) {
|
||||
rv.value.emplace_back(
|
||||
S::Unpack(std::span<const uint8_t, S::kSize>{in, in + S::kSize}));
|
||||
S::Unpack(std::span<const uint8_t>{std::to_address(in), size}));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
@@ -145,16 +146,17 @@ class StructArraySubscriber : public Subscriber {
|
||||
*/
|
||||
TimestampedValueType GetAtomic(std::span<const T> defaultValue) const {
|
||||
wpi::SmallVector<uint8_t, 128> buf;
|
||||
size_t size = S::GetSize();
|
||||
TimestampedRawView view = ::nt::GetAtomicRaw(m_subHandle, buf, {});
|
||||
if (view.value.size() == 0 || (view.value.size() % S::kSize) != 0) {
|
||||
if (view.value.size() == 0 || (view.value.size() % size) != 0) {
|
||||
return {0, 0, {defaultValue.begin(), defaultValue.end()}};
|
||||
}
|
||||
TimestampedValueType rv{view.time, view.serverTime, {}};
|
||||
rv.value.reserve(view.value.size() / S::kSize);
|
||||
rv.value.reserve(view.value.size() / size);
|
||||
for (auto in = view.value.begin(), end = view.value.end(); in != end;
|
||||
in += S::kSize) {
|
||||
in += size) {
|
||||
rv.value.emplace_back(
|
||||
S::Unpack(std::span<const uint8_t, S::kSize>{in, in + S::kSize}));
|
||||
S::Unpack(std::span<const uint8_t>{std::to_address(in), size}));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
@@ -174,16 +176,17 @@ class StructArraySubscriber : public Subscriber {
|
||||
auto raw = ::nt::ReadQueueRaw(m_subHandle);
|
||||
std::vector<TimestampedValueType> rv;
|
||||
rv.reserve(raw.size());
|
||||
size_t size = S::GetSize();
|
||||
for (auto&& r : raw) {
|
||||
if (r.value.size() == 0 || (r.value.size() % S::kSize) != 0) {
|
||||
if (r.value.size() == 0 || (r.value.size() % size) != 0) {
|
||||
continue;
|
||||
}
|
||||
std::vector<T> values;
|
||||
values.reserve(r.value.size() / S::kSize);
|
||||
values.reserve(r.value.size() / size);
|
||||
for (auto in = r.value.begin(), end = r.value.end(); in != end;
|
||||
in += S::kSize) {
|
||||
in += size) {
|
||||
values.emplace_back(
|
||||
S::Unpack(std::span<const uint8_t, S::kSize>{in, in + S::kSize}));
|
||||
S::Unpack(std::span<const uint8_t>{std::to_address(in), size}));
|
||||
}
|
||||
rv.emplace_back(r.time, r.serverTime, std::move(values));
|
||||
}
|
||||
|
||||
@@ -32,6 +32,13 @@ class StructTopic;
|
||||
template <wpi::StructSerializable T>
|
||||
class StructSubscriber : public Subscriber {
|
||||
using S = wpi::Struct<T>;
|
||||
static constexpr size_t kBufSize = []() -> size_t {
|
||||
if constexpr (wpi::is_constexpr([] { S::GetSize(); })) {
|
||||
return S::GetSize();
|
||||
} else {
|
||||
return 128;
|
||||
}
|
||||
}();
|
||||
|
||||
public:
|
||||
using TopicType = StructTopic<T>;
|
||||
@@ -81,12 +88,12 @@ class StructSubscriber : public Subscriber {
|
||||
* @return true if successful
|
||||
*/
|
||||
bool GetInto(T* out) {
|
||||
wpi::SmallVector<uint8_t, S::kSize> buf;
|
||||
wpi::SmallVector<uint8_t, kBufSize> buf;
|
||||
TimestampedRawView view = ::nt::GetAtomicRaw(m_subHandle, buf, {});
|
||||
if (view.value.size() < S::kSize) {
|
||||
if (view.value.size() < S::GetSize()) {
|
||||
return false;
|
||||
} else {
|
||||
wpi::UnpackStructInto(out, view.value.subspan<0, S::kSize>());
|
||||
wpi::UnpackStructInto(out, view.value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -109,13 +116,12 @@ class StructSubscriber : public Subscriber {
|
||||
* @return timestamped value
|
||||
*/
|
||||
TimestampedValueType GetAtomic(const T& defaultValue) const {
|
||||
wpi::SmallVector<uint8_t, S::kSize> buf;
|
||||
wpi::SmallVector<uint8_t, kBufSize> buf;
|
||||
TimestampedRawView view = ::nt::GetAtomicRaw(m_subHandle, buf, {});
|
||||
if (view.value.size() < S::kSize) {
|
||||
if (view.value.size() < S::GetSize()) {
|
||||
return {0, 0, defaultValue};
|
||||
} else {
|
||||
return {view.time, view.serverTime,
|
||||
S::Unpack(view.value.subspan<0, S::kSize>())};
|
||||
return {view.time, view.serverTime, S::Unpack(view.value)};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,13 +141,11 @@ class StructSubscriber : public Subscriber {
|
||||
std::vector<TimestampedValueType> rv;
|
||||
rv.reserve(raw.size());
|
||||
for (auto&& r : raw) {
|
||||
if (r.value.size() < S::kSize) {
|
||||
if (r.value.size() < S::GetSize()) {
|
||||
continue;
|
||||
} else {
|
||||
rv.emplace_back(
|
||||
r.time, r.serverTime,
|
||||
S::Unpack(
|
||||
std::span<const uint8_t>(r.value).subspan<0, S::kSize>()));
|
||||
rv.emplace_back(r.time, r.serverTime,
|
||||
S::Unpack(std::span<const uint8_t>(r.value)));
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
@@ -208,9 +212,16 @@ class StructPublisher : public Publisher {
|
||||
if (!m_schemaPublished.exchange(true, std::memory_order_relaxed)) {
|
||||
GetTopic().GetInstance().template AddStructSchema<T>();
|
||||
}
|
||||
uint8_t buf[S::kSize];
|
||||
S::Pack(buf, value);
|
||||
::nt::SetRaw(m_pubHandle, buf, time);
|
||||
if constexpr (wpi::is_constexpr([] { S::GetSize(); })) {
|
||||
uint8_t buf[S::GetSize()];
|
||||
S::Pack(buf, value);
|
||||
::nt::SetRaw(m_pubHandle, buf, time);
|
||||
} else {
|
||||
wpi::SmallVector<uint8_t, 128> buf;
|
||||
buf.resize_for_overwrite(S::GetSize());
|
||||
S::Pack(buf, value);
|
||||
::nt::SetRaw(m_pubHandle, buf, time);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -224,9 +235,16 @@ class StructPublisher : public Publisher {
|
||||
if (!m_schemaPublished.exchange(true, std::memory_order_relaxed)) {
|
||||
GetTopic().GetInstance().template AddStructSchema<T>();
|
||||
}
|
||||
uint8_t buf[S::kSize];
|
||||
S::Pack(buf, value);
|
||||
::nt::SetDefaultRaw(m_pubHandle, buf);
|
||||
if constexpr (wpi::is_constexpr([] { S::GetSize(); })) {
|
||||
uint8_t buf[S::GetSize()];
|
||||
S::Pack(buf, value);
|
||||
::nt::SetDefaultRaw(m_pubHandle, buf);
|
||||
} else {
|
||||
wpi::SmallVector<uint8_t, 128> buf;
|
||||
buf.resize_for_overwrite(S::GetSize());
|
||||
S::Pack(buf, value);
|
||||
::nt::SetDefaultRaw(m_pubHandle, buf);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user