Class: Barrister::Contract
- Inherits:
-
Object
- Object
- Barrister::Contract
- Includes:
- Barrister
- Defined in:
- lib/barrister.rb
Overview
Represents a single parsed IDL definition
Instance Attribute Summary collapse
-
#idl ⇒ Object
Returns the value of attribute idl.
Instance Method Summary collapse
-
#all_struct_fields(arr, struct) ⇒ Object
Recursively resolves all fields for the struct and its ancestors.
-
#initialize(idl) ⇒ Contract
constructor
‘idl` must be an Array loaded from a Barrister IDL JSON file.
-
#interface(name) ⇒ Object
Returns the Interface instance for the given name.
-
#interfaces ⇒ Object
Returns all Interfaces defined on this Contract.
-
#resolve_method(req) ⇒ Object
Takes a JSON-RPC request hash, and returns a 3 element tuple.
-
#type_err(name, exp_type, val) ⇒ Object
Helper function that returns a formatted string for a type mismatch error.
-
#validate(name, expected, expect_array, val) ⇒ Object
Validates the type for a single value.
-
#validate_params(req, func) ⇒ Object
Validates that the parameters on the JSON-RPC request match the types specified for this function.
-
#validate_result(req, result, func) ⇒ Object
Validates that the result from a handler method invocation match the return type for this function.
Methods included from Barrister
contract_from_file, #err_resp, #ok_resp, parse_method, rand_str
Constructor Details
#initialize(idl) ⇒ Contract
‘idl` must be an Array loaded from a Barrister IDL JSON file
‘initialize` iterates through the IDL and stores the interfaces, structs, and enums specified in the IDL
572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 |
# File 'lib/barrister.rb', line 572 def initialize(idl) @idl = idl @interfaces = { } @structs = { } @enums = { } idl.each do |item| type = item["type"] if type == "interface" @interfaces[item["name"]] = Interface.new(item) elsif type == "struct" @structs[item["name"]] = item elsif type == "enum" @enums[item["name"]] = item end end end |
Instance Attribute Details
#idl ⇒ Object
Returns the value of attribute idl.
566 567 568 |
# File 'lib/barrister.rb', line 566 def idl @idl end |
Instance Method Details
#all_struct_fields(arr, struct) ⇒ Object
Recursively resolves all fields for the struct and its ancestors
Returns an Array with all the fields
803 804 805 806 807 808 809 810 811 812 813 814 815 816 |
# File 'lib/barrister.rb', line 803 def all_struct_fields(arr, struct) struct["fields"].each do |f| arr << f end if struct["extends"] parent = @structs[struct["extends"]] if parent return all_struct_fields(arr, parent) end end return arr end |
#interface(name) ⇒ Object
Returns the Interface instance for the given name
591 592 593 |
# File 'lib/barrister.rb', line 591 def interface(name) return @interfaces[name] end |
#interfaces ⇒ Object
Returns all Interfaces defined on this Contract
596 597 598 |
# File 'lib/barrister.rb', line 596 def interfaces return @interfaces.values end |
#resolve_method(req) ⇒ Object
Takes a JSON-RPC request hash, and returns a 3 element tuple. This is called as part of the request validation sequence.
‘0` - JSON-RPC response hash representing an error. nil if valid. `1` - Interface instance on this Contract that matches `req` `2` - Function instance on the Interface that matches `req`
606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 |
# File 'lib/barrister.rb', line 606 def resolve_method(req) method = req["method"] iface_name, func_name = Barrister::parse_method(method) if iface_name == nil return err_resp(req, -32601, "Method not found: #{method}") end iface = interface(iface_name) if !iface return err_resp(req, -32601, "Interface not found on IDL: #{iface_name}") end func = iface.function(func_name) if !func return err_resp(req, -32601, "Function #{func_name} does not exist on interface #{iface_name}") end return nil, iface, func end |
#type_err(name, exp_type, val) ⇒ Object
Helper function that returns a formatted string for a type mismatch error
819 820 821 822 |
# File 'lib/barrister.rb', line 819 def type_err(name, exp_type, val) actual = val.class.name return "#{name} expects type '#{exp_type}' but got type '#{actual}'" end |
#validate(name, expected, expect_array, val) ⇒ Object
Validates the type for a single value. This method is recursive when validating arrays or structs.
Returns a string describing the validation error if invalid, or nil if valid
-
‘name` - string to prefix onto the validation error
-
‘expected` - expected type (hash)
-
‘expect_array` - if true, we expect val to be an Array
-
‘val` - value to validate
686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 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 797 798 |
# File 'lib/barrister.rb', line 686 def validate(name, expected, expect_array, val) # If val is nil, then check if the IDL allows this type to be optional if val == nil if expected["optional"] return nil else return "#{name} cannot be null" end else exp_type = expected["type"] # If we expect an array, make sure that val is an Array, and then # recursively validate the elements in the array if expect_array if val.kind_of?(Array) stop = val.length - 1 for i in (0..stop) invalid = validate("#{name}[#{i}]", expected, false, val[i]) if invalid != nil return invalid end end return nil else return type_err(name, "[]"+expected["type"], val) end # Check the built in Barrister primitive types elsif exp_type == "string" if val.class == String return nil else return type_err(name, exp_type, val) end elsif exp_type == "bool" if val.class == TrueClass || val.class == FalseClass return nil else return type_err(name, exp_type, val) end elsif exp_type == "int" || exp_type == "float" if val.class == Integer || val.class == Fixnum || val.class == Bignum return nil elsif val.class == Float && exp_type == "float" return nil else return type_err(name, exp_type, val) end # Expected type is not an array or a Barrister primitive. # It must be a struct or an enum. else # Try to find a struct struct = @structs[exp_type] if struct if !val.kind_of?(Hash) return "#{name} #{exp_type} value must be a map/hash. not: " + val.class.name end s_field_keys = { } # Resolve all fields on the struct and its ancestors s_fields = all_struct_fields([], struct) # Validate that each field on the struct has a valid value s_fields.each do |f| fname = f["name"] invalid = validate("#{name}.#{fname}", f, f["is_array"], val[fname]) if invalid != nil return invalid end s_field_keys[fname] = 1 end # Validate that there are no extraneous elements on the value val.keys.each do |k| if !s_field_keys.key?(k) return "#{name}.#{k} is not a field in struct '#{exp_type}'" end end # Struct is valid return nil end # Try to find an enum enum = @enums[exp_type] if enum if val.class != String return "#{name} enum value must be a string. got: " + val.class.name end # Try to find an enum value that matches this val enum["values"].each do |en| if en["value"] == val return nil end end # Invalid return "#{name} #{val} is not a value in enum '#{exp_type}'" end # Unlikely branch - suggests the IDL is internally inconsistent return "#{name} unknown type: #{exp_type}" end # Panic if we have a branch unaccounted for. Indicates a Barrister bug. raise "Barrister ERROR: validate did not return for: #{name} #{expected}" end end |
#validate_params(req, func) ⇒ Object
Validates that the parameters on the JSON-RPC request match the types specified for this function
Returns a JSON-RPC response hash if invalid, or nil if valid.
-
‘req` - JSON-RPC request hash
-
‘func` - Barrister::Function instance
634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 |
# File 'lib/barrister.rb', line 634 def validate_params(req, func) params = req["params"] if !params params = [] end e_params = func.params.length r_params = params.length if e_params != r_params msg = "Function #{func.name}: Param length #{r_params} != expected length: #{e_params}" return err_resp(req, -32602, msg) end for i in (0..(e_params-1)) expected = func.params[i] invalid = validate("Param[#{i}]", expected, expected["is_array"], params[i]) if invalid != nil return err_resp(req, -32602, invalid) end end # valid return nil end |
#validate_result(req, result, func) ⇒ Object
Validates that the result from a handler method invocation match the return type for this function
Returns a JSON-RPC response hash if invalid, or nil if valid.
-
‘req` - JSON-RPC request hash
-
‘result` - Result object from the handler method call
-
‘func` - Barrister::Function instance
667 668 669 670 671 672 673 674 |
# File 'lib/barrister.rb', line 667 def validate_result(req, result, func) invalid = validate("", func.returns, func.returns["is_array"], result) if invalid == nil return nil else return err_resp(req, -32001, invalid) end end |