001/*
002 * Copyright (C) Photon Vision.
003 *
004 * This program is free software: you can redistribute it and/or modify
005 * it under the terms of the GNU General Public License as published by
006 * the Free Software Foundation, either version 3 of the License, or
007 * (at your option) any later version.
008 *
009 * This program is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012 * GNU General Public License for more details.
013 *
014 * You should have received a copy of the GNU General Public License
015 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
016 */
017
018package org.photonvision.vision.pipeline.result;
019
020@SuppressWarnings("PointlessBitwiseExpression")
021public abstract class BytePackable {
022    public abstract byte[] toByteArray();
023
024    public abstract void fromByteArray(byte[] src);
025
026    protected int bufferPosition = 0;
027
028    public int getBufferPosition() {
029        return bufferPosition;
030    }
031
032    public void resetBufferPosition() {
033        bufferPosition = 0;
034    }
035
036    protected void bufferData(byte[] src, byte[] dest) {
037        System.arraycopy(src, 0, dest, bufferPosition, src.length);
038        bufferPosition += src.length;
039    }
040
041    protected void bufferData(byte src, byte[] dest) {
042        System.arraycopy(new byte[] {src}, 0, dest, bufferPosition, 1);
043        bufferPosition++;
044    }
045
046    protected void bufferData(int src, byte[] dest) {
047        System.arraycopy(toBytes(src), 0, dest, bufferPosition, Integer.BYTES);
048        bufferPosition += Integer.BYTES;
049    }
050
051    protected void bufferData(double src, byte[] dest) {
052        System.arraycopy(toBytes(src), 0, dest, bufferPosition, Double.BYTES);
053        bufferPosition += Double.BYTES;
054    }
055
056    protected void bufferData(boolean src, byte[] dest) {
057        System.arraycopy(toBytes(src), 0, dest, bufferPosition, 1);
058        bufferPosition += 1;
059    }
060
061    protected boolean unbufferBoolean(byte[] src) {
062        return toBoolean(src, bufferPosition++);
063    }
064
065    protected byte unbufferByte(byte[] src) {
066        var value = src[bufferPosition];
067        bufferPosition++;
068        return value;
069    }
070
071    protected byte[] unbufferBytes(byte[] src, int len) {
072        var bytes = new byte[len];
073        System.arraycopy(src, bufferPosition, bytes, 0, len);
074        return bytes;
075    }
076
077    protected int unbufferInt(byte[] src) {
078        var value = toInt(src, bufferPosition);
079        bufferPosition += Integer.BYTES;
080        return value;
081    }
082
083    protected double unbufferDouble(byte[] src) {
084        var value = toDouble(src, bufferPosition);
085        bufferPosition += Double.BYTES;
086        return value;
087    }
088
089    private static boolean toBoolean(byte[] src, int pos) {
090        return src[pos] != 0;
091    }
092
093    private static int toInt(byte[] src, int pos) {
094        return (0xff & src[pos]) << 24
095                | (0xff & src[pos + 1]) << 16
096                | (0xff & src[pos + 2]) << 8
097                | (0xff & src[pos + 3]) << 0;
098    }
099
100    private static long toLong(byte[] src, int pos) {
101        return (long) (0xff & src[pos]) << 56
102                | (long) (0xff & src[pos + 1]) << 48
103                | (long) (0xff & src[pos + 2]) << 40
104                | (long) (0xff & src[pos + 3]) << 32
105                | (long) (0xff & src[pos + 4]) << 24
106                | (long) (0xff & src[pos + 5]) << 16
107                | (long) (0xff & src[pos + 6]) << 8
108                | (long) (0xff & src[pos + 7]) << 0;
109    }
110
111    private static double toDouble(byte[] src, int pos) {
112        return Double.longBitsToDouble(toLong(src, pos));
113    }
114
115    protected byte[] toBytes(double value) {
116        long data = Double.doubleToRawLongBits(value);
117        return new byte[] {
118            (byte) ((data >> 56) & 0xff),
119            (byte) ((data >> 48) & 0xff),
120            (byte) ((data >> 40) & 0xff),
121            (byte) ((data >> 32) & 0xff),
122            (byte) ((data >> 24) & 0xff),
123            (byte) ((data >> 16) & 0xff),
124            (byte) ((data >> 8) & 0xff),
125            (byte) ((data >> 0) & 0xff),
126        };
127    }
128
129    protected byte[] toBytes(int value) {
130        return new byte[] {
131            (byte) ((value >> 24) & 0xff),
132            (byte) ((value >> 16) & 0xff),
133            (byte) ((value >> 8) & 0xff),
134            (byte) ((value >> 0) & 0xff)
135        };
136    }
137
138    protected byte[] toBytes(boolean value) {
139        return new byte[] {(byte) (value ? 1 : 0)};
140    }
141}