Pixie
Loading...
Searching...
No Matches
monotone.h
Go to the documentation of this file.
1#pragma once
2
7
8#include <pixie/detail/serialization.h>
10#include <pixie/memory_usage.h>
11#include <pixie/serialization.h>
12
13#include <array>
14#include <concepts>
15#include <cstddef>
16#include <cstdint>
17#include <span>
18#include <stdexcept>
19#include <utility>
20
21namespace pixie {
22
33template <class Vector>
34 requires requires { typename Vector::value_type; } &&
36 std::derived_from<
37 Vector,
40 : public MonotoneIntegerVectorBase<MonotoneIntegerVector<Vector>,
41 typename Vector::value_type>,
42 public SerializationBase<MonotoneIntegerVector<Vector>> {
43 public:
45 using value_type = typename Vector::value_type;
46
48 using size_type = std::size_t;
49
54 explicit MonotoneIntegerVector(Vector vector) : vector_(std::move(vector)) {
55 validate_monotone();
56 }
57
59 size_type size_impl() const { return vector_.size(); }
60
63 return vector_[position];
64 }
65
67 void copy_to_impl(size_type begin, std::span<value_type> output) const {
68 vector_.copy_to(begin, output);
69 }
70
73 requires requires(const Vector& vector) {
74 { vector.memory_usage_bytes() } -> std::convertible_to<size_type>;
75 }
76 {
77 return sizeof(*this) + nested_owned_memory_bytes(vector_);
78 }
79
82 return partition_point_index([x](value_type value) { return value < x; });
83 }
84
87 return partition_point_index([x](value_type value) { return value <= x; });
88 }
89
96 void serialize_impl(BinaryWriter& writer) const
98 {
99 if (writer.size_bytes() % alignof(std::uint64_t) != 0) {
100 throw std::invalid_argument(
101 "Monotone integer-vector serialization requires an aligned offset");
102 }
103 const std::size_t artifact_begin = writer.size_bytes();
104 detail::write_magic(writer, kSerializationMagic);
105 writer.write_u32(kSerializationVersion);
106 writer.write_u32(0);
107 const std::size_t size_position = writer.write_u64_placeholder();
108 vector_.serialize(writer);
109 writer.patch_u64(size_position, static_cast<std::uint64_t>(
110 writer.size_bytes() - artifact_begin));
111 }
112
122 BinaryReader& reader,
125 {
126 BinaryReader candidate = reader;
127 const std::size_t available_size = candidate.remaining();
128 detail::require_magic(candidate, kSerializationMagic);
129 if (candidate.read_u32() != kSerializationVersion ||
130 candidate.read_u32() != 0) {
131 throw std::invalid_argument(
132 "Incompatible serialized monotone integer vector");
133 }
134 const std::size_t artifact_size = detail::checked_artifact_size(
135 candidate.read_u64(), kSerializationHeaderBytes, available_size);
136 BinaryReader payload =
137 candidate.read_subreader(artifact_size - kSerializationHeaderBytes);
138 Vector vector = Vector::deserialize(payload, validation);
139 payload.require_zero_padding(0);
140
141 MonotoneIntegerVector result(std::move(vector), TrustedTag{});
142 if (validation == DeserializationValidation::kFull) {
143 result.validate_monotone();
144 }
145 reader = candidate;
146 return result;
147 }
148
149 private:
150 struct TrustedTag {};
151
152 inline static constexpr std::array<std::uint8_t, 8> kSerializationMagic = {
153 'P', 'X', 'M', 'O', 'N', 'O', 'V', '1'};
154 static constexpr std::uint32_t kSerializationVersion = 1;
155 static constexpr std::size_t kSerializationHeaderBytes = 24;
156
157 MonotoneIntegerVector(Vector vector, TrustedTag)
158 : vector_(std::move(vector)) {}
159
160 template <class GoesBefore>
161 size_type partition_point_index(GoesBefore goes_before) const {
162 size_type first = 0;
163 size_type count = vector_.size();
164 while (count != 0) {
165 const size_type step = count / 2;
166 const size_type middle = first + step;
167 if (goes_before(vector_[middle])) {
168 first = middle + 1;
169 count -= step + 1;
170 } else {
171 count = step;
172 }
173 }
174 return first;
175 }
176
177 void validate_monotone() const {
178 const size_type size = vector_.size();
179 if (size == 0) {
180 return;
181 }
182 value_type previous = vector_[0];
183 for (size_type i = 1; i < size; ++i) {
184 const value_type value = vector_[i];
185 if (value < previous) {
186 throw std::invalid_argument(
187 "Monotone integer vector contains a decreasing pair");
188 }
189 previous = value;
190 }
191 }
192
193 Vector vector_;
194};
195
196} // namespace pixie
Bounds-checked reader for canonical little-endian binary data.
Definition serialization.h:526
std::size_t remaining() const noexcept
Return the number of unconsumed bytes.
Definition serialization.h:544
BinaryReader read_subreader(std::size_t count)
Read a bounded region as an independent child reader.
Definition serialization.h:615
std::uint64_t read_u64()
Read an unsigned little-endian 64-bit integer.
Definition serialization.h:561
void require_zero_padding(std::size_t maximum)
Consume at most maximum trailing zero-padding bytes.
Definition serialization.h:633
std::uint32_t read_u32()
Read an unsigned little-endian 32-bit integer.
Definition serialization.h:558
Bounded-buffer writer for canonical little-endian binary data.
Definition serialization.h:198
CRTP facade for an immutable positional integer vector.
Definition integer_vector.h:40
size_type size() const
Definition integer_vector.h:49
CRTP refinement for duplicate-preserving monotone integer vectors.
Definition integer_vector.h:122
size_type count(value_type x) const
Definition integer_vector.h:150
value_type value_at_impl(size_type position) const
Read one valid zero-based position without bounds checking.
Definition monotone.h:62
void serialize_impl(BinaryWriter &writer) const
Write a version-1 monotone wrapper around one nested vector artifact.
Definition monotone.h:96
std::size_t size_type
Type used for element counts and positions.
Definition monotone.h:48
size_type memory_usage_bytes_impl() const
Return inline bytes plus memory owned below the nested vector.
Definition monotone.h:72
size_type upper_bound_index_impl(value_type x) const
Return the first index whose value is greater than x.
Definition monotone.h:86
typename Vector::value_type value_type
Stored unsigned integer type inherited from the nested vector.
Definition monotone.h:45
static MonotoneIntegerVector deserialize_impl(BinaryReader &reader, DeserializationValidation validation=DeserializationValidation::kQuick)
Restore one framed monotone vector and advance reader on success.
Definition monotone.h:121
void copy_to_impl(size_type begin, std::span< value_type > output) const
Copy a range already validated by the public facade.
Definition monotone.h:67
size_type lower_bound_index_impl(value_type x) const
Return the first index whose value is at least x.
Definition monotone.h:81
size_type size_impl() const
Return the number of retained values.
Definition monotone.h:59
MonotoneIntegerVector(Vector vector)
Take ownership of vector after validating nondecreasing order.
Definition monotone.h:54
CRTP facade for optional binary serialization and deserialization.
Definition serialization.h:693
Type restorable exactly from a reader and the listed context types.
Definition serialization.h:758
An unsigned integer-vector value type no wider than 64 bits.
Definition integer_vector.h:23
Type exposing the common binary serialization operation.
Definition serialization.h:750
Common interfaces for immutable positional integer vectors.
Checked byte-oriented binary serialization primitives.
DeserializationValidation
Validation strength used while restoring serialized indexes.
Definition serialization.h:28
@ kQuick
Check framing, dimensions, references, and other conditions needed for memory-safe terminating querie...
Definition serialization.h:33
@ kFull
Additionally authenticate all source-derived metadata against the supplied source contents.
Definition serialization.h:39