33 */
44import { basename , join } from '@std/path'
55import * as posix from '@std/path/posix'
6- import { type BIDSFile , FileTree } from '../types/filetree.ts'
6+ import { BIDSFile , FileTree } from '../types/filetree.ts'
77import { requestReadPermission } from '../setup/requestPermissions.ts'
88import { FileIgnoreRules , readBidsIgnore } from './ignore.ts'
9- import { logger } from '../utils/logger.ts'
10- import { createUTF8Stream } from './streams.ts'
11- export { type BIDSFile , FileTree }
12-
13- /**
14- * Deno implementation of BIDSFile
15- */
16- export class BIDSFileDeno implements BIDSFile {
17- #ignore: FileIgnoreRules
18- name : string
19- path : string
20- #parent! : WeakRef < FileTree >
21- #fileInfo?: Deno . FileInfo
22- #datasetAbsPath: string
23- viewed : boolean = false
9+ import { FsFileOpener } from './openers.ts'
2410
11+ export class BIDSFileDeno extends BIDSFile {
2512 constructor ( datasetPath : string , path : string , ignore ?: FileIgnoreRules , parent ?: FileTree ) {
26- this . #datasetAbsPath = datasetPath
27- this . path = path
28- this . name = basename ( path )
29- this . #ignore = ignore ?? new FileIgnoreRules ( [ ] )
30- try {
31- this . #fileInfo = Deno . statSync ( this . _getPath ( ) )
32- } catch ( error ) {
33- if ( error && typeof error === 'object' && 'code' in error && error . code === 'ENOENT' ) {
34- this . #fileInfo = Deno . lstatSync ( this . _getPath ( ) )
35- }
36- }
37- this . parent = parent ?? new FileTree ( '' , '/' , undefined )
38- }
39-
40- private _getPath ( ) : string {
41- return join ( this . #datasetAbsPath, this . path )
42- }
43-
44- get parent ( ) : FileTree {
45- return this . #parent. deref ( ) as FileTree
46- }
47-
48- set parent ( tree : FileTree ) {
49- this . #parent = new WeakRef ( tree )
50- }
51-
52- get size ( ) : number {
53- return this . #fileInfo ? this . #fileInfo. size : - 1
54- }
55-
56- get stream ( ) : ReadableStream < Uint8Array < ArrayBuffer > > {
57- const handle = this . #openHandle( )
58- return handle . readable
59- }
60-
61- get ignored ( ) : boolean {
62- return this . #ignore. test ( this . path )
63- }
64-
65- /**
66- * Read the entire file and decode as utf-8 text
67- */
68- async text ( ) : Promise < string > {
69- const reader = this . stream . pipeThrough ( createUTF8Stream ( ) ) . getReader ( )
70- const chunks : string [ ] = [ ]
71- try {
72- while ( true ) {
73- const { done, value } = await reader . read ( )
74- if ( done ) break
75- chunks . push ( value )
76- }
77- return chunks . join ( '' )
78- } finally {
79- reader . releaseLock ( )
80- }
81- }
82-
83- /**
84- * Read bytes in a range efficiently from a given file
85- *
86- * Reads up to size bytes, starting at offset.
87- * If EOF is encountered, the resulting array may be smaller.
88- */
89- async readBytes ( size : number , offset = 0 ) : Promise < Uint8Array < ArrayBuffer > > {
90- const handle = this . #openHandle( )
91- const buf = new Uint8Array ( size )
92- await handle . seek ( offset , Deno . SeekMode . Start )
93- const nbytes = await handle . read ( buf ) ?? 0
94- handle . close ( )
95- return buf . subarray ( 0 , nbytes )
96- }
97-
98- /**
99- * Return a Deno file handle
100- */
101- #openHandle( ) : Deno . FsFile {
102- // Avoid asking for write access
103- const openOptions = { read : true , write : false }
104- return Deno . openSync ( this . _getPath ( ) , openOptions )
13+ super ( path , new FsFileOpener ( datasetPath , path ) , ignore , parent )
10514 }
10615}
10716
@@ -122,12 +31,12 @@ async function _readFileTree(
12231 continue
12332 }
12433 if ( dirEntry . isFile || dirEntry . isSymlink ) {
125- const file = new BIDSFileDeno (
126- rootPath ,
34+ const file = new BIDSFile (
12735 thisPath ,
36+ new FsFileOpener ( rootPath , thisPath ) ,
12837 ignore ,
38+ tree ,
12939 )
130- file . parent = tree
13140 tree . files . push ( file )
13241 }
13342 if ( dirEntry . isDirectory ) {
0 commit comments