NGen
Loading...
Searching...
No Matches
id_predicates.hpp
1/*
2Author: Nels Frazier
3Copyright (C) 2025 Lynker
4------------------------------------------------------------------------
5Licensed under the Apache License, Version 2.0 (the "License");
6you may not use this file except in compliance with the License.
7You may obtain a copy of the License at
8
9 http://www.apache.org/licenses/LICENSE-2.0
10
11Unless required by applicable law or agreed to in writing, software
12distributed under the License is distributed on an "AS IS" BASIS,
13WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14See the License for the specific language governing permissions and
15limitations under the License.
16------------------------------------------------------------------------
17Application-defined predicates over SerializationRecord ids.
18
19The serialization library treats `SerializationRecord::id` as an
20opaque string — the producer composes it according to whatever
21identity convention the application uses, and the consumer parses
22it the same way. When a Reader is opened with an `IdPredicate`,
23the library invokes the closure on each candidate record's id
24during the index walk to decide eligibility. The library never
25parses, splits, or interprets the id itself; the closure is the
26only place where id semantics get applied.
27
28This header provides the calling-convention type alias and a
29small kit of stock helpers + combinators for common id-composition
30schemes. Applications may freely supply their own closures —
31the library calls them as opaque truth.
32
33Closure contract
34----------------
35- *Pure-ish.* Called once per record during the index walk; no
36 order-sensitive side effects beyond logging / telemetry.
37- *Cheap-ish.* On the hot index-build path; a slow predicate
38 slows the walk linearly in record count.
39- *Stable for the Reader's lifetime.* The library may memoize
40 the matched-id set once the walk completes — don't mutate
41 captures in ways that would retroactively change verdicts.
42*/
43#pragma once
44
45#include <cstddef>
46#include <functional>
47#include <string>
48#include <utility>
49#include <vector>
50
51namespace ngen{ namespace serialization{
52
56using IdPredicate = std::function<bool(const std::string& id)>;
57
58// ----- Stock helpers ------------------------------------------------
59
62inline IdPredicate exact_id(std::string target) {
63 return [t = std::move(target)](const std::string& id) {
64 return id == t;
65 };
66}
67
71inline IdPredicate primary_prefix(std::string prefix) {
72 return [p = std::move(prefix)](const std::string& id) {
73 const auto d = id.find_first_of(":.");
74 const auto head = (d == std::string::npos) ? id : id.substr(0, d);
75 return head == p;
76 };
77}
78
82inline IdPredicate contains_segment(std::string segment) {
83 return [s = std::move(segment)](const std::string& id) {
84 std::size_t start = 0;
85 while (start <= id.size()) {
86 const auto d = id.find_first_of(":.", start);
87 const auto end = (d == std::string::npos) ? id.size() : d;
88 if (id.compare(start, end - start, s) == 0) return true;
89 if (d == std::string::npos) break;
90 start = d + 1;
91 }
92 return false;
93 };
94}
95
99inline IdPredicate at_position(std::size_t n, std::string value) {
100 return [n, v = std::move(value)](const std::string& id) {
101 std::size_t start = 0;
102 std::size_t seg = 0;
103 while (start <= id.size()) {
104 const auto d = id.find_first_of(":.", start);
105 const auto end = (d == std::string::npos) ? id.size() : d;
106 if (seg == n) {
107 return id.compare(start, end - start, v) == 0;
108 }
109 if (d == std::string::npos) return false;
110 start = d + 1;
111 ++seg;
112 }
113 return false;
114 };
115}
116
119inline IdPredicate starts_with(std::string prefix) {
120 return [p = std::move(prefix)](const std::string& id) {
121 return id.size() >= p.size() &&
122 id.compare(0, p.size(), p) == 0;
123 };
124}
125
126// ----- Combinators --------------------------------------------------
127
130inline IdPredicate all_of(std::vector<IdPredicate> preds) {
131 return [p = std::move(preds)](const std::string& id) {
132 for (const auto& f : p) if (!f(id)) return false;
133 return true;
134 };
135}
136
138inline IdPredicate any_of(std::vector<IdPredicate> preds) {
139 return [p = std::move(preds)](const std::string& id) {
140 for (const auto& f : p) if (f(id)) return true;
141 return false;
142 };
143}
144
147 return [inner = std::move(p)](const std::string& id) {
148 return !inner(id);
149 };
150}
151
152}} // namespace ngen::serialization
IdPredicate starts_with(std::string prefix)
Match: the id begins with the substring prefix.
Definition id_predicates.hpp:119
IdPredicate at_position(std::size_t n, std::string value)
Match: the n'th (zero-indexed) :/.
Definition id_predicates.hpp:99
IdPredicate primary_prefix(std::string prefix)
Match: the first :/.
Definition id_predicates.hpp:71
std::function< bool(const std::string &id)> IdPredicate
Eligibility predicate over a SerializationRecord's id string.
Definition id_predicates.hpp:56
IdPredicate any_of(std::vector< IdPredicate > preds)
Any sub-predicate true.
Definition id_predicates.hpp:138
IdPredicate all_of(std::vector< IdPredicate > preds)
All sub-predicates must be true.
Definition id_predicates.hpp:130
IdPredicate not_fn(IdPredicate p)
Inverse of p.
Definition id_predicates.hpp:146
IdPredicate contains_segment(std::string segment)
Match: segment appears as any :/.
Definition id_predicates.hpp:82
IdPredicate exact_id(std::string target)
Match: the id equals target exactly.
Definition id_predicates.hpp:62
Definition DomainLayer.hpp:13