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

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

View File

@ -1,5 +1,5 @@
import { ReadStatus, PushStatus, ExecuteStatus } from "./enum/status" 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" import directory_search from "./index"
@ -15,6 +15,7 @@ const enum Permissions {
x = 1<<2, x = 1<<2,
none = 1<<3, none = 1<<3,
} }
const enum ROOT_ID { TRUNK = "/" }
type FileInner = string | number type FileInner = string | number
type BinaryError = string type BinaryError = string
@ -26,15 +27,6 @@ type Directory<T extends Entry> = EntryCollection<T>
type DirectoryAny = EntryCollection<Entry> type DirectoryAny = EntryCollection<Entry>
type DirectoryAnyDepth = EntryCollection<DirectoryAny> type DirectoryAnyDepth = EntryCollection<DirectoryAny>
interface Root<T extends Entry> {
readonly type: EntryType,
inner: T[],
}
interface RootFile<T extends Entry> extends Root<T> {
}
interface EntryStripped { interface EntryStripped {
readonly type: EntryType, readonly type: EntryType,
permissions: Permissions, permissions: Permissions,
@ -42,8 +34,8 @@ interface EntryStripped {
name: EntryValue<string>, name: EntryValue<string>,
} }
interface Entry extends EntryStripped { interface Entry<T = DirectoryAny | null> extends EntryStripped {
parent: DirectoryAny, parent: T,
} }
interface EntryFile extends Entry { interface EntryFile extends Entry {
@ -59,6 +51,15 @@ interface EntryBinary extends Entry {
inner: RfwfsBinary 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 { function strip_entry<T extends Entry>(entry: T): EntryStripped {
return { return {
type: entry.type, 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> { class EntryValue<T> {
public inner: T; public inner: T;
protected entry: Entry protected entry: Entry;
constructor(entry: Entry, inner_default: T) { constructor(entry: Entry, inner_default: T) {
this.inner = inner_default this.inner = inner_default
this.entry = entry this.entry = entry
} }
/**
Safe write
*/
public write<I extends T>(item: I): boolean { public write<I extends T>(item: I): boolean {
if (rfwfs.write_access(this.entry.permissions)) { if (rfwfs.write_access(this.entry.permissions)) {
this.inner = item 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> { class RfwfsDirectory<T extends Entry> {
public directory: T[]; public directory: T[];
protected entry: Entry; protected entry: Entry;
@ -114,52 +165,61 @@ class RfwfsDirectory<T extends Entry> {
public clone(file_name: string): WrapResultEntry<T, ReadStatus> { public clone(file_name: string): WrapResultEntry<T, ReadStatus> {
if (rfwfs.read_write_access(this.entry.permissions)) { if (rfwfs.read_write_access(this.entry.permissions)) {
const clone_find = directory_search(this.directory, file_name) return fs_dir_clone(this.directory, file_name)
if (clone_find) {
return wrap_entry(ReadStatus.Ok, { ...clone_find.result })
}
return wrap_entry(ReadStatus.NotFound)
} }
return wrap_entry(ReadStatus.Denied) return wrap_entry(ReadStatus.Denied)
} }
public find(file_name: string): WrapResultEntry<T, ReadStatus> { public find(file_name: string): WrapResultEntry<T, ReadStatus> {
if (rfwfs.read_write_access(this.entry.permissions)) { if (rfwfs.read_write_access(this.entry.permissions)) {
const file_search = directory_search(this.directory, file_name) return fs_dir_find(this.directory, file_name)
if (file_search) {
return wrap_entry(ReadStatus.Ok, file_search.result)
}
return wrap_entry(ReadStatus.NotFound)
} }
return wrap_entry(ReadStatus.Denied) return wrap_entry(ReadStatus.Denied)
} }
public push<E extends T>(entry: E): WrapResultNone<PushStatus> { public push<E extends T>(entry: E): WrapResultNone<PushStatus> {
if (rfwfs.read_write_access(this.entry.permissions)) { if (rfwfs.read_write_access(this.entry.permissions)) {
const no_duplicates = directory_search(this.directory, entry.name.inner) return fs_dir_push(this.directory, entry)
if (!no_duplicates) {
this.directory.push(entry)
this.directory.sort()
return wrap_none(PushStatus.Ok)
}
return wrap_none(PushStatus.Duplicate)
} }
return wrap_none(PushStatus.Denied) return wrap_none(PushStatus.Denied)
} }
public pop(file_name: string): WrapResultEntry<T, ReadStatus> { public pop(file_name: string): WrapResultEntry<T, ReadStatus> {
if (rfwfs.read_write_access(this.entry.permissions)) { if (rfwfs.read_write_access(this.entry.permissions)) {
const pop_find = directory_search(this.directory, file_name) fs_dir_pop(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)
} }
return wrap_entry(ReadStatus.Denied) 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 { class RfwfsBinary {
public lambda: BinaryLambda; public lambda: BinaryLambda;
protected entry: Entry; 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 { public static is_dir<T extends Entry>(entry: T): boolean {
return entry.type === EntryType.Directory return entry.type === EntryType.Directory
} }
@ -192,9 +255,6 @@ class rfwfs_static {
public static is_binary<T extends Entry>(entry: T): boolean { public static is_binary<T extends Entry>(entry: T): boolean {
return entry.type === EntryType.Binary 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 { public static read_access(permissions: Permissions): boolean {
return (permissions & Permissions.r) !== 0 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>; public root: Root<T>;
constructor(inner: T[]) { constructor() {
super() 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( public push_directory_into_root<T extends Entry>(dir: EntryCollection<T>): EntryCollection<T> {
default_name: string, this.root.inner.push(dir)
default_permissions: Permissions, return dir
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 static file( public static file(
@ -286,8 +342,8 @@ class rfwfs<T extends Entry> extends rfwfs_static {
export default rfwfs export default rfwfs
export { export {
type EntryCollection,
type DirectoryAnyDepth, type DirectoryAnyDepth,
type EntryCollection,
type RfwfsDirectory, type RfwfsDirectory,
type DirectoryAny, type DirectoryAny,
type BinaryError, type BinaryError,
@ -297,4 +353,5 @@ export {
type Entry, type Entry,
Permissions, Permissions,
EntryType, EntryType,
ROOT_ID,
} }