nspasojevic commited on
Commit
59b8d0e
·
verified ·
1 Parent(s): 0fa97f4

Web USD on the Space, dark (VIEWER_FORMAT unset = glb): UI slim-ui-6262a66a + #72's serving files

Browse files

Owner go 2026-10-15 (Web USD upload). Dist = indexing #73 (slim-ui-license 6262a66a = live b62bb449 + webusd/slim-viewer 7d9549c6). Runtime files = indexing #72 @02d329c0 (nginx: prod's rail lists kept; #59's rail names ship with Artem's deploy). Nothing reads the USD archives until VIEWER_FORMAT is usd or auto.

docker/hf-space/nginx.conf.template CHANGED
@@ -43,6 +43,13 @@ map $arg_v $slim_library_cache {
43
  "" "no-cache";
44
  default "public, max-age=31536000, immutable";
45
  }
 
 
 
 
 
 
 
46
  # <<< simready-central slim explorer (http) <<<
47
  server {
48
  listen __PORT__;
@@ -199,10 +206,28 @@ server {
199
  # category.qcode_property central:category: the Category tree (only the tree) reads the property the pipeline's
200
  # `categories` stage writes (pipeline/categories.py): the asset's Q-code, or oem:<HF owner> for a partner package,
201
  # so OEM > vendor scopes to that vendor and no asset is left Uncategorized. Search and parsing keep the Q-code.
 
 
 
 
202
  location = /config.js {
203
  default_type application/javascript;
204
  add_header Cache-Control "no-cache, must-revalidate" always;
205
- return 200 '(function(){var c="__CORPUS_NAME__";if(!c||c.indexOf("__")===0){c="usdsearch-dev";}window.__SERVER_MAPPING__={"usdsearch-dev":{"name":c+" (Hugging Face)","apiUrl":"","embedding_config":{"field_name":"siglip2-embedding.embedding","dimension":1536},"category":{"qcode_property":"central:category"},"features":{"download":__DOWNLOAD_ENABLED__,"s3UrlRemap":false,"seedDefaultScope":false,"railFilters":["profiles","simready_metadata_asset_license","category"],"railDefaults":["profiles","simready_metadata_asset_license","category"],"propertyAliases":{"wikidata_qcode":"simready_metadata_qcode"},"propertyFilterCombine":"and","submitContentUrl":"__SUBMIT_CONTENT_URL__"}}};window.__DEFAULT_SERVER__="usdsearch-dev";})();';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
206
  }
207
  # index.html must always revalidate (covers the try_files fallback too): a swap or rollback
208
  # must not leave a browser holding an index.html that names deleted chunks.
@@ -296,7 +321,7 @@ server {
296
  location /library_media/ {
297
  root /app/hf-space-pipeline/.build; # .build/library_media/: outside .build/restore/, which the index restore empties
298
  try_files $uri @slim_not_found;
299
- types { application/json json; model/gltf-binary glb; video/mp4 mp4; image/jpeg jpg; image/webp webp; }
300
  default_type application/octet-stream;
301
  gzip_types application/json model/gltf-binary; # meshopt GLBs still shrink under gzip
302
  add_header Cache-Control $slim_library_cache always;
@@ -305,6 +330,47 @@ server {
305
  add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
306
  add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
307
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
308
  # Central's per-user surface is absent in this build: hard 404s, never the SPA's index.html.
309
  location ~ ^/(auth|packs|prefs|chats|created_assets|concept_images|meshy_quota|info|process|folder_hierarchy\.json|category_hierarchy\.json|api/create-chat|api/cad2simready)(/|$) {
310
  default_type application/json;
 
43
  "" "no-cache";
44
  default "public, max-age=31536000, immutable";
45
  }
46
+ # Web USD (/library_media/<id>/usd/*.usdc, below): a client whose Accept-Encoding names br gets the precompressed
47
+ # <file>.br sibling the media builder ships; `br;q=0` refuses it (RFC 9110 12.5.3). First match wins.
48
+ map $http_accept_encoding $slim_accepts_br {
49
+ default 0;
50
+ "~*(^|,)\s*br\s*;\s*q\s*=\s*0(\.0{0,3})?\s*(,|$)" 0;
51
+ "~*(^|,)\s*br\s*(;|,|$)" 1;
52
+ }
53
  # <<< simready-central slim explorer (http) <<<
54
  server {
55
  listen __PORT__;
 
206
  # category.qcode_property central:category: the Category tree (only the tree) reads the property the pipeline's
207
  # `categories` stage writes (pipeline/categories.py): the asset's Q-code, or oem:<HF owner> for a partner package,
208
  # so OEM > vendor scopes to that vendor and no asset is left Uncategorized. Search and parsing keep the Q-code.
209
+ # viewerFormat (Web USD's runtime switch, 2026-10-14): __VIEWER_FORMAT__ is rendered by the same sed from the
210
+ # Space variable VIEWER_FORMAT — glb (the default, also for anything but glb|usd|auto), usd or auto. The Explorer
211
+ # reads it over its baked REACT_APP_VIEWER_FORMAT, so web USD goes off with a variable and a restart, no rebuild;
212
+ # pipeline/library_media.py fetches the USD archives only when it is usd or auto.
213
  location = /config.js {
214
  default_type application/javascript;
215
  add_header Cache-Control "no-cache, must-revalidate" always;
216
+ return 200 '(function(){var c="__CORPUS_NAME__";if(!c||c.indexOf("__")===0){c="usdsearch-dev";}window.__SERVER_MAPPING__={"usdsearch-dev":{"name":c+" (Hugging Face)","apiUrl":"","embedding_config":{"field_name":"siglip2-embedding.embedding","dimension":1536},"category":{"qcode_property":"central:category"},"features":{"download":__DOWNLOAD_ENABLED__,"s3UrlRemap":false,"seedDefaultScope":false,"railFilters":["profiles","simready_metadata_asset_license","category"],"railDefaults":["profiles","simready_metadata_asset_license","category"],"propertyAliases":{"wikidata_qcode":"simready_metadata_qcode"},"propertyFilterCombine":"and","submitContentUrl":"__SUBMIT_CONTENT_URL__","viewerFormat":"__VIEWER_FORMAT__"}}};window.__DEFAULT_SERVER__="usdsearch-dev";})();';
217
+ }
218
+ # The Web USD reader (SimReady Central's explorer/scripts/copy-usd-reader.js: /static/usd-reader/<revision>/, a
219
+ # module worker's few small .js files and its ~2.3 MB WebAssembly). The stock gzip_types (and the server's line
220
+ # above) name no application/wasm, so without this the .wasm goes out raw: a .gz sibling the dist ships is sent as
221
+ # is (gzip_static), else it is gzipped here. Same files and folder as the /static/ alias above; longer prefix wins.
222
+ location /static/usd-reader/ {
223
+ alias /usr/share/nginx/explorer/static/usd-reader/;
224
+ types { application/wasm wasm; application/javascript js; }
225
+ default_type application/octet-stream;
226
+ gzip_static on;
227
+ gzip on;
228
+ gzip_comp_level 6;
229
+ gzip_vary on;
230
+ gzip_types application/wasm application/javascript;
231
  }
232
  # index.html must always revalidate (covers the try_files fallback too): a swap or rollback
233
  # must not leave a browser holding an index.html that names deleted chunks.
 
321
  location /library_media/ {
322
  root /app/hf-space-pipeline/.build; # .build/library_media/: outside .build/restore/, which the index restore empties
323
  try_files $uri @slim_not_found;
324
+ types { application/json json; model/gltf-binary glb; video/mp4 mp4; image/jpeg jpg; image/webp webp; image/ktx2 ktx2; image/png png; }
325
  default_type application/octet-stream;
326
  gzip_types application/json model/gltf-binary; # meshopt GLBs still shrink under gzip
327
  add_header Cache-Control $slim_library_cache always;
 
330
  add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
331
  add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
332
  }
333
+ # Web USD (manifest entry `usd`, SimReady Central's simready-web-usd/1): <id>/usd/{asset,hd,colliders}.usdc beside
334
+ # its KTX2 textures (<id>/usd/tex/*.ktx2, served by the location above: image/ktx2, Range, never gzipped — Basis
335
+ # is compressed already). A .usdc whose client accepts br is answered with the builder's precompressed
336
+ # <file>.usdc.br (Content-Encoding: br; whole, never a Range: a byte range of an encoded body is not one of the
337
+ # file), else, or without a .br sibling, with the file itself (Range as usual). Both vary on Accept-Encoding. No
338
+ # gzip_static: the builder writes no .gz, and the dynamic gzip never takes application/octet-stream.
339
+ location ~ ^/library_media/.+\.usdc$ {
340
+ root /app/hf-space-pipeline/.build;
341
+ error_page 418 = @slim_usdc_identity;
342
+ if ($slim_accepts_br = 0) { return 418; }
343
+ try_files $uri.br @slim_usdc_identity;
344
+ types { }
345
+ default_type application/octet-stream;
346
+ gzip off;
347
+ max_ranges 0;
348
+ add_header Content-Encoding br;
349
+ add_header Vary Accept-Encoding always;
350
+ add_header Cache-Control $slim_library_cache always;
351
+ add_header X-Content-Type-Options nosniff always;
352
+ add_header Access-Control-Allow-Origin "*" always;
353
+ add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
354
+ add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
355
+ }
356
+ location @slim_usdc_identity {
357
+ root /app/hf-space-pipeline/.build;
358
+ try_files $uri @slim_not_found;
359
+ types { }
360
+ default_type application/octet-stream;
361
+ gzip off;
362
+ add_header Vary Accept-Encoding always;
363
+ add_header Cache-Control $slim_library_cache always;
364
+ add_header X-Content-Type-Options nosniff always;
365
+ add_header Access-Control-Allow-Origin "*" always;
366
+ add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
367
+ add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
368
+ }
369
+ # A .br sibling is an encoding of its file, never a URL of its own.
370
+ location ~ ^/library_media/.+\.br$ {
371
+ default_type application/json;
372
+ return 404 '{"detail":"Not Found"}';
373
+ }
374
  # Central's per-user surface is absent in this build: hard 404s, never the SPA's index.html.
375
  location ~ ^/(auth|packs|prefs|chats|created_assets|concept_images|meshy_quota|info|process|folder_hierarchy\.json|category_hierarchy\.json|api/create-chat|api/cad2simready)(/|$) {
376
  default_type application/json;
docker/hf-space/supervisord-gpu.conf CHANGED
@@ -171,7 +171,7 @@ stderr_logfile=/dev/stderr
171
  stderr_logfile_maxbytes=0
172
 
173
  [program:nginx]
174
- command=/bin/sh -c "until curl -sf http://localhost:8000/health >/dev/null 2>&1 && curl -sf http://localhost:8010/docs >/dev/null 2>&1; do sleep 2; done; dl=false; case '%(ENV_DOWNLOAD_ENABLED)s' in [Tt]rue|1) if [ -f /app/hf-space-pipeline/.build/restore/hf-storage-api-catalog.yaml ]; then dl=true; else echo 'nginx: no hf-storage-api catalog, rendering download:false' >&2; fi;; esac; sed -e 's/__PORT__/%(ENV_PORT)s/' -e 's|__CORPUS_NAME__|%(ENV_CORPUS_NAME)s|g' -e 's/__DOWNLOAD_ENABLED__/'$dl'/' -e 's|__SUBMIT_CONTENT_URL__|%(ENV_SUBMIT_CONTENT_URL)s|g' /etc/nginx/hf-space.conf.template > /etc/nginx/conf.d/hf-space.conf && exec nginx -g 'daemon off;'"
175
  user=root
176
  autorestart=true
177
  startsecs=3
 
171
  stderr_logfile_maxbytes=0
172
 
173
  [program:nginx]
174
+ command=/bin/sh -c "until curl -sf http://localhost:8000/health >/dev/null 2>&1 && curl -sf http://localhost:8010/docs >/dev/null 2>&1; do sleep 2; done; dl=false; case '%(ENV_DOWNLOAD_ENABLED)s' in [Tt]rue|1) if [ -f /app/hf-space-pipeline/.build/restore/hf-storage-api-catalog.yaml ]; then dl=true; else echo 'nginx: no hf-storage-api catalog, rendering download:false' >&2; fi;; esac; vf=glb; case $VIEWER_FORMAT in glb|usd|auto) vf=$VIEWER_FORMAT;; '') ;; *) echo 'nginx: VIEWER_FORMAT is not glb, usd or auto: rendering viewerFormat glb' >&2;; esac; sed -e 's/__PORT__/%(ENV_PORT)s/' -e 's|__CORPUS_NAME__|%(ENV_CORPUS_NAME)s|g' -e 's/__DOWNLOAD_ENABLED__/'$dl'/' -e 's|__SUBMIT_CONTENT_URL__|%(ENV_SUBMIT_CONTENT_URL)s|g' -e 's/__VIEWER_FORMAT__/'$vf'/' /etc/nginx/hf-space.conf.template > /etc/nginx/conf.d/hf-space.conf && exec nginx -g 'daemon off;'"
175
  user=root
176
  autorestart=true
177
  startsecs=3
docker/hf-space/supervisord.conf CHANGED
@@ -210,7 +210,7 @@ stderr_logfile_maxbytes=0
210
  ; deepsearch-api used to follow directly before nginx sat in front of it.
211
  ; %(ENV_PORT)s is substituted by supervisord itself, so no extra templating
212
  ; tool (envsubst etc.) is needed in the image.
213
- command=/bin/sh -c "until curl -sf http://localhost:8000/health >/dev/null 2>&1 && curl -sf http://localhost:8010/docs >/dev/null 2>&1; do sleep 2; done; dl=false; case '%(ENV_DOWNLOAD_ENABLED)s' in [Tt]rue|1) if [ -f /app/hf-space-pipeline/.build/restore/hf-storage-api-catalog.yaml ]; then dl=true; else echo 'nginx: no hf-storage-api catalog, rendering download:false' >&2; fi;; esac; sed -e 's/__PORT__/%(ENV_PORT)s/' -e 's|__CORPUS_NAME__|%(ENV_CORPUS_NAME)s|g' -e 's/__DOWNLOAD_ENABLED__/'$dl'/' -e 's|__SUBMIT_CONTENT_URL__|%(ENV_SUBMIT_CONTENT_URL)s|g' /etc/nginx/hf-space.conf.template > /etc/nginx/conf.d/hf-space.conf && exec nginx -g 'daemon off;'"
214
  user=root
215
  autorestart=true
216
  startsecs=3
 
210
  ; deepsearch-api used to follow directly before nginx sat in front of it.
211
  ; %(ENV_PORT)s is substituted by supervisord itself, so no extra templating
212
  ; tool (envsubst etc.) is needed in the image.
213
+ command=/bin/sh -c "until curl -sf http://localhost:8000/health >/dev/null 2>&1 && curl -sf http://localhost:8010/docs >/dev/null 2>&1; do sleep 2; done; dl=false; case '%(ENV_DOWNLOAD_ENABLED)s' in [Tt]rue|1) if [ -f /app/hf-space-pipeline/.build/restore/hf-storage-api-catalog.yaml ]; then dl=true; else echo 'nginx: no hf-storage-api catalog, rendering download:false' >&2; fi;; esac; vf=glb; case $VIEWER_FORMAT in glb|usd|auto) vf=$VIEWER_FORMAT;; '') ;; *) echo 'nginx: VIEWER_FORMAT is not glb, usd or auto: rendering viewerFormat glb' >&2;; esac; sed -e 's/__PORT__/%(ENV_PORT)s/' -e 's|__CORPUS_NAME__|%(ENV_CORPUS_NAME)s|g' -e 's/__DOWNLOAD_ENABLED__/'$dl'/' -e 's|__SUBMIT_CONTENT_URL__|%(ENV_SUBMIT_CONTENT_URL)s|g' -e 's/__VIEWER_FORMAT__/'$vf'/' /etc/nginx/hf-space.conf.template > /etc/nginx/conf.d/hf-space.conf && exec nginx -g 'daemon off;'"
214
  user=root
215
  autorestart=true
216
  startsecs=3
pipeline/library_media.py CHANGED
@@ -30,6 +30,25 @@ a sibling archive of the same stamp, ``media-<stamp>.hd.tar``, which ARCHIVE nev
30
  installed and served, it is STREAMED in (no copy of the archive on disk): each member the manifest lists lands
31
  under ``<id>/<file>`` through a temporary file, anything else is skipped. Until a file lands the Explorer reads a
32
  404 and stays on tier 1, quietly; a failure leaves what landed.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  """
34
 
35
  from __future__ import annotations
@@ -58,8 +77,17 @@ DISABLED = {"off", "none", "false", "0"}
58
  HD_SUFFIX = ".hd.tar"
59
  SAFE_ID = re.compile(r"^[A-Za-z0-9_-]{1,64}$")
60
  SAFE_NAME = re.compile(r"^[A-Za-z0-9_-][A-Za-z0-9._-]{0,127}$")
 
61
  HD_TRIES = 2
62
- HD_DISK_MARGIN = 8 * 10**9 # free disk the HD stream always leaves (the index, Neo4j and logs keep writing)
 
 
 
 
 
 
 
 
63
 
64
 
65
  def run_prefix(cfg: Config, store, corpus: str) -> str:
@@ -121,10 +149,75 @@ def install(src: Path, dest: Path) -> None:
121
  shutil.rmtree(old, ignore_errors=True)
122
 
123
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  def hd_files(manifest: dict) -> dict[str, set[str]]:
125
  """{entry id: file names} of the HD tiers the manifest lists: an entry's ``hd`` files (model_hd.glb), its spin's
126
  HD frames (``spin.hd``: ``spin_hd_{k:03d}.webp`` for every k below ``spin.frames``) and its RTX clip's HD files
127
- (``rtxclip.hd``). The only members an HD archive may write."""
128
  out: dict[str, set[str]] = {}
129
  for e in (manifest.get("assets") or {}).values():
130
  if not isinstance(e, dict) or not isinstance(e.get("id"), str) or not SAFE_ID.match(e["id"]):
@@ -146,37 +239,145 @@ def hd_files(manifest: dict) -> dict[str, set[str]]:
146
  return out
147
 
148
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  def stream_hd(body, tree: Path, allowed: dict[str, set[str]]) -> tuple[int, int, int]:
150
- """Write the HD archive ``body`` (a stream, read once in order) into ``tree``: each member the manifest lists
151
- (``allowed``) lands under ``<id>/<file>`` through a temporary file, so nginx never serves half of one; a file
152
- already there at the member's size is kept (a retried stream). Anything else is skipped. (written, bytes,
153
- skipped)."""
154
- written = size = skipped = 0
155
  with tarfile.open(fileobj=body, mode="r|") as tf:
156
  for m in tf:
157
- if m.isdir():
158
- continue
159
- parts = m.name.removeprefix("./").split("/")
160
- if not m.isfile() or len(parts) != 2 or parts[1] not in allowed.get(parts[0], ()):
161
- skipped += 1
162
- continue
163
- target = tree / parts[0] / parts[1]
164
- if target.is_file() and target.stat().st_size == m.size:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
  continue
166
- target.parent.mkdir(parents=True, exist_ok=True)
167
- part = target.with_name(f".{target.name}.part")
168
- try:
169
- with tf.extractfile(m) as src, open(part, "wb") as out:
170
- shutil.copyfileobj(src, out, 1 << 20)
171
- if part.stat().st_size != m.size:
172
- raise ValueError(f"{m.name}: {part.stat().st_size} of {m.size} bytes")
173
- except BaseException:
174
- part.unlink(missing_ok=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
  raise
176
- os.replace(part, target)
177
- written += 1
178
- size += m.size
179
- return written, size, skipped
180
 
181
 
182
  def fetch_hd(cfg: Config, store, uri: str, tree: Path) -> int:
@@ -190,35 +391,100 @@ def fetch_hd(cfg: Config, store, uri: str, tree: Path) -> int:
190
  allowed = hd_files(json.loads((tree / "manifest.json").read_text()))
191
  if not allowed:
192
  return 0
193
- folder, name = hd_uri.rsplit("/", 1)
194
- size = next((n for rel, n in store.list_objects(cfg, folder) if rel == name), None)
195
  if size is None:
196
  print(f"==> library media HD: none at {hd_uri}")
197
  return 0
198
- free = shutil.disk_usage(tree).free
199
- if size + HD_DISK_MARGIN > free:
200
- # never fill the disk OpenSearch and Neo4j write to: a smaller Space keeps tier 1
201
- print(f"==> library media HD: {size / 1e9:.1f} GB would leave under {HD_DISK_MARGIN / 1e9:.0f} GB of "
202
- f"{free / 1e9:.1f} GB free — not fetched")
203
  return 0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
  t0 = time.time()
205
- total = [0, 0, 0]
206
- for attempt in range(HD_TRIES):
207
- body = store.open_stream(cfg, hd_uri)
208
- if body is None:
209
- print(f"==> library media HD: none at {hd_uri}")
210
- return 0
211
- try:
212
- written, size, skipped = stream_hd(body, tree, allowed)
213
- total = [total[0] + written, total[1] + size, skipped]
214
- break
215
- except (OSError, ValueError, tarfile.TarError) as exc:
216
- if attempt == HD_TRIES - 1:
217
- raise
218
- print(f"==> library media HD: stream broke ({type(exc).__name__}: {str(exc)[:200]}), starting again")
219
- print(f"==> library media HD: {total[0]} files ({total[1] / 1e6:.0f} MB) from {hd_uri} in {time.time() - t0:.0f} s"
220
- + (f"; {total[2]} members not in the manifest skipped" if total[2] else ""))
221
- return total[0]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
222
 
223
 
224
  def fetch(env: dict[str, str], root: Path = MEDIA_ROOT, store=None) -> int:
@@ -253,6 +519,9 @@ def fetch(env: dict[str, str], root: Path = MEDIA_ROOT, store=None) -> int:
253
  if count is None:
254
  print(f"==> library media: {uri} has no usable manifest.json — none served")
255
  return 0
 
 
 
256
  install(tmp / "tree", root / INDEX_KEY)
257
  finally:
258
  shutil.rmtree(tmp, ignore_errors=True)
@@ -262,6 +531,11 @@ def fetch(env: dict[str, str], root: Path = MEDIA_ROOT, store=None) -> int:
262
  fetch_hd(cfg, store, uri, root / INDEX_KEY)
263
  except Exception as exc: # noqa: BLE001 — the tier-1 tree is served already; HD is a bonus
264
  print(f"==> library media HD: stopped ({type(exc).__name__}: {str(exc)[:300]}) — tier 1 stays", file=sys.stderr)
 
 
 
 
 
265
  return count
266
 
267
 
 
30
  installed and served, it is STREAMED in (no copy of the archive on disk): each member the manifest lists lands
31
  under ``<id>/<file>`` through a temporary file, anything else is skipped. Until a file lands the Explorer reads a
32
  404 and stays on tier 1, quietly; a failure leaves what landed.
33
+
34
+ Web USD (an entry's ``usd`` block, profile simready-web-usd/1, 2026-10-14) never touches the two archives above:
35
+ it travels in two more siblings of the same stamp, loaded after them, each with its own disk check, so the GLB tiers
36
+ are fetched exactly as before whatever the USD costs:
37
+
38
+ - ``media-<stamp>.usd.tar``: first member ``usd-manifest.json`` (the blocks, ``{version: 1, profile, assets: {Space
39
+ key: {id, usd}}}``), then per entry ``<id>/usd/asset.usdc``, ``usd/colliders.usdc`` (each + its ``.br``), the
40
+ export's own ``usd/articulation.json`` and the tier-1 KTX2 in ``usd/tex/``;
41
+ - ``media-<stamp>.usdhd.tar``: ``<id>/usd/hd.usdc`` (+ ``.br``) and the KTX2 only the full level binds
42
+ (``ktx2.full``).
43
+
44
+ Both are streamed like the HD archive (only listed paths, all under ``<id>/usd/``). The served manifest never names a
45
+ file that is not there: a ``usd`` block in the main archive's manifest is dropped at install; once the USD archive has
46
+ landed, the blocks whose tier-1 files are all there are added WITHOUT their full level (no ``files.hd``, no
47
+ ``ktx2.full``); once the USD HD archive has landed, the blocks whose full-level files are all there get it back. A
48
+ skipped or failed USD HD archive leaves tier 1; a skipped or failed USD archive leaves the GLB alone. Nothing of
49
+ either is fetched unless the Space's ``VIEWER_FORMAT`` (the Explorer's /config.js ``features.viewerFormat``, rendered
50
+ by supervisord.conf) is ``usd`` or ``auto``; LIBRARY_MEDIA_USD=off / LIBRARY_MEDIA_USD_HD=off skip one or both. nginx
51
+ serves a ``.usdc`` as its ``.br`` to a client that accepts brotli.
52
  """
53
 
54
  from __future__ import annotations
 
77
  HD_SUFFIX = ".hd.tar"
78
  SAFE_ID = re.compile(r"^[A-Za-z0-9_-]{1,64}$")
79
  SAFE_NAME = re.compile(r"^[A-Za-z0-9_-][A-Za-z0-9._-]{0,127}$")
80
+ USD_MAX_DEPTH = 4 # segments of a web USD path below its entry: usd/tex/<name>.ktx2 has 3
81
  HD_TRIES = 2
82
+ HD_DISK_MARGIN = 8 * 10**9 # free disk each streamed archive always leaves (the index, Neo4j and logs keep writing)
83
+ # Web USD (see the module doc): two more siblings of the archive's stamp, after the GLB ones.
84
+ USD_SUFFIX = ".usd.tar"
85
+ USD_HD_SUFFIX = ".usdhd.tar"
86
+ USD_OVERLAY = "usd-manifest.json" # the USD archive's first member: the blocks
87
+ USD_OVERLAY_MAX = 64 * 2**20
88
+ USD_PROFILE = "simready-web-usd/1"
89
+ USD_ASSET = "usd/asset.usdc"
90
+ VIEWER_FORMATS = ("glb", "usd", "auto") # the Space's VIEWER_FORMAT; anything else is "glb" (supervisord.conf too)
91
 
92
 
93
  def run_prefix(cfg: Config, store, corpus: str) -> str:
 
149
  shutil.rmtree(old, ignore_errors=True)
150
 
151
 
152
+ def safe_rel(path) -> bool:
153
+ """A file path below an entry's folder: 1 to USD_MAX_DEPTH SAFE_NAME segments joined by "/" (so never "", "."
154
+ or "..", never absolute)."""
155
+ if not isinstance(path, str):
156
+ return False
157
+ parts = path.split("/")
158
+ return len(parts) <= USD_MAX_DEPTH and all(SAFE_NAME.match(p) for p in parts)
159
+
160
+
161
+ def usd_path(path) -> bool:
162
+ """A web USD file path: under the entry's ``usd/`` folder, safe (``safe_rel``)."""
163
+ return isinstance(path, str) and path.startswith("usd/") and safe_rel(path)
164
+
165
+
166
+ def usd_block_ok(usd) -> bool:
167
+ """A ``usd`` block the loader can place: the profile, ``files.asset`` = usd/asset.usdc, every file and KTX2 path a
168
+ ``usd_path`` (the KTX2 ending .ktx2), ``br`` a list of strings. Anything else is no block (the GLB stays)."""
169
+ if not isinstance(usd, dict) or usd.get("profile") != USD_PROFILE:
170
+ return False
171
+ files, ktx2, br = usd.get("files"), usd.get("ktx2", {}), usd.get("br", [])
172
+ if not isinstance(files, dict) or files.get("asset") != USD_ASSET or not all(map(usd_path, files.values())):
173
+ return False
174
+ if not isinstance(ktx2, dict) or not isinstance(br, list) or not all(isinstance(n, str) for n in br):
175
+ return False
176
+ lists = [ktx2.get(k, []) for k in ("tier1", "full")]
177
+ return all(isinstance(lst, list) and all(usd_path(p) and p.endswith(".ktx2") for p in lst) for lst in lists)
178
+
179
+
180
+ def _with_br(usd: dict, names: set[str]) -> set[str]:
181
+ return names | {f"{n}.br" for n in usd.get("br", []) if n in names}
182
+
183
+
184
+ def usd_tier1_files(usd) -> set[str]:
185
+ """The USD archive's files of a block: every ``files`` role but ``hd`` (asset, colliders, articulation), the
186
+ tier-1 KTX2 (``ktx2.tier1``) and the ``.br`` sibling of each the block names in ``br``; none for a malformed
187
+ block."""
188
+ if not usd_block_ok(usd):
189
+ return set()
190
+ names = {p for role, p in usd["files"].items() if role != "hd"} | set(usd.get("ktx2", {}).get("tier1", []))
191
+ return _with_br(usd, names)
192
+
193
+
194
+ def usd_hd_files(usd) -> set[str]:
195
+ """The USD HD archive's files of a block: ``files.hd`` (usd/hd.usdc), the KTX2 only the full level binds
196
+ (``ktx2.full``) and the ``.br`` sibling of each the block names in ``br``; none without ``files.hd`` or for a
197
+ malformed block."""
198
+ if not usd_block_ok(usd) or not usd["files"].get("hd"):
199
+ return set()
200
+ return _with_br(usd, {usd["files"]["hd"], *usd.get("ktx2", {}).get("full", [])})
201
+
202
+
203
+ def usd_without_hd(usd: dict) -> dict:
204
+ """The block as tier 1 alone: no ``files.hd``, no ``ktx2.full``, their ``.br`` names gone, ``bytes.full`` 0 — the
205
+ Explorer then never asks for a tier 2 that is not there."""
206
+ out = json.loads(json.dumps(usd))
207
+ gone = usd_hd_files(usd)
208
+ out["files"].pop("hd", None)
209
+ if isinstance(out.get("ktx2"), dict):
210
+ out["ktx2"]["full"] = []
211
+ out["br"] = [n for n in out.get("br", []) if n not in gone]
212
+ if isinstance(out.get("bytes"), dict):
213
+ out["bytes"]["full"] = 0
214
+ return out
215
+
216
+
217
  def hd_files(manifest: dict) -> dict[str, set[str]]:
218
  """{entry id: file names} of the HD tiers the manifest lists: an entry's ``hd`` files (model_hd.glb), its spin's
219
  HD frames (``spin.hd``: ``spin_hd_{k:03d}.webp`` for every k below ``spin.frames``) and its RTX clip's HD files
220
+ (``rtxclip.hd``). The only members an HD archive may write (web USD has archives of its own)."""
221
  out: dict[str, set[str]] = {}
222
  for e in (manifest.get("assets") or {}).values():
223
  if not isinstance(e, dict) or not isinstance(e.get("id"), str) or not SAFE_ID.match(e["id"]):
 
239
  return out
240
 
241
 
242
+ def _write_member(tf, m, tree: Path, allowed: dict[str, set[str]]) -> tuple[int, int, int]:
243
+ """One member of a streamed archive: written under ``<id>/<path>`` when ``allowed`` lists it (through a temporary
244
+ file, so nginx never serves half of one; a file already there at the member's size is kept: a retried stream),
245
+ else skipped. (written, bytes, skipped), each 0 or 1 / the size."""
246
+ if m.isdir():
247
+ return 0, 0, 0
248
+ parts = m.name.removeprefix("./").split("/")
249
+ rel = "/".join(parts[1:])
250
+ if not m.isfile() or len(parts) < 2 or rel not in allowed.get(parts[0], ()):
251
+ return 0, 0, 1
252
+ target = tree / parts[0] / rel
253
+ if target.is_file() and target.stat().st_size == m.size:
254
+ return 0, 0, 0
255
+ target.parent.mkdir(parents=True, exist_ok=True)
256
+ part = target.with_name(f".{target.name}.part")
257
+ try:
258
+ with tf.extractfile(m) as src, open(part, "wb") as out:
259
+ shutil.copyfileobj(src, out, 1 << 20)
260
+ if part.stat().st_size != m.size:
261
+ raise ValueError(f"{m.name}: {part.stat().st_size} of {m.size} bytes")
262
+ except BaseException:
263
+ part.unlink(missing_ok=True)
264
+ raise
265
+ os.replace(part, target)
266
+ return 1, m.size, 0
267
+
268
+
269
  def stream_hd(body, tree: Path, allowed: dict[str, set[str]]) -> tuple[int, int, int]:
270
+ """Write the archive ``body`` (a stream, read once in order) into ``tree``: each member ``allowed`` lists (<id> →
271
+ paths below it, e.g. model_hd.glb or usd/hd.usdc) lands under ``<id>/<path>`` (``_write_member``); anything else
272
+ is skipped. (written, bytes, skipped)."""
273
+ total = [0, 0, 0]
 
274
  with tarfile.open(fileobj=body, mode="r|") as tf:
275
  for m in tf:
276
+ total = [a + b for a, b in zip(total, _write_member(tf, m, tree, allowed))]
277
+ return total[0], total[1], total[2]
278
+
279
+
280
+ def usd_overlay(doc, manifest: dict) -> tuple[dict[str, tuple[str, dict]], int]:
281
+ """The USD archive's ``usd-manifest.json`` against the served manifest: ({Space key: (entry id, block)} for every
282
+ well-formed block whose key the manifest lists under the same id, the number left out). Not an overlay at all:
283
+ ValueError."""
284
+ if not isinstance(doc, dict) or doc.get("version") != 1 or not isinstance(doc.get("assets"), dict):
285
+ raise ValueError(f"{USD_OVERLAY} is not a web USD overlay (version 1, assets{{}})")
286
+ assets = manifest.get("assets") if isinstance(manifest.get("assets"), dict) else {}
287
+ out, left = {}, 0
288
+ for key, o in doc["assets"].items():
289
+ e = assets.get(key)
290
+ i = o.get("id") if isinstance(o, dict) else None
291
+ if (isinstance(e, dict) and isinstance(i, str) and SAFE_ID.match(i) and e.get("id") == i
292
+ and usd_block_ok(o.get("usd"))):
293
+ out[key] = (i, o["usd"])
294
+ else:
295
+ left += 1
296
+ return out, left
297
+
298
+
299
+ def stream_usd(body, tree: Path, manifest: dict) -> tuple[dict[str, tuple[str, dict]], int, int, int, int]:
300
+ """Write the USD archive ``body`` into ``tree``: its FIRST member must be ``usd-manifest.json`` (else ValueError,
301
+ nothing written), whose usable blocks (``usd_overlay``) name the only members written — each block's
302
+ ``usd_tier1_files``. (blocks, left out, written, bytes, skipped)."""
303
+ blocks, left, total = None, 0, [0, 0, 0]
304
+ with tarfile.open(fileobj=body, mode="r|") as tf:
305
+ for m in tf:
306
+ if blocks is None:
307
+ if m.name.removeprefix("./") != USD_OVERLAY or not m.isfile() or m.size > USD_OVERLAY_MAX:
308
+ raise ValueError(f"the first member is {m.name!r}, not {USD_OVERLAY}")
309
+ with tf.extractfile(m) as src:
310
+ blocks, left = usd_overlay(json.loads(src.read()), manifest)
311
+ allowed: dict[str, set[str]] = {}
312
+ for i, block in blocks.values():
313
+ allowed.setdefault(i, set()).update(usd_tier1_files(block))
314
  continue
315
+ total = [a + b for a, b in zip(total, _write_member(tf, m, tree, allowed))]
316
+ if blocks is None:
317
+ raise ValueError(f"an empty archive, no {USD_OVERLAY}")
318
+ return blocks, left, total[0], total[1], total[2]
319
+
320
+
321
+ def landed(tree: Path, entry_id: str, names: set[str]) -> bool:
322
+ """Every one of ``names`` is a file under ``tree/<entry_id>/``."""
323
+ return bool(names) and all((tree / entry_id / n).is_file() for n in names)
324
+
325
+
326
+ def publish_usd(tree: Path, blocks: dict[str, dict]) -> int:
327
+ """Rewrite the served manifest with exactly ``blocks`` ({Space key: usd block}) as its entries' ``usd`` (every
328
+ other block untouched; an entry not in ``blocks`` loses any ``usd``), atomically. The number of entries carrying
329
+ one. An unchanged manifest is not written."""
330
+ path = tree / "manifest.json"
331
+ doc = json.loads(path.read_text())
332
+ changed = n = 0
333
+ for key, e in (doc.get("assets") or {}).items():
334
+ if not isinstance(e, dict):
335
+ continue
336
+ if key in blocks:
337
+ changed += e.get("usd") != blocks[key]
338
+ e["usd"] = blocks[key]
339
+ n += 1
340
+ elif "usd" in e:
341
+ del e["usd"]
342
+ changed += 1
343
+ if changed:
344
+ part = path.with_name(f".{path.name}.part")
345
+ part.write_text(json.dumps(doc, separators=(",", ":")))
346
+ os.replace(part, path)
347
+ return n
348
+
349
+
350
+ def listed_size(cfg: Config, store, uri: str) -> Optional[int]:
351
+ folder, name = uri.rsplit("/", 1)
352
+ return next((n for rel, n in store.list_objects(cfg, folder) if rel == name), None)
353
+
354
+
355
+ def room_for(tree: Path, size: int, what: str) -> bool:
356
+ """Never fill the disk OpenSearch and Neo4j write to: a streamed archive is fetched only while ``size`` leaves
357
+ HD_DISK_MARGIN free. Each archive asks on its own, after the ones before it landed."""
358
+ free = shutil.disk_usage(tree).free
359
+ if size + HD_DISK_MARGIN > free:
360
+ print(f"==> library media {what}: {size / 1e9:.1f} GB would leave under {HD_DISK_MARGIN / 1e9:.0f} GB of "
361
+ f"{free / 1e9:.1f} GB free — not fetched")
362
+ return False
363
+ return True
364
+
365
+
366
+ def stream_with_retry(cfg: Config, store, uri: str, what: str, run):
367
+ """``run(body)`` over the object ``uri`` streamed; a broken stream starts again once (files already complete are
368
+ kept). None: the object is gone."""
369
+ for attempt in range(HD_TRIES):
370
+ body = store.open_stream(cfg, uri)
371
+ if body is None:
372
+ print(f"==> library media {what}: none at {uri}")
373
+ return None
374
+ try:
375
+ return run(body)
376
+ except (OSError, ValueError, tarfile.TarError) as exc:
377
+ if attempt == HD_TRIES - 1:
378
  raise
379
+ print(f"==> library media {what}: stream broke ({type(exc).__name__}: {str(exc)[:200]}), starting again")
380
+ return None
 
 
381
 
382
 
383
  def fetch_hd(cfg: Config, store, uri: str, tree: Path) -> int:
 
391
  allowed = hd_files(json.loads((tree / "manifest.json").read_text()))
392
  if not allowed:
393
  return 0
394
+ size = listed_size(cfg, store, hd_uri)
 
395
  if size is None:
396
  print(f"==> library media HD: none at {hd_uri}")
397
  return 0
398
+ if not room_for(tree, size, "HD"):
399
+ return 0 # a smaller Space keeps tier 1
400
+ t0 = time.time()
401
+ got = stream_with_retry(cfg, store, hd_uri, "HD", lambda body: stream_hd(body, tree, allowed))
402
+ if got is None:
403
  return 0
404
+ written, size, skipped = got
405
+ print(f"==> library media HD: {written} files ({size / 1e6:.0f} MB) from {hd_uri} in {time.time() - t0:.0f} s"
406
+ + (f"; {skipped} members not in the manifest skipped" if skipped else ""))
407
+ return written
408
+
409
+
410
+ def viewer_format(cfg: Config) -> str:
411
+ """The Space's VIEWER_FORMAT as supervisord.conf renders it into /config.js: glb | usd | auto, anything else glb."""
412
+ value = cfg.get("VIEWER_FORMAT", "")
413
+ return value if value in VIEWER_FORMATS else "glb"
414
+
415
+
416
+ def fetch_usd(cfg: Config, store, uri: str, tree: Path) -> int:
417
+ """Web USD (see the module doc): stream ``uri``'s ``.usd.tar`` sibling into the installed ``tree`` and publish the
418
+ blocks whose tier-1 files landed (without their full level), then its ``.usdhd.tar`` and give back the full level
419
+ of the blocks whose files landed. Returns the number of entries the served manifest then gives a ``usd``. Off
420
+ unless VIEWER_FORMAT is usd or auto; each archive only with room to spare (``room_for``)."""
421
+ fmt = viewer_format(cfg)
422
+ if fmt == "glb":
423
+ print("==> library media USD: off (VIEWER_FORMAT glb)")
424
+ return 0
425
+ if cfg.get("LIBRARY_MEDIA_USD", "").strip().lower() in DISABLED:
426
+ print("==> library media USD: off (LIBRARY_MEDIA_USD)")
427
+ return 0
428
+ base = uri[: -len(".tar")]
429
+ usd_uri = base + USD_SUFFIX
430
+ size = listed_size(cfg, store, usd_uri)
431
+ if size is None:
432
+ print(f"==> library media USD: none at {usd_uri}")
433
+ return 0
434
+ if not room_for(tree, size, "USD"):
435
+ return 0
436
+ manifest = json.loads((tree / "manifest.json").read_text())
437
  t0 = time.time()
438
+ got = stream_with_retry(cfg, store, usd_uri, "USD", lambda body: stream_usd(body, tree, manifest))
439
+ del manifest
440
+ if got is None:
441
+ return 0
442
+ blocks, left, written, nbytes, skipped = got
443
+ tier1 = {k: usd_without_hd(b) for k, (i, b) in blocks.items() if landed(tree, i, usd_tier1_files(b))}
444
+ shown = publish_usd(tree, tier1)
445
+ print(f"==> library media USD: {shown} of {len(blocks)} blocks served at tier 1 ({written} files, "
446
+ f"{nbytes / 1e6:.0f} MB) from {usd_uri} in {time.time() - t0:.0f} s"
447
+ + (f"; {left} blocks not in this manifest (or malformed) left out" if left else "")
448
+ + (f"; {skipped} members not listed skipped" if skipped else ""))
449
+ full = {k: (i, b) for k, (i, b) in blocks.items() if k in tier1 and usd_hd_files(b)}
450
+ if not full:
451
+ return shown
452
+ try:
453
+ landed_hd = fetch_usd_hd(cfg, store, base + USD_HD_SUFFIX, tree, full)
454
+ except Exception as exc: # noqa: BLE001 — tier 1 is served already; the full level is a bonus
455
+ print(f"==> library media USD HD: stopped ({type(exc).__name__}: {str(exc)[:300]}) — USD tier 1 stays",
456
+ file=sys.stderr)
457
+ return shown
458
+ if landed_hd:
459
+ publish_usd(tree, {**tier1, **{k: blocks[k][1] for k in landed_hd}})
460
+ return shown
461
+
462
+
463
+ def fetch_usd_hd(cfg: Config, store, uri: str, tree: Path, blocks: dict[str, tuple[str, dict]]) -> set[str]:
464
+ """Stream the ``.usdhd.tar`` ``uri`` into ``tree`` (only ``blocks``' ``usd_hd_files``); the Space keys whose
465
+ full-level files are all there. Off (LIBRARY_MEDIA_USD_HD), absent or without room: none."""
466
+ if cfg.get("LIBRARY_MEDIA_USD_HD", "").strip().lower() in DISABLED:
467
+ print("==> library media USD HD: off (LIBRARY_MEDIA_USD_HD) — USD tier 1 only")
468
+ return set()
469
+ size = listed_size(cfg, store, uri)
470
+ if size is None:
471
+ print(f"==> library media USD HD: none at {uri} — USD tier 1 only")
472
+ return set()
473
+ if not room_for(tree, size, "USD HD"):
474
+ return set()
475
+ allowed: dict[str, set[str]] = {}
476
+ for i, block in blocks.values():
477
+ allowed.setdefault(i, set()).update(usd_hd_files(block))
478
+ t0 = time.time()
479
+ got = stream_with_retry(cfg, store, uri, "USD HD", lambda body: stream_hd(body, tree, allowed))
480
+ if got is None:
481
+ return set()
482
+ written, nbytes, skipped = got
483
+ keys = {k for k, (i, b) in blocks.items() if landed(tree, i, usd_hd_files(b))}
484
+ print(f"==> library media USD HD: {len(keys)} of {len(blocks)} blocks with their full level ({written} files, "
485
+ f"{nbytes / 1e6:.0f} MB) from {uri} in {time.time() - t0:.0f} s"
486
+ + (f"; {skipped} members not listed skipped" if skipped else ""))
487
+ return keys
488
 
489
 
490
  def fetch(env: dict[str, str], root: Path = MEDIA_ROOT, store=None) -> int:
 
519
  if count is None:
520
  print(f"==> library media: {uri} has no usable manifest.json — none served")
521
  return 0
522
+ if '"usd"' in (tmp / "tree" / "manifest.json").read_text():
523
+ # web USD comes only from its own archives (fetch_usd), never from this one's manifest
524
+ publish_usd(tmp / "tree", {})
525
  install(tmp / "tree", root / INDEX_KEY)
526
  finally:
527
  shutil.rmtree(tmp, ignore_errors=True)
 
531
  fetch_hd(cfg, store, uri, root / INDEX_KEY)
532
  except Exception as exc: # noqa: BLE001 — the tier-1 tree is served already; HD is a bonus
533
  print(f"==> library media HD: stopped ({type(exc).__name__}: {str(exc)[:300]}) — tier 1 stays", file=sys.stderr)
534
+ try:
535
+ fetch_usd(cfg, store, uri, root / INDEX_KEY)
536
+ except Exception as exc: # noqa: BLE001 — the GLB tiers are served already; web USD is a bonus
537
+ print(f"==> library media USD: stopped ({type(exc).__name__}: {str(exc)[:300]}) — the GLB stays",
538
+ file=sys.stderr)
539
  return count
540
 
541
 
services/explorer/dist/build-info.json CHANGED
@@ -1,7 +1,7 @@
1
  {
2
  "product": "simready-central-slim-explorer",
3
- "version": "slim-ui-b62bb449",
4
- "bundle_id": "main.9cf56290.js",
5
- "built_at": "2026-10-15T05:56:39Z",
6
  "flags": {"public_mode": true, "email_auth": false, "create_ui": false, "hierarchy_editor": false, "create_search": false, "auth_ui": false, "credentials_ui": false, "index_management": false, "inference_backend": "hub", "vlm_asset_refs": false, "validation_image_max_px": 448, "validation_max_retries": 0, "validation_max_concurrent": 32, "validation_tail_concurrent": 8, "validation_eager_count": 50, "validation_batch_stream": true, "library_idle_prefetch": false, "validation_score_scale": "percent", "parse_gate_fields": true, "parse_fast_path": true, "featured_landing": true, "dependency_views": true, "model_viewer": false, "library_viewer": true, "library_media": "runtime", "spell_correction": false, "downloads": "runtime", "submit_content": "runtime", "third_party_notices": "runtime"}
7
  }
 
1
  {
2
  "product": "simready-central-slim-explorer",
3
+ "version": "slim-ui-6262a66a",
4
+ "bundle_id": "main.cf692f87.js",
5
+ "built_at": "2026-10-15T08:41:49Z",
6
  "flags": {"public_mode": true, "email_auth": false, "create_ui": false, "hierarchy_editor": false, "create_search": false, "auth_ui": false, "credentials_ui": false, "index_management": false, "inference_backend": "hub", "vlm_asset_refs": false, "validation_image_max_px": 448, "validation_max_retries": 0, "validation_max_concurrent": 32, "validation_tail_concurrent": 8, "validation_eager_count": 50, "validation_batch_stream": true, "library_idle_prefetch": false, "validation_score_scale": "percent", "parse_gate_fields": true, "parse_fast_path": true, "featured_landing": true, "dependency_views": true, "model_viewer": false, "library_viewer": true, "library_media": "runtime", "spell_correction": false, "downloads": "runtime", "submit_content": "runtime", "third_party_notices": "runtime"}
7
  }
services/explorer/dist/index.html CHANGED
@@ -1 +1 @@
1
- <!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/ds.png"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="SimReady Central — SimReady asset search"/><meta name="ui-version" content="slim-ui-b62bb449"><script src="/config.js"></script><title>SimReady Central</title><script defer="defer" src="/static/js/main.9cf56290.js"></script><link href="/static/css/main.01671ca7.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
 
1
+ <!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/ds.png"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="SimReady Central — SimReady asset search"/><meta name="ui-version" content="slim-ui-6262a66a"><script src="/config.js"></script><title>SimReady Central</title><script defer="defer" src="/static/js/main.cf692f87.js"></script><link href="/static/css/main.01671ca7.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
services/explorer/dist/static/js/9.a9ea1e41.chunk.js ADDED
@@ -0,0 +1 @@
 
 
1
+ "use strict";(self.webpackChunkdeepsearch_ui=self.webpackChunkdeepsearch_ui||[]).push([[9],{9(e,t,o){o.r(t),o.d(t,{COLLIDERS_LAYER:()=>c,HD_LAYER:()=>i,LOCAL:()=>p,NORMAL_MODES:()=>N,READER_TEXTURES:()=>h,RECYCLE_BYTES:()=>m,ROOT_KEY:()=>u,ROOT_LAYER:()=>l,SLOTS:()=>k,WARM_KEY:()=>d,WebUsdError:()=>f,_readerState:()=>Me,_resetWebUsdReader:()=>ye,colorSpaceOf:()=>C,compactRecord:()=>I,expected:()=>ge,fallbackWarning:()=>Z,fileKey:()=>x,flipV:()=>T,geometryArrays:()=>Y,isWebUsdError:()=>v,loadWebUsd:()=>be,lowBitLog2:()=>W,mapUrl:()=>U,materialGaps:()=>ee,materialParams:()=>$,openpbrOnly:()=>J,pieceOf:()=>M,planHints:()=>_,quantizeLattice:()=>D,roleOf:()=>E,rootLayerText:()=>S,setWebUsdReader:()=>ae,siblingUrl:()=>A,snormNormals:()=>G,tierLayers:()=>L,uvDequant:()=>F,uvMatrix:()=>q,warmWebUsdReader:()=>fe,webUsdReaderFailure:()=>b,webUsdReaderSet:()=>le});var n=o(986),r=o(379),s=o(1);const a=["warnings"],l="asset.usdc",i="hd.usdc",c="colliders.usdc",u="simready-web.usda",d="simready-warm.usda",p="local:///",m=268435456,h="none";class f extends Error{constructor(e,t){let{cause:o,url:n,status:r,fatal:s}=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};super(t),this.name="WebUsdError",this.code=e,void 0!==o&&(this.cause=o),void 0!==n&&(this.url=n),void 0!==r&&(this.status=r),s&&(this.fatal=!0)}}const v=e=>e instanceof f;let g=null;function w(e,t){let o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return g=new f(e,t,(0,r.A)((0,r.A)({},o),{},{fatal:!0})),g}const b=()=>g,y=/\/Bodies\/(b\d+)\/(?:lo|hd)\/(m\d+)$/;function M(e){const t=y.exec(e||"");return t?{body:t[1],name:t[1]+t[2]}:null}function S(){const e=2===(arguments.length>0&&void 0!==arguments[0]?arguments[0]:1)?"full":"preview";return["#usda 1.0","(",' defaultPrim = "Asset"'," metersPerUnit = 1",' upAxis = "Y"'," subLayers = ["," @./".concat(l,"@")," ]",")","",'over "Asset" ('," variants = {",' string lod = "'.concat(e,'"'),' string textures = "web"'," }",")","{","}",""].join("\n")}const L=function(){return 2===(arguments.length>0&&void 0!==arguments[0]?arguments[0]:1)?[l,i]:[l]},x=e=>String(e).split(/[?#]/)[0];function A(e,t){const o=new URL(e,t);return o.search||(o.search=new URL(t).search),o.href}function U(e,t){return String(e).startsWith(p)?A(String(e).slice(p.length).replace(/^\/+/,""),t):new URL(e,t).href}function _(e,t){const o=new Map;for(const n of e||[]){if("string"!==typeof n||!n.trim())continue;const e=A(n.trim(),t),r=x(e);o.has(r)||o.set(r,e)}return o}const k={diffuseColor:"map",emissiveColor:"emissiveMap",roughness:"roughnessMap",metallic:"metalnessMap",occlusion:"aoMap",opacity:"alphaMap",normal:"normalMap"},R={map:"rgb",emissiveMap:"rgb",roughnessMap:"g",metalnessMap:"b",aoMap:"r",alphaMap:"g",normalMap:"rgb"},B=new Set(["map","emissiveMap","sheenColorMap","specularColorMap"]),E=e=>B.has(e)?"color":"data",C=e=>"color"===e?"srgb":"",O=(e,t)=>Math.abs(e-t)<1e-6,P={r:0,g:1,b:2,a:3};function T(e){for(let t=1;t<e.length;t+=2)e[t]=1-e[t];return e}function I(e,t){var o,n;if(!0===e)return!0;if(Array.isArray(e))return 3===e.length&&e.every(e=>Number.isInteger(e)&&e>0);if(e&&"object"===typeof e)return!!e.bits||Number.isInteger(e.points_log2);let r=null===t||void 0===t||null===(o=t.customLayerData)||void 0===o||null===(n=o.simready)||void 0===n?void 0:n.tiers;if("string"===typeof r)try{r=JSON.parse(r)}catch(s){r=null}return!(!r||"object"!==typeof r||!r.compact)}function W(e){const t=new Uint32Array(e.buffer,e.byteOffset,e.length);let o=1/0;for(let n=0;n<t.length;n+=1){const e=t[n];if(0===(2147483647&e)){if(0!==e)return null;continue}const r=e>>>23&255;if(255===r)return null;const s=r?8388607&e|8388608:8388607&e,a=(r||1)-150+(31-Math.clz32(s&-s));a<o&&(o=a)}return o===1/0?0:o}const j=[-32768,32767],z=[0,65535];function D(e,t){let o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:t;const n=e.length/t;if(!(n>0)||!Number.isInteger(n))return null;const r=W(e);if(null===r)return null;const s=2**-r,a=new Array(t).fill(1/0),l=new Array(t).fill(-1/0);for(let m=0,h=0;m<n;m+=1)for(let o=0;o<t;o+=1,h+=1){const t=e[h]*s;t<a[o]&&(a[o]=t),t>l[o]&&(l[o]=t)}const i=Math.min(...a),c=Math.max(...l);let u=null,d=new Array(t).fill(0);if(i>=j[0]&&c<=j[1])u=Int16Array;else if(i>=z[0]&&c<=z[1])u=Uint16Array;else{if(!a.every((e,t)=>l[t]-e<=z[1]))return null;u=Uint16Array,d=a.slice()}const p=new u(n*o);for(let m=0,h=0;m<n;m+=1)for(let n=0;n<t;n+=1,h+=1)p[m*o+n]=e[h]*s-d[n];return{array:p,k:r,offset:d,min:a.map((e,t)=>e-d[t]),max:l.map((e,t)=>e-d[t])}}function G(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:8;const o=16===t?Int16Array:Int8Array,n=16===t?32767:127,r=e.length/3,s=new o(4*r);for(let a=0;a<r;a+=1)for(let t=0;t<3;t+=1){const o=Math.max(-1,Math.min(1,e[3*a+t]||0));s[4*a+t]=Math.sign(o)*Math.floor(Math.abs(o)*n+.5)}return s}const F=e=>{let{k:t,offset:o}=e;const n=2**t;return[n,0,o[0]*n,0,n,o[1]*n,0,0,1].map(e=>e+0)},N={int8:8,int16:16,float:0};function Y(e,t){let o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"int8";const n=(e.uvs||[]).map(T),r=e=>e?(e.array||e).byteLength:0,s=r(e.positions)+r(e.normals)+n.reduce((e,t)=>e+t.byteLength,0),a={position:e.positions,normal:e.normals,uvs:n.slice(),positionLattice:null,uvLattice:null};if(t){var l;a.positionLattice=D(e.positions,3,4),a.positionLattice&&(a.position=a.positionLattice);const t=null!==(l=N[o])&&void 0!==l?l:8;t&&e.normals&&(a.normal={array:G(e.normals,t),bits:t}),n[0]&&(a.uvLattice=D(n[0],2,2),a.uvLattice&&(a.uvs[0]=a.uvLattice))}return a.bytes={float:s,upload:r(a.position)+r(a.normal)+a.uvs.reduce((e,t)=>e+r(t),0)},a}const H=(e,t)=>[0,1,2].flatMap(o=>[0,1,2].map(n=>e[3*o]*t[n]+e[3*o+1]*t[3+n]+e[3*o+2]*t[6+n])),K=[1,0,0,0,-1,1,0,0,1];function q(e){const[t,o]=(null===e||void 0===e?void 0:e.uvScale)||[1,1],[n,r]=(null===e||void 0===e?void 0:e.uvTranslation)||[0,0],s=((null===e||void 0===e?void 0:e.uvRotation)||0)*Math.PI/180;if(1===t&&1===o&&0===n&&0===r&&0===s)return null;const a=Math.cos(s),l=Math.sin(s);return H(H(K,[a*t,-l*o,n,l*t,a*o,r,0,0,1]),K).map(e=>e+0)}const V={mirror:"mirror",clamp:"clamp",black:"clamp"},X={specular_weight:"specularIntensity",specular_color:"specularColor",specular_ior:"ior",transmission_weight:"transmission",transmission_color:"attenuationColor",transmission_depth:"attenuationDistance",coat_weight:"clearcoat",coat_roughness:"clearcoatRoughness",fuzz_color:"sheenColor",fuzz_roughness:"sheenRoughness",specular_roughness_anisotropy:"anisotropy"},Q={base_weight:1,base_color:[.8,.8,.8],base_metalness:0,specular_roughness:.3,geometry_opacity:1,emission_color:[1,1,1]},J=e=>"fallback"===(null===e||void 0===e?void 0:e.kind)&&!(null===e||void 0===e||!e.openpbr);function $(e){var t,o,n,r;const s=e&&e.openpbr||{},a=e&&e.simready||{},l=e&&e.maps||{},i={name:(null===e||void 0===e?void 0:e.path)||"",color:[...(null===e||void 0===e?void 0:e.color)||[1,1,1]],opacity:null!==(t=null===e||void 0===e?void 0:e.opacity)&&void 0!==t?t:1,roughness:null!==(o=null===e||void 0===e?void 0:e.roughness)&&void 0!==o?o:1,metalness:null!==(n=null===e||void 0===e?void 0:e.metallic)&&void 0!==n?n:1,emissive:[...(null===e||void 0===e?void 0:e.emissive)||[0,0,0]],emissiveIntensity:1,alphaMode:"OPAQUE",alphaTest:0,transparent:!1,depthWrite:!0,doubleSided:null,normalScale:1,aoMapIntensity:1,physical:{},maps:{},gaps:[]},c=(e,t)=>{i.maps[e]={path:t.path,role:E(e),wrap:[V[t.wrapS]||"repeat",V[t.wrapT]||"repeat"],matrix:q(t)};const o=R[e];o&&t.channel!==o&&i.gaps.push("".concat(e," reads ").concat(t.channel,", three samples ").concat(o))},u=e=>e.channel in P?e.scale[P[e.channel]]:e.scale[0],d=l.diffuseColor;let p=!1;for(const[v,g]of Object.entries(l)){const t=k[v];t&&g&&g.path?(g.uvSet&&"st"!==g.uvSet&&i.gaps.push("".concat(v," samples primvar ").concat(g.uvSet,", not st")),"diffuseColor"===v?(i.color=[0,1,2].map(t=>{var o,n;return(null!==(o=null===(n=e.color)||void 0===n?void 0:n[t])&&void 0!==o?o:1)*g.scale[t]}),c(t,g)):"emissiveColor"===v?(i.emissive=[0,1,2].map(e=>g.scale[e]),c(t,g)):"roughness"===v?(i.roughness=u(g),c(t,g)):"metallic"===v?(i.metalness=u(g),c(t,g)):"occlusion"===v?(i.aoMapIntensity=u(g),c(t,g)):"normal"===v?(O(g.scale[0],2)&&O(g.bias[0],-1)||i.gaps.push("normal map not at scale 2 / bias -1"),c(t,g)):"opacity"===v&&(p=!0,i.opacity=u(g),d&&d.path===g.path&&"a"===g.channel||c(t,g)),"normal"!==v&&"occlusion"!==v&&g.bias&&g.bias.some(e=>!O(e,0))&&i.gaps.push("".concat(v," has a bias"))):i.gaps.push("".concat(v,": no three.js map"))}const m=J(e),h=new Set(e&&e.openpbrTextured||[]);if(m){const t=(e,t)=>t(s[e])?s[e]:Q[e],o=e=>"number"===typeof e,n=e=>Array.isArray(e)&&3===e.length,r=t("base_weight",o);i.color=t("base_color",n).map(e=>e*r),i.metalness=t("base_metalness",o),i.roughness=t("specular_roughness",o),i.opacity=t("geometry_opacity",o);const a=void 0!==s.emission_color||s.emission_luminance>0;i.emissive=a?[...t("emission_color",n)]:[0,0,0],p=h.has("geometry_opacity");for(const e of h)Object.hasOwn(Q,e)&&i.gaps.push("".concat(e,": its map is not read (factor only)"));"number"===typeof e.normalScale&&i.gaps.push("geometry_normal: its map is not read")}i.alphaMode=a.alphaMode||((null===e||void 0===e?void 0:e.opacityThreshold)>0?"MASK":p||i.opacity<1?"BLEND":"OPAQUE"),"MASK"===i.alphaMode&&(i.alphaTest=null!==(r=a.alphaCutoff)&&void 0!==r?r:(null===e||void 0===e?void 0:e.opacityThreshold)>0?e.opacityThreshold:.5),"BLEND"===i.alphaMode&&(i.transparent=!0,i.depthWrite=!1),"boolean"===typeof a.doubleSided&&(i.doubleSided=a.doubleSided),"number"===typeof(null===e||void 0===e?void 0:e.normalScale)&&(i.normalScale=e.normalScale),"number"===typeof a.occlusionStrength&&(i.aoMapIntensity=a.occlusionStrength);for(const[v,g]of Object.entries(X))void 0!==s[v]&&(i.physical[g]=s[v]);for(const v of h)X[v]&&i.gaps.push("".concat(v,": its map is not read (factor only)"));s.fuzz_weight>0&&(i.physical.sheen=1),"number"===typeof a.thickness&&(i.physical.thickness=a.thickness),s.geometry_thin_walled&&(i.physical.thickness=0),"number"===typeof a.anisotropyRotation&&(i.physical.anisotropyRotation=a.anisotropyRotation);const f=s.emission_luminance;return"number"===typeof f&&f>0&&(i.emissiveIntensity=f,m||(i.emissive=i.emissive.map(e=>e/f))),i}function Z(e){const t=(e||[]).filter(e=>"fallback"===(null===e||void 0===e?void 0:e.kind)&&e.path&&!J(e));return t.length?{code:"material-fallback",path:t[0].path,message:"".concat(t.length," material(s) have no ")+"UsdPreviewSurface, OpenPBR surface or supported MDL material and show as grey"}:null}function ee(e){var t;const o=[];return null!==e&&void 0!==e&&e.openpbr||o.push("openpbr: specular weight/colour, ior, transmission, coat, fuzz, anisotropy, emission luminance"),null!==e&&void 0!==e&&e.simready||o.push("simready: alphaMode, alphaCutoff, doubleSided, occlusionStrength, thickness, anisotropyRotation"),"number"!==typeof(null===e||void 0===e?void 0:e.normalScale)&&null!==e&&void 0!==e&&null!==(t=e.maps)&&void 0!==t&&t.normal&&o.push("normal scale"),o}let te=null,oe=null,ne=null,re=null,se=0;function ae(e){re&&ue(re),re=null,oe=null,ne=null,te=e||null}const le=()=>!!te;function ie(){if(!te)return Promise.reject(new f("reader","webUsdLoader: no reader set"));if(!oe){const e=performance.now(),t=te,o=Promise.resolve().then(()=>t.compile?t.compile():async function(e){const t=await fetch(e);if(!t.ok)throw new Error("HTTP ".concat(t.status));const o=await t.arrayBuffer();if(!(0,s.Hr)(o))throw new Error("not WebAssembly (a page served in its place?)");return WebAssembly.compile(o)}(t.wasmUrl)).then(t=>(ne=performance.now()-e,t)).catch(e=>{throw w("reader","webUsdLoader: could not compile the reader's WASM: ".concat((null===e||void 0===e?void 0:e.message)||e),{cause:e,url:t.wasmUrl&&String(t.wasmUrl)})});o.catch(()=>{oe===o&&(oe=null)}),oe=o}return oe}function ce(){let e;try{e=te.createWorker?te.createWorker():new Worker(te.workerUrl,{type:"module"})}catch(t){throw w("reader","webUsdLoader: could not start the reader's worker: ".concat((null===t||void 0===t?void 0:t.message)||t),{cause:t})}return se+=1,{worker:e,dead:!1,ready:Promise.resolve(!0)}}function ue(e){e&&!e.dead&&(e.dead=!0,e.worker.onmessage=null,e.worker.onerror=null,e.worker.terminate())}const de={fetch:"fetch",compose:"compose",aborted:"aborted",worker:"reader"};function pe(e,t,o,n){let r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:{};return new Promise((s,a)=>{const{worker:l}=e;let i=0,c=!1;r.posted=!1;const u=t=>{c||(c=!0,null===n||void 0===n||n.removeEventListener("abort",d),l.onmessage=null,l.onerror=null,t?(r.posted&&ue(e),a(t)):s(i))};function d(){u(new f("aborted","webUsdLoader: the load was aborted",{url:t.url}))}if(null!==n&&void 0!==n&&n.aborted)d();else{null===n||void 0===n||n.addEventListener("abort",d,{once:!0}),l.onmessage=e=>{var t,n,r;let{data:s}=e;if(!c&&s)if("texture"===s.type&&(null===(t=s.bitmap)||void 0===t||null===(n=t.close)||void 0===n||n.call(t)),"scene"===s.type&&(i=(null===(r=s.stats)||void 0===r?void 0:r.wasmMemoryBytes)||0),"done"!==s.type)if("error"!==s.type)try{o(s)}catch(a){u(v(a)?a:new f("compose","webUsdLoader: could not build the scene: ".concat((null===a||void 0===a?void 0:a.message)||a),{cause:a}))}else u(new f(de[s.code]||"compose","webUsdLoader: ".concat(s.message),{url:s.url,status:s.status}));else u(null)},l.onerror=e=>{var t;null===e||void 0===e||null===(t=e.preventDefault)||void 0===t||t.call(e),u(w("reader","webUsdLoader: the reader's worker failed: ".concat((null===e||void 0===e?void 0:e.message)||"error")))};try{l.postMessage(t),r.posted=!0}catch(p){u(new f("reader","webUsdLoader: could not post to the reader's worker: ".concat((null===p||void 0===p?void 0:p.message)||p),{cause:p}))}}})}function me(e,t){e.dead||(re||t>m?ue(e):re=e)}let he=null;function fe(){if(!te)return Promise.resolve(!1);if(re){const e=re;return e.ready.then(t=>t&&!e.dead)}if(he)return he;const e=ie().then(e=>{if(re)return re.ready;const t=ce();return t.ready=pe(t,(e=>({url:p+d,wasmModule:e,textures:h,files:new Map([[d,new Blob(['#usda 1.0\n(\n defaultPrim = "Asset"\n)\n\ndef Xform "Asset"\n{\n}\n'],{type:"text/plain"})]])}))(e),()=>{}).then(()=>!0,()=>(re===t&&(re=null),ue(t),!1)),re=t,t.ready}).catch(()=>!1).finally(()=>{he===e&&(he=null)});return he=e,e}function ve(e){let{ktx2:t,fetchFn:o,headers:n,signal:r,t0:s}=e;const a=new Map;let l=null;const i=(e,i)=>{const c=x(e);if(a.has(c))return a.get(c);const u={url:e,hinted:i,used:!1,startMs:performance.now()-s,readyMs:null,texture:null,error:null,derived:new Map};return u.promise=Promise.all([(l||(l=Promise.resolve("function"===typeof t?t():t).then(e=>{if(!e)throw new f("textures","webUsdLoader: maps need the page's KTX2 loader");return e})),l),Promise.resolve(o(e,{signal:r,headers:n,credentials:"same-origin"})).then(t=>{if(!t.ok)throw new f("textures","webUsdLoader: map ".concat(e,": HTTP ").concat(t.status),{url:e,status:t.status});return t.arrayBuffer()})]).then(e=>{let[t,o]=e;return((e,t)=>new Promise((o,n)=>e.parse(t,o,n)))(t,o)}).then(e=>(u.texture=e,u.readyMs=performance.now()-s,e)).catch(t=>{throw u.error=v(t)?t:new f(null!==r&&void 0!==r&&r.aborted?"aborted":"textures","webUsdLoader: map ".concat(e,": ").concat((null===t||void 0===t?void 0:t.message)||t),{cause:t,url:e}),u.error}),u.promise.catch(()=>{}),a.set(c,u),u};return{files:a,start:i,use(e){const t=i(e,!1);return t.used=!0,t},settle:()=>Promise.all([...a.values()].filter(e=>e.used).map(e=>e.promise)),texture(e,t,o,n,r){const s=a.get(x(t)),l=s.texture,i="color"===o?e.SRGBColorSpace:e.NoColorSpace,c=t=>"mirror"===t?e.MirroredRepeatWrapping:"clamp"===t?e.ClampToEdgeWrapping:e.RepeatWrapping,u="".concat(i,"|").concat(n.join(","),"|").concat(r?r.join(","):"");if(s.derived.size||(l.flipY=!1,l.colorSpace=i,l.magFilter=e.LinearFilter,l.minFilter=e.LinearMipmapLinearFilter,l.wrapS=c(n[0]),l.wrapT=c(n[1]),r&&(l.matrixAutoUpdate=!1,l.matrix.set(...r)),l.needsUpdate=!0,s.derived.set(u,l)),!s.derived.has(u)){const e=l.clone();e.colorSpace=i,e.wrapS=c(n[0]),e.wrapT=c(n[1]),e.matrixAutoUpdate=!r,r?e.matrix.set(...r):e.matrix.identity(),e.needsUpdate=!0,s.derived.set(u,e)}return s.derived.get(u)},all:()=>[...a.values()].flatMap(e=>[...e.derived.values()]),unused:()=>[...a.values()].filter(e=>!e.used&&e.texture).map(e=>e.texture)}}const ge=e=>"".concat((null===e||void 0===e?void 0:e.path)||""," ").concat((null===e||void 0===e?void 0:e.message)||"").includes(c);function we(e,t){let{maps:o,base:r,tier:s,compact:l=null,normals:i="int8"}=t;const c=new e.Group;c.name="usd";const u=new Map,d=[],p=new Map,m=[],h=[];let f=null,v=[],g=new Map,w=!1;const b={meshes:0,triangles:0,loose:0},y={compact:!1,geometries:0,position:0,normal:0,uv:0,floatBytes:0,uploadBytes:0,ms:0},S=t=>{if(!u.has(t)){const o=new e.Group;o.name=t,u.set(t,o),c.add(o)}return u.get(t)},L=function(t,o,n){let s=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null;const a=v[t],l=s&&Object.keys(a.maps).length?s.join(","):"",i="".concat(t,"|").concat(o,"|").concat(n,"|").concat(l);if(!p.has(i)){const t=function(e,t,o){var n;let r=!(arguments.length>3&&void 0!==arguments[3])||arguments[3];const s=new e.MeshPhysicalMaterial;s.name=t.name,s.color.setRGB(t.color[0],t.color[1],t.color[2],e.LinearSRGBColorSpace),s.opacity=t.opacity,s.roughness=t.roughness,s.metalness=t.metalness,s.emissive.setRGB(t.emissive[0],t.emissive[1],t.emissive[2],e.LinearSRGBColorSpace),s.emissiveIntensity=t.emissiveIntensity,s.transparent=t.transparent,s.depthWrite=t.depthWrite,s.alphaTest=t.alphaTest,s.side=(null!==(n=t.doubleSided)&&void 0!==n?n:o)?e.DoubleSide:e.FrontSide,s.normalScale.set(t.normalScale,r?-t.normalScale:t.normalScale),r&&(s.clearcoatNormalScale.y*=-1),s.aoMapIntensity=t.aoMapIntensity;for(const[l,i]of Object.entries(t.physical)){var a;null!==(a=s[l])&&void 0!==a&&a.isColor&&Array.isArray(i)?s[l].setRGB(i[0],i[1],i[2],e.LinearSRGBColorSpace):"number"===typeof i&&(s[l]=i)}return s}(e,a,o,n);for(const[e,o]of Object.entries(a.maps)){const n=l?o.matrix?H(o.matrix,s).map(e=>e+0):s:o.matrix;m.push([t,e,U(o.path,r),o.role,o.wrap,n])}p.set(i,t)}return p.get(i)};let x=null;return{root:c,bodies:u,geometries:d,materials:p,warnings:h,receive:t=>{if("meta"===t.type)(e=>{f=e.meta,w=I(l,f),y.compact=w,v=(f.materials||[]).map($);for(const t of v){for(const e of t.gaps)h.push({code:"material",message:"".concat(t.name,": ").concat(e)});for(const e of Object.values(t.maps))o.use(U(e.path,r))}g=new Map;for(const t of f.instances||[]){const e=M(t.path);e&&S(e.body),g.has(t.geometry)||g.set(t.geometry,[]),g.get(t.geometry).push(t)}for(const t of f.warnings||[])if("material-fallback"===t.code){const e=Z(f.materials);e&&h.push(e)}else ge(t)||h.push(t)})(t);else if("geometry"===t.type)(t=>{var o;let{index:n,meta:r,arrays:s}=t;if(!r)return;if(!s)throw new Error("a geometry without its arrays");const a=new e.BufferGeometry,l=performance.now(),u=Y(s,w,i);y.ms+=performance.now()-l;const p=u.positionLattice;let m=null;if(p){a.setAttribute("position",new e.InterleavedBufferAttribute(new e.InterleavedBuffer(p.array,4),3,0,!1));const t=2**p.k;m=(new e.Matrix4).makeScale(t,t,t).setPosition(p.offset[0]*t,p.offset[1]*t,p.offset[2]*t),a.boundingBox=new e.Box3(new e.Vector3(...p.min),new e.Vector3(...p.max))}else a.setAttribute("position",new e.BufferAttribute(u.position,3)),a.boundingBox=(new e.Box3).setFromArray(r.bounds);null!==(o=u.normal)&&void 0!==o&&o.bits?a.setAttribute("normal",new e.InterleavedBufferAttribute(new e.InterleavedBuffer(u.normal.array,4),3,0,!0)):u.normal&&a.setAttribute("normal",new e.BufferAttribute(u.normal,3)),u.uvs.forEach((t,o)=>a.setAttribute(o?"uv".concat(o):"uv",new e.BufferAttribute(t.array||t,2,!1)));const f=u.uvLattice?F(u.uvLattice):null;var v;a.setIndex(new e.BufferAttribute(s.indices,1)),a.boundingSphere=a.boundingBox.getBoundingSphere(new e.Sphere),w&&(y.geometries+=1,y.position+=p?1:0,y.normal+=null!==(v=u.normal)&&void 0!==v&&v.bits?1:0,y.uv+=f?1:0),y.floatBytes+=u.bytes.float,y.uploadBytes+=u.bytes.upload,r.groups.length>1&&r.groups.forEach((e,t)=>{let[o,n]=e;return a.addGroup(o,n,t)}),r.hasColors&&h.push({code:"vertex-colors",message:"geometry ".concat(n,": vertex colours ignored")}),d.push(a);const x=r.groups.reduce((e,t)=>{let[,o]=t;return e+o/3},0),A=void 0===a.attributes.tangent;for(const i of g.get(n)||[]){const t=r.groups.map(e=>{let[,,t]=e;return L(void 0!==t&&Object.hasOwn(i.subsets||{},t)?i.subsets[t]:i.material,!!i.doubleSided,A,f)}),o=new e.Mesh(a,t.length>1?t:t[0]),n=M(i.path);o.name=n?n.name:i.path.split("/").pop(),o.matrix.fromArray(i.matrix),m&&o.matrix.multiply(m),o.matrix.decompose(o.position,o.quaternion,o.scale),n?S(n.body).add(o):(b.loose+=1,c.add(o)),b.meshes+=1,b.triangles+=x}})(t);else if("scene"===t.type){const e=t.stats||{},{warnings:o}=e,r=(0,n.A)(e,a);x=r;for(const t of o||[])ge(t)||h.push(t)}},attachMaps:()=>{for(const[t,n,r,s,a,l]of m)t[n]=o.texture(e,r,s,a,l);for(const e of p.values())e.needsUpdate=!0},counts:b,attrs:y,stats:()=>x,meta:()=>f,tier:s}}async function be(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const{tier:n=1,ktx2:s=null,ktx2Hint:a=null,signal:i=null,headers:c,onStage:d=null,compact:m=null,normals:g="int8"}=t,w=t.fetchFn||function(){return fetch(...arguments)},b=performance.now(),y={},M=e=>{y[e]=Math.round(10*(performance.now()-b))/10,null===d||void 0===d||d(e,y[e])};if(!te)throw new f("reader","webUsdLoader: no reader set");if(null!==i&&void 0!==i&&i.aborted)throw new f("aborted","webUsdLoader: the load was aborted",{url:e});const x=new URL(e,"undefined"===typeof window?void 0:window.location.href).href,U=new AbortController,k=()=>U.abort(i.reason);null===i||void 0===i||i.addEventListener("abort",k,{once:!0});const R=ve({ktx2:s,fetchFn:w,headers:c,signal:U.signal,t0:b});for(const o of _(a,x).values())R.start(o,!0);a&&M("hintStarted");const B=L(n),E=Promise.all(B.map(e=>async function(e,t,o){let n,{signal:r,headers:s}=o;try{n=await e(t,{signal:r,headers:s,credentials:"same-origin"})}catch(a){throw new f(null!==r&&void 0!==r&&r.aborted?"aborted":"fetch","webUsdLoader: ".concat(t,": ").concat((null===a||void 0===a?void 0:a.message)||a),{cause:a,url:t})}if(!n.ok)throw new f("fetch","webUsdLoader: ".concat(t,": HTTP ").concat(n.status),{url:t,status:n.status});return n.blob()}(w,e===l?x:A(e,x),{signal:U.signal,headers:c})));E.catch(()=>{});const C=Promise.all([o.e(435),o.e(408)]).then(o.bind(o,408)),O=null===ne,P=async function(){const e=await ie(),t=re;return re=null,t&&(await t.ready,!t.dead)?{slot:t,module:e}:{slot:ce(),module:e}}();P.catch(()=>{});let T=null,I=!1;const W={posted:!1};let j=null;const z=()=>{if(U.signal.aborted)throw new f("aborted","webUsdLoader: the load was aborted",{url:e})};try{const[{slot:t,module:o},s,a]=await Promise.all([P,E,C]);T=t,I=!0,O&&null!==ne&&(y.wasmCompile=Math.round(10*ne)/10),M("ready"),z(),j=we(a,{maps:R,base:x,tier:n,compact:m,normals:g});const l=new Map([[u,new Blob([S(n)],{type:"text/plain"})]]);B.forEach((e,t)=>l.set(e,s[t]));const i={url:p+u,wasmModule:o,textures:h,files:l};if(me(T,await pe(T,i,j.receive,U.signal,W)),T=null,M("geometry"),z(),!j.bodies.size)throw new f("shape","webUsdLoader: no piece under /Asset/Bodies",{url:e});await R.settle(),z(),M("textures"),z(),j.attachMaps();for(const e of R.unused())e.dispose();M("total"),z();const c=j.stats()||{},d=R.all(),v=[...R.files.values()],w=()=>{j.geometries.forEach(e=>e.dispose());for(const e of j.materials.values())e.dispose();d.forEach(e=>e.dispose())};return{scene:j.root,bodies:j.bodies,materials:[...j.materials.values()],textures:d,info:{tier:n,meshes:j.counts.meshes,triangles:j.counts.triangles,loose:j.counts.loose,bodies:j.bodies.size,geometries:j.geometries.length,materials:j.materials.size,maps:v.filter(e=>e.used).length,hinted:v.filter(e=>e.hinted).length,hintMissed:v.filter(e=>e.used&&!e.hinted).length,hintUnused:v.filter(e=>!e.used).length,mapFiles:v.map(e=>({url:e.url,hinted:e.hinted,used:e.used,startMs:Math.round(e.startMs),readyMs:null===e.readyMs?null:Math.round(e.readyMs)})),reader:c,warnings:j.warnings,attributes:(0,r.A)((0,r.A)({},j.attrs),{},{ms:Math.round(10*j.attrs.ms)/10})},timings:y,dispose:w}}catch(D){if(U.abort(),T?W.posted?ue(T):me(T,0):I||P.then(e=>me(e.slot,0),()=>{}),j){j.geometries.forEach(e=>e.dispose());for(const e of j.materials.values())e.dispose()}const t=new Set(R.all());if(R.files.forEach(e=>{e.texture?t.add(e.texture):e.promise.then(e=>e.dispose(),()=>{})}),t.forEach(e=>e.dispose()),v(D))throw D;throw new f(null!==i&&void 0!==i&&i.aborted?"aborted":"compose","webUsdLoader: ".concat((null===D||void 0===D?void 0:D.message)||D),{cause:D,url:e})}finally{null===i||void 0===i||i.removeEventListener("abort",k)}}function ye(){ae(null),he=null,se=0,g=null}const Me=()=>({spawned:se,kept:!!re,compiled:!!oe})}}]);
services/explorer/dist/static/js/main.cf692f87.js ADDED
The diff for this file is too large to render. See raw diff
 
services/explorer/dist/static/js/main.cf692f87.js.LICENSE.txt ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * @license React
3
+ * react-dom.production.min.js
4
+ *
5
+ * Copyright (c) Facebook, Inc. and its affiliates.
6
+ *
7
+ * This source code is licensed under the MIT license found in the
8
+ * LICENSE file in the root directory of this source tree.
9
+ */
10
+
11
+ /**
12
+ * @license React
13
+ * react-jsx-runtime.production.min.js
14
+ *
15
+ * Copyright (c) Facebook, Inc. and its affiliates.
16
+ *
17
+ * This source code is licensed under the MIT license found in the
18
+ * LICENSE file in the root directory of this source tree.
19
+ */
20
+
21
+ /**
22
+ * @license React
23
+ * react.production.min.js
24
+ *
25
+ * Copyright (c) Facebook, Inc. and its affiliates.
26
+ *
27
+ * This source code is licensed under the MIT license found in the
28
+ * LICENSE file in the root directory of this source tree.
29
+ */
30
+
31
+ /**
32
+ * @license React
33
+ * scheduler.production.min.js
34
+ *
35
+ * Copyright (c) Facebook, Inc. and its affiliates.
36
+ *
37
+ * This source code is licensed under the MIT license found in the
38
+ * LICENSE file in the root directory of this source tree.
39
+ */
services/explorer/dist/static/usd-reader/79236f8/esm/errors.js ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /** Why a load failed: `aborted`, `fetch` (root layer or a resource limit), `compose`, `worker` or `webgl`. */
2
+ export class UsdLoadError extends Error {
3
+ name = "UsdLoadError";
4
+ code;
5
+ constructor(code, message, { url, status, cause } = {}) {
6
+ super(message, cause === undefined ? undefined : { cause });
7
+ this.code = code;
8
+ if (url !== undefined) {
9
+ this.url = url;
10
+ }
11
+ if (status !== undefined) {
12
+ this.status = status;
13
+ }
14
+ }
15
+ }
services/explorer/dist/static/usd-reader/79236f8/esm/hub-prefetch.js ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // The layers of a Hub package, listed with one tree-API call, so a load can
2
+ // request them all at once instead of discovering them a round trip at a time.
3
+ const RESOLVE = /^(https:\/\/(?:huggingface\.co|hf\.co))\/((?:datasets\/|spaces\/)?)([^/?#]+\/[^/?#]+)\/resolve\/([^/?#]+)\/([^?#]+)$/;
4
+ const LAYER = /\.(usd|usda|usdc)$/i;
5
+ const SIMREADY_PACKAGE = "com.nvidia.simready.packaging.json";
6
+ const MAX_FILES = 256;
7
+ const MAX_BYTES = 64 * 2 ** 20;
8
+ /**
9
+ * The USD layers of the package holding a Hub `resolve` URL, as `{ url, size }`:
10
+ * the directory with a SimReady packaging manifest among the root's parent
11
+ * and grandparent, else everything under the root's own directory. `eager`
12
+ * when a manifest declares the package, so its layers are worth requesting
13
+ * before the root is read. No layers, without a request, for a root at the
14
+ * top of its repo or any other URL, and none if the listing fails: the load then discovers layers as usual.
15
+ */
16
+ export async function hubPackageLayers(rootUrl, request) {
17
+ const match = rootUrl.split(/[?#]/)[0].match(RESOLVE);
18
+ const none = { layers: [], eager: false };
19
+ if (!match) {
20
+ return none;
21
+ }
22
+ const [, origin, prefix, repo, revision, path] = match;
23
+ const parent = path.split("/").slice(0, -1);
24
+ // A root at the top of a repo would list, and preload, the whole repo.
25
+ if (!parent.length) {
26
+ return none;
27
+ }
28
+ const listed = parent.length > 1 ? parent.slice(0, -1) : parent;
29
+ try {
30
+ const response = await request(`${origin}/api/${prefix || "models/"}${repo}/tree/${revision}/${listed.join("/")}?recursive=true`);
31
+ if (!response.ok) {
32
+ return none;
33
+ }
34
+ const entries = await response.json();
35
+ const decoded = parent.map(decodeURIComponent);
36
+ const manifest = [decoded, decoded.slice(0, -1)].find((dir) => dir.length >= listed.length && entries.some((e) => e.path === [...dir, SIMREADY_PACKAGE].join("/")));
37
+ const depth = (manifest ?? decoded).length;
38
+ const packageDir = decoded
39
+ .slice(0, depth)
40
+ .map((name) => name + "/")
41
+ .join("");
42
+ // As the root spells it, so URLs match the ones composition resolves.
43
+ const base = `${origin}/${prefix}${repo}/resolve/${revision}/${parent
44
+ .slice(0, depth)
45
+ .map((name) => name + "/")
46
+ .join("")}`;
47
+ const layers = [];
48
+ let bytes = 0;
49
+ for (const { type, path: file, size } of entries) {
50
+ if (type !== "file" || !file.startsWith(packageDir) || !LAYER.test(file)) {
51
+ continue;
52
+ }
53
+ if (layers.length >= MAX_FILES || bytes + size > MAX_BYTES) {
54
+ continue;
55
+ }
56
+ bytes += size;
57
+ layers.push({
58
+ url: new URL(file.slice(packageDir.length).replace(/[%#?]/g, encodeURIComponent), base).href,
59
+ size,
60
+ });
61
+ }
62
+ return { layers, eager: !!manifest };
63
+ }
64
+ catch {
65
+ return none;
66
+ }
67
+ }
68
+ /**
69
+ * A Hub `resolve` URL pinned to the commit its branch or tag points at now,
70
+ * so every layer and texture of one load (all resolved against the root)
71
+ * comes from the same commit even if the repo is pushed to meanwhile. Unchanged,
72
+ * without a request, for a commit or any other URL, and if the lookup fails.
73
+ */
74
+ export async function pinHubRevision(rootUrl, request) {
75
+ const match = rootUrl.split(/[?#]/)[0].match(RESOLVE);
76
+ if (!match) {
77
+ return rootUrl;
78
+ }
79
+ const [, origin, prefix, repo, revision] = match;
80
+ if (/^[0-9a-f]{40}$/.test(revision)) {
81
+ return rootUrl;
82
+ }
83
+ try {
84
+ const response = await request(`${origin}/api/${prefix || "models/"}${repo}/revision/${revision}?expand%5B%5D=sha`);
85
+ const { sha } = response.ok ? await response.json() : {};
86
+ if (!/^[0-9a-f]{40}$/.test(sha ?? "")) {
87
+ return rootUrl;
88
+ }
89
+ return rootUrl.replace(`/resolve/${revision}/`, `/resolve/${sha}/`);
90
+ }
91
+ catch {
92
+ return rootUrl;
93
+ }
94
+ }
services/explorer/dist/static/usd-reader/79236f8/esm/load-core.js ADDED
@@ -0,0 +1,744 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { UsdLoadError } from "./errors.js";
2
+ /** The load options' defaults, and the largest image side read at all. SECURITY.md documents the limits. */
3
+ export const DEFAULTS = {
4
+ textures: "preview",
5
+ maxTextureSize: 1024,
6
+ maxConcurrentFetches: 16,
7
+ maxLayerBytes: 768 * 2 ** 20,
8
+ maxLayers: 1024,
9
+ maxInstances: 100000,
10
+ maxTriangles: 20e6,
11
+ maxTextureBytes: 512 * 2 ** 20,
12
+ maxImageSize: 16384,
13
+ };
14
+ /** Loads and composes the stage at `rootUrl`. */
15
+ export async function composeStage({ UsdLoader, fetchBytes, rootUrl, maxConcurrentFetches = DEFAULTS.maxConcurrentFetches, maxLayerBytes = DEFAULTS.maxLayerBytes, maxLayers = DEFAULTS.maxLayers, maxInstances = DEFAULTS.maxInstances, allowedOrigins, preload, onProgress = () => { }, }) {
16
+ const root = rootUrl.split(/[?#]/)[0];
17
+ const urlOf = (path) => (path === root ? rootUrl : path);
18
+ const loader = new UsdLoader();
19
+ const stats = {
20
+ layers: 0,
21
+ layerBytes: 0,
22
+ missing: 0,
23
+ rounds: 0,
24
+ fetchMs: 0,
25
+ parseMs: 0,
26
+ composeMs: 0,
27
+ warnings: [],
28
+ };
29
+ const started = new Map();
30
+ const progress = () => onProgress({ stage: "layers", loaded: stats.layers + stats.missing, total: started.size, bytes: stats.layerBytes });
31
+ const throttle = limiter(maxConcurrentFetches);
32
+ // One budget for every layer body, charged as its bytes arrive, so fetches
33
+ // in parallel cannot each count on the whole remainder.
34
+ let heldBytes = 0;
35
+ const charge = (bytes, path) => {
36
+ heldBytes += bytes;
37
+ if (heldBytes > maxLayerBytes) {
38
+ throw resourceLimit(`layers exceed maxLayerBytes (${maxLayerBytes} bytes) at ${path}`);
39
+ }
40
+ };
41
+ // Re-fetched layers replace their earlier bytes, so count each path once.
42
+ const layerSizes = new Map();
43
+ // Speculative fetches by URL, dropped once composition is done. One that
44
+ // has not started when its layer is asked for, or that failed, gives way to
45
+ // the regular fetch, so the result is the same as without them. Their
46
+ // bytes are charged as they arrive, and stay charged once used.
47
+ const preloaded = new Map();
48
+ let composed = false;
49
+ // Every distinct layer URL requested, preloads included, for maxLayers.
50
+ const requested = new Set();
51
+ const startPreload = (layers) => {
52
+ let bytes = 0;
53
+ for (const { url, size } of layers) {
54
+ const key = urlKey(url);
55
+ bytes += size;
56
+ if (composed || bytes > maxLayerBytes) {
57
+ break;
58
+ }
59
+ if (requested.has(key)) {
60
+ continue;
61
+ }
62
+ if (requested.size >= maxLayers) {
63
+ break;
64
+ }
65
+ requested.add(key);
66
+ const entry = { started: false, charged: 0 };
67
+ preloaded.set(key, entry);
68
+ // Unused once composed: the next chunk cancels the body.
69
+ const budget = (bytes) => {
70
+ if (composed) {
71
+ throw new Error("composed without it");
72
+ }
73
+ entry.charged += bytes;
74
+ charge(bytes, url);
75
+ };
76
+ entry.bytes = throttle(async () => {
77
+ if (composed || preloaded.get(key) !== entry) {
78
+ return null;
79
+ }
80
+ entry.started = true;
81
+ const bytes = await fetchBytes(url, budget);
82
+ if (bytes) {
83
+ budget(bytes.byteLength - entry.charged);
84
+ }
85
+ return bytes;
86
+ }, { later: true }).catch(() => {
87
+ heldBytes -= entry.charged;
88
+ entry.charged = 0;
89
+ return null;
90
+ });
91
+ }
92
+ };
93
+ const takePreloaded = (path) => {
94
+ const entry = preloaded.get(urlKey(path));
95
+ preloaded.delete(urlKey(path));
96
+ return entry?.started ? entry : null;
97
+ };
98
+ // Jobs in flight. A job queues its dependencies here rather than awaiting
99
+ // them, so layers that reference each other cannot wait on each other.
100
+ const pending = [];
101
+ const drain = async () => {
102
+ while (pending.length) {
103
+ await Promise.all(pending.splice(0));
104
+ }
105
+ };
106
+ const fetchLayer = (path) => {
107
+ if (loader.has(path) || started.has(path)) {
108
+ return;
109
+ }
110
+ requested.add(urlKey(path));
111
+ if (requested.size > maxLayers) {
112
+ throw resourceLimit(`more than maxLayers (${maxLayers}) layer files at ${path}`);
113
+ }
114
+ const { refused } = requestPolicy(urlOf(path), rootUrl, allowedOrigins);
115
+ if (refused) {
116
+ started.set(path, Promise.resolve());
117
+ stats.missing++;
118
+ stats.warnings.push({ code: "layer-missing", message: `layer not fetched: ${refused}`, path });
119
+ loader.markUnavailable(path);
120
+ progress();
121
+ return;
122
+ }
123
+ const job = (async () => {
124
+ const t0 = performance.now();
125
+ heldBytes -= layerSizes.get(path) ?? 0;
126
+ layerSizes.delete(path);
127
+ let charged = 0;
128
+ const budget = (bytes) => {
129
+ charged += bytes;
130
+ charge(bytes, path);
131
+ };
132
+ // Any fetch failure, HTTP or network: the root fails the load, any
133
+ // other layer is left out with a warning.
134
+ let bytes = null;
135
+ let failure = null;
136
+ try {
137
+ const entry = takePreloaded(path);
138
+ bytes = entry && (await entry.bytes);
139
+ if (entry && bytes) {
140
+ charged = entry.charged;
141
+ }
142
+ bytes ??= await throttle(() => fetchBytes(urlOf(path), budget));
143
+ }
144
+ catch (error) {
145
+ heldBytes -= charged;
146
+ // HTTP errors carry a status; network errors are TypeErrors (as from fetch).
147
+ if (error?.status === undefined && !(error instanceof TypeError)) {
148
+ throw error;
149
+ }
150
+ failure = error;
151
+ }
152
+ stats.fetchMs = Math.max(stats.fetchMs, performance.now() - t0);
153
+ if (!bytes) {
154
+ if (path === root) {
155
+ const status = failure?.status ?? (failure ? undefined : 404);
156
+ throw new UsdLoadError("fetch", `could not fetch ${rootUrl}${status ? ` (HTTP ${status})` : ""}`, {
157
+ url: rootUrl,
158
+ status,
159
+ cause: failure ?? undefined,
160
+ });
161
+ }
162
+ stats.missing++;
163
+ stats.warnings.push({
164
+ code: "layer-missing",
165
+ message: `layer not found: ${failure?.message ?? urlOf(path)}`,
166
+ path: urlOf(path),
167
+ });
168
+ loader.markUnavailable(path);
169
+ progress();
170
+ return;
171
+ }
172
+ charge(bytes.byteLength - charged, path);
173
+ layerSizes.set(path, bytes.byteLength);
174
+ stats.layers++;
175
+ stats.layerBytes += bytes.byteLength;
176
+ const t1 = performance.now();
177
+ let deps;
178
+ try {
179
+ deps = loader.addLayer(path, bytes);
180
+ }
181
+ catch (error) {
182
+ // After a trap the module is unusable: the load fails.
183
+ if (isTrap(error)) {
184
+ throw error;
185
+ }
186
+ // An unreadable layer is left out; composition carries on without it.
187
+ stats.warnings.push({
188
+ code: "layer-unreadable",
189
+ message: String(error.message || error),
190
+ path: urlOf(path),
191
+ });
192
+ loader.markUnavailable(path);
193
+ progress();
194
+ return;
195
+ }
196
+ finally {
197
+ stats.parseMs += performance.now() - t1;
198
+ }
199
+ progress();
200
+ for (const dep of deps) {
201
+ fetchLayer(dep);
202
+ }
203
+ })();
204
+ started.set(path, job);
205
+ pending.push(job);
206
+ };
207
+ fetchLayer(root);
208
+ // A root without dependencies needs nothing else from its directory.
209
+ const rootHasDependencies = () => (started.get(root) ?? Promise.resolve()).then(() => started.size > 1, () => false);
210
+ preload?.then(async ({ layers, eager }) => (eager || (await rootHasDependencies())) && startPreload(layers));
211
+ await drain();
212
+ if (!loader.has(root)) {
213
+ const reason = stats.warnings.find((w) => w.path === rootUrl)?.message;
214
+ throw new UsdLoadError("compose", `could not read ${rootUrl}${reason ? `: ${reason}` : ""}`, { url: rootUrl });
215
+ }
216
+ for (;;) {
217
+ stats.rounds++;
218
+ onProgress({ stage: "compose", round: stats.rounds });
219
+ const t0 = performance.now();
220
+ const missing = loader.compose(root, maxInstances);
221
+ stats.composeMs += performance.now() - t0;
222
+ if (!missing.length) {
223
+ break;
224
+ }
225
+ if (stats.rounds > 16) {
226
+ throw new UsdLoadError("compose", `composition still missing layers: ${missing.join(", ")}`);
227
+ }
228
+ // The list also names layers the failed attempt consumed; fetch them again.
229
+ for (const path of missing) {
230
+ started.delete(path);
231
+ }
232
+ missing.forEach(fetchLayer);
233
+ await drain();
234
+ }
235
+ composed = true;
236
+ const scene = loader.takeScene();
237
+ loader.free();
238
+ const meta = JSON.parse(scene.meta());
239
+ return { scene, meta, stats };
240
+ }
241
+ /**
242
+ * What the page is told about a failed load. Fetch and resource-limit errors
243
+ * keep their code, url and status; anything the WASM side throws is a
244
+ * composition failure. Running out of WASM memory (4 GiB at most) reads as a
245
+ * scene too large to load: an allocation that fails while reading a layer
246
+ * reports "out of memory", one that aborts traps as a bare `unreachable`. A
247
+ * Rust panic, which also traps as `unreachable`, gives its message instead,
248
+ * read with `lastPanic` (the module's export). Overflowing the stack, the WASM one (an
249
+ * out-of-bounds access) or the engine's, means layers nested too deeply to read.
250
+ */
251
+ export function loadFailure(error, wasmMemoryBytes, lastPanic) {
252
+ const { code = "compose", url, status } = (error ?? {});
253
+ const message = String(error?.message || error);
254
+ const failure = (detail) => ({ code, message: detail, url, status });
255
+ if (code !== "compose") {
256
+ return failure(message);
257
+ }
258
+ const tooLarge = () => failure(`scene too large to load: ran out of memory (${(wasmMemoryBytes / 2 ** 30).toFixed(1)} GiB of WebAssembly memory in use): ${message}`);
259
+ if (OUT_OF_MEMORY.test(message) || (error instanceof WebAssembly.RuntimeError && wasmMemoryBytes > 3 * 2 ** 30)) {
260
+ return tooLarge();
261
+ }
262
+ if (!isTrap(error)) {
263
+ return failure(message);
264
+ }
265
+ const panic = readPanic(lastPanic);
266
+ if (panic) {
267
+ return failure(`${message}: ${panic}`);
268
+ }
269
+ if (/out of bounds|call stack|recursion/i.test(message)) {
270
+ return failure(`stack overflow: the layers nest too deeply to read (${message})`);
271
+ }
272
+ // Rust aborts on a failed allocation without a panic: a bare `unreachable`.
273
+ if (/unreachable/i.test(message)) {
274
+ return tooLarge();
275
+ }
276
+ return failure(message);
277
+ }
278
+ /** Messages of allocations that failed, in Rust or in the engine. */
279
+ export const OUT_OF_MEMORY = /out of memory|memory allocation|allocation failed|memory size exceeded|could not allocate/i;
280
+ /** Reading the panic calls into the trapped module, which can trap again (an exhausted stack does). */
281
+ function readPanic(lastPanic) {
282
+ try {
283
+ return lastPanic?.();
284
+ }
285
+ catch {
286
+ return undefined;
287
+ }
288
+ }
289
+ /** A WebAssembly trap or an exhausted engine call stack: the module is no longer usable. */
290
+ function isTrap(error) {
291
+ return (error instanceof WebAssembly.RuntimeError ||
292
+ error instanceof RangeError ||
293
+ error?.name === "InternalError");
294
+ }
295
+ function resourceLimit(detail) {
296
+ return new UsdLoadError("fetch", `resource limit exceeded: ${detail}`);
297
+ }
298
+ /** Runs at most `max` of the given tasks at once; tasks marked `later` wait for the others. */
299
+ export function limiter(max) {
300
+ let active = 0;
301
+ const queue = [];
302
+ const later = [];
303
+ const next = () => {
304
+ if (active >= max) {
305
+ return;
306
+ }
307
+ const job = queue.shift() ?? later.shift();
308
+ if (!job) {
309
+ return;
310
+ }
311
+ active++;
312
+ const { task, resolve, reject } = job;
313
+ task()
314
+ .then(resolve, reject)
315
+ .finally(() => {
316
+ active--;
317
+ next();
318
+ });
319
+ };
320
+ return (task, { later: low = false } = {}) => new Promise((resolve, reject) => {
321
+ (low ? later : queue).push({ task, resolve: resolve, reject });
322
+ next();
323
+ });
324
+ }
325
+ /** A layer URL as fetch would spell it, so an authored `a b.usd` matches a listed `a%20b.usd`. */
326
+ function urlKey(url) {
327
+ try {
328
+ return new URL(url).href;
329
+ }
330
+ catch {
331
+ return url;
332
+ }
333
+ }
334
+ /**
335
+ * Fetches a body, passing each chunk's size to `budget` as it arrives and
336
+ * giving up (cancelling the body) when `budget` throws. An HTTP error throws a
337
+ * `fetch` UsdLoadError carrying the status. `fetchFn` is the global fetch or a
338
+ * stand-in with the same contract. Rate limiting (429) and server errors
339
+ * (5xx) are retried with backoff, as the Hub answers bursts with 429.
340
+ */
341
+ export async function fetchLimited(url, budget, { fetchFn = fetch, retries = 3, retryDelayMs = 500, } = {}) {
342
+ let response = await fetchFn(url);
343
+ for (let attempt = 0; attempt < retries && (response.status === 429 || response.status >= 500); attempt++) {
344
+ response.body?.cancel().catch(() => { });
345
+ const retryAfterMs = Number(response.headers?.get("retry-after")) * 1000;
346
+ const delay = retryAfterMs > 0 ? Math.min(retryAfterMs, 10_000) : retryDelayMs * 2 ** attempt * (1 + Math.random());
347
+ await new Promise((resolve) => setTimeout(resolve, delay));
348
+ response = await fetchFn(url);
349
+ }
350
+ if (!response.ok) {
351
+ throw new UsdLoadError("fetch", `HTTP ${response.status} for ${url}`, { url, status: response.status });
352
+ }
353
+ if (!response.body) {
354
+ return new Uint8Array();
355
+ }
356
+ const reader = response.body.getReader();
357
+ const chunks = [];
358
+ let size = 0;
359
+ for (;;) {
360
+ const { done, value } = await reader.read();
361
+ if (done) {
362
+ break;
363
+ }
364
+ try {
365
+ budget(value.byteLength);
366
+ }
367
+ catch (error) {
368
+ await reader.cancel();
369
+ throw error;
370
+ }
371
+ size += value.byteLength;
372
+ chunks.push(value);
373
+ }
374
+ const out = new Uint8Array(size);
375
+ let offset = 0;
376
+ for (const chunk of chunks) {
377
+ out.set(chunk, offset);
378
+ offset += chunk.byteLength;
379
+ }
380
+ return out;
381
+ }
382
+ /**
383
+ * Size of a PNG, JPEG or WebP from its header, without decoding, and whether
384
+ * it is color: 8-bit RGB(A) or palette, rather than greyscale or 16-bit data
385
+ * (the images `sourceColorSpace = "auto"` decodes as sRGB; WebP is always
386
+ * color). Null for other formats, whose size cannot be checked before decoding.
387
+ */
388
+ export function imageInfo(b) {
389
+ const v = new DataView(b.buffer, b.byteOffset, b.byteLength);
390
+ const ascii = (at, text) => [...text].every((c, i) => b[at + i] === c.charCodeAt(0));
391
+ if (b.length > 25 && b[0] === 0x89 && ascii(1, "PNG")) {
392
+ const [bitDepth, colorType] = [b[24], b[25]];
393
+ const color = colorType === 3 || (bitDepth === 8 && (colorType === 2 || colorType === 6));
394
+ return { width: v.getUint32(16), height: v.getUint32(20), color };
395
+ }
396
+ if (b[0] === 0xff && b[1] === 0xd8) {
397
+ let i = 2;
398
+ while (i + 9 < b.length) {
399
+ if (b[i] !== 0xff) {
400
+ return null;
401
+ }
402
+ const marker = b[i + 1];
403
+ const length = (b[i + 2] << 8) | b[i + 3];
404
+ const isFrame = marker >= 0xc0 && marker <= 0xcf && marker !== 0xc4 && marker !== 0xc8 && marker !== 0xcc;
405
+ if (isFrame) {
406
+ return {
407
+ height: (b[i + 5] << 8) | b[i + 6],
408
+ width: (b[i + 7] << 8) | b[i + 8],
409
+ color: b[i + 4] === 8 && b[i + 9] >= 3,
410
+ };
411
+ }
412
+ i += 2 + length;
413
+ }
414
+ return null;
415
+ }
416
+ if (b.length >= 30 && ascii(0, "RIFF") && ascii(8, "WEBP")) {
417
+ // The first chunk: lossy (VP8), lossless (VP8L) or extended (VP8X).
418
+ if (ascii(12, "VP8 ")) {
419
+ return { width: v.getUint16(26, true) & 0x3fff, height: v.getUint16(28, true) & 0x3fff, color: true };
420
+ }
421
+ if (ascii(12, "VP8L")) {
422
+ const bits = v.getUint32(21, true);
423
+ return { width: (bits & 0x3fff) + 1, height: ((bits >>> 14) & 0x3fff) + 1, color: true };
424
+ }
425
+ if (ascii(12, "VP8X")) {
426
+ const u24 = (at) => b[at] | (b[at + 1] << 8) | (b[at + 2] << 16);
427
+ return { width: u24(24) + 1, height: u24(27) + 1, color: true };
428
+ }
429
+ }
430
+ return null;
431
+ }
432
+ // A trailing dot names the same host (`huggingface.co.`), so it matches too.
433
+ const HUB_HOST = /^(huggingface\.co|hf\.co)\.?$/;
434
+ const HUB_CDN = /\.hf\.co\.?$/;
435
+ // Paths of Hub repo files, of the tree listing the prefetch reads and of the
436
+ // revision lookup that pins a load to one commit: the only Hub URLs a load
437
+ // requests, never other `/api/*` endpoints or account pages. The last group is
438
+ // the revision.
439
+ const HUB_FILE = /^\/(?:(datasets|spaces)\/)?([\w.-]+)\/([\w.-]+)\/resolve\/([^/]*)/;
440
+ const HUB_TREE = /^\/api\/(datasets|models|spaces)\/([\w.-]+)\/([\w.-]+)\/(?:tree|revision)\/([^/]*)/;
441
+ // First path segments of Hub pages and endpoints: never a model's owner.
442
+ const HUB_RESERVED = new Set([
443
+ "api",
444
+ "oauth",
445
+ "settings",
446
+ "login",
447
+ "logout",
448
+ "join",
449
+ "docs",
450
+ "models",
451
+ "datasets",
452
+ "spaces",
453
+ "organizations",
454
+ "new",
455
+ "pricing",
456
+ "blog",
457
+ "papers",
458
+ "posts",
459
+ "collections",
460
+ "notifications",
461
+ "search",
462
+ "chat",
463
+ "learn",
464
+ "tasks",
465
+ "enterprise",
466
+ "billing",
467
+ "static-proxy",
468
+ "avatars",
469
+ "front",
470
+ ]);
471
+ /** The path match of a Hub file or tree-listing URL (`[, type, owner, repo, revision]`), else null. */
472
+ function hubMatch(url) {
473
+ if (!HUB_HOST.test(url.hostname) || url.protocol !== "https:") {
474
+ return null;
475
+ }
476
+ const file = url.pathname.match(HUB_FILE);
477
+ if (file && (file[1] || !HUB_RESERVED.has(file[2].toLowerCase()))) {
478
+ return file;
479
+ }
480
+ return url.pathname.match(HUB_TREE);
481
+ }
482
+ /** `type/owner/repo` of a Hub file or tree-listing URL, else null. */
483
+ function hubRepo(url) {
484
+ const match = hubMatch(url);
485
+ return match && `${match[1] ?? "models"}/${match[2]}/${match[3]}`;
486
+ }
487
+ /**
488
+ * A URL on hf.co, the Hub's short domain, as the huggingface.co URL it
489
+ * redirects to: fetched directly, a request keeps its headers (a redirect
490
+ * to another origin drops them) and its credentials scope stays the same.
491
+ */
492
+ export function canonicalUrl(url) {
493
+ try {
494
+ const parsed = new URL(url);
495
+ if (!/^hf\.co\.?$/.test(parsed.hostname)) {
496
+ return url;
497
+ }
498
+ parsed.hostname = "huggingface.co";
499
+ return parsed.href;
500
+ }
501
+ catch {
502
+ return url;
503
+ }
504
+ }
505
+ /** The scheme of files given with the `files` option: `local:///<key>`, the key percent-encoded. */
506
+ export const LOCAL = "local:";
507
+ /** A `files` key as the load spells it: `/` separators, no leading `./` or `/`. */
508
+ export function localKey(key) {
509
+ return key.replace(/\\/g, "/").replace(/^(?:\.?\/)+/, "");
510
+ }
511
+ /** The URL a `files` key loads as; relative asset paths in the file resolve against it. */
512
+ export function localUrl(key) {
513
+ return `${LOCAL}///${localKey(key).split("/").map(encodeURIComponent).join("/")}`;
514
+ }
515
+ /** The `files` key a `local:` URL names. */
516
+ export function keyOfLocalUrl(url) {
517
+ return decodeURIComponent(new URL(url).pathname.slice(1));
518
+ }
519
+ /**
520
+ * How a load rooted at `rootUrl` may request `url`: `{ refused }` with the
521
+ * reason, or the fetch options to use. Every request a load makes goes
522
+ * through this first, then through {@link fetchWithPolicy}. Only the
523
+ * requested URL is checked: fetches follow redirects (a Hub `resolve` URL
524
+ * redirects to its CDN, which the Hub controls), but never with the caller's
525
+ * headers off the Hub.
526
+ *
527
+ * - hf.co URLs are checked as the huggingface.co URLs they redirect to.
528
+ * - The root URL itself, as the caller gave it, is always allowed.
529
+ * - A `local:` root (the `files` option) may read other `local:` URLs, which
530
+ * are looked up in its files and never fetched; no other root may.
531
+ * - Only http(s), with no user name or password in the URL.
532
+ * - Origins: the root's, those in `allowedOrigins` (`'*'` for any) and, for a
533
+ * root on the Hugging Face Hub, the Hub and its CDN hosts.
534
+ * - On huggingface.co and hf.co, only repo files (`…/resolve/…`) and tree
535
+ * listings, under a user or organization name (not `/api/…`, `/oauth/…`
536
+ * and other Hub pages), with no encoded slashes outside the revision (a
537
+ * pull request's is `refs%2Fpr%2F1`).
538
+ * - Credentials (cookies and the caller's headers) go only to the root's own
539
+ * origin or, for a Hub root, only to the root's own repo.
540
+ */
541
+ export function requestPolicy(url, rootUrl, allowedOrigins = []) {
542
+ const refused = refusal(canonicalUrl(url), canonicalUrl(rootUrl), allowedOrigins);
543
+ if (refused) {
544
+ return { refused };
545
+ }
546
+ return {
547
+ credentials: credentialed(new URL(canonicalUrl(url)), new URL(canonicalUrl(rootUrl))) ? "same-origin" : "omit",
548
+ referrerPolicy: "no-referrer",
549
+ };
550
+ }
551
+ function refusal(url, rootUrl, allowedOrigins) {
552
+ if (url === rootUrl) {
553
+ return null;
554
+ }
555
+ let target;
556
+ try {
557
+ target = new URL(url);
558
+ }
559
+ catch {
560
+ return `not a URL: ${url}`;
561
+ }
562
+ const root = new URL(rootUrl);
563
+ if (root.protocol === LOCAL && target.protocol === LOCAL) {
564
+ return null;
565
+ }
566
+ if (target.protocol !== "http:" && target.protocol !== "https:") {
567
+ return `only http(s) URLs are fetched: ${url}`;
568
+ }
569
+ if (target.username || target.password) {
570
+ return `URLs with credentials are not fetched: ${url}`;
571
+ }
572
+ const hub = HUB_HOST.test(target.hostname);
573
+ if (hub && !hubFile(target)) {
574
+ return `only Hub repo files are fetched from ${target.host}: ${url}`;
575
+ }
576
+ const fromHub = HUB_HOST.test(root.hostname) && (hub || HUB_CDN.test(target.hostname)) && target.protocol === "https:";
577
+ if (target.origin === root.origin ||
578
+ fromHub ||
579
+ allowedOrigins.includes("*") ||
580
+ allowedOrigins.includes(target.origin)) {
581
+ return null;
582
+ }
583
+ return `its origin is not in allowedOrigins: ${url}`;
584
+ }
585
+ /** A Hub repo file or tree listing with no encoded slash or backslash, but for a `%2F` in its revision. */
586
+ function hubFile(url) {
587
+ const match = hubMatch(url);
588
+ if (!match) {
589
+ return false;
590
+ }
591
+ const revisionStart = match[0].length - match[4].length;
592
+ const outside = url.pathname.slice(0, revisionStart) + url.pathname.slice(match[0].length);
593
+ return !/%2f|%5c/i.test(outside) && !/%5c/i.test(match[4]);
594
+ }
595
+ function credentialed(target, root) {
596
+ // Every `local:` URL's origin is the string "null", which would match any other's.
597
+ if (root.protocol === LOCAL) {
598
+ return false;
599
+ }
600
+ if (target.origin !== root.origin) {
601
+ return false;
602
+ }
603
+ const repo = hubRepo(root);
604
+ return HUB_HOST.test(root.hostname) ? !!repo && hubRepo(target) === repo : true;
605
+ }
606
+ /**
607
+ * Fetches `url` under `policy` (see {@link requestPolicy}), sending `headers`
608
+ * only where credentials may go. A request carrying them does not follow a
609
+ * redirect with them: unless it is on the Hub (whose redirects stay on its own
610
+ * hosts), it is not followed, and the URL is fetched again without headers or
611
+ * cookies, for the browser to follow.
612
+ */
613
+ export async function fetchWithPolicy(url, policy, headers) {
614
+ const sendHeaders = policy.credentials === "same-origin" && !!headers && Object.keys(headers).length > 0;
615
+ if (!sendHeaders) {
616
+ return fetch(url, policy);
617
+ }
618
+ if (HUB_HOST.test(new URL(url).hostname)) {
619
+ return fetch(url, { ...policy, headers });
620
+ }
621
+ const response = await fetch(url, { ...policy, headers, redirect: "manual" });
622
+ if (response.type !== "opaqueredirect" && !(response.status >= 300 && response.status < 400)) {
623
+ return response;
624
+ }
625
+ response.body?.cancel().catch(() => { });
626
+ return fetch(url, { ...policy, credentials: "omit" });
627
+ }
628
+ /**
629
+ * Reads each geometry out of WASM in turn, so only one mesh's arrays are in
630
+ * WASM memory at a time, and calls `onGeometry(index, meta, arrays)` with
631
+ * JS-owned typed arrays (`meta` and `arrays` are null for a mesh with nothing
632
+ * drawable, or left out). Triangles count as drawn, once per instance:
633
+ * meshes that would take them past `maxTriangles` are left out unread.
634
+ * Releases the stage afterwards. Returns warnings: `triangle-limit` for
635
+ * meshes left out, `nothing-drawable` when no mesh had anything to draw.
636
+ */
637
+ export function readGeometries(scene, meta, onGeometry, { maxTriangles = DEFAULTS.maxTriangles } = {}) {
638
+ const instances = Array.from({ length: meta.geometryCount }, () => 0);
639
+ for (const { geometry } of meta.instances) {
640
+ instances[geometry]++;
641
+ }
642
+ let drawn = 0;
643
+ let left = maxTriangles;
644
+ const skipped = [];
645
+ for (let i = 0; i < meta.geometryCount; i++) {
646
+ // Not drawn anywhere (e.g. all its instances past maxInstances).
647
+ if (!instances[i]) {
648
+ onGeometry(i, null, null);
649
+ continue;
650
+ }
651
+ const json = scene.read(i, Math.min(Math.floor(left / instances[i]), 2 ** 32 - 1));
652
+ const g = json && JSON.parse(json);
653
+ if (!g || "overBudget" in g) {
654
+ if (g) {
655
+ skipped.push(g.path);
656
+ }
657
+ onGeometry(i, null, null);
658
+ continue;
659
+ }
660
+ drawn++;
661
+ left = Math.max(0, left - instances[i] * g.groups.reduce((n, [, count]) => n + count / 3, 0));
662
+ onGeometry(i, g, {
663
+ positions: scene.positions(),
664
+ normals: scene.normals(),
665
+ uvs: g.uvSets.map((_, k) => scene.uvs(k)),
666
+ colors: g.hasColors ? scene.colors() : null,
667
+ indices: g.maxIndex < 65536 ? scene.indices16() : scene.indices(),
668
+ });
669
+ }
670
+ scene.finish();
671
+ const warnings = [];
672
+ if (skipped.length) {
673
+ warnings.push({
674
+ code: "triangle-limit",
675
+ message: `${skipped.length} meshes left out: past maxTriangles (${maxTriangles}) drawn`,
676
+ path: skipped[0],
677
+ });
678
+ }
679
+ if (!drawn) {
680
+ warnings.push({
681
+ code: "nothing-drawable",
682
+ message: "nothing to draw: the stage has no visible meshes with geometry",
683
+ });
684
+ }
685
+ return warnings;
686
+ }
687
+ /**
688
+ * Images stored inside a USDZ package (they cannot be fetched by URL) among
689
+ * the texture `jobs` (see {@link textureJobs}), each read once, by path, all
690
+ * together at most `maxBytes`. One that cannot be read maps to its error, so
691
+ * it fails as that texture rather than the whole load.
692
+ */
693
+ export function takePackagedTextures(scene, jobs, { maxBytes = Infinity } = {}) {
694
+ const out = new Map();
695
+ let left = maxBytes;
696
+ for (const { path } of jobs) {
697
+ if (!path.includes("[")) {
698
+ continue;
699
+ }
700
+ try {
701
+ const bytes = scene.packagedFile(path, left);
702
+ if (bytes) {
703
+ out.set(path, bytes);
704
+ }
705
+ left -= bytes?.byteLength ?? 0;
706
+ }
707
+ catch (error) {
708
+ out.set(path, error);
709
+ }
710
+ }
711
+ return out;
712
+ }
713
+ /** Long-side cap for data maps (roughness, metallic, occlusion, ...) in `preview` mode. */
714
+ const PREVIEW_DATA_SIZE = 512;
715
+ /**
716
+ * The texture files to load and the size to decode each to, base colors first.
717
+ * `preview`: base color up to `maxSize`, other maps up to 512 px, no normal
718
+ * maps. `full`: every map, including normals, up to `maxSize`. `none`: nothing.
719
+ */
720
+ export function textureJobs(meta, { textures, maxSize }) {
721
+ if (textures === "none") {
722
+ return [];
723
+ }
724
+ const full = textures === "full";
725
+ const dataSize = full ? maxSize : Math.min(maxSize, PREVIEW_DATA_SIZE);
726
+ const tiers = [
727
+ [["diffuseColor"], maxSize],
728
+ [["opacity", "emissiveColor", "roughness", "metallic", "occlusion"], dataSize],
729
+ [full ? ["normal"] : [], maxSize],
730
+ ];
731
+ const jobs = new Map();
732
+ for (const [inputs, size] of tiers) {
733
+ for (const m of meta.materials) {
734
+ for (const input of inputs) {
735
+ const path = m.maps[input]?.path;
736
+ // A file shared by several inputs is decoded once, at the largest size asked.
737
+ if (path) {
738
+ jobs.set(path, Math.max(jobs.get(path) ?? 0, size));
739
+ }
740
+ }
741
+ }
742
+ }
743
+ return [...jobs].map(([path, size]) => ({ path, size }));
744
+ }
services/explorer/dist/static/usd-reader/79236f8/esm/worker.js ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Loads, composes and extracts a USD stage off the main thread, then streams
2
+ // textures as downscaled ImageBitmaps. One worker per load: the page
3
+ // terminates it when done, disposed or aborted, which releases all WASM memory.
4
+ import init, { lastPanic, UsdLoader } from "../wasm/usd_wasm.js";
5
+ import { hubPackageLayers, pinHubRevision } from "./hub-prefetch.js";
6
+ import { DEFAULTS, LOCAL, canonicalUrl, composeStage, fetchLimited, fetchWithPolicy, imageInfo, keyOfLocalUrl, limiter, loadFailure, readGeometries, requestPolicy, takePackagedTextures, textureJobs, } from "./load-core.js";
7
+ // Textures in flight at once (fetch and decode): decoding a large image
8
+ // briefly holds it at full size, so wide parallelism spikes memory.
9
+ const TEXTURE_CONCURRENCY = 4;
10
+ // Longest side of an image read at all: larger ones are refused from their
11
+ // header, before decoding (WebGL's own limit is commonly 16384 too).
12
+ const MAX_IMAGE_SIZE = DEFAULTS.maxImageSize;
13
+ self.onmessage = async ({ data }) => {
14
+ const { url, wasmModule, maxTextureSize = DEFAULTS.maxTextureSize, textures = DEFAULTS.textures, maxConcurrentFetches = DEFAULTS.maxConcurrentFetches, maxLayerBytes, maxTextureBytes = DEFAULTS.maxTextureBytes, maxLayers, maxInstances, maxTriangles, allowedOrigins, headers, files, } = data;
15
+ // Every request (layer, texture, Hub listing) goes through here, and
16
+ // through the request policy first. The caller's headers go only where
17
+ // cookies may, and never through a redirect off the Hub.
18
+ const request = async (target) => {
19
+ target = canonicalUrl(target);
20
+ const policy = requestPolicy(target, url, allowedOrigins);
21
+ // Reads like a network failure: a missing layer or a failed texture.
22
+ if (policy.refused !== undefined) {
23
+ throw new TypeError(`request refused: ${policy.refused}`);
24
+ }
25
+ if (target.startsWith(LOCAL)) {
26
+ const file = files?.get(keyOfLocalUrl(target));
27
+ return file ? new Response(file) : new Response(null, { status: 404 });
28
+ }
29
+ return fetchWithPolicy(target, policy, headers);
30
+ };
31
+ const fetchBytes = (target, budget) => fetchLimited(target, budget, { fetchFn: request });
32
+ // One budget for every texture, packaged ones first, then each fetched
33
+ // body as its bytes arrive. Bytes of a body cut short stay charged: they
34
+ // were downloaded.
35
+ let textureBytes = 0;
36
+ const chargeTexture = (bytes) => {
37
+ textureBytes += bytes;
38
+ if (textureBytes > maxTextureBytes) {
39
+ throw new Error(`textures exceed maxTextureBytes (${maxTextureBytes} bytes)`);
40
+ }
41
+ };
42
+ const progress = (p) => self.postMessage({ type: "progress", progress: p });
43
+ let wasmMemory;
44
+ try {
45
+ const t0 = performance.now();
46
+ // Looked up while the WASM module initializes.
47
+ const rootUrl = pinHubRevision(url, request);
48
+ const preload = rootUrl.then((root) => hubPackageLayers(root, request));
49
+ const wasm = await init({ module_or_path: wasmModule });
50
+ wasmMemory = wasm.memory;
51
+ const tInit = performance.now();
52
+ const { scene, meta, stats } = await composeStage({
53
+ UsdLoader,
54
+ fetchBytes,
55
+ rootUrl: await rootUrl,
56
+ maxConcurrentFetches,
57
+ maxLayerBytes,
58
+ maxLayers,
59
+ maxInstances,
60
+ allowedOrigins,
61
+ preload,
62
+ onProgress: progress,
63
+ });
64
+ stats.initMs = tInit - t0;
65
+ self.postMessage({ type: "meta", meta });
66
+ // One mesh at a time: each is transferred (not copied) as soon as it is read.
67
+ const onGeometry = (index, g, arrays) => {
68
+ const transfer = arrays
69
+ ? [arrays.positions, arrays.normals, arrays.colors, arrays.indices, ...arrays.uvs]
70
+ .filter((a) => !!a)
71
+ .map((a) => a.buffer)
72
+ : [];
73
+ self.postMessage({ type: "geometry", index, meta: g, arrays }, transfer);
74
+ progress({ stage: "geometry", loaded: index + 1, total: meta.geometryCount });
75
+ };
76
+ const warnings = readGeometries(scene, meta, onGeometry, { maxTriangles });
77
+ const jobs = textureJobs(meta, { textures, maxSize: maxTextureSize });
78
+ const packaged = takePackagedTextures(scene, jobs, { maxBytes: maxTextureBytes });
79
+ for (const entry of packaged.values()) {
80
+ if (!(entry instanceof Error)) {
81
+ textureBytes += entry.byteLength;
82
+ }
83
+ }
84
+ scene.free();
85
+ stats.warnings.push(...warnings);
86
+ stats.totalMs = performance.now() - t0;
87
+ stats.wasmMemoryBytes = wasm.memory.buffer.byteLength;
88
+ self.postMessage({ type: "scene", stats: stats });
89
+ let loaded = 0;
90
+ let bytes = 0;
91
+ progress({ stage: "textures", loaded, total: jobs.length, bytes });
92
+ // The limiter runs jobs in order, so base colors come first.
93
+ const throttle = limiter(Math.min(maxConcurrentFetches, TEXTURE_CONCURRENCY));
94
+ await Promise.all(jobs.map(({ path, size }) => throttle(async () => {
95
+ try {
96
+ const entry = packaged.get(path);
97
+ if (entry instanceof Error) {
98
+ throw entry;
99
+ }
100
+ // A packaged path is never a URL to fetch.
101
+ if (!entry && path.includes("[")) {
102
+ throw new Error(`not found in its package: ${path}`);
103
+ }
104
+ const image = entry ?? (await fetchBytes(path, chargeTexture));
105
+ bytes += image.byteLength;
106
+ const { bitmap, color } = await decodeTexture(image, size);
107
+ self.postMessage({ type: "texture", path, bitmap, color }, [bitmap]);
108
+ }
109
+ catch (error) {
110
+ self.postMessage({ type: "texture", path, error: String(error?.message || error) });
111
+ }
112
+ progress({ stage: "textures", loaded: ++loaded, total: jobs.length, bytes });
113
+ })));
114
+ self.postMessage({ type: "done" });
115
+ }
116
+ catch (error) {
117
+ self.postMessage({ type: "error", ...loadFailure(error, wasmMemory?.buffer.byteLength ?? 0, lastPanic) });
118
+ }
119
+ };
120
+ /**
121
+ * Decodes a PNG, JPEG or WebP straight to at most `maxSize` px on its long
122
+ * side, and tells whether it holds color (what `sourceColorSpace = "auto"`
123
+ * decodes as sRGB). Images whose size the header does not give, or that are
124
+ * too large, are refused before decoding.
125
+ */
126
+ async function decodeTexture(bytes, maxSize) {
127
+ const info = imageInfo(bytes);
128
+ if (!info) {
129
+ throw new Error("unsupported image format: only PNG, JPEG and WebP are read");
130
+ }
131
+ if (Math.max(info.width, info.height) > MAX_IMAGE_SIZE) {
132
+ throw new Error(`image too large: ${info.width}x${info.height} (at most ${MAX_IMAGE_SIZE} px a side)`);
133
+ }
134
+ // USD texture coordinates put (0,0) at the bottom-left, three.js's default.
135
+ const options = {
136
+ imageOrientation: "flipY",
137
+ premultiplyAlpha: "none",
138
+ colorSpaceConversion: "none",
139
+ };
140
+ const scale = Math.min(1, maxSize / Math.max(info.width, info.height));
141
+ if (scale < 1) {
142
+ options.resizeWidth = Math.max(1, Math.round(info.width * scale));
143
+ options.resizeHeight = Math.max(1, Math.round(info.height * scale));
144
+ options.resizeQuality = "high";
145
+ }
146
+ return { bitmap: await createImageBitmap(new Blob([bytes]), options), color: info.color };
147
+ }
services/explorer/dist/static/usd-reader/79236f8/wasm/usd_wasm.js ADDED
@@ -0,0 +1,683 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* @ts-self-types="./usd_wasm.d.ts" */
2
+
3
+ export class UsdLoader {
4
+ __destroy_into_raw() {
5
+ const ptr = this.__wbg_ptr;
6
+ this.__wbg_ptr = 0;
7
+ UsdLoaderFinalization.unregister(this);
8
+ return ptr;
9
+ }
10
+ free() {
11
+ const ptr = this.__destroy_into_raw();
12
+ wasm.__wbg_usdloader_free(ptr, 0);
13
+ }
14
+ /**
15
+ * Stores a layer and returns the layers it names outside unselected
16
+ * variants (see [`Loader::add_layer`]).
17
+ * @param {string} path
18
+ * @param {Uint8Array} bytes
19
+ * @returns {string[]}
20
+ */
21
+ addLayer(path, bytes) {
22
+ try {
23
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
24
+ const ptr0 = passStringToWasm0(path, wasm.__wbindgen_export2, wasm.__wbindgen_export3);
25
+ const len0 = WASM_VECTOR_LEN;
26
+ const ptr1 = passArray8ToWasm0(bytes, wasm.__wbindgen_export2);
27
+ const len1 = WASM_VECTOR_LEN;
28
+ wasm.usdloader_addLayer(retptr, this.__wbg_ptr, ptr0, len0, ptr1, len1);
29
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
30
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
31
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
32
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
33
+ if (r3) {
34
+ throw takeObject(r2);
35
+ }
36
+ var v3 = getArrayJsValueFromWasm0(r0, r1);
37
+ wasm.__wbindgen_export(r0, r1 * 4, 4);
38
+ return v3;
39
+ } finally {
40
+ wasm.__wbindgen_add_to_stack_pointer(16);
41
+ }
42
+ }
43
+ /**
44
+ * Composes the stage at `root`. Returns the layers still missing; when
45
+ * that is empty the scene is ready for [`take_scene`](Self::take_scene).
46
+ * The scene draws at most `max_instances` mesh instances.
47
+ * @param {string} root
48
+ * @param {number} max_instances
49
+ * @returns {string[]}
50
+ */
51
+ compose(root, max_instances) {
52
+ try {
53
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
54
+ const ptr0 = passStringToWasm0(root, wasm.__wbindgen_export2, wasm.__wbindgen_export3);
55
+ const len0 = WASM_VECTOR_LEN;
56
+ wasm.usdloader_compose(retptr, this.__wbg_ptr, ptr0, len0, max_instances);
57
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
58
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
59
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
60
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
61
+ if (r3) {
62
+ throw takeObject(r2);
63
+ }
64
+ var v2 = getArrayJsValueFromWasm0(r0, r1);
65
+ wasm.__wbindgen_export(r0, r1 * 4, 4);
66
+ return v2;
67
+ } finally {
68
+ wasm.__wbindgen_add_to_stack_pointer(16);
69
+ }
70
+ }
71
+ /**
72
+ * @param {string} path
73
+ * @returns {boolean}
74
+ */
75
+ has(path) {
76
+ const ptr0 = passStringToWasm0(path, wasm.__wbindgen_export2, wasm.__wbindgen_export3);
77
+ const len0 = WASM_VECTOR_LEN;
78
+ const ret = wasm.usdloader_has(this.__wbg_ptr, ptr0, len0);
79
+ return ret !== 0;
80
+ }
81
+ /**
82
+ * @param {string} path
83
+ */
84
+ markUnavailable(path) {
85
+ const ptr0 = passStringToWasm0(path, wasm.__wbindgen_export2, wasm.__wbindgen_export3);
86
+ const len0 = WASM_VECTOR_LEN;
87
+ wasm.usdloader_markUnavailable(this.__wbg_ptr, ptr0, len0);
88
+ }
89
+ constructor() {
90
+ const ret = wasm.usdloader_new();
91
+ this.__wbg_ptr = ret;
92
+ UsdLoaderFinalization.register(this, this.__wbg_ptr, this);
93
+ return this;
94
+ }
95
+ /**
96
+ * Hands over the extracted scene and drops every stored layer.
97
+ * @returns {UsdScene}
98
+ */
99
+ takeScene() {
100
+ try {
101
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
102
+ wasm.usdloader_takeScene(retptr, this.__wbg_ptr);
103
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
104
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
105
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
106
+ if (r2) {
107
+ throw takeObject(r1);
108
+ }
109
+ return UsdScene.__wrap(r0);
110
+ } finally {
111
+ wasm.__wbindgen_add_to_stack_pointer(16);
112
+ }
113
+ }
114
+ }
115
+ if (Symbol.dispose) UsdLoader.prototype[Symbol.dispose] = UsdLoader.prototype.free;
116
+
117
+ /**
118
+ * A composed scene whose meshes are read one at a time: `read(i)` makes
119
+ * geometry `i` current, and the array getters move its data out (each once).
120
+ * Only the current mesh's arrays live in WASM memory at any time.
121
+ */
122
+ export class UsdScene {
123
+ static __wrap(ptr) {
124
+ const obj = Object.create(UsdScene.prototype);
125
+ obj.__wbg_ptr = ptr;
126
+ UsdSceneFinalization.register(obj, obj.__wbg_ptr, obj);
127
+ return obj;
128
+ }
129
+ __destroy_into_raw() {
130
+ const ptr = this.__wbg_ptr;
131
+ this.__wbg_ptr = 0;
132
+ UsdSceneFinalization.unregister(this);
133
+ return ptr;
134
+ }
135
+ free() {
136
+ const ptr = this.__destroy_into_raw();
137
+ wasm.__wbg_usdscene_free(ptr, 0);
138
+ }
139
+ /**
140
+ * @returns {Float32Array}
141
+ */
142
+ colors() {
143
+ try {
144
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
145
+ wasm.usdscene_colors(retptr, this.__wbg_ptr);
146
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
147
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
148
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
149
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
150
+ if (r3) {
151
+ throw takeObject(r2);
152
+ }
153
+ var v1 = getArrayF32FromWasm0(r0, r1).slice();
154
+ wasm.__wbindgen_export(r0, r1 * 4, 4);
155
+ return v1;
156
+ } finally {
157
+ wasm.__wbindgen_add_to_stack_pointer(16);
158
+ }
159
+ }
160
+ /**
161
+ * Releases the stage once every geometry has been read.
162
+ */
163
+ finish() {
164
+ wasm.usdscene_finish(this.__wbg_ptr);
165
+ }
166
+ /**
167
+ * Indices as 16-bit, for geometries with fewer than 65536 vertices.
168
+ * @returns {Uint16Array}
169
+ */
170
+ indices16() {
171
+ try {
172
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
173
+ wasm.usdscene_indices16(retptr, this.__wbg_ptr);
174
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
175
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
176
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
177
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
178
+ if (r3) {
179
+ throw takeObject(r2);
180
+ }
181
+ var v1 = getArrayU16FromWasm0(r0, r1).slice();
182
+ wasm.__wbindgen_export(r0, r1 * 2, 2);
183
+ return v1;
184
+ } finally {
185
+ wasm.__wbindgen_add_to_stack_pointer(16);
186
+ }
187
+ }
188
+ /**
189
+ * @returns {Uint32Array}
190
+ */
191
+ indices() {
192
+ try {
193
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
194
+ wasm.usdscene_indices(retptr, this.__wbg_ptr);
195
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
196
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
197
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
198
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
199
+ if (r3) {
200
+ throw takeObject(r2);
201
+ }
202
+ var v1 = getArrayU32FromWasm0(r0, r1).slice();
203
+ wasm.__wbindgen_export(r0, r1 * 4, 4);
204
+ return v1;
205
+ } finally {
206
+ wasm.__wbindgen_add_to_stack_pointer(16);
207
+ }
208
+ }
209
+ /**
210
+ * Everything but the triangle data, as JSON.
211
+ * @returns {string}
212
+ */
213
+ meta() {
214
+ let deferred1_0;
215
+ let deferred1_1;
216
+ try {
217
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
218
+ wasm.usdscene_meta(retptr, this.__wbg_ptr);
219
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
220
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
221
+ deferred1_0 = r0;
222
+ deferred1_1 = r1;
223
+ return getStringFromWasm0(r0, r1);
224
+ } finally {
225
+ wasm.__wbindgen_add_to_stack_pointer(16);
226
+ wasm.__wbindgen_export(deferred1_0, deferred1_1, 1);
227
+ }
228
+ }
229
+ /**
230
+ * @returns {Float32Array}
231
+ */
232
+ normals() {
233
+ try {
234
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
235
+ wasm.usdscene_normals(retptr, this.__wbg_ptr);
236
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
237
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
238
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
239
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
240
+ if (r3) {
241
+ throw takeObject(r2);
242
+ }
243
+ var v1 = getArrayF32FromWasm0(r0, r1).slice();
244
+ wasm.__wbindgen_export(r0, r1 * 4, 4);
245
+ return v1;
246
+ } finally {
247
+ wasm.__wbindgen_add_to_stack_pointer(16);
248
+ }
249
+ }
250
+ /**
251
+ * A texture that lives inside a USDZ package, if `path` names one there.
252
+ * Fails rather than expand it past `limit` bytes.
253
+ * @param {string} path
254
+ * @param {number} limit
255
+ * @returns {Uint8Array | undefined}
256
+ */
257
+ packagedFile(path, limit) {
258
+ try {
259
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
260
+ const ptr0 = passStringToWasm0(path, wasm.__wbindgen_export2, wasm.__wbindgen_export3);
261
+ const len0 = WASM_VECTOR_LEN;
262
+ wasm.usdscene_packagedFile(retptr, this.__wbg_ptr, ptr0, len0, limit);
263
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
264
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
265
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
266
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
267
+ if (r3) {
268
+ throw takeObject(r2);
269
+ }
270
+ let v2;
271
+ if (r0 !== 0) {
272
+ v2 = getArrayU8FromWasm0(r0, r1).slice();
273
+ wasm.__wbindgen_export(r0, r1 * 1, 1);
274
+ }
275
+ return v2;
276
+ } finally {
277
+ wasm.__wbindgen_add_to_stack_pointer(16);
278
+ }
279
+ }
280
+ /**
281
+ * @returns {Float32Array}
282
+ */
283
+ positions() {
284
+ try {
285
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
286
+ wasm.usdscene_positions(retptr, this.__wbg_ptr);
287
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
288
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
289
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
290
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
291
+ if (r3) {
292
+ throw takeObject(r2);
293
+ }
294
+ var v1 = getArrayF32FromWasm0(r0, r1).slice();
295
+ wasm.__wbindgen_export(r0, r1 * 4, 4);
296
+ return v1;
297
+ } finally {
298
+ wasm.__wbindgen_add_to_stack_pointer(16);
299
+ }
300
+ }
301
+ /**
302
+ * Reads geometry `index` and returns its metadata as JSON, or `None` when
303
+ * the mesh has nothing drawable. A mesh with more than `max_triangles` is
304
+ * left unread: `{"overBudget": triangles, "path": prim path}`.
305
+ * @param {number} index
306
+ * @param {number} max_triangles
307
+ * @returns {string | undefined}
308
+ */
309
+ read(index, max_triangles) {
310
+ try {
311
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
312
+ wasm.usdscene_read(retptr, this.__wbg_ptr, index, max_triangles);
313
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
314
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
315
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
316
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
317
+ if (r3) {
318
+ throw takeObject(r2);
319
+ }
320
+ let v1;
321
+ if (r0 !== 0) {
322
+ v1 = getStringFromWasm0(r0, r1);
323
+ wasm.__wbindgen_export(r0, r1 * 1, 1);
324
+ }
325
+ return v1;
326
+ } finally {
327
+ wasm.__wbindgen_add_to_stack_pointer(16);
328
+ }
329
+ }
330
+ /**
331
+ * UV set `set` (in the order of the geometry's `uvSets`).
332
+ * @param {number} set
333
+ * @returns {Float32Array}
334
+ */
335
+ uvs(set) {
336
+ try {
337
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
338
+ wasm.usdscene_uvs(retptr, this.__wbg_ptr, set);
339
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
340
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
341
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
342
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
343
+ if (r3) {
344
+ throw takeObject(r2);
345
+ }
346
+ var v1 = getArrayF32FromWasm0(r0, r1).slice();
347
+ wasm.__wbindgen_export(r0, r1 * 4, 4);
348
+ return v1;
349
+ } finally {
350
+ wasm.__wbindgen_add_to_stack_pointer(16);
351
+ }
352
+ }
353
+ }
354
+ if (Symbol.dispose) UsdScene.prototype[Symbol.dispose] = UsdScene.prototype.free;
355
+
356
+ /**
357
+ * Takes the message of the last panic, if any.
358
+ * @returns {string | undefined}
359
+ */
360
+ export function lastPanic() {
361
+ try {
362
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
363
+ wasm.lastPanic(retptr);
364
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
365
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
366
+ let v1;
367
+ if (r0 !== 0) {
368
+ v1 = getStringFromWasm0(r0, r1);
369
+ wasm.__wbindgen_export(r0, r1 * 1, 1);
370
+ }
371
+ return v1;
372
+ } finally {
373
+ wasm.__wbindgen_add_to_stack_pointer(16);
374
+ }
375
+ }
376
+
377
+ export function start() {
378
+ wasm.start();
379
+ }
380
+ function __wbg_get_imports() {
381
+ const import0 = {
382
+ __proto__: null,
383
+ __wbg_Error_30c8987f7c2ed4e2: function(arg0, arg1) {
384
+ const ret = Error(getStringFromWasm0(arg0, arg1));
385
+ return addHeapObject(ret);
386
+ },
387
+ __wbg___wbindgen_throw_41e9ee4f547fc59a: function(arg0, arg1) {
388
+ throw new Error(getStringFromWasm0(arg0, arg1));
389
+ },
390
+ __wbindgen_generic_0000000000000001: function(arg0, arg1) {
391
+ // Cast intrinsic for `Ref(String) -> Externref`.
392
+ const ret = getStringFromWasm0(arg0, arg1);
393
+ return addHeapObject(ret);
394
+ },
395
+ };
396
+ return {
397
+ __proto__: null,
398
+ "./usd_wasm_bg.js": import0,
399
+ };
400
+ }
401
+
402
+ const UsdLoaderFinalization = (typeof FinalizationRegistry === 'undefined')
403
+ ? { register: () => {}, unregister: () => {} }
404
+ : new FinalizationRegistry(ptr => wasm.__wbg_usdloader_free(ptr, 1));
405
+ const UsdSceneFinalization = (typeof FinalizationRegistry === 'undefined')
406
+ ? { register: () => {}, unregister: () => {} }
407
+ : new FinalizationRegistry(ptr => wasm.__wbg_usdscene_free(ptr, 1));
408
+
409
+ function addHeapObject(obj) {
410
+ if (heap_next === heap.length) heap.push(heap.length + 1);
411
+ const idx = heap_next;
412
+ heap_next = heap[idx];
413
+
414
+ heap[idx] = obj;
415
+ return idx;
416
+ }
417
+
418
+ function dropObject(idx) {
419
+ if (idx < 1028) return;
420
+ heap[idx] = heap_next;
421
+ heap_next = idx;
422
+ }
423
+
424
+ function getArrayF32FromWasm0(ptr, len) {
425
+ ptr = ptr >>> 0;
426
+ return getFloat32ArrayMemory0().subarray(ptr / 4, ptr / 4 + len);
427
+ }
428
+
429
+ function getArrayJsValueFromWasm0(ptr, len) {
430
+ ptr = ptr >>> 0;
431
+ const mem = getDataViewMemory0();
432
+ const result = [];
433
+ for (let i = ptr; i < ptr + 4 * len; i += 4) {
434
+ result.push(takeObject(mem.getUint32(i, true)));
435
+ }
436
+ return result;
437
+ }
438
+
439
+ function getArrayU16FromWasm0(ptr, len) {
440
+ ptr = ptr >>> 0;
441
+ return getUint16ArrayMemory0().subarray(ptr / 2, ptr / 2 + len);
442
+ }
443
+
444
+ function getArrayU32FromWasm0(ptr, len) {
445
+ ptr = ptr >>> 0;
446
+ return getUint32ArrayMemory0().subarray(ptr / 4, ptr / 4 + len);
447
+ }
448
+
449
+ function getArrayU8FromWasm0(ptr, len) {
450
+ ptr = ptr >>> 0;
451
+ return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
452
+ }
453
+
454
+ let cachedDataViewMemory0 = null;
455
+ function getDataViewMemory0() {
456
+ if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
457
+ cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
458
+ }
459
+ return cachedDataViewMemory0;
460
+ }
461
+
462
+ let cachedFloat32ArrayMemory0 = null;
463
+ function getFloat32ArrayMemory0() {
464
+ if (cachedFloat32ArrayMemory0 === null || cachedFloat32ArrayMemory0.byteLength === 0) {
465
+ cachedFloat32ArrayMemory0 = new Float32Array(wasm.memory.buffer);
466
+ }
467
+ return cachedFloat32ArrayMemory0;
468
+ }
469
+
470
+ function getStringFromWasm0(ptr, len) {
471
+ return decodeText(ptr >>> 0, len);
472
+ }
473
+
474
+ let cachedUint16ArrayMemory0 = null;
475
+ function getUint16ArrayMemory0() {
476
+ if (cachedUint16ArrayMemory0 === null || cachedUint16ArrayMemory0.byteLength === 0) {
477
+ cachedUint16ArrayMemory0 = new Uint16Array(wasm.memory.buffer);
478
+ }
479
+ return cachedUint16ArrayMemory0;
480
+ }
481
+
482
+ let cachedUint32ArrayMemory0 = null;
483
+ function getUint32ArrayMemory0() {
484
+ if (cachedUint32ArrayMemory0 === null || cachedUint32ArrayMemory0.byteLength === 0) {
485
+ cachedUint32ArrayMemory0 = new Uint32Array(wasm.memory.buffer);
486
+ }
487
+ return cachedUint32ArrayMemory0;
488
+ }
489
+
490
+ let cachedUint8ArrayMemory0 = null;
491
+ function getUint8ArrayMemory0() {
492
+ if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
493
+ cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
494
+ }
495
+ return cachedUint8ArrayMemory0;
496
+ }
497
+
498
+ function getObject(idx) { return heap[idx]; }
499
+
500
+ let heap = new Array(1024).fill(undefined);
501
+ heap.push(undefined, null, true, false);
502
+
503
+ let heap_next = heap.length;
504
+
505
+ function passArray8ToWasm0(arg, malloc) {
506
+ const ptr = malloc(arg.length * 1, 1) >>> 0;
507
+ getUint8ArrayMemory0().set(arg, ptr / 1);
508
+ WASM_VECTOR_LEN = arg.length;
509
+ return ptr;
510
+ }
511
+
512
+ function passStringToWasm0(arg, malloc, realloc) {
513
+ if (realloc === undefined) {
514
+ const buf = cachedTextEncoder.encode(arg);
515
+ const ptr = malloc(buf.length, 1) >>> 0;
516
+ getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
517
+ WASM_VECTOR_LEN = buf.length;
518
+ return ptr;
519
+ }
520
+
521
+ let len = arg.length;
522
+ let ptr = malloc(len, 1) >>> 0;
523
+
524
+ const mem = getUint8ArrayMemory0();
525
+
526
+ let offset = 0;
527
+
528
+ for (; offset < len; offset++) {
529
+ const code = arg.charCodeAt(offset);
530
+ if (code > 0x7F) break;
531
+ mem[ptr + offset] = code;
532
+ }
533
+ if (offset !== len) {
534
+ if (offset !== 0) {
535
+ arg = arg.slice(offset);
536
+ }
537
+ ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
538
+ const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
539
+ const ret = cachedTextEncoder.encodeInto(arg, view);
540
+
541
+ offset += ret.written;
542
+ ptr = realloc(ptr, len, offset, 1) >>> 0;
543
+ }
544
+
545
+ WASM_VECTOR_LEN = offset;
546
+ return ptr;
547
+ }
548
+
549
+ function takeObject(idx) {
550
+ const ret = getObject(idx);
551
+ dropObject(idx);
552
+ return ret;
553
+ }
554
+
555
+ let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
556
+ cachedTextDecoder.decode();
557
+ const MAX_SAFARI_DECODE_BYTES = 2146435072;
558
+ let numBytesDecoded = 0;
559
+ function decodeText(ptr, len) {
560
+ numBytesDecoded += len;
561
+ if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {
562
+ cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
563
+ cachedTextDecoder.decode();
564
+ numBytesDecoded = len;
565
+ }
566
+ return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
567
+ }
568
+
569
+ const cachedTextEncoder = new TextEncoder();
570
+
571
+ if (!('encodeInto' in cachedTextEncoder)) {
572
+ cachedTextEncoder.encodeInto = function (arg, view) {
573
+ const buf = cachedTextEncoder.encode(arg);
574
+ view.set(buf);
575
+ return {
576
+ read: arg.length,
577
+ written: buf.length
578
+ };
579
+ };
580
+ }
581
+
582
+ let WASM_VECTOR_LEN = 0;
583
+
584
+ let wasmModule, wasmInstance, wasm;
585
+ function __wbg_finalize_init(instance, module) {
586
+ wasmInstance = instance;
587
+ wasm = instance.exports;
588
+ wasmModule = module;
589
+ cachedDataViewMemory0 = null;
590
+ cachedFloat32ArrayMemory0 = null;
591
+ cachedUint16ArrayMemory0 = null;
592
+ cachedUint32ArrayMemory0 = null;
593
+ cachedUint8ArrayMemory0 = null;
594
+ wasm.__wbindgen_start();
595
+ return wasm;
596
+ }
597
+
598
+ async function __wbg_load(module, imports) {
599
+ if (typeof Response === 'function' && module instanceof Response) {
600
+ if (!module.ok) {
601
+ throw new Error(`failed to fetch Wasm: ${module.status} ${module.statusText} fetching '${module.url}'`);
602
+ }
603
+
604
+ if (typeof WebAssembly.instantiateStreaming === 'function') {
605
+ try {
606
+ return await WebAssembly.instantiateStreaming(module, imports);
607
+ } catch (e) {
608
+ const validResponse = expectedResponseType(module.type);
609
+
610
+ if (validResponse && module.headers.get('Content-Type') !== 'application/wasm') {
611
+ console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
612
+
613
+ } else { throw e; }
614
+ }
615
+ }
616
+
617
+ const bytes = await module.arrayBuffer();
618
+ return await WebAssembly.instantiate(bytes, imports);
619
+ } else {
620
+ const instance = await WebAssembly.instantiate(module, imports);
621
+
622
+ if (instance instanceof WebAssembly.Instance) {
623
+ return { instance, module };
624
+ } else {
625
+ return instance;
626
+ }
627
+ }
628
+
629
+ function expectedResponseType(type) {
630
+ switch (type) {
631
+ case 'basic': case 'cors': case 'default': return true;
632
+ }
633
+ return false;
634
+ }
635
+ }
636
+
637
+ function initSync(module) {
638
+ if (wasm !== undefined) return wasm;
639
+
640
+
641
+ if (module !== undefined) {
642
+ if (Object.getPrototypeOf(module) === Object.prototype) {
643
+ ({module} = module)
644
+ } else {
645
+ console.warn('using deprecated parameters for `initSync()`; pass a single object instead')
646
+ }
647
+ }
648
+
649
+ const imports = __wbg_get_imports();
650
+ if (!(module instanceof WebAssembly.Module)) {
651
+ module = new WebAssembly.Module(module);
652
+ }
653
+ const instance = new WebAssembly.Instance(module, imports);
654
+ return __wbg_finalize_init(instance, module);
655
+ }
656
+
657
+ async function __wbg_init(module_or_path) {
658
+ if (wasm !== undefined) return wasm;
659
+
660
+
661
+ if (module_or_path !== undefined) {
662
+ if (Object.getPrototypeOf(module_or_path) === Object.prototype) {
663
+ ({module_or_path} = module_or_path)
664
+ } else {
665
+ console.warn('using deprecated parameters for the initialization function; pass a single object instead')
666
+ }
667
+ }
668
+
669
+ if (module_or_path === undefined) {
670
+ module_or_path = new URL('usd_wasm_bg.wasm', import.meta.url);
671
+ }
672
+ const imports = __wbg_get_imports();
673
+
674
+ if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) {
675
+ module_or_path = fetch(module_or_path);
676
+ }
677
+
678
+ const { instance, module } = await __wbg_load(await module_or_path, imports);
679
+
680
+ return __wbg_finalize_init(instance, module);
681
+ }
682
+
683
+ export { initSync, __wbg_init as default };
services/explorer/dist/static/usd-reader/79236f8/wasm/usd_wasm_bg.wasm ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:af8aa7e87080ade38ae5c9912a16f046dedaaa0f3c21a00ed3aef25a75e47811
3
+ size 2320130
services/explorer/dist/third-party-notices.txt CHANGED
@@ -1,9 +1,9 @@
1
- Third-party notices — SimReady Central Explorer slim-ui-b62bb449
2
 
3
  The software in this web application's browser bundle includes the packages below, each under its own
4
  license. Each entry gives the package, its version, its license and the license / notice text it ships.
5
 
6
- 31 third-party packages: Apache-2.0 2, MIT 29
7
  7 NVIDIA packages: @kui-contrib/brand-logo, @kui/foundations-css, @kui/foundations-react, @kui/foundations-react-core, @omniverse/auth, @omniverse/discovery, @omniverse/idl
8
 
9
  ====================================================================================================
@@ -1310,6 +1310,1463 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1310
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1311
  THE SOFTWARE.
1312
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1313
  ====================================================================================================
1314
  ====================================================================================================
1315
  NVIDIA packages (NVIDIA's own software in the bundle, listed for the record)
 
1
+ Third-party notices — SimReady Central Explorer slim-ui-6262a66a
2
 
3
  The software in this web application's browser bundle includes the packages below, each under its own
4
  license. Each entry gives the package, its version, its license and the license / notice text it ships.
5
 
6
+ 32 third-party packages: Apache-2.0 2, MIT 29, MIT AND Unicode-3.0 AND Zlib AND Apache-2.0 1
7
  7 NVIDIA packages: @kui-contrib/brand-logo, @kui/foundations-css, @kui/foundations-react, @kui/foundations-react-core, @omniverse/auth, @omniverse/discovery, @omniverse/idl
8
 
9
  ====================================================================================================
 
1310
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1311
  THE SOFTWARE.
1312
 
1313
+ ====================================================================================================
1314
+ usd-web-viewer (Web USD reader) (copied out of usd-web-viewer 0.1.0)
1315
+ License: MIT AND Unicode-3.0 AND Zlib AND Apache-2.0
1316
+ Homepage: https://github.com/cfahlgren1/usd-web-viewer
1317
+ ----------------------------------------------------------------------------------------------------
1318
+ [usd-web-viewer/LICENSE]
1319
+
1320
+ MIT License
1321
+
1322
+ Copyright (c) 2026 Caleb Fahlgren
1323
+
1324
+ Permission is hereby granted, free of charge, to any person obtaining a copy
1325
+ of this software and associated documentation files (the "Software"), to deal
1326
+ in the Software without restriction, including without limitation the rights
1327
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1328
+ copies of the Software, and to permit persons to whom the Software is
1329
+ furnished to do so, subject to the following conditions:
1330
+
1331
+ The above copyright notice and this permission notice shall be included in all
1332
+ copies or substantial portions of the Software.
1333
+
1334
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1335
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1336
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1337
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1338
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1339
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1340
+ SOFTWARE.
1341
+ ----------------------------------------------------------------------------------------------------
1342
+ [usd-web-viewer/THIRD_PARTY_LICENSES]
1343
+
1344
+ Third-party software linked into the WebAssembly module (wasm/usd_wasm_bg.wasm).
1345
+ Generated by scripts/third-party-licenses.mjs from Cargo.lock.
1346
+
1347
+ bitflags 2.13.2: MIT OR Apache-2.0, used under MIT (https://github.com/bitflags/bitflags)
1348
+ bumpalo 3.20.3: MIT OR Apache-2.0, used under MIT (https://github.com/fitzgen/bumpalo)
1349
+ bytemuck 1.25.2: Zlib OR Apache-2.0 OR MIT, used under MIT (https://github.com/Lokathor/bytemuck)
1350
+ cfg-if 1.0.5: MIT OR Apache-2.0, used under MIT (https://github.com/rust-lang/cfg-if)
1351
+ crc32fast 1.5.2: MIT OR Apache-2.0, used under MIT (https://github.com/srijs/rust-crc32fast)
1352
+ derive_more 2.1.1: MIT (https://github.com/JelteF/derive_more)
1353
+ equivalent 1.0.2: Apache-2.0 OR MIT, used under MIT (https://github.com/indexmap-rs/equivalent)
1354
+ flate2 1.1.10: MIT OR Apache-2.0, used under MIT (https://github.com/rust-lang/flate2-rs)
1355
+ half 2.7.1: MIT OR Apache-2.0, used under MIT (https://github.com/VoidStarKat/half-rs)
1356
+ hashbrown 0.17.1: MIT OR Apache-2.0, used under MIT (https://github.com/rust-lang/hashbrown)
1357
+ indexmap 2.14.2: Apache-2.0 OR MIT, used under MIT (https://github.com/indexmap-rs/indexmap)
1358
+ libm 0.2.16: MIT (https://github.com/rust-lang/compiler-builtins)
1359
+ log 0.4.34: MIT OR Apache-2.0, used under MIT (https://github.com/rust-lang/log)
1360
+ logos 0.16.1: MIT OR Apache-2.0, used under MIT (https://github.com/maciejhirsz/logos)
1361
+ lz4_flex 0.14.0: MIT (https://github.com/pseitz/lz4_flex)
1362
+ memchr 2.8.3: Unlicense OR MIT, used under MIT (https://github.com/BurntSushi/memchr)
1363
+ num-traits 0.2.19: MIT OR Apache-2.0, used under MIT (https://github.com/rust-num/num-traits)
1364
+ once_cell 1.21.4: MIT OR Apache-2.0, used under MIT (https://github.com/matklad/once_cell)
1365
+ openusd 0.8.0: MIT (https://github.com/mxpv/openusd)
1366
+ openusd-schemas 0.8.0: MIT (https://github.com/mxpv/openusd)
1367
+ regex-lite 0.1.9: MIT OR Apache-2.0, used under MIT (https://github.com/rust-lang/regex)
1368
+ simd-adler32 0.3.10: MIT (https://github.com/mcountryman/simd-adler32)
1369
+ strum 0.28.0: MIT (https://github.com/Peternator7/strum)
1370
+ thiserror 2.0.21: MIT OR Apache-2.0, used under MIT (https://github.com/dtolnay/thiserror)
1371
+ twox-hash 2.1.5: MIT (https://github.com/shepmaster/twox-hash)
1372
+ typed-path 0.12.3: MIT OR Apache-2.0, used under MIT (https://github.com/chipsenkbeil/typed-path)
1373
+ unicode-ident 1.0.26: (MIT OR Apache-2.0) AND Unicode-3.0, used under MIT AND Unicode-3.0 (https://github.com/dtolnay/unicode-ident)
1374
+ wasm-bindgen 0.2.129: MIT OR Apache-2.0, used under MIT (https://github.com/wasm-bindgen/wasm-bindgen)
1375
+ wasm-bindgen-shared 0.2.129: MIT OR Apache-2.0, used under MIT (https://github.com/wasm-bindgen/wasm-bindgen/tree/master/crates/shared)
1376
+ zerocopy 0.8.62: BSD-2-Clause OR Apache-2.0 OR MIT, used under MIT (https://github.com/google/zerocopy)
1377
+ zip 8.6.0: MIT (https://github.com/zip-rs/zip2)
1378
+ zip 9.0.2: MIT (https://github.com/zip-rs/zip2)
1379
+ zlib-rs 0.6.8: Zlib (https://github.com/trifectatechfoundation/zlib-rs)
1380
+ zopfli 0.8.3: Apache-2.0 (https://github.com/zopfli-rs/zopfli)
1381
+
1382
+ ================================================================================
1383
+ bitflags 2.13.2: LICENSE-MIT
1384
+ ================================================================================
1385
+
1386
+ Copyright (c) 2014 The Rust Project Developers
1387
+
1388
+ Permission is hereby granted, free of charge, to any
1389
+ person obtaining a copy of this software and associated
1390
+ documentation files (the "Software"), to deal in the
1391
+ Software without restriction, including without
1392
+ limitation the rights to use, copy, modify, merge,
1393
+ publish, distribute, sublicense, and/or sell copies of
1394
+ the Software, and to permit persons to whom the Software
1395
+ is furnished to do so, subject to the following
1396
+ conditions:
1397
+
1398
+ The above copyright notice and this permission notice
1399
+ shall be included in all copies or substantial portions
1400
+ of the Software.
1401
+
1402
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
1403
+ ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
1404
+ TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
1405
+ PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
1406
+ SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
1407
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
1408
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
1409
+ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
1410
+ DEALINGS IN THE SOFTWARE.
1411
+
1412
+ ================================================================================
1413
+ bumpalo 3.20.3: LICENSE-MIT
1414
+ ================================================================================
1415
+
1416
+ Copyright (c) 2019 Nick Fitzgerald
1417
+
1418
+ Permission is hereby granted, free of charge, to any
1419
+ person obtaining a copy of this software and associated
1420
+ documentation files (the "Software"), to deal in the
1421
+ Software without restriction, including without
1422
+ limitation the rights to use, copy, modify, merge,
1423
+ publish, distribute, sublicense, and/or sell copies of
1424
+ the Software, and to permit persons to whom the Software
1425
+ is furnished to do so, subject to the following
1426
+ conditions:
1427
+
1428
+ The above copyright notice and this permission notice
1429
+ shall be included in all copies or substantial portions
1430
+ of the Software.
1431
+
1432
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
1433
+ ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
1434
+ TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
1435
+ PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
1436
+ SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
1437
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
1438
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
1439
+ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
1440
+ DEALINGS IN THE SOFTWARE.
1441
+
1442
+ ================================================================================
1443
+ bytemuck 1.25.2: LICENSE-MIT
1444
+ ================================================================================
1445
+
1446
+ MIT License
1447
+
1448
+ Copyright (c) 2019 Daniel "Lokathor" Gee.
1449
+
1450
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
1451
+
1452
+ The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.
1453
+
1454
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1455
+
1456
+ ================================================================================
1457
+ cfg-if 1.0.5: LICENSE-MIT
1458
+ ================================================================================
1459
+
1460
+ Copyright (c) 2014 Alex Crichton
1461
+
1462
+ Permission is hereby granted, free of charge, to any
1463
+ person obtaining a copy of this software and associated
1464
+ documentation files (the "Software"), to deal in the
1465
+ Software without restriction, including without
1466
+ limitation the rights to use, copy, modify, merge,
1467
+ publish, distribute, sublicense, and/or sell copies of
1468
+ the Software, and to permit persons to whom the Software
1469
+ is furnished to do so, subject to the following
1470
+ conditions:
1471
+
1472
+ The above copyright notice and this permission notice
1473
+ shall be included in all copies or substantial portions
1474
+ of the Software.
1475
+
1476
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
1477
+ ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
1478
+ TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
1479
+ PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
1480
+ SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
1481
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
1482
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
1483
+ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
1484
+ DEALINGS IN THE SOFTWARE.
1485
+
1486
+ ================================================================================
1487
+ crc32fast 1.5.2: LICENSE-MIT
1488
+ ================================================================================
1489
+
1490
+ MIT License
1491
+
1492
+ Copyright (c) 2018 Sam Rijs, Alex Crichton and contributors
1493
+
1494
+ Permission is hereby granted, free of charge, to any person obtaining a copy
1495
+ of this software and associated documentation files (the "Software"), to deal
1496
+ in the Software without restriction, including without limitation the rights
1497
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1498
+ copies of the Software, and to permit persons to whom the Software is
1499
+ furnished to do so, subject to the following conditions:
1500
+
1501
+ The above copyright notice and this permission notice shall be included in all
1502
+ copies or substantial portions of the Software.
1503
+
1504
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1505
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1506
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1507
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1508
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1509
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1510
+ SOFTWARE.
1511
+
1512
+ ================================================================================
1513
+ derive_more 2.1.1: LICENSE
1514
+ ================================================================================
1515
+
1516
+ The MIT License (MIT)
1517
+
1518
+ Copyright (c) 2016 Jelte Fennema
1519
+
1520
+ Permission is hereby granted, free of charge, to any person obtaining a copy
1521
+ of this software and associated documentation files (the "Software"), to deal
1522
+ in the Software without restriction, including without limitation the rights
1523
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1524
+ copies of the Software, and to permit persons to whom the Software is
1525
+ furnished to do so, subject to the following conditions:
1526
+
1527
+ The above copyright notice and this permission notice shall be included in all
1528
+ copies or substantial portions of the Software.
1529
+
1530
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1531
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1532
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1533
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1534
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1535
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1536
+ SOFTWARE.
1537
+
1538
+ ================================================================================
1539
+ equivalent 1.0.2: LICENSE-MIT
1540
+ ================================================================================
1541
+
1542
+ Copyright (c) 2016--2023
1543
+
1544
+ Permission is hereby granted, free of charge, to any
1545
+ person obtaining a copy of this software and associated
1546
+ documentation files (the "Software"), to deal in the
1547
+ Software without restriction, including without
1548
+ limitation the rights to use, copy, modify, merge,
1549
+ publish, distribute, sublicense, and/or sell copies of
1550
+ the Software, and to permit persons to whom the Software
1551
+ is furnished to do so, subject to the following
1552
+ conditions:
1553
+
1554
+ The above copyright notice and this permission notice
1555
+ shall be included in all copies or substantial portions
1556
+ of the Software.
1557
+
1558
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
1559
+ ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
1560
+ TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
1561
+ PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
1562
+ SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
1563
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
1564
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
1565
+ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
1566
+ DEALINGS IN THE SOFTWARE.
1567
+
1568
+ ================================================================================
1569
+ flate2 1.1.10: LICENSE-MIT
1570
+ ================================================================================
1571
+
1572
+ Copyright (c) 2014-2026 Alex Crichton
1573
+
1574
+ Permission is hereby granted, free of charge, to any
1575
+ person obtaining a copy of this software and associated
1576
+ documentation files (the "Software"), to deal in the
1577
+ Software without restriction, including without
1578
+ limitation the rights to use, copy, modify, merge,
1579
+ publish, distribute, sublicense, and/or sell copies of
1580
+ the Software, and to permit persons to whom the Software
1581
+ is furnished to do so, subject to the following
1582
+ conditions:
1583
+
1584
+ The above copyright notice and this permission notice
1585
+ shall be included in all copies or substantial portions
1586
+ of the Software.
1587
+
1588
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
1589
+ ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
1590
+ TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
1591
+ PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
1592
+ SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
1593
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
1594
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
1595
+ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
1596
+ DEALINGS IN THE SOFTWARE.
1597
+
1598
+ ================================================================================
1599
+ half 2.7.1: LICENSE-MIT
1600
+ ================================================================================
1601
+
1602
+ MIT License
1603
+
1604
+ Permission is hereby granted, free of charge, to any person obtaining a copy
1605
+ of this software and associated documentation files (the "Software"), to deal
1606
+ in the Software without restriction, including without limitation the rights
1607
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1608
+ copies of the Software, and to permit persons to whom the Software is
1609
+ furnished to do so, subject to the following conditions:
1610
+
1611
+ The above copyright notice and this permission notice shall be included in all
1612
+ copies or substantial portions of the Software.
1613
+
1614
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1615
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1616
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1617
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1618
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1619
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1620
+ SOFTWARE.
1621
+
1622
+ ================================================================================
1623
+ hashbrown 0.17.1: LICENSE-MIT
1624
+ ================================================================================
1625
+
1626
+ Copyright (c) 2016 Amanieu d'Antras
1627
+
1628
+ Permission is hereby granted, free of charge, to any
1629
+ person obtaining a copy of this software and associated
1630
+ documentation files (the "Software"), to deal in the
1631
+ Software without restriction, including without
1632
+ limitation the rights to use, copy, modify, merge,
1633
+ publish, distribute, sublicense, and/or sell copies of
1634
+ the Software, and to permit persons to whom the Software
1635
+ is furnished to do so, subject to the following
1636
+ conditions:
1637
+
1638
+ The above copyright notice and this permission notice
1639
+ shall be included in all copies or substantial portions
1640
+ of the Software.
1641
+
1642
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
1643
+ ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
1644
+ TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
1645
+ PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
1646
+ SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
1647
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
1648
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
1649
+ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
1650
+ DEALINGS IN THE SOFTWARE.
1651
+
1652
+ ================================================================================
1653
+ indexmap 2.14.2: LICENSE-MIT
1654
+ ================================================================================
1655
+
1656
+ Copyright (c) 2016--2017
1657
+
1658
+ Permission is hereby granted, free of charge, to any
1659
+ person obtaining a copy of this software and associated
1660
+ documentation files (the "Software"), to deal in the
1661
+ Software without restriction, including without
1662
+ limitation the rights to use, copy, modify, merge,
1663
+ publish, distribute, sublicense, and/or sell copies of
1664
+ the Software, and to permit persons to whom the Software
1665
+ is furnished to do so, subject to the following
1666
+ conditions:
1667
+
1668
+ The above copyright notice and this permission notice
1669
+ shall be included in all copies or substantial portions
1670
+ of the Software.
1671
+
1672
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
1673
+ ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
1674
+ TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
1675
+ PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
1676
+ SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
1677
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
1678
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
1679
+ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
1680
+ DEALINGS IN THE SOFTWARE.
1681
+
1682
+ ================================================================================
1683
+ libm 0.2.16: LICENSE.txt
1684
+ ================================================================================
1685
+
1686
+ rust-lang/libm as a whole is available for use under the MIT license:
1687
+
1688
+ ------------------------------------------------------------------------------
1689
+ Permission is hereby granted, free of charge, to any person obtaining a copy
1690
+ of this software and associated documentation files (the "Software"), to deal
1691
+ in the Software without restriction, including without limitation the rights
1692
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1693
+ copies of the Software, and to permit persons to whom the Software is
1694
+ furnished to do so, subject to the following conditions:
1695
+
1696
+ The above copyright notice and this permission notice shall be included in all
1697
+ copies or substantial portions of the Software.
1698
+
1699
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1700
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1701
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1702
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1703
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1704
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1705
+ SOFTWARE.
1706
+ ------------------------------------------------------------------------------
1707
+
1708
+ As a contributor, you agree that your code can be used under either the MIT
1709
+ license or the Apache-2.0 license:
1710
+
1711
+ ------------------------------------------------------------------------------
1712
+ Apache License
1713
+ Version 2.0, January 2004
1714
+ http://www.apache.org/licenses/
1715
+
1716
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1717
+
1718
+ 1. Definitions.
1719
+
1720
+ "License" shall mean the terms and conditions for use, reproduction,
1721
+ and distribution as defined by Sections 1 through 9 of this document.
1722
+
1723
+ "Licensor" shall mean the copyright owner or entity authorized by
1724
+ the copyright owner that is granting the License.
1725
+
1726
+ "Legal Entity" shall mean the union of the acting entity and all
1727
+ other entities that control, are controlled by, or are under common
1728
+ control with that entity. For the purposes of this definition,
1729
+ "control" means (i) the power, direct or indirect, to cause the
1730
+ direction or management of such entity, whether by contract or
1731
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
1732
+ outstanding shares, or (iii) beneficial ownership of such entity.
1733
+
1734
+ "You" (or "Your") shall mean an individual or Legal Entity
1735
+ exercising permissions granted by this License.
1736
+
1737
+ "Source" form shall mean the preferred form for making modifications,
1738
+ including but not limited to software source code, documentation
1739
+ source, and configuration files.
1740
+
1741
+ "Object" form shall mean any form resulting from mechanical
1742
+ transformation or translation of a Source form, including but
1743
+ not limited to compiled object code, generated documentation,
1744
+ and conversions to other media types.
1745
+
1746
+ "Work" shall mean the work of authorship, whether in Source or
1747
+ Object form, made available under the License, as indicated by a
1748
+ copyright notice that is included in or attached to the work
1749
+ (an example is provided in the Appendix below).
1750
+
1751
+ "Derivative Works" shall mean any work, whether in Source or Object
1752
+ form, that is based on (or derived from) the Work and for which the
1753
+ editorial revisions, annotations, elaborations, or other modifications
1754
+ represent, as a whole, an original work of authorship. For the purposes
1755
+ of this License, Derivative Works shall not include works that remain
1756
+ separable from, or merely link (or bind by name) to the interfaces of,
1757
+ the Work and Derivative Works thereof.
1758
+
1759
+ "Contribution" shall mean any work of authorship, including
1760
+ the original version of the Work and any modifications or additions
1761
+ to that Work or Derivative Works thereof, that is intentionally
1762
+ submitted to Licensor for inclusion in the Work by the copyright owner
1763
+ or by an individual or Legal Entity authorized to submit on behalf of
1764
+ the copyright owner. For the purposes of this definition, "submitted"
1765
+ means any form of electronic, verbal, or written communication sent
1766
+ to the Licensor or its representatives, including but not limited to
1767
+ communication on electronic mailing lists, source code control systems,
1768
+ and issue tracking systems that are managed by, or on behalf of, the
1769
+ Licensor for the purpose of discussing and improving the Work, but
1770
+ excluding communication that is conspicuously marked or otherwise
1771
+ designated in writing by the copyright owner as "Not a Contribution."
1772
+
1773
+ "Contributor" shall mean Licensor and any individual or Legal Entity
1774
+ on behalf of whom a Contribution has been received by Licensor and
1775
+ subsequently incorporated within the Work.
1776
+
1777
+ 2. Grant of Copyright License. Subject to the terms and conditions of
1778
+ this License, each Contributor hereby grants to You a perpetual,
1779
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
1780
+ copyright license to reproduce, prepare Derivative Works of,
1781
+ publicly display, publicly perform, sublicense, and distribute the
1782
+ Work and such Derivative Works in Source or Object form.
1783
+
1784
+ 3. Grant of Patent License. Subject to the terms and conditions of
1785
+ this License, each Contributor hereby grants to You a perpetual,
1786
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
1787
+ (except as stated in this section) patent license to make, have made,
1788
+ use, offer to sell, sell, import, and otherwise transfer the Work,
1789
+ where such license applies only to those patent claims licensable
1790
+ by such Contributor that are necessarily infringed by their
1791
+ Contribution(s) alone or by combination of their Contribution(s)
1792
+ with the Work to which such Contribution(s) was submitted. If You
1793
+ institute patent litigation against any entity (including a
1794
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
1795
+ or a Contribution incorporated within the Work constitutes direct
1796
+ or contributory patent infringement, then any patent licenses
1797
+ granted to You under this License for that Work shall terminate
1798
+ as of the date such litigation is filed.
1799
+
1800
+ 4. Redistribution. You may reproduce and distribute copies of the
1801
+ Work or Derivative Works thereof in any medium, with or without
1802
+ modifications, and in Source or Object form, provided that You
1803
+ meet the following conditions:
1804
+
1805
+ (a) You must give any other recipients of the Work or
1806
+ Derivative Works a copy of this License; and
1807
+
1808
+ (b) You must cause any modified files to carry prominent notices
1809
+ stating that You changed the files; and
1810
+
1811
+ (c) You must retain, in the Source form of any Derivative Works
1812
+ that You distribute, all copyright, patent, trademark, and
1813
+ attribution notices from the Source form of the Work,
1814
+ excluding those notices that do not pertain to any part of
1815
+ the Derivative Works; and
1816
+
1817
+ (d) If the Work includes a "NOTICE" text file as part of its
1818
+ distribution, then any Derivative Works that You distribute must
1819
+ include a readable copy of the attribution notices contained
1820
+ within such NOTICE file, excluding those notices that do not
1821
+ pertain to any part of the Derivative Works, in at least one
1822
+ of the following places: within a NOTICE text file distributed
1823
+ as part of the Derivative Works; within the Source form or
1824
+ documentation, if provided along with the Derivative Works; or,
1825
+ within a display generated by the Derivative Works, if and
1826
+ wherever such third-party notices normally appear. The contents
1827
+ of the NOTICE file are for informational purposes only and
1828
+ do not modify the License. You may add Your own attribution
1829
+ notices within Derivative Works that You distribute, alongside
1830
+ or as an addendum to the NOTICE text from the Work, provided
1831
+ that such additional attribution notices cannot be construed
1832
+ as modifying the License.
1833
+
1834
+ You may add Your own copyright statement to Your modifications and
1835
+ may provide additional or different license terms and conditions
1836
+ for use, reproduction, or distribution of Your modifications, or
1837
+ for any such Derivative Works as a whole, provided Your use,
1838
+ reproduction, and distribution of the Work otherwise complies with
1839
+ the conditions stated in this License.
1840
+
1841
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
1842
+ any Contribution intentionally submitted for inclusion in the Work
1843
+ by You to the Licensor shall be under the terms and conditions of
1844
+ this License, without any additional terms or conditions.
1845
+ Notwithstanding the above, nothing herein shall supersede or modify
1846
+ the terms of any separate license agreement you may have executed
1847
+ with Licensor regarding such Contributions.
1848
+
1849
+ 6. Trademarks. This License does not grant permission to use the trade
1850
+ names, trademarks, service marks, or product names of the Licensor,
1851
+ except as required for reasonable and customary use in describing the
1852
+ origin of the Work and reproducing the content of the NOTICE file.
1853
+
1854
+ 7. Disclaimer of Warranty. Unless required by applicable law or
1855
+ agreed to in writing, Licensor provides the Work (and each
1856
+ Contributor provides its Contributions) on an "AS IS" BASIS,
1857
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
1858
+ implied, including, without limitation, any warranties or conditions
1859
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
1860
+ PARTICULAR PURPOSE. You are solely responsible for determining the
1861
+ appropriateness of using or redistributing the Work and assume any
1862
+ risks associated with Your exercise of permissions under this License.
1863
+
1864
+ 8. Limitation of Liability. In no event and under no legal theory,
1865
+ whether in tort (including negligence), contract, or otherwise,
1866
+ unless required by applicable law (such as deliberate and grossly
1867
+ negligent acts) or agreed to in writing, shall any Contributor be
1868
+ liable to You for damages, including any direct, indirect, special,
1869
+ incidental, or consequential damages of any character arising as a
1870
+ result of this License or out of the use or inability to use the
1871
+ Work (including but not limited to damages for loss of goodwill,
1872
+ work stoppage, computer failure or malfunction, or any and all
1873
+ other commercial damages or losses), even if such Contributor
1874
+ has been advised of the possibility of such damages.
1875
+
1876
+ 9. Accepting Warranty or Additional Liability. While redistributing
1877
+ the Work or Derivative Works thereof, You may choose to offer,
1878
+ and charge a fee for, acceptance of support, warranty, indemnity,
1879
+ or other liability obligations and/or rights consistent with this
1880
+ License. However, in accepting such obligations, You may act only
1881
+ on Your own behalf and on Your sole responsibility, not on behalf
1882
+ of any other Contributor, and only if You agree to indemnify,
1883
+ defend, and hold each Contributor harmless for any liability
1884
+ incurred by, or claims asserted against, such Contributor by reason
1885
+ of your accepting any such warranty or additional liability.
1886
+
1887
+ END OF TERMS AND CONDITIONS
1888
+
1889
+ APPENDIX: How to apply the Apache License to your work.
1890
+
1891
+ To apply the Apache License to your work, attach the following
1892
+ boilerplate notice, with the fields enclosed by brackets "[]"
1893
+ replaced with your own identifying information. (Don't include
1894
+ the brackets!) The text should be enclosed in the appropriate
1895
+ comment syntax for the file format. We also recommend that a
1896
+ file or class name and description of purpose be included on the
1897
+ same "printed page" as the copyright notice for easier
1898
+ identification within third-party archives.
1899
+
1900
+ Licensed under the Apache License, Version 2.0 (the "License");
1901
+ you may not use this file except in compliance with the License.
1902
+ You may obtain a copy of the License at
1903
+
1904
+ http://www.apache.org/licenses/LICENSE-2.0
1905
+
1906
+ Unless required by applicable law or agreed to in writing, software
1907
+ distributed under the License is distributed on an "AS IS" BASIS,
1908
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1909
+ See the License for the specific language governing permissions and
1910
+ limitations under the License.
1911
+ ------------------------------------------------------------------------------
1912
+
1913
+ This Rust library contains the following copyrights:
1914
+
1915
+ Copyright (c) 2018 Jorge Aparicio
1916
+
1917
+ Portions of this software are derived from third-party works licensed under
1918
+ terms compatible with the above MIT license:
1919
+
1920
+ * musl libc https://www.musl-libc.org/. This library contains the following
1921
+ copyright:
1922
+
1923
+ Copyright © 2005-2020 Rich Felker, et al.
1924
+
1925
+ * The CORE-MATH project https://core-math.gitlabpages.inria.fr/. CORE-MATH
1926
+ routines are available under the MIT license on a per-file basis.
1927
+
1928
+ The musl libc COPYRIGHT file also includes the following notice relevant to
1929
+ math portions of the library:
1930
+
1931
+ ------------------------------------------------------------------------------
1932
+ Much of the math library code (src/math/* and src/complex/*) is
1933
+ Copyright © 1993,2004 Sun Microsystems or
1934
+ Copyright © 2003-2011 David Schultz or
1935
+ Copyright © 2003-2009 Steven G. Kargl or
1936
+ Copyright © 2003-2009 Bruce D. Evans or
1937
+ Copyright © 2008 Stephen L. Moshier or
1938
+ Copyright © 2017-2018 Arm Limited
1939
+ and labelled as such in comments in the individual source files. All
1940
+ have been licensed under extremely permissive terms.
1941
+ ------------------------------------------------------------------------------
1942
+
1943
+ Copyright notices are retained in src/* files where relevant.
1944
+
1945
+ ================================================================================
1946
+ log 0.4.34: LICENSE-MIT
1947
+ ================================================================================
1948
+
1949
+ Copyright (c) 2014 The Rust Project Developers
1950
+
1951
+ Permission is hereby granted, free of charge, to any
1952
+ person obtaining a copy of this software and associated
1953
+ documentation files (the "Software"), to deal in the
1954
+ Software without restriction, including without
1955
+ limitation the rights to use, copy, modify, merge,
1956
+ publish, distribute, sublicense, and/or sell copies of
1957
+ the Software, and to permit persons to whom the Software
1958
+ is furnished to do so, subject to the following
1959
+ conditions:
1960
+
1961
+ The above copyright notice and this permission notice
1962
+ shall be included in all copies or substantial portions
1963
+ of the Software.
1964
+
1965
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
1966
+ ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
1967
+ TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
1968
+ PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
1969
+ SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
1970
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
1971
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
1972
+ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
1973
+ DEALINGS IN THE SOFTWARE.
1974
+
1975
+ ================================================================================
1976
+ logos 0.16.1: LICENSE-MIT
1977
+ ================================================================================
1978
+
1979
+ Copyright (c) 2018 Maciej Hirsz <maciej.hirsz@gmail.com>
1980
+
1981
+ The MIT License (MIT)
1982
+
1983
+ Permission is hereby granted, free of charge, to any person obtaining a copy
1984
+ of this software and associated documentation files (the "Software"), to deal
1985
+ in the Software without restriction, including without limitation the rights
1986
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1987
+ copies of the Software, and to permit persons to whom the Software is
1988
+ furnished to do so, subject to the following conditions:
1989
+
1990
+ The above copyright notice and this permission notice shall be included in all
1991
+ copies or substantial portions of the Software.
1992
+
1993
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1994
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1995
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1996
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1997
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1998
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1999
+ SOFTWARE.
2000
+
2001
+ ================================================================================
2002
+ lz4_flex 0.14.0: LICENSE
2003
+ ================================================================================
2004
+
2005
+ The MIT License (MIT)
2006
+
2007
+ Copyright (c) 2020 Pascal Seitz
2008
+
2009
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
2010
+ this software and associated documentation files (the "Software"), to deal in
2011
+ the Software without restriction, including without limitation the rights to
2012
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
2013
+ the Software, and to permit persons to whom the Software is furnished to do so,
2014
+ subject to the following conditions:
2015
+
2016
+ The above copyright notice and this permission notice shall be included in all
2017
+ copies or substantial portions of the Software.
2018
+
2019
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2020
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
2021
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
2022
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
2023
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2024
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2025
+
2026
+ ================================================================================
2027
+ memchr 2.8.3: LICENSE-MIT
2028
+ ================================================================================
2029
+
2030
+ The MIT License (MIT)
2031
+
2032
+ Copyright (c) 2015 Andrew Gallant
2033
+
2034
+ Permission is hereby granted, free of charge, to any person obtaining a copy
2035
+ of this software and associated documentation files (the "Software"), to deal
2036
+ in the Software without restriction, including without limitation the rights
2037
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2038
+ copies of the Software, and to permit persons to whom the Software is
2039
+ furnished to do so, subject to the following conditions:
2040
+
2041
+ The above copyright notice and this permission notice shall be included in
2042
+ all copies or substantial portions of the Software.
2043
+
2044
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2045
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2046
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2047
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2048
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2049
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2050
+ THE SOFTWARE.
2051
+
2052
+ ================================================================================
2053
+ num-traits 0.2.19: LICENSE-MIT
2054
+ ================================================================================
2055
+
2056
+ Copyright (c) 2014 The Rust Project Developers
2057
+
2058
+ Permission is hereby granted, free of charge, to any
2059
+ person obtaining a copy of this software and associated
2060
+ documentation files (the "Software"), to deal in the
2061
+ Software without restriction, including without
2062
+ limitation the rights to use, copy, modify, merge,
2063
+ publish, distribute, sublicense, and/or sell copies of
2064
+ the Software, and to permit persons to whom the Software
2065
+ is furnished to do so, subject to the following
2066
+ conditions:
2067
+
2068
+ The above copyright notice and this permission notice
2069
+ shall be included in all copies or substantial portions
2070
+ of the Software.
2071
+
2072
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
2073
+ ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
2074
+ TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
2075
+ PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
2076
+ SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
2077
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
2078
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
2079
+ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2080
+ DEALINGS IN THE SOFTWARE.
2081
+
2082
+ ================================================================================
2083
+ once_cell 1.21.4: LICENSE-MIT
2084
+ ================================================================================
2085
+
2086
+ Permission is hereby granted, free of charge, to any
2087
+ person obtaining a copy of this software and associated
2088
+ documentation files (the "Software"), to deal in the
2089
+ Software without restriction, including without
2090
+ limitation the rights to use, copy, modify, merge,
2091
+ publish, distribute, sublicense, and/or sell copies of
2092
+ the Software, and to permit persons to whom the Software
2093
+ is furnished to do so, subject to the following
2094
+ conditions:
2095
+
2096
+ The above copyright notice and this permission notice
2097
+ shall be included in all copies or substantial portions
2098
+ of the Software.
2099
+
2100
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
2101
+ ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
2102
+ TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
2103
+ PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
2104
+ SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
2105
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
2106
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
2107
+ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2108
+ DEALINGS IN THE SOFTWARE.
2109
+
2110
+ ================================================================================
2111
+ openusd 0.8.0: LICENSE
2112
+ ================================================================================
2113
+
2114
+ MIT License
2115
+
2116
+ Copyright (c) 2024 Maksym Pavlenko
2117
+
2118
+ Permission is hereby granted, free of charge, to any person obtaining a copy
2119
+ of this software and associated documentation files (the "Software"), to deal
2120
+ in the Software without restriction, including without limitation the rights
2121
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2122
+ copies of the Software, and to permit persons to whom the Software is
2123
+ furnished to do so, subject to the following conditions:
2124
+
2125
+ The above copyright notice and this permission notice shall be included in all
2126
+ copies or substantial portions of the Software.
2127
+
2128
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2129
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2130
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2131
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2132
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2133
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2134
+ SOFTWARE.
2135
+
2136
+ ================================================================================
2137
+ openusd-schemas 0.8.0: LICENSE
2138
+ ================================================================================
2139
+
2140
+ MIT License
2141
+
2142
+ Copyright (c) 2024 Maksym Pavlenko
2143
+
2144
+ Permission is hereby granted, free of charge, to any person obtaining a copy
2145
+ of this software and associated documentation files (the "Software"), to deal
2146
+ in the Software without restriction, including without limitation the rights
2147
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2148
+ copies of the Software, and to permit persons to whom the Software is
2149
+ furnished to do so, subject to the following conditions:
2150
+
2151
+ The above copyright notice and this permission notice shall be included in all
2152
+ copies or substantial portions of the Software.
2153
+
2154
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2155
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2156
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2157
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2158
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2159
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2160
+ SOFTWARE.
2161
+
2162
+ ================================================================================
2163
+ regex-lite 0.1.9: LICENSE-MIT
2164
+ ================================================================================
2165
+
2166
+ Copyright (c) 2014 The Rust Project Developers
2167
+
2168
+ Permission is hereby granted, free of charge, to any
2169
+ person obtaining a copy of this software and associated
2170
+ documentation files (the "Software"), to deal in the
2171
+ Software without restriction, including without
2172
+ limitation the rights to use, copy, modify, merge,
2173
+ publish, distribute, sublicense, and/or sell copies of
2174
+ the Software, and to permit persons to whom the Software
2175
+ is furnished to do so, subject to the following
2176
+ conditions:
2177
+
2178
+ The above copyright notice and this permission notice
2179
+ shall be included in all copies or substantial portions
2180
+ of the Software.
2181
+
2182
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
2183
+ ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
2184
+ TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
2185
+ PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
2186
+ SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
2187
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
2188
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
2189
+ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2190
+ DEALINGS IN THE SOFTWARE.
2191
+
2192
+ ================================================================================
2193
+ simd-adler32 0.3.10: LICENSE.md
2194
+ ================================================================================
2195
+
2196
+ MIT License
2197
+
2198
+ Copyright (c) [2021] [Marvin Countryman]
2199
+
2200
+ Permission is hereby granted, free of charge, to any person obtaining a copy
2201
+ of this software and associated documentation files (the "Software"), to deal
2202
+ in the Software without restriction, including without limitation the rights
2203
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2204
+ copies of the Software, and to permit persons to whom the Software is
2205
+ furnished to do so, subject to the following conditions:
2206
+
2207
+ The above copyright notice and this permission notice shall be included in all
2208
+ copies or substantial portions of the Software.
2209
+
2210
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2211
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2212
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2213
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2214
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2215
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2216
+ SOFTWARE.
2217
+
2218
+ ================================================================================
2219
+ strum 0.28.0: LICENSE
2220
+ ================================================================================
2221
+
2222
+ MIT License
2223
+
2224
+ Copyright (c) 2019 Peter Glotfelty
2225
+
2226
+ Permission is hereby granted, free of charge, to any person obtaining a copy
2227
+ of this software and associated documentation files (the "Software"), to deal
2228
+ in the Software without restriction, including without limitation the rights
2229
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2230
+ copies of the Software, and to permit persons to whom the Software is
2231
+ furnished to do so, subject to the following conditions:
2232
+
2233
+ The above copyright notice and this permission notice shall be included in all
2234
+ copies or substantial portions of the Software.
2235
+
2236
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2237
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2238
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2239
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2240
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2241
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2242
+ SOFTWARE.
2243
+
2244
+ ================================================================================
2245
+ thiserror 2.0.21: LICENSE-MIT
2246
+ ================================================================================
2247
+
2248
+ Permission is hereby granted, free of charge, to any
2249
+ person obtaining a copy of this software and associated
2250
+ documentation files (the "Software"), to deal in the
2251
+ Software without restriction, including without
2252
+ limitation the rights to use, copy, modify, merge,
2253
+ publish, distribute, sublicense, and/or sell copies of
2254
+ the Software, and to permit persons to whom the Software
2255
+ is furnished to do so, subject to the following
2256
+ conditions:
2257
+
2258
+ The above copyright notice and this permission notice
2259
+ shall be included in all copies or substantial portions
2260
+ of the Software.
2261
+
2262
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
2263
+ ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
2264
+ TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
2265
+ PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
2266
+ SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
2267
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
2268
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
2269
+ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2270
+ DEALINGS IN THE SOFTWARE.
2271
+
2272
+ ================================================================================
2273
+ twox-hash 2.1.5: LICENSE.txt
2274
+ ================================================================================
2275
+
2276
+ The MIT License (MIT)
2277
+
2278
+ Copyright (c) 2015 Jake Goulding
2279
+
2280
+ Permission is hereby granted, free of charge, to any person obtaining a copy
2281
+ of this software and associated documentation files (the "Software"), to deal
2282
+ in the Software without restriction, including without limitation the rights
2283
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2284
+ copies of the Software, and to permit persons to whom the Software is
2285
+ furnished to do so, subject to the following conditions:
2286
+
2287
+ The above copyright notice and this permission notice shall be included in all
2288
+ copies or substantial portions of the Software.
2289
+
2290
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2291
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2292
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2293
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2294
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2295
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2296
+ SOFTWARE.
2297
+
2298
+ ================================================================================
2299
+ typed-path 0.12.3: LICENSE-MIT
2300
+ ================================================================================
2301
+
2302
+ Permission is hereby granted, free of charge, to any
2303
+ person obtaining a copy of this software and associated
2304
+ documentation files (the "Software"), to deal in the
2305
+ Software without restriction, including without
2306
+ limitation the rights to use, copy, modify, merge,
2307
+ publish, distribute, sublicense, and/or sell copies of
2308
+ the Software, and to permit persons to whom the Software
2309
+ is furnished to do so, subject to the following
2310
+ conditions:
2311
+
2312
+ The above copyright notice and this permission notice
2313
+ shall be included in all copies or substantial portions
2314
+ of the Software.
2315
+
2316
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
2317
+ ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
2318
+ TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
2319
+ PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
2320
+ SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
2321
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
2322
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
2323
+ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2324
+ DEALINGS IN THE SOFTWARE.
2325
+
2326
+ ================================================================================
2327
+ unicode-ident 1.0.26: LICENSE-MIT
2328
+ ================================================================================
2329
+
2330
+ Permission is hereby granted, free of charge, to any
2331
+ person obtaining a copy of this software and associated
2332
+ documentation files (the "Software"), to deal in the
2333
+ Software without restriction, including without
2334
+ limitation the rights to use, copy, modify, merge,
2335
+ publish, distribute, sublicense, and/or sell copies of
2336
+ the Software, and to permit persons to whom the Software
2337
+ is furnished to do so, subject to the following
2338
+ conditions:
2339
+
2340
+ The above copyright notice and this permission notice
2341
+ shall be included in all copies or substantial portions
2342
+ of the Software.
2343
+
2344
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
2345
+ ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
2346
+ TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
2347
+ PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
2348
+ SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
2349
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
2350
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
2351
+ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2352
+ DEALINGS IN THE SOFTWARE.
2353
+
2354
+ ================================================================================
2355
+ unicode-ident 1.0.26: LICENSE-UNICODE
2356
+ ================================================================================
2357
+
2358
+ UNICODE LICENSE V3
2359
+
2360
+ COPYRIGHT AND PERMISSION NOTICE
2361
+
2362
+ Copyright © 1991-2023 Unicode, Inc.
2363
+
2364
+ NOTICE TO USER: Carefully read the following legal agreement. BY
2365
+ DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR
2366
+ SOFTWARE, YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
2367
+ TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT
2368
+ DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE.
2369
+
2370
+ Permission is hereby granted, free of charge, to any person obtaining a
2371
+ copy of data files and any associated documentation (the "Data Files") or
2372
+ software and any associated documentation (the "Software") to deal in the
2373
+ Data Files or Software without restriction, including without limitation
2374
+ the rights to use, copy, modify, merge, publish, distribute, and/or sell
2375
+ copies of the Data Files or Software, and to permit persons to whom the
2376
+ Data Files or Software are furnished to do so, provided that either (a)
2377
+ this copyright and permission notice appear with all copies of the Data
2378
+ Files or Software, or (b) this copyright and permission notice appear in
2379
+ associated Documentation.
2380
+
2381
+ THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
2382
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2383
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
2384
+ THIRD PARTY RIGHTS.
2385
+
2386
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE
2387
+ BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES,
2388
+ OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
2389
+ WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
2390
+ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA
2391
+ FILES OR SOFTWARE.
2392
+
2393
+ Except as contained in this notice, the name of a copyright holder shall
2394
+ not be used in advertising or otherwise to promote the sale, use or other
2395
+ dealings in these Data Files or Software without prior written
2396
+ authorization of the copyright holder.
2397
+
2398
+ ================================================================================
2399
+ wasm-bindgen 0.2.129: LICENSE-MIT
2400
+ ================================================================================
2401
+
2402
+ Copyright (c) 2014 Alex Crichton
2403
+
2404
+ Permission is hereby granted, free of charge, to any
2405
+ person obtaining a copy of this software and associated
2406
+ documentation files (the "Software"), to deal in the
2407
+ Software without restriction, including without
2408
+ limitation the rights to use, copy, modify, merge,
2409
+ publish, distribute, sublicense, and/or sell copies of
2410
+ the Software, and to permit persons to whom the Software
2411
+ is furnished to do so, subject to the following
2412
+ conditions:
2413
+
2414
+ The above copyright notice and this permission notice
2415
+ shall be included in all copies or substantial portions
2416
+ of the Software.
2417
+
2418
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
2419
+ ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
2420
+ TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
2421
+ PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
2422
+ SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
2423
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
2424
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
2425
+ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2426
+ DEALINGS IN THE SOFTWARE.
2427
+
2428
+ ================================================================================
2429
+ wasm-bindgen-shared 0.2.129: LICENSE-MIT
2430
+ ================================================================================
2431
+
2432
+ Copyright (c) 2014 Alex Crichton
2433
+
2434
+ Permission is hereby granted, free of charge, to any
2435
+ person obtaining a copy of this software and associated
2436
+ documentation files (the "Software"), to deal in the
2437
+ Software without restriction, including without
2438
+ limitation the rights to use, copy, modify, merge,
2439
+ publish, distribute, sublicense, and/or sell copies of
2440
+ the Software, and to permit persons to whom the Software
2441
+ is furnished to do so, subject to the following
2442
+ conditions:
2443
+
2444
+ The above copyright notice and this permission notice
2445
+ shall be included in all copies or substantial portions
2446
+ of the Software.
2447
+
2448
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
2449
+ ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
2450
+ TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
2451
+ PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
2452
+ SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
2453
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
2454
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
2455
+ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2456
+ DEALINGS IN THE SOFTWARE.
2457
+
2458
+ ================================================================================
2459
+ zerocopy 0.8.62: LICENSE-MIT
2460
+ ================================================================================
2461
+
2462
+ Copyright 2023 The Fuchsia Authors
2463
+
2464
+ Permission is hereby granted, free of charge, to any
2465
+ person obtaining a copy of this software and associated
2466
+ documentation files (the "Software"), to deal in the
2467
+ Software without restriction, including without
2468
+ limitation the rights to use, copy, modify, merge,
2469
+ publish, distribute, sublicense, and/or sell copies of
2470
+ the Software, and to permit persons to whom the Software
2471
+ is furnished to do so, subject to the following
2472
+ conditions:
2473
+
2474
+ The above copyright notice and this permission notice
2475
+ shall be included in all copies or substantial portions
2476
+ of the Software.
2477
+
2478
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
2479
+ ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
2480
+ TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
2481
+ PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
2482
+ SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
2483
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
2484
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
2485
+ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2486
+ DEALINGS IN THE SOFTWARE.
2487
+
2488
+ ================================================================================
2489
+ zip 8.6.0: LICENSE
2490
+ ================================================================================
2491
+
2492
+ The MIT License (MIT)
2493
+
2494
+ Copyright (c) 2014 Mathijs van de Nes
2495
+
2496
+ Permission is hereby granted, free of charge, to any person obtaining a copy
2497
+ of this software and associated documentation files (the "Software"), to deal
2498
+ in the Software without restriction, including without limitation the rights
2499
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2500
+ copies of the Software, and to permit persons to whom the Software is
2501
+ furnished to do so, subject to the following conditions:
2502
+
2503
+ The above copyright notice and this permission notice shall be included in all
2504
+ copies or substantial portions of the Software.
2505
+
2506
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2507
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2508
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2509
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2510
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2511
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2512
+ SOFTWARE.
2513
+
2514
+ ================================================================================
2515
+ zip 9.0.2: LICENSE
2516
+ ================================================================================
2517
+
2518
+ The MIT License (MIT)
2519
+
2520
+ Copyright (c) 2014 Mathijs van de Nes
2521
+
2522
+ Permission is hereby granted, free of charge, to any person obtaining a copy
2523
+ of this software and associated documentation files (the "Software"), to deal
2524
+ in the Software without restriction, including without limitation the rights
2525
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2526
+ copies of the Software, and to permit persons to whom the Software is
2527
+ furnished to do so, subject to the following conditions:
2528
+
2529
+ The above copyright notice and this permission notice shall be included in all
2530
+ copies or substantial portions of the Software.
2531
+
2532
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2533
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2534
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2535
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2536
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2537
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2538
+ SOFTWARE.
2539
+
2540
+ ================================================================================
2541
+ zlib-rs 0.6.8: LICENSE
2542
+ ================================================================================
2543
+
2544
+ (C) 2024 Trifecta Tech Foundation
2545
+
2546
+ This software is provided 'as-is', without any express or implied
2547
+ warranty. In no event will the authors be held liable for any damages
2548
+ arising from the use of this software.
2549
+
2550
+ Permission is granted to anyone to use this software for any purpose,
2551
+ including commercial applications, and to alter it and redistribute it
2552
+ freely, subject to the following restrictions:
2553
+
2554
+ 1. The origin of this software must not be misrepresented; you must not
2555
+ claim that you wrote the original software. If you use this software
2556
+ in a product, an acknowledgment in the product documentation would be
2557
+ appreciated but is not required.
2558
+
2559
+ 2. Altered source versions must be plainly marked as such, and must not be
2560
+ misrepresented as being the original software.
2561
+
2562
+ 3. This notice may not be removed or altered from any source distribution.
2563
+
2564
+ ================================================================================
2565
+ zopfli 0.8.3: COPYING
2566
+ ================================================================================
2567
+
2568
+ Apache License
2569
+ Version 2.0, January 2004
2570
+ http://www.apache.org/licenses/
2571
+
2572
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
2573
+
2574
+ 1. Definitions.
2575
+
2576
+ "License" shall mean the terms and conditions for use, reproduction,
2577
+ and distribution as defined by Sections 1 through 9 of this document.
2578
+
2579
+ "Licensor" shall mean the copyright owner or entity authorized by
2580
+ the copyright owner that is granting the License.
2581
+
2582
+ "Legal Entity" shall mean the union of the acting entity and all
2583
+ other entities that control, are controlled by, or are under common
2584
+ control with that entity. For the purposes of this definition,
2585
+ "control" means (i) the power, direct or indirect, to cause the
2586
+ direction or management of such entity, whether by contract or
2587
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
2588
+ outstanding shares, or (iii) beneficial ownership of such entity.
2589
+
2590
+ "You" (or "Your") shall mean an individual or Legal Entity
2591
+ exercising permissions granted by this License.
2592
+
2593
+ "Source" form shall mean the preferred form for making modifications,
2594
+ including but not limited to software source code, documentation
2595
+ source, and configuration files.
2596
+
2597
+ "Object" form shall mean any form resulting from mechanical
2598
+ transformation or translation of a Source form, including but
2599
+ not limited to compiled object code, generated documentation,
2600
+ and conversions to other media types.
2601
+
2602
+ "Work" shall mean the work of authorship, whether in Source or
2603
+ Object form, made available under the License, as indicated by a
2604
+ copyright notice that is included in or attached to the work
2605
+ (an example is provided in the Appendix below).
2606
+
2607
+ "Derivative Works" shall mean any work, whether in Source or Object
2608
+ form, that is based on (or derived from) the Work and for which the
2609
+ editorial revisions, annotations, elaborations, or other modifications
2610
+ represent, as a whole, an original work of authorship. For the purposes
2611
+ of this License, Derivative Works shall not include works that remain
2612
+ separable from, or merely link (or bind by name) to the interfaces of,
2613
+ the Work and Derivative Works thereof.
2614
+
2615
+ "Contribution" shall mean any work of authorship, including
2616
+ the original version of the Work and any modifications or additions
2617
+ to that Work or Derivative Works thereof, that is intentionally
2618
+ submitted to Licensor for inclusion in the Work by the copyright owner
2619
+ or by an individual or Legal Entity authorized to submit on behalf of
2620
+ the copyright owner. For the purposes of this definition, "submitted"
2621
+ means any form of electronic, verbal, or written communication sent
2622
+ to the Licensor or its representatives, including but not limited to
2623
+ communication on electronic mailing lists, source code control systems,
2624
+ and issue tracking systems that are managed by, or on behalf of, the
2625
+ Licensor for the purpose of discussing and improving the Work, but
2626
+ excluding communication that is conspicuously marked or otherwise
2627
+ designated in writing by the copyright owner as "Not a Contribution."
2628
+
2629
+ "Contributor" shall mean Licensor and any individual or Legal Entity
2630
+ on behalf of whom a Contribution has been received by Licensor and
2631
+ subsequently incorporated within the Work.
2632
+
2633
+ 2. Grant of Copyright License. Subject to the terms and conditions of
2634
+ this License, each Contributor hereby grants to You a perpetual,
2635
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
2636
+ copyright license to reproduce, prepare Derivative Works of,
2637
+ publicly display, publicly perform, sublicense, and distribute the
2638
+ Work and such Derivative Works in Source or Object form.
2639
+
2640
+ 3. Grant of Patent License. Subject to the terms and conditions of
2641
+ this License, each Contributor hereby grants to You a perpetual,
2642
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
2643
+ (except as stated in this section) patent license to make, have made,
2644
+ use, offer to sell, sell, import, and otherwise transfer the Work,
2645
+ where such license applies only to those patent claims licensable
2646
+ by such Contributor that are necessarily infringed by their
2647
+ Contribution(s) alone or by combination of their Contribution(s)
2648
+ with the Work to which such Contribution(s) was submitted. If You
2649
+ institute patent litigation against any entity (including a
2650
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
2651
+ or a Contribution incorporated within the Work constitutes direct
2652
+ or contributory patent infringement, then any patent licenses
2653
+ granted to You under this License for that Work shall terminate
2654
+ as of the date such litigation is filed.
2655
+
2656
+ 4. Redistribution. You may reproduce and distribute copies of the
2657
+ Work or Derivative Works thereof in any medium, with or without
2658
+ modifications, and in Source or Object form, provided that You
2659
+ meet the following conditions:
2660
+
2661
+ (a) You must give any other recipients of the Work or
2662
+ Derivative Works a copy of this License; and
2663
+
2664
+ (b) You must cause any modified files to carry prominent notices
2665
+ stating that You changed the files; and
2666
+
2667
+ (c) You must retain, in the Source form of any Derivative Works
2668
+ that You distribute, all copyright, patent, trademark, and
2669
+ attribution notices from the Source form of the Work,
2670
+ excluding those notices that do not pertain to any part of
2671
+ the Derivative Works; and
2672
+
2673
+ (d) If the Work includes a "NOTICE" text file as part of its
2674
+ distribution, then any Derivative Works that You distribute must
2675
+ include a readable copy of the attribution notices contained
2676
+ within such NOTICE file, excluding those notices that do not
2677
+ pertain to any part of the Derivative Works, in at least one
2678
+ of the following places: within a NOTICE text file distributed
2679
+ as part of the Derivative Works; within the Source form or
2680
+ documentation, if provided along with the Derivative Works; or,
2681
+ within a display generated by the Derivative Works, if and
2682
+ wherever such third-party notices normally appear. The contents
2683
+ of the NOTICE file are for informational purposes only and
2684
+ do not modify the License. You may add Your own attribution
2685
+ notices within Derivative Works that You distribute, alongside
2686
+ or as an addendum to the NOTICE text from the Work, provided
2687
+ that such additional attribution notices cannot be construed
2688
+ as modifying the License.
2689
+
2690
+ You may add Your own copyright statement to Your modifications and
2691
+ may provide additional or different license terms and conditions
2692
+ for use, reproduction, or distribution of Your modifications, or
2693
+ for any such Derivative Works as a whole, provided Your use,
2694
+ reproduction, and distribution of the Work otherwise complies with
2695
+ the conditions stated in this License.
2696
+
2697
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
2698
+ any Contribution intentionally submitted for inclusion in the Work
2699
+ by You to the Licensor shall be under the terms and conditions of
2700
+ this License, without any additional terms or conditions.
2701
+ Notwithstanding the above, nothing herein shall supersede or modify
2702
+ the terms of any separate license agreement you may have executed
2703
+ with Licensor regarding such Contributions.
2704
+
2705
+ 6. Trademarks. This License does not grant permission to use the trade
2706
+ names, trademarks, service marks, or product names of the Licensor,
2707
+ except as required for reasonable and customary use in describing the
2708
+ origin of the Work and reproducing the content of the NOTICE file.
2709
+
2710
+ 7. Disclaimer of Warranty. Unless required by applicable law or
2711
+ agreed to in writing, Licensor provides the Work (and each
2712
+ Contributor provides its Contributions) on an "AS IS" BASIS,
2713
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
2714
+ implied, including, without limitation, any warranties or conditions
2715
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
2716
+ PARTICULAR PURPOSE. You are solely responsible for determining the
2717
+ appropriateness of using or redistributing the Work and assume any
2718
+ risks associated with Your exercise of permissions under this License.
2719
+
2720
+ 8. Limitation of Liability. In no event and under no legal theory,
2721
+ whether in tort (including negligence), contract, or otherwise,
2722
+ unless required by applicable law (such as deliberate and grossly
2723
+ negligent acts) or agreed to in writing, shall any Contributor be
2724
+ liable to You for damages, including any direct, indirect, special,
2725
+ incidental, or consequential damages of any character arising as a
2726
+ result of this License or out of the use or inability to use the
2727
+ Work (including but not limited to damages for loss of goodwill,
2728
+ work stoppage, computer failure or malfunction, or any and all
2729
+ other commercial damages or losses), even if such Contributor
2730
+ has been advised of the possibility of such damages.
2731
+
2732
+ 9. Accepting Warranty or Additional Liability. While redistributing
2733
+ the Work or Derivative Works thereof, You may choose to offer,
2734
+ and charge a fee for, acceptance of support, warranty, indemnity,
2735
+ or other liability obligations and/or rights consistent with this
2736
+ License. However, in accepting such obligations, You may act only
2737
+ on Your own behalf and on Your sole responsibility, not on behalf
2738
+ of any other Contributor, and only if You agree to indemnify,
2739
+ defend, and hold each Contributor harmless for any liability
2740
+ incurred by, or claims asserted against, such Contributor by reason
2741
+ of your accepting any such warranty or additional liability.
2742
+
2743
+ END OF TERMS AND CONDITIONS
2744
+
2745
+ APPENDIX: How to apply the Apache License to your work.
2746
+
2747
+ To apply the Apache License to your work, attach the following
2748
+ boilerplate notice, with the fields enclosed by brackets "[]"
2749
+ replaced with your own identifying information. (Don't include
2750
+ the brackets!) The text should be enclosed in the appropriate
2751
+ comment syntax for the file format. We also recommend that a
2752
+ file or class name and description of purpose be included on the
2753
+ same "printed page" as the copyright notice for easier
2754
+ identification within third-party archives.
2755
+
2756
+ Copyright 2011 Google Inc.
2757
+
2758
+ Licensed under the Apache License, Version 2.0 (the "License");
2759
+ you may not use this file except in compliance with the License.
2760
+ You may obtain a copy of the License at
2761
+
2762
+ http://www.apache.org/licenses/LICENSE-2.0
2763
+
2764
+ Unless required by applicable law or agreed to in writing, software
2765
+ distributed under the License is distributed on an "AS IS" BASIS,
2766
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2767
+ See the License for the specific language governing permissions and
2768
+ limitations under the License.
2769
+
2770
  ====================================================================================================
2771
  ====================================================================================================
2772
  NVIDIA packages (NVIDIA's own software in the bundle, listed for the record)