Direct immutable Ion value validation against Smithy shapes
///|
test {
let loaded = @smithy.Loader::new()
.add_idl(
"model.smithy", "$version: \"2\"\nnamespace example\nstructure Input { @required name: String }",
)
.assemble()
let prepared = @adapter.PreparedValidator::prepare(
loaded.model.unwrap(),
@smithy.ShapeId::parse("example#Input").unwrap(),
)
let value = @ion.Ion::from_fields([
@ion.Field("name", @ion.Ion::string("Ada")),
])
assert_true(prepared.validate(value).is_valid())
}///|
test "validate an Ion reading" {
let model = @smithy.Loader::new()
.add_idl(
"reading.smithy",
(
#|$version: "2"
#|namespace example
#|
#|structure Reading {
#| @required
#| sensor: String
#|
#| @required
#| @range(min: -50, max: 60)
#| celsius: Integer
#|
#| @required
#| takenAt: Timestamp
#|}
),
)
.assemble().model.unwrap()
let prepared = @adapter.PreparedValidator::prepare(
model,
@smithy.ShapeId::parse("example#Reading").unwrap(),
)
let reading = @text.read_ion(
"{sensor: \"roof\", celsius: 21, takenAt: 2026-10-24T09:30:00Z}",
)
assert_true(prepared.validate(reading).is_valid())
let text_time = @text.read_ion(
"{sensor: \"roof\", celsius: 21, takenAt: \"2026-10-24T09:30:00Z\"}",
)
let result = prepared.validate(text_time)
assert_false(result.is_valid())
assert_eq(result.findings.length(), 1)
let finding = result.findings[0]
assert_eq(finding.code.to_string(), "TypeMismatch")
assert_eq(finding.path.pointer(), "/takenAt")
assert_eq(finding.shape.to_string(), "example#Reading$takenAt")
assert_eq(finding.native_kind, Some(@ion.IonType::String))
}| Ion value | Smithy mapping |
|---|---|
| bool, string | Boolean, String and matching string enums; normal constraints apply |
| int | Exact numeric token; numeric targets apply their bounds and range |
| decimal | BigDecimal, Float or Double; coefficient, exponent and signed zero stay exact |
| float | Float or Double; exact binary numeric magnitude and range checks |
| timestamp | Timestamp with valid calendar, seconds precision and known offset |
| blob | Blob with byte length constraints |
| list, struct | List, structure, map, union or Document as appropriate |
| null and typed null | Document or sparse collection positions; never an absent member |
| symbol, clob, sexp | UnsupportedValue |
| annotated value | UnsupportedValue, with descendants still inspected at their original paths |
pub(all) struct Finding {
code : FindingCode
severity : FindingSeverity
path : InstancePath
shape : ShapeId
message : String
native_kind : IonType?
} derive(Eq, Debug)pub struct PreparedValidator {
// private fields
}fn PreparedValidator::prepare(model : Model, shape : ShapeId, config? : Config) -> PreparedValidator raise PreparationErrorimpl ToJson for ValidationResult