aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2026-03-22 10:59:03 +0000
committerMichael Williamson <mike@zwobble.org>2026-03-22 10:59:03 +0000
commitd8e89e31a95b7f435b07a5756368e5b39e063c6c (patch)
tree34a78709d64c1d146363acf6035606c98f8abb5a /src/main/java
parent0d83766cdb08286adf64c54d82ef2a78755f4c1e (diff)
Add serialization of sources to flatbuffers
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/org/shedlang/compiler/sources/serialization/SourceToFlatbuffers.java141
1 files changed, 141 insertions, 0 deletions
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<Source> 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<Source> 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<Source> 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<Source> 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));
+ }
+}