
--[[
  Library for simple and fast reading and writing of binary files. Works great with `ac.StructItem` in case you want to read whole structures instead
  of individual entities. Not available to scripts without full I/O access until CSP 0.2.8.

  Raises errors when failing to read or write data.

  Please do not fork it and copy it in your project directly, but always load it from “shared/…”: it uses a bit of internal API to better integrate
  to some other functions and be able to map files into RAM instead of loading files the usual way.

  Since 0.2.8 the implementation has been moved to CSP SDK so that scripts without I/O access could use it.
]]
---@diagnostic disable

---Namespace with some functions helpful for reading and writing binary data and files.
local binaryUtils = {}

---------------------------
-- Binary reader section --
---------------------------

---@class binaryUtils.BinaryReader
local _readMt_index = {}

---Returns 0-based offset of a cursor.
---@return integer
function _readMt_index:offset() end

---Returns total size in bytes.
---@return integer
function _readMt_index:size() end

---Returns number of bytes left to read.
---@return integer
function _readMt_index:remaining() end

---Returns `true` if there is no more data left.
---@return boolean
function _readMt_index:finished() end

---Moves cursor to a different point in a file. Raises an error if final position is below 0 or exceeds file size.
---@param offset integer
---@param relative nil|true|'start'|'cursor'|'end' @Pass `true` to offset relative to cursor. By default offsets from the start.
---@return self
function _readMt_index:seek(offset, relative) end

---Reads `size` bytes and returns as a string.
---@param size integer
---@return string
---@overload fun(): string @If `size` is not specified, all the remaining data will be read.
function _readMt_index:raw(size) end

---Be extra careful with this method! Better yet, don’t use it at all.
---
---Similar to `:raw()`, reads `size` bytes and returns as a `binary` type. However, there are three main differences:
---- Views don’t hold data and only refer to data in the parent reader.
---- That means creating a view doesn’t involve copying data around.
---- The moment parent `binaryUtils.BinaryReader` expires, all become views become not just expired, but cursed, and any interaction with them will lead to the crash at best. Be careful!
---- Views can’t be dealt with directly, but you can create new `binaryUtils.BinaryReader` instances to read data from them.
---- Main point of views is that they can be passed to CSP API if argument type is `binary` with zero overhead.
---
---So, as an example, if your binary file has a header followed by, let’s say, compressed data, you can simply pass the data to `ac.decompress()` like so:
---```
---local decompressedData = ac.decompress(mainFile:view())
---local decompressedReader = binaryUtils.process(decompressedData)
---```
---
---To prevent crashes, scripts without I/O access will get a safe `string` instead.
---@param size integer
---@return binary
---@overload fun(): binary @If `size` is not specified, all the remaining data will be read.
function _readMt_index:view(size) end

---Reads next byte without proceeding further.
---@return integer? @Returns `nil` if end has been reached.
function _readMt_index:peek() end

---Returns `true` if `pattern` matches bytes coming next. Doesn’t proceed further. Helpful if you want to quickly compare a file header, for example.
---@param pattern string
---@return boolean
function _readMt_index:match(pattern) end

---Returns `true` if there are at least `size` bytes (or entities) left to read. Doesn’t progress cursor further.
---@param targetType nil|table|string|fun(s: binaryUtils.BinaryReader): any @Could be a `ac.StructItem.combine()` output, a structure name, a data-reading `binaryUtils.BinaryReader` method or `nil` if you want to read a single char.
---@param size integer? @Default value: 1.
---@return boolean @Returns `false` if there is not enough data.
---@overload fun(s: binaryUtils.BinaryReader, size: integer): boolean
function _readMt_index:has(size, targetType) end

---Skips specified number of bytes (or entities). Raises an error if there is not enough data.
---@param targetType nil|table|string|fun(s: binaryUtils.BinaryReader): any @Could be a `ac.StructItem.combine()` output, a structure name, a data-reading `binaryUtils.BinaryReader` method or `nil` if you want to read a single char.
---@param size integer? @Default value: 1.
---@return self
---@overload fun(s: binaryUtils.BinaryReader, size: integer): binaryUtils.BinaryReader
function _readMt_index:skip(targetType, size) end

---@return boolean
function _readMt_index:bool() end
---@return number
function _readMt_index:float() end
---@return number
function _readMt_index:double() end
---@return integer
function _readMt_index:int8() end
---@return integer
function _readMt_index:uint8() end
---@return integer
function _readMt_index:int16() end
---@return integer
function _readMt_index:uint16() end
---@return integer
function _readMt_index:int32() end
---@return integer
function _readMt_index:uint32() end
---@return integer
function _readMt_index:int64() end
---@return integer
function _readMt_index:uint64() end
---@return vec2
function _readMt_index:vec2() end
---@return vec3
function _readMt_index:vec3() end
---@return vec4
function _readMt_index:vec4() end
---@return rgb
function _readMt_index:rgb() end
---@return rgbm
function _readMt_index:rgbm() end
---@return hsv
function _readMt_index:hsv() end
---@return quat
function _readMt_index:quat() end
---@return mat3x3
function _readMt_index:mat3x3() end
---@return mat4x4
function _readMt_index:mat4x4() end

