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.
-
#meta ⇒ Object
Returns the value of attribute meta.
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
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 |
# File 'lib/barrister.rb', line 579 def initialize(idl) @idl = idl @interfaces = { } @structs = { } @enums = { } @meta = { } 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 elsif type == "meta" item.keys.each do |key| if key != "type" @meta[key] = item[key] end end end end end |
Instance Attribute Details
#idl ⇒ Object
Returns the value of attribute idl.
573 574 575 |
# File 'lib/barrister.rb', line 573 def idl @idl end |
#meta ⇒ Object
Returns the value of attribute meta.
573 574 575 |
# File 'lib/barrister.rb', line 573 def @meta 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
817 818 819 820 821 822 823 824 825 826 827 828 829 830 |
# File 'lib/barrister.rb', line 817 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
605 606 607 |
# File 'lib/barrister.rb', line 605 def interface(name) return @interfaces[name] end |
#interfaces ⇒ Object
Returns all Interfaces defined on this Contract
610 611 612 |
# File 'lib/barrister.rb', line 610 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`
620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 |
# File 'lib/barrister.rb', line 620 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
833 834 835 836 |
# File 'lib/barrister.rb', line 833 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
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 799 800 801 802 803 804 805 806 807 808 809 810 811 812 |
# File 'lib/barrister.rb', line 700 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
648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 |
# File 'lib/barrister.rb', line 648 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
681 682 683 684 685 686 687 688 |
# File 'lib/barrister.rb', line 681 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 |