class Barrister::Contract
Represents a single parsed IDL definition
Attributes
Public Class Methods
‘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
# 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
Public Instance Methods
Recursively resolves all fields for the struct and its ancestors
Returns an Array with all the fields
# 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
Returns the Interface
instance for the given name
# File lib/barrister.rb, line 605 def interface(name) return @interfaces[name] end
Returns all Interfaces defined on this Contract
# File lib/barrister.rb, line 610 def interfaces return @interfaces.values end
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`
# 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
Helper function that returns a formatted string for a type mismatch error
# 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
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
# 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
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
# 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
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
# 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