code wiki / (root) / nx_catalog_id_lookup.nx

nx_catalog_id_lookup.nx source

↩ module page · 290 lines · 15695 B

1// nx_catalog_id_lookup.nx -- string-id <-> sealed-enum bridge. 2// 3// CAPABILITY_COMPLETENESS: FULL (for shipped catalog enums; 4// new catalog entries register via the lookup-table extension 5// pattern documented inline) 6// 7// Phase 1.5 of NISHI_NSFW_LESSONS_AND_ADDITIVE_CATALOG.md: 8// bridges the JSONL catalog files (nxc2/seed/modesty_profiles.jsonl 9// + nxc2/seed/object_specs.jsonl) -- where each row's `id` field 10// is a human-readable string -- with the runtime sealed-enum 11// integers that nx_modesty_profile + nx_object_spec use. 12// 13// Without this bridge, every JSONL-loader would need to embed 14// the same string -> enum mapping. With it, ONE place owns the 15// canonical mapping; Phase 2 loaders compose against it. 16// 17// The lookup is OPEN-FORM lookup (no fancy hash table) because 18// the catalogs are small (16 modesty + 23 object specs). When 19// the catalog grows past a few hundred entries, swap to FNV-1a 20// hash table; the API stays. 21// 22// genealogy_id: substrate_additive_catalog_phase_1_5_2026_05_16 23// lineage_id: nx_catalog_id_lookup_v1 24 25import "nx_syscalls.nx" 26import "nx_runtime.nx" 27import "nx_tier.nx" 28import "nx_modesty_profile.nx" 29import "nx_object_spec.nx" 30 31// ===== string comparison helper ================================== 32// 33// Substrate doesn't have nx_str_eq imported here; build a focused 34// byte-by-byte comparator. Returns 1 if equal, 0 otherwise. 35 36func _idlk_streq(a: *u8, n: nx_int, lit: *u8) -> nx_int { 37 var i: nx_int = 0 38 while i < n { 39 let ac: nx_int = (a[i] as nx_int) & 255 40 let bc: nx_int = (lit[i] as nx_int) & 255 41 if ac != bc { return 0 } 42 if bc == 0 { return 0 } 43 i = i + 1 44 } 45 // Verify lit ends here (no trailing chars after our length). 46 if (lit[n] as nx_int) & 255 != 0 { return 0 } 47 return 1 48} 49 50// ===== modesty id -> enum ======================================== 51// 52// Returns the NX_MODESTY_* sealed-enum integer for the given 53// canonical id string. Returns -1 if unknown. 54 55func nx_modesty_id_to_enum(id_buf: *u8, id_len: nx_int) -> nx_int { 56 if id_len <= 0 { return -1 } 57 if _idlk_streq(id_buf, id_len, "modern_western_casual" as *u8) == 1 { 58 return NX_MODESTY_MODERN_WESTERN_CASUAL 59 } 60 if _idlk_streq(id_buf, id_len, "modern_western_formal" as *u8) == 1 { 61 return NX_MODESTY_MODERN_WESTERN_FORMAL 62 } 63 if _idlk_streq(id_buf, id_len, "modern_western_beach" as *u8) == 1 { 64 return NX_MODESTY_MODERN_WESTERN_BEACH 65 } 66 if _idlk_streq(id_buf, id_len, "modern_lingerie" as *u8) == 1 { 67 return NX_MODESTY_MODERN_LINGERIE 68 } 69 if _idlk_streq(id_buf, id_len, "victorian" as *u8) == 1 { 70 return NX_MODESTY_VICTORIAN 71 } 72 if _idlk_streq(id_buf, id_len, "ancient_greek_athletic_m" as *u8) == 1 { 73 return NX_MODESTY_ANCIENT_GREEK_ATHLETIC_M 74 } 75 if _idlk_streq(id_buf, id_len, "ancient_greek_athletic_f" as *u8) == 1 { 76 return NX_MODESTY_ANCIENT_GREEK_ATHLETIC_F 77 } 78 if _idlk_streq(id_buf, id_len, "ancient_roman_public" as *u8) == 1 { 79 return NX_MODESTY_ANCIENT_ROMAN_PUBLIC 80 } 81 if _idlk_streq(id_buf, id_len, "renaissance_nobility" as *u8) == 1 { 82 return NX_MODESTY_RENAISSANCE_NOBILITY 83 } 84 if _idlk_streq(id_buf, id_len, "heian_court" as *u8) == 1 { 85 return NX_MODESTY_HEIAN_COURT 86 } 87 if _idlk_streq(id_buf, id_len, "islamic_hijab" as *u8) == 1 { 88 return NX_MODESTY_ISLAMIC_HIJAB 89 } 90 if _idlk_streq(id_buf, id_len, "islamic_niqab" as *u8) == 1 { 91 return NX_MODESTY_ISLAMIC_NIQAB 92 } 93 if _idlk_streq(id_buf, id_len, "hindu_sari" as *u8) == 1 { 94 return NX_MODESTY_HINDU_SARI 95 } 96 if _idlk_streq(id_buf, id_len, "medical_professional" as *u8) == 1 { 97 return NX_MODESTY_MEDICAL_PROFESSIONAL 98 } 99 if _idlk_streq(id_buf, id_len, "artistic_nude_renaissance" as *u8) == 1 { 100 return NX_MODESTY_ARTISTIC_NUDE_RENAISSANCE 101 } 102 if _idlk_streq(id_buf, id_len, "athletic_dance" as *u8) == 1 { 103 return NX_MODESTY_ATHLETIC_DANCE 104 } 105 return -1 106} 107 108// ===== modesty enum -> id ======================================== 109// 110// Reverse lookup for human-readable phrase rendering. 111 112func nx_modesty_enum_to_id(profile_id: nx_int) -> *u8 { 113 if profile_id == NX_MODESTY_MODERN_WESTERN_CASUAL { return "modern_western_casual" as *u8 } 114 if profile_id == NX_MODESTY_MODERN_WESTERN_FORMAL { return "modern_western_formal" as *u8 } 115 if profile_id == NX_MODESTY_MODERN_WESTERN_BEACH { return "modern_western_beach" as *u8 } 116 if profile_id == NX_MODESTY_MODERN_LINGERIE { return "modern_lingerie" as *u8 } 117 if profile_id == NX_MODESTY_VICTORIAN { return "victorian" as *u8 } 118 if profile_id == NX_MODESTY_ANCIENT_GREEK_ATHLETIC_M { return "ancient_greek_athletic_m" as *u8 } 119 if profile_id == NX_MODESTY_ANCIENT_GREEK_ATHLETIC_F { return "ancient_greek_athletic_f" as *u8 } 120 if profile_id == NX_MODESTY_ANCIENT_ROMAN_PUBLIC { return "ancient_roman_public" as *u8 } 121 if profile_id == NX_MODESTY_RENAISSANCE_NOBILITY { return "renaissance_nobility" as *u8 } 122 if profile_id == NX_MODESTY_HEIAN_COURT { return "heian_court" as *u8 } 123 if profile_id == NX_MODESTY_ISLAMIC_HIJAB { return "islamic_hijab" as *u8 } 124 if profile_id == NX_MODESTY_ISLAMIC_NIQAB { return "islamic_niqab" as *u8 } 125 if profile_id == NX_MODESTY_HINDU_SARI { return "hindu_sari" as *u8 } 126 if profile_id == NX_MODESTY_MEDICAL_PROFESSIONAL { return "medical_professional" as *u8 } 127 if profile_id == NX_MODESTY_ARTISTIC_NUDE_RENAISSANCE { return "artistic_nude_renaissance" as *u8 } 128 if profile_id == NX_MODESTY_ATHLETIC_DANCE { return "athletic_dance" as *u8 } 129 return "unknown_profile" as *u8 130} 131 132// ===== object spec id -> enum ==================================== 133 134func nx_object_spec_id_to_enum(id_buf: *u8, id_len: nx_int) -> nx_int { 135 if id_len <= 0 { return -1 } 136 if _idlk_streq(id_buf, id_len, "sword_long" as *u8) == 1 { return NX_SPEC_SWORD_LONG } 137 if _idlk_streq(id_buf, id_len, "sword_short" as *u8) == 1 { return NX_SPEC_SWORD_SHORT } 138 if _idlk_streq(id_buf, id_len, "dagger" as *u8) == 1 { return NX_SPEC_DAGGER } 139 if _idlk_streq(id_buf, id_len, "spear" as *u8) == 1 { return NX_SPEC_SPEAR } 140 if _idlk_streq(id_buf, id_len, "axe_battle" as *u8) == 1 { return NX_SPEC_AXE_BATTLE } 141 if _idlk_streq(id_buf, id_len, "mace" as *u8) == 1 { return NX_SPEC_MACE } 142 if _idlk_streq(id_buf, id_len, "hammer_war" as *u8) == 1 { return NX_SPEC_HAMMER_WAR } 143 if _idlk_streq(id_buf, id_len, "bow_long" as *u8) == 1 { return NX_SPEC_BOW_LONG } 144 if _idlk_streq(id_buf, id_len, "staff_quarter" as *u8) == 1 { return NX_SPEC_STAFF_QUARTER } 145 if _idlk_streq(id_buf, id_len, "wand_magic" as *u8) == 1 { return NX_SPEC_WAND_MAGIC } 146 if _idlk_streq(id_buf, id_len, "shirt_button" as *u8) == 1 { return NX_SPEC_SHIRT_BUTTON } 147 if _idlk_streq(id_buf, id_len, "shirt_t" as *u8) == 1 { return NX_SPEC_SHIRT_T } 148 if _idlk_streq(id_buf, id_len, "pants_jeans" as *u8) == 1 { return NX_SPEC_PANTS_JEANS } 149 if _idlk_streq(id_buf, id_len, "dress_sundress" as *u8) == 1 { return NX_SPEC_DRESS_SUNDRESS } 150 if _idlk_streq(id_buf, id_len, "coat_trench" as *u8) == 1 { return NX_SPEC_COAT_TRENCH } 151 if _idlk_streq(id_buf, id_len, "hat_fedora" as *u8) == 1 { return NX_SPEC_HAT_FEDORA } 152 if _idlk_streq(id_buf, id_len, "lingerie_bra" as *u8) == 1 { return NX_SPEC_LINGERIE_BRA } 153 if _idlk_streq(id_buf, id_len, "orc_standard" as *u8) == 1 { return NX_SPEC_ORC_STANDARD } 154 if _idlk_streq(id_buf, id_len, "elf_high" as *u8) == 1 { return NX_SPEC_ELF_HIGH } 155 if _idlk_streq(id_buf, id_len, "dragon_western" as *u8) == 1 { return NX_SPEC_DRAGON_WESTERN } 156 if _idlk_streq(id_buf, id_len, "werewolf" as *u8) == 1 { return NX_SPEC_WEREWOLF } 157 if _idlk_streq(id_buf, id_len, "car_sedan" as *u8) == 1 { return NX_SPEC_CAR_SEDAN } 158 if _idlk_streq(id_buf, id_len, "motorcycle" as *u8) == 1 { return NX_SPEC_MOTORCYCLE } 159 if _idlk_streq(id_buf, id_len, "castle_medieval" as *u8) == 1 { return NX_SPEC_CASTLE_MEDIEVAL } 160 if _idlk_streq(id_buf, id_len, "bubble_wand" as *u8) == 1 { return NX_SPEC_BUBBLE_WAND } 161 if _idlk_streq(id_buf, id_len, "pen_ballpoint" as *u8) == 1 { return NX_SPEC_PEN_BALLPOINT } 162 if _idlk_streq(id_buf, id_len, "torch" as *u8) == 1 { return NX_SPEC_TORCH } 163 if _idlk_streq(id_buf, id_len, "flashlight" as *u8) == 1 { return NX_SPEC_FLASHLIGHT } 164 return -1 165} 166 167// ===== part id (used in object_specs JSONL required_parts arrays) == 168 169func nx_part_id_to_enum(name: *u8, len: nx_int) -> nx_int { 170 if len <= 0 { return -1 } 171 // Weapon parts 172 if _idlk_streq(name, len, "BLADE" as *u8) == 1 { return NX_PT_BLADE } 173 if _idlk_streq(name, len, "EDGE" as *u8) == 1 { return NX_PT_EDGE } 174 if _idlk_streq(name, len, "POINT" as *u8) == 1 { return NX_PT_POINT } 175 if _idlk_streq(name, len, "TANG" as *u8) == 1 { return NX_PT_TANG } 176 if _idlk_streq(name, len, "CROSSGUARD" as *u8) == 1 { return NX_PT_CROSSGUARD } 177 if _idlk_streq(name, len, "GRIP" as *u8) == 1 { return NX_PT_GRIP } 178 if _idlk_streq(name, len, "POMMEL" as *u8) == 1 { return NX_PT_POMMEL } 179 if _idlk_streq(name, len, "HAFT" as *u8) == 1 { return NX_PT_HAFT } 180 if _idlk_streq(name, len, "HEAD_WEAPON" as *u8) == 1 { return NX_PT_HEAD_WEAPON } 181 if _idlk_streq(name, len, "LIMB_BOW" as *u8) == 1 { return NX_PT_LIMB_BOW } 182 if _idlk_streq(name, len, "STRING_BOW" as *u8) == 1 { return NX_PT_STRING_BOW } 183 if _idlk_streq(name, len, "NOCK" as *u8) == 1 { return NX_PT_NOCK } 184 if _idlk_streq(name, len, "FLETCHING" as *u8) == 1 { return NX_PT_FLETCHING } 185 // Wand / non-weapon stick parts 186 if _idlk_streq(name, len, "HANDLE_STICK" as *u8) == 1 { return NX_PT_HANDLE_STICK } 187 if _idlk_streq(name, len, "LOOP" as *u8) == 1 { return NX_PT_LOOP } 188 if _idlk_streq(name, len, "FILM" as *u8) == 1 { return NX_PT_FILM } 189 if _idlk_streq(name, len, "NIB" as *u8) == 1 { return NX_PT_NIB } 190 if _idlk_streq(name, len, "TIP" as *u8) == 1 { return NX_PT_TIP } 191 if _idlk_streq(name, len, "FLAME" as *u8) == 1 { return NX_PT_FLAME } 192 // Clothing parts 193 if _idlk_streq(name, len, "COLLAR" as *u8) == 1 { return NX_PT_COLLAR } 194 if _idlk_streq(name, len, "NECKLINE" as *u8) == 1 { return NX_PT_NECKLINE } 195 if _idlk_streq(name, len, "SLEEVE_SHORT" as *u8) == 1 { return NX_PT_SLEEVE_SHORT } 196 if _idlk_streq(name, len, "SLEEVE_LONG" as *u8) == 1 { return NX_PT_SLEEVE_LONG } 197 if _idlk_streq(name, len, "CUFF" as *u8) == 1 { return NX_PT_CUFF } 198 if _idlk_streq(name, len, "HEM" as *u8) == 1 { return NX_PT_HEM } 199 if _idlk_streq(name, len, "WAISTBAND" as *u8) == 1 { return NX_PT_WAISTBAND } 200 if _idlk_streq(name, len, "BUTTON" as *u8) == 1 { return NX_PT_BUTTON } 201 if _idlk_streq(name, len, "ZIPPER" as *u8) == 1 { return NX_PT_ZIPPER } 202 if _idlk_streq(name, len, "POCKET" as *u8) == 1 { return NX_PT_POCKET } 203 if _idlk_streq(name, len, "LAPEL" as *u8) == 1 { return NX_PT_LAPEL } 204 if _idlk_streq(name, len, "HOOD" as *u8) == 1 { return NX_PT_HOOD } 205 if _idlk_streq(name, len, "BRA_CUP" as *u8) == 1 { return NX_PT_BRA_CUP } 206 if _idlk_streq(name, len, "BRA_STRAP" as *u8) == 1 { return NX_PT_BRA_STRAP } 207 // Creature parts 208 if _idlk_streq(name, len, "HEAD" as *u8) == 1 { return NX_PT_HEAD } 209 if _idlk_streq(name, len, "TUSK" as *u8) == 1 { return NX_PT_TUSK } 210 if _idlk_streq(name, len, "HORN" as *u8) == 1 { return NX_PT_HORN } 211 if _idlk_streq(name, len, "WING" as *u8) == 1 { return NX_PT_WING } 212 if _idlk_streq(name, len, "TAIL" as *u8) == 1 { return NX_PT_TAIL } 213 if _idlk_streq(name, len, "SCALE" as *u8) == 1 { return NX_PT_SCALE } 214 if _idlk_streq(name, len, "FUR" as *u8) == 1 { return NX_PT_FUR } 215 if _idlk_streq(name, len, "POINTED_EAR" as *u8) == 1 { return NX_PT_POINTED_EAR } 216 if _idlk_streq(name, len, "CLAW" as *u8) == 1 { return NX_PT_CLAW } 217 if _idlk_streq(name, len, "FANG" as *u8) == 1 { return NX_PT_FANG } 218 // Vehicle parts 219 if _idlk_streq(name, len, "WHEEL" as *u8) == 1 { return NX_PT_WHEEL } 220 if _idlk_streq(name, len, "WINDSHIELD" as *u8) == 1 { return NX_PT_WINDSHIELD } 221 if _idlk_streq(name, len, "HEADLIGHT" as *u8) == 1 { return NX_PT_HEADLIGHT } 222 if _idlk_streq(name, len, "LICENSE_PLATE" as *u8) == 1 { return NX_PT_LICENSE_PLATE } 223 if _idlk_streq(name, len, "MIRROR" as *u8) == 1 { return NX_PT_MIRROR } 224 if _idlk_streq(name, len, "GRILLE" as *u8) == 1 { return NX_PT_GRILLE } 225 if _idlk_streq(name, len, "HANDLEBAR" as *u8) == 1 { return NX_PT_HANDLEBAR } 226 // Architecture parts 227 if _idlk_streq(name, len, "WALL" as *u8) == 1 { return NX_PT_WALL } 228 if _idlk_streq(name, len, "WINDOW_PANE" as *u8) == 1 { return NX_PT_WINDOW_PANE } 229 if _idlk_streq(name, len, "DOOR" as *u8) == 1 { return NX_PT_DOOR } 230 if _idlk_streq(name, len, "ROOF" as *u8) == 1 { return NX_PT_ROOF } 231 if _idlk_streq(name, len, "BATTLEMENT" as *u8) == 1 { return NX_PT_BATTLEMENT } 232 if _idlk_streq(name, len, "ARROW_SLIT" as *u8) == 1 { return NX_PT_ARROW_SLIT } 233 if _idlk_streq(name, len, "TURRET" as *u8) == 1 { return NX_PT_TURRET } 234 if _idlk_streq(name, len, "CHIMNEY" as *u8) == 1 { return NX_PT_CHIMNEY } 235 return -1 236} 237 238// ===== self-test ================================================= 239 240func main() -> nx_int { 241 // ---- modesty: forward lookups ---- 242 let s1: *u8 = "modern_western_casual" as *u8 243 if nx_modesty_id_to_enum(s1, 21) != NX_MODESTY_MODERN_WESTERN_CASUAL { return 1 } 244 let s2: *u8 = "victorian" as *u8 245 if nx_modesty_id_to_enum(s2, 9) != NX_MODESTY_VICTORIAN { return 2 } 246 let s3: *u8 = "islamic_niqab" as *u8 247 if nx_modesty_id_to_enum(s3, 13) != NX_MODESTY_ISLAMIC_NIQAB { return 3 } 248 let s4: *u8 = "heian_court" as *u8 249 if nx_modesty_id_to_enum(s4, 11) != NX_MODESTY_HEIAN_COURT { return 4 } 250 let s5: *u8 = "hindu_sari" as *u8 251 if nx_modesty_id_to_enum(s5, 10) != NX_MODESTY_HINDU_SARI { return 5 } 252 253 // ---- modesty: unknown returns -1 ---- 254 let s_bad: *u8 = "not_a_real_profile" as *u8 255 if nx_modesty_id_to_enum(s_bad, 18) != -1 { return 10 } 256 257 // ---- modesty: reverse lookup ---- 258 let p_back: *u8 = nx_modesty_enum_to_id(NX_MODESTY_VICTORIAN) 259 if _idlk_streq(p_back, 9, "victorian" as *u8) != 1 { return 20 } 260 let p_unk: *u8 = nx_modesty_enum_to_id(NX_MODESTY_N_PROFILES) 261 if _idlk_streq(p_unk, 15, "unknown_profile" as *u8) != 1 { return 21 } 262 263 // ---- object spec: forward lookups ---- 264 let o1: *u8 = "sword_long" as *u8 265 if nx_object_spec_id_to_enum(o1, 10) != NX_SPEC_SWORD_LONG { return 30 } 266 let o2: *u8 = "bubble_wand" as *u8 267 if nx_object_spec_id_to_enum(o2, 11) != NX_SPEC_BUBBLE_WAND { return 31 } 268 let o3: *u8 = "dragon_western" as *u8 269 if nx_object_spec_id_to_enum(o3, 14) != NX_SPEC_DRAGON_WESTERN { return 32 } 270 let o4: *u8 = "orc_standard" as *u8 271 if nx_object_spec_id_to_enum(o4, 12) != NX_SPEC_ORC_STANDARD { return 33 } 272 273 // ---- part id: forward lookups (the JSONL row's required_parts[] entries) ---- 274 let pt1: *u8 = "BLADE" as *u8 275 if nx_part_id_to_enum(pt1, 5) != NX_PT_BLADE { return 40 } 276 let pt2: *u8 = "CROSSGUARD" as *u8 277 if nx_part_id_to_enum(pt2, 10) != NX_PT_CROSSGUARD { return 41 } 278 let pt3: *u8 = "LOOP" as *u8 279 if nx_part_id_to_enum(pt3, 4) != NX_PT_LOOP { return 42 } 280 let pt4: *u8 = "POINTED_EAR" as *u8 281 if nx_part_id_to_enum(pt4, 11) != NX_PT_POINTED_EAR { return 43 } 282 let pt5: *u8 = "BATTLEMENT" as *u8 283 if nx_part_id_to_enum(pt5, 10) != NX_PT_BATTLEMENT { return 44 } 284 285 // ---- part id: unknown ---- 286 let pt_bad: *u8 = "NOT_A_PART" as *u8 287 if nx_part_id_to_enum(pt_bad, 10) != -1 { return 50 } 288 289 return 0 290}