-
-
Notifications
You must be signed in to change notification settings - Fork 662
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
(asys) API #8832
base: development
Are you sure you want to change the base?
(asys) API #8832
Changes from 5 commits
e896285
616b89f
c36b72f
e827e8f
a001fc6
ca56786
2f02673
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package asys; | ||
|
||
import haxe.Error; | ||
import haxe.NoData; | ||
import haxe.async.Callback; | ||
import haxe.io.Bytes; | ||
import haxe.io.FilePath; | ||
import asys.*; | ||
|
||
/** | ||
This class provides methods for asynchronous operations on files and | ||
directories. For synchronous operations, see `asys.FileSystem`. | ||
|
||
All methods here are asynchronous versions of the functions in | ||
`asys.FileSystem`. Please see them for a description of the arguments and | ||
use of each method. | ||
|
||
Any synchronous method that returns no value (`Void` return type) has an | ||
extra `callback:Callback<NoData>` argument. | ||
|
||
Any synchronous method that returns a value has an extra | ||
`callback:Callback<T>` argument, where `T` is the return type of the | ||
synchronous method. | ||
|
||
Errors are communicated through the callbacks or in some cases thrown | ||
immediately. | ||
**/ | ||
extern class AsyncFileSystem { | ||
static function access(path:FilePath, ?mode:FileAccessMode = FileAccessMode.Ok, callback:Callback<NoData>):Void; | ||
static function chmod(path:FilePath, mode:FilePermissions, ?followSymLinks:Bool = true, callback:Callback<NoData>):Void; | ||
static function chown(path:FilePath, uid:Int, gid:Int, ?followSymLinks:Bool = true, callback:Callback<NoData>):Void; | ||
static function copyFile(src:FilePath, dest:FilePath, ?flags:FileCopyFlags, callback:Callback<NoData>):Void; | ||
static function exists(path:FilePath, callback:Callback<Bool>):Void; | ||
static function link(existingPath:FilePath, newPath:FilePath, callback:Callback<NoData>):Void; | ||
static function mkdir(path:FilePath, ?recursive:Bool, ?mode:FilePermissions, callback:Callback<NoData>):Void; | ||
static function mkdtemp(prefix:FilePath, callback:Callback<FilePath>):Void; | ||
static function readdir(path:FilePath, callback:Callback<Array<FilePath>>):Void; | ||
static function readdirTypes(path:FilePath, callback:Callback<Array<DirectoryEntry>>):Void; | ||
static function readlink(path:FilePath, callback:Callback<FilePath>):Void; | ||
static function realpath(path:FilePath, callback:Callback<FilePath>):Void; | ||
static function rename(oldPath:FilePath, newPath:FilePath, callback:Callback<NoData>):Void; | ||
static function rmdir(path:FilePath, callback:Callback<NoData>):Void; | ||
static function stat(path:FilePath, ?followSymLinks:Bool = true, callback:Callback<FileStat>):Void; | ||
static function symlink(target:FilePath, path:FilePath, ?type:String, callback:Callback<NoData>):Void; | ||
static function truncate(path:FilePath, len:Int, callback:Callback<NoData>):Void; | ||
static function unlink(path:FilePath, callback:Callback<NoData>):Void; | ||
static function utimes(path:FilePath, atime:Date, mtime:Date, callback:Callback<NoData>):Void; | ||
static function appendFile(path:FilePath, data:Bytes, ?flags:FileOpenFlags, ?mode:FilePermissions, callback:Callback<NoData>):Void; | ||
static function open(path:FilePath, ?flags:FileOpenFlags, ?mode:FilePermissions, ?binary:Bool = true, callback:Callback<sys.io.File>):Void; | ||
static function readFile(path:FilePath, ?flags:FileOpenFlags, callback:Callback<Bytes>):Void; | ||
static function writeFile(path:FilePath, data:Bytes, ?flags:FileOpenFlags, ?mode:FilePermissions, callback:Callback<NoData>):Void; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package asys; | ||
|
||
import haxe.async.*; | ||
import asys.net.Socket; | ||
import asys.io.*; | ||
|
||
/** | ||
Methods to control the current process and IPC interaction with the parent | ||
process. | ||
**/ | ||
class CurrentProcess { | ||
/** | ||
Emitted when a message is received over IPC. `initIpc` must be called first | ||
to initialise the IPC channel. | ||
**/ | ||
public static final messageSignal:Signal<IpcMessage> = new ArraySignal(); | ||
|
||
static var ipc:Socket; | ||
static var ipcOut:IpcSerializer; | ||
static var ipcIn:IpcUnserializer; | ||
|
||
/** | ||
Initialise the IPC channel on the given file descriptor `fd`. This should | ||
only be used when the current process was spawned with `Process.spawn` from | ||
another Haxe process. `fd` should correspond to the index of the `Ipc` | ||
entry in `options.stdio`. | ||
**/ | ||
public static function initIpc(fd:Int):Void { | ||
if (ipc != null) | ||
throw "IPC already initialised"; | ||
ipc = Socket.create(); | ||
ipcOut = @:privateAccess new IpcSerializer(ipc); | ||
ipcIn = @:privateAccess new IpcUnserializer(ipc); | ||
ipc.connectFd(true, fd); | ||
ipc.errorSignal.on(err -> trace("IPC error", err)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this error should be exposed somehow instead of just tracing it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, |
||
ipcIn.messageSignal.on(message -> messageSignal.emit(message)); | ||
} | ||
|
||
/** | ||
Sends a message over IPC. `initIpc` must be called first to initialise the | ||
IPC channel. | ||
**/ | ||
public static function send(message:IpcMessage):Void { | ||
if (ipc == null) | ||
throw "IPC not connected"; | ||
ipcOut.write(message); | ||
} | ||
|
||
extern public static function initUv():Void; | ||
|
||
extern public static function runUv(?mode:asys.uv.UVRunMode = RunDefault):Bool; | ||
|
||
extern public static function stopUv():Void; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package asys; | ||
|
||
import haxe.io.FilePath; | ||
|
||
/** | ||
An entry returned from `asys.FileSystem.readdirTypes`. | ||
**/ | ||
interface DirectoryEntry { | ||
var name(get, never):FilePath; | ||
function isBlockDevice():Bool; | ||
function isCharacterDevice():Bool; | ||
function isDirectory():Bool; | ||
function isFIFO():Bool; | ||
function isFile():Bool; | ||
function isSocket():Bool; | ||
function isSymbolicLink():Bool; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package asys; | ||
|
||
/** | ||
Wrapper for file access modes. See `asys.FileSystem.access`. | ||
**/ | ||
enum abstract FileAccessMode(Int) { | ||
var Ok = 0; | ||
var Execute = 1 << 0; | ||
var Write = 1 << 1; | ||
var Read = 1 << 2; | ||
|
||
inline function get_raw():Int return this; | ||
|
||
@:op(A | B) | ||
inline function join(other:FileAccessMode) return this | other.get_raw(); | ||
Aurel300 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package asys; | ||
|
||
enum abstract FileCopyFlags(Int) { | ||
/** | ||
Fail if destination exists. | ||
**/ | ||
var FailIfExists = 1 << 0; | ||
|
||
/** | ||
Copy-on-write reflink if possible. | ||
**/ | ||
var COWClone = 1 << 1; | ||
|
||
/** | ||
Copy-on-write reflink or fail. | ||
**/ | ||
var COWCloneForce = 1 << 2; | ||
|
||
inline function get_raw():Int return this; | ||
|
||
@:op(A | B) | ||
inline function join(other:FileCopyFlags) return this | other.get_raw(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package asys; | ||
|
||
class FileOpenFlagsImpl { | ||
public static function fromString(flags:String):FileOpenFlags { | ||
return (switch (flags) { | ||
case "r": ReadOnly; | ||
case "r+": ReadWrite; | ||
case "rs+": ReadWrite | Sync; | ||
case "sr+": ReadWrite | Sync; | ||
case "w": Truncate | Create | WriteOnly; | ||
case "w+": Truncate | Create | ReadWrite; | ||
case "a": Append | Create | WriteOnly; | ||
case "a+": Append | Create | ReadWrite; | ||
case "wx": Truncate | Create | WriteOnly | Excl; | ||
case "xw": Truncate | Create | WriteOnly | Excl; | ||
case "wx+": Truncate | Create | ReadWrite | Excl; | ||
case "xw+": Truncate | Create | ReadWrite | Excl; | ||
case "ax": Append | Create | WriteOnly | Excl; | ||
case "xa": Append | Create | WriteOnly | Excl; | ||
case "as": Append | Create | WriteOnly | Sync; | ||
case "sa": Append | Create | WriteOnly | Sync; | ||
case "ax+": Append | Create | ReadWrite | Excl; | ||
case "xa+": Append | Create | ReadWrite | Excl; | ||
case "as+": Append | Create | ReadWrite | Sync; | ||
case "sa+": Append | Create | ReadWrite | Sync; | ||
case _: throw "invalid file open flags"; | ||
}); | ||
} | ||
} | ||
|
||
/** | ||
Flags used when opening a file with `asys.FileSystem.open` or other file | ||
functions. Specify whether the opened file: | ||
|
||
- will be readable | ||
- will be writable | ||
- will be truncated (all data lost) first | ||
- will be in append mode | ||
- will be opened exclusively by this process | ||
|
||
Instances of this type can be created by combining flags with the bitwise or | ||
operator: | ||
|
||
```haxe | ||
Truncate | Create | WriteOnly | ||
``` | ||
|
||
Well-known combinations of flags can be specified with a string. The | ||
supported modes are: `r`, `r+`, `rs+`, `sr+`, `w`, `w+`, `a`, `a+`, `wx`, | ||
`xw`, `wx+`, `xw+`, `ax`, `xa`, `as`, `sa`, `ax+`, `xa+`, `as+`, `sa+`. | ||
**/ | ||
@:native("asys.FileOpenFlagsImpl") | ||
extern enum abstract FileOpenFlags(Int) { | ||
@:from public static function fromString(flags:String):FileOpenFlags; | ||
|
||
inline function new(value:Int) | ||
this = value; | ||
|
||
inline function get_raw():Int return this; | ||
|
||
@:op(A | B) | ||
inline function join(other:FileOpenFlags):FileOpenFlags return new FileOpenFlags(this | other.get_raw()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This spoils our enums behavior. It makes switches non-exhaustive, and compiler is not aware of that. |
||
|
||
// TODO: some of these don't make sense in Haxe-wrapped libuv | ||
var Append; | ||
var Create; | ||
var Direct; | ||
var Directory; | ||
var Dsync; | ||
var Excl; | ||
var NoAtime; | ||
var NoCtty; | ||
var NoFollow; | ||
var NonBlock; | ||
var ReadOnly; | ||
var ReadWrite; | ||
var Sync; | ||
var Truncate; | ||
var WriteOnly; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package asys; | ||
|
||
/** | ||
File permissions in specify whether a file can be read, written, or executed | ||
by its owner, its owning group, and everyone else. Instances of this type | ||
can be constructed by combining individual file permissions with the `|` | ||
operator: | ||
|
||
```haxe | ||
ReadOwner | WriteOwner | ReadGroup | ReadOthers | ||
``` | ||
|
||
Alternatively, file permissions may be specified as a string with exactly 9 | ||
characters, in the format `rwxrwxrwx`, where each letter may instead be a | ||
`-` character. The first three characters represent the permissions of the | ||
owner, the second three characters represent the permissions of the owning | ||
group, and the last three characters represent the permissions of everyone | ||
else. | ||
|
||
```haxe | ||
"rw-r--r--" | ||
``` | ||
|
||
Finally, file permissions may be constructed from an octal representation | ||
using the `fromOctal` function. | ||
|
||
```haxe | ||
FilePermissions.fromOctal("644") | ||
``` | ||
**/ | ||
enum abstract FilePermissions(Int) { | ||
@:from public static function fromString(s:String):FilePermissions { | ||
inline function bit(cc:Int, expect:Int):Int { | ||
return (if (cc == expect) | ||
1; | ||
else if (cc == "-".code) | ||
0; | ||
else | ||
throw "invalid file permissions string"); | ||
} | ||
switch (s.length) { | ||
case 9: // rwxrwxrwx | ||
return new FilePermissions(bit(s.charCodeAt(0), "r".code) << 8 | ||
| bit(s.charCodeAt(1), "w".code) << 7 | ||
| bit(s.charCodeAt(2), "x".code) << 6 | ||
| bit(s.charCodeAt(3), "r".code) << 5 | ||
| bit(s.charCodeAt(4), "w".code) << 4 | ||
| bit(s.charCodeAt(5), "x".code) << 3 | ||
| bit(s.charCodeAt(6), "r".code) << 2 | ||
| bit(s.charCodeAt(7), "w".code) << 1 | ||
| bit(s.charCodeAt(8), "x".code)); | ||
case _: | ||
throw "invalid file permissions string"; | ||
} | ||
} | ||
|
||
public static function fromOctal(s:String):FilePermissions { | ||
inline function digit(n:Int):Int { | ||
if (n >= "0".code && n <= "7".code) return n - "0".code; | ||
throw "invalid octal file permissions"; | ||
} | ||
switch (s.length) { | ||
case 3: // 777 | ||
return new FilePermissions(digit(s.charCodeAt(0)) << 6 | ||
| digit(s.charCodeAt(1)) << 3 | ||
| digit(s.charCodeAt(2))); | ||
case _: | ||
throw "invalid octal file permissions"; | ||
} | ||
} | ||
|
||
var None = 0; | ||
var ExecuteOthers = 1 << 0; | ||
var WriteOthers = 1 << 1; | ||
var ReadOthers = 1 << 2; | ||
var ExecuteGroup = 1 << 3; | ||
var WriteGroup = 1 << 4; | ||
var ReadGroup = 1 << 5; | ||
var ExecuteOwner = 1 << 6; | ||
var WriteOwner = 1 << 7; | ||
var ReadOwner = 1 << 8; | ||
|
||
inline function new(value:Int) | ||
this = value; | ||
|
||
inline function get_raw():Int return this; | ||
|
||
@:op(A | B) | ||
inline function join(other:FilePermissions) return new FilePermissions(this | other.get_raw()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This subverts enums. We should have |
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
flags
ofasys.FileSystem.access()
is commented out