trickle.lua 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. -- trickle v0.1.0 - Lua bitstream
  2. -- https://github.com/bjornbytes/trickle
  3. -- MIT License
  4. local trickle = {}
  5. local bit = bit32 or require 'bit'
  6. local lshift, rshift, band, bxor, bnot = bit.lshift, bit.rshift, bit.band, bit.bxor, bit.bnot
  7. local extract = bit.extract or function(x, i, n)
  8. return band(rshift(x, i), lshift(1, n or 1) - 1)
  9. end
  10. local replace = bit.replace or function(x, y, i, n)
  11. local mask = lshift(rshift(bit.bnot(0), 31 - (n - 1)), i)
  12. return bit.bxor(x, bit.band(bit.bxor(x, lshift(y, i)), mask))
  13. end
  14. function trickle.create(str)
  15. local stream = {
  16. str = str or '',
  17. byte = nil,
  18. byteLen = nil
  19. }
  20. return setmetatable(stream, trickle)
  21. end
  22. function trickle:truncate()
  23. if self.byte then
  24. self.str = self.str .. string.char(self.byte)
  25. self.byte = nil
  26. self.byteLen = nil
  27. end
  28. return self.str
  29. end
  30. function trickle:clear()
  31. self.str = ''
  32. self.byte = nil
  33. self.byteLen = nil
  34. return self
  35. end
  36. function trickle:write(x, sig)
  37. if sig == 'string' then self:writeString(x)
  38. elseif sig == 'bool' then self:writeBool(x)
  39. elseif sig == 'float' then self:writeFloat(x)
  40. else
  41. local n = sig:match('(%d+)bit')
  42. self:writeBits(x, n)
  43. end
  44. return self
  45. end
  46. function trickle:writeString(string)
  47. self:truncate()
  48. string = tostring(string)
  49. self.str = self.str .. string.char(#string) .. string
  50. end
  51. function trickle:writeBool(bool)
  52. local x = bool and 1 or 0
  53. self:writeBits(x, 1)
  54. end
  55. function trickle:writeFloat(float)
  56. self:writeString(float)
  57. end
  58. function trickle:writeBits(x, n)
  59. local idx = 0
  60. repeat
  61. if not self.byte then self.byte = 0 self.byteLen = 0 end
  62. local numWrite = math.min(n, (7 - self.byteLen) + 1)
  63. local toWrite = extract(x, idx, numWrite)
  64. self.byte = replace(self.byte, toWrite, self.byteLen, numWrite)
  65. self.byteLen = self.byteLen + numWrite
  66. if self.byteLen == 8 then
  67. self.str = self.str .. string.char(self.byte)
  68. self.byte = nil
  69. self.byteLen = nil
  70. end
  71. n = n - numWrite
  72. idx = idx + numWrite
  73. until n == 0
  74. end
  75. function trickle:read(kind)
  76. if kind == 'string' then return self:readString()
  77. elseif kind == 'bool' then return self:readBool()
  78. elseif kind == 'float' then return self:readFloat()
  79. else
  80. local n = tonumber(kind:match('(%d+)bit'))
  81. return self:readBits(n)
  82. end
  83. end
  84. function trickle:readString()
  85. if self.byte then
  86. self.str = self.str:sub(2)
  87. self.byte = nil
  88. self.byteLen = nil
  89. end
  90. local len = self.str:byte(1)
  91. local res = ''
  92. if len then
  93. self.str = self.str:sub(2)
  94. res = self.str:sub(1, len)
  95. self.str = self.str:sub(len + 1)
  96. end
  97. return res
  98. end
  99. function trickle:readBool()
  100. return self:readBits(1) > 0
  101. end
  102. function trickle:readFloat()
  103. return tonumber(self:readString())
  104. end
  105. function trickle:readBits(n)
  106. local x = 0
  107. local idx = 0
  108. while n > 0 do
  109. if not self.byte then self.byte = self.str:byte(1) or 0 self.byteLen = 0 end
  110. local numRead = math.min(n, (7 - self.byteLen) + 1)
  111. x = x + (extract(self.byte, self.byteLen, numRead) * (2 ^ idx))
  112. self.byteLen = self.byteLen + numRead
  113. if self.byteLen == 8 then
  114. self.str = self.str:sub(2)
  115. self.byte = nil
  116. self.byteLen = nil
  117. end
  118. n = n - numRead
  119. idx = idx + numRead
  120. end
  121. return x
  122. end
  123. function trickle:pack(data, signature)
  124. local keys
  125. if signature.delta then
  126. keys = {}
  127. for _, key in ipairs(signature.delta) do
  128. if type(key) == 'table' then
  129. local has = 0
  130. for i = 1, #key do
  131. if data[key[i]] ~= nil then
  132. keys[key[i]] = true
  133. has = has + 1
  134. else
  135. keys[key[i]] = false
  136. end
  137. end
  138. if has == 0 then self:write(0, '1bit')
  139. elseif has == #key then self:write(1, '1bit')
  140. else error('Only part of message delta group "' .. table.concat(key, ', ') .. '" was provided.') end
  141. else
  142. self:write(data[key] ~= nil and 1 or 0, '1bit')
  143. keys[key] = data[key] ~= nil and true or false
  144. end
  145. end
  146. end
  147. for _, sig in ipairs(signature) do
  148. if not keys or keys[sig[1]] ~= false then
  149. if type(sig[2]) == 'table' then
  150. self:write(#data[sig[1]], '4bits')
  151. for i = 1, #data[sig[1]] do self:pack(data[sig[1]][i], sig[2]) end
  152. else
  153. self:write(data[sig[1]], sig[2])
  154. end
  155. end
  156. end
  157. end
  158. function trickle:unpack(signature)
  159. local keys
  160. if signature.delta then
  161. keys = {}
  162. for i = 1, #signature.delta do
  163. local val = self:read('1bit') > 0
  164. if type(signature.delta[i]) == 'table' then
  165. for j = 1, #signature.delta[i] do keys[signature.delta[i][j]] = val end
  166. else
  167. keys[signature.delta[i]] = val
  168. end
  169. end
  170. end
  171. local data = {}
  172. for _, sig in ipairs(signature) do
  173. if not keys or keys[sig[1]] ~= false then
  174. if type(sig[2]) == 'table' then
  175. local ct = self:read('4bits')
  176. data[sig[1]] = {}
  177. for i = 1, ct do table.insert(data[sig[1]], self:unpack(sig[2])) end
  178. else
  179. data[sig[1]] = self:read(sig[2])
  180. end
  181. end
  182. end
  183. return data
  184. end
  185. trickle.__tostring = trickle.truncate
  186. trickle.__index = trickle
  187. return { create = trickle.create }