1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// Hand-written Custom bodies for the generated netnode domain (namespace gen): the irregular
// lifecycle and node-value functions the netnode array-family generator doesn't cover. A netnode
// is a value type over a single nodeidx_t id, so each body reconstructs it from the raw id and
// drives its inline methods. rust::Str keys are not NUL-terminated, so they route through
// std::string before reaching a `const char *` parameter. The combinatorial array-family bodies
// live in the generated gen_netnode_bodies.cc; to_rust_string/to_rust_bytes are shared helpers in
// gen_helpers.h, pulled in transitively through gen_netnode.h.
#include <ida.hpp>
#include <pro.h>
#include <netnode.hpp>
#include <stdexcept>
#include <string>
#include "gen_netnode.h"
namespace gen {
// Lifecycle.
// Resolves name to a netnode id, creating it first when create is set; otherwise the returned id
// is BADNODE if no netnode with that name exists yet. netnode converts to nodeidx_t via its own
// operator, then widens to the FFI's uint64_t.
uint64_t netnode_by_name(rust::Str name, bool create) {
std::string s(name);
netnode node(s.c_str(), s.size(), create);
return static_cast<uint64_t>(static_cast<nodeidx_t>(node));
}
// Reports whether any data is attached to the netnode with this raw id.
bool netnode_exists(uint64_t node) {
netnode handle(static_cast<nodeidx_t>(node));
return exist(handle);
}
// Reports whether a netnode with this name has been created, without resolving its id first.
bool netnode_exists_name(rust::Str name) {
std::string s(name);
return netnode::exist(s.c_str());
}
// Deletes the netnode and all data attached to it.
void netnode_kill(uint64_t node) {
netnode handle(static_cast<nodeidx_t>(node));
handle.kill();
}
// The netnode's name; throws if the netnode is unnamed.
rust::String netnode_get_name(uint64_t node) {
netnode handle(static_cast<nodeidx_t>(node));
qstring out;
if (handle.get_name(&out) < 0)
throw std::runtime_error("netnode is unnamed");
return to_rust_string(out);
}
// Renames the netnode; returns whether the new name was free to take.
bool netnode_rename(uint64_t node, rust::Str name) {
std::string s(name);
netnode handle(static_cast<nodeidx_t>(node));
return handle.rename(s.c_str(), s.size());
}
// The lowest netnode id in the database, or BADNODE if there are none.
uint64_t netnode_first() {
netnode node;
return node.start() ? static_cast<uint64_t>(static_cast<nodeidx_t>(node))
: static_cast<uint64_t>(BADNODE);
}
// The highest netnode id in the database, or BADNODE if there are none.
uint64_t netnode_last() {
netnode node;
return node.end() ? static_cast<uint64_t>(static_cast<nodeidx_t>(node))
: static_cast<uint64_t>(BADNODE);
}
// The next netnode id after cur, or BADNODE if cur is the last one.
uint64_t netnode_next(uint64_t cur) {
netnode node(static_cast<nodeidx_t>(cur));
return node.next() ? static_cast<uint64_t>(static_cast<nodeidx_t>(node))
: static_cast<uint64_t>(BADNODE);
}
// The netnode id before cur, or BADNODE if cur is the first one.
uint64_t netnode_prev(uint64_t cur) {
netnode node(static_cast<nodeidx_t>(cur));
return node.prev() ? static_cast<uint64_t>(static_cast<nodeidx_t>(node))
: static_cast<uint64_t>(BADNODE);
}
// Copies (or, if move_, moves) count consecutive netnode ids starting at node onto target;
// returns the number of keys actually copied/moved, or BADNODE on failure.
size_t netnode_copyto(uint64_t node, uint64_t count, uint64_t target, bool move_) {
return ::netnode_copy(static_cast<nodeidx_t>(node), static_cast<nodeidx_t>(count),
static_cast<nodeidx_t>(target), move_);
}
// Node value (vtag).
// The netnode's raw value blob, copied into an owned Vec<u8>; throws if it has none. valobj
// reports the stored object's size, not the bytes it wrote, so the length is clamped to buf.
rust::Vec<uint8_t> netnode_value(uint64_t node) {
netnode handle(static_cast<nodeidx_t>(node));
uint8_t buf[MAXSPECSIZE];
ssize_t r = handle.valobj(buf, sizeof(buf));
if (r < 0)
throw std::runtime_error("netnode has no value");
size_t len = static_cast<size_t>(r) < sizeof(buf) ? static_cast<size_t>(r) : sizeof(buf);
return to_rust_bytes(buf, len);
}
// The netnode's value read back as a string; throws if it has none.
rust::String netnode_value_str(uint64_t node) {
netnode handle(static_cast<nodeidx_t>(node));
qstring out;
if (handle.valstr(&out) < 0)
throw std::runtime_error("netnode has no value");
return to_rust_string(out);
}
// Sets the netnode's value blob; returns whether the write succeeded. set() reads a length of 0
// as "measure with strlen", walking an empty slice's dangling pointer, and truncates silently
// past MAXSPECSIZE while still reporting success, so both are rejected here.
bool netnode_set_value(uint64_t node, rust::Slice<const uint8_t> value) {
if (value.empty() || value.size() > static_cast<size_t>(MAXSPECSIZE))
return false;
netnode handle(static_cast<nodeidx_t>(node));
return handle.set(value.data(), value.size());
}
// Deletes the netnode's value; returns whether there was one to delete.
bool netnode_del_value(uint64_t node) {
netnode handle(static_cast<nodeidx_t>(node));
return handle.delvalue();
}
} // namespace gen