Source code for simvx.core.assets.loaders.base
"""Loader base class: parses raw bytes from a Source into a typed asset.
Each Loader owns its own LRU cache keyed on ``(uri, version)``. The
:class:`AssetServer` looks up the loader either by URI suffix
(``.png`` → texture loader) or by the explicit ``loader=`` argument
passed to ``server.load(...)``.
"""
from __future__ import annotations
from collections.abc import Callable
from typing import Any
from ..cache import LRUCache
[docs]
class Loader:
"""Base class for asset-type loaders.
Subclasses override :meth:`parse` to convert raw bytes into a typed
asset. The base class handles caching, size estimation, and the
cache opt-out.
"""
#: File-name suffixes this loader claims (e.g. ``(".png", ".jpg")``).
suffixes: tuple[str, ...] = ()
def __init__(self, *, cache_bytes: int = 256 * 1024 * 1024) -> None:
self.cache = LRUCache(max_bytes=cache_bytes)
[docs]
def parse(self, raw: bytes, uri: str) -> Any:
"""Convert raw bytes from a Source into the typed asset.
Override in subclasses. The default returns the bytes unchanged
(used by :class:`BytesLoader`).
"""
return raw
# ----- Server hooks -------------------------------------------------------
[docs]
def get_cached(self, uri: str, version: str | None) -> Any | None:
return self.cache.get(uri, version)
[docs]
def store(self, uri: str, version: str | None, value: Any) -> None:
self.cache.put(uri, version, value)
[docs]
def claims(self, uri: str) -> bool:
"""Return True if this loader handles *uri* by suffix.
AssetServer iterates registered loaders and picks the first one
that claims the URI; falls back to :class:`BytesLoader`.
"""
if not self.suffixes:
return False
return uri.endswith(self.suffixes)
# Type alias for a function-style loader (rare; subclass Loader instead).
LoaderFunc = Callable[[bytes, str], Any]