code wiki / _hdl_build / nx_vizsla_dedup.nx

nx_vizsla_dedup.nx source

↩ module page · 460 lines · 18868 B

1// nx_vizsla_dedup.nx -- NISHI VIZSLA: DEDUP / MERGE (PRM/CRM depth). Operator 2026-06-23: real-system depth + 2// "import my linkedin my email my phone" -- imports from multiple sources create DUPLICATES of the same person. 3// A real CRM detects them and merges into one canonical contact WITHOUT losing data. This: 4// detect <prefix> <key> contacts sharing the same CURRENT value for <key> (e.g. email) = 5// duplicate candidates (>=2 distinct ids on one value). 6// merge <prefix> <survivor> <loser> <date> record a merge as an ADDITIVE "mrg:" record (rule 13: 7// NEVER deletes the loser -- history sacred, soft-merge, reversible). 8// canonical <prefix> <id> resolve the merge chain (transitive, latest-by-date) to the survivor. 9// view <prefix> <id> the UNIFIED profile: resolve to canonical, union the fields of the 10// survivor + every merged-in loser (latest-value-per-key wins). 11// Composes the fld: store (nx_vizsla_contact) for fields; mrg: records for the merge graph. Local, no cloud. 12// license_tier: ORIGINAL 13import "nx_syscalls.nx" 14import "nx_canon_cid.nx" 15import "nx_seg_store.nx" 16const K_MAGIC_1970: i64 = 1970 17const K_MAGIC_146097: i64 = 146097 18const K_MAGIC_719468: i64 = 719468 19const K_MAGIC_4096: i64 = 4096 20const K_MAGIC_1024: i64 = 1024 21const K_MAGIC_65536: i64 = 65536 22const K_MAGIC_2048: i64 = 2048 23 24func vd_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 25func vd_p(s: *u8) -> i64 { sys_write(1, s, vd_slen(s)); return 0 } 26 27func vd_eq(a: *u8, b: *u8) -> i64 { 28 var i: i64 = 0 29 var go: i64 = 1 30 while go == 1 { if a[i] != b[i] { return 0 } if a[i] == (0 as u8) { return 1 } i = i + 1 } 31 return 0 32} 33 34func vd_dup(s: *u8) -> *u8 { 35 let n: i64 = vd_slen(s) 36 let d: *u8 = sys_mmap(n + 2) 37 var i: i64 = 0 38 while i <= n { d[i] = s[i]; i = i + 1 } 39 return d 40} 41 42func vd_cpy(out: *u8, cap: i64, s: *u8) -> i64 { 43 var i: i64 = 0 44 while s[i] != (0 as u8) { if i < cap - 1 { out[i] = s[i] } i = i + 1 } 45 if i > cap - 1 { i = cap - 1 } 46 out[i] = 0 as u8 47 return i 48} 49 50func vd_cat(dst: *u8, off: i64, s: *u8) -> i64 { 51 var i: i64 = 0 52 while s[i] != (0 as u8) { dst[off + i] = s[i]; i = i + 1 } 53 return off + i 54} 55 56func vd_catn(dst: *u8, off: i64, v: i64) -> i64 { 57 var o: i64 = off 58 var m: i64 = v 59 if m < 0 { dst[o] = 45 as u8; o = o + 1; m = 0 - m } 60 let t: *u8 = sys_mmap(28) 61 var k: i64 = 0 62 if m == 0 { t[0] = 48 as u8; k = 1 } 63 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 64 var i: i64 = 0 65 while i < k { dst[o + i] = t[k - 1 - i]; i = i + 1 } 66 return o + k 67} 68 69func vd_kmemeq(b: *u8, off: i64, n: i64, s: *u8) -> i64 { 70 if vd_slen(s) != n { return 0 } 71 var i: i64 = 0 72 while i < n { if b[off + i] != s[i] { return 0 } i = i + 1 } 73 return 1 74} 75 76func vd_iskind(b: *u8, koff: i64, kl: i64, pfx: *u8) -> i64 { 77 let pl: i64 = vd_slen(pfx) 78 if kl <= pl { return 0 } 79 return vd_kmemeq(b, koff, pl, pfx) 80} 81 82func vd_field(rec: *u8, rl: i64, want: *u8, out: *u8, cap: i64) -> i64 { 83 if rl < 8 { return 0 } 84 let nf: i64 = ss_r32(rec, 4) 85 var off: i64 = 8 86 var fi: i64 = 0 87 while fi < nf { 88 if off + 8 > rl { return 0 } 89 let kl: i64 = ss_r32(rec, off) 90 let koff: i64 = off + 4 91 let vl: i64 = ss_r32(rec, koff + kl) 92 let voff: i64 = koff + kl + 4 93 if vd_kmemeq(rec, koff, kl, want) == 1 { 94 var t: i64 = 0 95 while t < vl { if t < cap - 1 { out[t] = rec[voff + t] } t = t + 1 } 96 if t > cap - 1 { t = cap - 1 } 97 out[t] = 0 as u8 98 return 1 99 } 100 off = voff + vl 101 fi = fi + 1 102 } 103 return 0 104} 105 106func vd_datedays(s: *u8) -> i64 { 107 let nums: *i64 = sys_mmap(8 * 4) as *i64 108 var nn: i64 = 0 109 var cur: i64 = 0 110 var indig: i64 = 0 111 var i: i64 = 0 112 var go: i64 = 1 113 while go == 1 { 114 let c: i64 = s[i] as i64 115 var isd: i64 = 0 116 if c >= 48 { if c <= 57 { isd = 1 } } 117 if isd == 1 { cur = cur * 10 + (c - 48); indig = 1 } 118 if isd == 0 { if indig == 1 { if nn < 4 { nums[nn] = cur; nn = nn + 1 } cur = 0; indig = 0 } } 119 if c == 0 { go = 0 } 120 i = i + 1 121 } 122 if nn != 3 { return 0 - 1 } 123 var y: i64 = nums[0] 124 let m: i64 = nums[1] 125 let d: i64 = nums[2] 126 if y < K_MAGIC_1970 { return 0 - 1 } 127 if m < 1 { return 0 - 1 } 128 if m > 12 { return 0 - 1 } 129 if d < 1 { return 0 - 1 } 130 if d > 31 { return 0 - 1 } 131 if m <= 2 { y = y - 1 } 132 let era: i64 = y / 400 133 let yoe: i64 = y - era * 400 134 var mp: i64 = m - 3 135 if m <= 2 { mp = m + 9 } 136 let doy: i64 = (153 * mp + 2) / 5 + d - 1 137 let doe: i64 = yoe * 365 + yoe / 4 - yoe / 100 + doy 138 return era * K_MAGIC_146097 + doe - K_MAGIC_719468 139} 140 141// ----- fld: collection (composes nx_vizsla_contact's data plane) ----- 142func vd_collect_fld(prefix: *u8, rct: *i64, rkey: *i64, rval: *i64, rdate: *i64) -> i64 { 143 var n: i64 = 0 144 let segs: *i64 = sys_mmap(8 * 260) as *i64 145 let nseg: i64 = ss_manifest(prefix, segs) 146 let fa: *u8 = sys_mmap(128) 147 let fb: *u8 = sys_mmap(128) 148 let fc: *u8 = sys_mmap(256) 149 let fdt: *u8 = sys_mmap(128) 150 var s: i64 = 0 151 while s < nseg { 152 let path: *u8 = sys_mmap(512) 153 var po: i64 = 0 154 po = vd_cat(path, po, prefix); po = vd_cat(path, po, segs[s] as *u8); po = vd_cat(path, po, ".docs" as *u8) 155 path[po] = 0 as u8 156 let szp: *i64 = sys_mmap(16) as *i64 157 let b: *u8 = ss_readall(path, szp) 158 let sz: i64 = szp[0] 159 var j: i64 = 0 160 while j + 9 <= sz { 161 let kind: i64 = b[j] 162 let kl: i64 = ss_r32(b, j + 1) 163 let koff: i64 = j + 5 164 let vl: i64 = ss_r32(b, koff + kl) 165 let voff: i64 = koff + kl + 4 166 var take: i64 = 0 167 if kind == 1 { take = vd_iskind(b, koff, kl, "fld:" as *u8) } 168 if take == 1 { 169 let rec: *u8 = (b as i64 + voff) as *u8 170 if vd_field(rec, vl, "contact" as *u8, fa, 128) == 1 { 171 vd_field(rec, vl, "key" as *u8, fb, 128) 172 vd_field(rec, vl, "value" as *u8, fc, 256) 173 vd_field(rec, vl, "date" as *u8, fdt, 128) 174 if n < K_MAGIC_4096 { rct[n] = vd_dup(fa) as i64; rkey[n] = vd_dup(fb) as i64; rval[n] = vd_dup(fc) as i64; rdate[n] = vd_datedays(fdt); n = n + 1 } 175 } 176 } 177 j = voff + vl 178 } 179 s = s + 1 180 } 181 return n 182} 183 184func vd_latest_fld(rct: *i64, rkey: *i64, rval: *i64, rdate: *i64, n: i64, contact: *u8, key: *u8, out: *u8, cap: i64) -> i64 { 185 var best: i64 = 0 - 1 186 var found: i64 = 0 187 var i: i64 = 0 188 while i < n { 189 if vd_eq(rct[i] as *u8, contact) == 1 { if vd_eq(rkey[i] as *u8, key) == 1 { if rdate[i] > best { 190 best = rdate[i]; vd_cpy(out, cap, rval[i] as *u8); found = 1 191 } } } 192 i = i + 1 193 } 194 return found 195} 196 197// ----- mrg: collection + chain resolution ----- 198func vd_collect_mrg(prefix: *u8, ml: *i64, ms: *i64, md: *i64) -> i64 { 199 var n: i64 = 0 200 let segs: *i64 = sys_mmap(8 * 260) as *i64 201 let nseg: i64 = ss_manifest(prefix, segs) 202 let fl: *u8 = sys_mmap(128) 203 let fs: *u8 = sys_mmap(128) 204 let fdt: *u8 = sys_mmap(128) 205 var s: i64 = 0 206 while s < nseg { 207 let path: *u8 = sys_mmap(512) 208 var po: i64 = 0 209 po = vd_cat(path, po, prefix); po = vd_cat(path, po, segs[s] as *u8); po = vd_cat(path, po, ".docs" as *u8) 210 path[po] = 0 as u8 211 let szp: *i64 = sys_mmap(16) as *i64 212 let b: *u8 = ss_readall(path, szp) 213 let sz: i64 = szp[0] 214 var j: i64 = 0 215 while j + 9 <= sz { 216 let kind: i64 = b[j] 217 let kl: i64 = ss_r32(b, j + 1) 218 let koff: i64 = j + 5 219 let vl: i64 = ss_r32(b, koff + kl) 220 let voff: i64 = koff + kl + 4 221 var take: i64 = 0 222 if kind == 1 { take = vd_iskind(b, koff, kl, "mrg:" as *u8) } 223 if take == 1 { 224 let rec: *u8 = (b as i64 + voff) as *u8 225 if vd_field(rec, vl, "loser" as *u8, fl, 128) == 1 { 226 vd_field(rec, vl, "survivor" as *u8, fs, 128) 227 vd_field(rec, vl, "date" as *u8, fdt, 128) 228 if n < K_MAGIC_4096 { ml[n] = vd_dup(fl) as i64; ms[n] = vd_dup(fs) as i64; md[n] = vd_datedays(fdt); n = n + 1 } 229 } 230 } 231 j = voff + vl 232 } 233 s = s + 1 234 } 235 return n 236} 237 238// resolve id -> canonical survivor (transitive; latest-by-date per loser; cycle-guarded) 239func vd_canonical(ml: *i64, ms: *i64, md: *i64, m: i64, id: *u8, out: *u8, cap: i64) -> i64 { 240 let cur: *u8 = sys_mmap(256) 241 vd_cpy(cur, 256, id) 242 var iter: i64 = 0 243 var go: i64 = 1 244 while go == 1 { 245 var best: i64 = 0 - 1 246 var bsurv: i64 = 0 247 var i: i64 = 0 248 while i < m { if vd_eq(ml[i] as *u8, cur) == 1 { if md[i] > best { best = md[i]; bsurv = ms[i] } } i = i + 1 } 249 if best < 0 { go = 0 } 250 else { 251 vd_cpy(cur, 256, bsurv as *u8) 252 iter = iter + 1 253 if iter > 64 { go = 0 } 254 } 255 } 256 vd_cpy(out, cap, cur) 257 return 0 258} 259 260// ---------------- DETECT ---------------- 261func vd_cmd_detect(argc: i64, argv: *i64) -> i64 { 262 if argc < 4 { vd_p("VIZSLA-DEDUP detect needs <prefix> <key> -- fail loud\n" as *u8); return 1 } 263 let prefix: *u8 = argv[2] as *u8 264 let key: *u8 = argv[3] as *u8 265 let rct: *i64 = sys_mmap(8 * K_MAGIC_4096) as *i64 266 let rkey: *i64 = sys_mmap(8 * K_MAGIC_4096) as *i64 267 let rval: *i64 = sys_mmap(8 * K_MAGIC_4096) as *i64 268 let rdate: *i64 = sys_mmap(8 * K_MAGIC_4096) as *i64 269 let n: i64 = vd_collect_fld(prefix, rct, rkey, rval, rdate) 270 271 // distinct contacts having <key>, with their latest value 272 let dc_id: *i64 = sys_mmap(8 * K_MAGIC_1024) as *i64 273 let dc_val: *i64 = sys_mmap(8 * K_MAGIC_1024) as *i64 274 var ndc: i64 = 0 275 let lv: *u8 = sys_mmap(256) 276 var i: i64 = 0 277 while i < n { 278 if vd_eq(rkey[i] as *u8, key) == 1 { 279 var dup: i64 = 0 280 var k: i64 = 0 281 while k < ndc { if vd_eq(dc_id[k] as *u8, rct[i] as *u8) == 1 { dup = 1; k = ndc } k = k + 1 } 282 if dup == 0 { vd_latest_fld(rct, rkey, rval, rdate, n, rct[i] as *u8, key, lv, 256); if ndc < K_MAGIC_1024 { dc_id[ndc] = rct[i]; dc_val[ndc] = vd_dup(lv) as i64; ndc = ndc + 1 } } 283 } 284 i = i + 1 285 } 286 287 // group by value -> emit groups with >=2 contacts 288 let vseen: *i64 = sys_mmap(8 * K_MAGIC_1024) as *i64 289 var nvs: i64 = 0 290 let rep: *u8 = sys_mmap(K_MAGIC_65536) 291 var o: i64 = 0 292 var cands: i64 = 0 293 var a: i64 = 0 294 while a < ndc { 295 var vdup: i64 = 0 296 var k: i64 = 0 297 while k < nvs { if vd_eq(vseen[k] as *u8, dc_val[a] as *u8) == 1 { vdup = 1; k = nvs } k = k + 1 } 298 if vdup == 0 { 299 if nvs < K_MAGIC_1024 { vseen[nvs] = dc_val[a]; nvs = nvs + 1 } 300 var cnt: i64 = 0 301 var b: i64 = 0 302 while b < ndc { if vd_eq(dc_val[b] as *u8, dc_val[a] as *u8) == 1 { cnt = cnt + 1 } b = b + 1 } 303 if cnt >= 2 { 304 o = vd_cat(rep, o, "VIZSLA-DEDUP-CANDIDATE key=" as *u8); o = vd_cat(rep, o, key) 305 o = vd_cat(rep, o, " value=" as *u8); o = vd_cat(rep, o, dc_val[a] as *u8) 306 o = vd_cat(rep, o, " count=" as *u8); o = vd_catn(rep, o, cnt) 307 o = vd_cat(rep, o, " contacts=" as *u8) 308 var first: i64 = 1 309 var c2: i64 = 0 310 while c2 < ndc { 311 if vd_eq(dc_val[c2] as *u8, dc_val[a] as *u8) == 1 { if first == 0 { o = vd_cat(rep, o, "," as *u8) } o = vd_cat(rep, o, dc_id[c2] as *u8); first = 0 } 312 c2 = c2 + 1 313 } 314 o = vd_cat(rep, o, "\n" as *u8) 315 cands = cands + 1 316 } 317 } 318 a = a + 1 319 } 320 o = vd_cat(rep, o, "VIZSLA-DEDUP-DETECT key=" as *u8); o = vd_cat(rep, o, key) 321 o = vd_cat(rep, o, " candidates=" as *u8); o = vd_catn(rep, o, cands); o = vd_cat(rep, o, "\n" as *u8) 322 sys_write(1, rep, o) 323 return 0 324} 325 326// ---------------- MERGE ---------------- 327func vd_cmd_merge(argc: i64, argv: *i64) -> i64 { 328 if argc < 6 { vd_p("VIZSLA-DEDUP merge needs <prefix> <survivor> <loser> <date> -- fail loud\n" as *u8); return 1 } 329 let prefix: *u8 = argv[2] as *u8 330 let survivor: *u8 = argv[3] as *u8 331 let loser: *u8 = argv[4] as *u8 332 let date: *u8 = argv[5] as *u8 333 if vd_datedays(date) < 0 { vd_p("VIZSLA-DEDUP merge: bad date (YYYY-MM-DD) -- fail loud\n" as *u8); return 1 } 334 if vd_eq(survivor, loser) == 1 { vd_p("VIZSLA-DEDUP merge: survivor==loser refused -- fail loud\n" as *u8); return 1 } 335 336 let keys: *i64 = sys_mmap(8 * 8) as *i64 337 let vals: *i64 = sys_mmap(8 * 8) as *i64 338 keys[0] = "kind" as *u8 as i64; keys[1] = "loser" as *u8 as i64; keys[2] = "survivor" as *u8 as i64; keys[3] = "date" as *u8 as i64 339 vals[0] = "mrg" as *u8 as i64; vals[1] = loser as i64; vals[2] = survivor as i64; vals[3] = date as i64 340 341 let enc: *u8 = sys_mmap(K_MAGIC_2048) 342 let el: i64 = canon_encode(keys, vals, 4, enc) 343 let cid: *u8 = sys_mmap(96) 344 cid_of(enc, el, cid) 345 let kbuf: *u8 = sys_mmap(160) 346 var ko: i64 = 0 347 ko = vd_cat(kbuf, ko, "mrg:" as *u8); ko = vd_cat(kbuf, ko, cid); kbuf[ko] = 0 as u8 348 349 var new: i64 = 1 350 let pp: *i64 = sys_mmap(16) as *i64 351 let ll: *i64 = sys_mmap(16) as *i64 352 if ss_get_idx(prefix, kbuf, pp, ll) == 1 { new = 0 } 353 var committed: i64 = 0 354 let segid: i64 = sys_now_us() 355 if new == 1 { 356 let wr: *i64 = ss_begin() 357 if ss_add(wr, 1, kbuf, enc, el) != 0 { vd_p("VIZSLA-DEDUP merge: writer full -- fail loud\n" as *u8); return 1 } 358 if ss_commit(prefix, wr, segid) != 0 { vd_p("VIZSLA-DEDUP merge: commit FAILED -- fail loud\n" as *u8); return 1 } 359 committed = 1 360 } 361 let rep: *u8 = sys_mmap(K_MAGIC_1024) 362 var o: i64 = 0 363 o = vd_cat(rep, o, "VIZSLA-DEDUP-MERGE survivor=" as *u8); o = vd_cat(rep, o, survivor) 364 o = vd_cat(rep, o, " loser=" as *u8); o = vd_cat(rep, o, loser) 365 o = vd_cat(rep, o, " new=" as *u8); o = vd_catn(rep, o, new) 366 o = vd_cat(rep, o, " segment=" as *u8) 367 if committed == 1 { o = vd_cat(rep, o, "seg-" as *u8); o = vd_catn(rep, o, segid) } else { o = vd_cat(rep, o, "none" as *u8) } 368 o = vd_cat(rep, o, "\n" as *u8) 369 sys_write(1, rep, o) 370 return 0 371} 372 373// ---------------- CANONICAL ---------------- 374func vd_cmd_canonical(argc: i64, argv: *i64) -> i64 { 375 if argc < 4 { vd_p("VIZSLA-DEDUP canonical needs <prefix> <id> -- fail loud\n" as *u8); return 1 } 376 let prefix: *u8 = argv[2] as *u8 377 let id: *u8 = argv[3] as *u8 378 let ml: *i64 = sys_mmap(8 * K_MAGIC_4096) as *i64 379 let ms: *i64 = sys_mmap(8 * K_MAGIC_4096) as *i64 380 let md: *i64 = sys_mmap(8 * K_MAGIC_4096) as *i64 381 let m: i64 = vd_collect_mrg(prefix, ml, ms, md) 382 let c: *u8 = sys_mmap(256) 383 vd_canonical(ml, ms, md, m, id, c, 256) 384 let rep: *u8 = sys_mmap(K_MAGIC_1024) 385 var o: i64 = 0 386 o = vd_cat(rep, o, "VIZSLA-DEDUP-CANONICAL id=" as *u8); o = vd_cat(rep, o, id) 387 o = vd_cat(rep, o, " canonical=" as *u8); o = vd_cat(rep, o, c); o = vd_cat(rep, o, "\n" as *u8) 388 sys_write(1, rep, o) 389 return 0 390} 391 392// ---------------- VIEW (unified merged profile) ---------------- 393func vd_cmd_view(argc: i64, argv: *i64) -> i64 { 394 if argc < 4 { vd_p("VIZSLA-DEDUP view needs <prefix> <id> -- fail loud\n" as *u8); return 1 } 395 let prefix: *u8 = argv[2] as *u8 396 let id: *u8 = argv[3] as *u8 397 let rct: *i64 = sys_mmap(8 * K_MAGIC_4096) as *i64 398 let rkey: *i64 = sys_mmap(8 * K_MAGIC_4096) as *i64 399 let rval: *i64 = sys_mmap(8 * K_MAGIC_4096) as *i64 400 let rdate: *i64 = sys_mmap(8 * K_MAGIC_4096) as *i64 401 let n: i64 = vd_collect_fld(prefix, rct, rkey, rval, rdate) 402 let ml: *i64 = sys_mmap(8 * K_MAGIC_4096) as *i64 403 let ms: *i64 = sys_mmap(8 * K_MAGIC_4096) as *i64 404 let md: *i64 = sys_mmap(8 * K_MAGIC_4096) as *i64 405 let m: i64 = vd_collect_mrg(prefix, ml, ms, md) 406 407 let c: *u8 = sys_mmap(256) 408 vd_canonical(ml, ms, md, m, id, c, 256) 409 410 // precompute canonical of every fld record's contact 411 let rcanon: *i64 = sys_mmap(8 * K_MAGIC_4096) as *i64 412 var i: i64 = 0 413 while i < n { 414 let cc: *u8 = sys_mmap(256) 415 vd_canonical(ml, ms, md, m, rct[i] as *u8, cc, 256) 416 rcanon[i] = cc as i64 417 i = i + 1 418 } 419 420 // distinct keys among in-set records (canonical(contact)==c); latest value across the merge set 421 let emitted: *i64 = sys_mmap(8 * 512) as *i64 422 var ne: i64 = 0 423 let rep: *u8 = sys_mmap(K_MAGIC_65536) 424 var o: i64 = 0 425 var fields: i64 = 0 426 let bv: *u8 = sys_mmap(256) 427 var a: i64 = 0 428 while a < n { 429 var inset: i64 = 0 430 if vd_eq(rcanon[a] as *u8, c) == 1 { inset = 1 } 431 var done: i64 = 0 432 if inset == 1 { var k: i64 = 0; while k < ne { if vd_eq(emitted[k] as *u8, rkey[a] as *u8) == 1 { done = 1; k = ne } k = k + 1 } } 433 if inset == 1 { if done == 0 { 434 var best: i64 = 0 - 1 435 var b: i64 = 0 436 while b < n { if vd_eq(rcanon[b] as *u8, c) == 1 { if vd_eq(rkey[b] as *u8, rkey[a] as *u8) == 1 { if rdate[b] > best { best = rdate[b]; vd_cpy(bv, 256, rval[b] as *u8) } } } b = b + 1 } 437 o = vd_cat(rep, o, "VIZSLA-DEDUP-VIEW contact=" as *u8); o = vd_cat(rep, o, c) 438 o = vd_cat(rep, o, " key=" as *u8); o = vd_cat(rep, o, rkey[a] as *u8) 439 o = vd_cat(rep, o, " value=" as *u8); o = vd_cat(rep, o, bv); o = vd_cat(rep, o, "\n" as *u8) 440 if ne < 512 { emitted[ne] = rkey[a]; ne = ne + 1 } 441 fields = fields + 1 442 } } 443 a = a + 1 444 } 445 o = vd_cat(rep, o, "VIZSLA-DEDUP-VIEW-SUMMARY contact=" as *u8); o = vd_cat(rep, o, c) 446 o = vd_cat(rep, o, " fields=" as *u8); o = vd_catn(rep, o, fields); o = vd_cat(rep, o, "\n" as *u8) 447 sys_write(1, rep, o) 448 return 0 449} 450 451func main(argc: i64, argv: *i64) -> i64 { 452 if argc < 2 { vd_p("VIZSLA-DEDUP usage: detect|merge|canonical|view -- fail loud\n" as *u8); return 1 } 453 let cmd: *u8 = argv[1] as *u8 454 if vd_eq(cmd, "detect" as *u8) == 1 { return vd_cmd_detect(argc, argv) } 455 if vd_eq(cmd, "merge" as *u8) == 1 { return vd_cmd_merge(argc, argv) } 456 if vd_eq(cmd, "canonical" as *u8) == 1 { return vd_cmd_canonical(argc, argv) } 457 if vd_eq(cmd, "view" as *u8) == 1 { return vd_cmd_view(argc, argv) } 458 vd_p("VIZSLA-DEDUP unknown command (detect|merge|canonical|view) -- fail loud\n" as *u8) 459 return 1 460}