
io.opentelemetry.api.baggage.propagation.Element Maven / Gradle / Ivy
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.api.baggage.propagation;
import java.util.BitSet;
import javax.annotation.Nullable;
/**
* Represents single element of a W3C baggage header (key or value). Allows tracking parsing of a
* header string, keeping the state and validating allowed characters. Parsing state can be reset
* with {@link #reset(int)} allowing instance re-use.
*/
class Element {
private static final BitSet EXCLUDED_KEY_CHARS = new BitSet(128);
private static final BitSet EXCLUDED_VALUE_CHARS = new BitSet(128);
static {
for (char c :
new char[] {
'(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '{', '}'
}) {
EXCLUDED_KEY_CHARS.set(c);
}
for (char c : new char[] {'"', ',', ';', '\\'}) {
EXCLUDED_VALUE_CHARS.set(c);
}
}
private final BitSet excluded;
private boolean leadingSpace;
private boolean readingValue;
private boolean trailingSpace;
private int start;
private int end;
@Nullable private String value;
static Element createKeyElement() {
return new Element(EXCLUDED_KEY_CHARS);
}
static Element createValueElement() {
return new Element(EXCLUDED_VALUE_CHARS);
}
/**
* Constructs element instance.
*
* @param excluded characters that are not allowed for this type of an element
*/
private Element(BitSet excluded) {
this.excluded = excluded;
reset(0);
}
@Nullable
String getValue() {
return value;
}
void reset(int start) {
this.start = start;
leadingSpace = true;
readingValue = false;
trailingSpace = false;
value = null;
}
boolean tryTerminating(int index, String header) {
if (this.readingValue) {
markEnd(index);
}
if (this.trailingSpace) {
setValue(header);
return true;
} else {
// leading spaces - no content, invalid
return false;
}
}
private void markEnd(int end) {
this.end = end;
this.readingValue = false;
trailingSpace = true;
}
private void setValue(String header) {
this.value = header.substring(this.start, this.end);
}
boolean tryNextChar(char character, int index) {
if (isWhitespace(character)) {
return tryNextWhitespace(index);
} else if (isExcluded(character)) {
return false;
} else {
return tryNextTokenChar(index);
}
}
private static boolean isWhitespace(char character) {
return character == ' ' || character == '\t';
}
private boolean tryNextWhitespace(int index) {
if (readingValue) {
markEnd(index);
}
return true;
}
private boolean isExcluded(char character) {
return (character <= 32 || character >= 127 || excluded.get(character));
}
private boolean tryNextTokenChar(int index) {
if (leadingSpace) {
markStart(index);
}
return !trailingSpace;
}
private void markStart(int start) {
this.start = start;
readingValue = true;
leadingSpace = false;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy