hyf

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

fixture_loader.mojo (5402B)


      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(
     96     path: Path, key: String
     97 ) raises -> Value:
     98     var raw = path.read_text()
     99     var data = raw.as_bytes()
    100     var index = _skip_whitespace(raw, 0)
    101     if index >= len(data) or data[index] != UInt8(ord("{")):
    102         raise Error("fixture scenario must be a top-level JSON object")
    103 
    104     index += 1
    105     while index < len(data):
    106         index = _skip_whitespace(raw, index)
    107         if index >= len(data):
    108             break
    109 
    110         if data[index] == UInt8(ord("}")):
    111             break
    112 
    113         if data[index] != UInt8(ord('"')):
    114             raise Error("fixture scenario object key must be a JSON string")
    115 
    116         var key_json = _extract_json_value(raw, index)
    117         var parsed_key = loads(key_json)
    118         if not parsed_key.is_string():
    119             raise Error("fixture scenario object key did not parse as a string")
    120 
    121         index += key_json.byte_length()
    122         index = _skip_whitespace(raw, index)
    123         if index >= len(data) or data[index] != UInt8(ord(":")):
    124             raise Error(
    125                 "fixture scenario field '"
    126                 + parsed_key.string_value()
    127                 + "' missing colon"
    128             )
    129 
    130         var value_start = _skip_whitespace(raw, index + 1)
    131         var value_json = _extract_json_value(raw, value_start)
    132         if parsed_key.string_value() == key:
    133             return loads(value_json)
    134 
    135         index = value_start + value_json.byte_length()
    136         index = _skip_whitespace(raw, index)
    137         if index >= len(data):
    138             break
    139         if data[index] == UInt8(ord(",")):
    140             index += 1
    141             continue
    142         if data[index] == UInt8(ord("}")):
    143             break
    144         raise Error(
    145             "fixture scenario field '"
    146             + parsed_key.string_value()
    147             + "' missing delimiter"
    148         )
    149 
    150     raise Error("fixture scenario missing field '" + key + "'")
    151 
    152 
    153 def load_fixture_manifest() raises -> Value:
    154     return load_fixture_json_file(fixture_manifest_path())
    155 
    156 
    157 def load_fixture_scenario(relative_path: String) raises -> Value:
    158     return load_fixture_json_file(fixture_root_path() / String(relative_path))
    159 
    160 
    161 def load_fixture_scenario_request(relative_path: String) raises -> Value:
    162     return load_fixture_top_level_field_from_path(
    163         fixture_root_path() / String(relative_path), "request"
    164     )
    165 
    166 
    167 def load_fixture_scenario_expected(relative_path: String) raises -> Value:
    168     return load_fixture_top_level_field_from_path(
    169         fixture_root_path() / String(relative_path), "expected"
    170     )