_readMt_index.char = _readMt_index.int8
_readMt_index.byte = _readMt_index.uint8

---@return number
function _readMt_index:half() end
---@return number
function _readMt_index:norm8() end
---@return number
function _readMt_index:unorm8() end
---@return number
function _readMt_index:norm16() end
---@return number
function _readMt_index:unorm16() end

---Create a new struct using `ac.StructItem.combine()` and pass it here as a template, and this method will create a new
---copy with data from the file.
---@generic T
---@param targetType T @Could be a `ac.StructItem.combine()` output, a structure name, a data-reading `binaryUtils.BinaryReader` method or `nil` if you want to read a single char.
---@return T
function _readMt_index:struct(targetType) end

---Create a new array using either a structure similar to `:struct()`, or you can pass a type-reading method (as long as it doesn’t take arguments).
---A bit more efficient than reading lists on your side, and will return `nil` instantly if there is not enough data.
---@generic T
---@param targetType T @Could be a `ac.StructItem.combine()` output, a structure name, a data-reading `binaryUtils.BinaryReader` method or `nil` if you want to read a single char.
---@param size integer? @If not set, next 4-byte integer will be read (common AC arrays format).
---@return T[]
function _readMt_index:array(targetType, size) end

---Reads next string using a common AC format: four bytes for its length following by the actual content.
---@return string
function _readMt_index:string() end

---Disposes reader and closes any associated data. Doesn’t have to be called unless you want to close the file earlier, GC can take care of things too.
---Empties data so any future read calls won’t return anything.
function _readMt_index:dispose() end

---Try to read a file on a disk using memory mapping for faster access. File will be locked until `:dispose()` is called. Raises an error if failed to open a file. Not available
---to scripts without I/O access.
---@param filename string @Full filename.
---@return binaryUtils.BinaryReader
function binaryUtils.readFile(filename)
  return __util.safe('lib_binary').readFile(filename)
end

---Read something (string, `ac.StructItem`, something like `ac.connect`) as binary data.
---@param data binary @Any binary data in a form of a string.
---@return binaryUtils.BinaryReader
function binaryUtils.readData(data)
  return __util.safe('lib_binary').readData(data)
end

---------------------------
-- Binary writer section --
---------------------------

---@class binaryUtils.BinaryWriter
local _writeMt_index = {}

---Returns 0-based offset of a cursor.
---@return integer
function _writeMt_index:offset() end

---Returns total size in bytes.
---@return integer
function _writeMt_index:size() end

---Returns total capacity in bytes. If created with `.writeData()`, more space will be allocated once the capacity has been exceeded.
---@return integer
function _writeMt_index:capacity() end

---Returns number of bytes left to write until full. If created with `.writeData()`, more space will be allocated once the end is reached.
---@return integer
function _writeMt_index:remaining() end

---Returns `true` if there is no more space left. If finished but created with `.writeData()`, more space will be allocated with the next write.
---@return boolean
function _writeMt_index:finished() end

---Moves cursor to a different point in a file. Raises an error if final position is below 0 or exceeds file size (if created with `.writeFile()`).
---@param offset integer
---@param relative nil|true|'start'|'cursor'|'end'|'capacity' @Pass `true` to offset relative to cursor. By default offsets from the start.
---@return self
function _writeMt_index:seek(offset, relative) end

---Writes data directly.
---@param data binary
---@return self
function _writeMt_index:raw(data) end

---Reads next byte without proceeding further.
---@return integer? @Returns `nil` if there are no more written bytes ahead.
function _writeMt_index:peek() end

---Returns `true` if there are at least `size` bytes (or entities) left to write within capacity. Doesn’t progress cursor further.
---@param targetType nil|table|string|fun(s: binaryUtils.BinaryReader): any @Could be a `ac.StructItem.combine()` output, a structure name, a data-writing `binaryUtils.BinaryWriter` method or `nil` if you want to read a single char.
---@param size integer? @Default value: 1.
---@return boolean @Returns `false` if there is not enough data.
---@overload fun(s: binaryUtils.BinaryReader, size: integer): boolean
function _writeMt_index:has(size, targetType) end

---Skips specified number of bytes (or entities). Fills space with zeroes. If for who knows what reason you want to keep existing data, use `:seek(offset, 'cursor')` instead, but it could leave you with
---garbage data. 
---@param targetType nil|table|string|fun(s: binaryUtils.BinaryReader): any @Could be a `ac.StructItem.combine()` output, a structure name, a data-writing `binaryUtils.BinaryWriter` method or `nil` if you want to read a single char.
---@param size integer? @Default value: 1.
---@return self
---@overload fun(s: binaryUtils.BinaryReader, size: integer): binaryUtils.BinaryReader
function _writeMt_index:skip(size, targetType) end

