blob: b106a63c44f536da43b31911780fbef1026018f2 [file] [log] [blame]
// Copyright 2018 The Bazel Authors. All rights reserved.
//
// 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
//
// http://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 com.google.devtools.build.lib.skyframe.serialization;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.skyframe.serialization.Memoizer.MemoizingAfterObjectCodecAdapter;
import com.google.devtools.build.lib.skyframe.serialization.Memoizer.MemoizingCodec;
import com.google.devtools.build.lib.skyframe.serialization.ObjectCodecRegistry.MemoizingCodecDescriptor;
import com.google.devtools.build.lib.skyframe.serialization.SerializationException.NoCodecException;
import com.google.protobuf.CodedOutputStream;
import java.io.IOException;
import javax.annotation.Nullable;
/** Stateful class for providing additional context to a single serialization "session". */
public class SerializationContext {
private final ObjectCodecRegistry registry;
private final ImmutableMap<Class<?>, Object> dependencies;
public SerializationContext(
ObjectCodecRegistry registry, ImmutableMap<Class<?>, Object> dependencies) {
this.registry = registry;
this.dependencies = dependencies;
}
public SerializationContext(ImmutableMap<Class<?>, Object> dependencies) {
this(AutoRegistry.get(), dependencies);
}
private boolean writeNullOrConstant(@Nullable Object object, CodedOutputStream codedOut)
throws IOException {
if (object == null) {
codedOut.writeSInt32NoTag(0);
return true;
}
Integer tag = registry.maybeGetTagForConstant(object);
if (tag != null) {
codedOut.writeSInt32NoTag(tag);
return true;
}
return false;
}
@Nullable
private ObjectCodecRegistry.CodecDescriptor recordAndGetDescriptorIfNotConstantOrNull(
@Nullable Object object, CodedOutputStream codedOut) throws IOException, NoCodecException {
if (writeNullOrConstant(object, codedOut)) {
return null;
}
ObjectCodecRegistry.CodecDescriptor descriptor = registry.getCodecDescriptor(object.getClass());
codedOut.writeSInt32NoTag(descriptor.getTag());
return descriptor;
}
// TODO(shahan): consider making codedOut a member of this class.
public void serialize(Object object, CodedOutputStream codedOut)
throws IOException, SerializationException {
ObjectCodecRegistry.CodecDescriptor descriptor =
recordAndGetDescriptorIfNotConstantOrNull(object, codedOut);
if (descriptor != null) {
descriptor.serialize(this, object, codedOut);
}
}
@Nullable
public <T> MemoizingCodec<? super T> recordAndMaybeGetMemoizingCodec(
T object, CodedOutputStream codedOut) throws IOException, NoCodecException {
if (writeNullOrConstant(object, codedOut)) {
return null;
}
@SuppressWarnings("unchecked")
Class<T> clazz = (Class<T>) object.getClass();
MemoizingCodecDescriptor<? super T> memoizingCodecDescriptor =
registry.getMemoizingCodecDescriptor(clazz);
if (memoizingCodecDescriptor != null) {
codedOut.writeSInt32NoTag(memoizingCodecDescriptor.getTag());
return memoizingCodecDescriptor.getMemoizingCodec();
}
ObjectCodecRegistry.CodecDescriptor codecDescriptor = registry.getCodecDescriptor(clazz);
codedOut.writeSInt32NoTag(codecDescriptor.getTag());
@SuppressWarnings("unchecked")
ObjectCodec<? super T> objectCodec = (ObjectCodec<? super T>) codecDescriptor.getCodec();
return new MemoizingAfterObjectCodecAdapter<>(objectCodec);
}
@SuppressWarnings("unchecked")
public <T> T getDependency(Class<T> type) {
Preconditions.checkNotNull(type);
return (T) dependencies.get(type);
}
}