diff options
-rw-r--r-- | docs/DESIGN.md | 27 | ||||
-rw-r--r-- | src/main/kotlin/WebOS.kt | 55 |
2 files changed, 82 insertions, 0 deletions
diff --git a/docs/DESIGN.md b/docs/DESIGN.md new file mode 100644 index 0000000..f3dd5aa --- /dev/null +++ b/docs/DESIGN.md @@ -0,0 +1,27 @@ +# Components of WebOs + +## WebOS + +A WebOS is the uppermost parent object of everything. It holds multiple console windows, one or more file systems, and other capabilities of the OS, such as whether network access, user control and system configurations. + +## Console + +A Console represents one access port to a [WebOS]. It can be a virtual console, which has no visual output port (potentially in the future used as a daemon), or one bound to a HTML Element, to which its output will be rendered. + +## Activity + +An Activity is a program which has direct access to a [Console]s rendering output, such as a shell which runs programs with only a STDOUT available. + +## FileSystem + +A FileSystem is composed of multiple [Mount]s to which it delegates file accesses to. + +## Mount + +A Mount processes individual file accesses and actions in its domain. It controls most files within its prefix, however it is not aware of it's prefix. A mount may be mounted at multiple paths. + + + +[Console]: #console +[WebOS]: #webos +[Activity]: #activity diff --git a/src/main/kotlin/WebOS.kt b/src/main/kotlin/WebOS.kt index 2ff0b62..d1b0d81 100644 --- a/src/main/kotlin/WebOS.kt +++ b/src/main/kotlin/WebOS.kt @@ -58,7 +58,62 @@ class Console(val os: WebOS, val renderElement: Element?) { class WebOS { private val _consoles = mutableListOf<Console>() val consoles get() = _consoles.toList() + val fileSystem = FileSystem() fun registerConsole(element: Element) { _consoles.add(Console(this, element)) } } + +interface User { + val name: String + val homeDirectory: Path +} + +data class Path private constructor(val parts: List<String>) { + companion object { + fun of(text: String) = + Path(text.split("/")) + fun of(vararg parts: String): Path { + if(parts.any { it.contains("/") }) + throw IllegalArgumentException("Path parts cannot contain forward slashes") + return Path(parts.toList()) + } + } +} + +class FileSystem { + val mounts = mutableMapOf<Path, Mount>() + fun mount(path: Path, mount:Mount) { + mounts[path] = mount + } + fun <T>findMountFor(path: Path, operation: Mount.(relativePath: Path) -> T) :T{ + val (mountPath, mount) = mounts.filterKeys { + // path.startsWith(it) + true + }.maxByOrNull { it.key.parts.size} ?: throw IllegalStateException("No mount present") + return mount.operation(mountPath.relativize(path)) + } + + fun read(path: Path): ReadResult = findMountFor(path) { read(it) } + fun write(path: Path, data: ByteArray): Unit = TODO() + fun stat(path: Path): Unit = TODO() +} + +sealed class ReadResult { + class Success(val text: String) : ReadResult() + object NotFound + object NoAccess +} +interface Mount { + fun read(relativePath: Path): ReadResult = TODO() + fun write(path: Path, data: ByteArray): Unit = TODO() + fun stat(path: Path): Unit = TODO() +} + +data class Stat( + val exists: Boolean, + var owner: User, + val created: Long, + val edited: Long, + val size: Long +) |