package skadistats.clarity.decoder.bitstream;

import com.google.protobuf.ByteString;
import com.google.protobuf.ZeroCopy;
import skadistats.clarity.ClarityException;
import skadistats.clarity.decoder.Util;
import sun.misc.Unsafe;

import java.lang.reflect.Constructor;

public abstract class UnsafeBitStreamBase extends BitStream {

    protected static final Unsafe unsafe;
    protected static final long base;

    static {
        Unsafe u = null;
        try {
            Constructor<Unsafe> unsafeConstructor = Unsafe.class.getDeclaredConstructor();
            unsafeConstructor.setAccessible(true);
            u = unsafeConstructor.newInstance();
        } catch (Exception e) {
            Util.uncheckedThrow(e);
        }
        unsafe = u;
        base = unsafe.arrayBaseOffset(byte[].class);
    }

    protected final byte[] data;
    protected final long bound;

    public UnsafeBitStreamBase(ByteString input) {
        data = ZeroCopy.extract(input);
        pos = 0;
        len = data.length * 8;
        bound = ((data.length + 8) & 0xFFFFFFF8);
    }

    protected void checkAccessAbsolute(long offs, long n) {
        checkAccessRelative(offs - base, n);
    }

    protected void checkAccessRelative(long offs, long n) {
        if (offs < 0L) {
            throw new ClarityException(
                "Invalid memory access: Tried to access array of length %d at offset %d", data.length, offs
            );
        }
        if (offs + n > bound) {
            throw new ClarityException(
                "Invalid memory access: Tried to access array of length %d at offset %d", data.length, offs + n
            );
        }
    }
}

@@ -1284,156 +1284,101 @@
     
-throw new ClarityException(%0A                %22Invalid memory access: Tried to access array of length %25d at offset %25d%22, data.length, offs%0A            
+accessFailed(offs);%0A        %7D else  if (offs + n %3E bound) %7B%0A            accessFailed(offs + n
 );%0A 
@@ -1394,40 +1394,54 @@
     
+%7D%0A%0A
     
-if (offs + n %3E bound) %7B%0A    
+private void accessFailed(long offs) %7B%0A
     
@@ -1583,17 +1583,9 @@
 offs
- + n%0A    
+%0A
     
@@ -1595,22 +1595,14 @@
  );%0A    
- 
-   %7D%0A    %7D
+%7D%0A%0A
 %0A%7D%0A

make checkAccess functions inlineable