============================================================================== ./http-hash.lua ============================================================================== local function isEmpty(str) 3725 return str == nil or str == "" end -- Invertible split function local function split(str, delimiter) 1376 local result = {} 1376 local index = 1 1346 local from = 1 1346 local delim_from, delim_to = string.find(str, delimiter, from) 3876 while delim_from do 2530 result[index] = string.sub(str, from, delim_from - 1) 2560 index = index + 1 2590 from = delim_to + 1 2537 delim_from, delim_to = string.find(str, delimiter, from) end 1377 result[index] = string.sub(str, from) 1378 return result end -- Invertible join function (starting from index in table) local function join(arr, delimiter, fromIndex) 38 fromIndex = fromIndex or 1 98 local len = #arr - fromIndex + 1 98 if len <= 0 then ****0 return "" end 38 local res = arr[fromIndex] 88 for i = fromIndex + 1, fromIndex + len - 1 do 20 res = res .. delimiter .. arr[i] end 98 return res end local function createRouteNode(parent, segment, isSplat) 1142 return { 1142 handler = nil, 1112 isSplat = isSplat or isSplat == true, 1142 parent = parent, 1112 segment = segment, 1142 src = nil, 1112 staticPaths = {}, 1112 variablePaths = nil 1142 } end local function createRouteResult(node, params, splat) 627 return { 627 handler = node and node.handler or nil, 621 splat = splat, 651 params = params, 597 src = node and node.src or null 657 } end local function routeConflictError(pathname, hash) local conflictPath 200 if hash.isSplat then 55 conflictPath = "" else 211 conflictPath = "/" end 352 while hash and hash.parent do local prefix 200 if not hash.isSplat and hash == hash.parent.variablePaths then 139 prefix = ":" else 37 prefix = "" end 182 conflictPath = "/" .. prefix .. hash.segment .. conflictPath 152 hash = hash.parent; end 394 error({ 182 message = "Route conflict", 182 attemptedPath = pathname, 212 conflictPath = conflictPath 182 }, 2) end local function getHttpHash(self, pathname) 609 local pathSegments = split(pathname, "/") 603 local hash = self._hash 633 local splatIndex, splatTo = string.find(pathname, "*") 579 local params = {} local splat 2069 for i = 1, #pathSegments do 1823 local segment = pathSegments[i] 1378 if not isEmpty(segment) and not hash.isSplat then 890 local newHash = hash.staticPaths[segment] 685 if newHash then 423 hash = newHash 373 elseif hash.variablePaths then 202 hash = hash.variablePaths 238 if hash.isSplat then 32 splat = join(pathSegments, "/", i) 60 break; else 295 params[hash.segment] = segment; end else 100 hash = nil break end end end -- Match the empty splat 535 if hash ~= nil and 417 hash.handler == nil and 240 hash.variablePaths and 30 hash.variablePaths.isSplat then 68 splat = "" 8 hash = hash.variablePaths end 328 return createRouteResult(hash, params, splat) end local function setHttpHash(self, pathname, handler) 779 local pathSegments = split(pathname, "/") 779 local hash = self._hash 749 local lastIndex = #pathSegments 749 local splatIndex, splatTo = string.find(pathname, "*") 425 local hasSplat = splatIndex ~= nil 455 if handler == nil then 19 error({ 62 message = "The route handler must not be nil", 2 pathname = pathname 96 }) end 355 if hasSplat and splatIndex ~= string.len(pathname) then 18 error({ 9 message = "The splat * must be the last segment of the path", 69 pathname = pathname 96 }) end 1958 for i = 1, lastIndex do 826 local segment = pathSegments[i] 1224 if (not isEmpty(segment)) then 489 if hasSplat and i == lastIndex then 89 if (hash.variablePaths) then 201 hash = hash.variablePaths else 46 local variablePaths = createRouteNode(hash, segment, true) 210 hash.variablePaths = variablePaths 58 hash = variablePaths end 40 if (not hash.isSplat) then 4 routeConflictError(pathname, hash) end 561 elseif string.sub(segment, 1, 1) == ":" then 351 segment = string.sub(segment, 2) 217 if (hash.variablePaths) then 54 hash = hash.variablePaths else 241 local variablePaths = createRouteNode(hash, segment) 231 hash.variablePaths = variablePaths 127 hash = variablePaths end 277 if hash.segment ~= segment or hash.isSplat then 52 routeConflictError(pathname, hash) end else 227 local nextHash = hash.staticPaths[segment] 398 if (nextHash == nil) then 362 nextHash = createRouteNode(hash, segment) 259 hash.staticPaths[segment] = nextHash end 210 hash = nextHash end end end 598 if hash.handler == nil then 561 hash.src = pathname 238 hash.handler = handler else 38 routeConflictError(pathname, hash) end end local function createHttpHash() 94 HttpHash = {} 68 HttpHash.get = getHttpHash 47 HttpHash.set = setHttpHash 27 HttpHash._hash = createRouteNode() 47 return HttpHash end 1 return createHttpHash; ============================================================================== Summary ============================================================================== File Hits Missed Coverage ------------------------------------ ./http-hash.lua 122 1 99.19% ------------------------------------ Total 122 1 99.19%