Commit Graph

6751 Commits

Author SHA1 Message Date
Paul Yang
455440fc47
Add binary conformance test for enum fields. (#6434)
* Add binary conformance test for enum fields.

* Add failed conformance test to js failure list
2019-07-23 15:07:26 -07:00
rmstar
2c76c2c413 Add podspec for C++ (#6404) 2019-07-23 13:51:21 -07:00
Paul Yang
29e4fadbfb
Add binary conformance test case for bytes field (#6428)
* Add binary conformance test case for bytes field

* Add failed conformance test to php's failure list
2019-07-23 12:42:30 -07:00
Joe Bolinger
180d3e3287 fix null terminated string (#6370) 2019-07-22 17:11:58 -07:00
Paul Yang
33af06edbb
Drop building wheel for python 3.4 (#6406) (#6426)
https://github.com/matthew-brett/multibuild/pull/240
2019-07-22 16:52:46 -07:00
Paul Yang
eef87dd138
Add conformance test for binary string (#6415)
* Add conformance test for binary string

* Add failing tests to php failure list
2019-07-22 16:52:31 -07:00
Paul Yang
d28cf02ee0 Drop building wheel for python 3.4 (#6406)
https://github.com/matthew-brett/multibuild/pull/240
2019-07-22 14:56:18 -07:00
Wang Kirin
1bbae02cff fix typo in io/printer.h 2019-07-22 13:41:14 -07:00
Sydney Acksman
9857d636fd Fix binary compatibility in FieldCodec factory methods (#6380)
* Fix binary compatibility in FieldCodec factory messages

* Make default value parameter for current factories required

* Route old methods through default value overloads
2019-07-19 16:25:00 -07:00
Leon Barrett
de5d071f44 Fix assignment between Python protobuf Structs (#6377)
Currently, if you access a ListValue from a Struct and attempted to
assign it to another Struct, you would get an exception:

   > s1 = spb.Struct()
   > s1['a'] = [1]
   > s2 = spb.Struct()
   > s2['a'] = s1['a']
   ValueError: Unexpected type

This fixes that case.
2019-07-19 15:47:52 -07:00
Paul Yang
7bff8393ca
Down Integrate to GitHub (#6414)
* Down integrate to GitHub

* Fix broken tests
2019-07-19 14:49:01 -07:00
Adam Cozzette
63d9c1fb95 Updated Bazel test script to use most recent Bazel version (#6413)
I'm not exactly sure why, but this fixes the failing Bazel presubmit
test. Using the most recent version seems like a good idea anyway so
that we can make sure we're compatible with any new Bazel changes.
2019-07-19 12:55:58 -07:00
Thomas Van Lenten
400d3888b9 Revert bad change to objc conformance test in #6199
Since true for objc is external, changes should always start on the github
side, so the fact that something got pushed out is a sign something was
broken in the process.
2019-07-19 10:14:53 -04:00
Yannic Bonenberger
a03d332aca [bazel] Use strip_import_prefix for wkp instead of copying them 2019-07-18 13:59:40 -07:00
Adam Cozzette
582640ef31 Updated cmake path to io_win32.h (#6397)
Fixes #6382.
2019-07-17 15:38:57 -07:00
Adam Liddell
19ca196e4d Remove zlib copts flags when on Windows 2019-07-17 13:17:02 -07:00
Po-Chuan Hsieh
640b932cf8 Fix test on FreeBSD
google/protobuf/testing/zcgzip.cc:61:25: error: unknown type name 'STDOUT_FILENO'
  FileOutputStream fout(STDOUT_FILENO);
                        ^
google/protobuf/testing/zcgzip.cc:61:24: warning: parentheses were disambiguated as a function declaration [-Wvexing-parse]
  FileOutputStream fout(STDOUT_FILENO);
                       ^~~~~~~~~~~~~~~
google/protobuf/testing/zcgzip.cc:61:25: note: add a pair of parentheses to declare a variable
  FileOutputStream fout(STDOUT_FILENO);
                        ^
                        (
google/protobuf/testing/zcgzip.cc:75:20: error: use of undeclared identifier 'STDIN_FILENO'
    readlen = read(STDIN_FILENO, outptr, outlen);
                   ^
1 warning and 2 errors generated.
gmake[3]: *** [Makefile:4009: google/protobuf/testing/zcgzip.o] Error 1

google/protobuf/testing/zcgunzip.cc:62:23: error: unknown type name 'STDIN_FILENO'
  FileInputStream fin(STDIN_FILENO);
                      ^
google/protobuf/testing/zcgunzip.cc:62:22: warning: parentheses were disambiguated as a function declaration [-Wvexing-parse]
  FileInputStream fin(STDIN_FILENO);
                     ^~~~~~~~~~~~~~
google/protobuf/testing/zcgunzip.cc:62:23: note: add a pair of parentheses to declare a variable
  FileInputStream fin(STDIN_FILENO);
                      ^
                      (
google/protobuf/testing/zcgunzip.cc:74:23: error: use of undeclared identifier 'STDOUT_FILENO'
      int err = write(STDOUT_FILENO, inptr, inlen);
                      ^
1 warning and 2 errors generated.
gmake[3]: *** [Makefile:4009: google/protobuf/testing/zcgunzip.o] Error 1

Reference:	https://bugs.FreeBSD.org/bugzilla/show_bug.cgi?id=215346
		https://svnweb.FreeBSD.org/changeset/ports/428734
2019-07-17 13:02:54 -07:00
Seth Greenstein
744e799bda Change "python" to "python_headers" in comment (#6046)
Following the instructions as is does not work, the new_local_repository rule needs to be called "python_headers"
2019-07-15 16:40:57 -07:00
Adam Liddell
a74c43bbd9 Fix usage of six in //:protobuf_python rule and add import (#6310)
* Fix reference to six in //:protobuf_python rule

* Add six to protobuf_deps.bzl

* Use six archive directly as repo @six
2019-07-15 16:35:19 -07:00
Hao Nguyen
f2cfe2c834
Merge pull request #6363 from toasttab/master
Requesting extension id 1072
2019-07-11 18:22:00 -06:00
Hao Nguyen
fc9fd4d437
Merge pull request #6331 from elharo/patch-2
Update guava
2019-07-10 13:55:11 -06:00
Hao Nguyen
a387c1025e
Merge pull request #6330 from elharo/patch-1
Update gson
2019-07-10 13:48:14 -06:00
Hao Nguyen
90bb99c872
Merge pull request #6348 from elharo/patch-4
Update version in README
2019-07-10 12:43:09 -06:00
Chris Gaffney
7da7bec441 ruby: Improve performance of Google::Protobuf::Timestamp#to_time (#6360)
This changes to_time to use Ruby's built in Time.at with nanos support
rather than calculating a float and passing it to Time.at. The new
version runs about 3 times faster than the original version and
allocates fewer objects.

Warming up --------------------------------------
    protobuf#to_time    57.296k i/100ms
      faster#to_time   133.229k i/100ms
Calculating -------------------------------------
    protobuf#to_time    635.361k (± 2.1%) i/s -      3.209M in   5.052169s
      faster#to_time      1.873M (± 3.3%) i/s -      9.459M in   5.055169s

Comparison:
      faster#to_time:  1873368.8 i/s
    protobuf#to_time:   635361.4 i/s - 2.95x  slower

Calculating -------------------------------------
    protobuf#to_time   326.000  memsize (   126.000  retained)
                         7.000  objects (     2.000  retained)
                         0.000  strings (     0.000  retained)
      faster#to_time    86.000  memsize (     0.000  retained)
                         1.000  objects (     0.000  retained)
                         0.000  strings (     0.000  retained)

Comparison:
      faster#to_time:         86 allocated
    protobuf#to_time:        326 allocated - 3.79x more
2019-07-10 09:41:11 -07:00
Ben Gordon
f5362e11fd
Requesting extension id 1072
This library supports an idiomatic proto3 protobuf generator for kotlin.
The library will be open sourced by Toast Inc under the Apache2 license, and is currently used in production at Toast.
The following is the readme.md that will be released with the code by the end of Q4 2019.

Supports only the Protocol Buffers language version 3.

#### Features
- Clean data class generation
- Oneof types handled as sealed classes
- JavaDoc comments on generated code
- Deprecation option pass-through to Kotlin's `@Deprecated` annotation
- Protokt-specific options: non-null types, wrapper types, interface implementation,
and more
- Tight integration with Protobuf's Java library: compatibility with its well-known
types and usage of CodedInputStream and CodedOutputStream for best performance

#### Not yet implemented
- Kotlin native support
- Kotlin JS support
- Support for gRPC service generation
- Protobuf JSON support

See examples in [protokt-testing](https://github.com/toasttab/protokt/tree/master/protokt-testing).

### Generated Code
Generated code is placed in `<buildDir>/generated-sources/main/protokt`.

A simple example:
```proto
syntax = "proto3";

package com.protokt.sample;

message Sample {
  string sample_field = 1;
}
```

will produce:
```kotlin
/*
 * Generated by protokt. Do not modify.
 */
package com.protokt.sample

import com.toasttab.protokt.rt.*

data class Sample(
    val sampleField: String,
    val unknown: Map<Int, Unknown> = emptyMap()
) : KtMessage {
    @Suppress("UNUSED")
    constructor(
        sampleField: String = ""
    ) : this(
        sampleField,
        emptyMap()
    )

    override val messageSize by lazy { sizeof() }

    override fun serialize(serializer: KtMessageSerializer) {
        if (sampleField.isNotEmpty()) {
            serializer.write(Tag(10)).write(sampleField)
        }
        if (unknown.isNotEmpty()) {
            serializer.writeUnknown(unknown)
        }
    }

    private fun sizeof(): Int {
        var res = 0
        if (sampleField.isNotEmpty()) {
            res += sizeof(Tag(1)) + sizeof(sampleField)
        }
        res += unknown.entries.sumBy { it.value.sizeof() }
        return res
    }

    companion object Deserializer : KtDeserializer<Sample> {
        override fun deserialize(deserializer: KtMessageDeserializer): Sample {
            var sampleField = ""
            val unknown = mutableMapOf<Int, Unknown>()
            while (true) {
                when (deserializer.readTag()) {
                    0 ->
                        return Sample(
                            sampleField,
                            unknown
                        )
                    10 -> sampleField = deserializer.readString()
                    else -> {
                        val unk = deserializer.readUnknown()
                        unknown[unk.fieldNum] = unknown[unk.fieldNum].let {
                            when (it) {
                                null -> unk
                                else ->
                                    when (val v = it.value) {
                                        is ListVal ->
                                            Unknown(unk.fieldNum, ListVal(v.value + unk.value))
                                        else ->
                                            Unknown(unk.fieldNum, ListVal(listOf(v, unk.value)))
                                    }
                            }
                        }
                    }
                }
            }
        }
    }
}
```

#### Runtime Notes
##### Package
The Kotlin package of a generated file can be overridden from protobuf package with the `(protokt).package` option:
```proto
syntax = "proto3";

import "protokt.proto";

package com.example;

option (protokt).package = "com.package";
```

##### Message
Each protokt message implements the `KtMessage` interface. `KtMessage` defines the `serialize()`
method and its overloads which can serialize to a byte array, a `KtMessageSerializer`, or on the JVM,
an `OutputStream`.

Each protokt message has a companion object `Deserializer` that implements the `KtDeserializer`
interface, which provides the `deserialize()` method and its overloads to construct an
instance of the message from a byte array, a Java InputStream, or others.

In order to enjoy the full benefits of Kotlin data classes, byte arrays are wrapped in the
protokt `Bytes` class, which provides appropriate `equals()` and `hashCode()` implementations.

##### Enums
Enum fields are generated as data classes with a single integer field. Kotlin enum classes are
closed and cannot retain unknown values, and protobuf requires that unknown enum values are
preserved for reserialization. This compromise exposes a constructor taking an integer, but the
`from(value: Int)` on an enum's `Deserializer` should be preferred as it avoids instantiation
when possible.


Other notes:
- `optimize_for` is ignored.
- `repeated` fields are deserialized to Lists.
- `map` fields are deserialized to Maps.
- `oneof` fields are represented as data class subtypes of a sealed base class with a single property.

### Extensions
See examples of each option in the [protokt-options](https://github.com/toasttab/protokt/tree/master/protokt-testing/protokt-options/src/main/proto)
module. All protokt-specific options require importing `protokt.proto` in the protocol file.
#### Wrapper Types
Sometimes a field on a protobuf message corresponds to a concrete nonprimitive type. In
standard protobuf the user would be responsible for this extra transformation, but the
protokt wrapper type option allows specification of a converter that will automatically
encode and decode custom types to protobuf primitives and well-known types. Some standard
types are implemented in
[protokt-extensions](https://github.com/toasttab/protokt/tree/master/protokt-extensions/src/main/kotlin/com/toasttab/protokt/ext).

Wrap a field by invoking the `(protokt_property).wrap` option:
```proto
message DateWrapperMessage {
  int64 date = 1 [
    (protokt_property).wrap = "java.util.Date"
  ];
}
```

Converters implement the `Converter` interface:
```kotlin
interface Converter<S: Any, T: Any> {
    val wrapper: KClass<S>

    fun wrap(unwrapped: T): S

    fun unwrap(wrapped: S): T
}
```

and protokt will reference the converter's methods to wrap and unwrap from protobuf primitives:
```kotlin
object DateConverter : Converter<Date, Long> {
    override val wrapper = Date::class

    override fun wrap(unwrapped: Long) =
        Date(unwrapped)

    override fun unwrap(wrapped: Date) =
        wrapped.time
}
```

```kotlin
data class WrapperModel(
    val date: java.util.Date,
    ...
) : KtMessage {
    ...
    override fun serialize(serializer: KtMessageSerializer) {
        serializer.write(Tag(10)).write(Int64(DateConverter.unwrap(date)))
        ...
    }

    override fun deserialize(deserializer: KtMessageDeserializer): WrapperModel {
        var date = 0L

        while (true) {
            when (deserializer.readTag()) {
                0 ->
                    return WrapperModel(
                        DateConverter.wrap(date),
                        ...
                    )
                ...
            }
        }
    }
}
```

Converters can also implement the `OptimizedSizeofConverter` interface adding `sizeof()`,
which allows them to optimize the calculation of the wrapper's size rather than unwrap
the object twice. For example, a UUID is always 16 bytes:

```kotlin
object UuidConverter : OptimizedSizeofConverter<UUID, ByteArray> {
    override val wrapper = UUID::class

    private val sizeofProxy = ByteArray(16)

    override fun sizeof(wrapped: UUID) =
        sizeof(sizeofProxy)

    override fun wrap(unwrapped: ByteArray): UUID {
        require(unwrapped.size == 16) {
            "input must have size 16; had ${unwrapped.size}"
        }

        return ByteBuffer.wrap(unwrapped)
            .run { UUID(long, long) }
    }

    override fun unwrap(wrapped: UUID) =
        ByteBuffer.allocate(16)
            .putLong(wrapped.mostSignificantBits)
            .putLong(wrapped.leastSignificantBits)
            .array()
}
```

Rather than convert a UUID to a byte array both for size calculation and for serialization
(which is what a naïve implementation would do), UuidConverter always returns the size of a
constant 16-byte array.

If the wrapper type is in the same package as the generated protobuf message, then it
does not need a fully-qualified name. Custom wrapper type converters can be in the same module as
protobuf types that reference them. In order to use any wrapper type defined in
`protokt-extensions`, the module must be included as a dependency:

```groovy
dependencies {
    implementation 'com.toasttab.protokt:protokt-extensions:0.0.3'
}
```

#### Interface implementation
To avoid the need to create domain-specific objects from protobuf messages you can declare
that a protobuf message implements a custom interface with properties and default methods.

```kotlin
package com.protokt.sample

interface Model {
    val id: String
}
```

```proto
package com.protokt.sample;

message ImplementsSampleMessage {
  option (protokt_class).implements = "Model";

  string id = 1;
}
```

If the wrapper interface is in the same package as the generated protobuf message, then it
does not need a fully-qualified name. Wrapper interfaces cannot be used by protobuf messages
in the same module that defines them; the dependency must be declared with`protoktExtensions`
in `build.gradle`:

```groovy
dependencies {
    protoktExtensions project(':api-module')
}
```

#### Nonnull fields
If there is a message that has no meaning whatsoever when a particular field is missing, you
can emulate proto2's `required` key word by using the `(protokt_oneof).non_null` option:

```proto
message Sample {
}

message NonNullSampleMessage {
  Sample non_null_sample = 1 [
    (protokt_property).non_null = true
  ];
}
```

Generated code will not have a nullable type so the field can be referenced without using
Kotlin's `!!`.

Oneof fields can also be declared non-null:

```proto
message NonNullSampleMessage {
  oneof non_null_oneof {
    option (protokt_oneof).non_null = true;

    string message = 2;
  }
}
```

Note that deserialization of a message with a non-nullable field will fail if the
message being decoded does not contain an instance of the required field.

#### BytesSlice
When reading messages that contain other serialized messages as `bytes` fields, protokt can
keep a reference to the originating byte array to prevent a large copy operation on
deserialization. This can be desirable when the wrapping message is a thin metadata shim and
doesn't include much memory overhead:

```proto
message SliceModel {
  int64 version = 1;

  bytes encoded_message = 2 [
    (protokt_property).bytes_slice = true
  ];
}
```

### Usage

#### Gradle

```groovy
buildscript {
    dependencies {
        classpath "com.toasttab.protokt:protokt-gradle-plugin:0.0.3"
    }
}

apply plugin: 'com.toasttab.protokt'
```

This will automatically download and install protokt, apply the Google protobuf plugin,
and configure all the necessary boilerplate. By default it will also add `protokt-runtime`
to the api scope of the project, and `protobuf-java` to the implementation scope.

If your project is pure Kotlin you may run into the following error:

```
Execution failed for task ':compileJava'.
> error: no source files
```

To work around it, disable all `JavaCompile` tasks in the project:

```groovy
tasks.withType(JavaCompile) {
    enabled = false
}
```

or:
```groovy
compileJava.enabled = false
```

#### Command line code generation

```bash
protokt-codegen$ ./gradlew assemble [OR ./gradlew installDist]

protokt-codegen$ ./run-protokt.sh -h

protokt-codegen$ ./run-protokt.sh \
  -out=../kotlin \
  -pkg=com.toasttab.protokt.conformance \
  -file=conformance.proto \
  -cp=../build/libs/protokt-codegen-0.0.3-SNAPSHOT-all.jar \
  -plugin=../bin/protokt.sh
```

### Contribution
To enable rapid development of the code generator, the protobuf conformance tests have been 
compiled and included in the protokt-testing project. They run on Mac OS 10.14+ and Ubuntu
16.04 x86-64.

Publish the plugin to the integration repository:
```bash
protokt$ ./gradlew publishToIntegrationRepository
```

Then run the tests from `protokt-testing`:
```bash
protokt-testing$ ./gradlew protokt-conformance-tests:test
```

All integration tests can be run with:
```
protokt-testing$ ./gradlew test
```
2019-07-10 09:58:38 -04:00
Ben Bader
de57caa1fd Fix unused-parameter clang warnings in arena.h and map_type_handler.h 2019-07-09 11:22:38 -07:00
Ben Bader
56e7bdf278 Fix builtin_atomics check in CMakeLists.txt 2019-07-08 20:30:04 -07:00
Yilun Chong
2d61b9edd9
Merge pull request #6346 from phanirithvij/patch-1
fix dart example readme typo
2019-07-08 12:00:57 -07:00
Yilun Chong
3a10cf1557
Merge pull request #6343 from johndpope/patch-1
allow copy and paste from readme
2019-07-08 12:00:31 -07:00
Yilun Chong
a96f3af2bc
Merge pull request #6323 from cushon/toolchain
Use proto_library in proto_lang_toolchain.blacklisted_protos
2019-07-08 10:21:19 -07:00
Elliotte Rusty Harold
4b21abdef3
Update version in README
to 3.8.0
2019-07-08 10:12:19 -04:00
Phani Rithvij
39c6b58a9b
fix dart example readme typo 2019-07-07 09:10:41 +05:30
John D. Pope
c5fb586fc9
allow copy and paste from readme
spare people the time deleting $ from text.
2019-07-05 10:35:51 +10:00
boscosiu
55ed1d427c link libatomic on systems without adequate builtin atomics 2019-07-03 15:32:29 -07:00
Asra Ali
de3e728c69 fix ubsan warning
Signed-off-by: Asra Ali <asraa@google.com>
2019-07-03 15:21:15 -07:00
Elliotte Rusty Harold
17eca42734
Update guava 2019-07-02 12:03:34 -04:00
Elliotte Rusty Harold
6ae7391b1f
Update gson 2019-07-02 12:02:35 -04:00
Tomo Suzuki
8b09686253 Added linkage monitor badge (#6327) 2019-07-01 14:59:15 -07:00
Liam Miller-Cushon
7b28278c7d Use proto_library in proto_lang_toolchain.blacklisted_protos
Support for using proto_library in this attribute was added in:
a5ee2c4d97

Legacy support for using .proto files will be removed in a future
version of Bazel.
2019-07-01 14:15:32 -07:00
Liam Miller-Cushon
2b857d0078 Format with buildifier 2019-07-01 14:10:31 -07:00
Tomo Suzuki
bedef1ede2 Kokoro: run Linkage Monitor on presubmit (#6318)
* adding mvn install with snapshot version

* Added linkage monitor

* comment

* space

* Added comment

* Maven to use $HOME/.m2

* setting MVN
2019-07-01 14:03:04 -07:00
Paul Yang
ee5f29f46e
Merge pull request #6306 from suztomo/linkage-monitor
Setting up JDK8 for Kokoro jobs
2019-06-27 16:08:09 -07:00
Tomo Suzuki
c9212beed2 continuous.cfg 2019-06-27 15:19:17 -04:00
Tomo Suzuki
3507314d67 build.sh to use linux/dockerfile/test/java_stretch 2019-06-27 15:15:49 -04:00
Tomo Suzuki
89fbae62f4 java_stretch 2019-06-27 15:12:39 -04:00
Tomo Suzuki
8886454fc0 uncomented jdk7 2019-06-27 14:22:21 -04:00
Tomo Suzuki
699bab2e2d reverted 64-bit/Dockerfile 2019-06-27 14:20:41 -04:00
Hao Nguyen
f30c68b792
Merge pull request #6231 from ST-DDT/fix-javadoc-warnings
Fix javadoc warnings in generated files
2019-06-27 10:46:21 -07:00
Tomo Suzuki
30673ff200 backslash at the end of the comment 2019-06-27 08:45:04 -04:00
Hao Nguyen
de5a1fabab
Merge pull request #6308 from haon4/201906261101
Down integrate to GitHub
2019-06-26 16:39:17 -07:00