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

package com.google.protobuf;

import java.io.IOException;

@CheckReturnValue
abstract class UnknownFieldSchema<T, B>
{
    static final int DEFAULT_RECURSION_LIMIT = 100;
    private static volatile int recursionLimit;
    
    abstract boolean shouldDiscardUnknownFields(final Reader reader);
    
    abstract void addVarint(final B fields, final int number, final long value);
    
    abstract void addFixed32(final B fields, final int number, final int value);
    
    abstract void addFixed64(final B fields, final int number, final long value);
    
    abstract void addLengthDelimited(final B fields, final int number, final ByteString value);
    
    abstract void addGroup(final B fields, final int number, final T subFieldSet);
    
    abstract B newBuilder();
    
    abstract T toImmutable(final B fields);
    
    abstract void setToMessage(final Object message, final T fields);
    
    abstract T getFromMessage(final Object message);
    
    abstract B getBuilderFromMessage(final Object message);
    
    abstract void setBuilderToMessage(final Object message, final B builder);
    
    abstract void makeImmutable(final Object message);
    
    final boolean mergeOneFieldFrom(final B unknownFields, final Reader reader, int currentDepth) throws IOException {
        final int tag = reader.getTag();
        final int fieldNumber = WireFormat.getTagFieldNumber(tag);
        switch (WireFormat.getTagWireType(tag)) {
            case 0: {
                this.addVarint(unknownFields, fieldNumber, reader.readInt64());
                return true;
            }
            case 5: {
                this.addFixed32(unknownFields, fieldNumber, reader.readFixed32());
                return true;
            }
            case 1: {
                this.addFixed64(unknownFields, fieldNumber, reader.readFixed64());
                return true;
            }
            case 2: {
                this.addLengthDelimited(unknownFields, fieldNumber, reader.readBytes());
                return true;
            }
            case 3: {
                final B subFields = this.newBuilder();
                final int endGroupTag = WireFormat.makeTag(fieldNumber, 4);
                if (++currentDepth >= UnknownFieldSchema.recursionLimit) {
                    throw InvalidProtocolBufferException.recursionLimitExceeded();
                }
                this.mergeFrom(subFields, reader, currentDepth);
                --currentDepth;
                if (endGroupTag != reader.getTag()) {
                    throw InvalidProtocolBufferException.invalidEndTag();
                }
                this.addGroup(unknownFields, fieldNumber, this.toImmutable(subFields));
                return true;
            }
            case 4: {
                if (currentDepth == 0) {
                    throw InvalidProtocolBufferException.invalidEndTag();
                }
                return false;
            }
            default: {
                throw InvalidProtocolBufferException.invalidWireType();
            }
        }
    }
    
    private final void mergeFrom(final B unknownFields, final Reader reader, final int currentDepth) throws IOException {
        while (reader.getFieldNumber() != Integer.MAX_VALUE && this.mergeOneFieldFrom(unknownFields, reader, currentDepth)) {}
    }
    
    abstract void writeTo(final T unknownFields, final Writer writer) throws IOException;
    
    abstract void writeAsMessageSetTo(final T unknownFields, final Writer writer) throws IOException;
    
    abstract T merge(final T destination, final T source);
    
    abstract int getSerializedSizeAsMessageSet(final T message);
    
    abstract int getSerializedSize(final T unknowns);
    
    public void setRecursionLimit(final int limit) {
        UnknownFieldSchema.recursionLimit = limit;
    }
    
    static {
        UnknownFieldSchema.recursionLimit = 100;
    }
}
