// KEKS -- C99 KEKS encoder implementation
// Copyright (C) 2024-2025 Sergey Matveev <stargrave@stargrave.org>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation, version 3 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this program.  If not, see <http://www.gnu.org/licenses/>.

#include <assert.h>
#include <stddef.h>
#include <stdint.h>

#include "frombe.h"

uint64_t
keksFromBE(const unsigned char *buf, const size_t len)
{
    assert(buf != NULL);
    uint64_t v = 0;
    switch (len) {
    case 1:
        v = (uint64_t)(buf[0]);
        break;
    case 2:
        v = ((uint64_t)(buf[0]) << (uint64_t)8) | (uint64_t)(buf[1]);
        break;
    case 3:
        v = ((uint64_t)(buf[0]) << (uint64_t)16) | ((uint64_t)(buf[1]) << (uint64_t)8) |
            (uint64_t)(buf[2]);
        break;
    case 4:
        v = ((uint64_t)(buf[0]) << (uint64_t)24) |
            ((uint64_t)(buf[1]) << (uint64_t)16) | ((uint64_t)(buf[2]) << (uint64_t)8) |
            (uint64_t)(buf[3]);
        break;
    case 5:
        v = ((uint64_t)(buf[0]) << (uint64_t)32) |
            ((uint64_t)(buf[1]) << (uint64_t)24) |
            ((uint64_t)(buf[2]) << (uint64_t)16) | ((uint64_t)(buf[3]) << (uint64_t)8) |
            (uint64_t)(buf[4]);
        break;
    case 6:
        v = ((uint64_t)(buf[0]) << (uint64_t)40) |
            ((uint64_t)(buf[1]) << (uint64_t)32) |
            ((uint64_t)(buf[2]) << (uint64_t)24) |
            ((uint64_t)(buf[3]) << (uint64_t)16) | ((uint64_t)(buf[4]) << (uint64_t)8) |
            (uint64_t)(buf[5]);
        break;
    case 7:
        v = ((uint64_t)(buf[0]) << (uint64_t)48) |
            ((uint64_t)(buf[1]) << (uint64_t)40) |
            ((uint64_t)(buf[2]) << (uint64_t)32) |
            ((uint64_t)(buf[3]) << (uint64_t)24) |
            ((uint64_t)(buf[4]) << (uint64_t)16) | ((uint64_t)(buf[5]) << (uint64_t)8) |
            (uint64_t)(buf[6]);
        break;
    case 8:
        v = ((uint64_t)(buf[0]) << (uint64_t)56) |
            ((uint64_t)(buf[1]) << (uint64_t)48) |
            ((uint64_t)(buf[2]) << (uint64_t)40) |
            ((uint64_t)(buf[3]) << (uint64_t)32) |
            ((uint64_t)(buf[4]) << (uint64_t)24) |
            ((uint64_t)(buf[5]) << (uint64_t)16) | ((uint64_t)(buf[6]) << (uint64_t)8) |
            (uint64_t)(buf[7]);
        break;
    default:
        for (size_t i = 0; i < len; i++) {
            v |= (uint64_t)(buf[i]) << ((len - i - 1) * 8);
        }
    }
    return v;
}
