as_status
aerospike_query_users(aerospike* as, as_error* err, const as_policy_admin* policy, as_user*** users, int* users_size)
{
    as_error_reset(err);

    uint8_t buffer[AS_STACK_BUF_SIZE];
    uint8_t* p = buffer + 8;

    p = as_admin_write_header(p, QUERY_USERS, 0);

    as_vector list;
    as_vector_init(&list, sizeof(as_user*), 100);
    as_status status = as_admin_read_list(as, err, policy, buffer, p, as_parse_users, &list);

    if (status == AEROSPIKE_OK) {
        // Transfer array to output argument. Do not destroy vector.
        *users_size = list.size;
        *users = list.list;
    }
    else {
        *users_size = 0;
        *users = 0;
        as_free_users(&list, 0);
    }
    return status;
}
as_status
aerospike_query_user(aerospike* as, as_error* err, const as_policy_admin* policy, const char* user_name, as_user** user)
{
    as_error_reset(err);

    if (! user_name) {
        user_name = as->cluster->user;

        if (! user_name) {
            return AEROSPIKE_INVALID_USER;
        }
    }
    uint8_t buffer[AS_STACK_BUF_SIZE];
    uint8_t* p = buffer + 8;

    p = as_admin_write_header(p, QUERY_USERS, 1);
    p = as_admin_write_field_string(p, USER, user_name);

    as_vector list;
    as_vector_inita(&list, sizeof(as_user*), 1);
    as_status status = as_admin_read_list(as, err, policy, buffer, p, as_parse_users, &list);

    if (status == AEROSPIKE_OK) {
        if (list.size == 1) {
            *user = as_vector_get_ptr(&list, 0);
        }
        else if (list.size <= 0) {
            *user = 0;
            as_free_users(&list, 0);
        }
        else {
            *user = as_vector_get_ptr(&list, 0);
            // Delete excess users.
            as_free_users(&list, 1);
        }
    }
    else {
        *user = 0;
        as_free_users(&list, 0);
    }
    return status;
}
int
aerospike_query_user(aerospike* as, const as_policy_admin* policy, const char* user, as_user_roles** user_roles)
{
	if (! user) {
		user = as->cluster->user;
	}
	uint8_t buffer[STACK_BUF_SZ];
	uint8_t* p = buffer + 8;
	
	p = write_header(p, QUERY_USERS, 1);
	p = write_field_string(p, USER, user);
	
	as_vector users;
	as_vector_inita(&users, sizeof(as_user_roles*), 1);
	int status = as_read_users(as, policy, buffer, p, &users);
	
	if (status == 0) {
		if (users.size == 1) {
			*user_roles = as_vector_get_ptr(&users, 0);
		}
		else if (users.size <= 0) {
			*user_roles = 0;
			as_free_users(&users, 0);
		}
		else {
			*user_roles = as_vector_get_ptr(&users, 0);
			// Delete excess users.
			as_free_users(&users, 1);
		}
	}
	else {
		*user_roles = 0;
		as_free_users(&users, 0);
	}
	return status;
}
int
aerospike_query_users(aerospike* as, const as_policy_admin* policy, as_user_roles*** user_roles, int* user_roles_size)
{
	uint8_t buffer[STACK_BUF_SZ];
	uint8_t* p = buffer + 8;
	
	p = write_header(p, QUERY_USERS, 0);
	
	as_vector users;
	as_vector_init(&users, sizeof(as_user_roles*), 100);
	int status = as_read_users(as, policy, buffer, p, &users);
	
	if (status == 0) {
		// Transfer array to output argument. Do not destroy vector.
		*user_roles_size = users.size;
		*user_roles = users.list;
	}
	else {
		*user_roles_size = 0;
		*user_roles = 0;
		as_free_users(&users, 0);
	}
	return status;
}