在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称(OpenSource Name):square/wire开源软件地址(OpenSource Url):https://github.com/square/wire开源编程语言(OpenSource Language):Kotlin 60.7%开源软件介绍(OpenSource Introduction):Wire“A man got to have a code!” - Omar Little See the project website for documentation and APIs. As our teams and programs grow, the variety and volume of data also grows. Success will turn your simple data models into complex ones! Whether your application is storing data to disk or transmitting it over a network, the structure and interpretation of that data should be clear. Consumers work best with data they understand! Schemas describe and document data models. If you have data, you should have a schema. Protocol BuffersGoogle's Protocol Buffers are built around a great schema language:
Here's a sample message definition: syntax = "proto3";
package squareup.dinosaurs;
option java_package = "com.squareup.dinosaurs";
import "squareup/geology/period.proto";
message Dinosaur {
// Common name of this dinosaur, like "Stegosaurus".
string name = 1;
// URLs with images of this dinosaur.
repeated string picture_urls = 2;
squareup.geology.Period period = 5;
} And here's an enum definition: syntax = "proto3";
package squareup.geology;
option java_package = "com.squareup.geology";
enum Period {
// 145.5 million years ago — 66.0 million years ago.
CRETACEOUS = 0;
// 201.3 million years ago — 145.0 million years ago.
JURASSIC = 1;
// 252.17 million years ago — 201.3 million years ago.
TRIASSIC = 2;
} This schema language is Protocol Buffers' best feature. You might even use it purely for documentation purposes, such as to describe a JSON API. Protocol Buffers also defines a compact binary encoding of messages that conform to the schema. This
encoding is fast to encode, fast to decode, small to transmit, and small to store. The binary
encoding uses numeric tags from the schema, like the For example, let's encode this dinosaur:
The encoded value is just 15 bytes:
Why Wire?The Protocol Buffers schema language and binary encoding are both defined by Google. Wire is an independent implementation from Square that's specifically designed for Android and Java. For each message type defined in the schema, Wire generates an immutable model class and its builder. The generated code looks like code you'd write by hand: it's documented, formatted, and simple. Wire's APIs should feel at home to programmers who like Effective Java. That said, there are some interesting design decisions in Wire:
Here's the compact generated code for the // Code generated by Wire protocol buffer compiler, do not edit.
// Source: squareup.dinosaurs.Dinosaur in squareup/dinosaurs/dinosaur.proto
package com.squareup.dinosaurs;
import com.squareup.geology.Period;
import com.squareup.wire.Message;
import com.squareup.wire.ProtoAdapter;
import com.squareup.wire.Syntax;
import com.squareup.wire.WireField;
import com.squareup.wire.internal.Internal;
import java.lang.Object;
import java.lang.Override;
import java.lang.String;
import java.util.List;
import okio.ByteString;
public final class Dinosaur extends Message<Dinosaur, Dinosaur.Builder> {
public static final ProtoAdapter<Dinosaur> ADAPTER = ProtoAdapter.newMessageAdapter(Dinosaur.class, "type.googleapis.com/squareup.dinosaurs.Dinosaur", Syntax.PROTO_3);
private static final long serialVersionUID = 0L;
/**
* Common name of this dinosaur, like "Stegosaurus".
*/
@WireField(
tag = 1,
adapter = "com.squareup.wire.ProtoAdapter#STRING",
label = WireField.Label.OMIT_IDENTITY
)
public final String name;
/**
* URLs with images of this dinosaur.
*/
@WireField(
tag = 2,
adapter = "com.squareup.wire.ProtoAdapter#STRING",
label = WireField.Label.REPEATED,
jsonName = "pictureUrls"
)
public final List<String> picture_urls;
@WireField(
tag = 5,
adapter = "com.squareup.geology.Period#ADAPTER",
label = WireField.Label.OMIT_IDENTITY
)
public final Period period;
public Dinosaur(String name, List<String> picture_urls, Period period) {
this(name, picture_urls, period, ByteString.EMPTY);
}
public Dinosaur(String name, List<String> picture_urls, Period period, ByteString unknownFields) {
super(ADAPTER, unknownFields);
if (name == null) {
throw new IllegalArgumentException("name == null");
}
this.name = name;
this.picture_urls = Internal.immutableCopyOf("picture_urls", picture_urls);
if (period == null) {
throw new IllegalArgumentException("period == null");
}
this.period = period;
}
@Override
public Builder newBuilder() {
Builder builder = new Builder();
builder.name = name;
builder.picture_urls = Internal.copyOf(picture_urls);
builder.period = period;
builder.addUnknownFields(unknownFields());
return builder;
}
@Override
public boolean equals(Object other) {
if (other == this) return true;
if (!(other instanceof Dinosaur)) return false;
Dinosaur o = (Dinosaur) other;
return unknownFields().equals(o.unknownFields())
&& Internal.equals(name, o.name)
&& picture_urls.equals(o.picture_urls)
&& Internal.equals(period, o.period);
}
@Override
public int hashCode() {
int result = super.hashCode;
if (result == 0) {
result = unknownFields().hashCode();
result = result * 37 + (name != null ? name.hashCode() : 0);
result = result * 37 + picture_urls.hashCode();
result = result * 37 + (period != null ? period.hashCode() : 0);
super.hashCode = result;
}
return result;
}
public static final class Builder extends Message.Builder<Dinosaur, Builder> {
public String name;
public List<String> picture_urls;
public Period period;
public Builder() {
name = "";
picture_urls = Internal.newMutableList();
period = Period.CRETACEOUS;
}
/**
* Common name of this dinosaur, like "Stegosaurus".
*/
public Builder name(String name) {
this.name = name;
return this;
}
/**
* URLs with images of this dinosaur.
*/
public Builder picture_urls(List<String> picture_urls) {
Internal.checkElementsNotNull(picture_urls);
this.picture_urls = picture_urls;
return this;
}
public Builder period(Period period) {
this.period = period;
return this;
}
@Override
public Dinosaur build() {
return new Dinosaur(name, picture_urls, period, super.buildUnknownFields());
}
}
} The Java code to create and access proto models is compact and readable: Dinosaur stegosaurus = new Dinosaur.Builder()
.name("Stegosaurus")
.period(Period.JURASSIC)
.build();
System.out.println("My favorite dinosaur existed in the " + stegosaurus.period + " period."); Each type has a corresponding Dinosaur stegosaurus = ...
byte[] stegosaurusBytes = Dinosaur.ADAPTER.encode(stegosaurus);
byte[] tyrannosaurusBytes = ...
Dinosaur tyrannosaurus = Dinosaur.ADAPTER.decode(tyrannosaurusBytes); When accessing a field, use Period period = Wire.get(stegosaurus.period, Dinosaur.DEFAULT_PERIOD); This is equivalent to the following:
Wire KotlinSince version 3.0.0, Wire can generate Kotlin code. See Wire Compiler & Gradle Plugin to learn how to configure your build. Kotlin is a pragmatic and expressive programming language that makes it easy to model data. Here's how we used Kotlin to model Protocol Buffers messages:
Here's the same // Code generated by Wire protocol buffer compiler, do not edit.
// Source: squareup.dinosaurs.Dinosaur in squareup/dinosaurs/dinosaur.proto
package com.squareup.dinosaurs
import com.squareup.geology.Period
import com.squareup.wire.FieldEncoding
import com.squareup.wire.Message
import com.squareup.wire.ProtoAdapter
import com.squareup.wire.ProtoReader
import com.squareup.wire.ProtoWriter
import com.squareup.wire.Syntax.PROTO_3
import com.squareup.wire.WireField
import com.squareup.wire.internal.immutableCopyOf
import com.squareup.wire.internal.sanitize
import kotlin.Any
import kotlin.AssertionError
import kotlin.Boolean
import kotlin.Deprecated
import kotlin.DeprecationLevel
import kotlin.Int
import kotlin.Long
import kotlin.Nothing
import kotlin.String
import kotlin.collections.List
import kotlin.hashCode
import kotlin.jvm.JvmField
import okio.ByteString
class Dinosaur(
/**
* Common name of this dinosaur, like "Stegosaurus".
*/
@field:WireField(
tag = 1,
adapter = "com.squareup.wire.ProtoAdapter#STRING",
label = WireField.Label.OMIT_IDENTITY
)
val name: String = "",
picture_urls: List<String> = emptyList(),
@field:WireField(
tag = 5,
adapter = "com.squareup.geology.Period#ADAPTER",
label = WireField.Label.OMIT_IDENTITY
)
val period: Period = Period.CRETACEOUS,
unknownFields: ByteString = ByteString.EMPTY
) : Message<Dinosaur, Nothing>(ADAPTER, unknownFields) {
/**
* URLs with images of this dinosaur.
*/
@field:WireField(
tag = 2,
adapter = "com.squareup.wire.ProtoAdapter#STRING",
label = WireField.Label.REPEATED,
jsonName = "pictureUrls"
)
val picture_urls: List<String> = immutableCopyOf("picture_urls", picture_urls)
@Deprecated(
message = "Shouldn't be used in Kotlin",
level = DeprecationLevel.HIDDEN
)
override fun newBuilder(): Nothing = throw AssertionError()
override fun equals(other: Any?): Boolean {
if (other === this) return true
if (other !is Dinosaur) return false
if (unknownFields != other.unknownFields) return false
if (name != other.name) return false
if (picture_urls != other.picture_urls) return false
if (period != other.period) return false
return true
}
override fun hashCode(): Int {
var result = super.hashCode
if (result == 0) {
result = unknownFields.hashCode()
result = result * 37 + name.hashCode()
result = result * 37 + picture_urls.hashCode()
result = result * 37 + period.hashCode()
super.hashCode = result
}
return result
}
override fun toString(): String {
val result = mutableListOf<String>()
result += """name=${sanitize(name)}"""
if (picture_urls.isNotEmpty()) result += """picture_urls=${sanitize(picture_urls)}"""
result += """period=$period"""
return result.joinToString(prefix = "Dinosaur{", separator = ", ", postfix = "}")
}
fun copy(
name: String = this.name,
picture_urls: List<String> = this.picture_urls,
period: Period = this.period,
unknownFields: ByteString = this.unknownFields
): Dinosaur = Dinosaur(name, picture_urls, period, unknownFields)
companion object {
@JvmField
val ADAPTER: ProtoAdapter<Dinosaur> = object : ProtoAdapter<Dinosaur>(
FieldEncoding.LENGTH_DELIMITED,
Dinosaur::class,
"type.googleapis.com/squareup.dinosaurs.Dinosaur",
PROTO_3,
null
) {
override fun encodedSize(value: Dinosaur): Int {
var size = value.unknownFields.size
if (value.name != "") size += ProtoAdapter.STRING.encodedSizeWithTag(1, value.name)
size += ProtoAdapter.STRING.asRepeated().encodedSizeWithTag(2, value.picture_urls)
if (value.period != Period.CRETACEOUS) size += Period.ADAPTER.encodedSizeWithTag(5,
value.period)
return size
}
override fun encode(writer: ProtoWriter, value: Dinosaur) {
if (value.name != "") ProtoAdapter.STRING.encodeWithTag(writer, 1, value.name)
ProtoAdapter.STRING.asRepeated().encodeWithTag(writer, 2, value.picture_urls)
if (value.period != Period.CRETACEOUS) Period.ADAPTER.encodeWithTag(writer, 5, value.period)
writer.writeBytes(value.unknownFields)
}
override fun decode(reader: ProtoReader): Dinosaur {
var name: String = ""
val picture_urls = mutableListOf<String>()
var period: Period = Period.CRETACEOUS
val unknownFields = reader.forEachTag { tag ->
when (tag) {
1 -> name = ProtoAdapter.STRING.decode(reader)
2 -> picture_urls.add(ProtoAdapter.STRING.decode(reader))
5 -> try {
period = Period.ADAPTER.decode(reader)
} catch (e: ProtoAdapter.EnumConstantNotFoundException) {
reader.addUnknownField(tag, FieldEncoding.VARINT, e.value.toLong())
}
else -> reader.readUnknownField(tag)
}
}
return Dinosaur(
name = name,
picture_urls = picture_urls,
period = period,
unknownFields = unknownFields
)
}
override fun redact(value: Dinosaur): Dinosaur = value.copy(
unknownFields = ByteString.EMPTY
)
}
private const val serialVersionUID: Long = 0L
}
} Creating and accessing proto models is easy: val stegosaurus = Dinosaur(
name = "Stegosaurus",
period = Period.JURASSIC
)
println("My favorite dinosaur existed in the ${stegosaurus.period} period.") Here's how you can modify the object to add extra fields: val stegosaurus = stegosaurus.copy(
picture_urls = listOf("https://www.flickr.com/photos/tags/Stegosaurus/")
)
println("Here are some photos of ${stegosaurus.name}: ${stegosaurus.picture_urls}") Wire gRPCSince version 3.0.0, Wire supports gRPC. Generating Code With WireWire can read The compiler can optionally prune your schema to a subset of root types and their transitive dependencies. This is useful when sharing a schema between projects: a Java service and Android app may each use a subset of a larger shared schema. For more info on how to get started, see Wire Compiler & Gradle Plugin. If you don't use Gradle, the compiler also has a command line interface. Just substitute
Supplying the If you use Proguard, then you need to add
Get WireThe With Maven: <dependency>
<groupId>com.squareup.wire</groupId>
<artifactId>wire-runtime-jvm</artifactId>
<version>4.4.1</version>
</dependency> With Gradle: api "com.squareup.wire:wire-runtime:4.4.1" Snapshots of the development version are available in Sonatype's |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论