what-the-bank/sources/io/grpc/internal/GrpcUtil.java

589 lines
26 KiB
Java
Raw Permalink Normal View History

2024-07-27 18:17:47 +07:00
package io.grpc.internal;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.base.Stopwatch;
import com.google.common.base.Supplier;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import io.grpc.CallOptions;
import io.grpc.ClientStreamTracer;
import io.grpc.InternalChannelz;
import io.grpc.InternalLogId;
import io.grpc.InternalMetadata;
import io.grpc.LoadBalancer;
import io.grpc.Metadata;
import io.grpc.MethodDescriptor;
import io.grpc.ProxiedSocketAddress;
import io.grpc.ProxyDetector;
import io.grpc.Status;
import io.grpc.internal.ClientStreamListener;
import io.grpc.internal.ClientTransport;
import io.grpc.internal.SharedResourceHolder;
import io.grpc.internal.StreamListener;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
/* loaded from: classes6.dex */
public final class GrpcUtil {
public static final String CONTENT_ACCEPT_ENCODING = "accept-encoding";
public static final Metadata.Key<byte[]> CONTENT_ACCEPT_ENCODING_KEY;
public static final String CONTENT_TYPE_GRPC = "application/grpc";
public static final String DEFAULT_LB_POLICY = "pick_first";
public static final int DEFAULT_MAX_HEADER_LIST_SIZE = 8192;
public static final int DEFAULT_MAX_MESSAGE_SIZE = 4194304;
public static final int DEFAULT_PORT_PLAINTEXT = 80;
public static final int DEFAULT_PORT_SSL = 443;
public static final String HTTP_METHOD = "POST";
private static final String IMPLEMENTATION_VERSION = "1.44.1";
public static final long KEEPALIVE_TIME_NANOS_DISABLED = Long.MAX_VALUE;
public static final String MESSAGE_ACCEPT_ENCODING = "grpc-accept-encoding";
public static final Metadata.Key<byte[]> MESSAGE_ACCEPT_ENCODING_KEY;
public static final long SERVER_KEEPALIVE_TIME_NANOS_DISABLED = Long.MAX_VALUE;
public static final String TE_TRAILERS = "trailers";
private static final Logger log = Logger.getLogger(GrpcUtil.class.getName());
public static final Charset US_ASCII = StandardCharsets.US_ASCII;
public static final String TIMEOUT = "grpc-timeout";
public static final Metadata.Key<Long> TIMEOUT_KEY = Metadata.Key.of(TIMEOUT, new TimeoutMarshaller());
public static final String MESSAGE_ENCODING = "grpc-encoding";
public static final Metadata.Key<String> MESSAGE_ENCODING_KEY = Metadata.Key.of(MESSAGE_ENCODING, Metadata.ASCII_STRING_MARSHALLER);
public static final String CONTENT_ENCODING = "content-encoding";
public static final Metadata.Key<String> CONTENT_ENCODING_KEY = Metadata.Key.of(CONTENT_ENCODING, Metadata.ASCII_STRING_MARSHALLER);
static final Metadata.Key<String> CONTENT_LENGTH_KEY = Metadata.Key.of("content-length", Metadata.ASCII_STRING_MARSHALLER);
public static final Metadata.Key<String> CONTENT_TYPE_KEY = Metadata.Key.of("content-type", Metadata.ASCII_STRING_MARSHALLER);
public static final Metadata.Key<String> TE_HEADER = Metadata.Key.of("te", Metadata.ASCII_STRING_MARSHALLER);
public static final Metadata.Key<String> USER_AGENT_KEY = Metadata.Key.of("user-agent", Metadata.ASCII_STRING_MARSHALLER);
public static final Splitter ACCEPT_ENCODING_SPLITTER = Splitter.on(',').trimResults();
public static final long DEFAULT_KEEPALIVE_TIMEOUT_NANOS = TimeUnit.SECONDS.toNanos(20);
public static final long DEFAULT_SERVER_KEEPALIVE_TIME_NANOS = TimeUnit.HOURS.toNanos(2);
public static final long DEFAULT_SERVER_KEEPALIVE_TIMEOUT_NANOS = TimeUnit.SECONDS.toNanos(20);
public static final ProxyDetector DEFAULT_PROXY_DETECTOR = new ProxyDetectorImpl();
public static final ProxyDetector NOOP_PROXY_DETECTOR = new ProxyDetector() { // from class: io.grpc.internal.GrpcUtil.1
@Override // io.grpc.ProxyDetector
public ProxiedSocketAddress proxyFor(SocketAddress socketAddress) {
return null;
}
};
public static final CallOptions.Key<Boolean> CALL_OPTIONS_RPC_OWNED_BY_BALANCER = CallOptions.Key.create("io.grpc.internal.CALL_OPTIONS_RPC_OWNED_BY_BALANCER");
private static final ClientStreamTracer NOOP_TRACER = new ClientStreamTracer() { // from class: io.grpc.internal.GrpcUtil.2
};
public static final SharedResourceHolder.Resource<Executor> SHARED_CHANNEL_EXECUTOR = new SharedResourceHolder.Resource<Executor>() { // from class: io.grpc.internal.GrpcUtil.3
private static final String NAME = "grpc-default-executor";
@Override // io.grpc.internal.SharedResourceHolder.Resource
public Executor create() {
return Executors.newCachedThreadPool(GrpcUtil.getThreadFactory("grpc-default-executor-%d", true));
}
@Override // io.grpc.internal.SharedResourceHolder.Resource
public void close(Executor executor) {
((ExecutorService) executor).shutdown();
}
public String toString() {
return NAME;
}
};
public static final SharedResourceHolder.Resource<ScheduledExecutorService> TIMER_SERVICE = new SharedResourceHolder.Resource<ScheduledExecutorService>() { // from class: io.grpc.internal.GrpcUtil.4
@Override // io.grpc.internal.SharedResourceHolder.Resource
public ScheduledExecutorService create() {
ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(1, GrpcUtil.getThreadFactory("grpc-timer-%d", true));
try {
newScheduledThreadPool.getClass().getMethod("setRemoveOnCancelPolicy", Boolean.TYPE).invoke(newScheduledThreadPool, Boolean.TRUE);
} catch (NoSuchMethodException unused) {
} catch (RuntimeException e) {
throw e;
} catch (Exception e2) {
throw new RuntimeException(e2);
}
return Executors.unconfigurableScheduledExecutorService(newScheduledThreadPool);
}
@Override // io.grpc.internal.SharedResourceHolder.Resource
public void close(ScheduledExecutorService scheduledExecutorService) {
scheduledExecutorService.shutdown();
}
};
public static final Supplier<Stopwatch> STOPWATCH_SUPPLIER = new Supplier<Stopwatch>() { // from class: io.grpc.internal.GrpcUtil.5
/* JADX WARN: Can't rename method to resolve collision */
@Override // com.google.common.base.Supplier
public Stopwatch get() {
return Stopwatch.createUnstarted();
}
};
static {
MESSAGE_ACCEPT_ENCODING_KEY = InternalMetadata.keyOf(MESSAGE_ACCEPT_ENCODING, new AcceptEncodingMarshaller());
CONTENT_ACCEPT_ENCODING_KEY = InternalMetadata.keyOf(CONTENT_ACCEPT_ENCODING, new AcceptEncodingMarshaller());
}
/* loaded from: classes6.dex */
static final class AcceptEncodingMarshaller implements InternalMetadata.TrustedAsciiMarshaller<byte[]> {
@Override // io.grpc.Metadata.TrustedAsciiMarshaller
public final byte[] parseAsciiString(byte[] bArr) {
return bArr;
}
@Override // io.grpc.Metadata.TrustedAsciiMarshaller
public final byte[] toAsciiString(byte[] bArr) {
return bArr;
}
private AcceptEncodingMarshaller() {
}
}
public static boolean shouldBeCountedForInUse(CallOptions callOptions) {
return !Boolean.TRUE.equals(callOptions.getOption(CALL_OPTIONS_RPC_OWNED_BY_BALANCER));
}
public static Status httpStatusToGrpcStatus(int i) {
return httpStatusToGrpcCode(i).toStatus().withDescription("HTTP status code ".concat(String.valueOf(i)));
}
private static Status.Code httpStatusToGrpcCode(int i) {
if (i >= 100 && i < 200) {
return Status.Code.INTERNAL;
}
if (i != 400) {
if (i == 401) {
return Status.Code.UNAUTHENTICATED;
}
if (i == 403) {
return Status.Code.PERMISSION_DENIED;
}
if (i == 404) {
return Status.Code.UNIMPLEMENTED;
}
if (i != 429) {
if (i != 431) {
switch (i) {
case 502:
case 503:
case 504:
break;
default:
return Status.Code.UNKNOWN;
}
}
}
return Status.Code.UNAVAILABLE;
}
return Status.Code.INTERNAL;
}
/* JADX WARN: Failed to restore enum class, 'enum' modifier and super class removed */
/* JADX WARN: Found several "values" enum fields: [] */
/* loaded from: classes6.dex */
public static final class Http2Error {
private static final Http2Error[] $VALUES;
public static final Http2Error CANCEL;
public static final Http2Error COMPRESSION_ERROR;
public static final Http2Error CONNECT_ERROR;
public static final Http2Error ENHANCE_YOUR_CALM;
public static final Http2Error FLOW_CONTROL_ERROR;
public static final Http2Error FRAME_SIZE_ERROR;
public static final Http2Error HTTP_1_1_REQUIRED;
public static final Http2Error INADEQUATE_SECURITY;
public static final Http2Error INTERNAL_ERROR;
public static final Http2Error NO_ERROR;
public static final Http2Error PROTOCOL_ERROR;
public static final Http2Error REFUSED_STREAM;
public static final Http2Error SETTINGS_TIMEOUT;
public static final Http2Error STREAM_CLOSED;
private static final Http2Error[] codeMap;
private final int code;
private final Status status;
public static Http2Error valueOf(String str) {
return (Http2Error) Enum.valueOf(Http2Error.class, str);
}
public static Http2Error[] values() {
return (Http2Error[]) $VALUES.clone();
}
static {
Http2Error http2Error = new Http2Error("NO_ERROR", 0, 0, Status.UNAVAILABLE);
NO_ERROR = http2Error;
Http2Error http2Error2 = new Http2Error("PROTOCOL_ERROR", 1, 1, Status.INTERNAL);
PROTOCOL_ERROR = http2Error2;
Http2Error http2Error3 = new Http2Error("INTERNAL_ERROR", 2, 2, Status.INTERNAL);
INTERNAL_ERROR = http2Error3;
Http2Error http2Error4 = new Http2Error("FLOW_CONTROL_ERROR", 3, 3, Status.INTERNAL);
FLOW_CONTROL_ERROR = http2Error4;
Http2Error http2Error5 = new Http2Error("SETTINGS_TIMEOUT", 4, 4, Status.INTERNAL);
SETTINGS_TIMEOUT = http2Error5;
Http2Error http2Error6 = new Http2Error("STREAM_CLOSED", 5, 5, Status.INTERNAL);
STREAM_CLOSED = http2Error6;
Http2Error http2Error7 = new Http2Error("FRAME_SIZE_ERROR", 6, 6, Status.INTERNAL);
FRAME_SIZE_ERROR = http2Error7;
Http2Error http2Error8 = new Http2Error("REFUSED_STREAM", 7, 7, Status.UNAVAILABLE);
REFUSED_STREAM = http2Error8;
Http2Error http2Error9 = new Http2Error("CANCEL", 8, 8, Status.CANCELLED);
CANCEL = http2Error9;
Http2Error http2Error10 = new Http2Error("COMPRESSION_ERROR", 9, 9, Status.INTERNAL);
COMPRESSION_ERROR = http2Error10;
Http2Error http2Error11 = new Http2Error("CONNECT_ERROR", 10, 10, Status.INTERNAL);
CONNECT_ERROR = http2Error11;
Http2Error http2Error12 = new Http2Error("ENHANCE_YOUR_CALM", 11, 11, Status.RESOURCE_EXHAUSTED.withDescription("Bandwidth exhausted"));
ENHANCE_YOUR_CALM = http2Error12;
Http2Error http2Error13 = new Http2Error("INADEQUATE_SECURITY", 12, 12, Status.PERMISSION_DENIED.withDescription("Permission denied as protocol is not secure enough to call"));
INADEQUATE_SECURITY = http2Error13;
Http2Error http2Error14 = new Http2Error("HTTP_1_1_REQUIRED", 13, 13, Status.UNKNOWN);
HTTP_1_1_REQUIRED = http2Error14;
$VALUES = new Http2Error[]{http2Error, http2Error2, http2Error3, http2Error4, http2Error5, http2Error6, http2Error7, http2Error8, http2Error9, http2Error10, http2Error11, http2Error12, http2Error13, http2Error14};
codeMap = buildHttp2CodeMap();
}
private static Http2Error[] buildHttp2CodeMap() {
Http2Error[] values = values();
Http2Error[] http2ErrorArr = new Http2Error[((int) values[values.length - 1].code()) + 1];
for (Http2Error http2Error : values) {
http2ErrorArr[(int) http2Error.code()] = http2Error;
}
return http2ErrorArr;
}
private Http2Error(String str, int i, int i2, Status status) {
this.code = i2;
StringBuilder sb = new StringBuilder("HTTP/2 error code: ");
sb.append(name());
String obj = sb.toString();
if (status.getDescription() != null) {
StringBuilder sb2 = new StringBuilder();
sb2.append(obj);
sb2.append(" (");
sb2.append(status.getDescription());
sb2.append(")");
obj = sb2.toString();
}
this.status = status.withDescription(obj);
}
public static Http2Error forCode(long j) {
Http2Error[] http2ErrorArr = codeMap;
if (j >= http2ErrorArr.length || j < 0) {
return null;
}
return http2ErrorArr[(int) j];
}
public static Status statusForCode(long j) {
Http2Error forCode = forCode(j);
if (forCode == null) {
return Status.fromCodeValue(INTERNAL_ERROR.status().getCode().value()).withDescription("Unrecognized HTTP/2 error code: ".concat(String.valueOf(j)));
}
return forCode.status();
}
public final Status status() {
return this.status;
}
public final long code() {
return this.code;
}
}
public static boolean isGrpcContentType(String str) {
if (str == null || 16 > str.length()) {
return false;
}
String lowerCase = str.toLowerCase();
if (!lowerCase.startsWith(CONTENT_TYPE_GRPC)) {
return false;
}
if (lowerCase.length() == 16) {
return true;
}
char charAt = lowerCase.charAt(16);
return charAt == '+' || charAt == ';';
}
public static String getGrpcUserAgent(String str, String str2) {
StringBuilder sb = new StringBuilder();
if (str2 != null) {
sb.append(str2);
sb.append(' ');
}
sb.append("grpc-java-");
sb.append(str);
sb.append("/1.44.1");
return sb.toString();
}
/* loaded from: classes6.dex */
public static final class GrpcBuildVersion {
private final String implementationVersion;
private final String userAgent;
private GrpcBuildVersion(String str, String str2) {
this.userAgent = (String) Preconditions.checkNotNull(str, "userAgentName");
this.implementationVersion = (String) Preconditions.checkNotNull(str2, "implementationVersion");
}
public final String toString() {
StringBuilder sb = new StringBuilder();
sb.append(this.userAgent);
sb.append(" ");
sb.append(this.implementationVersion);
return sb.toString();
}
public final String getUserAgent() {
return this.userAgent;
}
public final String getImplementationVersion() {
return this.implementationVersion;
}
}
public static GrpcBuildVersion getGrpcBuildVersion() {
return new GrpcBuildVersion("gRPC Java", IMPLEMENTATION_VERSION);
}
public static URI authorityToUri(String str) {
Preconditions.checkNotNull(str, "authority");
try {
return new URI(null, str, null, null, null);
} catch (URISyntaxException e) {
throw new IllegalArgumentException("Invalid authority: ".concat(String.valueOf(str)), e);
}
}
public static String checkAuthority(String str) {
URI authorityToUri = authorityToUri(str);
Preconditions.checkArgument(authorityToUri.getHost() != null, "No host in authority '%s'", str);
Preconditions.checkArgument(authorityToUri.getUserInfo() == null, "Userinfo must not be present on authority: '%s'", str);
return str;
}
public static String authorityFromHostAndPort(String str, int i) {
try {
return new URI(null, null, str, i, null, null, null).getAuthority();
} catch (URISyntaxException e) {
StringBuilder sb = new StringBuilder("Invalid host or port: ");
sb.append(str);
sb.append(" ");
sb.append(i);
throw new IllegalArgumentException(sb.toString(), e);
}
}
public static ThreadFactory getThreadFactory(String str, boolean z) {
return new ThreadFactoryBuilder().setDaemon(z).setNameFormat(str).build();
}
public static String getHost(InetSocketAddress inetSocketAddress) {
try {
return (String) InetSocketAddress.class.getMethod("getHostString", new Class[0]).invoke(inetSocketAddress, new Object[0]);
} catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException unused) {
return inetSocketAddress.getHostName();
}
}
/* loaded from: classes6.dex */
static class TimeoutMarshaller implements Metadata.AsciiMarshaller<Long> {
TimeoutMarshaller() {
}
@Override // io.grpc.Metadata.AsciiMarshaller
public String toAsciiString(Long l) {
TimeUnit timeUnit = TimeUnit.NANOSECONDS;
if (l.longValue() < 0) {
throw new IllegalArgumentException("Timeout too small");
}
if (l.longValue() < 100000000) {
StringBuilder sb = new StringBuilder();
sb.append(l);
sb.append("n");
return sb.toString();
}
if (l.longValue() < 100000000000L) {
StringBuilder sb2 = new StringBuilder();
sb2.append(timeUnit.toMicros(l.longValue()));
sb2.append("u");
return sb2.toString();
}
if (l.longValue() < 100000000000000L) {
StringBuilder sb3 = new StringBuilder();
sb3.append(timeUnit.toMillis(l.longValue()));
sb3.append("m");
return sb3.toString();
}
if (l.longValue() < 100000000000000000L) {
StringBuilder sb4 = new StringBuilder();
sb4.append(timeUnit.toSeconds(l.longValue()));
sb4.append("S");
return sb4.toString();
}
if (l.longValue() < 6000000000000000000L) {
StringBuilder sb5 = new StringBuilder();
sb5.append(timeUnit.toMinutes(l.longValue()));
sb5.append("M");
return sb5.toString();
}
StringBuilder sb6 = new StringBuilder();
sb6.append(timeUnit.toHours(l.longValue()));
sb6.append("H");
return sb6.toString();
}
/* JADX WARN: Can't rename method to resolve collision */
@Override // io.grpc.Metadata.AsciiMarshaller
public Long parseAsciiString(String str) {
Preconditions.checkArgument(str.length() > 0, "empty timeout");
Preconditions.checkArgument(str.length() <= 9, "bad timeout format");
long parseLong = Long.parseLong(str.substring(0, str.length() - 1));
char charAt = str.charAt(str.length() - 1);
if (charAt == 'H') {
return Long.valueOf(TimeUnit.HOURS.toNanos(parseLong));
}
if (charAt == 'M') {
return Long.valueOf(TimeUnit.MINUTES.toNanos(parseLong));
}
if (charAt == 'S') {
return Long.valueOf(TimeUnit.SECONDS.toNanos(parseLong));
}
if (charAt == 'u') {
return Long.valueOf(TimeUnit.MICROSECONDS.toNanos(parseLong));
}
if (charAt == 'm') {
return Long.valueOf(TimeUnit.MILLISECONDS.toNanos(parseLong));
}
if (charAt == 'n') {
return Long.valueOf(parseLong);
}
throw new IllegalArgumentException(String.format("Invalid timeout unit: %s", Character.valueOf(charAt)));
}
}
/* JADX INFO: Access modifiers changed from: package-private */
public static ClientTransport getTransportFromPickResult(LoadBalancer.PickResult pickResult, boolean z) {
LoadBalancer.Subchannel subchannel = pickResult.getSubchannel();
ClientTransport obtainActiveTransport = subchannel != null ? ((TransportProvider) subchannel.getInternalSubchannel()).obtainActiveTransport() : null;
if (obtainActiveTransport != null) {
ClientStreamTracer.Factory streamTracerFactory = pickResult.getStreamTracerFactory();
return streamTracerFactory == null ? obtainActiveTransport : new ClientTransport(streamTracerFactory, obtainActiveTransport) { // from class: io.grpc.internal.GrpcUtil.6
final ClientStreamTracer.Factory val$streamTracerFactory;
final ClientTransport val$transport;
{
this.val$streamTracerFactory = streamTracerFactory;
this.val$transport = obtainActiveTransport;
}
@Override // io.grpc.internal.ClientTransport
public ClientStream newStream(MethodDescriptor<?, ?> methodDescriptor, Metadata metadata, CallOptions callOptions, ClientStreamTracer[] clientStreamTracerArr) {
ClientStreamTracer newClientStreamTracer = this.val$streamTracerFactory.newClientStreamTracer(ClientStreamTracer.StreamInfo.newBuilder().setCallOptions(callOptions).build(), metadata);
Preconditions.checkState(clientStreamTracerArr[clientStreamTracerArr.length - 1] == GrpcUtil.NOOP_TRACER, "lb tracer already assigned");
clientStreamTracerArr[clientStreamTracerArr.length - 1] = newClientStreamTracer;
return this.val$transport.newStream(methodDescriptor, metadata, callOptions, clientStreamTracerArr);
}
@Override // io.grpc.internal.ClientTransport
public void ping(ClientTransport.PingCallback pingCallback, Executor executor) {
this.val$transport.ping(pingCallback, executor);
}
@Override // io.grpc.InternalWithLogId
public InternalLogId getLogId() {
return this.val$transport.getLogId();
}
@Override // io.grpc.InternalInstrumented
public ListenableFuture<InternalChannelz.SocketStats> getStats() {
return this.val$transport.getStats();
}
};
}
if (!pickResult.getStatus().isOk()) {
if (pickResult.isDrop()) {
return new FailingClientTransport(pickResult.getStatus(), ClientStreamListener.RpcProgress.DROPPED);
}
if (!z) {
return new FailingClientTransport(pickResult.getStatus(), ClientStreamListener.RpcProgress.PROCESSED);
}
}
return null;
}
public static ClientStreamTracer[] getClientStreamTracers(CallOptions callOptions, Metadata metadata, int i, boolean z) {
List<ClientStreamTracer.Factory> streamTracerFactories = callOptions.getStreamTracerFactories();
int size = streamTracerFactories.size();
ClientStreamTracer[] clientStreamTracerArr = new ClientStreamTracer[size + 1];
ClientStreamTracer.StreamInfo build = ClientStreamTracer.StreamInfo.newBuilder().setCallOptions(callOptions).setPreviousAttempts(i).setIsTransparentRetry(z).build();
for (int i2 = 0; i2 < streamTracerFactories.size(); i2++) {
clientStreamTracerArr[i2] = streamTracerFactories.get(i2).newClientStreamTracer(build, metadata);
}
clientStreamTracerArr[size] = NOOP_TRACER;
return clientStreamTracerArr;
}
/* JADX INFO: Access modifiers changed from: package-private */
public static void closeQuietly(StreamListener.MessageProducer messageProducer) {
while (true) {
InputStream next = messageProducer.next();
if (next == null) {
return;
} else {
closeQuietly(next);
}
}
}
public static void closeQuietly(Closeable closeable) {
if (closeable == null) {
return;
}
try {
closeable.close();
} catch (IOException e) {
log.log(Level.WARNING, "exception caught in closeQuietly", (Throwable) e);
}
}
/* JADX INFO: Access modifiers changed from: package-private */
public static <T> boolean iterableContains(Iterable<T> iterable, T t) {
if (iterable instanceof Collection) {
try {
return ((Collection) iterable).contains(t);
} catch (ClassCastException | NullPointerException unused) {
return false;
}
}
Iterator<T> it = iterable.iterator();
while (it.hasNext()) {
if (Objects.equal(it.next(), t)) {
return true;
}
}
return false;
}
private GrpcUtil() {
}
}