CONSTBUFFER_FROM_BUFFER_RESULT CONSTBUFFER_from_buffer()

in src/constbuffer.c [590:667]


CONSTBUFFER_FROM_BUFFER_RESULT CONSTBUFFER_from_buffer(const unsigned char* source, uint32_t size, uint32_t* consumed, CONSTBUFFER_HANDLE* destination)
{
    CONSTBUFFER_FROM_BUFFER_RESULT result;
    if (
        /*Codes_SRS_CONSTBUFFER_02_063: [ If source is NULL then CONSTBUFFER_from_buffer shall fail and return CONSTBUFFER_FROM_BUFFER_RESULT_INVALID_ARG. ]*/
        (source == NULL) ||
        /*Codes_SRS_CONSTBUFFER_02_064: [ If consumed is NULL then CONSTBUFFER_from_buffer shall fail and return CONSTBUFFER_FROM_BUFFER_RESULT_INVALID_ARG. ]*/
        (consumed == NULL) ||
        /*Codes_SRS_CONSTBUFFER_02_065: [ If destination is NULL then CONSTBUFFER_from_buffer shall fail and return CONSTBUFFER_FROM_BUFFER_RESULT_INVALID_ARG. ]*/
        (destination == NULL)
        )
    {
        LogError("invalid arguments const unsigned char* source=%p, uint32_t size=%" PRIu32 ", uint32_t* consumed=%p, CONSTBUFFER_HANDLE* destination=%p", 
            source, size, consumed, destination);
        result = CONSTBUFFER_FROM_BUFFER_RESULT_INVALID_ARG;
    }
    else
    {
        if (size == 0)
        {
            /*Codes_SRS_CONSTBUFFER_02_066: [ If size is 0 then CONSTBUFFER_from_buffer shall fail and return CONSTBUFFER_FROM_BUFFER_RESULT_INVALID_ARG. ]*/
            LogError("cannot deserialize from size=%" PRIu32 "", size);
            result = CONSTBUFFER_FROM_BUFFER_RESULT_INVALID_ARG;
        }
        else
        {
            uint8_t version;
            read_uint8_t(source + CONSTBUFFER_VERSION_OFFSET, &version);
            if (version != CONSTBUFFER_VERSION_V1)
            {
                /*Codes_SRS_CONSTBUFFER_02_067: [ If source byte at offset 0 is not 1 (current version) then CONSTBUFFER_from_buffer shall fail and return CONSTBUFFER_FROM_BUFFER_RESULT_INVALID_DATA. ]*/
                LogError("different version (%" PRIu8 ") detected. This module only knows about version %" PRIu8 "", version, CONSTBUFFER_VERSION_V1);
                result = CONSTBUFFER_FROM_BUFFER_RESULT_INVALID_DATA;
            }
            else
            {
                /*Codes_SRS_CONSTBUFFER_02_068: [ If source's size is less than sizeof(uint8_t) + sizeof(uint32_t) then CONSTBUFFER_from_buffer shall fail and return CONSTBUFFER_FROM_BUFFER_RESULT_INVALID_DATA. ]*/
                if (size < CONSTBUFFER_VERSION_SIZE + CONSTBUFFER_SIZE_SIZE)
                {
                    LogError("cannot deserialize when the numbe of serialized bytes cannot be determined. size=%" PRIu32 "", size);
                    result = CONSTBUFFER_FROM_BUFFER_RESULT_INVALID_DATA;
                }
                else
                {
                    /*Codes_SRS_CONSTBUFFER_02_069: [ CONSTBUFFER_from_buffer shall read the number of serialized content bytes from offset 1 of source. ]*/
                    uint32_t content_size;
                    read_uint32_t(source + CONSTBUFFER_SIZE_OFFSET, &content_size);
                    /*Codes_SRS_CONSTBUFFER_02_070: [ If source's size is less than sizeof(uint8_t) + sizeof(uint32_t) + number of content bytes then CONSTBUFFER_from_buffer shall fail and return CONSTBUFFER_FROM_BUFFER_RESULT_INVALID_DATA. ]*/
                    if (size - (CONSTBUFFER_VERSION_SIZE + CONSTBUFFER_SIZE_SIZE) < content_size)
                    {
                        LogError("in the buffer at source=%p of size=%" PRIu32 " there are not enough bytes remaining after version and size to construct content from. Serialized content size was computed as %" PRIu32 " but there are only %" PRIu32 " bytes available",
                            source, size, content_size, (uint32_t)(size - CONSTBUFFER_VERSION_SIZE + CONSTBUFFER_SIZE_SIZE));
                        result = CONSTBUFFER_FROM_BUFFER_RESULT_INVALID_DATA;
                    }
                    else
                    {
                        /*Codes_SRS_CONSTBUFFER_02_071: [ CONSTBUFFER_from_buffer shall create a CONSTBUFFER_HANDLE from the bytes at offset 5 of source. ]*/
                        *destination = CONSTBUFFER_Create_Internal(source + CONSTBUFFER_CONTENT_OFFSET, content_size);
                        if (*destination == NULL)
                        {
                            /*Codes_SRS_CONSTBUFFER_02_073: [ If there are any failures then shall fail and return CONSTBUFFER_FROM_BUFFER_RESULT_ERROR. ]*/
                            LogError("failure in CONSTBUFFER_Create(source=%p + CONSTBUFFER_CONTENT_OFFSET=%zu, content_size=%" PRIu32 ")",
                                source, CONSTBUFFER_CONTENT_OFFSET, content_size);
                            result = CONSTBUFFER_FROM_BUFFER_RESULT_ERROR;
                        }
                        else
                        {
                            /*Codes_SRS_CONSTBUFFER_02_072: [ CONSTBUFFER_from_buffer shall succeed, write in consumed the total number of consumed bytes from source, write in destination the constructed CONSTBUFFER_HANDLE and return CONSTBUFFER_FROM_BUFFER_RESULT_OK. ]*/
                            *consumed = CONSTBUFFER_VERSION_SIZE + CONSTBUFFER_SIZE_SIZE + content_size;
                            result = CONSTBUFFER_FROM_BUFFER_RESULT_OK;
                        }
                    }
                }
            }
        }
    }
    return result;
}