capnproto / capnproto-java

Cap'n Proto in pure Java
Other
390 stars 86 forks source link

Unable to set alternative union member that is a List #12

Open velvia opened 9 years ago

velvia commented 9 years ago

I have the following struct:

struct NaMask {
  union {
    allZeroes @0 :Void;            # every value is available
    simpleBitMask @1 :List(Bool);
    allOnes @2 :Void;              # no value is available / empty
  }
}

I can set it to allOnes:

scala> res2.setAllOnes(org.capnproto.Void.VOID)

scala> res2.which
res20: org.velvia.CapnColumn.NaMask.Which = ALL_ONES

I can initialize the member that is a List(Bool):

scala> res2.initSimpleBitMask(5)
res8: org.capnproto.PrimitiveList.Boolean.Builder = org.capnproto.PrimitiveList$Boolean$Builder@7f0c715e

scala> res8.set(1, true)

scala> res8.set(2, true)

However, I cannot set it:

scala> res2.setSimpleBitMask(res8)
<console>:14: error: type mismatch;
 found   : org.capnproto.PrimitiveList.Boolean.Builder
 required: org.capnproto.PrimitiveList.Boolean.Reader
              res2.setSimpleBitMask(res8)
                                    ^

How do I get a PrimitiveList.Boolean.Reader out of the Builder?

Also, you appear to be able to call set on the PrimitiveList.Boolean.Builder on an index higher than the size, and no error or exception is thrown.

dwrensha commented 9 years ago

How do I get a PrimitiveList.Boolean.Reader out of the Builder?

Ah, looks like we need to add asReader() methods to ListBuilders.

Also, you appear to be able to call set on the PrimitiveList.Boolean.Builder on an index higher than the > size, and no error or exception is thrown.

We should add a bounds check. I think an assert would be best, so that it's only active in debug mode.

I'm not sure when I'll get around to adding these things. I'd certainly welcome pull requests in the meantime. :)

velvia commented 9 years ago

BTW, looks like capnproto-rust is very active right now..... would love to try that at some point. :)

On Mon, Jan 5, 2015 at 7:20 PM, David Renshaw notifications@github.com wrote:

How do I get a PrimitiveList.Boolean.Reader out of the Builder?

Ah, looks like we need to add asReader() methods to ListBuilders.

Also, you appear to be able to call set on the PrimitiveList.Boolean.Builder on an index higher than the > size, and no error or exception is thrown.

We should add a bounds check. I think an assert would be best, so that it's only active in debug mode.

I'm not sure when I'll get around to adding these things. I'd certainly welcome pull requests in the meantime. :)

— Reply to this email directly or view it on GitHub https://github.com/dwrensha/capnproto-java/issues/12#issuecomment-68820935 .

The fruit of silence is prayer; the fruit of prayer is faith; the fruit of faith is love; the fruit of love is service; the fruit of service is peace. -- Mother Teresa

dwrensha commented 6 years ago

asReader() methods were added in https://github.com/capnproto/capnproto-java/commit/f4411ba2c73d5250f69a469d52589155926b4bcc

yamass commented 4 years ago

I've got the same problem. I cannot make the builder choose the union alternative that is of type List(struct). See the unit tests below. Note that the problem also occurs when using asReader().

Since this issue (#12) actually discusses multiple problems, should I open a new one for this distinct one?

Model:

struct ClientMessage {
    uuid0 @0 :UInt64;
    uuid1 @1 :UInt64;

    union {
        tv :group {
            x @2 :UInt64;
            y @3 :UInt64;
            z @4 :E;
        }
        data @5 :List(DataFrame);
    }

    enum E {
        e1 @0;
        e2 @1;
    }
}

struct DataFrame {
    timestamp @0 :UInt64;
}

Unit Test:

public class CapnProtoIssue12Test {

    @Test
    public void testUnionWithStructList_writeRead() throws Exception {
        MessageBuilder messageBuilder = new MessageBuilder();
        ClientMessage.Builder clientMessage = messageBuilder.initRoot(ClientMessage.factory);

        StructList.Builder<DataFrame.Builder> dataList = clientMessage.initData(10);
        for (DataFrame.Builder dataFrame : dataList) {
            dataFrame.setTimestamp(123);
        }

        final Path file1 = Files.createTempFile("CapnProtoCopyTest", "");
        try (final FileChannel writeChannel = FileChannel.open(file1, TRUNCATE_EXISTING, WRITE)) {
            Serialize.write(writeChannel, messageBuilder);
        }

        final ClientMessage.Reader clientMessageReader;
        try (final FileChannel readChannel = FileChannel.open(file1, READ)) {
            final MessageReader messageReader = Serialize.read(readChannel);
            clientMessageReader = messageReader.getRoot(ClientMessage.factory);
        }

        Assert.assertTrue(clientMessageReader.isData()); // ===== FAILS =====
    }

    @Test
    public void testUnionWithStructList_usingAsReader() throws Exception {
        MessageBuilder messageBuilder = new MessageBuilder();
        ClientMessage.Builder clientMessage = messageBuilder.initRoot(ClientMessage.factory);

        StructList.Builder<DataFrame.Builder> dataList = clientMessage.initData(10);
        for (DataFrame.Builder dataFrame : dataList) {
            dataFrame.setTimestamp(123);
        }

        Assert.assertTrue(clientMessage.asReader().isData()); // ===== FAILS =====
    }

}