Source release 14.1.0

This commit is contained in:
John W. Bruce
2018-06-29 15:59:47 -07:00
parent 3ab70cec4e
commit afa11a48a0
1941 changed files with 557780 additions and 105547 deletions

View File

@@ -50,7 +50,7 @@ class AddPerson {
stdout.println("Unknown phone type. Using default.");
}
person.addPhone(phoneNumber);
person.addPhones(phoneNumber);
}
return person.build();
@@ -80,7 +80,7 @@ class AddPerson {
}
// Add an address.
addressBook.addPerson(
addressBook.addPeople(
PromptForAddress(new BufferedReader(new InputStreamReader(System.in)),
System.out));

101
third_party/protobuf/examples/BUILD vendored Normal file
View File

@@ -0,0 +1,101 @@
# This BUILD file shows how to use protobuf with bazel. Before you can use
# proto_library/<lang>_proto_library rules in a BUILD file, you need to
# include protobuf repo as remote repositories in your WORKSPACE file. See
# the WORKSPACE file in the same directory with this BUILD file for an
# example.
# For each .proto file, a proto_library target should be defined. This target
# is not bound to any particular language. Instead, it defines the dependency
# graph of the .proto files (i.e., proto imports) and serves as the provider
# of .proto source files to the protocol compiler.
#
# Remote repository "com_google_protobuf" must be defined to use this rule.
proto_library(
name = "addressbook_proto",
srcs = ["addressbook.proto"],
deps = ["@com_google_protobuf//:timestamp_proto"],
)
# The cc_proto_library rule generates C++ code for a proto_library rule. It
# must have exactly one proto_library dependency. If you want to use multiple
# proto_library targets, create a separate cc_proto_library target for each
# of them.
#
# Remote repository "com_google_protobuf_cc" must be defined to use this rule.
cc_proto_library(
name = "addressbook_cc_proto",
deps = [":addressbook_proto"],
)
# cc_library/cc_binary targets can depend on cc_proto_library targets.
cc_binary(
name = "add_person_cpp",
srcs = ["add_person.cc"],
deps = [":addressbook_cc_proto"],
)
cc_binary(
name = "list_people_cpp",
srcs = ["list_people.cc"],
deps = [":addressbook_cc_proto"],
)
# Similar to cc_proto_library but for Java.
#
# Remote repository "com_google_protobuf_java" must be defined to use this rule.
java_proto_library(
name = "addressbook_java_proto",
deps = [":addressbook_proto"],
)
java_binary(
name = "add_person_java",
srcs = ["AddPerson.java"],
main_class = "AddPerson",
deps = [":addressbook_java_proto"],
)
java_binary(
name = "list_people_java",
srcs = ["ListPeople.java"],
main_class = "ListPeople",
deps = [":addressbook_java_proto"],
)
# Java lite.
#
# Remote repository "com_google_protobuf_javalite" must be defined to use this
# rule.
java_lite_proto_library(
name = "addressbook_java_lite_proto",
deps = [":addressbook_proto"],
)
# Java lite API is a subset of the regular Java API so if you only uses this
# subset in your code, you can actually compile your code against both (i.e.,
# share code between server build and Android build).
#
# The lite version has a smaller code size, and you can see that by comparing
# the resulted .jar file:
#
# $ bazel build :add_person_java_deploy.jar :add_person_java_lite_deploy.jar
# $ ls -l bazel-bin/*_deploy.jar
# -r-xr-xr-x 1 xiaofeng eng 1230797 Sep 8 12:24 bazel-bin/add_person_java_deploy.jar
# -r-xr-xr-x 1 xiaofeng eng 236166 Sep 8 12:24 bazel-bin/add_person_java_lite_deploy.jar
#
# In the above example, the lite .jar file is 6 times smaller. With proper
# proguard inlining/stripping, the difference can be much more larger than
# that.
java_binary(
name = "add_person_java_lite",
srcs = ["AddPerson.java"],
main_class = "AddPerson",
deps = [":addressbook_java_lite_proto"],
)
java_binary(
name = "list_people_java_lite",
srcs = ["ListPeople.java"],
main_class = "ListPeople",
deps = [":addressbook_java_lite_proto"],
)

View File

@@ -0,0 +1,48 @@
# Minimum CMake required
cmake_minimum_required(VERSION 2.8.12)
# Project
project(protobuf-examples)
# Find required protobuf package
find_package(protobuf CONFIG REQUIRED)
if(protobuf_VERBOSE)
message(STATUS "Using Protocol Buffers ${Protobuf_VERSION}")
endif()
set(CMAKE_INCLUDE_CURRENT_DIR TRUE)
# http://www.cmake.org/Wiki/CMake_FAQ#How_can_I_build_my_MSVC_application_with_a_static_runtime.3F
if(MSVC AND protobuf_MSVC_STATIC_RUNTIME)
foreach(flag_var
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
if(${flag_var} MATCHES "/MD")
string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
endif(${flag_var} MATCHES "/MD")
endforeach()
endif()
foreach(example add_person list_people)
set(${example}_SRCS ${example}.cc)
set(${example}_PROTOS addressbook.proto)
#Code Generation
if(protobuf_MODULE_COMPATIBLE) #Legacy Support
protobuf_generate_cpp(${example}_PROTO_SRCS ${example}_PROTO_HDRS ${${example}_PROTOS})
list(APPEND ${example}_SRCS ${${example}_PROTO_SRCS} ${${example}_PROTO_HDRS})
endif()
#Executable setup
set(executable_name ${example}_cpp)
add_executable(${executable_name} ${${example}_SRCS} ${${example}_PROTOS})
if(protobuf_MODULE_COMPATIBLE) #Legacy mode
target_include_directories(${executable_name} PUBLIC ${PROTOBUF_INCLUDE_DIRS})
target_link_libraries(${executable_name} ${PROTOBUF_LIBRARIES})
else()
target_link_libraries(${executable_name} protobuf::libprotobuf)
protobuf_generate(TARGET ${executable_name})
endif()
endforeach()

View File

@@ -9,14 +9,14 @@ import java.io.PrintStream;
class ListPeople {
// Iterates though all people in the AddressBook and prints info about them.
static void Print(AddressBook addressBook) {
for (Person person: addressBook.getPersonList()) {
for (Person person: addressBook.getPeopleList()) {
System.out.println("Person ID: " + person.getId());
System.out.println(" Name: " + person.getName());
if (person.hasEmail()) {
if (!person.getEmail().isEmpty()) {
System.out.println(" E-mail address: " + person.getEmail());
}
for (Person.PhoneNumber phoneNumber : person.getPhoneList()) {
for (Person.PhoneNumber phoneNumber : person.getPhonesList()) {
switch (phoneNumber.getType()) {
case MOBILE:
System.out.print(" Mobile phone #: ");
@@ -27,6 +27,9 @@ class ListPeople {
case WORK:
System.out.print(" Work phone #: ");
break;
default:
System.out.println(" Unknown phone #: ");
break;
}
System.out.println(phoneNumber.getNumber());
}

124
third_party/protobuf/examples/README.md vendored Normal file
View File

@@ -0,0 +1,124 @@
# Protocol Buffers - Code Example
This directory contains example code that uses Protocol Buffers to manage an
address book. Two programs are provided for each supported language. The
add_person example adds a new person to an address book, prompting the user to
input the person's information. The list_people example lists people already in
the address book. The examples use the exact same format in all three languages,
so you can, for example, use add_person_java to create an address book and then
use list_people_python to read it.
These examples are part of the Protocol Buffers tutorial, located at:
https://developers.google.com/protocol-buffers/docs/tutorials
## Build the example using bazel
The example requires bazel 0.5.4 or newer to build. You can download/install
the latest version of bazel from bazel's release page:
https://github.com/bazelbuild/bazel/releases
Once you have bazel installed, simply run the following command in this examples
directory to build the code:
$ bazel build :all
Then you can run the built binary:
$ bazel-bin/add_person_cpp addressbook.data
To use protobuf in your own bazel project, please follow instructions in the
[BUILD](BUILD) file and [WORKSPACE](WORKSPACE) file.
## Build the example using make
You must install the protobuf package before you can build it using make. The
minimum requirement is to install protocol compiler (i.e., the protoc binary)
and the protobuf runtime for the language you want to build.
You can simply run "make" to build the example for all languages (except for
Go). However, since different language has different installation requirement,
it will likely fail. It's better to follow individual instrutions below to
build only the language you are interested in.
### C++
You can follow instructions in [../src/README.md](../src/README.md) to install
protoc and protobuf C++ runtime from source.
Then run "make cpp" in this examples directory to build the C++ example. It
will create two executables: add_person_cpp and list_people_cpp. These programs
simply take an address book file as their parameter. The add_person_cpp
programs will create the file if it doesn't already exist.
To run the examples:
$ ./add_person_cpp addressbook.data
$ ./list_people_cpp addressbook.data
Note that on some platforms you may have to edit the Makefile and remove
"-lpthread" from the linker commands (perhaps replacing it with something else).
We didn't do this automatically because we wanted to keep the example simple.
### Python
Follow instructions in [../README.md](../README.md) to install protoc and then
follow [../python/README.md](../python/README.md) to install protobuf python
runtime from source. You can also install python runtime using pip:
$ pip install protobuf
Make sure the runtime version is the same as protoc binary, or it may not work.
After you have install both protoc and python runtime, run "make python" to
build two executables (shell scripts actually): add_person_python and
list_people_python. They work the same way as the C++ executables.
### Java
Follow instructions in [../README.md](../README.md) to install protoc and then
download protobuf Java runtime .jar file from maven:
https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java
Then run the following:
$ export CLASSPATH=/path/to/protobuf-java-[version].jar
$ make java
This will create the add_person_java/list_people_java executables (shell
scripts) and can be used to create/display an address book data file.
### Go
The Go example requires a plugin to the protocol buffer compiler, so it is not
build with all the other examples. See:
https://github.com/golang/protobuf
for more information about Go protocol buffer support.
First, install the Protocol Buffers compiler (protoc).
Then, install the Go Protocol Buffers plugin ($GOPATH/bin must be in your $PATH
for protoc to find it):
go get github.com/golang/protobuf/protoc-gen-go
Build the Go samples in this directory with "make go". This creates the
following executable files in the current directory:
add_person_go list_people_go
To run the example:
./add_person_go addressbook.data
to add a person to the protocol buffer encoded file addressbook.data. The file
is created if it does not exist. To view the data, run:
./list_people_go addressbook.data
Observe that the C++, Python, and Java examples in this directory run in a
similar way and can view/modify files created by the Go example and vice
versa.

View File

@@ -1,29 +0,0 @@
This directory contains example code that uses Protocol Buffers to manage an
address book. Two programs are provided, each with three different
implementations, one written in each of C++, Java, and Python. The add_person
example adds a new person to an address book, prompting the user to input
the person's information. The list_people example lists people already in the
address book. The examples use the exact same format in all three languages,
so you can, for example, use add_person_java to create an address book and then
use list_people_python to read it.
You must install the protobuf package before you can build these.
To build all the examples (on a unix-like system), simply run "make". This
creates the following executable files in the current directory:
add_person_cpp list_people_cpp
add_person_java list_people_java
add_person_python list_people_python
If you only want to compile examples in one language, use "make cpp"*,
"make java", or "make python".
All of these programs simply take an address book file as their parameter.
The add_person programs will create the file if it doesn't already exist.
These examples are part of the Protocol Buffers tutorial, located at:
https://developers.google.com/protocol-buffers/docs/tutorials
* Note that on some platforms you may have to edit the Makefile and remove
"-lpthread" from the linker commands (perhaps replacing it with something else).
We didn't do this automatically because we wanted to keep the example simple.

33
third_party/protobuf/examples/WORKSPACE vendored Normal file
View File

@@ -0,0 +1,33 @@
# This com_google_protobuf repository is required for proto_library rule.
# It provides the protocol compiler binary (i.e., protoc).
http_archive(
name = "com_google_protobuf",
strip_prefix = "protobuf-master",
urls = ["https://github.com/google/protobuf/archive/master.zip"],
)
# This com_google_protobuf_cc repository is required for cc_proto_library
# rule. It provides protobuf C++ runtime. Note that it actually is the same
# repo as com_google_protobuf but has to be given a different name as
# required by bazel.
http_archive(
name = "com_google_protobuf_cc",
strip_prefix = "protobuf-master",
urls = ["https://github.com/google/protobuf/archive/master.zip"],
)
# Similar to com_google_protobuf_cc but for Java (i.e., java_proto_library).
http_archive(
name = "com_google_protobuf_java",
strip_prefix = "protobuf-master",
urls = ["https://github.com/google/protobuf/archive/master.zip"],
)
# Similar to com_google_protobuf_cc but for Java lite. If you are building
# for Android, the lite version should be prefered because it has a much
# smaller code size.
http_archive(
name = "com_google_protobuf_javalite",
strip_prefix = "protobuf-javalite",
urls = ["https://github.com/google/protobuf/archive/javalite.zip"],
)

View File

@@ -1,11 +1,17 @@
// See README.txt for information and build instructions.
#include <iostream>
#include <ctime>
#include <fstream>
#include <google/protobuf/util/time_util.h>
#include <iostream>
#include <string>
#include "addressbook.pb.h"
using namespace std;
using google::protobuf::util::TimeUtil;
// This function fills in a Person message based on user input.
void PromptForAddress(tutorial::Person* person) {
cout << "Enter person ID number: ";
@@ -32,7 +38,7 @@ void PromptForAddress(tutorial::Person* person) {
break;
}
tutorial::Person::PhoneNumber* phone_number = person->add_phone();
tutorial::Person::PhoneNumber* phone_number = person->add_phones();
phone_number->set_number(number);
cout << "Is this a mobile, home, or work phone? ";
@@ -48,6 +54,7 @@ void PromptForAddress(tutorial::Person* person) {
cout << "Unknown phone type. Using default." << endl;
}
}
*person->mutable_last_updated() = TimeUtil::SecondsToTimestamp(time(NULL));
}
// Main function: Reads the entire address book from a file,
@@ -77,7 +84,7 @@ int main(int argc, char* argv[]) {
}
// Add an address.
PromptForAddress(address_book.add_person());
PromptForAddress(address_book.add_people());
{
// Write the new address book back to disk.

View File

@@ -0,0 +1,133 @@
package main
import (
"bufio"
"fmt"
"io"
"io/ioutil"
"log"
"os"
"strings"
"github.com/golang/protobuf/proto"
pb "github.com/google/protobuf/examples/tutorial"
)
func promptForAddress(r io.Reader) (*pb.Person, error) {
// A protocol buffer can be created like any struct.
p := &pb.Person{}
rd := bufio.NewReader(r)
fmt.Print("Enter person ID number: ")
// An int32 field in the .proto file is represented as an int32 field
// in the generated Go struct.
if _, err := fmt.Fscanf(rd, "%d\n", &p.Id); err != nil {
return p, err
}
fmt.Print("Enter name: ")
name, err := rd.ReadString('\n')
if err != nil {
return p, err
}
// A string field in the .proto file results in a string field in Go.
// We trim the whitespace because rd.ReadString includes the trailing
// newline character in its output.
p.Name = strings.TrimSpace(name)
fmt.Print("Enter email address (blank for none): ")
email, err := rd.ReadString('\n')
if err != nil {
return p, err
}
p.Email = strings.TrimSpace(email)
for {
fmt.Print("Enter a phone number (or leave blank to finish): ")
phone, err := rd.ReadString('\n')
if err != nil {
return p, err
}
phone = strings.TrimSpace(phone)
if phone == "" {
break
}
// The PhoneNumber message type is nested within the Person
// message in the .proto file. This results in a Go struct
// named using the name of the parent prefixed to the name of
// the nested message. Just as with pb.Person, it can be
// created like any other struct.
pn := &pb.Person_PhoneNumber{
Number: phone,
}
fmt.Print("Is this a mobile, home, or work phone? ")
ptype, err := rd.ReadString('\n')
if err != nil {
return p, err
}
ptype = strings.TrimSpace(ptype)
// A proto enum results in a Go constant for each enum value.
switch ptype {
case "mobile":
pn.Type = pb.Person_MOBILE
case "home":
pn.Type = pb.Person_HOME
case "work":
pn.Type = pb.Person_WORK
default:
fmt.Printf("Unknown phone type %q. Using default.\n", ptype)
}
// A repeated proto field maps to a slice field in Go. We can
// append to it like any other slice.
p.Phones = append(p.Phones, pn)
}
return p, nil
}
// Main reads the entire address book from a file, adds one person based on
// user input, then writes it back out to the same file.
func main() {
if len(os.Args) != 2 {
log.Fatalf("Usage: %s ADDRESS_BOOK_FILE\n", os.Args[0])
}
fname := os.Args[1]
// Read the existing address book.
in, err := ioutil.ReadFile(fname)
if err != nil {
if os.IsNotExist(err) {
fmt.Printf("%s: File not found. Creating new file.\n", fname)
} else {
log.Fatalln("Error reading file:", err)
}
}
// [START marshal_proto]
book := &pb.AddressBook{}
// [START_EXCLUDE]
if err := proto.Unmarshal(in, book); err != nil {
log.Fatalln("Failed to parse address book:", err)
}
// Add an address.
addr, err := promptForAddress(os.Stdin)
if err != nil {
log.Fatalln("Error with address:", err)
}
book.People = append(book.People, addr)
// [END_EXCLUDE]
// Write the new address book back to disk.
out, err := proto.Marshal(book)
if err != nil {
log.Fatalln("Failed to encode address book:", err)
}
if err := ioutil.WriteFile(fname, out, 0644); err != nil {
log.Fatalln("Failed to write address book:", err)
}
// [END marshal_proto]
}

View File

@@ -1,10 +1,16 @@
#! /usr/bin/python
#! /usr/bin/env python
# See README.txt for information and build instructions.
import addressbook_pb2
import sys
try:
raw_input # Python 2
except NameError:
raw_input = input # Python 3
# This function fills in a Person message based on user input.
def PromptForAddress(person):
person.id = int(raw_input("Enter person ID number: "))
@@ -19,7 +25,7 @@ def PromptForAddress(person):
if number == "":
break
phone_number = person.phone.add()
phone_number = person.phones.add()
phone_number.number = number
type = raw_input("Is this a mobile, home, or work phone? ")
@@ -30,29 +36,28 @@ def PromptForAddress(person):
elif type == "work":
phone_number.type = addressbook_pb2.Person.WORK
else:
print "Unknown phone type; leaving as default value."
print("Unknown phone type; leaving as default value.")
# Main procedure: Reads the entire address book from a file,
# adds one person based on user input, then writes it back out to the same
# file.
if len(sys.argv) != 2:
print "Usage:", sys.argv[0], "ADDRESS_BOOK_FILE"
print("Usage:", sys.argv[0], "ADDRESS_BOOK_FILE")
sys.exit(-1)
address_book = addressbook_pb2.AddressBook()
# Read the existing address book.
try:
f = open(sys.argv[1], "rb")
address_book.ParseFromString(f.read())
f.close()
with open(sys.argv[1], "rb") as f:
address_book.ParseFromString(f.read())
except IOError:
print sys.argv[1] + ": File not found. Creating a new file."
print(sys.argv[1] + ": File not found. Creating a new file.")
# Add an address.
PromptForAddress(address_book.person.add())
PromptForAddress(address_book.people.add())
# Write the new address book back to disk.
f = open(sys.argv[1], "wb")
f.write(address_book.SerializeToString())
f.close()
with open(sys.argv[1], "wb") as f:
f.write(address_book.SerializeToString())

View File

@@ -0,0 +1,58 @@
package main
import (
"strings"
"testing"
"github.com/golang/protobuf/proto"
pb "github.com/google/protobuf/examples/tutorial"
)
func TestPromptForAddressReturnsAddress(t *testing.T) {
in := `12345
Example Name
name@example.com
123-456-7890
home
222-222-2222
mobile
111-111-1111
work
777-777-7777
unknown
`
got, err := promptForAddress(strings.NewReader(in))
if err != nil {
t.Fatalf("promptForAddress(%q) had unexpected error: %s", in, err.Error())
}
if got.Id != 12345 {
t.Errorf("promptForAddress(%q) got %d, want ID %d", in, got.Id, 12345)
}
if got.Name != "Example Name" {
t.Errorf("promptForAddress(%q) => want name %q, got %q", "Example Name", got.Name)
}
if got.Email != "name@example.com" {
t.Errorf("promptForAddress(%q) => want email %q, got %q", "name@example.com", got.Email)
}
want := []*pb.Person_PhoneNumber{
{Number: "123-456-7890", Type: pb.Person_HOME},
{Number: "222-222-2222", Type: pb.Person_MOBILE},
{Number: "111-111-1111", Type: pb.Person_WORK},
{Number: "777-777-7777", Type: pb.Person_MOBILE},
}
if len(got.Phones) != len(want) {
t.Errorf("want %d phone numbers, got %d", len(want), len(got.Phones))
}
phones := len(got.Phones)
if phones > len(want) {
phones = len(want)
}
for i := 0; i < phones; i++ {
if !proto.Equal(got.Phones[i], want[i]) {
t.Errorf("want phone %q, got %q", *want[i], *got.Phones[i])
}
}
}

View File

@@ -1,14 +1,32 @@
// See README.txt for information and build instructions.
//
// Note: START and END tags are used in comments to define sections used in
// tutorials. They are not part of the syntax for Protocol Buffers.
//
// To get an in-depth walkthrough of this file and the related examples, see:
// https://developers.google.com/protocol-buffers/docs/tutorials
// [START declaration]
syntax = "proto3";
package tutorial;
import "google/protobuf/timestamp.proto";
// [END declaration]
// [START java_declaration]
option java_package = "com.example.tutorial";
option java_outer_classname = "AddressBookProtos";
// [END java_declaration]
// [START csharp_declaration]
option csharp_namespace = "Google.Protobuf.Examples.AddressBook";
// [END csharp_declaration]
// [START messages]
message Person {
required string name = 1;
required int32 id = 2; // Unique ID number for this person.
optional string email = 3;
string name = 1;
int32 id = 2; // Unique ID number for this person.
string email = 3;
enum PhoneType {
MOBILE = 0;
@@ -17,14 +35,17 @@ message Person {
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
string number = 1;
PhoneType type = 2;
}
repeated PhoneNumber phone = 4;
repeated PhoneNumber phones = 4;
google.protobuf.Timestamp last_updated = 5;
}
// Our address book file is just one of these.
message AddressBook {
repeated Person person = 1;
repeated Person people = 1;
}
// [END messages]

View File

@@ -1,24 +1,29 @@
// See README.txt for information and build instructions.
#include <iostream>
#include <fstream>
#include <google/protobuf/util/time_util.h>
#include <iostream>
#include <string>
#include "addressbook.pb.h"
using namespace std;
using google::protobuf::util::TimeUtil;
// Iterates though all people in the AddressBook and prints info about them.
void ListPeople(const tutorial::AddressBook& address_book) {
for (int i = 0; i < address_book.person_size(); i++) {
const tutorial::Person& person = address_book.person(i);
for (int i = 0; i < address_book.people_size(); i++) {
const tutorial::Person& person = address_book.people(i);
cout << "Person ID: " << person.id() << endl;
cout << " Name: " << person.name() << endl;
if (person.has_email()) {
if (person.email() != "") {
cout << " E-mail address: " << person.email() << endl;
}
for (int j = 0; j < person.phone_size(); j++) {
const tutorial::Person::PhoneNumber& phone_number = person.phone(j);
for (int j = 0; j < person.phones_size(); j++) {
const tutorial::Person::PhoneNumber& phone_number = person.phones(j);
switch (phone_number.type()) {
case tutorial::Person::MOBILE:
@@ -30,9 +35,15 @@ void ListPeople(const tutorial::AddressBook& address_book) {
case tutorial::Person::WORK:
cout << " Work phone #: ";
break;
default:
cout << " Unknown phone #: ";
break;
}
cout << phone_number.number() << endl;
}
if (person.has_last_updated()) {
cout << " Updated: " << TimeUtil::ToString(person.last_updated()) << endl;
}
}
}

View File

@@ -0,0 +1,61 @@
package main
import (
"fmt"
"io"
"io/ioutil"
"log"
"os"
"github.com/golang/protobuf/proto"
pb "github.com/google/protobuf/examples/tutorial"
)
func writePerson(w io.Writer, p *pb.Person) {
fmt.Fprintln(w, "Person ID:", p.Id)
fmt.Fprintln(w, " Name:", p.Name)
if p.Email != "" {
fmt.Fprintln(w, " E-mail address:", p.Email)
}
for _, pn := range p.Phones {
switch pn.Type {
case pb.Person_MOBILE:
fmt.Fprint(w, " Mobile phone #: ")
case pb.Person_HOME:
fmt.Fprint(w, " Home phone #: ")
case pb.Person_WORK:
fmt.Fprint(w, " Work phone #: ")
}
fmt.Fprintln(w, pn.Number)
}
}
func listPeople(w io.Writer, book *pb.AddressBook) {
for _, p := range book.People {
writePerson(w, p)
}
}
// Main reads the entire address book from a file and prints all the
// information inside.
func main() {
if len(os.Args) != 2 {
log.Fatalf("Usage: %s ADDRESS_BOOK_FILE\n", os.Args[0])
}
fname := os.Args[1]
// [START unmarshal_proto]
// Read the existing address book.
in, err := ioutil.ReadFile(fname)
if err != nil {
log.Fatalln("Error reading file:", err)
}
book := &pb.AddressBook{}
if err := proto.Unmarshal(in, book); err != nil {
log.Fatalln("Failed to parse address book:", err)
}
// [END unmarshal_proto]
listPeople(os.Stdout, book)
}

View File

@@ -1,38 +1,40 @@
#! /usr/bin/python
#! /usr/bin/env python
# See README.txt for information and build instructions.
from __future__ import print_function
import addressbook_pb2
import sys
# Iterates though all people in the AddressBook and prints info about them.
def ListPeople(address_book):
for person in address_book.person:
print "Person ID:", person.id
print " Name:", person.name
if person.HasField('email'):
print " E-mail address:", person.email
for person in address_book.people:
print("Person ID:", person.id)
print(" Name:", person.name)
if person.email != "":
print(" E-mail address:", person.email)
for phone_number in person.phone:
for phone_number in person.phones:
if phone_number.type == addressbook_pb2.Person.MOBILE:
print " Mobile phone #:",
print(" Mobile phone #:", end=" ")
elif phone_number.type == addressbook_pb2.Person.HOME:
print " Home phone #:",
print(" Home phone #:", end=" ")
elif phone_number.type == addressbook_pb2.Person.WORK:
print " Work phone #:",
print phone_number.number
print(" Work phone #:", end=" ")
print(phone_number.number)
# Main procedure: Reads the entire address book from a file and prints all
# the information inside.
if len(sys.argv) != 2:
print "Usage:", sys.argv[0], "ADDRESS_BOOK_FILE"
print("Usage:", sys.argv[0], "ADDRESS_BOOK_FILE")
sys.exit(-1)
address_book = addressbook_pb2.AddressBook()
# Read the existing address book.
f = open(sys.argv[1], "rb")
address_book.ParseFromString(f.read())
f.close()
with open(sys.argv[1], "rb") as f:
address_book.ParseFromString(f.read())
ListPeople(address_book)

View File

@@ -0,0 +1,120 @@
package main
import (
"bytes"
"strings"
"testing"
pb "github.com/google/protobuf/examples/tutorial"
)
func TestWritePersonWritesPerson(t *testing.T) {
buf := new(bytes.Buffer)
// [START populate_proto]
p := pb.Person{
Id: 1234,
Name: "John Doe",
Email: "jdoe@example.com",
Phones: []*pb.Person_PhoneNumber{
{Number: "555-4321", Type: pb.Person_HOME},
},
}
// [END populate_proto]
writePerson(buf, &p)
got := buf.String()
want := `Person ID: 1234
Name: John Doe
E-mail address: jdoe@example.com
Home phone #: 555-4321
`
if got != want {
t.Errorf("writePerson(%s) =>\n\t%q, want %q", p.String(), got, want)
}
}
func TestListPeopleWritesList(t *testing.T) {
buf := new(bytes.Buffer)
in := pb.AddressBook{[]*pb.Person{
{
Name: "John Doe",
Id: 101,
Email: "john@example.com",
},
{
Name: "Jane Doe",
Id: 102,
},
{
Name: "Jack Doe",
Id: 201,
Email: "jack@example.com",
Phones: []*pb.Person_PhoneNumber{
{Number: "555-555-5555", Type: pb.Person_WORK},
},
},
{
Name: "Jack Buck",
Id: 301,
Email: "buck@example.com",
Phones: []*pb.Person_PhoneNumber{
{Number: "555-555-0000", Type: pb.Person_HOME},
{Number: "555-555-0001", Type: pb.Person_MOBILE},
{Number: "555-555-0002", Type: pb.Person_WORK},
},
},
{
Name: "Janet Doe",
Id: 1001,
Email: "janet@example.com",
Phones: []*pb.Person_PhoneNumber{
{Number: "555-777-0000"},
{Number: "555-777-0001", Type: pb.Person_HOME},
},
},
}}
listPeople(buf, &in)
want := strings.Split(`Person ID: 101
Name: John Doe
E-mail address: john@example.com
Person ID: 102
Name: Jane Doe
Person ID: 201
Name: Jack Doe
E-mail address: jack@example.com
Work phone #: 555-555-5555
Person ID: 301
Name: Jack Buck
E-mail address: buck@example.com
Home phone #: 555-555-0000
Mobile phone #: 555-555-0001
Work phone #: 555-555-0002
Person ID: 1001
Name: Janet Doe
E-mail address: janet@example.com
Mobile phone #: 555-777-0000
Home phone #: 555-777-0001
`, "\n")
got := strings.Split(buf.String(), "\n")
if len(got) != len(want) {
t.Errorf(
"listPeople(%s) =>\n\t%q has %d lines, want %d",
in.String(),
buf.String(),
len(got),
len(want))
}
lines := len(got)
if lines > len(want) {
lines = len(want)
}
for i := 0; i < lines; i++ {
if got[i] != want[i] {
t.Errorf(
"listPeople(%s) =>\n\tline %d %q, want %q",
in.String(),
i,
got[i],
want[i])
}
}
}