AZ_NODISCARD AZ_INLINE bool _az_span_is_valid()

in sdk/inc/azure/core/internal/az_precondition_internal.h [85:129]


AZ_NODISCARD AZ_INLINE bool _az_span_is_valid(az_span span, int32_t min_size, bool null_is_valid)
{
  if (min_size < 0)
  {
    return false;
  }

  uint8_t* const ptr = az_span_ptr(span);
  int32_t const span_size = az_span_size(span);

  bool result = false;

  /* Span is valid if:
     The size is greater than or equal to a user defined minimum value AND one of the
     following:
        - If null_is_valid is true and the pointer in the span is null, the size must also be 0.
        - In the case of the pointer not being NULL, the size is greater than or equal to zero.
  */

  // On some platforms, in some compilation configurations (Debug), NULL is not 0x0...0. But if you
  // initialize a span with { 0 } (or if that span is a part of a structure that is initialized with
  // { 0 }) the ptr is not going to be equal to NULL, however the intent of the precondition is to
  // disallow default-initialized and null ptrs, so we should treat them the same.
  uint8_t* const default_init_ptr = az_span_ptr((az_span){ 0 });
  if (null_is_valid)
  {
    result = (ptr == NULL || ptr == default_init_ptr) ? span_size == 0 : span_size >= 0;
  }
  else
  {
    result = (ptr != NULL && ptr != default_init_ptr) && span_size >= 0;
  }

  // Can't wrap over the end of the address space.
  // The biggest theoretical pointer value is "(void*)~0" (0xFFFF...), which is the end of address
  // space. We don't attempt to read/write beyond the end of the address space - it is unlikely a
  // desired behavior, and it is not defined. So, if the span size is greater than the addresses
  // left until the theoretical end of the address space, it is not a valid span.
  // Example: (az_span) { .ptr = (uint8_t*)(~0 - 5), .size = 10 } is not a valid span, because most
  // likely you end up pointing to 0x0000 at .ptr[6], &.ptr[7] is 0x...0001, etc.
  uint8_t* const max_ptr = (uint8_t*)~(uint8_t)0;
  result = result && ((size_t)span_size <= (size_t)(max_ptr - ptr));

  return result && min_size <= span_size;
}