Home > other >  How to: ProtoBuf: get the parent message
How to: ProtoBuf: get the parent message

Time:11-23

Given a message (b of type B), nested in another (a of type A); how does one get ‘a’? I was hoping for something like ‘b.getParent()’.

message B { optional string name = 1;  repeated B b = 2; }
message A { optional string name = 1;  repeated B b = 1; }

Here is an example instance of an ‘a’ with textual serialization.

name: "a"
b { name: “foo”
    b { name: “fred”
        b { name: “flintstone” }}}
b { name: “bar” }
b { name: “baz” }

The issue is that I am navigating the collection 'a' with a visitor and I need to be able to reconstruct a full name composed of names of all the ancestors.

Refs:

I am fine with internal representation as I will wrap it in a kotlin extension.

CodePudding user response:

You cannot do this. A B has no need of, or attachment to, an A. If you want to track the parents, you must do so explicitly yourself.

CodePudding user response:

There is no good (efficient) way to initialize a backing data structure.

An alternative approach is for the visitor to maintain an Array rather than just a B. Here is an example:


fun depthFirstVisitor(root: A, fragFilter: (frag: B) -> Boolean): Sequence<Array<B>> {
    return sequence {
        root.fragmentsList.forEach { child ->
            if (fragFilter(child)) {
                yield(arrayOf(child))
                dfs(emptyArray(), child, fragFilter)
            }
        }
    }
}

private suspend fun SequenceScope<Array<B>>.dfs(
    ancestry: Array<B>,
    base: B,
    fragFilter: (frag: B) -> Boolean
) {
    val ancestryNew = ancestry   base
    base.fragmentsList.forEach { child ->
        if (fragFilter(child)) {
            yield(ancestryNew   child)
            dfs(ancestryNew, child, fragFilter)
        }
    }
}

The current B is the last element of the array. I am using an Array because it does not suffer from type erasure like other containers.

  • Related