-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmetadata.cpp
More file actions
154 lines (131 loc) · 5.9 KB
/
metadata.cpp
File metadata and controls
154 lines (131 loc) · 5.9 KB
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include "../include/metadata.h"
#include <iostream>
namespace feather {
void Metadata::serialize(std::ostream& os) const {
os.write(reinterpret_cast<const char*>(×tamp), 8);
os.write(reinterpret_cast<const char*>(&importance), 4);
uint8_t type_val = static_cast<uint8_t>(type);
os.write(reinterpret_cast<const char*>(&type_val), 1);
uint16_t source_len = static_cast<uint16_t>(source.size());
os.write(reinterpret_cast<const char*>(&source_len), 2);
os.write(source.data(), source_len);
uint32_t content_len = static_cast<uint32_t>(content.size());
os.write(reinterpret_cast<const char*>(&content_len), 4);
os.write(content.data(), content_len);
uint16_t tags_len = static_cast<uint16_t>(tags_json.size());
os.write(reinterpret_cast<const char*>(&tags_len), 2);
os.write(tags_json.data(), tags_len);
// Phase 3: Write 0 links (legacy slot — edges field replaces this in v5)
// We write links_count=0 so v3/v4 readers see no plain links and don't crash.
uint16_t links_count = 0;
os.write(reinterpret_cast<const char*>(&links_count), 2);
os.write(reinterpret_cast<const char*>(&recall_count), 4);
os.write(reinterpret_cast<const char*>(&last_recalled_at), 8);
// Phase 4: namespace_id, entity_id, attributes
uint16_t ns_len = static_cast<uint16_t>(namespace_id.size());
os.write(reinterpret_cast<const char*>(&ns_len), 2);
os.write(namespace_id.data(), ns_len);
uint16_t eid_len = static_cast<uint16_t>(entity_id.size());
os.write(reinterpret_cast<const char*>(&eid_len), 2);
os.write(entity_id.data(), eid_len);
uint16_t attr_count = static_cast<uint16_t>(attributes.size());
os.write(reinterpret_cast<const char*>(&attr_count), 2);
for (const auto& [key, val] : attributes) {
uint16_t key_len = static_cast<uint16_t>(key.size());
os.write(reinterpret_cast<const char*>(&key_len), 2);
os.write(key.data(), key_len);
uint32_t val_len = static_cast<uint32_t>(val.size());
os.write(reinterpret_cast<const char*>(&val_len), 4);
os.write(val.data(), val_len);
}
// Phase 5: typed, weighted edges
uint16_t edge_count = static_cast<uint16_t>(edges.size());
os.write(reinterpret_cast<const char*>(&edge_count), 2);
for (const auto& e : edges) {
os.write(reinterpret_cast<const char*>(&e.target_id), 8);
uint8_t rt_len = static_cast<uint8_t>(std::min(e.rel_type.size(), size_t(255)));
os.write(reinterpret_cast<const char*>(&rt_len), 1);
os.write(e.rel_type.data(), rt_len);
os.write(reinterpret_cast<const char*>(&e.weight), 4);
}
// Phase 6: ttl + confidence
os.write(reinterpret_cast<const char*>(&ttl), 8);
os.write(reinterpret_cast<const char*>(&confidence), 4);
}
Metadata Metadata::deserialize(std::istream& is) {
Metadata m;
is.read(reinterpret_cast<char*>(&m.timestamp), 8);
is.read(reinterpret_cast<char*>(&m.importance), 4);
uint8_t type_val;
is.read(reinterpret_cast<char*>(&type_val), 1);
m.type = static_cast<ContextType>(type_val);
uint16_t source_len;
is.read(reinterpret_cast<char*>(&source_len), 2);
m.source.resize(source_len);
is.read(&m.source[0], source_len);
uint32_t content_len;
is.read(reinterpret_cast<char*>(&content_len), 4);
m.content.resize(content_len);
is.read(&m.content[0], content_len);
uint16_t tags_len;
is.read(reinterpret_cast<char*>(&tags_len), 2);
m.tags_json.resize(tags_len);
is.read(&m.tags_json[0], tags_len);
// Phase 3: legacy links slot (v3/v4 used this; v5 writes 0 here but reads edges below)
uint16_t links_count = 0;
if (!is.read(reinterpret_cast<char*>(&links_count), 2)) return m;
if (links_count > 0) {
// Old v3/v4 plain link IDs — promote to edges with default type/weight
for (uint16_t i = 0; i < links_count; ++i) {
uint64_t target;
is.read(reinterpret_cast<char*>(&target), 8);
m.edges.push_back({target, "related_to", 1.0f});
}
}
is.read(reinterpret_cast<char*>(&m.recall_count), 4);
is.read(reinterpret_cast<char*>(&m.last_recalled_at), 8);
// Phase 4: namespace_id, entity_id, attributes
uint16_t ns_len = 0;
if (!is.read(reinterpret_cast<char*>(&ns_len), 2)) return m;
m.namespace_id.resize(ns_len);
if (ns_len > 0) is.read(&m.namespace_id[0], ns_len);
uint16_t eid_len = 0;
is.read(reinterpret_cast<char*>(&eid_len), 2);
m.entity_id.resize(eid_len);
if (eid_len > 0) is.read(&m.entity_id[0], eid_len);
uint16_t attr_count = 0;
is.read(reinterpret_cast<char*>(&attr_count), 2);
for (uint16_t i = 0; i < attr_count; ++i) {
uint16_t key_len = 0;
is.read(reinterpret_cast<char*>(&key_len), 2);
std::string key(key_len, '\0');
if (key_len > 0) is.read(&key[0], key_len);
uint32_t val_len = 0;
is.read(reinterpret_cast<char*>(&val_len), 4);
std::string val(val_len, '\0');
if (val_len > 0) is.read(&val[0], val_len);
m.attributes[key] = val;
}
// Phase 5: typed, weighted edges
uint16_t edge_count = 0;
if (!is.read(reinterpret_cast<char*>(&edge_count), 2)) return m;
for (uint16_t i = 0; i < edge_count; ++i) {
Edge e;
is.read(reinterpret_cast<char*>(&e.target_id), 8);
uint8_t rt_len = 0;
is.read(reinterpret_cast<char*>(&rt_len), 1);
e.rel_type.resize(rt_len);
if (rt_len > 0) is.read(&e.rel_type[0], rt_len);
is.read(reinterpret_cast<char*>(&e.weight), 4);
m.edges.push_back(std::move(e));
}
// Phase 6: ttl + confidence (guarded — v5 files default to 0 / 1.0)
int64_t ttl_val = 0;
if (!is.read(reinterpret_cast<char*>(&ttl_val), 8)) return m;
m.ttl = ttl_val;
float conf_val = 1.0f;
if (!is.read(reinterpret_cast<char*>(&conf_val), 4)) return m;
m.confidence = conf_val;
return m;
}
} // namespace feather