fromz85

function fromz85( z85str [, ignore] ) --> str, err

Description

Decodes a Z85 encoded string to a data string. It is possible to ignore characters like \n in z85str via the optional ignore string. The Z85 without the ignored characters must be divisible by 5.

Parameters

z85str

The Z85 encoded string that should be decoded.

ignore

String that represents a optional set of characters that should be ignored in z85str.

Return Values

str

The decoded data string or nil if an error occurs.

err

A message that explains the error, otherwise nil.

Code

--ZFUNC-fromz85-v1
local function fromz85( z85str, ignore ) --> str
   local z85Decoder = { 0x00, 0x44, 0x00, 0x54, 0x53, 0x52, 0x48, 0x00,
                       0x4B, 0x4C, 0x46, 0x41, 0x00, 0x3F, 0x3E, 0x45,
                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
                       0x08, 0x09, 0x40, 0x00, 0x49, 0x42, 0x4A, 0x47,
                       0x51, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,
                       0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32,
                       0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
                       0x3B, 0x3C, 0x3D, 0x4D, 0x00, 0x4E, 0x43, 0x00,
                       0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
                       0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
                       0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
                       0x21, 0x22, 0x23, 0x4F, 0x00, 0x50, 0x00, 0x00 }
   local errlen = "invalid length: %d - must be a multiple of 5"
   local errchar = "unexpected character at position %d: '%s'"

   if ignore then z85str = z85str:gsub( "["..ignore.."]", "" ) end
   if ( #z85str % 5 ) ~= 0 then return nil, string.format( errlen, #z85str ) end

   local result = {}

   local value = 0
   for i = 1, #z85str do
      local index = string.byte( z85str, i ) - 31
      if index < 1 or index >= #z85Decoder then
         return nil, string.format( errchar, i, string.sub( z85str, i, i ) )
      end
      value = ( value * 85 ) + z85Decoder[ index ]
      if ( i % 5 ) == 0 then
         local divisor = 256 * 256 * 256
         while divisor ~= 0 do
            local b = math.floor( value / divisor ) % 256
            table.insert( result, string.char( b ) )
            divisor = math.floor( divisor / 256 )
         end
         value = 0
      end
   end

   return table.concat( result )
end

return fromz85

Examples

local t = require( "tapered" )
local fromz85 = require( "fromz85" )

--http://rfc.zeromq.org/spec:32
local data = string.char( 0x86, 0x4f, 0xd2, 0x6f, 0xb5, 0x59, 0xf7, 0x5b )
t.is( fromz85( "HelloWorld" ), data )

--https://github.com/msealand/z85.node/blob/master/test/encode.test.js
t.is( fromz85( "f!$Kw" ), "1234" )

--ignore characters
t.is( fromz85( "'f!$Kw'\n", "'\n" ), "1234" )

--wrong length error
local res, err = fromz85( "abcdefghi" )
t.nok( res )
t.is( err, "invalid length: 9 - must be a multiple of 5" )

--wrong character error
local c = string.char( 140 )
local res, err = fromz85( "f"..c.."$Kw" )
t.nok( res )
t.is( err, string.format( "unexpected character at position 2: '%s'", c ) )

t.done()

See also