Skip to main content

voxgig_struct/
consts.rs

1// Copyright (c) 2025-2026 Voxgig Ltd. MIT LICENSE.
2// VERSION: @voxgig/struct 0.1.0
3//
4// String, type-bitflag, mode, and regex constants — port of the top of
5// StructUtility.ts. The bitfield type is `u32` (TS uses `(1<<31)-1` which
6// overflows a signed 32-bit int).
7
8#![allow(non_upper_case_globals)] // S_* string constants mirror the TS names
9
10use crate::re::Regex;
11use std::sync::LazyLock as Lazy;
12
13// ---- mode flags (bitfield) for inject steps ---------------------------
14pub const M_KEYPRE: i64 = 1;
15pub const M_KEYPOST: i64 = 2;
16pub const M_VAL: i64 = 4;
17
18// ---- special strings --------------------------------------------------
19pub const S_BKEY: &str = "`$KEY`";
20pub const S_BANNO: &str = "`$ANNO`";
21pub const S_BEXACT: &str = "`$EXACT`";
22pub const S_BVAL: &str = "`$VAL`";
23pub const S_BOPEN: &str = "`$OPEN`";
24
25pub const S_DKEY: &str = "$KEY";
26pub const S_DTOP: &str = "$TOP";
27pub const S_DERRS: &str = "$ERRS";
28pub const S_DSPEC: &str = "$SPEC";
29
30// general
31pub const S_base: &str = "base";
32pub const S_key: &str = "key";
33pub const S_nil: &str = "nil";
34pub const S_null: &str = "null";
35pub const S_string: &str = "string";
36pub const S_object: &str = "object";
37pub const S_list: &str = "list";
38pub const S_map: &str = "map";
39
40// chars
41pub const S_BT: &str = "`";
42pub const S_CN: &str = ":";
43pub const S_DS: &str = "$";
44pub const S_DT: &str = ".";
45pub const S_FS: &str = "/";
46pub const S_KEY: &str = "KEY";
47pub const S_MT: &str = "";
48pub const S_SP: &str = " ";
49pub const S_CM: &str = ",";
50pub const S_VIZ: &str = ": ";
51
52// ---- type bit codes (u32) ---------------------------------------------
53// let t = 31; T_any = (1<<t--)-1; ... (see StructUtility.ts).
54pub const T_ANY: u32 = (1u32 << 31) - 1; // 0x7FFF_FFFF
55pub const T_NOVAL: u32 = 1 << 30; // property absent, undefined. NOT a scalar.
56pub const T_BOOLEAN: u32 = 1 << 29;
57pub const T_DECIMAL: u32 = 1 << 28;
58pub const T_INTEGER: u32 = 1 << 27;
59pub const T_NUMBER: u32 = 1 << 26;
60pub const T_STRING: u32 = 1 << 25;
61pub const T_FUNCTION: u32 = 1 << 24;
62pub const T_SYMBOL: u32 = 1 << 23;
63pub const T_NULL: u32 = 1 << 22; // the actual JSON null value.
64                                 // t -= 7  => t = 14
65pub const T_LIST: u32 = 1 << 14;
66pub const T_MAP: u32 = 1 << 13;
67pub const T_INSTANCE: u32 = 1 << 12;
68// t -= 4  => t = 7
69pub const T_SCALAR: u32 = 1 << 7;
70pub const T_NODE: u32 = 1 << 6;
71
72// TYPENAME indexed by Math.clz32(t). 26 entries (0..=25).
73pub const TYPENAME: [&str; 26] = [
74    "any",      // 0
75    "nil",      // 1   clz32(T_noval=1<<30)
76    "boolean",  // 2   clz32(1<<29)
77    "decimal",  // 3   clz32(1<<28)
78    "integer",  // 4   clz32(1<<27)
79    "number",   // 5   clz32(1<<26)
80    "string",   // 6   clz32(1<<25)
81    "function", // 7   clz32(1<<24)
82    "symbol",   // 8   clz32(1<<23)
83    "null",     // 9   clz32(1<<22)
84    "", "", "", "", "", "", "",         // 10..=16
85    "list",     // 17  clz32(1<<14)
86    "map",      // 18  clz32(1<<13)
87    "instance", // 19  clz32(1<<12)
88    "", "", "", "",       // 20..=23
89    "scalar", // 24  clz32(1<<7)
90    "node",   // 25  clz32(1<<6)
91];
92
93pub const MAXDEPTH: i64 = 32;
94
95// ---- regexes ----------------------------------------------------------
96pub static R_INTEGER_KEY: Lazy<Regex> = Lazy::new(|| Regex::new(r"^[-0-9]+$").unwrap());
97pub static R_ESCAPE_REGEXP: Lazy<Regex> = Lazy::new(|| Regex::new(r"[.*+?^${}()|\[\]\\]").unwrap());
98pub static R_QUOTES: Lazy<Regex> = Lazy::new(|| Regex::new(r#"""#).unwrap());
99pub static R_DOT: Lazy<Regex> = Lazy::new(|| Regex::new(r"\.").unwrap());
100pub static R_CLONE_REF: Lazy<Regex> = Lazy::new(|| Regex::new(r"^`\$REF:([0-9]+)`$").unwrap());
101pub static R_META_PATH: Lazy<Regex> = Lazy::new(|| Regex::new(r"^([^$]+)\$([=~])(.+)$").unwrap());
102pub static R_TRANSFORM_NAME: Lazy<Regex> = Lazy::new(|| Regex::new(r"`\$([A-Z]+)`").unwrap());
103pub static R_INJECTION_FULL: Lazy<Regex> =
104    Lazy::new(|| Regex::new(r"^`(\$[A-Z]+|[^`]*)[0-9]*`$").unwrap());
105pub static R_INJECTION_PARTIAL: Lazy<Regex> = Lazy::new(|| Regex::new(r"`([^`]+)`").unwrap());
106
107pub fn mode_name(mode: i64) -> &'static str {
108    match mode {
109        M_VAL => "val",
110        M_KEYPRE => "key:pre",
111        M_KEYPOST => "key:post",
112        _ => "",
113    }
114}
115
116pub fn placement_name(mode: i64) -> &'static str {
117    match mode {
118        M_VAL => "value",
119        M_KEYPRE | M_KEYPOST => "key",
120        _ => "",
121    }
122}