SYS-REQ-115
(config Config, data []byte, setValue []byte, keys ...string)
| 1344 | |
| 1345 | // SYS-REQ-115 |
| 1346 | func setConfig(config Config, data []byte, setValue []byte, keys ...string) (value []byte, err error) { |
| 1347 | // ensure keys are set |
| 1348 | if len(keys) == 0 { |
| 1349 | return nil, KeyPathNotFoundError |
| 1350 | } |
| 1351 | |
| 1352 | _, _, startOffset, endOffset, err := internalGetConfig(config, data, keys...) |
| 1353 | if err != nil { |
| 1354 | if err != KeyPathNotFoundError { |
| 1355 | // problem parsing the data |
| 1356 | return nil, err |
| 1357 | } |
| 1358 | // full path doesnt exist |
| 1359 | // does any subpath exist? |
| 1360 | var depth int |
| 1361 | for i := range keys { |
| 1362 | _, _, start, end, sErr := internalGetConfig(config, data, keys[:i+1]...) |
| 1363 | if sErr != nil { |
| 1364 | break |
| 1365 | } else { |
| 1366 | endOffset = end |
| 1367 | startOffset = start |
| 1368 | depth++ |
| 1369 | } |
| 1370 | } |
| 1371 | comma := true |
| 1372 | object := false |
| 1373 | // KI-3: when the path's next component expects one container type but |
| 1374 | // the existing structure is the other (array-index [N] under an object, |
| 1375 | // or an object key under an array), auto-coerce the container to the |
| 1376 | // type expected by the path and proceed with fresh insertion. The |
| 1377 | // mismatched container is treated as if it needs to be (re)created, so |
| 1378 | // the output is always valid JSON. |
| 1379 | coerceTopLevel := false |
| 1380 | coerceStart := 0 |
| 1381 | topLevelArrayAppend := false |
| 1382 | topLevelArrayEmpty := false |
| 1383 | topLevelArrayStart := 0 |
| 1384 | topLevelArrayInsertOffset := 0 |
| 1385 | if endOffset == -1 { |
| 1386 | firstToken := nextTokenConfig(config, data) |
| 1387 | if firstToken < 0 { |
| 1388 | return nil, KeyPathNotFoundError |
| 1389 | } |
| 1390 | pathIsIndex := len(keys[0]) > 0 && keys[0][0] == '[' |
| 1391 | // An empty trailing key component is the degenerate "no path |
| 1392 | // provided" case (SYS-REQ-111), not a real object key — it must |
| 1393 | // keep returning KeyPathNotFoundError on a non-object root, so it |
| 1394 | // is excluded from auto-coerce. |
| 1395 | pathIsObjectKey := len(keys[0]) > 0 && !pathIsIndex |
| 1396 | dataIsObject := data[firstToken] == '{' |
| 1397 | dataIsArray := data[firstToken] == '[' |
| 1398 | if (pathIsIndex && dataIsObject) || (pathIsObjectKey && dataIsArray) { |
| 1399 | // SYS-REQ-009: cross-type Set at the top level — replace the |
| 1400 | // mismatched container with a fresh container of the type the |
| 1401 | // path expects, then perform a fresh insertion. |
| 1402 | coerceTopLevel = true |
| 1403 | coerceStart = firstToken |
no test coverage detected