hyf

Context-aware query service for Radroots
git clone https://radroots.dev/git/hyf.git
Log | Files | Refs | README | LICENSE

fixture_loader.mojo (5364B)


      1 from std.pathlib import Path, _dir_of_current_file
      2 
      3 from json import Value, loads
      4 
      5 
      6 def fixture_root_path() raises -> Path:
      7     return _dir_of_current_file() / "fixtures" / "v1"
      8 
      9 
     10 def fixture_manifest_path() raises -> Path:
     11     return fixture_root_path() / "manifest.json"
     12 
     13 
     14 def load_fixture_json_file(path: Path) raises -> Value:
     15     return loads(path.read_text())
     16 
     17 
     18 def _skip_whitespace(raw: String, start_index: Int) -> Int:
     19     var data = raw.as_bytes()
     20     var index = start_index
     21     while index < len(data):
     22         var byte = data[index]
     23         if (
     24             byte == UInt8(ord(" "))
     25             or byte == UInt8(ord("\n"))
     26             or byte == UInt8(ord("\t"))
     27             or byte == UInt8(ord("\r"))
     28         ):
     29             index += 1
     30             continue
     31         break
     32     return index
     33 
     34 
     35 def _extract_json_value(raw: String, start_index: Int) raises -> String:
     36     var data = raw.as_bytes()
     37     if start_index >= len(data):
     38         raise Error("fixture field value start out of bounds")
     39 
     40     var first = data[start_index]
     41     if first == UInt8(ord("{")) or first == UInt8(ord("[")):
     42         var depth = 0
     43         var in_string = False
     44         var escaped = False
     45         var index = start_index
     46         while index < len(data):
     47             var byte = data[index]
     48             if escaped:
     49                 escaped = False
     50             elif in_string:
     51                 if byte == UInt8(ord("\\")):
     52                     escaped = True
     53                 elif byte == UInt8(ord('"')):
     54                     in_string = False
     55             else:
     56                 if byte == UInt8(ord('"')):
     57                     in_string = True
     58                 elif byte == UInt8(ord("{")) or byte == UInt8(ord("[")):
     59                     depth += 1
     60                 elif byte == UInt8(ord("}")) or byte == UInt8(ord("]")):
     61                     depth -= 1
     62                     if depth == 0:
     63                         return String(raw[byte=start_index : index + 1])
     64             index += 1
     65         raise Error("unterminated fixture object or array field")
     66 
     67     if first == UInt8(ord('"')):
     68         var escaped = False
     69         var index = start_index + 1
     70         while index < len(data):
     71             var byte = data[index]
     72             if escaped:
     73                 escaped = False
     74             elif byte == UInt8(ord("\\")):
     75                 escaped = True
     76             elif byte == UInt8(ord('"')):
     77                 return String(raw[byte=start_index : index + 1])
     78             index += 1
     79         raise Error("unterminated fixture string field")
     80 
     81     var index = start_index
     82     while index < len(data):
     83         var byte = data[index]
     84         if (
     85             byte == UInt8(ord(","))
     86             or byte == UInt8(ord("}"))
     87             or byte == UInt8(ord("]"))
     88         ):
     89             return String(raw[byte=start_index:index])
     90         index += 1
     91 
     92     return String(raw[byte=start_index:])
     93 
     94 
     95 def load_fixture_top_level_field_from_path(path: Path, key: String) raises -> Value:
     96     var raw = path.read_text()
     97     var data = raw.as_bytes()
     98     var index = _skip_whitespace(raw, 0)
     99     if index >= len(data) or data[index] != UInt8(ord("{")):
    100         raise Error("fixture scenario must be a top-level JSON object")
    101 
    102     index += 1
    103     while index < len(data):
    104         index = _skip_whitespace(raw, index)
    105         if index >= len(data):
    106             break
    107 
    108         if data[index] == UInt8(ord("}")):
    109             break
    110 
    111         if data[index] != UInt8(ord('"')):
    112             raise Error("fixture scenario object key must be a JSON string")
    113 
    114         var key_json = _extract_json_value(raw, index)
    115         var parsed_key = loads(key_json)
    116         if not parsed_key.is_string():
    117             raise Error("fixture scenario object key did not parse as a string")
    118 
    119         index += key_json.byte_length()
    120         index = _skip_whitespace(raw, index)
    121         if index >= len(data) or data[index] != UInt8(ord(":")):
    122             raise Error(
    123                 "fixture scenario field '" + parsed_key.string_value()
    124                 + "' missing colon"
    125             )
    126 
    127         var value_start = _skip_whitespace(raw, index + 1)
    128         var value_json = _extract_json_value(raw, value_start)
    129         if parsed_key.string_value() == key:
    130             return loads(value_json)
    131 
    132         index = value_start + value_json.byte_length()
    133         index = _skip_whitespace(raw, index)
    134         if index >= len(data):
    135             break
    136         if data[index] == UInt8(ord(",")):
    137             index += 1
    138             continue
    139         if data[index] == UInt8(ord("}")):
    140             break
    141         raise Error(
    142             "fixture scenario field '" + parsed_key.string_value()
    143             + "' missing delimiter"
    144         )
    145 
    146     raise Error("fixture scenario missing field '" + key + "'")
    147 
    148 
    149 def load_fixture_manifest() raises -> Value:
    150     return load_fixture_json_file(fixture_manifest_path())
    151 
    152 
    153 def load_fixture_scenario(relative_path: String) raises -> Value:
    154     return load_fixture_json_file(fixture_root_path() / String(relative_path))
    155 
    156 
    157 def load_fixture_scenario_request(relative_path: String) raises -> Value:
    158     return load_fixture_top_level_field_from_path(
    159         fixture_root_path() / String(relative_path), "request"
    160     )
    161 
    162 
    163 def load_fixture_scenario_expected(relative_path: String) raises -> Value:
    164     return load_fixture_top_level_field_from_path(
    165         fixture_root_path() / String(relative_path), "expected"
    166     )