Current section
Files
Jump to
Current section
Files
src/polly_ffi.mjs
import fs from 'node:fs'
import { Ok, Error as GError, toList } from './gleam.mjs'
import * as $polly from './polly.mjs'
export function readdir(filepath) {
return gleamResult(() => toList(fs.readdirSync(filepath)))
}
export function lstat(filepath) {
return gleamResult(() => {
const stat = fs.lstatSync(filepath)
const mode = stat.mode
const type =
((mode & fs.constants.S_IFMT) === fs.constants.S_IFLNK) ? new $polly.Symlink()
: ((mode & fs.constants.S_IFMT) === fs.constants.S_IFDIR) ? new $polly.Directory()
: ((mode & fs.constants.S_IFMT) === fs.constants.S_IFREG) ? new $polly.Regular()
: ((mode & fs.constants.S_IFMT) === fs.constants.S_IFCHR) ? new $polly.Device()
: new $polly.Other()
const read = (mode & (fs.constants.S_IRUSR | fs.constants.S_IRGRP | fs.constants.S_IROTH))
const write = (mode & (fs.constants.S_IWUSR | fs.constants.S_IWGRP | fs.constants.S_IWOTH))
const access = read && write ? new $polly.ReadWrite()
: read ? new $polly.Read()
: write ? new $polly.Write()
: new $polly.None()
return new $polly.Stat(
stat.size,
type,
access,
Math.trunc(stat.atimeMs / 1000),
Math.trunc(stat.mtimeMs / 1000),
Math.trunc(stat.ctimeMs / 1000),
mode,
stat.nlink,
stat.dev,
stat.rdev,
stat.ino,
stat.uid,
stat.gid
)
})
}
export function repeatedly(timeout, state, callback) {
let timerId = setTimeout(step, timeout)
return stop
function step() {
state = callback(state)
timerId = setTimeout(step, timeout)
}
function stop() {
clearTimeout(timerId)
}
}
function gleamResult(f) {
try {
return new Ok(f())
} catch(e) {
switch (e.code) {
case 'EACCES': return new GError(new $polly.Eacces())
case 'ENOENT': return new GError(new $polly.Enoent())
case 'ENODIR': return new GError(new $polly.Enotdir())
// map_error will fix her!
default: return new GError(e.code)
}
}
}