// 
// Decompiled by Procyon v0.6.0
// 

package org.bouncycastle.crypto.digests;

import org.bouncycastle.crypto.Xof;

abstract class AsconXofBase extends AsconBaseDigest implements Xof
{
    private boolean m_squeezing;
    private final byte[] buffer;
    private int bytesInBuffer;
    
    AsconXofBase() {
        this.buffer = new byte[this.BlockSize];
    }
    
    @Override
    public void update(final byte b) {
        this.ensureNoAbsorbWhileSqueezing(this.m_squeezing);
        super.update(b);
    }
    
    @Override
    public void update(final byte[] array, final int n, final int n2) {
        this.ensureNoAbsorbWhileSqueezing(this.m_squeezing);
        super.update(array, n, n2);
    }
    
    @Override
    public int doOutput(final byte[] array, final int n, final int a) {
        this.ensureSufficientOutputBuffer(array, n, a);
        int n2 = 0;
        if (this.bytesInBuffer != 0) {
            final int n3 = this.BlockSize - this.bytesInBuffer;
            final int min = Math.min(a, this.bytesInBuffer);
            System.arraycopy(this.buffer, n3, array, n, min);
            this.bytesInBuffer -= min;
            n2 += min;
        }
        final int n4 = a - n2;
        if (n4 >= this.BlockSize) {
            n2 += this.hash(array, n + n2, n4 - n4 % this.BlockSize);
        }
        if (n2 < a) {
            this.hash(this.buffer, 0, this.BlockSize);
            final int n5 = a - n2;
            System.arraycopy(this.buffer, 0, array, n + n2, n5);
            this.bytesInBuffer = this.buffer.length - n5;
            n2 += n5;
        }
        return n2;
    }
    
    @Override
    public int doFinal(final byte[] array, final int n, final int n2) {
        final int doOutput = this.doOutput(array, n, n2);
        this.reset();
        return doOutput;
    }
    
    @Override
    public void reset() {
        this.m_squeezing = false;
        this.bytesInBuffer = 0;
        super.reset();
    }
    
    @Override
    protected void padAndAbsorb() {
        if (!this.m_squeezing) {
            this.m_squeezing = true;
            super.padAndAbsorb();
        }
        else {
            this.p.p(this.ASCON_PB_ROUNDS);
        }
    }
    
    private void ensureNoAbsorbWhileSqueezing(final boolean b) {
        if (b) {
            throw new IllegalStateException("attempt to absorb while squeezing");
        }
    }
}
