Discussion:
[capnproto] possible to access MessageBuilder from RootType::Builder?
Liam Staskawicz
2017-11-22 21:10:03 UTC
Permalink
Hello,

Part of my current project provides a mechanism to transmit capnp
messages and I'd like to accept a T::Builder as input, rather than a
MessageBuilder if possible, to help avoid messages of the incorrect type
being sent on a channel.
Is it possible to access the MessageBuilder that a T::Builder is
associated with through the T::Builder? Is there a better way to
approach this issue?
Thanks!
Liam
--
You received this message because you are subscribed to the Google Groups "Cap'n Proto" group.
To unsubscribe from this group and stop receiving emails from it, send an email to capnproto+***@googlegroups.com.
Visit this group at https://groups.google.com/group/capnproto.
'Kenton Varda' via Cap'n Proto
2017-11-22 22:53:40 UTC
Permalink
Hi Liam,

Currently there's no way to do this.

But I think it would lead to a different kind of type unsafety anyway: If
you accept a T::Builder, the implication is that it doesn't need to be the
root builder of the message. If someone passed an inner object, or an
orphan, what should happen?

What I'd suggest instead is that you encapsulate MessageBuilder into your
own API, such that people can only construct a MessageBuilder of the right
type. Two ways you might do that:

1) You could define a type `FooMessage` which privately contains a
MallocMessageBuilder and which has a getRoot() method that only returns the
appropriate builder type. Then have your project require a `FooMessage`
instead of a `MesasgeBuilder`. If you have a lot of root types, you could
of course make this a template.

template <typename T>
class TypedMessage {
public:
typename T::Builder getRoot() { return inner.getRoot<T>(); }

private:
capnp::MallocMessageBuilder inner;
};

2) If your framework controls the scope in which the message is supposed to
be constructed (like, your framework calls "up" to the application to
request a message), then it could allocate the MessageBuilder internally
and pass the T::Builder up to be filled in, so the app never sees the
MessageBuilder. This is what Cap'n Proto RPC does, for example. This has
the neat advantage that your framework can play with message allocation
strategies. E.g. Cap'n Proto RPC aims to be able to allocate messages
directly inside a shared memory segment, if using a shared memory
transport, without the application knowing that this is the case.

-Kenton
Post by Liam Staskawicz
Hello,
Part of my current project provides a mechanism to transmit capnp messages
and I'd like to accept a T::Builder as input, rather than a MessageBuilder
if possible, to help avoid messages of the incorrect type being sent on a
channel.
Is it possible to access the MessageBuilder that a T::Builder is
associated with through the T::Builder? Is there a better way to approach
this issue?
Thanks!
Liam
--
You received this message because you are subscribed to the Google Groups
"Cap'n Proto" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at https://groups.google.com/group/capnproto.
--
You received this message because you are subscribed to the Google Groups "Cap'n Proto" group.
To unsubscribe from this group and stop receiving emails from it, send an email to capnproto+***@googlegroups.com.
Visit this group at https://groups.google.com/group/capnproto.
Liam Staskawicz
2017-11-23 00:37:04 UTC
Permalink
That makes sense and should work for my case - thanks as always for the
quick and comprehensive answer, Kenton.
Post by 'Kenton Varda' via Cap'n Proto
Hi Liam,
Currently there's no way to do this.
If you accept a T::Builder, the implication is that it doesn't need to
be the root builder of the message. If someone passed an inner object,
or an orphan, what should happen?>
What I'd suggest instead is that you encapsulate MessageBuilder into
your own API, such that people can only construct a MessageBuilder of
the right type. Two ways you might do that:>
1) You could define a type `FooMessage` which privately contains a
MallocMessageBuilder and which has a getRoot() method that only
returns the appropriate builder type. Then have your project
require a `FooMessage` instead of a `MesasgeBuilder`. If you have a
lot of root types, you could of course make this a template.>
template <typename T>
class TypedMessage {
typename T::Builder getRoot() { return inner.getRoot<T>(); }
capnp::MallocMessageBuilder inner;
};
2) If your framework controls the scope in which the message is
supposed to be constructed (like, your framework calls "up" to the
application to request a message), then it could allocate the
MessageBuilder internally and pass the T::Builder up to be filled
in, so the app never sees the MessageBuilder. This is what Cap'n
Proto RPC does, for example. This has the neat advantage that your
framework can play with message allocation strategies. E.g. Cap'n
Proto RPC aims to be able to allocate messages directly inside a
shared memory segment, if using a shared memory transport, without
the application knowing that this is the case.>
-Kenton
On Wed, Nov 22, 2017 at 1:10 PM, Liam Staskawicz
Post by Liam Staskawicz
Hello,
Part of my current project provides a mechanism to transmit capnp
messages and I'd like to accept a T::Builder as input, rather than a
MessageBuilder if possible, to help avoid messages of the incorrect
type being sent on a channel.>>
Is it possible to access the MessageBuilder that a T::Builder is
associated with through the T::Builder? Is there a better way to
approach this issue?>>
Thanks!
Liam
--
You received this message because you are subscribed to the Google
Groups "Cap'n Proto" group. To unsubscribe from this group and stop
receiving emails from it, send an email to
https://groups.google.com/group/capnproto.
--
You received this message because you are subscribed to the Google Groups "Cap'n Proto" group.
To unsubscribe from this group and stop receiving emails from it, send an email to capnproto+***@googlegroups.com.
Visit this group at https://groups.google.com/group/capnproto.
Loading...