class T::Props::Decorator

def prop_get(instance, prop, rules=props[prop.to_sym])

def prop_get(instance, prop, rules=props[prop.to_sym])
  val = get(instance, prop, rules)
  # NB: Do NOT change this to check `val.nil?` instead. BSON::ByteBuffer overrides `==` such
  # that `== nil` can return true while `.nil?` returns false. Tests will break in mysterious
  # ways. A special thanks to Ruby for enabling this type of bug.
  #
  # One side effect here is that _if_ a class (like BSON::ByteBuffer) defines ==
  # in such a way that instances which are not `nil`, ie are not NilClass, nevertheless
  # are `== nil`, then we will transparently convert such instances to `nil` on read.
  # Yes, our code relies on this behavior (as of writing). :thisisfine:
  if val != nil # rubocop:disable Style/NonNilCheck
    val
  else
    raise NoRulesError.new if !rules
    d = rules[:ifunset]
    if d
      T::Props::Utils.deep_clone_object(d)
    else
      nil
    end
  end
end