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
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 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