Skip to content

Commit

Permalink
add details for installation, clean up
Browse files Browse the repository at this point in the history
  • Loading branch information
Bilal2453 committed Jul 17, 2023
1 parent 432edff commit 0b42e52
Show file tree
Hide file tree
Showing 9 changed files with 163 additions and 66 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# coro-docs

Unofficial docs for the luvit libraries coro-*.
Documentation for the [Luvit](https://luvit.io/) coro-* libraries.

## Index

Expand Down
90 changes: 58 additions & 32 deletions docs/coro-channel.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,18 @@
layout: doc
---

# Documentation
# coro-channel

Unofficial documentation for the [coro-channel](https://github.com/luvit/lit/blob/master/deps/coro-channel.lua) module, version 3.0.2.
Documentation for the [coro-channel](https://github.com/luvit/lit/blob/master/deps/coro-channel.lua) module, version 3.0.3.

[coro-channel](https://github.com/luvit/lit/blob/master/deps/coro-channel.lua) is a wrapper module that provides manipulating read/write streams in a sync style of code using Lua coroutines without blocking the event loop.
[coro-channel](https://github.com/luvit/lit/blob/master/deps/coro-channel.lua) is a wrapper module that wraps [stream handles](https://github.com/luvit/luv/blob/master/docs.md#uv_stream_t--stream-handle) (or any other handle that inherits stream) to provide a sync style read/write interface making use of Lua coroutines, and without blocking the event loop.

### Installation

```sh
lit install creationix/coro-channel
```
[On Lit search.](https://luvit.io/lit.html#coro-channel)

----

Expand All @@ -16,7 +23,7 @@ Unofficial documentation for the [coro-channel](https://github.com/luvit/lit/blo

### wrapRead(socket) {#wrapRead}

Wraps a [stream handle](https://github.com/luvit/luv/blob/master/docs.md#uv_stream_t--stream-handle) for a coroutine based reading.
Wraps a [stream handle](https://github.com/luvit/luv/blob/master/docs.md#uv_stream_t--stream-handle) for coroutine based reading.

*This method does not require running in a coroutine*

Expand All @@ -38,28 +45,32 @@ Wraps a [stream handle](https://github.com/luvit/luv/blob/master/docs.md#uv_stre
- A standard input echo example<br>(Type something in the console to get an echo)

```lua
local uv = require("uv") -- or luv outside of Luvi
local stdin = uv.new_tty(0, true) -- Create a readable stream, a TTY stream in this case
local reader, closer = wrapRead(stdin) -- Wrap the readable stream
for chunk in reader do -- Each time something is typed in console: execute reader and store the result in chunk
if not chunk or chunk == '\n' then break end -- If the user inputs an empty chunk then stop reading
print("You typed: " .. chunk) -- Output what the user have input
local uv = require("uv") -- or "luv" outside of Luvi
local wrapRead = require("coro-channel").wrapRead

local stdin = uv.new_tty(0, true) -- create a readable stream, a TTY stream in this case
local reader, closer = wrapRead(stdin) -- wrap the readable stream
for chunk in reader do -- each time something is typed in console: execute reader and store the result in chunk
if chunk == '\n' then break end -- if the input is a new line (Enter) stop reading
print("You typed: " .. chunk) -- output the user input
end
closer() -- Close the handle if reading has stopped
closer() -- close the handle if reading has stopped
print("You have exited")
```

Note: In the above example we won't receive an End of Stream (EoS), so we break manually on new lines, but this is not always the case, for example the coro-net reader will return `nil` when an EoS is received which would automatically break out of the for loop.

----

### wrapWrite(socket) {#wrapWrite}

Wraps a [stream](https://github.com/luvit/luv/blob/master/docs.md#uv_stream_t--stream-handle) handle for a coroutine based writing.
Wraps a [stream handle](https://github.com/luvit/luv/blob/master/docs.md#uv_stream_t--stream-handle) for coroutine based writing.

#### Parameters {#wrapWrite-parameters}

| Param | Type | Description |
|:------:|:------:|:------------|
| socket | [uv_stream_t](https://github.com/luvit/luv/blob/master/docs.md#uv_stream_t--stream-handle) | The stream [handle](https://github.com/luvit/luv/blob/master/docs.md#uv_handle_t--base-handle) to be wrapped for writing. |
| socket | [uv_stream_t](https://github.com/luvit/luv/blob/master/docs.md#uv_stream_t--stream-handle) | The [stream handle](https://github.com/luvit/luv/blob/master/docs.md#uv_handle_t--base-handle) to be wrapped for writing. |

#### Returns {#wrapWrite-returns}

Expand All @@ -73,24 +84,26 @@ Wraps a [stream](https://github.com/luvit/luv/blob/master/docs.md#uv_stream_t--s
- Timer writing to stdout TTY every second

```lua
local uv = require("uv") -- or luv outside of Luvi
local stdout = uv.new_tty(1, false) -- Create a writable stdout stream
local writer, closer = wrapWrite(stdout) -- Wrap the writable stream
local uv = require("uv") -- or "luv" outside of Luvi
local wrapWrite = require("coro-channel").wrapWrite

local stdout = uv.new_tty(1, false) -- create a writable stdout stream
local writer, closer = wrapWrite(stdout) -- wrap the writable stream

local passed = 0 -- How many second have passed?
local function callback() -- A callback to be executed every second
coroutine.wrap(function() -- A new coroutine each time
local passed = 0 -- how many second have passed?
local function callback() -- a callback to be executed every second
coroutine.wrap(function() -- a new coroutine each time
passed = passed + 1
writer(passed .. " seconds has passed!\n") -- Write to stdout
writer(passed .. " seconds has passed!\n") -- write to stdout
end)()
end

writer("Hello to the timer! To exit press Ctrl + C\n")
local timer = uv.new_timer() -- Create a timer handle
timer:start(1000, 1000, callback) -- Start it and repeat every second
local timer = uv.new_timer() -- create a timer handle
timer:start(1000, 1000, callback) -- start it and repeat every second
```

Note: In the previous example the callback could be defined in the following way:
Note: In the previous example the callback could be defined in the following way to avoid creating a new one everytime:
```lua
local callback = coroutine.wrap(function()
while true do
Expand All @@ -105,9 +118,9 @@ end)

### wrapSteam(socket) {#wrapStream}

Wraps a [stream](https://github.com/luvit/luv/blob/master/docs.md#uv_stream_t--stream-handle) handle for both writing and reading.
Wraps a [stream handle](https://github.com/luvit/luv/blob/master/docs.md#uv_stream_t--stream-handle) for both writing and reading.

Has the same effect to calling `wrapRead` and `wrapWrite` on a stream, such as:
Has the same effect to calling `wrapRead` and `wrapWrite` on the handle, such as:
```lua
local reader = wrapRead(stream)
local writer, closer = wrapWrite(stream)
Expand All @@ -117,7 +130,7 @@ local writer, closer = wrapWrite(stream)

| Param | Type | Description |
|:------:|:------:|:------------|
| socket | [uv_stream_t](https://github.com/luvit/luv/blob/master/docs.md#uv_stream_t--stream-handle) | The stream [handle](https://github.com/luvit/luv/blob/master/docs.md#uv_handle_t--base-handle) to be wrapped for writing. |
| socket | [uv_stream_t](https://github.com/luvit/luv/blob/master/docs.md#uv_stream_t--stream-handle) | The [stream handle](https://github.com/luvit/luv/blob/master/docs.md#uv_handle_t--base-handle) to be wrapped for reading and writing. |

#### Returns {#wrapStream-returns}

Expand All @@ -136,6 +149,7 @@ local writer, closer = wrapWrite(stream)
### reader() {#reader}

Yields the running coroutine and resumes it after receiving a chunk of data.
Effectively: wait until there is data to read, then return the read data.

#### Returns {#reader-returns}

Expand All @@ -148,14 +162,19 @@ Yields the running coroutine and resumes it after receiving a chunk of data.

- Using a reader in an iterator

```lua
```lua
local uv = require("uv") -- or "luv" outside of luvi
local wrapRead = require("coro-channel").wrapRead

local handle = uv.new_tty(1, true) -- or any kind of streams
local reader = coro_channel.wrapRead(handle)
local reader = wrapRead(handle)

for chunk, err in reader do
if err then
print("An error has occurred: " .. err)
break
elseif chunk == '\n' then -- press Enter to exit the tty
break
end
print("Data chunk successfully read: " .. chunk)
end
Expand All @@ -168,12 +187,13 @@ print("Reading data done")
### writer(chunk) {#writer}

Yields the running coroutine and resumes it when done writing the provided chunk of data.
Effectively: write the data and wait until it has been written, then return.

#### Parameters {#writer-parameters}

| Param | Type | Description |
|:------:|:------:|:------------|
| chunk | string / table / nil | `nil` indicates EOF and will completely close the stream if there's nothing to read, otherwise it will shutdown the writing duplex only.<br> If the provided value is a string it will be written to the stream as a single chunk.<br> If a table of strings is provided the strings will be written in a one system call as if they were concatenated. |
| chunk | string / table / nil | `nil` indicates End of Stream and will completely close the stream if there's nothing to read, if there is, it will only shutdown the writing duplex.<br> If the provided value is a string it will be written to the stream as a single chunk.<br> If a table of strings is provided the string values will be concatenated and written in a single system call. |

#### Returns {#writer-returns}

Expand All @@ -187,8 +207,11 @@ Yields the running coroutine and resumes it when done writing the provided chunk
Assuming the following example of using `writer` with a TTY handle running in a coroutine:

```lua
local uv = require("uv") -- or "luv" outside of Luvi
local wrapWrite = require("coro-channel").wrapWrite

local handle = uv.new_tty(0, false) -- or any kind of streams
local writer = coro_channel.wrapWrite(handle)
local writer = wrapWrite(handle)

local tbl = {"Hello ", "There", "!!", "\n"}
local success, err = writer(tbl)
Expand All @@ -198,13 +221,16 @@ if not success then
end
```

Note: usually though you don't use it like this with a TTY handle, it was used like this in the above example just to make it simple.
Note: usually though this example is not how you use it with a TTY handle, the example is simplified and for explanation purposes only.

----


### closer() {#closer}

Closes the wrapped stream completely if it wasn't already closed. You cannot read or write from a closed stream. Note that this returns immediately, even if the stream isn't closed yet.
Closes the wrapped stream handle if it hasn't been already closed.
You cannot read or write from/to a closed stream.

Note: This call returns immediately, even if the stream hasn't fully closed yet.

----
42 changes: 32 additions & 10 deletions docs/coro-fs.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@
layout: doc
---

# Documentation
# coro-fs

Documentation for the module [coro-fs](https://github.com/luvit/lit/blob/master/deps/coro-fs.lua), version 2.2.4.

[coro-fs](https://github.com/luvit/lit/blob/master/deps/coro-fs.lua) is a library for asynchronous non-blocking filesystem manipulations while keeping the sync style of your code, making use of Lua coroutines.
[coro-fs](https://github.com/luvit/lit/blob/master/deps/coro-fs.lua) is a library for asynchronous non-blocking filesystem operations that keeps the synchronous code style, making use of Lua coroutines.

Luvit's built-in `fs` module already has asynchronous non-blocking operations (the calls not suffixed with `Sync`, as `Sync` calls *are* blocking!) but they use the ugly callbacks!
Luvit's built-in `fs` module already has asynchronous non-blocking operations (the calls not suffixed with `Sync`, as `Sync` calls *will* block a thread in the threadpool!) but they use the ugly callbacks!

Note: that by choosing to do asynchronous FS, you are making a tradeoff.
First Luvit (and coro-fs) uses Libuv for filesystem IO, while the synchronous blocking calls in the Luvit `fs` API (e.x. `fs.writeFileSync`) will block the main thread (when executed outside of a luv callback), they *still* allow other I/O operations to happen, and the event loop can still tick just fine, this is because Libuv has a threadpool which all I/O happens in (by default 4 threads and can be changed with the `UV_THREADPOOL_SIZE` environment variable). So you can aboslutely be doing 4 blocking reads/writes (by default) before you actually run into issues where you need asynchronous FS. For example, if you are running a web server where you read a file and send it back, it is possible that you could receive 4 connections at the same time, they all concurrently read some file and send the responses back without interrupting each other.
The tradeoff you make by using asynchronous FS is performance, synchronous I/O are much faster but they block a thread in the threadpool, while asynchronous I/O is much slower but won't block any threads. Unless you are running a very busy server, I can't imagine you need asynchronous FS!
First off, Luvit (and coro-fs) uses Libuv for filesystem IO, while the synchronous blocking calls in the Luvit `fs` API (e.x. `fs.writeFileSync`) will block the main thread (when executed outside of a luv callback), they *still* allow other I/O operations to happen, and the event loop can still tick just fine, this is because Libuv has a threadpool which all I/O happens in (by default 4 threads and can be changed with the `UV_THREADPOOL_SIZE` environment variable). So you can aboslutely be doing 4 blocking reads/writes (by default) before you actually run into issues where you need asynchronous FS. For example, if you are running a web server where you read a file and send it back, it is possible that you could receive 4 connections at the same time, they all concurrently read some file and send the responses back without interrupting each other.
The tradeoff you make by using asynchronous FS is performance, synchronous I/O is much faster but it blocks a thread in the threadpool, while asynchronous I/O is much slower but won't block any threads. Unless you are running a very busy server, I can't imagine you need asynchronous FS!

Another Note: Luvit built-in async fs *ALREADY* has coroutine support which achieve a similar purpose to this module:
```lua
Expand All @@ -28,6 +28,13 @@ local contents = coro_fs.readFile('./my_file.txt')
print("The file contains: ", contents)
```

### Installation

```sh
lit install creationix/coro-fs
```
[On Lit search.](https://luvit.io/lit.html#coro-fs)

----

## Errors
Expand Down Expand Up @@ -176,13 +183,10 @@ Identical to [stat](#stat), except that instead of accepting a path to file/dire

----

### symlink(target, path) {#symlink}
### symlink(target, path, flags) {#symlink}

Creates a symbolic link (also known as soft link) at `path` that points up to `target`.

***WARNING***: There is currently a bug with this, it was fixed in the latest GH version but not yet published to Lit.
***TODO***: In the next release of coro-fs a new parameter will be added, document it when it is published to Lit.

***This method MUST be run in a coroutine***

#### Parameters {#symlink-parameters}
Expand All @@ -191,6 +195,7 @@ Creates a symbolic link (also known as soft link) at `path` that points up to `t
|:------|:------:|:------------|
| target| string | The path of the file you want to link against. |
| path | string | The path to where to create the said link at. |
| flags | table / integer / nil | Optional table with `dir` and `junction` boolean fields that control how the symlink is created on Windows. See [Libuv page](https://docs.libuv.org/en/v1.x/fs.html#c.uv_fs_symlink) for more details. |

#### Returns {#symlink-returns}

Expand Down Expand Up @@ -520,6 +525,23 @@ For example `mkdir("./a/b/c/")` this call will create a directory `a` that conta

### chroot(base) {#chroot}

***TODO***: Document this.
Returns a version of this module that can only operate inside `base` directory.
This is supposed to be safe and unescapable, and is used in sensitive places such as the Lit server.

The table returned is identical to the module table, except an additional `base` field that is equal to the passed argument.

***WARNING***: In version 2.2.1 and before, there was a bug that allowed an attacker to escape the chroot. If you are using a vulnerable version, please update to `2.2.2` or newer!

*This method does not require running in a coroutine*

#### Parameters {#mkdirp-parameters}

| Param | Type | Description | Optional |
|:------|:------:|:------------|:--------:|
| base | string | The path to the directory FS operations will be contained in. ||

#### Returns {#mkdirp-returns}

| Name | Type | Description | Provided On |
|:-----|:------:|:------------|:-----------:|
| chroot | table | A table containing all methods this module contains. | Always |
9 changes: 8 additions & 1 deletion docs/coro-http.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
layout: doc
---

# Documentation
# coro-http

Documentation for the library [coro-http](https://github.com/luvit/lit/blob/master/deps/coro-http.lua), version 3.2.3.

Expand All @@ -14,6 +14,13 @@ Keep in mind, Luvit (starting with [version 2.18](https://github.com/luvit/luvit

Many thanks for [@trumedian](https://github.com/truemedian) for helping out with this!

### Installation

```sh
lit install creationix/coro-http
```
[On Lit search.](https://luvit.io/lit.html#coro-http)

----

## Functions
Expand Down
13 changes: 10 additions & 3 deletions docs/coro-net.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,18 @@
layout: doc
---

# Documentation
# coro-net

Unofficial docs for the module [coro-net](https://github.com/luvit/lit/blob/master/deps/coro-net.lua) version 3.2.1.
Documentation for the module [coro-net](https://github.com/luvit/lit/blob/master/deps/coro-net.lua), version 3.2.1.

[coro-net](https://github.com/luvit/lit/blob/master/deps/coro-net.lua) is a library for TCP and pipes manipulations, with optional secure-layer support while keeping the sync code style.
[coro-net](https://github.com/luvit/lit/blob/master/deps/coro-net.lua) is a library for handling TCP, UDP and generally pipes, with an optional secure-layer support using a synchronous style interface.

### Installation

```sh
lit install creationix/coro-net
```
[On Lit search.](https://luvit.io/lit.html#coro-net)

----

Expand Down
21 changes: 14 additions & 7 deletions docs/coro-spawn.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,20 @@
layout: doc
---

# Documentation
# coro-spawn

Unofficial docs for the [coro-spawn](https://github.com/luvit/lit/blob/master/deps/coro-spawn.lua) module, version 3.0.3.
Documentation for the [coro-spawn](https://github.com/luvit/lit/blob/master/deps/coro-spawn.lua) module, version 3.0.3.

[coro-spawn](https://github.com/luvit/lit/blob/master/deps/coro-spawn.lua) is single-function module that provides manipulating child-process in a sync style of code using Lua coroutines.
[coro-spawn](https://github.com/luvit/lit/blob/master/deps/coro-spawn.lua) is single-function module that provides spawning child-processes with a synchronous interface making use of Lua coroutines.

We will call the only function return of this module `spawn`.
Throughout the documentation, we will refer to the function return of this module as `spawn`. And it is obtained by calling `require("coro-spawn")`.

### Installation

```sh
lit install creationix/coro-spawn
```
[On Lit search.](https://luvit.io/lit.html#coro-spawn)

----

Expand All @@ -18,17 +25,17 @@ We will call the only function return of this module `spawn`.

### spawn(path, options) {#spawn}

Spawns a process of an executable at `path` using the said `options`.
Spawns a process of an executable at `path` using the provided `options`.

Note: The `options` parameter is NOT optional, if you don't want to provide any options just pass an empty table.
Note: The `options` parameter is *NOT* optional, if you don't want to provide any options, pass an empty table.

*This method does not require running in a coroutine*

#### Parameters {#spawn-parameters}

| Param | Type | Description |
|:-----:|:------:|:------------|
| path | string | The path of the executable (defined by system) to be spawned. |
| path | string | The path of the executable to spawn. |
| options | table| Various options to control the process flow. See [Spawn Options](#spawn-options). |

#### Returns {#spawn-returns}
Expand Down
Loading

0 comments on commit 0b42e52

Please sign in to comment.