schema_ext.go (1252B)
1 package smithy 2 3 import ( 4 "sync/atomic" 5 "unsafe" 6 ) 7 8 // ExtensionID identifies a schema extension slot. Each codec family 9 // (JSON, CBOR, etc.) uses a distinct slot to cache precomputed data. 10 type ExtensionID int 11 12 const numExtensionSlots = 5 13 14 const ( 15 ExtJSON ExtensionID = iota // transport/http/protocol/internal/json 16 ExtCBOR // transport/http/protocol/internal/cbor 17 ExtXML // transport/http/protocol/internal/xml 18 ExtQuery // transport/http/protocol/internal/query 19 ExtHTTPBinding // transport/http/protocol/internal/httpbinding 20 ) 21 22 // SchemaExtension retrieves or lazily computes the extension for the given 23 // slot. build is called on first access for a schema and the result is cached. 24 // The build function must return a pointer to an immutable value. 25 func SchemaExtension[T any](s *Schema, id ExtensionID, build func(*Schema) *T) *T { 26 p := atomic.LoadPointer(&s.ext[id]) 27 if p != nil { 28 return (*T)(p) 29 } 30 return computeSchemaExtension(s, id, build) 31 } 32 33 //go:noinline 34 func computeSchemaExtension[T any](s *Schema, id ExtensionID, build func(*Schema) *T) *T { 35 v := build(s) 36 atomic.StorePointer(&s.ext[id], unsafe.Pointer(v)) 37 return v 38 }