Skip to content

Commit

Permalink
[wpiutil] Change Struct to allow non-constexpr implementation
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
PeterJohnson committed Dec 3, 2023
1 parent ca272de commit b61d786
Show file tree
Hide file tree
Showing 62 changed files with 812 additions and 450 deletions.
29 changes: 16 additions & 13 deletions ntcore/src/main/native/include/networktables/StructArrayTopic.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
#include <stdint.h>

#include <atomic>
#include <memory>
#include <ranges>
#include <span>
#include <string_view>
#include <utility>
#include <vector>

Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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));
}
Expand Down
54 changes: 36 additions & 18 deletions ntcore/src/main/native/include/networktables/StructTopic.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
Expand Down Expand Up @@ -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;
}
}
Expand All @@ -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)};
}
}

Expand All @@ -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;
Expand Down Expand Up @@ -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);
}
}

/**
Expand All @@ -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);
}
}

/**
Expand Down
Loading

0 comments on commit b61d786

Please sign in to comment.