Simplify module cleanup paths
This commit is contained in:
@@ -12,9 +12,9 @@ an opaque implementation detail. A plain name is likewise insufficient where
|
||||
multiple supplied records share that name.
|
||||
|
||||
The LLM boundary must preserve the typed artifact and durable-schema ownership
|
||||
of [ADR-0003](0003-strongly-typed-stage-interfaces.md) and the distinction
|
||||
of [ADR-0003](0003-typed-interfaces-with-two-zone-data-model.md) and the distinction
|
||||
between disambiguating references and source evidence in
|
||||
[ADR-0009](0009-prefer-minimal-evidence-grounded-extraction-artifacts.md).
|
||||
[ADR-0009](0009-minimal-evidence-grounded-extraction-artifacts.md).
|
||||
|
||||
## Decision
|
||||
|
||||
|
||||
@@ -21,11 +21,6 @@ type SourceRefResponse struct {
|
||||
EndUnitID UnitRef `json:"end_unit_id"`
|
||||
}
|
||||
|
||||
func UnitRefFromString(value string) UnitRef {
|
||||
parsed, _ := parseUnitRefNumber(value)
|
||||
return UnitRef{value: parsed}
|
||||
}
|
||||
|
||||
func UnitRefFromInt(value int) UnitRef {
|
||||
return UnitRef{
|
||||
value: value,
|
||||
|
||||
@@ -2,10 +2,7 @@ package units
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
|
||||
"gitea.maximumdirect.net/eric/notarius/internal/core/source"
|
||||
"gitea.maximumdirect.net/eric/notarius/internal/framework/contracts"
|
||||
@@ -158,67 +155,11 @@ func nonNegativeIntOption(name string, value any) (int, error) {
|
||||
}
|
||||
|
||||
func intOption(name string, value any) (int, error) {
|
||||
switch typed := value.(type) {
|
||||
case int:
|
||||
return typed, nil
|
||||
case int8:
|
||||
return int(typed), nil
|
||||
case int16:
|
||||
return int(typed), nil
|
||||
case int32:
|
||||
return int(typed), nil
|
||||
case int64:
|
||||
if typed > maxInt() || typed < minInt() {
|
||||
return 0, chunkerErrorf("%s is outside supported integer range", name)
|
||||
}
|
||||
return int(typed), nil
|
||||
case uint:
|
||||
if uint64(typed) > uint64(maxInt()) {
|
||||
return 0, chunkerErrorf("%s is outside supported integer range", name)
|
||||
}
|
||||
return int(typed), nil
|
||||
case uint8:
|
||||
return int(typed), nil
|
||||
case uint16:
|
||||
return int(typed), nil
|
||||
case uint32:
|
||||
if uint64(typed) > uint64(maxInt()) {
|
||||
return 0, chunkerErrorf("%s is outside supported integer range", name)
|
||||
}
|
||||
return int(typed), nil
|
||||
case uint64:
|
||||
if typed > uint64(maxInt()) {
|
||||
return 0, chunkerErrorf("%s is outside supported integer range", name)
|
||||
}
|
||||
return int(typed), nil
|
||||
case float64:
|
||||
if typed != math.Trunc(typed) {
|
||||
return 0, chunkerErrorf("%s must be an integer", name)
|
||||
}
|
||||
if typed > float64(maxInt()) || typed < float64(minInt()) {
|
||||
return 0, chunkerErrorf("%s is outside supported integer range", name)
|
||||
}
|
||||
return int(typed), nil
|
||||
case json.Number:
|
||||
parsed, err := typed.Int64()
|
||||
if err != nil {
|
||||
return 0, chunkerErrorf("%s must be an integer", name)
|
||||
}
|
||||
if parsed > maxInt() || parsed < minInt() {
|
||||
return 0, chunkerErrorf("%s is outside supported integer range", name)
|
||||
}
|
||||
return int(parsed), nil
|
||||
default:
|
||||
got, ok := value.(int)
|
||||
if !ok {
|
||||
return 0, chunkerErrorf("%s must be an integer", name)
|
||||
}
|
||||
}
|
||||
|
||||
func maxInt() int64 {
|
||||
return int64(1<<(strconv.IntSize-1) - 1)
|
||||
}
|
||||
|
||||
func minInt() int64 {
|
||||
return -maxInt() - 1
|
||||
return got, nil
|
||||
}
|
||||
|
||||
func chunkerErrorf(format string, args ...any) error {
|
||||
|
||||
@@ -121,6 +121,22 @@ func TestPlanRejectsInvalidOptions(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeOptionsRejectsNonNativeIntegers(t *testing.T) {
|
||||
for _, value := range []any{
|
||||
int8(2), int16(2), int32(2), int64(2),
|
||||
uint(2), uint8(2), uint16(2), uint32(2), uint64(2),
|
||||
float32(2), float64(2), json.Number("2"),
|
||||
} {
|
||||
_, err := DecodeOptions(map[string]any{"max_units": value})
|
||||
if err == nil {
|
||||
t.Fatalf("DecodeOptions(max_units: %T) error = nil, want error", value)
|
||||
}
|
||||
if !strings.Contains(err.Error(), "max_units must be an integer") {
|
||||
t.Fatalf("DecodeOptions(max_units: %T) error = %q, want integer type error", value, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlanRejectsEmptySource(t *testing.T) {
|
||||
doc := testSource(1)
|
||||
doc.Units = nil
|
||||
|
||||
@@ -494,38 +494,6 @@ func cloneWarnings(warnings []contracts.Warning) []contracts.Warning {
|
||||
return append([]contracts.Warning(nil), warnings...)
|
||||
}
|
||||
|
||||
func cloneMetadata(metadata map[string]any) map[string]any {
|
||||
if len(metadata) == 0 {
|
||||
return nil
|
||||
}
|
||||
out := make(map[string]any, len(metadata))
|
||||
for key, value := range metadata {
|
||||
out[key] = cloneJSONMetadataValue(value)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func cloneJSONMetadataValue(value any) any {
|
||||
switch typed := value.(type) {
|
||||
case map[string]any:
|
||||
return cloneMetadata(typed)
|
||||
case []any:
|
||||
out := make([]any, len(typed))
|
||||
for i := range typed {
|
||||
out[i] = cloneJSONMetadataValue(typed[i])
|
||||
}
|
||||
return out
|
||||
case stdjson.RawMessage:
|
||||
return append(stdjson.RawMessage(nil), typed...)
|
||||
case []byte:
|
||||
return append([]byte(nil), typed...)
|
||||
case []string:
|
||||
return append([]string(nil), typed...)
|
||||
default:
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
func encoderErrorf(format string, args ...any) error {
|
||||
return fmt.Errorf("json output encoder: "+format, args...)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user