File size: 6,069 Bytes
9bd422a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/**
 * Formatters - Data formatting utilities
 * Provides functions for formatting file names, tensor shapes, file sizes,
 * data types, and tensor info for display in the UI.
 * Requirements: 2.5, 5.6, 7.3
 */

const Formatters = (function () {

  // ─── File Name Formatting ─────────────────────────────────────────────────

  /**
   * Format a file path into a human-readable display name.
   * Strips directory separators and returns only the base file name.
   * e.g. "models/jsl/model.onnx" β†’ "model.onnx"
   * @param {string} filePath
   * @returns {string}
   */
  function formatFileName(filePath) {
    if (!filePath) return 'Unknown';
    const base = filePath.replace(/\\/g, '/').split('/').pop() || filePath;
    return base;
  }

  /**
   * Format a model name for display: strip extension and replace
   * underscores/hyphens with spaces, then title-case.
   * e.g. "my_model.onnx" β†’ "My Model"
   * @param {string} filePath
   * @returns {string}
   */
  function formatModelName(filePath) {
    if (!filePath) return 'Unknown';
    const base = formatFileName(filePath);
    const noExt = base.replace(/\.onnx$/i, '');
    return noExt
      .replace(/[_-]+/g, ' ')
      .replace(/\b\w/g, c => c.toUpperCase());
  }

  // ─── Tensor Shape Formatting ──────────────────────────────────────────────

  /**
   * Format a tensor shape array into a readable string.
   * Dynamic dimensions (null, -1, 0, or string) are shown as "?".
   * e.g. [1, 3, 224, 224] β†’ "[1, 3, 224, 224]"
   * e.g. [-1, 3, 224, 224] β†’ "[?, 3, 224, 224]"
   * @param {Array<number|string|null>} shape
   * @returns {string}
   */
  function formatShape(shape) {
    if (!Array.isArray(shape) || shape.length === 0) return '[]';
    const dims = shape.map(d => {
      if (d === null || d === undefined) return '?';
      if (typeof d === 'string') return d || '?';
      if (typeof d === 'number' && (d < 0 || d === 0)) return '?';
      return String(d);
    });
    return '[' + dims.join(', ') + ']';
  }

  // ─── File Size Formatting ─────────────────────────────────────────────────

  /**
   * Format a byte count into a human-readable size string.
   * e.g. 1024 β†’ "1.00 KB", 1048576 β†’ "1.00 MB"
   * @param {number} bytes
   * @param {number} [decimals=2]
   * @returns {string}
   */
  function formatBytes(bytes, decimals = 2) {
    if (bytes == null || isNaN(bytes)) return 'Unknown';
    if (bytes === 0) return '0 B';
    const k = 1024;
    const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
    const i = Math.floor(Math.log(Math.abs(bytes)) / Math.log(k));
    const idx = Math.min(i, sizes.length - 1);
    const value = bytes / Math.pow(k, idx);
    return value.toFixed(decimals) + ' ' + sizes[idx];
  }

  // ─── Data Type Formatting ─────────────────────────────────────────────────

  /**
   * ONNX data type code β†’ human-readable name mapping.
   */
  const DATA_TYPE_MAP = {
    0: 'UNDEFINED',
    1: 'FLOAT',
    2: 'UINT8',
    3: 'INT8',
    4: 'UINT16',
    5: 'INT16',
    6: 'INT32',
    7: 'INT64',
    8: 'STRING',
    9: 'BOOL',
    10: 'FLOAT16',
    11: 'DOUBLE',
    12: 'UINT32',
    13: 'UINT64',
    14: 'COMPLEX64',
    15: 'COMPLEX128',
    16: 'BFLOAT16',
  };

  /**
   * Format an ONNX data type code or string into a readable label.
   * Accepts numeric codes (1–16) or string names.
   * @param {number|string} code
   * @returns {string}
   */
  function formatDataType(code) {
    if (code == null) return 'Unknown';
    if (typeof code === 'number') {
      return DATA_TYPE_MAP[code] || `Type(${code})`;
    }
    // Already a string β€” normalise to upper-case
    const upper = String(code).toUpperCase();
    // Check if it matches a known name
    const known = Object.values(DATA_TYPE_MAP);
    return known.includes(upper) ? upper : code;
  }

  // ─── Tensor Info Formatting ───────────────────────────────────────────────

  /**
   * Format a TensorInfo object into a concise one-line description.
   * e.g. "input_0: FLOAT [1, 3, 224, 224]"
   * @param {{ name: string, shape: Array, dataType: number|string }} tensor
   * @returns {string}
   */
  function formatTensorInfo(tensor) {
    if (!tensor) return 'Unknown';
    const name = tensor.name || 'unnamed';
    const dtype = formatDataType(tensor.dataType);
    const shape = formatShape(tensor.shape);
    return `${name}: ${dtype} ${shape}`;
  }

  /**
   * Format element count for an initializer.
   * @param {Array<number>} shape
   * @returns {number}
   */
  function calcElementCount(shape) {
    if (!Array.isArray(shape) || shape.length === 0) return 0;
    return shape.reduce((acc, d) => acc * (d > 0 ? d : 1), 1);
  }

  // ─── Number Formatting ────────────────────────────────────────────────────

  /**
   * Format a large integer with locale-aware thousands separators.
   * @param {number} n
   * @returns {string}
   */
  function formatNumber(n) {
    if (n == null || isNaN(n)) return '0';
    return n.toLocaleString();
  }

  // ─── Public API ───────────────────────────────────────────────────────────

  return {
    formatFileName,
    formatModelName,
    formatShape,
    formatBytes,
    formatDataType,
    formatTensorInfo,
    calcElementCount,
    formatNumber,
    DATA_TYPE_MAP,
  };
})();

// Export for global access in vanilla JS context
window.Formatters = Formatters;