22
33namespace Amp \File \Internal ;
44
5+ use Amp \ByteStream \ClosedException ;
6+ use Amp \ByteStream \StreamException ;
57use Amp \Cache \Cache ;
8+ use Amp \Cache \CacheException ;
69use Amp \Cancellation ;
710use Amp \File \Driver \BlockingFile ;
811use Amp \File \Driver \BlockingFilesystemDriver ;
1215
1316/**
1417 * @codeCoverageIgnore
15- *
1618 * @internal
19+ * @implements Task<mixed, never, never, BlockingFile>
1720 */
1821final class FileTask implements Task
1922{
23+ private static ?BlockingFilesystemDriver $ driver = null ;
24+
2025 private const ENV_PREFIX = "amphp/file# " ;
2126
2227 private static function makeId (int $ id ): string
2328 {
2429 return self ::ENV_PREFIX . $ id ;
2530 }
2631
27- private string $ operation ;
28-
29- private array $ args ;
30-
31- private ?int $ id ;
32-
3332 /**
3433 * @param int|null $id File ID.
3534 *
3635 * @throws \Error
3736 */
38- public function __construct (string $ operation , array $ args = [], ?int $ id = null )
39- {
37+ public function __construct (
38+ private readonly string $ operation ,
39+ private readonly array $ args = [],
40+ private readonly ?int $ id = null ,
41+ ) {
4042 if ($ operation === '' ) {
4143 throw new \Error ('Operation must be a non-empty string ' );
4244 }
43-
44- $ this ->operation = $ operation ;
45- $ this ->args = $ args ;
46- $ this ->id = $ id ;
4745 }
4846
4947 /**
5048 * @throws FilesystemException
51- * @throws \Amp\Cache\ CacheException
52- * @throws \Amp\ByteStream\ ClosedException
53- * @throws \Amp\ByteStream\ StreamException
49+ * @throws CacheException
50+ * @throws ClosedException
51+ * @throws StreamException
5452 */
5553 public function run (Channel $ channel , Cache $ cache , Cancellation $ cancellation ): mixed
5654 {
55+ self ::$ driver ??= new BlockingFilesystemDriver ();
56+
5757 if ('f ' === $ this ->operation [0 ]) {
5858 if ("fopen " === $ this ->operation ) {
59- $ path = $ this ->args [0 ];
60- $ mode = \str_replace (['b ' , 't ' , 'e ' ], '' , $ this ->args [1 ]);
61-
62- switch ($ mode ) {
63- case "r " :
64- case "r+ " :
65- case "w " :
66- case "w+ " :
67- case "a " :
68- case "a+ " :
69- case "x " :
70- case "x+ " :
71- case "c " :
72- case "c+ " :
73- break ;
74-
75- default :
76- throw new \Error ("Invalid file mode " );
77- }
78-
79- $ handle = @\fopen ($ path , $ mode . 'be ' );
80-
81- if (!$ handle ) {
82- $ message = 'Could not open the file. ' ;
83- if ($ error = \error_get_last ()) {
84- $ message .= \sprintf (" Errno: %d; %s " , $ error ["type " ], $ error ["message " ]);
85- }
86- throw new FilesystemException ($ message );
87- }
88-
89- $ file = new BlockingFile ($ handle , $ path , $ mode );
90- $ id = (int ) $ handle ;
91- $ size = \fstat ($ handle )["size " ];
59+ $ file = self ::$ driver ->openFile (...$ this ->args );
60+
61+ $ size = self ::$ driver ->getStatus ($ file ->getPath ())["size " ]
62+ ?? throw new FilesystemException ("Could not determine file size " );
63+
64+ $ id = $ file ->getId ();
9265 $ cache ->set (self ::makeId ($ id ), $ file );
9366
94- return [$ id , $ size , $ mode ];
67+ return [$ id , $ size , $ file -> getMode () ];
9568 }
9669
9770 if ($ this ->id === null ) {
@@ -114,14 +87,18 @@ public function run(Channel $channel, Cache $cache, Cancellation $cancellation):
11487
11588 switch ($ this ->operation ) {
11689 case "fread " :
117- \array_shift ($ this ->args );
11890 return $ file ->read ($ cancellation , ...$ this ->args );
91+
11992 case "fwrite " :
120- return $ file ->write (...$ this ->args );
93+ $ file ->write (...$ this ->args );
94+ return null ;
95+
12196 case "fseek " :
12297 return $ file ->seek (...$ this ->args );
98+
12399 case "ftruncate " :
124- return $ file ->truncate (...$ this ->args );
100+ $ file ->truncate (...$ this ->args );
101+ return null ;
125102
126103 case "fclose " :
127104 $ cache ->delete ($ id );
@@ -151,7 +128,7 @@ public function run(Channel $channel, Cache $cache, Cancellation $cancellation):
151128 case "touch " :
152129 case "read " :
153130 case "write " :
154- return ([ new BlockingFilesystemDriver , $ this ->operation ]) (...$ this ->args );
131+ return self :: $ driver ->{ $ this ->operation } (...$ this ->args );
155132
156133 default :
157134 throw new \Error ("Invalid operation - " . $ this ->operation );
0 commit comments