import{mergeObjectsDeeply as i,retriedFetch as o}from"./misc.js";export class Source{constructor(){this._sizePromise=null,this.onread=null}getSize(){return this._sizePromise??=this._retrieveSize()}}export class BufferSource extends Source{constructor(t){if(!(t instanceof ArrayBuffer)&&!(t instanceof Uint8Array))throw new TypeError("buffer must be an ArrayBuffer or Uint8Array.");super(),this._bytes=t instanceof Uint8Array?t:new Uint8Array(t)}async _read(t,e){return this._bytes.subarray(t,e)}async _retrieveSize(){return this._bytes.byteLength}}export class StreamSource extends Source{constructor(t){if(!t||typeof t!="object")throw new TypeError("options must be an object.");if(typeof t.read!="function")throw new TypeError("options.read must be a function.");if(typeof t.getSize!="function")throw new TypeError("options.getSize must be a function.");super(),this._options=t}async _read(t,e){return this._options.read(t,e)}async _retrieveSize(){return this._options.getSize()}}export class BlobSource extends Source{constructor(t){if(!(t instanceof Blob))throw new TypeError("blob must be a Blob.");super(),this._blob=t}async _read(t,e){const s=await this._blob.slice(t,e).arrayBuffer();return new Uint8Array(s)}async _retrieveSize(){return this._blob.size}}export class UrlSource extends Source{constructor(t,e={}){if(typeof t!="string"&&!(t instanceof URL))throw new TypeError("url must be a string or URL.");if(!e||typeof e!="object")throw new TypeError("options must be an object.");if(e.requestInit!==void 0&&(!e.requestInit||typeof e.requestInit!="object"))throw new TypeError("options.requestInit, when provided, must be an object.");if(e.getRetryDelay!==void 0&&typeof e.getRetryDelay!="function")throw new TypeError("options.getRetryDelay, when provided, must be a function.");super(),this._fullData=null,this._nextUrlVersion=null,this._url=t instanceof URL?t:new URL(t),this._options=e}async _makeRequest(t){const e={};t&&(e.Range=`bytes=${t.start}-${t.end-1}`),this._nextUrlVersion!==null&&(this._url.searchParams.set("mediabunny_version",this._nextUrlVersion.toString()),this._nextUrlVersion++);const r=await o(this._url,i(this._options.requestInit??{},{method:"GET",headers:e}),this._options.getRetryDelay??(()=>null));if(!r.ok)throw new Error(`Error fetching ${this._url}: ${r.status} ${r.statusText}`);const s=await r.arrayBuffer();return r.status===206&&t&&s.byteLength!==t.end-t.start&&this._nextUrlVersion===null?(this._nextUrlVersion=1,this._makeRequest(t)):(r.status===200&&(this._fullData=s),{response:s,statusCode:r.status})}async _read(t,e){if(this._fullData)return new Uint8Array(this._fullData,t,e-t);const{response:r,statusCode:s}=await this._makeRequest({start:t,end:e});return s===200?new Uint8Array(r).subarray(t,e):new Uint8Array(r)}async _retrieveSize(){if(this._fullData)return this._fullData.byteLength;try{const r=await o(this._url,i(this._options.requestInit??{},{method:"HEAD"}),this._options.getRetryDelay??(()=>null));if(r.ok){const s=r.headers.get("Content-Length");if(s)return parseInt(s)}}catch{}const t=await o(this._url,i(this._options.requestInit??{},{method:"GET",headers:{Range:"bytes=0-0"}}),this._options.getRetryDelay??(()=>null));if(t.status===206){const r=t.headers.get("Content-Range");if(r){const s=r.match(/bytes \d+-\d+\/(\d+)/);if(s&&s[1])return parseInt(s[1])}}else if(t.status===200&&(this._fullData=await t.arrayBuffer(),this._fullData.byteLength!==1))return this._fullData.byteLength;const{response:e}=await this._makeRequest();return e.byteLength}}
