Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion extern/rerun
Submodule rerun updated 508 files
5 changes: 3 additions & 2 deletions src/Rerun.Net.CodeGen/Emitters/ComponentEmitter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,11 +147,12 @@ private string EmitEnumComponent(FbsEnum e)
return sb.ToString();
}

/// <summary>Qualify datatype references to avoid name collisions with component names.</summary>
/// <summary>Qualify datatype references with the <c>Datatypes.</c> prefix so the
/// blueprint namespace rewrite in Program.cs can unambiguously fully-qualify them.</summary>
private static string QualifyDatatypeRef(FbsReference r, string componentName)
{
var shortName = GetShortName(r.FullyQualifiedName);
if (shortName == componentName && r.FullyQualifiedName.Contains("datatypes"))
if (r.FullyQualifiedName.Contains("datatypes"))
return $"Datatypes.{shortName}";
return shortName;
}
Expand Down
15 changes: 15 additions & 0 deletions src/Rerun.Net.CodeGen/Emitters/DatatypeEmitter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ namespace Rerun.Net.CodeGen.Emitters;

internal class DatatypeEmitter : EmitterBase
{
private readonly TypeRegistry? _registry;

public DatatypeEmitter(TypeRegistry? registry = null)
{
_registry = registry;
}

// Primitive-wrapper datatypes that clash with System types.
// Components referencing them can optionally inline the primitive Arrow directly.
internal static readonly Dictionary<string, string> PrimitiveWrapperTypes = new()
Expand Down Expand Up @@ -274,6 +281,14 @@ private string EmitTable(FbsTable t)
sb.AppendLine($" foreach (var v in data) {f.Name}Builder.Append(v.{fPropName});");
sb.AppendLine($" var {f.Name}Array = (IArrowArray){f.Name}Builder.Build();");
break;
case FbsReference r when _registry?.Resolve(r.FullyQualifiedName) is FbsEnum enumType:
// Enum-typed reference field: cast to underlying primitive and use a primitive Arrow builder.
var enumPrimCs = MapPrimitiveToCSharp(enumType.UnderlyingType);
var enumPrimBuilder = MapPrimitiveToArrowBuilder(enumType.UnderlyingType);
sb.AppendLine($" var {f.Name}Builder = new {enumPrimBuilder}();");
sb.AppendLine($" foreach (var v in data) {f.Name}Builder.Append(({enumPrimCs})v.{fPropName});");
sb.AppendLine($" var {f.Name}Array = (IArrowArray){f.Name}Builder.Build();");
break;
case FbsReference r:
var innerName = GetShortName(r.FullyQualifiedName);
sb.AppendLine($" var {f.Name}Tmp = new {innerName}[data.Length];");
Expand Down
18 changes: 10 additions & 8 deletions src/Rerun.Net.CodeGen/FbsParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,15 +140,15 @@ private static string CollectBlock(string[] lines, ref int i)

return kind switch
{
"struct" => new FbsStruct(name, ns, ParseFields(body), attrs, doc),
"table" => new FbsTable(name, ns, ParseFields(body), attrs, doc),
"struct" => new FbsStruct(name, ns, ParseFields(body, ns), attrs, doc),
"table" => new FbsTable(name, ns, ParseFields(body, ns), attrs, doc),
"enum" => new FbsEnum(name, ns, underlying, ParseEnumValues(body), attrs, doc),
"union" => new FbsUnion(name, ns, ParseUnionVariants(body), attrs, doc),
_ => null,
};
}

private List<FbsField> ParseFields(string body)
private List<FbsField> ParseFields(string body, string currentNamespace)
{
var fields = new List<FbsField>();
var docBuffer = new List<string>();
Expand Down Expand Up @@ -185,36 +185,38 @@ private List<FbsField> ParseFields(string body)
fieldAttrs.Remove("order");
}

var fieldType = ParseFieldType(typeStr);
var fieldType = ParseFieldType(typeStr, currentNamespace);
fields.Add(new FbsField(fieldName, fieldType, fieldAttrs, nullable, order, doc));
}

return fields.OrderBy(f => f.Order).ToList();
}

