Skip to content

Latest commit

 

History

History
142 lines (111 loc) · 4.36 KB

README.md

File metadata and controls

142 lines (111 loc) · 4.36 KB

lua-buffet

Luarocks OPM Build Status License

Socket-like buffer objects for Lua

Name

The word “buffet” is a portmanteau of “buffer” and “socket”.

Description

A buffet is an object that has the same interface as socket objects in the popular Lua libraries LuaSocket and Lua Nginx Module but doesn't do any real network communication. Instead the network stack the buffet receives data from an arbitrary source. The data source can be a string, a table of strings or an iterator function producing strings.

The buffet works in a streaming fashion. That is, the buffet doesn't try to read and store internally the whole source data at once but reads as little as possible and only when necessary. That means that the buffet can be efficiently used as a proxy for sources of unlimited amounts of data such as real sockets or file I/O readers.

Another possible use is unit testing where the buffet can be used as a mock object instead of the real socket object.

Basic usage

local buffet = require('buffet')
local buffet_resty = require('buffet.resty')

-- Input data is a string.
-- Read data in chunks of 3 bytes.
do
    local bf = buffet_resty.new('data string')
    print(buffet.is_closed(bf))   -- false
    repeat
        local data, err, partial = bf:receive(3)
        print(data, err, partial)
    until err
    print(buffet.is_closed(bf))   -- true
end

-- Input data is a table containing data chunks.
-- Read data line by line.
do
    local bf = buffet_resty.new({'line 1\nline', ' 2\nli', 'ne 3\n'})
    repeat
        local data, err, partial = bf:receive('*l')
        print(data, err, partial)
    until err
end

-- Input data is a function producing data chunks.
-- Read data splitted by the specified pattern, up to 4 bytes at once.
do
    local iterator = coroutine.wrap(function()
        coroutine.yield('first-==-se')
        coroutine.yield('cond-==')
        coroutine.yield('-thi')
        coroutine.yield('rd')
        coroutine.yield(nil, 'some error')
        coroutine.yield('unreachable')
    end)
    local bf = buffet_resty.new(iterator)
    local reader = bf:receiveuntil('-==-')
    print(buffet.get_iterator_error(bf))   -- nil
    repeat
        local data, err, partial = reader(4)
        print(data, err, partial)
    until err
    print(buffet.get_iterator_error(bf))   -- some error
end

-- Send data.
do
    local bf = buffet_resty.new()
    for i = 1, 5 do
        local char = string.char(0x40 + i)
        bf:send(string.rep(char, i))
    end
    local send_buffer = buffet.get_send_buffer(bf)
    print(#send_buffer)   -- 5
    for _, chunk in ipairs(send_buffer) do
        print(chunk)
    end
    print(buffet.get_sent_data(bf))   -- ABBCCCDDDDEEEEE
end

For more advanded usage see the examples directory.

Documentation

Documentation is available at https://undef.im/lua-buffet/.

Changelog

For detailed changelog see CHANGELOG.md.

TODO

OpenResty

ngx.socket.tcp

  • constructor (ngx.socket.tcp ~ buffet.resty.new)
  • :connect (noop)
  • :sslhandshake (noop)
  • :send
  • :receive
    • :receive()
    • :receive('*l')
    • :receive('*a')
    • :receive(size)
  • :receiveany
  • :receiveuntil
    • iterator()
    • iterator(size)
    • inclusive option
  • :close
  • :settimeout (noop)
  • :settimeouts (noop)
  • :setoption (noop)
  • :setkeepalive (equivalent to :close)
  • :getreusedtimes (noop)

ngx.socket.udp

  • constructor
  • :setpeername
  • :send
  • :receive
  • :close
  • :settimeout

LuaSocket

...

License

The MIT License.