From d8e89e31a95b7f435b07a5756368e5b39e063c6c Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Sun, 22 Mar 2026 10:59:03 +0000 Subject: Add serialization of sources to flatbuffers --- .../sources/serialization/SourceToFlatbuffers.java | 141 +++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 src/main/java/org/shedlang/compiler/sources/serialization/SourceToFlatbuffers.java (limited to 'src/main/java') diff --git a/src/main/java/org/shedlang/compiler/sources/serialization/SourceToFlatbuffers.java b/src/main/java/org/shedlang/compiler/sources/serialization/SourceToFlatbuffers.java new file mode 100644 index 00000000..7c1bb074 --- /dev/null +++ b/src/main/java/org/shedlang/compiler/sources/serialization/SourceToFlatbuffers.java @@ -0,0 +1,141 @@ +package org.shedlang.compiler.sources.serialization; + +import com.google.flatbuffers.FlatBufferBuilder; +import org.shedlang.compiler.sources.*; +import org.shedlang.compiler.sources.flatbuffers.*; +import org.zwobble.sourcetext.SourcePosition; +import org.zwobble.sourcetext.SourceRange; +import org.zwobble.sourcetext.SourceText; + +import java.util.Optional; + +public class SourceToFlatbuffers { + private SourceToFlatbuffers() { + } + + public static int serializeSource( + FlatBufferBuilder builder, + Source source, + Source parentSource + ) { + return serializeSource(builder, source, Optional.of(parentSource)); + } + + public static int serializeSource( + FlatBufferBuilder builder, + Source source, + Optional parentSource + ) { + switch (source) { + case NullSource nullSource -> { + NullSourceFbs.startNullSourceFbs(builder); + var nullSourceFbs = NullSourceFbs.endNullSourceFbs(builder); + + SourceFbs.startSourceFbs(builder); + SourceFbs.addValueType(builder, SourceValueFbs.NullSourceFbs); + SourceFbs.addValue(builder, nullSourceFbs); + return SourceFbs.endSourceFbs(builder); + } + case RuntimeSource runtimeSource -> { + RuntimeSourceFbs.startRuntimeSourceFbs(builder); + var runtimeSourceFbs = RuntimeSourceFbs.endRuntimeSourceFbs(builder); + + SourceFbs.startSourceFbs(builder); + SourceFbs.addValueType(builder, SourceValueFbs.RuntimeSourceFbs); + SourceFbs.addValue(builder, runtimeSourceFbs); + return SourceFbs.endSourceFbs(builder); + } + case FileFragmentSource fileFragmentSource -> { + var fileFragmentSourceFbs = serializeFileFragmentSource(builder, fileFragmentSource, parentSource); + + SourceFbs.startSourceFbs(builder); + SourceFbs.addValueType(builder, SourceValueFbs.FileFragmentSourceFbs); + SourceFbs.addValue( + builder, + fileFragmentSourceFbs + ); + return SourceFbs.endSourceFbs(builder); + } + default -> { + throw new UnsupportedOperationException("Unhandled source: " + source); + } + } + } + + public static Source deserializeSource( + SourceFbs sourceFbs, + Source parentSource + ) { + return deserializeSource(sourceFbs, Optional.of(parentSource)); + } + + public static Source deserializeSource( + SourceFbs sourceFbs, + Optional parentSource + ) { + return switch (sourceFbs.valueType()) { + case SourceValueFbs.NullSourceFbs -> + Sources.NULL; + + case SourceValueFbs.RuntimeSourceFbs -> + Sources.RUNTIME; + + case SourceValueFbs.FileFragmentSourceFbs -> + deserializeFileFragmentSource( + (FileFragmentSourceFbs) sourceFbs.value(new FileFragmentSourceFbs()), + parentSource + ); + + default -> { + throw new UnsupportedOperationException("TODO"); + } + }; + } + + private static int serializeFileFragmentSource( + FlatBufferBuilder builder, + FileFragmentSource source, + Optional parentSource + ) { + var sourceTextName = source.sourceRange().sourceText().name(); + if (!( + parentSource.isPresent() && + parentSource.get() instanceof FileFragmentSource( + SourceRange parentSourceRange) && + parentSourceRange.sourceText().name().equals(sourceTextName) + )) { + var sourceTextNameFbs = builder.createString(sourceTextName); + var sourceTextContentsFbs = builder.createString(source.sourceRange().sourceText().charSequence()); + var sourceTextFbs = SourceTextFbs.createSourceTextFbs(builder, sourceTextNameFbs, sourceTextContentsFbs); + FileFragmentSourceFbs.startFileFragmentSourceFbs(builder); + FileFragmentSourceFbs.addSourceText(builder, sourceTextFbs); + } else { + FileFragmentSourceFbs.startFileFragmentSourceFbs(builder); + } + + FileFragmentSourceFbs.addStartCharacterIndex(builder, source.sourceRange().start().characterIndex()); + FileFragmentSourceFbs.addEndCharacterIndex(builder, source.sourceRange().end().characterIndex()); + + return FileFragmentSourceFbs.endFileFragmentSourceFbs(builder); + } + + private static FileFragmentSource deserializeFileFragmentSource( + FileFragmentSourceFbs sourceFbs, + Optional parentSource + ) { + SourceText sourceText; + if (sourceFbs.sourceText() != null) { + sourceText = SourceText.fromString( + sourceFbs.sourceText().name(), + sourceFbs.sourceText().contents() + ); + } else { + // TODO: handle missing parent + sourceText = ((FileFragmentSource) parentSource.orElseThrow()).sourceRange().sourceText(); + } + + var start = new SourcePosition(sourceText, (int) sourceFbs.startCharacterIndex()); + var end = new SourcePosition(sourceText, (int) sourceFbs.endCharacterIndex()); + return new FileFragmentSource(new SourceRange(sourceText, start, end)); + } +} -- cgit v1.2.3