wip: root can add directories to itself

This commit is contained in:
2025-04-24 01:23:11 -04:00
parent b79234a1f5
commit 22b9e1f3d5
2 changed files with 121 additions and 65 deletions

View File

@ -2,11 +2,10 @@ import { Permissions } from "./rfwfs/main"
import rfwfs from "./rfwfs/main"
const time_now = (Date.now()/1000)|0
const time_now = (Date.now()/1000) | 0
const fs = new rfwfs([
rfwfs.directory("bin", Permissions.r, fs, time_now)
])
const fs = new rfwfs()
fs.add_file(default_name, default_permissions)
export default fs

View File

@ -1,5 +1,5 @@
import { ReadStatus, PushStatus, ExecuteStatus } from "./enum/status"
import { wrap_entry, wrap_none, type WrapResultEntry, type WrapResultNone, type WrapBinary, wrap_binary } from "./wrap"
import { wrap_entry, wrap_none, wrap_binary, type WrapResultEntry, type WrapResultNone, type WrapBinary } from "./wrap"
import directory_search from "./index"
@ -15,6 +15,7 @@ const enum Permissions {
x = 1<<2,
none = 1<<3,
}
const enum ROOT_ID { TRUNK = "/" }
type FileInner = string | number
type BinaryError = string
@ -26,15 +27,6 @@ type Directory<T extends Entry> = EntryCollection<T>
type DirectoryAny = EntryCollection<Entry>
type DirectoryAnyDepth = EntryCollection<DirectoryAny>
interface Root<T extends Entry> {
readonly type: EntryType,
inner: T[],
}
interface RootFile<T extends Entry> extends Root<T> {
}
interface EntryStripped {
readonly type: EntryType,
permissions: Permissions,
@ -42,8 +34,8 @@ interface EntryStripped {
name: EntryValue<string>,
}
interface Entry extends EntryStripped {
parent: DirectoryAny,
interface Entry<T = DirectoryAny | null> extends EntryStripped {
parent: T,
}
interface EntryFile extends Entry {
@ -59,6 +51,15 @@ interface EntryBinary extends Entry {
inner: RfwfsBinary
}
interface Root<T extends Entry> {
readonly type: EntryType,
readonly permissions: Permissions,
readonly timestamp: EntryValueRoot<number>,
readonly parent: null,
readonly inner: RfwfsRootDirectory<T>,
readonly name: ROOT_ID.TRUNK,
}
function strip_entry<T extends Entry>(entry: T): EntryStripped {
return {
type: entry.type,
@ -68,15 +69,53 @@ function strip_entry<T extends Entry>(entry: T): EntryStripped {
}
}
function fs_dir_clone<T extends Entry>(directory: T[], file_name: string): WrapResultEntry<T, ReadStatus> {
const clone_find = directory_search(directory, file_name)
if (clone_find) {
return wrap_entry(ReadStatus.Ok, { ...clone_find.result })
}
return wrap_entry(ReadStatus.NotFound)
}
function fs_dir_find<T extends Entry>(directory: T[], file_name: string): WrapResultEntry<T, ReadStatus> {
const file_search = directory_search(directory, file_name)
if (file_search) {
return wrap_entry(ReadStatus.Ok, file_search.result)
}
return wrap_entry(ReadStatus.NotFound)
}
function fs_dir_push<T extends Entry, E extends T>(directory: T[], entry: E) {
const no_duplicates = directory_search(directory, entry.name.inner)
if (!no_duplicates) {
directory.push(entry)
directory.sort()
return wrap_none(PushStatus.Ok)
}
return wrap_none(PushStatus.Duplicate)
}
function fs_dir_pop<T extends Entry>(directory: T[], file_name: string): WrapResultEntry<T, ReadStatus> {
const pop_find = directory_search(directory, file_name)
if (pop_find) {
directory.splice(pop_find.status, 1)
return wrap_entry(ReadStatus.Ok, pop_find.result)
}
return wrap_entry(ReadStatus.NotFound)
}
class EntryValue<T> {
public inner: T;
protected entry: Entry
protected entry: Entry;
constructor(entry: Entry, inner_default: T) {
this.inner = inner_default
this.entry = entry
}
/**
Safe write
*/
public write<I extends T>(item: I): boolean {
if (rfwfs.write_access(this.entry.permissions)) {
this.inner = item
@ -99,6 +138,18 @@ class EntryValue<T> {
}
}
class EntryValueRoot<T> {
protected inner: T;
constructor(inner: T) {
this.inner = inner
}
public read(): T {
return this.inner
}
}
class RfwfsDirectory<T extends Entry> {
public directory: T[];
protected entry: Entry;
@ -114,52 +165,61 @@ class RfwfsDirectory<T extends Entry> {
public clone(file_name: string): WrapResultEntry<T, ReadStatus> {
if (rfwfs.read_write_access(this.entry.permissions)) {
const clone_find = directory_search(this.directory, file_name)
if (clone_find) {
return wrap_entry(ReadStatus.Ok, { ...clone_find.result })
}
return wrap_entry(ReadStatus.NotFound)
return fs_dir_clone(this.directory, file_name)
}
return wrap_entry(ReadStatus.Denied)
}
public find(file_name: string): WrapResultEntry<T, ReadStatus> {
if (rfwfs.read_write_access(this.entry.permissions)) {
const file_search = directory_search(this.directory, file_name)
if (file_search) {
return wrap_entry(ReadStatus.Ok, file_search.result)
}
return wrap_entry(ReadStatus.NotFound)
return fs_dir_find(this.directory, file_name)
}
return wrap_entry(ReadStatus.Denied)
}
public push<E extends T>(entry: E): WrapResultNone<PushStatus> {
if (rfwfs.read_write_access(this.entry.permissions)) {
const no_duplicates = directory_search(this.directory, entry.name.inner)
if (!no_duplicates) {
this.directory.push(entry)
this.directory.sort()
return wrap_none(PushStatus.Ok)
}
return wrap_none(PushStatus.Duplicate)
return fs_dir_push(this.directory, entry)
}
return wrap_none(PushStatus.Denied)
}
public pop(file_name: string): WrapResultEntry<T, ReadStatus> {
if (rfwfs.read_write_access(this.entry.permissions)) {
const pop_find = directory_search(this.directory, file_name)
if (pop_find) {
this.directory.splice(pop_find.status, 1)
return wrap_entry(ReadStatus.Ok, pop_find.result)
}
return wrap_entry(ReadStatus.NotFound)
fs_dir_pop(this.directory, file_name)
}
return wrap_entry(ReadStatus.Denied)
}
}
class RfwfsRootDirectory<T extends Entry> {
public directory: T[];
constructor() {
this.directory = []
}
public sort() {
this.directory.sort((a,z) => a.name.inner.localeCompare(z.name.inner))
}
public clone(file_name: string): WrapResultEntry<T, ReadStatus> {
return fs_dir_clone(this.directory, file_name)
}
public find(file_name: string): WrapResultEntry<T, ReadStatus> {
return fs_dir_find(this.directory, file_name)
}
public push<E extends T>(entry: E): WrapResultNone<PushStatus> {
return fs_dir_push(this.directory, entry)
}
public pop(file_name: string): WrapResultEntry<T, ReadStatus> {
return fs_dir_pop(this.directory, file_name)
}
}
class RfwfsBinary {
public lambda: BinaryLambda;
protected entry: Entry;
@ -182,7 +242,10 @@ class RfwfsBinary {
}
}
class rfwfs_static {
class rfwfs_lib {
public static is_root<T extends Entry>(entry: T): boolean {
return entry.type === EntryType.Root
}
public static is_dir<T extends Entry>(entry: T): boolean {
return entry.type === EntryType.Directory
}
@ -192,9 +255,6 @@ class rfwfs_static {
public static is_binary<T extends Entry>(entry: T): boolean {
return entry.type === EntryType.Binary
}
public static is_root<T extends Entry>(entry: Root<T>): boolean {
return entry.type === EntryType.Root
}
public static read_access(permissions: Permissions): boolean {
return (permissions & Permissions.r) !== 0
@ -210,28 +270,24 @@ class rfwfs_static {
}
}
class rfwfs<T extends Entry> extends rfwfs_static {
class rfwfs<T extends Entry> extends rfwfs_lib {
public root: Root<T>;
constructor(inner: T[]) {
constructor() {
super()
this.root = { type: EntryType.Root, inner: inner }
this.root = {
type: EntryType.Root,
permissions: Permissions.r | Permissions.w,
timestamp: new EntryValueRoot((Date.now()/1000) | 0),
parent: null,
inner: new RfwfsRootDirectory(),
name: ROOT_ID.TRUNK,
} as Root<T>
}
public add_file(
default_name: string,
default_permissions: Permissions,
default_timestamp?: number,
default_inner?: FileInner
): EntryFile {
const file = { type: EntryType.File } as EntryFile
file.hash = "0"
file.permissions = default_permissions
file.parent = this.root
file.timestamp = new EntryValue(file, default_timestamp ? default_timestamp : (Date.now()/1000)|0)
file.inner = new EntryValue(file, default_inner ? default_inner : "")
file.name = new EntryValue(file, default_name)
return file
public push_directory_into_root<T extends Entry>(dir: EntryCollection<T>): EntryCollection<T> {
this.root.inner.push(dir)
return dir
}
public static file(
@ -245,7 +301,7 @@ class rfwfs<T extends Entry> extends rfwfs_static {
file.hash = "0"
file.permissions = default_permissions
file.parent = default_parent
file.timestamp = new EntryValue(file, default_timestamp ? default_timestamp : (Date.now()/1000)|0)
file.timestamp = new EntryValue(file, default_timestamp ? default_timestamp : (Date.now()/1000) | 0)
file.inner = new EntryValue(file, default_inner ? default_inner : "")
file.name = new EntryValue(file, default_name)
return file
@ -261,7 +317,7 @@ class rfwfs<T extends Entry> extends rfwfs_static {
const directory = { type: EntryType.Directory } as EntryCollection<T>
directory.parent = default_parent
directory.permissions = default_permissions
directory.timestamp = new EntryValue(directory, default_timestamp ? default_timestamp : (Date.now()/1000)|0)
directory.timestamp = new EntryValue(directory, default_timestamp ? default_timestamp : (Date.now()/1000) | 0)
directory.inner = new RfwfsDirectory(directory, default_inner ? default_inner : [])
directory.name = new EntryValue(directory, default_name)
return directory
@ -277,7 +333,7 @@ class rfwfs<T extends Entry> extends rfwfs_static {
const binary = { type: EntryType.Binary } as EntryBinary
binary.parent = default_parent
binary.permissions = default_permissions
binary.timestamp = new EntryValue(binary, default_timestamp ? default_timestamp : (Date.now()/1000)|0)
binary.timestamp = new EntryValue(binary, default_timestamp ? default_timestamp : (Date.now()/1000) | 0)
binary.inner = new RfwfsBinary(binary, default_inner ? default_inner : () => {})
binary.name = new EntryValue(binary, default_name)
return binary
@ -286,8 +342,8 @@ class rfwfs<T extends Entry> extends rfwfs_static {
export default rfwfs
export {
type EntryCollection,
type DirectoryAnyDepth,
type EntryCollection,
type RfwfsDirectory,
type DirectoryAny,
type BinaryError,
@ -297,4 +353,5 @@ export {
type Entry,
Permissions,
EntryType,
ROOT_ID,
}