wip: root can add directories to itself
This commit is contained in:
@ -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
|
@ -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,
|
||||
}
|
Reference in New Issue
Block a user