---@param value boolean
---@return self
function _writeMt_index:bool(value) end
---@param value number
---@return self
function _writeMt_index:float(value) end
---@param value number
---@return self
function _writeMt_index:double(value) end
---@param value integer
---@return self
function _writeMt_index:int8(value) end
---@param value integer
---@return self
function _writeMt_index:uint8(value) end
---@param value integer
---@return self
function _writeMt_index:int16(value) end
---@param value integer
---@return self
function _writeMt_index:uint16(value) end
---@param value integer
---@return self
function _writeMt_index:int32(value) end
---@param value integer
---@return self
function _writeMt_index:uint32(value) end
---@param value integer
---@return self
function _writeMt_index:int64(value) end
---@param value integer
---@return self
function _writeMt_index:uint64(value) end
---@param value vec2
---@return self
function _writeMt_index:vec2(value) end
---@param value vec3
---@return self
function _writeMt_index:vec3(value) end
---@param value vec4
---@return self
function _writeMt_index:vec4(value) end
---@param value rgb
---@return self
function _writeMt_index:rgb(value) end
---@param value rgbm
---@return self
function _writeMt_index:rgbm(value) end
---@param value hsv
---@return self
function _writeMt_index:hsv(value) end
---@param value quat
---@return self
function _writeMt_index:quat(value) end
---@param value mat3x3
---@return self
function _writeMt_index:mat3x3(value) end
---@param value mat4x4
---@return self
function _writeMt_index:mat4x4(value) end

_writeMt_index.char = _writeMt_index.int8
_writeMt_index.byte = _writeMt_index.uint8

---@param value number
---@return self
function _writeMt_index:half(value) end
---@param value number
---@return self
function _writeMt_index:norm8(value) end
---@param value number
---@return self
function _writeMt_index:unorm8(value) end
---@param value number
---@return self
function _writeMt_index:norm16(value) end
---@param value number
---@return self
function _writeMt_index:unorm16(value) end

---Writes a structure.
---@param data table|vec2|vec3|vec4|rgb|rgbm|hsv|quat|mat3x3|mat4x4 @Items could be a `ac.StructItem.combine()` output, or a structure such as a vec3.
---@return self
function _writeMt_index:struct(data) end

---Writes array of entities.
---@generic T
---@param values T[] @Items could be a `ac.StructItem.combine()` output, or a structure such as a vec3.
---@param sizePrefix boolean? @If set, first four bytes with array size will be written.
---@return self
function _writeMt_index:array(values, sizePrefix) end

---Writes a string using a common AC format: 4 bytes for length and then the data.
---@param data binary
---@return self
function _writeMt_index:string(data) end

---Appends a string or binary data without any size prefixes.
---@param data binary
---@return self
function _writeMt_index:append(data) end

---Disposes reader and closes any associated data. Doesn’t have to be called unless you want to close the file earlier, GC can take care of things too.
---Empties data so any future read calls won’t return anything.
function _writeMt_index:dispose() end

---Create a new `binaryUtils.BinaryReader` in the same position (with optional offset). Raises an error if position is below 0 or exceeds current file capacity.
---@param offset integer? @If not specified, current cursor position will be used.
---@param relative nil|true|'start'|'cursor'|'end'|'capacity' @Pass `true` to offset relative to cursor. By default offsets from the start.
function _writeMt_index:read(offset, relative) end

---Store all content in a file. Raises an error if failed to save. Not available to scripts without I/O access.
---@param filename string @Full filename.
---@return self
function _writeMt_index:commit(filename) end

---Return all content as a string. Alternatively, you can use `:read(0):raw()`. Note: you can pass this writer (or reader) to functions expecting `binary` directly.
---@return string
function _writeMt_index:stringify() end

---Clear writer without deallocating memory.
---@return self
function _writeMt_index:clear() return self end

---Create and write a new file. Pros: with this function writer will store things directly to a disk. Cons: you have to know size of your
---file beforehand unless you only need to edit a few bytes here and there. Raises an error if failed to create or open a file.
---
---Not available to scripts without I/O access.
---@param filename string @Full filename.
---@param size integer? @File size. If not set, current file size will be used (and if there is no such file, an error will be raised).
---@return binaryUtils.BinaryWriter
function binaryUtils.writeFile(filename, size) end

---Write binary stuff into memory, occasionally allocating more and more space as new data gets added. Can grow to any size, but saving things
---to disk will require a copy (not that it matters that much though).
---@param sizeHint integer? @Specify amount of bytes to allocate from the start. Default value: 256 (can’t be less than that).
---@return binaryUtils.BinaryWriter
function binaryUtils.writeData(sizeHint) end

return binaryUtils