Internal helper: removes JSONC comments and trailing commas.
(input: &str)
| 1025 | |
| 1026 | /// Internal helper: removes JSONC comments and trailing commas. |
| 1027 | fn strip_jsonc_comments(input: &str) -> String { |
| 1028 | let mut out = String::with_capacity(input.len()); |
| 1029 | let chars: Vec<char> = input.chars().collect(); |
| 1030 | let len = chars.len(); |
| 1031 | let mut i = 0; |
| 1032 | let mut in_string = false; |
| 1033 | |
| 1034 | while i < len { |
| 1035 | // Handle string literals (skip comment stripping inside strings). |
| 1036 | if in_string { |
| 1037 | if chars[i] == '\\' && i + 1 < len { |
| 1038 | out.push(chars[i]); |
| 1039 | out.push(chars[i + 1]); |
| 1040 | i += 2; |
| 1041 | continue; |
| 1042 | } |
| 1043 | if chars[i] == '"' { |
| 1044 | in_string = false; |
| 1045 | } |
| 1046 | out.push(chars[i]); |
| 1047 | i += 1; |
| 1048 | continue; |
| 1049 | } |
| 1050 | |
| 1051 | // Start of string. |
| 1052 | if chars[i] == '"' { |
| 1053 | in_string = true; |
| 1054 | out.push(chars[i]); |
| 1055 | i += 1; |
| 1056 | continue; |
| 1057 | } |
| 1058 | |
| 1059 | // Line comment `//`. |
| 1060 | if chars[i] == '/' && i + 1 < len && chars[i + 1] == '/' { |
| 1061 | // Skip until newline. |
| 1062 | while i < len && chars[i] != '\n' { |
| 1063 | i += 1; |
| 1064 | } |
| 1065 | continue; |
| 1066 | } |
| 1067 | |
| 1068 | // Block comment `/* ... */`. |
| 1069 | if chars[i] == '/' && i + 1 < len && chars[i + 1] == '*' { |
| 1070 | i += 2; |
| 1071 | while i + 1 < len && !(chars[i] == '*' && chars[i + 1] == '/') { |
| 1072 | i += 1; |
| 1073 | } |
| 1074 | i += 2; // consume `*/` |
| 1075 | continue; |
| 1076 | } |
| 1077 | |
| 1078 | out.push(chars[i]); |
| 1079 | i += 1; |
| 1080 | } |
| 1081 | |
| 1082 | // Remove trailing commas before `}` or `]`. |
| 1083 | // Simple regex-free approach: repeatedly collapse ", <whitespace> }" patterns. |
| 1084 | remove_trailing_commas(&out) |
no test coverage detected