Internal doc reshuffling. The generated .svg files will return soon, generated by a GitHub Action.
PiperOrigin-RevId: 441201617
diff --git a/docs/wrapping-upb.md b/docs/wrapping-upb.md
index ad35428..10a2c6d 100644
--- a/docs/wrapping-upb.md
+++ b/docs/wrapping-upb.md
@@ -180,18 +180,40 @@
fields), and maps. A protobuf message is a hierarchical tree of these objects.
For example, a relatively simple protobuf tree might look something like this:
-<div align=center>
-<img src='wrapping-upb/1.svg'/>
-</div>
+```dot {align="center"}
+digraph G {
+ rankdir=LR;
+ newrank=true;
+ node [style="rounded,filled" shape=box colorscheme=accent8 fillcolor=1, ordering=out]
+ upb_msg -> upb_msg2;
+ upb_msg -> upb_array;
+ upb_msg [label="upb Message" fillcolor=1]
+ upb_msg2 [label="upb Message"];
+ upb_array [label="upb Array"]
+}
+```
All upb objects are allocated from an arena. An arena lets you allocate objects
individually, but you cannot free individual objects; you can only free the arena
as a whole. When the arena is freed, all of the individual objects allocated
from that arena are freed together.
-<div align=center>
-<img src='wrapping-upb/2.svg'/>
-</div>
+```dot {align="center"}
+digraph G {
+ rankdir=LR;
+ newrank=true;
+ subgraph cluster_0 {
+ label = "upb Arena"
+ graph[style="rounded,filled" fillcolor=gray]
+ node [style="rounded,filled" shape=box colorscheme=accent8 fillcolor=1, ordering=out]
+ upb_msg -> upb_array;
+ upb_msg -> upb_msg2;
+ upb_msg [label="upb Message" fillcolor=1]
+ upb_msg2 [label="upb Message"];
+ upb_array [label="upb Array"];
+ }
+}
+```
In simple cases, the entire tree of objects will all live in a single arena.
This has the nice property that there cannot be any dangling pointers between
@@ -201,9 +223,30 @@
not they are in the same arena. The library does not know or care what arenas
the objects are in when you create links between them.
-<div align=center>
-<img src='wrapping-upb/3.svg'/>
-</div>
+```dot {align="center"}
+digraph G {
+ rankdir=LR;
+ newrank=true;
+ subgraph cluster_0 {
+ label = "upb Arena 1"
+ graph[style="rounded,filled" fillcolor=gray]
+ node [style="rounded,filled" shape=box colorscheme=accent8 fillcolor=1, ordering=out]
+ upb_msg -> upb_array;
+ upb_msg -> upb_msg2;
+ upb_msg [label="upb Message 1" fillcolor=1]
+ upb_msg2 [label="upb Message 2"];
+ upb_array [label="upb Array"];
+ }
+ subgraph cluster_1 {
+ label = "upb Arena 2"
+ graph[style="rounded,filled" fillcolor=gray]
+ node [style="rounded,filled" shape=box colorscheme=accent8 fillcolor=1]
+ upb_msg3;
+ }
+ upb_msg2 -> upb_msg3;
+ upb_msg3 [label="upb Message 3"];
+}
+```
When objects are on separate arenas, it is the user's responsibility to ensure
that there are no dangling pointers. In the example above, this means Arena 2
@@ -222,9 +265,78 @@
For this example, we will assume we are wrapping upb in Python:
-<div align=center>
-<img src='wrapping-upb/4.svg'/>
-</div>
+```dot {align="center"}
+digraph G {
+ rankdir=LR;
+ newrank=true;
+ compound=true;
+
+ subgraph cluster_1 {
+ label = "upb Arena"
+ graph[style="rounded,filled" fillcolor=gray]
+ node [style="rounded,filled" shape=box colorscheme=accent8 fillcolor=1, ordering=out]
+ upb_msg -> upb_array [style=dashed];
+ upb_msg -> upb_msg2 [style=dashed];
+ upb_msg [label="upb Message" fillcolor=1]
+ upb_msg2 [label="upb Message"];
+ upb_array [label="upb Array"]
+ dummy [style=invis]
+ }
+ subgraph cluster_python {
+ node [style="rounded,filled" shape=box colorscheme=accent8 fillcolor=2]
+ peripheries=0
+ py_upb_msg [label="Python Message"];
+ py_upb_msg2 [label="Python Message"];
+ py_upb_arena [label="Python Arena"];
+ }
+ py_upb_msg -> upb_msg [style=dashed];
+ py_upb_msg2->upb_msg2 [style=dashed];
+ py_upb_msg2 -> py_upb_arena [color=springgreen4];
+ py_upb_msg -> py_upb_arena [color=springgreen4];
+ py_upb_arena -> dummy [lhead=cluster_1, color=red];
+ {
+ rank=same;
+ upb_msg;
+ py_upb_msg;
+ }
+ {
+ rank=same;
+ upb_array;
+ upb_msg2;
+ py_upb_msg2;
+ }
+ { rank=same;
+ dummy;
+ py_upb_arena;
+ }
+ dummy->upb_array [style=invis];
+ dummy->upb_msg2 [style=invis];
+
+ subgraph cluster_01 {
+ node [shape=plaintext]
+ peripheries=0
+ key [label=<<table border="0" cellpadding="2" cellspacing="0" cellborder="0">
+ <tr><td align="right" port="i1">raw ptr</td></tr>
+ <tr><td align="right" port="i2">unique ptr</td></tr>
+ <tr><td align="right" port="i3">shared (GC) ptr</td></tr>
+ </table>>]
+ key2 [label=<<table border="0" cellpadding="2" cellspacing="0" cellborder="0">
+ <tr><td port="i1"> </td></tr>
+ <tr><td port="i2"> </td></tr>
+ <tr><td port="i3"> </td></tr>
+ </table>>]
+ key:i1:e -> key2:i1:w [style=dashed]
+ key:i2:e -> key2:i2:w [color=red]
+ key:i3:e -> key2:i3:w [color=springgreen4]
+ }
+ key2:i1:w -> upb_msg [style=invis];
+ {
+ rank=same;
+ key;
+ upb_msg;
+ }
+}
+```
In this example we have three different kinds of pointers: