module T::Props::Utils

def self.deep_clone_object(what, freeze: false)

types and Hashes and Arrays.
Deep copy an object. The object must consist of Ruby primitive
def self.deep_clone_object(what, freeze: false)
  result = case what
  when true
    true
  when false
    false
  when Symbol, NilClass, Numeric
    what
  when Array
    what.map {|v| deep_clone_object(v, freeze: freeze)}
  when Hash
    h = what.class.new
    what.each do |k, v|
      k.freeze if freeze
      h[k] = deep_clone_object(v, freeze: freeze)
    end
    h
  when Regexp
    what.dup
  when T::Enum
    what
  else
    what.clone
  end
  freeze ? result.freeze : result
end

def self.merge_serialized_optional_rule(prop_rules)

def self.merge_serialized_optional_rule(prop_rules)
  {'_tnilable' => true}.merge(prop_rules.merge('_tnilable' => true))
end

def self.need_nil_read_check?(prop_rules)

This is mostly for the compatibility check that we allow existing documents carry some nil prop/field.
The prop_rules indicate whether we should check for reading a nil value for the prop/field.
def self.need_nil_read_check?(prop_rules)
  # . :on_load allows nil read, but we need to check for the read for future writes
  prop_rules[:optional] == :on_load || prop_rules[:raise_on_nil_write]
end

def self.need_nil_write_check?(prop_rules)

The prop_rules indicate whether we should check for writing a nil value for the prop/field.
def self.need_nil_write_check?(prop_rules)
  need_nil_read_check?(prop_rules) || T::Props::Utils.required_prop?(prop_rules)
end

def self.optional_prop?(prop_rules)

def self.optional_prop?(prop_rules)
  # Clients should never reference :_tnilable as the implementation can change.
  !!prop_rules[:_tnilable]
end

def self.required_prop?(prop_rules)

def self.required_prop?(prop_rules)
  # Clients should never reference :_tnilable as the implementation can change.
  !prop_rules[:_tnilable]
end