private FbsFieldType ParseFieldType(string typeStr)
private FbsFieldType ParseFieldType(string typeStr, string currentNamespace = "")
{
// Fixed array: [type: N]
var fixedMatch = Regex.Match(typeStr, @"^\[(\w+)\s*:\s*(\d+)\]$");
if (fixedMatch.Success)
{
var elemType = ParseFieldType(fixedMatch.Groups[1].Value);
var elemType = ParseFieldType(fixedMatch.Groups[1].Value, currentNamespace);
return new FbsFixedArray(elemType, int.Parse(fixedMatch.Groups[2].Value));
}

// Dynamic array: [type]
var arrayMatch = Regex.Match(typeStr, @"^\[(.+)\]$");
if (arrayMatch.Success)
{
var elemType = ParseFieldType(arrayMatch.Groups[1].Value);
var elemType = ParseFieldType(arrayMatch.Groups[1].Value, currentNamespace);
return new FbsArray(elemType);
}

// Primitive
if (Primitives.Contains(typeStr))
return new FbsPrimitive(typeStr);

// Qualified reference
// Reference: qualify same-namespace shorthand with the current namespace.
if (!typeStr.Contains('.') && currentNamespace.Length > 0)
return new FbsReference($"{currentNamespace}.{typeStr}");
return new FbsReference(typeStr);
}

Expand Down
44 changes: 43 additions & 1 deletion src/Rerun.Net.CodeGen/Program.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Text.RegularExpressions;
using Rerun.Net.CodeGen;
using Rerun.Net.CodeGen.Emitters;

Expand Down Expand Up @@ -44,7 +45,7 @@
}
}

var datatypeEmitter = new DatatypeEmitter();
var datatypeEmitter = new DatatypeEmitter(registry);
var componentEmitter = new ComponentEmitter();
var archetypeEmitter = new ArchetypeEmitter();

Expand Down Expand Up @@ -138,6 +139,43 @@ bool ArchetypeHasMissingComponent(FbsTable arch)
}
}

// Sets of all known type short-names per category, used by the blueprint
// post-processor to fully-qualify cross-namespace references.
var coreDatatypeNames = registry.GetByNamespace("rerun.datatypes")
.Select(t => t.Name).ToHashSet();
var coreComponentNames = registry.GetByNamespace("rerun.components")
.Select(t => t.Name).ToHashSet();
var bpDatatypeNames = registry.GetByNamespace("rerun.blueprint.datatypes")
.Select(t => t.Name).ToHashSet();
var bpComponentNames = registry.GetByNamespace("rerun.blueprint.components")
.Select(t => t.Name).ToHashSet();

// Inside Rerun.Net.Blueprint.* the unqualified names "Datatypes" and "Components"
// resolve to the closer Rerun.Net.Blueprint.{Datatypes,Components} sibling, which
// shadows the matching core namespaces. Rewrite every "Datatypes.X" / "Components.X"
// reference to a fully-qualified global:: path so the resolution is unambiguous.
var qualifiedRefRegex = new Regex(@"\b(Datatypes|Components)\.([A-Z]\w*)");
string FullyQualifyBlueprintRefs(string code) => qualifiedRefRegex.Replace(code, m =>
{
var category = m.Groups[1].Value;
var name = m.Groups[2].Value;
if (category == "Datatypes")
{
if (bpDatatypeNames.Contains(name))
return $"global::Rerun.Net.Blueprint.Datatypes.{name}";
if (coreDatatypeNames.Contains(name))
return $"global::Rerun.Net.Datatypes.{name}";
}
else
{
if (bpComponentNames.Contains(name))
return $"global::Rerun.Net.Blueprint.Components.{name}";
if (coreComponentNames.Contains(name))
return $"global::Rerun.Net.Components.{name}";
}
return m.Value;
});

