Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 18 additions & 5 deletions src/asset/core/parser.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/** @import { Constructor } from '../../reflect/index.js' */
import { throws } from '../../logger/index.js'

/**
Expand All @@ -6,6 +7,19 @@ import { throws } from '../../logger/index.js'
*/
export class Parser {

/**
* @readonly
* @type {Constructor<T>}
*/
asset

/**
* @param {Constructor<T>} asset
*/
constructor(asset) {
this.asset = asset
}

/**
* @param {Response} _response
* @returns {Promise<T | undefined>}
Expand All @@ -17,12 +31,11 @@ export class Parser {
}

/**
* @param {string} _extension
* @returns {boolean}
* @returns {string[]}
*/
verify(_extension) {
throws(`Implement the method \`verify\` on \`${this.constructor.name}\``)
getExtensions() {
throws(`Implement the method \`getExtensions\` on \`${this.constructor.name}\``)

return false
return []
}
}
89 changes: 76 additions & 13 deletions src/asset/resources/assetserver.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,82 @@
/** @import { TypeId, Constructor } from '../../reflect/index.js' */
/** @import { AssetId } from '../types/index.js' */
import { typeid } from '../../reflect/index.js'
import { assert } from '../../logger/index.js'
import { assert, warn } from '../../logger/index.js'
import { getFileExtension, swapRemove } from '../../utils/index.js'
import { Assets, Handle, Parser } from '../core/index.js'
import { AssetLoadSuccess, AssetLoadFail } from '../events/index.js'

/**
* @typedef {number} ParserId
*/
export class Parsers {

/**
* @private
* @type {Parser<unknown>[]}
*/
parsers = []

/**
* @private
* @type {Map<string, Map<TypeId,ParserId>>}
*/
extensions = new Map()

/**
* @template T
* @param {Parser<T>} parser
*/
add(parser) {
const id = this.parsers.length
const typeId = typeid(parser.asset)
const extensions = parser.getExtensions()

this.parsers.push(parser)

for (let i = 0; i < extensions.length; i++) {
const extension = extensions[i]
const extensionMap = this.extensions.get(extension)

if (extensionMap) {
if (extensionMap.has(typeId)) {
warn(`Overriding a parser already present with asset type \`${typeId}\` and with extension "${extension}"".`)
}

extensionMap.set(typeId, id)
} else {
this.extensions.set(extension, new Map([[typeId, id]]))
}
}
}

/**
* @template T
* @param {TypeId} type
* @param {string} extension
* @returns {Parser<T>}
* @throws {string}
*/
get(type, extension) {
const extensions = this.extensions.get(extension)

if (!extensions) {
throw 'The given extension does not have a parser registered'
}

const parserId = extensions.get(type)

if (parserId === undefined) {
throw 'The given asset type does not support the given extension'
}

const parser = this.parsers[parserId]

assert(parser, 'Internal error: The givk&en parser index is invalid.')

return /** @type {Parser<T>} */(parser)
}
}
export class AssetServer {

/**
Expand All @@ -18,9 +89,9 @@ export class AssetServer {
/**
* @private
* @readonly
* @type {Map<TypeId, Parser<unknown>>}
* @type {Parsers}
*/
parsers = new Map()
parsers = new Parsers()

/**
* @private
Expand Down Expand Up @@ -69,7 +140,7 @@ export class AssetServer {
* @param {Parser<T>} parser
*/
registerParser(type, parser) {
this.parsers.set(typeid(type), parser)
this.parsers.add(parser)
}

/**
Expand Down Expand Up @@ -151,15 +222,7 @@ export class AssetServer {
*/
async internalFetch(assetId, typeId, path) {
const extension = getFileExtension(path)
const parser = this.parsers.get(typeId)

if (!parser) {
throw 'No parser registered for the asset type.'
}

if (!parser.verify(extension)) {
throw `The extension "${extension}" is not supported by \`${parser.constructor.name}\``
}
const parser = this.parsers.get(typeId, extension)

const response = await fetch(path)

Expand Down
16 changes: 8 additions & 8 deletions src/asset/tests/assetserver.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { deepStrictEqual, notDeepStrictEqual, strictEqual } from "assert";
import { deepStrictEqual, notDeepStrictEqual } from "assert";
import test, { describe,todo } from "node:test";
import { Assets, AssetServer, LoadState, Parser } from "../index.js";
import { Assets, AssetServer, Parser } from "../index.js";

class Text {
inner = ''
Expand All @@ -16,11 +16,14 @@ class Text {
* @extends {Parser<Text>}
*/
class TextParser extends Parser {
constructor(){
super(Text)
}
/**
* @param {string} extension
* @override
*/
verify(extension){
return extension === 'txt'
getExtensions(){
return ['txt']
}

/**
Expand Down Expand Up @@ -50,9 +53,6 @@ describe('Testing `AssetServer`', () => {
// simulates `unloadDroppedAssets`
server.dropAssetInfo(handle1.id())

// TODO: Remove when handles are unique
// handles arent unique yet, so this ensures handle is at a different index
const handle3 = server.load(Text,"/assets/text/sample2.txt")
const handle2 = server.load(Text,"/assets/text/sample.txt")

notDeepStrictEqual(handle1.id(),handle2.id())
Expand Down
27 changes: 6 additions & 21 deletions src/audio/resources/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,6 @@ import { Audio } from '../assets/index.js'
*/
export class AudioParser extends Parser {

/**
* @private
* @type {Set<string>}
*/
extensions

/**
* @private
* @type {OfflineAudioContext}
Expand All @@ -25,17 +19,8 @@ export class AudioParser extends Parser {
sampleRate: 44100,
length: 512
}) {
super()
super(Audio)
this.decoder = new OfflineAudioContext(options)
this.extensions = this.getExtensions()
}

/**
* @inheritdoc
* @param {string} extension
*/
verify(extension) {
return this.extensions.has(extension)
}

/**
Expand All @@ -52,19 +37,19 @@ export class AudioParser extends Parser {

// audio capabilities
const audio = document.createElement('audio')
const extensions = new Set()
const extensions = []

if (audio.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/, '')) {
extensions.add('ogg')
extensions.push('ogg')
}
if (audio.canPlayType('audio/mpeg;').replace(/^no$/, '')) {
extensions.add('mp3')
extensions.push('mp3')
}
if (audio.canPlayType('audio/wav; codecs="1"').replace(/^no$/, '')) {
extensions.add('wav')
extensions.push('wav')
}
if (audio.canPlayType('audio/x-m4a;').replace(/^no$/, '') || audio.canPlayType('audio/aac;').replace(/^no$/, '')) {
extensions.add('m4a')
extensions.push('m4a')
}

return extensions
Expand Down
13 changes: 8 additions & 5 deletions src/render-core/resources/image.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ import { Vector2 } from '../../math/index.js'
*/
export class ImageParser extends Parser {

/**
* @param {string} _extension
*/
verify(_extension) {
return true
constructor() {
super(Image)
}

getExtensions() {

// TODO: Actually get the supported image formats
return ['png', 'jpeg']
}

/**
Expand Down