All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.micronaut.serde.LimitingStream Maven / Gradle / Ivy

Go to download

Enables serialization/deserialization in Micronaut applications using build time information

There is a newer version: 2.11.0
Show newest version
/*
 * Copyright 2017-2023 original authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.micronaut.serde;

import io.micronaut.core.annotation.Internal;
import io.micronaut.core.annotation.NonNull;
import io.micronaut.core.type.Argument;
import io.micronaut.serde.config.SerdeConfiguration;
import io.micronaut.serde.exceptions.SerdeException;

/**
 * Utility class to check data limits in encoders and decoders. Currently, the only limit that is
 * checked is the nesting depth.
 * 

* This class can be used in both implementation "patterns" for {@link Encoder} (and * {@link Decoder}): For the same-object pattern, where {@link Encoder#encodeObject(Argument)} * returns the same instance, the encoder should call {@link #increaseDepth()}, with a * corresponding {@link #decreaseDepth()} call in {@link Encoder#finishStructure()}. Conversely, if * the encoder is implemented using the child-object pattern, where * {@link Encoder#encodeObject(Argument)} returns a child encoder responsible for the subtree, that * child encoder should be instantiated using the new limits returned by {@link #childLimits()}. *

* If there is a limit violation, {@link #childLimits()} or {@link #increaseDepth()} will throw an * exception. * * @author Jonas Konrad * @since 2.0.0 */ @Internal public abstract class LimitingStream { /** * Default nesting depth limit. */ public static final int DEFAULT_MAXIMUM_DEPTH = 1024; /** * Default limits, only use this when no {@link SerdeConfiguration} is available. */ public static final RemainingLimits DEFAULT_LIMITS = new RemainingLimits(DEFAULT_MAXIMUM_DEPTH); private int remainingDepth; public LimitingStream(@NonNull RemainingLimits remainingLimits) { this.remainingDepth = remainingLimits.remainingDepth; } /** * Get a snapshot of our current limits to be passed to the constructor. This can be used for * buffering decoders, when a new decoder takes over but no change in depth takes place. * * @return The current limits */ @NonNull protected final RemainingLimits ourLimits() { return new RemainingLimits(remainingDepth); } /** * Get the limits of a new child encoder. * * @return The new limits * @throws SerdeException If there is a nesting depth limit violation */ @NonNull protected final RemainingLimits childLimits() throws SerdeException { if (remainingDepth == 0) { reportMaxDepthExceeded(); } return new RemainingLimits(remainingDepth - 1); } /** * Increase the current depth. * * @throws SerdeException If there is a nesting depth limit violation */ protected final void increaseDepth() throws SerdeException { if (remainingDepth == 0) { reportMaxDepthExceeded(); } remainingDepth--; } /** * Decrease the current depth, always needs a corresponding {@link #increaseDepth()} call. */ protected final void decreaseDepth() { remainingDepth++; } private void reportMaxDepthExceeded() throws SerdeException { boolean encoder = this instanceof Encoder; throw new SerdeException("Maximum depth exceeded while " + (encoder ? "serializing" : "deserializing") + ". The maximum nesting depth can be increased, if necessary, using the " + SerdeConfiguration.PREFIX + ".maximum-nesting-depth config property."); } /** * Get the configured limits. * * @param configuration The serde configuration * @return The configured limits */ public static RemainingLimits limitsFromConfiguration(SerdeConfiguration configuration) { return new RemainingLimits(configuration.getMaximumNestingDepth()); } /** * This data structure contains the limits for this stream. */ public static final class RemainingLimits { final int remainingDepth; private RemainingLimits(int remainingDepth) { this.remainingDepth = remainingDepth; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy