wireforge 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wireforge/__init__.py +3 -0
- wireforge/_data/cmake/WireForgeConfig.cmake +29 -0
- wireforge/_data/cmake/WireForgeConfigVersion.cmake +15 -0
- wireforge/_data/cmake/WireForgeGenerate.cmake +64 -0
- wireforge/_data/runtime/LICENSE +21 -0
- wireforge/_data/runtime/include/wireforge/array_access.hpp +35 -0
- wireforge/_data/runtime/include/wireforge/bit_utils.hpp +226 -0
- wireforge/_data/runtime/include/wireforge/byte_io.hpp +387 -0
- wireforge/_data/runtime/include/wireforge/checksum.hpp +201 -0
- wireforge/_data/runtime/include/wireforge/codec_support.hpp +412 -0
- wireforge/_data/runtime/include/wireforge/config.hpp +41 -0
- wireforge/_data/runtime/include/wireforge/delegate.hpp +101 -0
- wireforge/_data/runtime/include/wireforge/dispatcher.hpp +339 -0
- wireforge/_data/runtime/include/wireforge/expr_support.hpp +38 -0
- wireforge/_data/runtime/include/wireforge/frame_decoder.hpp +262 -0
- wireforge/_data/runtime/include/wireforge/frame_layout.hpp +20 -0
- wireforge/_data/runtime/include/wireforge/link.hpp +223 -0
- wireforge/_data/runtime/include/wireforge/lock.hpp +146 -0
- wireforge/_data/runtime/include/wireforge/ring_buffer.hpp +226 -0
- wireforge/_data/runtime/include/wireforge/span.hpp +116 -0
- wireforge/_data/runtime/include/wireforge/static_vector.hpp +264 -0
- wireforge/_data/runtime/include/wireforge/status.hpp +75 -0
- wireforge/_data/runtime/include/wireforge/transport.hpp +95 -0
- wireforge/_data/runtime/include/wireforge/validation.hpp +153 -0
- wireforge/_data/runtime/include/wireforge/version.hpp +22 -0
- wireforge/_data/runtime/requirements.yaml +438 -0
- wireforge/_data/schema/deviations.schema.json +47 -0
- wireforge/_data/schema/fragment.schema.json +79 -0
- wireforge/_data/schema/llr_ids.schema.json +25 -0
- wireforge/_data/schema/project.schema.json +1240 -0
- wireforge/_data/schema/runtime_requirements.schema.json +34 -0
- wireforge/_data/ui/assets/index-6Pomu6U4.js +44 -0
- wireforge/_data/ui/assets/index-GVdDyUAG.css +1 -0
- wireforge/_data/ui/index.html +13 -0
- wireforge/bundle.py +177 -0
- wireforge/ci_check.py +155 -0
- wireforge/cli.py +617 -0
- wireforge/codec.py +897 -0
- wireforge/compat.py +536 -0
- wireforge/coverage_points.py +64 -0
- wireforge/cpp.py +273 -0
- wireforge/cpp_codec.py +440 -0
- wireforge/cpp_interface.py +874 -0
- wireforge/cpp_tests.py +1993 -0
- wireforge/differential.py +586 -0
- wireforge/docs_markdown.py +72 -0
- wireforge/expr.py +598 -0
- wireforge/findings.py +187 -0
- wireforge/fmt.py +351 -0
- wireforge/generate.py +644 -0
- wireforge/golden.py +253 -0
- wireforge/hlr_import.py +112 -0
- wireforge/impact.py +249 -0
- wireforge/importers.py +402 -0
- wireforge/issues.py +27 -0
- wireforge/layout.py +681 -0
- wireforge/lifecycle.py +1266 -0
- wireforge/lifecycle_results.py +205 -0
- wireforge/lifecycle_rules.py +78 -0
- wireforge/lifecycle_runtime.py +375 -0
- wireforge/llr.py +693 -0
- wireforge/llr_ids.py +104 -0
- wireforge/loader.py +422 -0
- wireforge/mcp_server.py +357 -0
- wireforge/model.py +322 -0
- wireforge/plain.py +15 -0
- wireforge/py.typed +0 -0
- wireforge/reqif.py +289 -0
- wireforge/resources.py +43 -0
- wireforge/results.py +377 -0
- wireforge/runtime_reqs.py +147 -0
- wireforge/schema.py +151 -0
- wireforge/server/__init__.py +1 -0
- wireforge/server/app.py +619 -0
- wireforge/server/oidc.py +99 -0
- wireforge/server/storage.py +146 -0
- wireforge/service.py +1354 -0
- wireforge/templates/command/project.yaml +38 -0
- wireforge/templates/raw/project.yaml +28 -0
- wireforge/templates/telemetry/project.yaml +51 -0
- wireforge/test_cases.py +475 -0
- wireforge/test_project.py +478 -0
- wireforge/trace.py +442 -0
- wireforge/validate.py +1241 -0
- wireforge/vcs.py +44 -0
- wireforge/vectors.py +222 -0
- wireforge/versioning.py +137 -0
- wireforge/wireshark.py +792 -0
- wireforge/wireshark_runtime.lua +725 -0
- wireforge-0.1.0.dist-info/METADATA +91 -0
- wireforge-0.1.0.dist-info/RECORD +96 -0
- wireforge-0.1.0.dist-info/WHEEL +5 -0
- wireforge-0.1.0.dist-info/entry_points.txt +2 -0
- wireforge-0.1.0.dist-info/licenses/LICENSE +98 -0
- wireforge-0.1.0.dist-info/licenses/runtime/LICENSE +21 -0
- wireforge-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file span.hpp
|
|
3
|
+
* @brief Non-owning view of contiguous memory.
|
|
4
|
+
*/
|
|
5
|
+
#ifndef WIREFORGE_SPAN_HPP
|
|
6
|
+
#define WIREFORGE_SPAN_HPP
|
|
7
|
+
|
|
8
|
+
#include <array>
|
|
9
|
+
#include <cstddef>
|
|
10
|
+
#include <iterator>
|
|
11
|
+
#include <type_traits>
|
|
12
|
+
|
|
13
|
+
namespace wireforge {
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @brief Non-owning view of a contiguous sequence, similar to C++20 `std::span` with a dynamic
|
|
17
|
+
* extent.
|
|
18
|
+
*
|
|
19
|
+
* Element access is unchecked; check size() first. All constructors are explicit.
|
|
20
|
+
* @tparam T Element type; use `const T` for a read-only view.
|
|
21
|
+
*/
|
|
22
|
+
template <typename T> class Span {
|
|
23
|
+
public:
|
|
24
|
+
using element_type = T; ///< Element type, including const.
|
|
25
|
+
using value_type = std::remove_cv_t<T>; ///< Element type without cv-qualifiers.
|
|
26
|
+
using size_type = std::size_t; ///< Type of sizes and indices.
|
|
27
|
+
using pointer = T*; ///< Pointer to an element.
|
|
28
|
+
using reference = T&; ///< Reference to an element.
|
|
29
|
+
using iterator = T*; ///< Random-access iterator.
|
|
30
|
+
|
|
31
|
+
/// @brief Creates an empty view.
|
|
32
|
+
constexpr Span() noexcept = default;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @brief Creates a view of @p size elements starting at @p data.
|
|
36
|
+
* @param data First element (may be null when @p size is 0).
|
|
37
|
+
* @param size Number of elements.
|
|
38
|
+
*/
|
|
39
|
+
constexpr Span(T* data, std::size_t size) noexcept : data_(data), size_(size) {}
|
|
40
|
+
|
|
41
|
+
/// @brief Creates a view of all elements of @p array.
|
|
42
|
+
template <std::size_t N>
|
|
43
|
+
explicit constexpr Span(std::array<value_type, N>& array) noexcept
|
|
44
|
+
: data_(array.data()), size_(N) {}
|
|
45
|
+
|
|
46
|
+
/// @brief Creates a read-only view of all elements of @p array.
|
|
47
|
+
template <std::size_t N, typename U = T, typename = std::enable_if_t<std::is_const_v<U>>>
|
|
48
|
+
explicit constexpr Span(const std::array<value_type, N>& array) noexcept
|
|
49
|
+
: data_(array.data()), size_(N) {}
|
|
50
|
+
|
|
51
|
+
/// @brief Creates a read-only view from a mutable view of the same elements.
|
|
52
|
+
template <typename U,
|
|
53
|
+
typename = std::enable_if_t<std::is_same_v<const U, T> && !std::is_same_v<U, T>>>
|
|
54
|
+
explicit constexpr Span(Span<U> other) noexcept : data_(other.data()), size_(other.size()) {}
|
|
55
|
+
|
|
56
|
+
/// @brief Pointer to the first element.
|
|
57
|
+
[[nodiscard]] constexpr T* data() const noexcept { return data_; }
|
|
58
|
+
/// @brief Number of elements.
|
|
59
|
+
[[nodiscard]] constexpr std::size_t size() const noexcept { return size_; }
|
|
60
|
+
/// @brief true when the view has no elements.
|
|
61
|
+
[[nodiscard]] constexpr bool empty() const noexcept { return size_ == 0U; }
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @brief Element access without bounds check.
|
|
65
|
+
* @param index Position, must be less than size().
|
|
66
|
+
*/
|
|
67
|
+
[[nodiscard]] constexpr T& operator[](std::size_t index) const noexcept {
|
|
68
|
+
return *std::next(data_, static_cast<std::ptrdiff_t>(index));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/// @brief Iterator to the first element.
|
|
72
|
+
[[nodiscard]] constexpr iterator begin() const noexcept { return data_; }
|
|
73
|
+
/// @brief Iterator past the last element.
|
|
74
|
+
[[nodiscard]] constexpr iterator end() const noexcept {
|
|
75
|
+
return std::next(data_, static_cast<std::ptrdiff_t>(size_));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* @brief View of the elements [offset, offset + count), clamped to this view.
|
|
80
|
+
* @param offset First element of the result; values past the end give an empty view.
|
|
81
|
+
* @param count Maximum number of elements.
|
|
82
|
+
*/
|
|
83
|
+
[[nodiscard]] constexpr Span subspan(std::size_t offset, std::size_t count) const noexcept {
|
|
84
|
+
const std::size_t start = offset < size_ ? offset : size_;
|
|
85
|
+
const std::size_t available = size_ - start;
|
|
86
|
+
return Span(std::next(data_, static_cast<std::ptrdiff_t>(start)),
|
|
87
|
+
count < available ? count : available);
|
|
88
|
+
}
|
|
89
|
+
/// @brief View of the elements from @p offset to the end, clamped to this view.
|
|
90
|
+
[[nodiscard]] constexpr Span subspan(std::size_t offset) const noexcept {
|
|
91
|
+
return subspan(offset, size_);
|
|
92
|
+
}
|
|
93
|
+
/// @brief View of the first @p count elements, clamped to this view.
|
|
94
|
+
[[nodiscard]] constexpr Span first(std::size_t count) const noexcept {
|
|
95
|
+
return subspan(0U, count);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
private:
|
|
99
|
+
T* data_ = nullptr;
|
|
100
|
+
std::size_t size_ = 0U;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
/// @brief Creates a mutable view of all elements of @p array.
|
|
104
|
+
template <typename T, std::size_t N> constexpr Span<T> make_span(std::array<T, N>& array) noexcept {
|
|
105
|
+
return Span<T>(array);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/// @brief Creates a read-only view of all elements of @p array.
|
|
109
|
+
template <typename T, std::size_t N>
|
|
110
|
+
constexpr Span<const T> make_span(const std::array<T, N>& array) noexcept {
|
|
111
|
+
return Span<const T>(array);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
} // namespace wireforge
|
|
115
|
+
|
|
116
|
+
#endif // WIREFORGE_SPAN_HPP
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file static_vector.hpp
|
|
3
|
+
* @brief Fixed-capacity containers: StaticVector and FixedString.
|
|
4
|
+
*/
|
|
5
|
+
#ifndef WIREFORGE_STATIC_VECTOR_HPP
|
|
6
|
+
#define WIREFORGE_STATIC_VECTOR_HPP
|
|
7
|
+
|
|
8
|
+
#include "wireforge/span.hpp"
|
|
9
|
+
#include "wireforge/status.hpp"
|
|
10
|
+
|
|
11
|
+
#include <array>
|
|
12
|
+
#include <cstddef>
|
|
13
|
+
#include <initializer_list>
|
|
14
|
+
#include <iterator>
|
|
15
|
+
#include <string_view>
|
|
16
|
+
|
|
17
|
+
namespace wireforge {
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @brief Vector with a fixed capacity and in-place storage; never allocates.
|
|
21
|
+
*
|
|
22
|
+
* Holds an element count plus a `std::array<T, N>`. An optional field is a StaticVector<T, 1>, a
|
|
23
|
+
* bounded array a StaticVector<T, N>. Elements beyond size() keep their previous values. Element
|
|
24
|
+
* access is unchecked.
|
|
25
|
+
* @tparam T Element type, must be default-constructible.
|
|
26
|
+
* @tparam N Capacity.
|
|
27
|
+
*/
|
|
28
|
+
template <typename T, std::size_t N> class StaticVector {
|
|
29
|
+
public:
|
|
30
|
+
using value_type = T; ///< Element type.
|
|
31
|
+
using iterator = T*; ///< Mutable iterator.
|
|
32
|
+
using const_iterator = const T*; ///< Read-only iterator.
|
|
33
|
+
|
|
34
|
+
/// @brief Creates an empty vector; the storage is value-initialized.
|
|
35
|
+
constexpr StaticVector() noexcept = default;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @brief Creates a vector holding @p values; values beyond the capacity are dropped.
|
|
39
|
+
*/
|
|
40
|
+
explicit constexpr StaticVector(std::initializer_list<T> values) noexcept {
|
|
41
|
+
for (const T& value : values) {
|
|
42
|
+
static_cast<void>(push_back(value)); // values beyond the capacity are dropped
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/// @brief Maximum number of elements (N).
|
|
47
|
+
[[nodiscard]] static constexpr std::size_t capacity() noexcept { return N; }
|
|
48
|
+
/// @brief Current number of elements.
|
|
49
|
+
[[nodiscard]] constexpr std::size_t size() const noexcept { return size_; }
|
|
50
|
+
/// @brief true when size() is 0.
|
|
51
|
+
[[nodiscard]] constexpr bool empty() const noexcept { return size_ == 0U; }
|
|
52
|
+
/// @brief true when size() equals capacity().
|
|
53
|
+
[[nodiscard]] constexpr bool full() const noexcept { return size_ == N; }
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @brief Sets the element count; elements added by growing are value-initialized.
|
|
57
|
+
* @param count New size.
|
|
58
|
+
* @return Status::CountExceedsMax (and no change) when @p count > N, otherwise Status::Ok.
|
|
59
|
+
*/
|
|
60
|
+
constexpr Status resize(std::size_t count) noexcept {
|
|
61
|
+
if (count > N) {
|
|
62
|
+
return Status::CountExceedsMax;
|
|
63
|
+
}
|
|
64
|
+
for (std::size_t index = size_; index < count; ++index) {
|
|
65
|
+
*slot(index) = T{};
|
|
66
|
+
}
|
|
67
|
+
size_ = count;
|
|
68
|
+
return Status::Ok;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @brief Appends a copy of @p value.
|
|
73
|
+
* @return Status::CountExceedsMax when the vector is full, otherwise Status::Ok.
|
|
74
|
+
*/
|
|
75
|
+
constexpr Status push_back(const T& value) noexcept {
|
|
76
|
+
if (size_ == N) {
|
|
77
|
+
return Status::CountExceedsMax;
|
|
78
|
+
}
|
|
79
|
+
*slot(size_) = value;
|
|
80
|
+
++size_;
|
|
81
|
+
return Status::Ok;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/// @brief Sets the size to 0 (the storage is not modified).
|
|
85
|
+
constexpr void clear() noexcept { size_ = 0U; }
|
|
86
|
+
|
|
87
|
+
/// @brief Element access without bounds check; @p index must be less than capacity().
|
|
88
|
+
[[nodiscard]] constexpr T& operator[](std::size_t index) noexcept { return *slot(index); }
|
|
89
|
+
/// @brief Read-only element access without bounds check.
|
|
90
|
+
[[nodiscard]] constexpr const T& operator[](std::size_t index) const noexcept {
|
|
91
|
+
return *slot(index);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/// @brief Pointer to the storage.
|
|
95
|
+
[[nodiscard]] constexpr T* data() noexcept { return storage_.data(); }
|
|
96
|
+
/// @brief Read-only pointer to the storage.
|
|
97
|
+
[[nodiscard]] constexpr const T* data() const noexcept { return storage_.data(); }
|
|
98
|
+
/// @brief Iterator to the first element.
|
|
99
|
+
[[nodiscard]] constexpr iterator begin() noexcept { return data(); }
|
|
100
|
+
/// @brief Iterator past the last element.
|
|
101
|
+
[[nodiscard]] constexpr iterator end() noexcept { return slot(size_); }
|
|
102
|
+
/// @brief Read-only iterator to the first element.
|
|
103
|
+
[[nodiscard]] constexpr const_iterator begin() const noexcept { return data(); }
|
|
104
|
+
/// @brief Read-only iterator past the last element.
|
|
105
|
+
[[nodiscard]] constexpr const_iterator end() const noexcept { return slot(size_); }
|
|
106
|
+
|
|
107
|
+
/// @brief View of the first size() elements.
|
|
108
|
+
[[nodiscard]] constexpr Span<T> span() noexcept { return Span<T>(data(), size_); }
|
|
109
|
+
/// @brief Read-only view of the first size() elements.
|
|
110
|
+
[[nodiscard]] constexpr Span<const T> span() const noexcept {
|
|
111
|
+
return Span<const T>(data(), size_);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/// @brief Equal when the sizes and the first size() elements are equal.
|
|
115
|
+
[[nodiscard]] friend constexpr bool operator==(const StaticVector& lhs,
|
|
116
|
+
const StaticVector& rhs) noexcept {
|
|
117
|
+
if (lhs.size_ != rhs.size_) {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
for (std::size_t index = 0U; index < lhs.size_; ++index) {
|
|
121
|
+
if (!(lhs[index] == rhs[index])) {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
/// @brief Negation of operator==.
|
|
128
|
+
[[nodiscard]] friend constexpr bool operator!=(const StaticVector& lhs,
|
|
129
|
+
const StaticVector& rhs) noexcept {
|
|
130
|
+
return !(lhs == rhs);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
private:
|
|
134
|
+
[[nodiscard]] constexpr T* slot(std::size_t index) noexcept {
|
|
135
|
+
return std::next(storage_.data(), static_cast<std::ptrdiff_t>(index));
|
|
136
|
+
}
|
|
137
|
+
[[nodiscard]] constexpr const T* slot(std::size_t index) const noexcept {
|
|
138
|
+
return std::next(storage_.data(), static_cast<std::ptrdiff_t>(index));
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
std::array<T, N> storage_{};
|
|
142
|
+
std::size_t size_ = 0U;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* @brief Bounded character string with in-place storage; never allocates.
|
|
147
|
+
*
|
|
148
|
+
* Holds up to N characters plus a terminating zero, so c_str() is always valid. Only size()
|
|
149
|
+
* characters are transmitted.
|
|
150
|
+
* @tparam N Maximum number of characters.
|
|
151
|
+
*/
|
|
152
|
+
template <std::size_t N> class FixedString {
|
|
153
|
+
public:
|
|
154
|
+
/// @brief Creates an empty string.
|
|
155
|
+
constexpr FixedString() noexcept = default;
|
|
156
|
+
|
|
157
|
+
/// @brief Creates a string holding @p text, truncated to N characters.
|
|
158
|
+
explicit constexpr FixedString(std::string_view text) noexcept {
|
|
159
|
+
static_cast<void>(assign(text.substr(0U, text.size() < N ? text.size() : N)));
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/// @brief Maximum number of characters (N).
|
|
163
|
+
[[nodiscard]] static constexpr std::size_t capacity() noexcept { return N; }
|
|
164
|
+
/// @brief Current number of characters.
|
|
165
|
+
[[nodiscard]] constexpr std::size_t size() const noexcept { return size_; }
|
|
166
|
+
/// @brief true when size() is 0.
|
|
167
|
+
[[nodiscard]] constexpr bool empty() const noexcept { return size_ == 0U; }
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* @brief Replaces the content with @p text.
|
|
171
|
+
* @return Status::CountExceedsMax (and no change) when @p text is longer than N.
|
|
172
|
+
*/
|
|
173
|
+
constexpr Status assign(std::string_view text) noexcept {
|
|
174
|
+
if (text.size() > N) {
|
|
175
|
+
return Status::CountExceedsMax;
|
|
176
|
+
}
|
|
177
|
+
for (std::size_t index = 0U; index < text.size(); ++index) {
|
|
178
|
+
*slot(index) = text[index];
|
|
179
|
+
}
|
|
180
|
+
size_ = text.size();
|
|
181
|
+
*slot(size_) = '\0';
|
|
182
|
+
return Status::Ok;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* @brief Sets the length; characters added by growing are zero.
|
|
187
|
+
* @return Status::CountExceedsMax (and no change) when @p count > N.
|
|
188
|
+
*/
|
|
189
|
+
constexpr Status resize(std::size_t count) noexcept {
|
|
190
|
+
if (count > N) {
|
|
191
|
+
return Status::CountExceedsMax;
|
|
192
|
+
}
|
|
193
|
+
for (std::size_t index = size_; index <= count; ++index) {
|
|
194
|
+
*slot(index) = '\0';
|
|
195
|
+
}
|
|
196
|
+
size_ = count;
|
|
197
|
+
*slot(size_) = '\0';
|
|
198
|
+
return Status::Ok;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/// @brief Makes the string empty.
|
|
202
|
+
constexpr void clear() noexcept {
|
|
203
|
+
size_ = 0U;
|
|
204
|
+
*slot(0U) = '\0';
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/// @brief Character access without bounds check; @p index must be at most capacity().
|
|
208
|
+
[[nodiscard]] constexpr char& operator[](std::size_t index) noexcept { return *slot(index); }
|
|
209
|
+
/// @brief Read-only character access without bounds check.
|
|
210
|
+
[[nodiscard]] constexpr const char& operator[](std::size_t index) const noexcept {
|
|
211
|
+
return *slot(index);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/// @brief Pointer to the characters.
|
|
215
|
+
[[nodiscard]] constexpr char* data() noexcept { return chars_.data(); }
|
|
216
|
+
/// @brief Read-only pointer to the characters.
|
|
217
|
+
[[nodiscard]] constexpr const char* data() const noexcept { return chars_.data(); }
|
|
218
|
+
/// @brief Zero-terminated content.
|
|
219
|
+
[[nodiscard]] constexpr const char* c_str() const noexcept { return chars_.data(); }
|
|
220
|
+
/// @brief Content as a string view of size() characters.
|
|
221
|
+
[[nodiscard]] constexpr std::string_view view() const noexcept {
|
|
222
|
+
return std::string_view(chars_.data(), size_);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/// @brief Equal when the contents are equal.
|
|
226
|
+
[[nodiscard]] friend constexpr bool operator==(const FixedString& lhs,
|
|
227
|
+
const FixedString& rhs) noexcept {
|
|
228
|
+
return lhs.view() == rhs.view();
|
|
229
|
+
}
|
|
230
|
+
/// @brief Negation of operator==.
|
|
231
|
+
[[nodiscard]] friend constexpr bool operator!=(const FixedString& lhs,
|
|
232
|
+
const FixedString& rhs) noexcept {
|
|
233
|
+
return !(lhs == rhs);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
private:
|
|
237
|
+
[[nodiscard]] constexpr char* slot(std::size_t index) noexcept {
|
|
238
|
+
return std::next(chars_.data(), static_cast<std::ptrdiff_t>(index));
|
|
239
|
+
}
|
|
240
|
+
[[nodiscard]] constexpr const char* slot(std::size_t index) const noexcept {
|
|
241
|
+
return std::next(chars_.data(), static_cast<std::ptrdiff_t>(index));
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
std::array<char, N + 1U> chars_{};
|
|
245
|
+
std::size_t size_ = 0U;
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* @brief Returns an array whose elements are all @p value.
|
|
250
|
+
* @tparam T Element type.
|
|
251
|
+
* @tparam N Number of elements.
|
|
252
|
+
*/
|
|
253
|
+
template <typename T, std::size_t N>
|
|
254
|
+
[[nodiscard]] constexpr std::array<T, N> filled(T value) noexcept {
|
|
255
|
+
std::array<T, N> result{};
|
|
256
|
+
for (std::size_t index = 0U; index < N; ++index) {
|
|
257
|
+
*std::next(result.data(), static_cast<std::ptrdiff_t>(index)) = value;
|
|
258
|
+
}
|
|
259
|
+
return result;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
} // namespace wireforge
|
|
263
|
+
|
|
264
|
+
#endif // WIREFORGE_STATIC_VECTOR_HPP
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file status.hpp
|
|
3
|
+
* @brief Status codes returned by every WireForge runtime and generated codec function.
|
|
4
|
+
*/
|
|
5
|
+
#ifndef WIREFORGE_STATUS_HPP
|
|
6
|
+
#define WIREFORGE_STATUS_HPP
|
|
7
|
+
|
|
8
|
+
#include <array>
|
|
9
|
+
#include <cstddef>
|
|
10
|
+
#include <cstdint>
|
|
11
|
+
#include <iterator>
|
|
12
|
+
|
|
13
|
+
namespace wireforge {
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @brief Result of a runtime or codec operation.
|
|
17
|
+
*
|
|
18
|
+
* The runtime never throws exceptions; every fallible function returns a Status that the caller
|
|
19
|
+
* must inspect.
|
|
20
|
+
*/
|
|
21
|
+
enum class Status : std::uint8_t {
|
|
22
|
+
Ok, ///< The operation succeeded.
|
|
23
|
+
BufferTooSmall, ///< The output buffer cannot hold the encoded data.
|
|
24
|
+
Truncated, ///< The input ended before the data was complete.
|
|
25
|
+
OutOfRange, ///< A value violates its min/max, enum or bit-width range.
|
|
26
|
+
CountExceedsMax, ///< An element count is above the capacity (or below the minimum).
|
|
27
|
+
ConstMismatch, ///< A constant field differs from its declared value.
|
|
28
|
+
ChecksumMismatch, ///< A received checksum does not match the recomputed one.
|
|
29
|
+
UnknownMessageId, ///< A message id is not known on this interface.
|
|
30
|
+
InvalidLength, ///< A length field is inconsistent with the frame or buffer.
|
|
31
|
+
TrailingBytes, ///< The payload was not fully consumed.
|
|
32
|
+
InvalidState, ///< The API was misused (invalid argument or call sequence).
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @brief Tests a status for success.
|
|
37
|
+
* @param status Status to test.
|
|
38
|
+
* @return true when @p status is Status::Ok.
|
|
39
|
+
*/
|
|
40
|
+
[[nodiscard]] constexpr bool is_ok(Status status) noexcept {
|
|
41
|
+
return status == Status::Ok;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @brief Returns the name of a status code.
|
|
46
|
+
* @param status Status to name.
|
|
47
|
+
* @return A static, zero-terminated string such as "Truncated"; "Unknown" for values outside the
|
|
48
|
+
* enumeration.
|
|
49
|
+
*/
|
|
50
|
+
[[nodiscard]] constexpr const char* to_string(Status status) noexcept {
|
|
51
|
+
// Indexed by the enumerator value. A lookup table instead of a switch: a switch over
|
|
52
|
+
// every enumerator needs a default label that -Wcovered-switch-default rejects.
|
|
53
|
+
constexpr std::array<const char*, 11U> kNames{
|
|
54
|
+
"Ok",
|
|
55
|
+
"BufferTooSmall",
|
|
56
|
+
"Truncated",
|
|
57
|
+
"OutOfRange",
|
|
58
|
+
"CountExceedsMax",
|
|
59
|
+
"ConstMismatch",
|
|
60
|
+
"ChecksumMismatch",
|
|
61
|
+
"UnknownMessageId",
|
|
62
|
+
"InvalidLength",
|
|
63
|
+
"TrailingBytes",
|
|
64
|
+
"InvalidState",
|
|
65
|
+
};
|
|
66
|
+
const auto index = static_cast<std::size_t>(status);
|
|
67
|
+
if (index < kNames.size()) {
|
|
68
|
+
return *std::next(kNames.begin(), static_cast<std::ptrdiff_t>(index));
|
|
69
|
+
}
|
|
70
|
+
return "Unknown";
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
} // namespace wireforge
|
|
74
|
+
|
|
75
|
+
#endif // WIREFORGE_STATUS_HPP
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file transport.hpp
|
|
3
|
+
* @brief Byte transport requirements, a polymorphic transport base and an in-memory loopback.
|
|
4
|
+
*
|
|
5
|
+
* A transport is any type with two non-blocking member functions:
|
|
6
|
+
* @code
|
|
7
|
+
* std::size_t send(wireforge::Span<const std::uint8_t> bytes) noexcept; // bytes accepted
|
|
8
|
+
* std::size_t receive(wireforge::Span<std::uint8_t> buffer) noexcept; // bytes read, 0 = none
|
|
9
|
+
* @endcode
|
|
10
|
+
* An existing driver interface is connected by a thin adapter class with these two functions,
|
|
11
|
+
* either as a plain type (no virtual calls) or derived from ITransport.
|
|
12
|
+
*/
|
|
13
|
+
#ifndef WIREFORGE_TRANSPORT_HPP
|
|
14
|
+
#define WIREFORGE_TRANSPORT_HPP
|
|
15
|
+
|
|
16
|
+
#include "wireforge/ring_buffer.hpp"
|
|
17
|
+
#include "wireforge/span.hpp"
|
|
18
|
+
|
|
19
|
+
#include <cstddef>
|
|
20
|
+
#include <cstdint>
|
|
21
|
+
#include <type_traits>
|
|
22
|
+
#include <utility>
|
|
23
|
+
|
|
24
|
+
namespace wireforge {
|
|
25
|
+
|
|
26
|
+
/// @brief Detects whether @p T satisfies the transport requirements.
|
|
27
|
+
template <typename T, typename = void> struct is_transport : std::false_type {};
|
|
28
|
+
|
|
29
|
+
/// @cond INTERNAL
|
|
30
|
+
template <typename T>
|
|
31
|
+
struct is_transport<
|
|
32
|
+
T, std::void_t<decltype(std::declval<T&>().send(std::declval<Span<const std::uint8_t>>())),
|
|
33
|
+
decltype(std::declval<T&>().receive(std::declval<Span<std::uint8_t>>()))>>
|
|
34
|
+
: std::bool_constant<
|
|
35
|
+
std::is_same_v<decltype(std::declval<T&>().send(
|
|
36
|
+
std::declval<Span<const std::uint8_t>>())),
|
|
37
|
+
std::size_t> &&
|
|
38
|
+
std::is_same_v<decltype(std::declval<T&>().receive(std::declval<Span<std::uint8_t>>())),
|
|
39
|
+
std::size_t>> {};
|
|
40
|
+
/// @endcond
|
|
41
|
+
|
|
42
|
+
/// @brief true when @p T is a transport.
|
|
43
|
+
template <typename T> inline constexpr bool is_transport_v = is_transport<T>::value;
|
|
44
|
+
|
|
45
|
+
/// @brief Base class for transports selected at run time.
|
|
46
|
+
class ITransport {
|
|
47
|
+
public:
|
|
48
|
+
/**
|
|
49
|
+
* @brief Hands bytes to the driver without blocking.
|
|
50
|
+
* @return Number of bytes accepted; 0 when the driver cannot take any now.
|
|
51
|
+
*/
|
|
52
|
+
virtual std::size_t send(Span<const std::uint8_t> bytes) noexcept = 0;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @brief Copies received bytes into @p buffer without blocking.
|
|
56
|
+
* @return Number of bytes copied; 0 when nothing was received.
|
|
57
|
+
*/
|
|
58
|
+
virtual std::size_t receive(Span<std::uint8_t> buffer) noexcept = 0;
|
|
59
|
+
|
|
60
|
+
protected:
|
|
61
|
+
ITransport() = default; ///< Only derived classes construct.
|
|
62
|
+
ITransport(const ITransport&) = default; ///< Copy for derived classes.
|
|
63
|
+
ITransport& operator=(const ITransport&) = default; ///< Copy for derived classes.
|
|
64
|
+
ITransport(ITransport&&) = default; ///< Move for derived classes.
|
|
65
|
+
ITransport& operator=(ITransport&&) = default; ///< Move for derived classes.
|
|
66
|
+
/// @brief Not virtual: transports are never deleted through an ITransport pointer.
|
|
67
|
+
~ITransport() = default;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
static_assert(is_transport_v<ITransport>, "ITransport must satisfy the transport requirements");
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @brief Transport whose sent bytes are received again, for tests and local links.
|
|
74
|
+
*
|
|
75
|
+
* One thread may send while another receives.
|
|
76
|
+
* @tparam N Capacity in bytes; send() accepts only what fits.
|
|
77
|
+
*/
|
|
78
|
+
template <std::size_t N> class LoopbackTransport {
|
|
79
|
+
public:
|
|
80
|
+
/// @brief Stores as many bytes as fit; returns how many.
|
|
81
|
+
std::size_t send(Span<const std::uint8_t> bytes) noexcept { return ring_.write(bytes); }
|
|
82
|
+
/// @brief Returns bytes in the order they were sent.
|
|
83
|
+
std::size_t receive(Span<std::uint8_t> buffer) noexcept { return ring_.read(buffer); }
|
|
84
|
+
/// @brief Bytes that can still be sent.
|
|
85
|
+
[[nodiscard]] std::size_t free_space() const noexcept { return ring_.free_space(); }
|
|
86
|
+
/// @brief Bytes waiting to be received.
|
|
87
|
+
[[nodiscard]] std::size_t pending() const noexcept { return ring_.size(); }
|
|
88
|
+
|
|
89
|
+
private:
|
|
90
|
+
StaticSpscByteRing<N> ring_;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
} // namespace wireforge
|
|
94
|
+
|
|
95
|
+
#endif // WIREFORGE_TRANSPORT_HPP
|