Module: JSI::Schema
- Included in:
- MetaSchemaNode::BootstrapSchema
- Defined in:
- lib/jsi/schema.rb,
lib/jsi/schema.rb,
lib/jsi/schema/cxt.rb,
lib/jsi/schema/issue.rb,
lib/jsi/schema/dialect.rb,
lib/jsi/schema/draft04.rb,
lib/jsi/schema/draft06.rb,
lib/jsi/schema/draft07.rb,
lib/jsi/schema/element.rb,
lib/jsi/schema/vocabulary.rb
Overview
JSI::Schema is a module which extends Base instances which represent JSON schemas.
This module is included on the JSI Schema module of any schema that describes other schemas, i.e. is a meta-schema (a MetaSchema). Therefore, any JSI instance described by a schema which is a MetaSchema is a schema and is extended by this module.
The content of an instance which is a JSI::Schema (referred to in this context as schema_content) is typically a Hash (JSON object) or a boolean.
Defined Under Namespace
Modules: Draft04, Draft06, Draft07, Draft202012, Elements, MetaSchema, SchemaAncestorNode Classes: Cxt, Dialect, DynamicAnchorMap, Element, Issue, NotAMetaSchemaError, NotASchemaError, Ref, Vocabulary
Constant Summary collapse
- ReferenceError =
Deprecated.
alias after v0.8
an exception raised when we are unable to resolve a schema reference
ResolutionError
Class Method Summary collapse
-
.ensure_metaschema(metaschema, name: nil, registry: JSI.registry) ⇒ Base + Schema + Schema::MetaSchema
private
Ensures the given param identifies a meta-schema and returns that meta-schema.
-
.ensure_schema(schema, reinstantiate_as: nil) ⇒ Schema
ensure the given object is a JSI Schema.
Instance Method Summary collapse
- #anchors ⇒ Enumerable<String>
-
#described_object_property_names ⇒ Set
any object property names this schema indicates may be present on its instances.
-
#describes_schema!(dialect = nil)
Indicates that this schema describes schemas, i.e.
-
#describes_schema? ⇒ Boolean
Does this schema itself describe a schema? I.e.
-
#dialect ⇒ Schema::Dialect
The dialect of this schema.
- #dialect_invoke_each(action_name, cxt_class = Cxt::Block, **cxt_param) { ... } ⇒ Object
-
#each_child_applicator_schema(token, instance) {|JSI::Schema| ... } ⇒ nil, Enumerator
yields each child applicator subschema (from properties, items, etc.) which applies to the child of the given instance on the given token.
- #each_immediate_subschema_ptr {|Ptr| ... } ⇒ Object
-
#each_inplace_applicator_schema(instance, visited_refs: Util::EMPTY_ARY) {|JSI::Schema| ... } ⇒ nil
Yields each in-place applicator schema which applies to the given instance.
-
#each_inplace_child_applicator_schema(token, instance, visited_refs: Util::EMPTY_ARY, collect_evaluated: false, collect_evaluated_validate: false) {|Schema| ... } ⇒ Boolean
For each in-place applicator schema that applies to the given instance, yields each child applicator of that schema that applies to the child of the instance on the given token.
-
#id ⇒ #to_str?
the string contents of an
$id/idkeyword, or nil. - #initialize ⇒ Object
-
#instance_valid!(instance) ⇒ nil
Asserts that the given instance is valid against this schema.
-
#instance_valid?(instance) ⇒ Boolean
whether the given instance is valid against this schema.
-
#instance_validate(instance) ⇒ JSI::Validation::Result::Full
Validates the given instance against this schema, returning a result with each validation error.
- #jsi_as_child_default_as_jsi ⇒ Object
- #jsi_each_descendent_schema {|Schema| ... } ⇒ Object
-
#jsi_each_descendent_schema_same_resource {|Schema| ... } ⇒ Object
yields each descendent of this node (including itself) within the same resource that is a Schema.
-
#jsi_is_resource_root? ⇒ Boolean
is this schema the root of a schema resource?.
-
#jsi_is_schema? ⇒ Boolean
Is this a JSI Schema?.
-
#jsi_schema_module ⇒ SchemaModule
The JSI Schema Module for this schema.
-
#jsi_schema_module_exec(*a, **kw, &block) ⇒ Object
Evaluates the given block in the context of this schema's JSI schema module.
- #jsi_schema_module_name ⇒ String?
- #jsi_schema_module_name_from_ancestor ⇒ String?
-
#jsi_subschema_resource_ancestors ⇒ Array<JSI::Schema>
private
schema resources which are ancestors of any subschemas below this schema.
-
#keyword?(keyword) ⇒ Boolean
does this schema contain the given keyword?.
-
#keyword_value?(keyword, value) ⇒ Boolean
Does this schema contain the given keyword with the given value?.
-
#new_jsi(instance, **kw) ⇒ Base
Instantiates a new JSI whose content comes from the given
instanceparam. -
#resource_root_subschema(ptr) ⇒ JSI::Schema
A schema in the same schema resource as this one (see SchemaAncestorNode#jsi_resource_root) at the given pointer relative to the root of the schema resource.
-
#schema_absolute_uri ⇒ URI?
deprecated
Deprecated.
after v0.8 - use
#jsi_resource_uri -
#schema_absolute_uris ⇒ Enumerable<URI>
deprecated
Deprecated.
after v0.8 - use
#jsi_resource_uris -
#schema_content ⇒ Object
the underlying JSON data used to instantiate this JSI::Schema.
- #schema_ref(ref = ) ⇒ Schema::Ref
-
#schema_resource_root ⇒ JSI::Base
deprecated
Deprecated.
after v0.8
-
#schema_resource_root? ⇒ Boolean
deprecated
Deprecated.
after v0.8
-
#schema_uri ⇒ URI?
a nonrelative URI which refers to this schema.
-
#schema_uris ⇒ Array<URI>
nonrelative URIs (that is, absolute, but possibly with a fragment) which refer to this schema.
-
#subschema(subptr) ⇒ JSI::Schema
a subschema of this Schema.
Class Method Details
.ensure_metaschema(metaschema, name: nil, registry: JSI.registry) ⇒ Base + Schema + Schema::MetaSchema
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Ensures the given param identifies a meta-schema and returns that meta-schema.
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 |
# File 'lib/jsi/schema.rb', line 342 def (, name: nil, registry: JSI.registry) if .respond_to?(:to_str) schema = Schema::Ref.new(, registry: registry).resolve if !schema.describes_schema? raise(NotAMetaSchemaError, [name, "URI indicates a schema that is not a meta-schema: #{.pretty_inspect.chomp}"].compact.join(" ")) end schema elsif .is_a?(SchemaModule::MetaSchemaModule) .schema elsif .is_a?(Schema::MetaSchema) else raise(NotAMetaSchemaError, "#{name || "param"} does not indicate a meta-schema: #{.pretty_inspect.chomp}") end end |
.ensure_schema(schema, reinstantiate_as: nil) ⇒ Schema
ensure the given object is a JSI Schema
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 |
# File 'lib/jsi/schema.rb', line 297 def ensure_schema(schema, reinstantiate_as: nil) if schema.is_a?(Schema) schema else if reinstantiate_as && schema.is_a?(JSI::Base) # TODO warn; behavior is undefined and I hate this implementation result_schema_indicated_schemas = SchemaSet.new(schema.jsi_indicated_schemas + reinstantiate_as) result_schema_applied_schemas = result_schema_indicated_schemas.each_yield_set do |is, y| is.each_inplace_applicator_schema(schema.jsi_node_content, &y) end result_schema_class = JSI::SchemaClasses.class_for_schemas(result_schema_applied_schemas, includes: SchemaClasses.includes_for(schema.jsi_node_content), mutable: schema.jsi_mutable?, ) result_schema_class.new( jsi_document: schema.jsi_document, jsi_ptr: schema.jsi_ptr, jsi_indicated_schemas: result_schema_indicated_schemas, jsi_base_uri: schema.jsi_base_uri, jsi_schema_resource_ancestors: schema.jsi_schema_resource_ancestors, jsi_schema_dynamic_anchor_map: schema.jsi_schema_dynamic_anchor_map, jsi_conf: schema.equal?(schema.jsi_root_node) ? schema.jsi_conf : nil, jsi_root_node: schema.equal?(schema.jsi_root_node) ? nil : schema.jsi_root_node, # bad ).send(:jsi_initialized) else msg = [] msg.concat([*(block_given? ? yield : "indicated object is not a schema:")]) msg << schema.pretty_inspect.chomp if schema.is_a?(Base) msg << "its schemas (which should include a Meta-Schema): #{schema.jsi_schemas.pretty_inspect.chomp}" end raise(NotASchemaError, msg.compact.join("\n")) end end end |
Instance Method Details
#anchors ⇒ Enumerable<String>
404 405 406 407 408 409 |
# File 'lib/jsi/schema.rb', line 404 def anchors anchors = Set[] anchors.merge(dialect_invoke_each(:anchor)) anchors.merge(dialect_invoke_each(:dynamicAnchor)) anchors.freeze end |
#described_object_property_names ⇒ Set
any object property names this schema indicates may be present on its instances. this includes any keys of this schema's "properties" object and any entries of this schema's array of "required" property keys.
802 803 804 |
# File 'lib/jsi/schema.rb', line 802 def described_object_property_names @described_object_property_names_map[schema_content: schema_content] end |
#describes_schema!(dialect = nil)
This method returns an undefined value.
Indicates that this schema describes schemas, i.e. it is a meta-schema. this schema is extended with MetaSchema and its #jsi_schema_module is extended with JSI::SchemaModule::MetaSchemaModule, and the JSI Schema Module will include JSI::Schema.
539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 |
# File 'lib/jsi/schema.rb', line 539 def describes_schema!(dialect = nil) # TODO rm bridge code hax dialect = dialect.first::DIALECT if dialect.is_a?(Array) && dialect.size == 1 if !dialect raise(ArgumentError, "no dialect given and no $vocabulary hash/object") if !schema_content['$vocabulary'].respond_to?(:to_hash) dialect = Schema::Dialect.from_xvocabulary(schema_content['$vocabulary'], registry: jsi_registry) end raise(TypeError) if !dialect.is_a?(Schema::Dialect) if jsi_schema_module <= Schema # this schema has already had describes_schema! called on it. # this is to be avoided, but is not particularly a problem. # it is a bug if it was called different times with different dialect, though. if @described_dialect != dialect raise(ArgumentError, "this schema already describes a schema with different dialect") end else jsi_schema_module.include(Schema) jsi_schema_module.send(:define_method, :dialect) { dialect } proc { || jsi_schema_module.send(:define_method, :metaschema) { } }[self] jsi_schema_module.extend(SchemaModule::MetaSchemaModule) end @described_dialect = dialect extend(Schema::MetaSchema) nil end |
#describes_schema? ⇒ Boolean
Does this schema itself describe a schema? I.e. is this schema a meta-schema?
522 523 524 |
# File 'lib/jsi/schema.rb', line 522 def describes_schema? is_a?(Schema::MetaSchema) end |
#dialect_invoke_each(action_name, cxt_class = Cxt::Block, **cxt_param) { ... } ⇒ Object
884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 |
# File 'lib/jsi/schema.rb', line 884 def dialect_invoke_each( action_name, cxt_class = Cxt::Block, **cxt_param, &block ) return(to_enum(__method__, action_name, cxt_class, **cxt_param)) unless block_given? cxt = cxt_class.new( schema: self, abort: false, block: block, **cxt_param, ) dialect.invoke(action_name, cxt) nil end |
#each_child_applicator_schema(token, instance) {|JSI::Schema| ... } ⇒ nil, Enumerator
yields each child applicator subschema (from properties, items, etc.) which applies to the child of the given instance on the given token.
718 719 720 721 722 723 724 725 726 727 728 |
# File 'lib/jsi/schema.rb', line 718 def each_child_applicator_schema(token, instance, &block) dialect_invoke_each(:child_applicate, Cxt::ChildApplication, instance: instance, token: token, collect_evaluated: false, collect_evaluated_validate: false, evaluated: false, &block ) end |
#each_immediate_subschema_ptr {|Ptr| ... } ⇒ Object
637 638 639 640 641 |
# File 'lib/jsi/schema.rb', line 637 def each_immediate_subschema_ptr return(to_enum(__method__)) unless block_given? dialect_invoke_each(:subschema) { |ptr| yield(Ptr.ary_ptr(ptr)) } end |
#each_inplace_applicator_schema(instance, visited_refs: Util::EMPTY_ARY) {|JSI::Schema| ... } ⇒ nil
Yields each in-place applicator schema which applies to the given instance.
689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 |
# File 'lib/jsi/schema.rb', line 689 def each_inplace_applicator_schema( instance, visited_refs: Util::EMPTY_ARY, &block ) each_immediate_inplace_applicator_schema( instance: instance, visited_refs: visited_refs, collect_evaluated: false, # child application is not invoked so no evaluated children to collect ) do |schema, ref: nil, applicate: true| if schema.equal?(self) && !ref yield(self) elsif applicate schema.each_inplace_applicator_schema( instance, visited_refs: Util.add_visited_ref(visited_refs, ref), &block ) end end end |
#each_inplace_child_applicator_schema(token, instance, visited_refs: Util::EMPTY_ARY, collect_evaluated: false, collect_evaluated_validate: false) {|Schema| ... } ⇒ Boolean
For each in-place applicator schema that applies to the given instance, yields each child applicator of that schema that applies to the child of the instance on the given token.
This method handles collection of whether the child was evaluated by any applicator
when that evaluation is needed by either this schema or the caller (per param collect_evaluated).
This is relevant to schemas containing unevaluatedProperties or unevaluatedItems.
746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 |
# File 'lib/jsi/schema.rb', line 746 def each_inplace_child_applicator_schema( token, instance, visited_refs: Util::EMPTY_ARY, collect_evaluated: false, collect_evaluated_validate: false, &block ) collect_evaluated ||= application_requires_evaluated inplace_child_evaluated = false applicate_self = false each_immediate_inplace_applicator_schema( instance: instance, visited_refs: visited_refs, collect_evaluated: collect_evaluated, ) do |schema, ref: nil, applicate: true| if schema.equal?(self) && !ref applicate_self = true elsif applicate || (collect_evaluated && !inplace_child_evaluated) schema_evaluated = schema.each_inplace_child_applicator_schema( token, instance, visited_refs: Util.add_visited_ref(visited_refs, ref), collect_evaluated: collect_evaluated && !inplace_child_evaluated, collect_evaluated_validate: collect_evaluated_validate, # the `if` keyword needs to yield to here because it does affect `evaluated`, # but it does not applicate itself/its applicators, so does not yield to the given block. &(applicate ? block : proc { }) ) inplace_child_evaluated ||= collect_evaluated && schema_evaluated && (!collect_evaluated_validate || schema.instance_valid?(instance)) end end if applicate_self child_application = dialect.invoke(:child_applicate, Cxt::ChildApplication.new( schema: self, abort: false, token: token, instance: instance, collect_evaluated: collect_evaluated, collect_evaluated_validate: collect_evaluated_validate, evaluated: inplace_child_evaluated, block: block, )) child_application.evaluated else inplace_child_evaluated end end |
#id ⇒ #to_str?
the string contents of an $id/id keyword, or nil
399 400 401 |
# File 'lib/jsi/schema.rb', line 399 def id dialect_invoke_each(:id).first end |
#initialize ⇒ Object
360 361 362 363 |
# File 'lib/jsi/schema.rb', line 360 def initialize(*) super jsi_schema_initialize end |
#instance_valid!(instance) ⇒ nil
Asserts that the given instance is valid against this schema. Error::Invalid is raised if it is not.
836 837 838 |
# File 'lib/jsi/schema.rb', line 836 def instance_valid!(instance) instance_validate(instance).valid! end |
#instance_valid?(instance) ⇒ Boolean
whether the given instance is valid against this schema
824 825 826 827 828 829 |
# File 'lib/jsi/schema.rb', line 824 def instance_valid?(instance) if instance.is_a?(SchemaAncestorNode) instance = instance.jsi_node_content end internal_validate_instance(Ptr[], instance, validate_only: true).valid? end |
#instance_validate(instance) ⇒ JSI::Validation::Result::Full
Validates the given instance against this schema, returning a result with each validation error.
810 811 812 813 814 815 816 817 818 819 |
# File 'lib/jsi/schema.rb', line 810 def instance_validate(instance) if instance.is_a?(SchemaAncestorNode) instance_ptr = instance.jsi_ptr instance_document = instance.jsi_document else instance_ptr = Ptr[] instance_document = instance end internal_validate_instance(instance_ptr, instance_document) end |
#jsi_as_child_default_as_jsi ⇒ Object
See Base#jsi_as_child_default_as_jsi. true for Schema, including boolean schemas.
877 878 879 |
# File 'lib/jsi/schema.rb', line 877 def jsi_as_child_default_as_jsi true end |
#jsi_each_descendent_schema {|Schema| ... } ⇒ Object
615 616 617 618 619 620 |
# File 'lib/jsi/schema.rb', line 615 def jsi_each_descendent_schema(&block) return(to_enum(__method__)) unless block_given? yield(self) dialect_invoke_each(:subschema) { |ptr| subschema(ptr).jsi_each_descendent_schema(&block) } end |
#jsi_each_descendent_schema_same_resource {|Schema| ... } ⇒ Object
yields each descendent of this node (including itself) within the same resource that is a Schema
624 625 626 627 628 629 630 631 632 633 634 |
# File 'lib/jsi/schema.rb', line 624 def jsi_each_descendent_schema_same_resource(&block) return(to_enum(__method__)) unless block_given? yield(self) dialect_invoke_each(:subschema) do |ptr| desc = subschema(ptr) if !desc.jsi_is_resource_root? desc.jsi_each_descendent_schema_same_resource(&block) end end end |
#jsi_is_resource_root? ⇒ Boolean
is this schema the root of a schema resource?
586 587 588 |
# File 'lib/jsi/schema.rb', line 586 def jsi_is_resource_root? super || jsi_resource_uris.any? end |
#jsi_is_schema? ⇒ Boolean
Is this a JSI Schema?
528 529 530 |
# File 'lib/jsi/schema.rb', line 528 def jsi_is_schema? true end |
#jsi_schema_module ⇒ SchemaModule
The JSI Schema Module for this schema. JSI instances described by this schema are instances of this module.
476 477 478 |
# File 'lib/jsi/schema.rb', line 476 def jsi_schema_module jsi_schema_module_connection end |
#jsi_schema_module_exec(*a, **kw, &block) ⇒ Object
Evaluates the given block in the context of this schema's JSI schema module. Any arguments passed to this method will be passed to the block. shortcut to invoke Module#module_exec on our #jsi_schema_module.
486 487 488 |
# File 'lib/jsi/schema.rb', line 486 def jsi_schema_module_exec(*a, **kw, &block) jsi_schema_module.module_exec(*a, **kw, &block) end |
#jsi_schema_module_name ⇒ String?
491 492 493 494 |
# File 'lib/jsi/schema.rb', line 491 def jsi_schema_module_name # don't hit #jsi_schema_module - avoid creating module, avoid erroring for MSN::BootstrapSchema @memos[:schema_module_connection] && @memos[:schema_module_connection].name end |
#jsi_schema_module_name_from_ancestor ⇒ String?
497 498 499 |
# File 'lib/jsi/schema.rb', line 497 def jsi_schema_module_name_from_ancestor is_a?(Base) ? jsi_schema_module.name_from_ancestor : nil end |
#jsi_subschema_resource_ancestors ⇒ Array<JSI::Schema>
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
schema resources which are ancestors of any subschemas below this schema. this may include this schema if this is a schema resource root.
907 908 909 910 911 912 913 |
# File 'lib/jsi/schema.rb', line 907 def jsi_subschema_resource_ancestors if jsi_is_resource_root? jsi_schema_resource_ancestors.dup.push(self).freeze else jsi_schema_resource_ancestors end end |
#keyword?(keyword) ⇒ Boolean
does this schema contain the given keyword?
386 387 388 389 |
# File 'lib/jsi/schema.rb', line 386 def keyword?(keyword) schema_content = jsi_node_content schema_content.respond_to?(:to_hash) && schema_content.key?(keyword) end |
#keyword_value?(keyword, value) ⇒ Boolean
Does this schema contain the given keyword with the given value?
393 394 395 |
# File 'lib/jsi/schema.rb', line 393 def keyword_value?(keyword, value) keyword?(keyword) && schema_content[keyword] == value end |
#new_jsi(instance, **kw) ⇒ Base
Instantiates a new JSI whose content comes from the given instance param.
This schema indicates the schemas of the JSI - its schemas are in-place
applicators of this schema which apply to the given instance.
All parameters are passed to JSI::SchemaSet#new_jsi.
509 510 511 512 |
# File 'lib/jsi/schema.rb', line 509 def new_jsi(instance, **kw) raise(BlockGivenError) if block_given? SchemaSet[self].new_jsi(instance, **kw) end |
#resource_root_subschema(ptr) ⇒ JSI::Schema
A schema in the same schema resource as this one (see JSI::Schema::SchemaAncestorNode#jsi_resource_root) at the given pointer relative to the root of the schema resource.
608 609 610 611 612 |
# File 'lib/jsi/schema.rb', line 608 def resource_root_subschema(ptr) Schema.ensure_schema(jsi_resource_root.jsi_descendent_node(ptr), reinstantiate_as: jsi_conf.reinstantiate_nonschemas && jsi_schemas.select(&:describes_schema?), ) end |
#schema_absolute_uri ⇒ URI?
after v0.8 - use #jsi_resource_uri
the URI of this schema, from an $id keyword, resolved against our #jsi_base_uri
414 415 416 |
# File 'lib/jsi/schema.rb', line 414 def schema_absolute_uri jsi_resource_uri end |
#schema_absolute_uris ⇒ Enumerable<URI>
after v0.8 - use #jsi_resource_uris
420 421 422 |
# File 'lib/jsi/schema.rb', line 420 def schema_absolute_uris jsi_resource_uris end |
#schema_content ⇒ Object
the underlying JSON data used to instantiate this JSI::Schema. this is an alias for Base#jsi_node_content, named for clarity in the context of working with a schema.
380 381 382 |
# File 'lib/jsi/schema.rb', line 380 def schema_content jsi_node_content end |
#schema_ref(ref = ) ⇒ Schema::Ref
516 517 518 |
# File 'lib/jsi/schema.rb', line 516 def schema_ref(ref = schema_content["$ref"]) @schema_ref_map[ref] end |
#schema_resource_root ⇒ JSI::Base
after v0.8
a resource containing this schema.
If any ancestor, or this schema itself, is a schema with an absolute uri (see #schema_absolute_uri), the resource root is the closest schema with an absolute uri.
If no ancestor schema has an absolute uri, the schema_resource_root is the document's root node. In this case, the resource root may or may not be a schema itself.
580 581 582 |
# File 'lib/jsi/schema.rb', line 580 def schema_resource_root jsi_resource_root end |
#schema_resource_root? ⇒ Boolean
after v0.8
591 592 593 |
# File 'lib/jsi/schema.rb', line 591 def schema_resource_root? jsi_is_resource_root? end |
#schema_uri ⇒ URI?
a nonrelative URI which refers to this schema.
nil if no ancestor of this schema defines an id.
see #schema_uris for all URIs known to refer to this schema.
440 441 442 |
# File 'lib/jsi/schema.rb', line 440 def schema_uri schema_uris.first end |
#schema_uris ⇒ Array<URI>
nonrelative URIs (that is, absolute, but possibly with a fragment) which refer to this schema
446 447 448 |
# File 'lib/jsi/schema.rb', line 446 def schema_uris @schema_uris_map[schema_content: schema_content] end |
#subschema(subptr) ⇒ JSI::Schema
a subschema of this Schema
599 600 601 |
# File 'lib/jsi/schema.rb', line 599 def subschema(subptr) Schema.ensure_schema(jsi_descendent_node(subptr)) { "subschema is not a schema at pointer: #{Ptr.ary_ptr(subptr).pointer}" } end |