Current section

Files

Jump to
mist src mist internal file.gleam
Raw

src/mist/internal/file.gleam

import gleam/bytes_tree
import gleam/result
import glisten.{type Socket, type SocketReason}
import glisten/transport.{type Transport, Ssl, Tcp}
pub type FileDescriptor
pub type FileError {
IsDir
NoAccess
NoEntry
UnknownFileError
}
pub type SendError {
FileErr(FileError)
SocketErr(SocketReason)
}
pub type File {
File(descriptor: FileDescriptor, file_size: Int)
}
pub fn stat(filename: BitArray) -> Result(File, FileError) {
filename
|> open
|> result.map(fn(fd) {
let file_size = size(filename)
File(fd, file_size)
})
}
pub fn sendfile(
transport: Transport,
file_descriptor file_descriptor: FileDescriptor,
socket socket: Socket,
offset offset: Int,
bytes bytes: Int,
options options: List(a),
) -> Result(Nil, SendError) {
case transport {
Tcp(..) -> {
send_file(file_descriptor, socket, offset, bytes, options)
|> result.map_error(SocketErr)
|> result.replace(Nil)
}
Ssl(..) as transport -> {
pread(file_descriptor, offset, bytes)
|> result.map_error(FileErr)
|> result.then(fn(bits) {
transport.send(transport, socket, bytes_tree.from_bit_array(bits))
|> result.map_error(SocketErr)
})
}
}
}
@external(erlang, "file", "sendfile")
fn send_file(
file_descriptor file_descriptor: FileDescriptor,
socket socket: Socket,
offset offset: Int,
bytes bytes: Int,
options options: List(a),
) -> Result(Nil, SocketReason)
@external(erlang, "file", "pread")
fn pread(
fd: FileDescriptor,
location: Int,
bytes: Int,
) -> Result(BitArray, FileError)
@external(erlang, "mist_ffi", "file_open")
pub fn open(file: BitArray) -> Result(FileDescriptor, FileError)
@external(erlang, "filelib", "file_size")
fn size(path: BitArray) -> Int
@external(erlang, "mist_ffi", "file_close")
pub fn close(file: FileDescriptor) -> Result(Nil, FileError)