// Generate blueprint types — same emitters, different namespace mapping
var bpNamespaces = new[] {
("rerun.blueprint.datatypes", "Blueprint/Datatypes", datatypeEmitter),
Expand Down Expand Up @@ -172,6 +210,10 @@ bool ArchetypeHasMissingComponent(FbsTable arch)
.Replace("namespace Rerun.Net.Archetypes;",
"using Rerun.Net.Components;\nusing Rerun.Net.Blueprint.Components;\n\nnamespace Rerun.Net.Blueprint.Archetypes;");

// Fully-qualify cross-namespace type references so blueprint sibling
// namespaces don't shadow the core ones.
code = FullyQualifyBlueprintRefs(code);

var outFile = Path.Combine(outputPath, subDir, $"{type.Name}.g.cs");
Directory.CreateDirectory(Path.GetDirectoryName(outFile)!);
File.WriteAllText(outFile, code);
Expand Down
4 changes: 2 additions & 2 deletions src/Rerun.Net/Blueprint/Archetypes/ActiveVisualizers.g.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ public sealed partial class ActiveVisualizers : IAsComponents

public ComponentBatch InstructionIds { get; private set; }

public ActiveVisualizers(ReadOnlySpan<Components.VisualizerInstructionId> instruction_ids)
public ActiveVisualizers(ReadOnlySpan<global::Rerun.Net.Blueprint.Components.VisualizerInstructionId> instruction_ids)
{
InstructionIds = ComponentBatch.FromLoggable(instruction_ids,
new ComponentDescriptor(ArchetypeName, "ActiveVisualizers:instruction_ids", "rerun.blueprint.components.VisualizerInstructionId"));
}

public ActiveVisualizers(params Components.VisualizerInstructionId[] instruction_ids) : this(instruction_ids.AsSpan()) { }
public ActiveVisualizers(params global::Rerun.Net.Blueprint.Components.VisualizerInstructionId[] instruction_ids) : this(instruction_ids.AsSpan()) { }

/// <summary>Create an empty ActiveVisualizers for partial updates. Use With*() to set fields.</summary>
public static ActiveVisualizers UpdateFields() => new();
Expand Down
54 changes: 54 additions & 0 deletions src/Rerun.Net/Blueprint/Archetypes/Background.g.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// <auto-generated/>
// DO NOT EDIT — generated by Rerun.Net.CodeGen
#pragma warning disable CS0542 // member names shall not match enclosing type

using Rerun.Net.Components;

using Rerun.Net.Components;
using Rerun.Net.Blueprint.Components;

namespace Rerun.Net.Blueprint.Archetypes;

/// <summary>
/// Configuration for the background of a spatial view.
/// </summary>
public sealed partial class Background : IAsComponents
{
private const string ArchetypeName = "rerun.blueprint.archetypes.Background";

public ComponentBatch Kind { get; private set; }
public ComponentBatch? Color { get; private set; }

public Background(ReadOnlySpan<global::Rerun.Net.Blueprint.Components.BackgroundKind> kind)
{
Kind = ComponentBatch.FromLoggable(kind,
new ComponentDescriptor(ArchetypeName, "Background:kind", "rerun.blueprint.components.BackgroundKind"));
}

public Background(params global::Rerun.Net.Blueprint.Components.BackgroundKind[] kind) : this(kind.AsSpan()) { }

public Background WithColor(ReadOnlySpan<global::Rerun.Net.Components.Color> color)
{
Color = ComponentBatch.FromLoggable(color,
new ComponentDescriptor(ArchetypeName, "Background:color", "rerun.components.Color"));
return this;
}

public Background WithColor(params global::Rerun.Net.Components.Color[] color) => WithColor(color.AsSpan());

/// <summary>Create an empty Background for partial updates. Use With*() to set fields.</summary>
public static Background UpdateFields() => new();

/// <summary>Clear all fields, then use With*() to set specific ones.</summary>
public static Background ClearFields() => new();

private Background() { }

public IReadOnlyList<ComponentBatch> AsBatches()
{
var batches = new List<ComponentBatch>(2);
batches.Add(Kind);
if (Color != null) batches.Add(Color);
return batches;
}
}
120 changes: 120 additions & 0 deletions src/Rerun.Net/Blueprint/Archetypes/ContainerBlueprint.g.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// <auto-generated/>
// DO NOT EDIT — generated by Rerun.Net.CodeGen
#pragma warning disable CS0542 // member names shall not match enclosing type

using Rerun.Net.Components;

using Rerun.Net.Components;
using Rerun.Net.Blueprint.Components;

namespace Rerun.Net.Blueprint.Archetypes;

/// <summary>
/// The description of a container.
/// </summary>
public sealed partial class ContainerBlueprint : IAsComponents
{
private const string ArchetypeName = "rerun.blueprint.archetypes.ContainerBlueprint";

public ComponentBatch ContainerKind { get; private set; }
public ComponentBatch? DisplayName { get; private set; }
public ComponentBatch? Contents { get; private set; }
public ComponentBatch? ColShares { get; private set; }
public ComponentBatch? RowShares { get; private set; }
public ComponentBatch? ActiveTab { get; private set; }
public ComponentBatch? Visible { get; private set; }
public ComponentBatch? GridColumns { get; private set; }

public ContainerBlueprint(ReadOnlySpan<global::Rerun.Net.Blueprint.Components.ContainerKind> container_kind)
{
ContainerKind = ComponentBatch.FromLoggable(container_kind,
new ComponentDescriptor(ArchetypeName, "ContainerBlueprint:container_kind", "rerun.blueprint.components.ContainerKind"));
}

public ContainerBlueprint(params global::Rerun.Net.Blueprint.Components.ContainerKind[] container_kind) : this(container_kind.AsSpan()) { }

public ContainerBlueprint WithDisplayName(ReadOnlySpan<global::Rerun.Net.Components.Name> display_name)
{
DisplayName = ComponentBatch.FromLoggable(display_name,
new ComponentDescriptor(ArchetypeName, "ContainerBlueprint:display_name", "rerun.components.Name"));
return this;
}

public ContainerBlueprint WithDisplayName(params global::Rerun.Net.Components.Name[] display_name) => WithDisplayName(display_name.AsSpan());

public ContainerBlueprint WithContents(ReadOnlySpan<global::Rerun.Net.Blueprint.Components.IncludedContent> contents)
{
Contents = ComponentBatch.FromLoggable(contents,
new ComponentDescriptor(ArchetypeName, "ContainerBlueprint:contents", "rerun.blueprint.components.IncludedContent"));
return this;
}

public ContainerBlueprint WithContents(params global::Rerun.Net.Blueprint.Components.IncludedContent[] contents) => WithContents(contents.AsSpan());

public ContainerBlueprint WithColShares(ReadOnlySpan<global::Rerun.Net.Blueprint.Components.ColumnShare> col_shares)
{
ColShares = ComponentBatch.FromLoggable(col_shares,
new ComponentDescriptor(ArchetypeName, "ContainerBlueprint:col_shares", "rerun.blueprint.components.ColumnShare"));
return this;
}

public ContainerBlueprint WithColShares(params global::Rerun.Net.Blueprint.Components.ColumnShare[] col_shares) => WithColShares(col_shares.AsSpan());

public ContainerBlueprint WithRowShares(ReadOnlySpan<global::Rerun.Net.Blueprint.Components.RowShare> row_shares)
{
RowShares = ComponentBatch.FromLoggable(row_shares,
new ComponentDescriptor(ArchetypeName, "ContainerBlueprint:row_shares", "rerun.blueprint.components.RowShare"));
return this;
}

public ContainerBlueprint WithRowShares(params global::Rerun.Net.Blueprint.Components.RowShare[] row_shares) => WithRowShares(row_shares.AsSpan());

public ContainerBlueprint WithActiveTab(ReadOnlySpan<global::Rerun.Net.Blueprint.Components.ActiveTab> active_tab)
{
ActiveTab = ComponentBatch.FromLoggable(active_tab,
new ComponentDescriptor(ArchetypeName, "ContainerBlueprint:active_tab", "rerun.blueprint.components.ActiveTab"));
return this;
}

public ContainerBlueprint WithActiveTab(params global::Rerun.Net.Blueprint.Components.ActiveTab[] active_tab) => WithActiveTab(active_tab.AsSpan());

public ContainerBlueprint WithVisible(ReadOnlySpan<global::Rerun.Net.Components.Visible> visible)
{
Visible = ComponentBatch.FromLoggable(visible,
new ComponentDescriptor(ArchetypeName, "ContainerBlueprint:visible", "rerun.components.Visible"));
return this;
}

public ContainerBlueprint WithVisible(params global::Rerun.Net.Components.Visible[] visible) => WithVisible(visible.AsSpan());

public ContainerBlueprint WithGridColumns(ReadOnlySpan<global::Rerun.Net.Blueprint.Components.GridColumns> grid_columns)
{
GridColumns = ComponentBatch.FromLoggable(grid_columns,
new ComponentDescriptor(ArchetypeName, "ContainerBlueprint:grid_columns", "rerun.blueprint.components.GridColumns"));
return this;
}

public ContainerBlueprint WithGridColumns(params global::Rerun.Net.Blueprint.Components.GridColumns[] grid_columns) => WithGridColumns(grid_columns.AsSpan());

/// <summary>Create an empty ContainerBlueprint for partial updates. Use With*() to set fields.</summary>
public static ContainerBlueprint UpdateFields() => new();

/// <summary>Clear all fields, then use With*() to set specific ones.</summary>
public static ContainerBlueprint ClearFields() => new();

private ContainerBlueprint() { }

public IReadOnlyList<ComponentBatch> AsBatches()
{
var batches = new List<ComponentBatch>(8);
batches.Add(ContainerKind);
if (DisplayName != null) batches.Add(DisplayName);
if (Contents != null) batches.Add(Contents);
if (ColShares != null) batches.Add(ColShares);
if (RowShares != null) batches.Add(RowShares);
if (ActiveTab != null) batches.Add(ActiveTab);
if (Visible != null) batches.Add(Visible);
if (GridColumns != null) batches.Add(GridColumns);
return batches;
}
}
Loading
Loading