all: implement first-class WKT support

This CL introduces generation of specialized APIs directly into the
generated packages for certain well-known types. This follows the pattern
set forth by the other language implementations that have specialized
generated support for certain well-known types.

Overview of new API:
  package anypb
    func MarshalFrom(*Any, proto.Message, proto.MarshalOptions) error
    func UnmarshalTo(*Any, proto.Message, proto.UnmarshalOptions) error
    func UnmarshalNew(*Any, proto.UnmarshalOptions) (proto.Message, error)
    func (*Any) MessageIs(proto.Message) bool
    func (*Any) MessageName() protoreflect.FullName
    func (*Any) MarshalFrom(proto.Message) error
    func (*Any) UnmarshalTo(proto.Message) error
    func (*Any) UnmarshalNew() (proto.Message, error)

  package timestamppb
    func Now() *Timestamp
    func New(time.Time) *Timestamp
    func (*Timestamp) AsTime() time.Time
    func (*Timestamp) IsValid() bool
    func (*Timestamp) CheckValid() error

  package durationpb
    func New(time.Duration) *Duration
    func (*Duration) AsDuration() time.Duration
    func (*Duration) IsValid() bool
    func (*Duration) CheckValid() error

  package structpb
    func NewStruct(map[string]interface{}) (*Struct, error)
    func (*Struct) AsMap() map[string]interface{}
    func (*Struct) MarshalJSON() ([]byte, error)
    func (*Struct) UnmarshalJSON(b []byte) error

    func NewList([]interface{}) (*ListValue, error)
    func (*ListValue) AsSlice() []interface{}
    func (*ListValue) MarshalJSON() ([]byte, error)
    func (*ListValue) UnmarshalJSON(b []byte) error

    func NewValue(interface{}) (*Value, error)
    func NewNullValue() *Value
    func NewBoolValue(bool) *Value
    func NewNumberValue(float64) *Value
    func NewStringValue(string) *Value
    func NewStructValue(*Struct) *Value
    func NewListValue(*ListValue) *Value
    func (*Value) AsInterface() interface{}
    func (*Value) MarshalJSON() ([]byte, error)
    func (*Value) UnmarshalJSON(b []byte) error

  package fieldmaskpb
    func New(proto.Message, ...string) (*FieldMask, error)
    func Union(*FieldMask, *FieldMask, ...*FieldMask) *FieldMask
    func Intersect(*FieldMask, *FieldMask, ...*FieldMask) *FieldMask
    func (*FieldMask) IsValid(proto.Message) bool
    func (*FieldMask) Append(proto.Message, ...string) error
    func (*FieldMask) Normalize()

  package wrapperspb
    func Bool(bool) *BoolValue
    func Int32(int32) *Int32Value
    func Int64(int64) *Int64Value
    func UInt32(uint32) *UInt32Value
    func UInt64(uint64) *UInt64Value
    func Float(float32) *FloatValue
    func Double(float64) *DoubleValue
    func String(string) *StringValue
    func Bytes([]byte) *BytesValue

This functionality expands upon and supersedes the
older github.com/golang/protobuf/ptypes package,
which provided helpers for Any, Timestamp, and Duration.

Comparison with older ptypes package:

* ptypes.AnyMessageName is replaced by anypb.Any.MessageName.
  The former returned an error for malformed type URLs,
  while the latter simply returns an empty string.

* ptypes.Is is replaced by anypb.Any.MessageIs.

* ptypes.Empty has no direct replacement as it is equivalent to:
	mt, err := protoregistry.GlobalTypes.FindMessageByURL(any.GetTypeUrl())
	if err != nil {
		return nil, err
	}
	return mt.New().Interface(), nil
  Analysis of user code revealed that this function is seldom used.

* ptypes.MarshalAny is replaced by anypb.Any.MarshalFrom.
  The former creates a new Any message and returns it,
  while the latter is a method that modifies the receiver.

* ptypes.UnmarshalAny is replaced by anypb.Any.UnmarshalTo.

* ptypes.DynamicAny is loosely replaced by anypb.Any.UnmarshalNew.
  The DynamicAny type is a custom proto.Message that is special
  to ptypes.UnmarshalAny where it would allocate a new message
  and store it into the DynamicAny instance. The UnmarshalNew method
  accomplishes the equivalent functionality in a more direct fashion.

* ptypes.TimestampNow is replaced by timestamppb.Now.

* ptypes.TimestampProto is replaced by timestamppb.New.
  The former returned an error if the timestamp was outside the
  10000-year range recommended by timestamp.proto,
  while the latter always succeeded. To preserve the behavior of
  the former validation check, the replacement can additionally
  call the timestamppb.Timestamp.CheckValid method.

* ptypes.Timestamp is replaced by timestamppb.Timestamp.AsTime.
  The former returned an error if the timestamp was outside the
  10000-year range recommended by timestamp.proto,
  while the latter always succeeded. To preserve the behavior of
  the former validation check, the replacement can additionally
  call the timestamppb.Timestamp.CheckValid method.

* ptypes.TimestampString has no direct replacement as it is equivalent to:
	ts.AsTime().Format(time.RFC3339Nano)

* ptypes.DurationProto is replaced by durationpb.New.

* ptypes.Duration is replaced by durationpb.Duration.AsDuration.
  The former returned an error if the duration would overflow
  when converting to a time.Duration, while the latter uses
  saturation arithmetic (similiar to the time package itself).
  Underflow resulted in time.Duration(math.MinInt64), while
  overflow resulted in time.Duration(math.MaxInt64).
  To preserve the behavior of former validation checks,
  the replacement can call the durationpb.Duration.CheckValid method
  and check whether the duration is fixed to one of the overflow values.

Change-Id: Ia996b1037a1fcafced7c7e10e9408ef7fa22863a
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/225298
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/cmd/protoc-gen-go/internal_gengo/main.go b/cmd/protoc-gen-go/internal_gengo/main.go
index 83c89d3..40cb614 100644
--- a/cmd/protoc-gen-go/internal_gengo/main.go
+++ b/cmd/protoc-gen-go/internal_gengo/main.go
@@ -36,9 +36,14 @@
 
 // Standard library dependencies.
 const (
+	base64Package  = protogen.GoImportPath("encoding/base64")
 	mathPackage    = protogen.GoImportPath("math")
 	reflectPackage = protogen.GoImportPath("reflect")
+	sortPackage    = protogen.GoImportPath("sort")
+	stringsPackage = protogen.GoImportPath("strings")
 	syncPackage    = protogen.GoImportPath("sync")
+	timePackage    = protogen.GoImportPath("time")
+	utf8Package    = protogen.GoImportPath("unicode/utf8")
 )
 
 // Protobuf library dependencies.
@@ -47,11 +52,13 @@
 // patched to support unique build environments that impose restrictions
 // on the dependencies of generated source code.
 var (
-	protoPackage        goImportPath = protogen.GoImportPath("google.golang.org/protobuf/proto")
-	protoifacePackage   goImportPath = protogen.GoImportPath("google.golang.org/protobuf/runtime/protoiface")
-	protoimplPackage    goImportPath = protogen.GoImportPath("google.golang.org/protobuf/runtime/protoimpl")
-	protoreflectPackage goImportPath = protogen.GoImportPath("google.golang.org/protobuf/reflect/protoreflect")
-	protoV1Package      goImportPath = protogen.GoImportPath("github.com/golang/protobuf/proto")
+	protoPackage         goImportPath = protogen.GoImportPath("google.golang.org/protobuf/proto")
+	protoifacePackage    goImportPath = protogen.GoImportPath("google.golang.org/protobuf/runtime/protoiface")
+	protoimplPackage     goImportPath = protogen.GoImportPath("google.golang.org/protobuf/runtime/protoimpl")
+	protojsonPackage     goImportPath = protogen.GoImportPath("google.golang.org/protobuf/encoding/protojson")
+	protoreflectPackage  goImportPath = protogen.GoImportPath("google.golang.org/protobuf/reflect/protoreflect")
+	protoregistryPackage goImportPath = protogen.GoImportPath("google.golang.org/protobuf/reflect/protoregistry")
+	protoV1Package       goImportPath = protogen.GoImportPath("github.com/golang/protobuf/proto")
 )
 
 type goImportPath interface {
@@ -328,6 +335,7 @@
 	g.P("}")
 	g.P()
 
+	genMessageKnownFunctions(g, f, m)
 	genMessageDefaultDecls(g, f, m)
 	genMessageMethods(g, f, m)
 	genMessageOneofWrapperTypes(g, f, m)
diff --git a/cmd/protoc-gen-go/internal_gengo/well_known_types.go b/cmd/protoc-gen-go/internal_gengo/well_known_types.go
new file mode 100644
index 0000000..99f3e44
--- /dev/null
+++ b/cmd/protoc-gen-go/internal_gengo/well_known_types.go
@@ -0,0 +1,723 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package internal_gengo
+
+import (
+	"strings"
+
+	"google.golang.org/protobuf/compiler/protogen"
+	"google.golang.org/protobuf/internal/genid"
+)
+
+// Specialized support for well-known types are hard-coded into the generator
+// as opposed to being injected in adjacent .go sources in the generated package
+// in order to support specialized build systems like Bazel that always generate
+// dynamically from the source .proto files.
+
+func genMessageKnownFunctions(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) {
+	switch m.Desc.FullName() {
+	case genid.Any_message_fullname:
+		g.P("// MarshalFrom marshals src into dst as the underlying message")
+		g.P("// using the provided marshal options.")
+		g.P("//")
+		g.P("// If no options are specified, call dst.MarshalFrom instead.")
+		g.P("func MarshalFrom(dst *Any, src ", protoPackage.Ident("Message"), ", opts ", protoPackage.Ident("MarshalOptions"), ") error {")
+		g.P("	const urlPrefix = \"type.googleapis.com/\"")
+		g.P("	b, err := opts.Marshal(src)")
+		g.P("	if err != nil {")
+		g.P("		return err")
+		g.P("	}")
+		g.P("	dst.TypeUrl = urlPrefix + string(src.ProtoReflect().Descriptor().FullName())")
+		g.P("	dst.Value = b")
+		g.P("	return nil")
+		g.P("}")
+		g.P()
+
+		g.P("// UnmarshalTo unmarshals the underlying message from src into dst")
+		g.P("// using the provided unmarshal options.")
+		g.P("// It reports an error if dst is not of the right message type.")
+		g.P("//")
+		g.P("// If no options are specified, call src.UnmarshalTo instead.")
+		g.P("func UnmarshalTo(src *Any, dst ", protoPackage.Ident("Message"), ", opts ", protoPackage.Ident("UnmarshalOptions"), ") error {")
+		g.P("	if !src.MessageIs(dst) {")
+		g.P("		got := dst.ProtoReflect().Descriptor().FullName()")
+		g.P("		want := src.MessageName()")
+		g.P("		return ", protoimplPackage.Ident("X"), ".NewError(\"mismatching message types: got %q, want %q\", got, want)")
+		g.P("	}")
+		g.P("	return opts.Unmarshal(src.GetValue(), dst)")
+		g.P("}")
+		g.P()
+
+		g.P("// UnmarshalNew unmarshals the underlying message from src into dst,")
+		g.P("// which is newly created message using a type resolved from the type URL.")
+		g.P("// The message type is resolved according to opt.Resolver,")
+		g.P("// which should implement protoregistry.MessageTypeResolver.")
+		g.P("// It reports an error if the underlying message type could not be resolved.")
+		g.P("//")
+		g.P("// If no options are specified, call src.UnmarshalNew instead.")
+		g.P("func UnmarshalNew(src *Any, opts ", protoPackage.Ident("UnmarshalOptions"), ") (dst ", protoPackage.Ident("Message"), ", err error) {")
+		g.P("	if src.GetTypeUrl() == \"\" {")
+		g.P("		return nil, ", protoimplPackage.Ident("X"), ".NewError(\"invalid empty type URL\")")
+		g.P("	}")
+		g.P("	if opts.Resolver == nil {")
+		g.P("		opts.Resolver = ", protoregistryPackage.Ident("GlobalTypes"))
+		g.P("	}")
+		g.P("	r, ok := opts.Resolver.(", protoregistryPackage.Ident("MessageTypeResolver"), ")")
+		g.P("	if !ok {")
+		g.P("		return nil, ", protoregistryPackage.Ident("NotFound"))
+		g.P("	}")
+		g.P("	mt, err := r.FindMessageByURL(src.GetTypeUrl())")
+		g.P("	if err != nil {")
+		g.P("		if err == ", protoregistryPackage.Ident("NotFound"), " {")
+		g.P("			return nil, err")
+		g.P("		}")
+		g.P("		return nil, ", protoimplPackage.Ident("X"), ".NewError(\"could not resolve %q: %v\", src.GetTypeUrl(), err)")
+		g.P("	}")
+		g.P("	dst = mt.New().Interface()")
+		g.P("	return dst, opts.Unmarshal(src.GetValue(), dst)")
+		g.P("}")
+		g.P()
+
+		g.P("// MessageIs reports whether the underlying message is of the same type as m.")
+		g.P("func (x *Any) MessageIs(m ", protoPackage.Ident("Message"), ") bool {")
+		g.P("	if m == nil {")
+		g.P("		return false")
+		g.P("	}")
+		g.P("	url := x.GetTypeUrl()")
+		g.P("	name := string(m.ProtoReflect().Descriptor().FullName())")
+		g.P("	if !", stringsPackage.Ident("HasSuffix"), "(url, name) {")
+		g.P("		return false")
+		g.P("	}")
+		g.P("	return len(url) == len(name) || url[len(url)-len(name)-1] == '/'")
+		g.P("}")
+		g.P()
+
+		g.P("// MessageName reports the full name of the underlying message,")
+		g.P("// returning an empty string if invalid.")
+		g.P("func (x *Any) MessageName() ", protoreflectPackage.Ident("FullName"), " {")
+		g.P("	url := x.GetTypeUrl()")
+		g.P("	name := ", protoreflectPackage.Ident("FullName"), "(url)")
+		g.P("	if i := ", stringsPackage.Ident("LastIndexByte"), "(url, '/'); i >= 0 {")
+		g.P("		name = name[i+len(\"/\"):]")
+		g.P("	}")
+		g.P("	if !name.IsValid() {")
+		g.P("		return \"\"")
+		g.P("	}")
+		g.P("	return name")
+		g.P("}")
+		g.P()
+
+		g.P("// MarshalFrom marshals m into x as the underlying message.")
+		g.P("func (x *Any) MarshalFrom(m ", protoPackage.Ident("Message"), ") error {")
+		g.P("	return MarshalFrom(x, m, ", protoPackage.Ident("MarshalOptions"), "{})")
+		g.P("}")
+		g.P()
+
+		g.P("// UnmarshalTo unmarshals the contents of the underlying message of x into m.")
+		g.P("// It resets m before performing the unmarshal operation.")
+		g.P("// It reports an error if m is not of the right message type.")
+		g.P("func (x *Any) UnmarshalTo(m ", protoPackage.Ident("Message"), ") error {")
+		g.P("	return UnmarshalTo(x, m, ", protoPackage.Ident("UnmarshalOptions"), "{})")
+		g.P("}")
+		g.P()
+
+		g.P("// UnmarshalNew unmarshals the contents of the underlying message of x into")
+		g.P("// a newly allocated message of the specified type.")
+		g.P("// It reports an error if the underlying message type could not be resolved.")
+		g.P("func (x *Any) UnmarshalNew() (", protoPackage.Ident("Message"), ", error) {")
+		g.P("	return UnmarshalNew(x, ", protoPackage.Ident("UnmarshalOptions"), "{})")
+		g.P("}")
+		g.P()
+
+	case genid.Timestamp_message_fullname:
+		g.P("// Now constructs a new Timestamp from the current time.")
+		g.P("func Now() *Timestamp {")
+		g.P("	return New(", timePackage.Ident("Now"), "())")
+		g.P("}")
+		g.P()
+
+		g.P("// New constructs a new Timestamp from the provided time.Time.")
+		g.P("func New(t ", timePackage.Ident("Time"), ") *Timestamp {")
+		g.P("	return &Timestamp{Seconds: int64(t.Unix()), Nanos: int32(t.Nanosecond())}")
+		g.P("}")
+		g.P()
+
+		g.P("// AsTime converts x to a time.Time.")
+		g.P("func (x *Timestamp) AsTime() ", timePackage.Ident("Time"), " {")
+		g.P("	return ", timePackage.Ident("Unix"), "(int64(x.GetSeconds()), int64(x.GetNanos())).UTC()")
+		g.P("}")
+		g.P()
+
+		g.P("// IsValid reports whether the timestamp is valid.")
+		g.P("// It is equivalent to CheckValid == nil.")
+		g.P("func (x *Timestamp) IsValid() bool {")
+		g.P("	return x.check() == 0")
+		g.P("}")
+		g.P()
+
+		g.P("// CheckValid returns an error if the timestamp is invalid.")
+		g.P("// In particular, it checks whether the value represents a date that is")
+		g.P("// in the range of 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive.")
+		g.P("func (x *Timestamp) CheckValid() error {")
+		g.P("	switch x.check() {")
+		g.P("	case invalidUnderflow:")
+		g.P("		return ", protoimplPackage.Ident("X"), ".NewError(\"timestamp (%v) before 0001-01-01\", x)")
+		g.P("	case invalidOverflow:")
+		g.P("		return ", protoimplPackage.Ident("X"), ".NewError(\"timestamp (%v) after 9999-12-31\", x)")
+		g.P("	case invalidNanos:")
+		g.P("		return ", protoimplPackage.Ident("X"), ".NewError(\"timestamp (%v) has out-of-range nanos\", x)")
+		g.P("	default:")
+		g.P("		return nil")
+		g.P("	}")
+		g.P("}")
+		g.P()
+
+		g.P("const invalidUnderflow = 1")
+		g.P("const invalidOverflow = 2")
+		g.P("const invalidNanos = 3")
+		g.P()
+
+		g.P("func (x *Timestamp) check() uint {")
+		g.P("	const minTimestamp = -62135596800  // Seconds between 1970-01-01T00:00:00Z and 0001-01-01T00:00:00Z, inclusive")
+		g.P("	const maxTimestamp = +253402300799 // Seconds between 1970-01-01T00:00:00Z and 9999-12-31T23:59:59Z, inclusive")
+		g.P("	secs := x.GetSeconds()")
+		g.P("	nanos := x.GetNanos()")
+		g.P("	switch {")
+		g.P("	case secs < minTimestamp:")
+		g.P("		return invalidUnderflow")
+		g.P("	case secs > maxTimestamp:")
+		g.P("		return invalidOverflow")
+		g.P("	case nanos < 0 || nanos >= 1e9:")
+		g.P("		return invalidNanos")
+		g.P("	default:")
+		g.P("		return 0")
+		g.P("	}")
+		g.P("}")
+		g.P()
+
+	case genid.Duration_message_fullname:
+		g.P("// New constructs a new Duration from the provided time.Duration.")
+		g.P("func New(d ", timePackage.Ident("Duration"), ") *Duration {")
+		g.P("	nanos := d.Nanoseconds()")
+		g.P("	secs := nanos / 1e9")
+		g.P("	nanos -= secs * 1e9")
+		g.P("	return &Duration{Seconds: int64(secs), Nanos: int32(nanos)}")
+		g.P("}")
+		g.P()
+
+		g.P("// AsDuration converts x to a time.Duration,")
+		g.P("// returning the closest duration value in the event of overflow.")
+		g.P("func (x *Duration) AsDuration() ", timePackage.Ident("Duration"), " {")
+		g.P("	secs := x.GetSeconds()")
+		g.P("	nanos := x.GetNanos()")
+		g.P("	d := ", timePackage.Ident("Duration"), "(secs) * ", timePackage.Ident("Second"))
+		g.P("	overflow := d/", timePackage.Ident("Second"), " != ", timePackage.Ident("Duration"), "(secs)")
+		g.P("	d += ", timePackage.Ident("Duration"), "(nanos) * ", timePackage.Ident("Nanosecond"))
+		g.P("	overflow = overflow || (secs < 0 && nanos < 0 && d > 0)")
+		g.P("	overflow = overflow || (secs > 0 && nanos > 0 && d < 0)")
+		g.P("	if overflow {")
+		g.P("		switch {")
+		g.P("		case secs < 0:")
+		g.P("			return ", timePackage.Ident("Duration"), "(", mathPackage.Ident("MinInt64"), ")")
+		g.P("		case secs > 0:")
+		g.P("			return ", timePackage.Ident("Duration"), "(", mathPackage.Ident("MaxInt64"), ")")
+		g.P("		}")
+		g.P("	}")
+		g.P("	return d")
+		g.P("}")
+		g.P()
+
+		g.P("// IsValid reports whether the duration is valid.")
+		g.P("// It is equivalent to CheckValid == nil.")
+		g.P("func (x *Duration) IsValid() bool {")
+		g.P("	return x.check() == 0")
+		g.P("}")
+		g.P()
+
+		g.P("// CheckValid returns an error if the duration is invalid.")
+		g.P("// In particular, it checks whether the value is within the range of")
+		g.P("// -10000 years to +10000 years inclusive.")
+		g.P("func (x *Duration) CheckValid() error {")
+		g.P("	switch x.check() {")
+		g.P("	case invalidUnderflow:")
+		g.P("		return ", protoimplPackage.Ident("X"), ".NewError(\"duration (%v) exceeds -10000 years\", x)")
+		g.P("	case invalidOverflow:")
+		g.P("		return ", protoimplPackage.Ident("X"), ".NewError(\"duration (%v) exceeds +10000 years\", x)")
+		g.P("	case invalidNanosRange:")
+		g.P("		return ", protoimplPackage.Ident("X"), ".NewError(\"duration (%v) has out-of-range nanos\", x)")
+		g.P("	case invalidNanosSign:")
+		g.P("		return ", protoimplPackage.Ident("X"), ".NewError(\"duration (%v) has seconds and nanos with different signs\", x)")
+		g.P("	default:")
+		g.P("		return nil")
+		g.P("	}")
+		g.P("}")
+		g.P()
+
+		g.P("const invalidUnderflow = 1")
+		g.P("const invalidOverflow = 2")
+		g.P("const invalidNanosRange = 3")
+		g.P("const invalidNanosSign = 4")
+		g.P()
+
+		g.P("func (x *Duration) check() uint {")
+		g.P("	const absDuration = 315576000000 // 10000yr * 365.25day/yr * 24hr/day * 60min/hr * 60sec/min")
+		g.P("	secs := x.GetSeconds()")
+		g.P("	nanos := x.GetNanos()")
+		g.P("	switch {")
+		g.P("	case secs < -absDuration:")
+		g.P("		return invalidUnderflow")
+		g.P("	case secs > +absDuration:")
+		g.P("		return invalidOverflow")
+		g.P("	case nanos <= -1e9 || nanos >= +1e9:")
+		g.P("		return invalidNanosRange")
+		g.P("	case (secs > 0 && nanos < 0) || (secs < 0 && nanos > 0):")
+		g.P("		return invalidNanosSign")
+		g.P("	default:")
+		g.P("		return 0")
+		g.P("	}")
+		g.P("}")
+		g.P()
+
+	case genid.Struct_message_fullname:
+		g.P("// NewStruct constructs a Struct from a general-purpose Go map.")
+		g.P("// The map keys must be valid UTF-8.")
+		g.P("// The map values are converted using NewValue.")
+		g.P("func NewStruct(v map[string]interface{}) (*Struct, error) {")
+		g.P("	x := &Struct{Fields: make(map[string]*Value, len(v))}")
+		g.P("	for k, v := range v {")
+		g.P("		if !", utf8Package.Ident("ValidString"), "(k) {")
+		g.P("			return nil, ", protoimplPackage.Ident("X"), ".NewError(\"invalid UTF-8 in string: %q\", k)")
+		g.P("		}")
+		g.P("		var err error")
+		g.P("		x.Fields[k], err = NewValue(v)")
+		g.P("		if err != nil {")
+		g.P("			return nil, err")
+		g.P("		}")
+		g.P("	}")
+		g.P("	return x, nil")
+		g.P("}")
+		g.P()
+
+		g.P("// AsMap converts x to a general-purpose Go map.")
+		g.P("// The map values are converted by calling Value.AsInterface.")
+		g.P("func (x *Struct) AsMap() map[string]interface{} {")
+		g.P("	vs := make(map[string]interface{})")
+		g.P("	for k, v := range x.GetFields() {")
+		g.P("		vs[k] = v.AsInterface()")
+		g.P("	}")
+		g.P("	return vs")
+		g.P("}")
+		g.P()
+
+		g.P("func (x *Struct) MarshalJSON() ([]byte, error) {")
+		g.P("	return ", protojsonPackage.Ident("Marshal"), "(x)")
+		g.P("}")
+		g.P()
+
+		g.P("func (x *Struct) UnmarshalJSON(b []byte) error {")
+		g.P("	return ", protojsonPackage.Ident("Unmarshal"), "(b, x)")
+		g.P("}")
+		g.P()
+
+	case genid.ListValue_message_fullname:
+		g.P("// NewList constructs a ListValue from a general-purpose Go slice.")
+		g.P("// The slice elements are converted using NewValue.")
+		g.P("func NewList(v []interface{}) (*ListValue, error) {")
+		g.P("	x := &ListValue{Values: make([]*Value, len(v))}")
+		g.P("	for i, v := range v {")
+		g.P("		var err error")
+		g.P("		x.Values[i], err = NewValue(v)")
+		g.P("		if err != nil {")
+		g.P("			return nil, err")
+		g.P("		}")
+		g.P("	}")
+		g.P("	return x, nil")
+		g.P("}")
+		g.P()
+
+		g.P("// AsSlice converts x to a general-purpose Go slice.")
+		g.P("// The slice elements are converted by calling Value.AsInterface.")
+		g.P("func (x *ListValue) AsSlice() []interface{} {")
+		g.P("	vs := make([]interface{}, len(x.GetValues()))")
+		g.P("	for i, v := range x.GetValues() {")
+		g.P("		vs[i] = v.AsInterface()")
+		g.P("	}")
+		g.P("	return vs")
+		g.P("}")
+		g.P()
+
+		g.P("func (x *ListValue) MarshalJSON() ([]byte, error) {")
+		g.P("	return ", protojsonPackage.Ident("Marshal"), "(x)")
+		g.P("}")
+		g.P()
+
+		g.P("func (x *ListValue) UnmarshalJSON(b []byte) error {")
+		g.P("	return ", protojsonPackage.Ident("Unmarshal"), "(b, x)")
+		g.P("}")
+		g.P()
+
+	case genid.Value_message_fullname:
+		g.P("// NewValue constructs a Value from a general-purpose Go interface.")
+		g.P("//")
+		g.P("//	╔════════════════════════╤════════════════════════════════════════════╗")
+		g.P("//	║ Go type                │ Conversion                                 ║")
+		g.P("//	╠════════════════════════╪════════════════════════════════════════════╣")
+		g.P("//	║ nil                    │ stored as NullValue                        ║")
+		g.P("//	║ bool                   │ stored as BoolValue                        ║")
+		g.P("//	║ int, int32, int64      │ stored as NumberValue                      ║")
+		g.P("//	║ uint, uint32, uint64   │ stored as NumberValue                      ║")
+		g.P("//	║ float32, float64       │ stored as NumberValue                      ║")
+		g.P("//	║ string                 │ stored as StringValue; must be valid UTF-8 ║")
+		g.P("//	║ []byte                 │ stored as StringValue; base64-encoded      ║")
+		g.P("//	║ map[string]interface{} │ stored as StructValue                      ║")
+		g.P("//	║ []interface{}          │ stored as ListValue                        ║")
+		g.P("//	╚════════════════════════╧════════════════════════════════════════════╝")
+		g.P("//")
+		g.P("// When converting an int64 or uint64 to a NumberValue, numeric precision loss")
+		g.P("// is possible since they are stored as a float64.")
+		g.P("func NewValue(v interface{}) (*Value, error) {")
+		g.P("	switch v := v.(type) {")
+		g.P("	case nil:")
+		g.P("		return NewNullValue(), nil")
+		g.P("	case bool:")
+		g.P("		return NewBoolValue(v), nil")
+		g.P("	case int:")
+		g.P("		return NewNumberValue(float64(v)), nil")
+		g.P("	case int32:")
+		g.P("		return NewNumberValue(float64(v)), nil")
+		g.P("	case int64:")
+		g.P("		return NewNumberValue(float64(v)), nil")
+		g.P("	case uint:")
+		g.P("		return NewNumberValue(float64(v)), nil")
+		g.P("	case uint32:")
+		g.P("		return NewNumberValue(float64(v)), nil")
+		g.P("	case uint64:")
+		g.P("		return NewNumberValue(float64(v)), nil")
+		g.P("	case float32:")
+		g.P("		return NewNumberValue(float64(v)), nil")
+		g.P("	case float64:")
+		g.P("		return NewNumberValue(float64(v)), nil")
+		g.P("	case string:")
+		g.P("		if !", utf8Package.Ident("ValidString"), "(v) {")
+		g.P("			return nil, ", protoimplPackage.Ident("X"), ".NewError(\"invalid UTF-8 in string: %q\", v)")
+		g.P("		}")
+		g.P("		return NewStringValue(v), nil")
+		g.P("	case []byte:")
+		g.P("		s := ", base64Package.Ident("StdEncoding"), ".EncodeToString(v)")
+		g.P("		return NewStringValue(s), nil")
+		g.P("	case map[string]interface{}:")
+		g.P("		v2, err := NewStruct(v)")
+		g.P("		if err != nil {")
+		g.P("			return nil, err")
+		g.P("		}")
+		g.P("		return NewStructValue(v2), nil")
+		g.P("	case []interface{}:")
+		g.P("		v2, err := NewList(v)")
+		g.P("		if err != nil {")
+		g.P("			return nil, err")
+		g.P("		}")
+		g.P("		return NewListValue(v2), nil")
+		g.P("	default:")
+		g.P("		return nil, ", protoimplPackage.Ident("X"), ".NewError(\"invalid type: %T\", v)")
+		g.P("	}")
+		g.P("}")
+		g.P()
+
+		g.P("// NewNullValue constructs a new null Value.")
+		g.P("func NewNullValue() *Value {")
+		g.P("	return &Value{Kind: &Value_NullValue{NullValue: NullValue_NULL_VALUE}}")
+		g.P("}")
+		g.P()
+
+		g.P("// NewBoolValue constructs a new boolean Value.")
+		g.P("func NewBoolValue(v bool) *Value {")
+		g.P("	return &Value{Kind: &Value_BoolValue{BoolValue: v}}")
+		g.P("}")
+		g.P()
+
+		g.P("// NewNumberValue constructs a new number Value.")
+		g.P("func NewNumberValue(v float64) *Value {")
+		g.P("	return &Value{Kind: &Value_NumberValue{NumberValue: v}}")
+		g.P("}")
+		g.P()
+
+		g.P("// NewStringValue constructs a new string Value.")
+		g.P("func NewStringValue(v string) *Value {")
+		g.P("	return &Value{Kind: &Value_StringValue{StringValue: v}}")
+		g.P("}")
+		g.P()
+
+		g.P("// NewStructValue constructs a new struct Value.")
+		g.P("func NewStructValue(v *Struct) *Value {")
+		g.P("	return &Value{Kind: &Value_StructValue{StructValue: v}}")
+		g.P("}")
+		g.P()
+
+		g.P("// NewListValue constructs a new list Value.")
+		g.P("func NewListValue(v *ListValue) *Value {")
+		g.P("	return &Value{Kind: &Value_ListValue{ListValue: v}}")
+		g.P("}")
+		g.P()
+
+		g.P("// AsInterface converts x to a general-purpose Go interface.")
+		g.P("//")
+		g.P("// Calling Value.MarshalJSON and \"encoding/json\".Marshal on this output produce")
+		g.P("// semantically equivalent JSON (assuming no errors occur).")
+		g.P("//")
+		g.P("// Floating-point values (i.e., \"NaN\", \"Infinity\", and \"-Infinity\") are")
+		g.P("// converted as strings to remain compatible with MarshalJSON.")
+		g.P("func (x *Value) AsInterface() interface{} {")
+		g.P("	switch v := x.GetKind().(type) {")
+		g.P("	case *Value_NumberValue:")
+		g.P("		if v != nil {")
+		g.P("			switch {")
+		g.P("			case ", mathPackage.Ident("IsNaN"), "(v.NumberValue):")
+		g.P("				return \"NaN\"")
+		g.P("			case ", mathPackage.Ident("IsInf"), "(v.NumberValue, +1):")
+		g.P("				return \"Infinity\"")
+		g.P("			case ", mathPackage.Ident("IsInf"), "(v.NumberValue, -1):")
+		g.P("				return \"-Infinity\"")
+		g.P("			default:")
+		g.P("				return v.NumberValue")
+		g.P("			}")
+		g.P("		}")
+		g.P("	case *Value_StringValue:")
+		g.P("		if v != nil {")
+		g.P("			return v.StringValue")
+		g.P("		}")
+		g.P("	case *Value_BoolValue:")
+		g.P("		if v != nil {")
+		g.P("			return v.BoolValue")
+		g.P("		}")
+		g.P("	case *Value_StructValue:")
+		g.P("		if v != nil {")
+		g.P("			return v.StructValue.AsMap()")
+		g.P("		}")
+		g.P("	case *Value_ListValue:")
+		g.P("		if v != nil {")
+		g.P("			return v.ListValue.AsSlice()")
+		g.P("		}")
+		g.P("	}")
+		g.P("	return nil")
+		g.P("}")
+		g.P()
+
+		g.P("func (x *Value) MarshalJSON() ([]byte, error) {")
+		g.P("	return ", protojsonPackage.Ident("Marshal"), "(x)")
+		g.P("}")
+		g.P()
+
+		g.P("func (x *Value) UnmarshalJSON(b []byte) error {")
+		g.P("	return ", protojsonPackage.Ident("Unmarshal"), "(b, x)")
+		g.P("}")
+		g.P()
+
+	case genid.FieldMask_message_fullname:
+		g.P("// New constructs a field mask from a list of paths and verifies that")
+		g.P("// each one is valid according to the specified message type.")
+		g.P("func New(m ", protoPackage.Ident("Message"), ", paths ...string) (*FieldMask, error) {")
+		g.P("	x := new(FieldMask)")
+		g.P("	return x, x.Append(m, paths...)")
+		g.P("}")
+		g.P()
+
+		g.P("// Union returns the union of all the paths in the input field masks.")
+		g.P("func Union(mx *FieldMask, my *FieldMask, ms ...*FieldMask) *FieldMask {")
+		g.P("	var out []string")
+		g.P("	out = append(out, mx.GetPaths()...)")
+		g.P("	out = append(out, my.GetPaths()...)")
+		g.P("	for _, m := range ms {")
+		g.P("		out = append(out, m.GetPaths()...)")
+		g.P("	}")
+		g.P("	return &FieldMask{Paths: normalizePaths(out)}")
+		g.P("}")
+		g.P()
+
+		g.P("// Intersect returns the intersection of all the paths in the input field masks.")
+		g.P("func Intersect(mx *FieldMask, my *FieldMask, ms ...*FieldMask) *FieldMask {")
+		g.P("	var ss1, ss2 []string // reused buffers for performance")
+		g.P("	intersect := func(out, in []string) []string {")
+		g.P("		ss1 = normalizePaths(append(ss1[:0], in...))")
+		g.P("		ss2 = normalizePaths(append(ss2[:0], out...))")
+		g.P("		out = out[:0]")
+		g.P("		for i1, i2 := 0, 0; i1 < len(ss1) && i2 < len(ss2); {")
+		g.P("			switch s1, s2 := ss1[i1], ss2[i2]; {")
+		g.P("			case hasPathPrefix(s1, s2):")
+		g.P("				out = append(out, s1)")
+		g.P("				i1++")
+		g.P("			case hasPathPrefix(s2, s1):")
+		g.P("				out = append(out, s2)")
+		g.P("				i2++")
+		g.P("			case lessPath(s1, s2):")
+		g.P("				i1++")
+		g.P("			case lessPath(s2, s1):")
+		g.P("				i2++")
+		g.P("			}")
+		g.P("		}")
+		g.P("		return out")
+		g.P("	}")
+		g.P()
+		g.P("	out := Union(mx, my, ms...).GetPaths()")
+		g.P("	out = intersect(out, mx.GetPaths())")
+		g.P("	out = intersect(out, my.GetPaths())")
+		g.P("	for _, m := range ms {")
+		g.P("		out = intersect(out, m.GetPaths())")
+		g.P("	}")
+		g.P("	return &FieldMask{Paths: normalizePaths(out)}")
+		g.P("}")
+		g.P()
+
+		g.P("// IsValid reports whether all the paths are syntactically valid and")
+		g.P("// refer to known fields in the specified message type.")
+		g.P("func (x *FieldMask) IsValid(m ", protoPackage.Ident("Message"), ") bool {")
+		g.P("	paths := x.GetPaths()")
+		g.P("	return numValidPaths(m, paths) == len(paths)")
+		g.P("}")
+		g.P()
+
+		g.P("// Append appends a list of paths to the mask and verifies that each one")
+		g.P("// is valid according to the specified message type.")
+		g.P("// An invalid path is not appended and breaks insertion of subsequent paths.")
+		g.P("func (x *FieldMask) Append(m ", protoPackage.Ident("Message"), ", paths ...string) error {")
+		g.P("	numValid := numValidPaths(m, paths)")
+		g.P("	x.Paths = append(x.Paths, paths[:numValid]...)")
+		g.P("	paths = paths[numValid:]")
+		g.P("	if len(paths) > 0 {")
+		g.P("		name := m.ProtoReflect().Descriptor().FullName()")
+		g.P("		return ", protoimplPackage.Ident("X"), ".NewError(\"invalid path %q for message %q\", paths[0], name)")
+		g.P("	}")
+		g.P("	return nil")
+		g.P("}")
+		g.P()
+
+		g.P("func numValidPaths(m ", protoPackage.Ident("Message"), ", paths []string) int {")
+		g.P("	md0 := m.ProtoReflect().Descriptor()")
+		g.P("	for i, path := range paths {")
+		g.P("		md := md0")
+		g.P("		if !rangeFields(path, func(field string) bool {")
+		g.P("			// Search the field within the message.")
+		g.P("			if md == nil {")
+		g.P("				return false // not within a message")
+		g.P("			}")
+		g.P("			fd := md.Fields().ByName(", protoreflectPackage.Ident("Name"), "(field))")
+		g.P("			// The real field name of a group is the message name.")
+		g.P("			if fd == nil {")
+		g.P("				gd := md.Fields().ByName(", protoreflectPackage.Ident("Name"), "(", stringsPackage.Ident("ToLower"), "(field)))")
+		g.P("				if gd != nil && gd.Kind() == ", protoreflectPackage.Ident("GroupKind"), " && string(gd.Message().Name()) == field {")
+		g.P("					fd = gd")
+		g.P("				}")
+		g.P("			} else if fd.Kind() == ", protoreflectPackage.Ident("GroupKind"), " && string(fd.Message().Name()) != field {")
+		g.P("				fd = nil")
+		g.P("			}")
+		g.P("			if fd == nil {")
+		g.P("				return false // message has does not have this field")
+		g.P("			}")
+		g.P()
+		g.P("			// Identify the next message to search within.")
+		g.P("			md = fd.Message() // may be nil")
+		g.P("			if fd.IsMap() {")
+		g.P("				md = fd.MapValue().Message() // may be nil")
+		g.P("			}")
+		g.P("			return true")
+		g.P("		}) {")
+		g.P("			return i")
+		g.P("		}")
+		g.P("	}")
+		g.P("	return len(paths)")
+		g.P("}")
+		g.P()
+
+		g.P("// Normalize converts the mask to its canonical form where all paths are sorted")
+		g.P("// and redundant paths are removed.")
+		g.P("func (x *FieldMask) Normalize() {")
+		g.P("	x.Paths = normalizePaths(x.Paths)")
+		g.P("}")
+		g.P()
+		g.P("func normalizePaths(paths []string) []string {")
+		g.P("	", sortPackage.Ident("Slice"), "(paths, func(i, j int) bool {")
+		g.P("		return lessPath(paths[i], paths[j])")
+		g.P("	})")
+		g.P()
+		g.P("	// Elide any path that is a prefix match on the previous.")
+		g.P("	out := paths[:0]")
+		g.P("	for _, path := range paths {")
+		g.P("		if len(out) > 0 && hasPathPrefix(path, out[len(out)-1]) {")
+		g.P("			continue")
+		g.P("		}")
+		g.P("		out = append(out, path)")
+		g.P("	}")
+		g.P("	return out")
+		g.P("}")
+		g.P()
+
+		g.P("// hasPathPrefix is like strings.HasPrefix, but further checks for either")
+		g.P("// an exact matche or that the prefix is delimited by a dot.")
+		g.P("func hasPathPrefix(path, prefix string) bool {")
+		g.P("	return ", stringsPackage.Ident("HasPrefix"), "(path, prefix) && (len(path) == len(prefix) || path[len(prefix)] == '.')")
+		g.P("}")
+		g.P()
+
+		g.P("// lessPath is a lexicographical comparison where dot is specially treated")
+		g.P("// as the smallest symbol.")
+		g.P("func lessPath(x, y string) bool {")
+		g.P("	for i := 0; i < len(x) && i < len(y); i++ {")
+		g.P("		if x[i] != y[i] {")
+		g.P("			return (x[i] - '.') < (y[i] - '.')")
+		g.P("		}")
+		g.P("	}")
+		g.P("	return len(x) < len(y)")
+		g.P("}")
+		g.P()
+
+		g.P("// rangeFields is like strings.Split(path, \".\"), but avoids allocations by")
+		g.P("// iterating over each field in place and calling a iterator function.")
+		g.P("func rangeFields(path string, f func(field string) bool) bool {")
+		g.P("	for {")
+		g.P("		var field string")
+		g.P("		if i := ", stringsPackage.Ident("IndexByte"), "(path, '.'); i >= 0 {")
+		g.P("			field, path = path[:i], path[i:]")
+		g.P("		} else {")
+		g.P("			field, path = path, \"\"")
+		g.P("		}")
+		g.P()
+		g.P("		if !f(field) {")
+		g.P("			return false")
+		g.P("		}")
+		g.P()
+		g.P("		if len(path) == 0 {")
+		g.P("			return true")
+		g.P("		}")
+		g.P("		path = ", stringsPackage.Ident("TrimPrefix"), "(path, \".\")")
+		g.P("	}")
+		g.P("}")
+		g.P()
+
+	case genid.BoolValue_message_fullname,
+		genid.Int32Value_message_fullname,
+		genid.Int64Value_message_fullname,
+		genid.UInt32Value_message_fullname,
+		genid.UInt64Value_message_fullname,
+		genid.FloatValue_message_fullname,
+		genid.DoubleValue_message_fullname,
+		genid.StringValue_message_fullname,
+		genid.BytesValue_message_fullname:
+		funcName := strings.TrimSuffix(m.GoIdent.GoName, "Value")
+		typeName := strings.ToLower(funcName)
+		switch typeName {
+		case "float":
+			typeName = "float32"
+		case "double":
+			typeName = "float64"
+		case "bytes":
+			typeName = "[]byte"
+		}
+
+		g.P("// ", funcName, " stores v in a new ", m.GoIdent, " and returns a pointer to it.")
+		g.P("func ", funcName, "(v ", typeName, ") *", m.GoIdent, " {")
+		g.P("	return &", m.GoIdent, "{Value: v}")
+		g.P("}")
+		g.P()
+	}
+}
diff --git a/internal/impl/api_export.go b/internal/impl/api_export.go
index 4d22c96..b597452 100644
--- a/internal/impl/api_export.go
+++ b/internal/impl/api_export.go
@@ -10,6 +10,7 @@
 	"strconv"
 
 	"google.golang.org/protobuf/encoding/prototext"
+	"google.golang.org/protobuf/internal/errors"
 	"google.golang.org/protobuf/proto"
 	pref "google.golang.org/protobuf/reflect/protoreflect"
 	piface "google.golang.org/protobuf/runtime/protoiface"
@@ -19,6 +20,12 @@
 // functions that we do not want to appear in godoc.
 type Export struct{}
 
+// NewError formats a string according to the format specifier and arguments and
+// returns an error that has a "proto" prefix.
+func (Export) NewError(f string, x ...interface{}) error {
+	return errors.New(f, x...)
+}
+
 // enum is any enum type generated by protoc-gen-go
 // and must be a named int32 type.
 type enum = interface{}
diff --git a/types/known/anypb/any.pb.go b/types/known/anypb/any.pb.go
index 5f9498e..775d839 100644
--- a/types/known/anypb/any.pb.go
+++ b/types/known/anypb/any.pb.go
@@ -34,9 +34,12 @@
 package anypb
 
 import (
+	proto "google.golang.org/protobuf/proto"
 	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoregistry "google.golang.org/protobuf/reflect/protoregistry"
 	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
 	reflect "reflect"
+	strings "strings"
 	sync "sync"
 )
 
@@ -158,6 +161,110 @@
 	Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
 }
 
+// MarshalFrom marshals src into dst as the underlying message
+// using the provided marshal options.
+//
+// If no options are specified, call dst.MarshalFrom instead.
+func MarshalFrom(dst *Any, src proto.Message, opts proto.MarshalOptions) error {
+	const urlPrefix = "type.googleapis.com/"
+	b, err := opts.Marshal(src)
+	if err != nil {
+		return err
+	}
+	dst.TypeUrl = urlPrefix + string(src.ProtoReflect().Descriptor().FullName())
+	dst.Value = b
+	return nil
+}
+
+// UnmarshalTo unmarshals the underlying message from src into dst
+// using the provided unmarshal options.
+// It reports an error if dst is not of the right message type.
+//
+// If no options are specified, call src.UnmarshalTo instead.
+func UnmarshalTo(src *Any, dst proto.Message, opts proto.UnmarshalOptions) error {
+	if !src.MessageIs(dst) {
+		got := dst.ProtoReflect().Descriptor().FullName()
+		want := src.MessageName()
+		return protoimpl.X.NewError("mismatching message types: got %q, want %q", got, want)
+	}
+	return opts.Unmarshal(src.GetValue(), dst)
+}
+
+// UnmarshalNew unmarshals the underlying message from src into dst,
+// which is newly created message using a type resolved from the type URL.
+// The message type is resolved according to opt.Resolver,
+// which should implement protoregistry.MessageTypeResolver.
+// It reports an error if the underlying message type could not be resolved.
+//
+// If no options are specified, call src.UnmarshalNew instead.
+func UnmarshalNew(src *Any, opts proto.UnmarshalOptions) (dst proto.Message, err error) {
+	if src.GetTypeUrl() == "" {
+		return nil, protoimpl.X.NewError("invalid empty type URL")
+	}
+	if opts.Resolver == nil {
+		opts.Resolver = protoregistry.GlobalTypes
+	}
+	r, ok := opts.Resolver.(protoregistry.MessageTypeResolver)
+	if !ok {
+		return nil, protoregistry.NotFound
+	}
+	mt, err := r.FindMessageByURL(src.GetTypeUrl())
+	if err != nil {
+		if err == protoregistry.NotFound {
+			return nil, err
+		}
+		return nil, protoimpl.X.NewError("could not resolve %q: %v", src.GetTypeUrl(), err)
+	}
+	dst = mt.New().Interface()
+	return dst, opts.Unmarshal(src.GetValue(), dst)
+}
+
+// MessageIs reports whether the underlying message is of the same type as m.
+func (x *Any) MessageIs(m proto.Message) bool {
+	if m == nil {
+		return false
+	}
+	url := x.GetTypeUrl()
+	name := string(m.ProtoReflect().Descriptor().FullName())
+	if !strings.HasSuffix(url, name) {
+		return false
+	}
+	return len(url) == len(name) || url[len(url)-len(name)-1] == '/'
+}
+
+// MessageName reports the full name of the underlying message,
+// returning an empty string if invalid.
+func (x *Any) MessageName() protoreflect.FullName {
+	url := x.GetTypeUrl()
+	name := protoreflect.FullName(url)
+	if i := strings.LastIndexByte(url, '/'); i >= 0 {
+		name = name[i+len("/"):]
+	}
+	if !name.IsValid() {
+		return ""
+	}
+	return name
+}
+
+// MarshalFrom marshals m into x as the underlying message.
+func (x *Any) MarshalFrom(m proto.Message) error {
+	return MarshalFrom(x, m, proto.MarshalOptions{})
+}
+
+// UnmarshalTo unmarshals the contents of the underlying message of x into m.
+// It resets m before performing the unmarshal operation.
+// It reports an error if m is not of the right message type.
+func (x *Any) UnmarshalTo(m proto.Message) error {
+	return UnmarshalTo(x, m, proto.UnmarshalOptions{})
+}
+
+// UnmarshalNew unmarshals the contents of the underlying message of x into
+// a newly allocated message of the specified type.
+// It reports an error if the underlying message type could not be resolved.
+func (x *Any) UnmarshalNew() (proto.Message, error) {
+	return UnmarshalNew(x, proto.UnmarshalOptions{})
+}
+
 func (x *Any) Reset() {
 	*x = Any{}
 	if protoimpl.UnsafeEnabled {
diff --git a/types/known/anypb/any_test.go b/types/known/anypb/any_test.go
new file mode 100644
index 0000000..68e6391
--- /dev/null
+++ b/types/known/anypb/any_test.go
@@ -0,0 +1,184 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package anypb_test
+
+import (
+	"testing"
+
+	"github.com/google/go-cmp/cmp"
+	"google.golang.org/protobuf/proto"
+	"google.golang.org/protobuf/reflect/protoreflect"
+	"google.golang.org/protobuf/testing/protocmp"
+
+	testpb "google.golang.org/protobuf/internal/testprotos/test"
+	apb "google.golang.org/protobuf/types/known/anypb"
+	epb "google.golang.org/protobuf/types/known/emptypb"
+	wpb "google.golang.org/protobuf/types/known/wrapperspb"
+)
+
+func mustMarshal(m proto.Message) []byte {
+	b, err := proto.MarshalOptions{AllowPartial: true, Deterministic: true}.Marshal(m)
+	if err != nil {
+		panic(err)
+	}
+	return b
+}
+
+func TestMessage(t *testing.T) {
+	tests := []struct {
+		inAny    *apb.Any
+		inTarget proto.Message
+		wantIs   bool
+		wantName protoreflect.FullName
+	}{{
+		inAny:    nil,
+		inTarget: nil,
+		wantIs:   false,
+		wantName: "",
+	}, {
+		inAny:    new(apb.Any),
+		inTarget: nil,
+		wantIs:   false,
+		wantName: "",
+	}, {
+		inAny:    new(apb.Any),
+		inTarget: (*testpb.TestAllTypes)(nil),
+		wantIs:   false,
+		wantName: "",
+	}, {
+		inAny:    &apb.Any{TypeUrl: "foo"},
+		inTarget: (*testpb.TestAllTypes)(nil),
+		wantIs:   false,
+		wantName: "foo",
+	}, {
+		inAny:    &apb.Any{TypeUrl: "foo$"},
+		inTarget: (*testpb.TestAllTypes)(nil),
+		wantIs:   false,
+		wantName: "",
+	}, {
+		inAny:    &apb.Any{TypeUrl: "/foo"},
+		inTarget: (*testpb.TestAllTypes)(nil),
+		wantIs:   false,
+		wantName: "foo",
+	}, {
+		inAny:    &apb.Any{TypeUrl: "/bar/foo"},
+		inTarget: (*testpb.TestAllTypes)(nil),
+		wantIs:   false,
+		wantName: "foo",
+	}, {
+		inAny:    &apb.Any{TypeUrl: "google.golang.org/bar/foo"},
+		inTarget: (*testpb.TestAllTypes)(nil),
+		wantIs:   false,
+		wantName: "foo",
+	}, {
+		inAny:    &apb.Any{TypeUrl: "goproto.proto.test.TestAllTypes"},
+		inTarget: (*testpb.TestAllTypes)(nil),
+		wantIs:   true,
+		wantName: "goproto.proto.test.TestAllTypes",
+	}, {
+		inAny:    &apb.Any{TypeUrl: "goproto.proto.test.TestAllTypes$"},
+		inTarget: (*testpb.TestAllTypes)(nil),
+		wantIs:   false,
+		wantName: "",
+	}, {
+		inAny:    &apb.Any{TypeUrl: "/goproto.proto.test.TestAllTypes"},
+		inTarget: (*testpb.TestAllTypes)(nil),
+		wantIs:   true,
+		wantName: "goproto.proto.test.TestAllTypes",
+	}, {
+		inAny:    &apb.Any{TypeUrl: "google.golang.org/foo/goproto.proto.test.TestAllTypes"},
+		inTarget: (*testpb.TestAllTypes)(nil),
+		wantIs:   true,
+		wantName: "goproto.proto.test.TestAllTypes",
+	}}
+
+	for _, tt := range tests {
+		gotIs := tt.inAny.MessageIs(tt.inTarget)
+		if gotIs != tt.wantIs {
+			t.Errorf("MessageIs(%v, %v) = %v, want %v", tt.inAny, tt.inTarget, gotIs, tt.wantIs)
+		}
+		gotName := tt.inAny.MessageName()
+		if gotName != tt.wantName {
+			t.Errorf("MessageName(%v) = %v, want %v", tt.inAny, gotName, tt.wantName)
+		}
+	}
+}
+
+func TestRoundtrip(t *testing.T) {
+	tests := []struct {
+		msg proto.Message
+		any *apb.Any
+	}{{
+		msg: &testpb.TestAllTypes{},
+		any: &apb.Any{
+			TypeUrl: "type.googleapis.com/goproto.proto.test.TestAllTypes",
+		},
+	}, {
+		msg: &testpb.TestAllTypes{
+			OptionalString: proto.String("hello, world!"),
+		},
+		any: &apb.Any{
+			TypeUrl: "type.googleapis.com/goproto.proto.test.TestAllTypes",
+			Value: mustMarshal(&testpb.TestAllTypes{
+				OptionalString: proto.String("hello, world!"),
+			}),
+		},
+	}, {
+		msg: &wpb.StringValue{Value: ""},
+		any: &apb.Any{
+			TypeUrl: "type.googleapis.com/google.protobuf.StringValue",
+		},
+	}, {
+		msg: wpb.String("hello, world"),
+		any: &apb.Any{
+			TypeUrl: "type.googleapis.com/google.protobuf.StringValue",
+			Value:   mustMarshal(wpb.String("hello, world")),
+		},
+	}, {
+		msg: &apb.Any{
+			TypeUrl: "type.googleapis.com/google.protobuf.StringValue",
+			Value:   mustMarshal(wpb.String("hello, world")),
+		},
+		any: &apb.Any{
+			TypeUrl: "type.googleapis.com/google.protobuf.Any",
+			Value: mustMarshal(&apb.Any{
+				TypeUrl: "type.googleapis.com/google.protobuf.StringValue",
+				Value:   mustMarshal(wpb.String("hello, world")),
+			}),
+		},
+	}}
+
+	for _, tt := range tests {
+		// Unmarshal to the wrong message type.
+		var empty epb.Empty
+		if err := tt.any.UnmarshalTo(&empty); err == nil {
+			t.Errorf("UnmarshalTo(empty) = nil, want non-nil")
+		}
+
+		gotAny := new(apb.Any)
+		if err := gotAny.MarshalFrom(tt.msg); err != nil {
+			t.Errorf("MarshalFrom() error: %v", err)
+		}
+		if diff := cmp.Diff(tt.any, gotAny, protocmp.Transform()); diff != "" {
+			t.Errorf("MarshalFrom() output mismatch (-want +got):\n%s", diff)
+		}
+
+		gotPB := tt.msg.ProtoReflect().New().Interface()
+		if err := tt.any.UnmarshalTo(gotPB); err != nil {
+			t.Errorf("UnmarshalTo() error: %v", err)
+		}
+		if diff := cmp.Diff(tt.msg, gotPB, protocmp.Transform()); diff != "" {
+			t.Errorf("UnmarshalTo() output mismatch (-want +got):\n%s", diff)
+		}
+
+		gotPB, err := tt.any.UnmarshalNew()
+		if err != nil {
+			t.Errorf("UnmarshalNew() error: %v", err)
+		}
+		if diff := cmp.Diff(tt.msg, gotPB, protocmp.Transform()); diff != "" {
+			t.Errorf("UnmarshalNew() output mismatch (-want +got):\n%s", diff)
+		}
+	}
+}
diff --git a/types/known/durationpb/duration.pb.go b/types/known/durationpb/duration.pb.go
index 3997c60..53004d2 100644
--- a/types/known/durationpb/duration.pb.go
+++ b/types/known/durationpb/duration.pb.go
@@ -36,8 +36,10 @@
 import (
 	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
 	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	math "math"
 	reflect "reflect"
 	sync "sync"
+	time "time"
 )
 
 // A Duration represents a signed, fixed-length span of time represented
@@ -118,6 +120,82 @@
 	Nanos int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"`
 }
 
+// New constructs a new Duration from the provided time.Duration.
+func New(d time.Duration) *Duration {
+	nanos := d.Nanoseconds()
+	secs := nanos / 1e9
+	nanos -= secs * 1e9
+	return &Duration{Seconds: int64(secs), Nanos: int32(nanos)}
+}
+
+// AsDuration converts x to a time.Duration,
+// returning the closest duration value in the event of overflow.
+func (x *Duration) AsDuration() time.Duration {
+	secs := x.GetSeconds()
+	nanos := x.GetNanos()
+	d := time.Duration(secs) * time.Second
+	overflow := d/time.Second != time.Duration(secs)
+	d += time.Duration(nanos) * time.Nanosecond
+	overflow = overflow || (secs < 0 && nanos < 0 && d > 0)
+	overflow = overflow || (secs > 0 && nanos > 0 && d < 0)
+	if overflow {
+		switch {
+		case secs < 0:
+			return time.Duration(math.MinInt64)
+		case secs > 0:
+			return time.Duration(math.MaxInt64)
+		}
+	}
+	return d
+}
+
+// IsValid reports whether the duration is valid.
+// It is equivalent to CheckValid == nil.
+func (x *Duration) IsValid() bool {
+	return x.check() == 0
+}
+
+// CheckValid returns an error if the duration is invalid.
+// In particular, it checks whether the value is within the range of
+// -10000 years to +10000 years inclusive.
+func (x *Duration) CheckValid() error {
+	switch x.check() {
+	case invalidUnderflow:
+		return protoimpl.X.NewError("duration (%v) exceeds -10000 years", x)
+	case invalidOverflow:
+		return protoimpl.X.NewError("duration (%v) exceeds +10000 years", x)
+	case invalidNanosRange:
+		return protoimpl.X.NewError("duration (%v) has out-of-range nanos", x)
+	case invalidNanosSign:
+		return protoimpl.X.NewError("duration (%v) has seconds and nanos with different signs", x)
+	default:
+		return nil
+	}
+}
+
+const invalidUnderflow = 1
+const invalidOverflow = 2
+const invalidNanosRange = 3
+const invalidNanosSign = 4
+
+func (x *Duration) check() uint {
+	const absDuration = 315576000000 // 10000yr * 365.25day/yr * 24hr/day * 60min/hr * 60sec/min
+	secs := x.GetSeconds()
+	nanos := x.GetNanos()
+	switch {
+	case secs < -absDuration:
+		return invalidUnderflow
+	case secs > +absDuration:
+		return invalidOverflow
+	case nanos <= -1e9 || nanos >= +1e9:
+		return invalidNanosRange
+	case (secs > 0 && nanos < 0) || (secs < 0 && nanos > 0):
+		return invalidNanosSign
+	default:
+		return 0
+	}
+}
+
 func (x *Duration) Reset() {
 	*x = Duration{}
 	if protoimpl.UnsafeEnabled {
diff --git a/types/known/durationpb/duration_test.go b/types/known/durationpb/duration_test.go
new file mode 100644
index 0000000..464fbf1
--- /dev/null
+++ b/types/known/durationpb/duration_test.go
@@ -0,0 +1,100 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package durationpb_test
+
+import (
+	"math"
+	"strings"
+	"testing"
+	"time"
+
+	"github.com/google/go-cmp/cmp"
+	"github.com/google/go-cmp/cmp/cmpopts"
+	"google.golang.org/protobuf/internal/detrand"
+	"google.golang.org/protobuf/testing/protocmp"
+
+	durpb "google.golang.org/protobuf/types/known/durationpb"
+)
+
+func init() {
+	detrand.Disable()
+}
+
+const (
+	minGoSeconds = math.MinInt64 / int64(1e9)
+	maxGoSeconds = math.MaxInt64 / int64(1e9)
+	absSeconds   = 315576000000 // 10000yr * 365.25day/yr * 24hr/day * 60min/hr * 60sec/min
+)
+
+func TestToDuration(t *testing.T) {
+	tests := []struct {
+		in   time.Duration
+		want *durpb.Duration
+	}{
+		{in: time.Duration(0), want: &durpb.Duration{Seconds: 0, Nanos: 0}},
+		{in: -time.Second, want: &durpb.Duration{Seconds: -1, Nanos: 0}},
+		{in: +time.Second, want: &durpb.Duration{Seconds: +1, Nanos: 0}},
+		{in: -time.Second - time.Millisecond, want: &durpb.Duration{Seconds: -1, Nanos: -1e6}},
+		{in: +time.Second + time.Millisecond, want: &durpb.Duration{Seconds: +1, Nanos: +1e6}},
+		{in: time.Duration(math.MinInt64), want: &durpb.Duration{Seconds: minGoSeconds, Nanos: int32(math.MinInt64 - 1e9*minGoSeconds)}},
+		{in: time.Duration(math.MaxInt64), want: &durpb.Duration{Seconds: maxGoSeconds, Nanos: int32(math.MaxInt64 - 1e9*maxGoSeconds)}},
+	}
+
+	for _, tt := range tests {
+		got := durpb.New(tt.in)
+		if diff := cmp.Diff(tt.want, got, protocmp.Transform()); diff != "" {
+			t.Errorf("New(%v) mismatch (-want +got):\n%s", tt.in, diff)
+		}
+	}
+}
+
+func TestFromDuration(t *testing.T) {
+	tests := []struct {
+		in      *durpb.Duration
+		wantDur time.Duration
+		wantErr error
+	}{
+		{in: nil, wantDur: time.Duration(0)},
+		{in: new(durpb.Duration), wantDur: time.Duration(0)},
+		{in: &durpb.Duration{Seconds: -1, Nanos: 0}, wantDur: -time.Second},
+		{in: &durpb.Duration{Seconds: +1, Nanos: 0}, wantDur: +time.Second},
+		{in: &durpb.Duration{Seconds: 0, Nanos: -1}, wantDur: -time.Nanosecond},
+		{in: &durpb.Duration{Seconds: 0, Nanos: +1}, wantDur: +time.Nanosecond},
+		{in: &durpb.Duration{Seconds: -100, Nanos: 0}, wantDur: -100 * time.Second},
+		{in: &durpb.Duration{Seconds: +100, Nanos: 0}, wantDur: +100 * time.Second},
+		{in: &durpb.Duration{Seconds: -100, Nanos: -987}, wantDur: -100*time.Second - 987*time.Nanosecond},
+		{in: &durpb.Duration{Seconds: +100, Nanos: +987}, wantDur: +100*time.Second + 987*time.Nanosecond},
+		{in: &durpb.Duration{Seconds: minGoSeconds, Nanos: int32(math.MinInt64 - 1e9*minGoSeconds)}, wantDur: time.Duration(math.MinInt64)},
+		{in: &durpb.Duration{Seconds: maxGoSeconds, Nanos: int32(math.MaxInt64 - 1e9*maxGoSeconds)}, wantDur: time.Duration(math.MaxInt64)},
+		{in: &durpb.Duration{Seconds: minGoSeconds - 1, Nanos: int32(math.MinInt64 - 1e9*minGoSeconds)}, wantDur: time.Duration(math.MinInt64)},
+		{in: &durpb.Duration{Seconds: maxGoSeconds + 1, Nanos: int32(math.MaxInt64 - 1e9*maxGoSeconds)}, wantDur: time.Duration(math.MaxInt64)},
+		{in: &durpb.Duration{Seconds: minGoSeconds, Nanos: int32(math.MinInt64-1e9*minGoSeconds) - 1}, wantDur: time.Duration(math.MinInt64)},
+		{in: &durpb.Duration{Seconds: maxGoSeconds, Nanos: int32(math.MaxInt64-1e9*maxGoSeconds) + 1}, wantDur: time.Duration(math.MaxInt64)},
+		{in: &durpb.Duration{Seconds: -123, Nanos: +456}, wantDur: -123*time.Second + 456*time.Nanosecond, wantErr: textError("duration (seconds:-123 nanos:456) has seconds and nanos with different signs")},
+		{in: &durpb.Duration{Seconds: +123, Nanos: -456}, wantDur: +123*time.Second - 456*time.Nanosecond, wantErr: textError("duration (seconds:123 nanos:-456) has seconds and nanos with different signs")},
+		{in: &durpb.Duration{Seconds: math.MinInt64}, wantDur: time.Duration(math.MinInt64), wantErr: textError("duration (seconds:-9223372036854775808) exceeds -10000 years")},
+		{in: &durpb.Duration{Seconds: math.MaxInt64}, wantDur: time.Duration(math.MaxInt64), wantErr: textError("duration (seconds:9223372036854775807) exceeds +10000 years")},
+		{in: &durpb.Duration{Seconds: -absSeconds, Nanos: -(1e9 - 1)}, wantDur: time.Duration(math.MinInt64)},
+		{in: &durpb.Duration{Seconds: +absSeconds, Nanos: +(1e9 - 1)}, wantDur: time.Duration(math.MaxInt64)},
+		{in: &durpb.Duration{Seconds: -absSeconds - 1, Nanos: 0}, wantDur: time.Duration(math.MinInt64), wantErr: textError("duration (seconds:-315576000001) exceeds -10000 years")},
+		{in: &durpb.Duration{Seconds: +absSeconds + 1, Nanos: 0}, wantDur: time.Duration(math.MaxInt64), wantErr: textError("duration (seconds:315576000001) exceeds +10000 years")},
+	}
+
+	for _, tt := range tests {
+		gotDur := tt.in.AsDuration()
+		if diff := cmp.Diff(tt.wantDur, gotDur); diff != "" {
+			t.Errorf("AsDuration(%v) mismatch (-want +got):\n%s", tt.in, diff)
+		}
+		gotErr := tt.in.CheckValid()
+		if diff := cmp.Diff(tt.wantErr, gotErr, cmpopts.EquateErrors()); diff != "" {
+			t.Errorf("CheckValid(%v) mismatch (-want +got):\n%s", tt.in, diff)
+		}
+	}
+}
+
+type textError string
+
+func (e textError) Error() string     { return string(e) }
+func (e textError) Is(err error) bool { return err != nil && strings.Contains(err.Error(), e.Error()) }
diff --git a/types/known/fieldmaskpb/field_mask.pb.go b/types/known/fieldmaskpb/field_mask.pb.go
index 2ccf95a..6d845c8 100644
--- a/types/known/fieldmaskpb/field_mask.pb.go
+++ b/types/known/fieldmaskpb/field_mask.pb.go
@@ -34,9 +34,12 @@
 package fieldmaskpb
 
 import (
+	proto "google.golang.org/protobuf/proto"
 	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
 	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
 	reflect "reflect"
+	sort "sort"
+	strings "strings"
 	sync "sync"
 )
 
@@ -248,6 +251,175 @@
 	Paths []string `protobuf:"bytes,1,rep,name=paths,proto3" json:"paths,omitempty"`
 }
 
+// New constructs a field mask from a list of paths and verifies that
+// each one is valid according to the specified message type.
+func New(m proto.Message, paths ...string) (*FieldMask, error) {
+	x := new(FieldMask)
+	return x, x.Append(m, paths...)
+}
+
+// Union returns the union of all the paths in the input field masks.
+func Union(mx *FieldMask, my *FieldMask, ms ...*FieldMask) *FieldMask {
+	var out []string
+	out = append(out, mx.GetPaths()...)
+	out = append(out, my.GetPaths()...)
+	for _, m := range ms {
+		out = append(out, m.GetPaths()...)
+	}
+	return &FieldMask{Paths: normalizePaths(out)}
+}
+
+// Intersect returns the intersection of all the paths in the input field masks.
+func Intersect(mx *FieldMask, my *FieldMask, ms ...*FieldMask) *FieldMask {
+	var ss1, ss2 []string // reused buffers for performance
+	intersect := func(out, in []string) []string {
+		ss1 = normalizePaths(append(ss1[:0], in...))
+		ss2 = normalizePaths(append(ss2[:0], out...))
+		out = out[:0]
+		for i1, i2 := 0, 0; i1 < len(ss1) && i2 < len(ss2); {
+			switch s1, s2 := ss1[i1], ss2[i2]; {
+			case hasPathPrefix(s1, s2):
+				out = append(out, s1)
+				i1++
+			case hasPathPrefix(s2, s1):
+				out = append(out, s2)
+				i2++
+			case lessPath(s1, s2):
+				i1++
+			case lessPath(s2, s1):
+				i2++
+			}
+		}
+		return out
+	}
+
+	out := Union(mx, my, ms...).GetPaths()
+	out = intersect(out, mx.GetPaths())
+	out = intersect(out, my.GetPaths())
+	for _, m := range ms {
+		out = intersect(out, m.GetPaths())
+	}
+	return &FieldMask{Paths: normalizePaths(out)}
+}
+
+// IsValid reports whether all the paths are syntactically valid and
+// refer to known fields in the specified message type.
+func (x *FieldMask) IsValid(m proto.Message) bool {
+	paths := x.GetPaths()
+	return numValidPaths(m, paths) == len(paths)
+}
+
+// Append appends a list of paths to the mask and verifies that each one
+// is valid according to the specified message type.
+// An invalid path is not appended and breaks insertion of subsequent paths.
+func (x *FieldMask) Append(m proto.Message, paths ...string) error {
+	numValid := numValidPaths(m, paths)
+	x.Paths = append(x.Paths, paths[:numValid]...)
+	paths = paths[numValid:]
+	if len(paths) > 0 {
+		name := m.ProtoReflect().Descriptor().FullName()
+		return protoimpl.X.NewError("invalid path %q for message %q", paths[0], name)
+	}
+	return nil
+}
+
+func numValidPaths(m proto.Message, paths []string) int {
+	md0 := m.ProtoReflect().Descriptor()
+	for i, path := range paths {
+		md := md0
+		if !rangeFields(path, func(field string) bool {
+			// Search the field within the message.
+			if md == nil {
+				return false // not within a message
+			}
+			fd := md.Fields().ByName(protoreflect.Name(field))
+			// The real field name of a group is the message name.
+			if fd == nil {
+				gd := md.Fields().ByName(protoreflect.Name(strings.ToLower(field)))
+				if gd != nil && gd.Kind() == protoreflect.GroupKind && string(gd.Message().Name()) == field {
+					fd = gd
+				}
+			} else if fd.Kind() == protoreflect.GroupKind && string(fd.Message().Name()) != field {
+				fd = nil
+			}
+			if fd == nil {
+				return false // message has does not have this field
+			}
+
+			// Identify the next message to search within.
+			md = fd.Message() // may be nil
+			if fd.IsMap() {
+				md = fd.MapValue().Message() // may be nil
+			}
+			return true
+		}) {
+			return i
+		}
+	}
+	return len(paths)
+}
+
+// Normalize converts the mask to its canonical form where all paths are sorted
+// and redundant paths are removed.
+func (x *FieldMask) Normalize() {
+	x.Paths = normalizePaths(x.Paths)
+}
+
+func normalizePaths(paths []string) []string {
+	sort.Slice(paths, func(i, j int) bool {
+		return lessPath(paths[i], paths[j])
+	})
+
+	// Elide any path that is a prefix match on the previous.
+	out := paths[:0]
+	for _, path := range paths {
+		if len(out) > 0 && hasPathPrefix(path, out[len(out)-1]) {
+			continue
+		}
+		out = append(out, path)
+	}
+	return out
+}
+
+// hasPathPrefix is like strings.HasPrefix, but further checks for either
+// an exact matche or that the prefix is delimited by a dot.
+func hasPathPrefix(path, prefix string) bool {
+	return strings.HasPrefix(path, prefix) && (len(path) == len(prefix) || path[len(prefix)] == '.')
+}
+
+// lessPath is a lexicographical comparison where dot is specially treated
+// as the smallest symbol.
+func lessPath(x, y string) bool {
+	for i := 0; i < len(x) && i < len(y); i++ {
+		if x[i] != y[i] {
+			return (x[i] - '.') < (y[i] - '.')
+		}
+	}
+	return len(x) < len(y)
+}
+
+// rangeFields is like strings.Split(path, "."), but avoids allocations by
+// iterating over each field in place and calling a iterator function.
+func rangeFields(path string, f func(field string) bool) bool {
+	for {
+		var field string
+		if i := strings.IndexByte(path, '.'); i >= 0 {
+			field, path = path[:i], path[i:]
+		} else {
+			field, path = path, ""
+		}
+
+		if !f(field) {
+			return false
+		}
+
+		if len(path) == 0 {
+			return true
+		}
+		path = strings.TrimPrefix(path, ".")
+	}
+}
+
 func (x *FieldMask) Reset() {
 	*x = FieldMask{}
 	if protoimpl.UnsafeEnabled {
diff --git a/types/known/fieldmaskpb/field_mask_test.go b/types/known/fieldmaskpb/field_mask_test.go
new file mode 100644
index 0000000..6d21711
--- /dev/null
+++ b/types/known/fieldmaskpb/field_mask_test.go
@@ -0,0 +1,196 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package fieldmaskpb_test
+
+import (
+	"testing"
+
+	"github.com/google/go-cmp/cmp"
+	"github.com/google/go-cmp/cmp/cmpopts"
+	"google.golang.org/protobuf/proto"
+
+	testpb "google.golang.org/protobuf/internal/testprotos/test"
+	fmpb "google.golang.org/protobuf/types/known/fieldmaskpb"
+)
+
+func TestAppend(t *testing.T) {
+	tests := []struct {
+		inMessage proto.Message
+		inPaths   []string
+		wantPaths []string
+		wantError error
+	}{{
+		inMessage: (*fmpb.FieldMask)(nil),
+		inPaths:   []string{},
+		wantPaths: []string{},
+	}, {
+		inMessage: (*fmpb.FieldMask)(nil),
+		inPaths:   []string{"paths", "paths"},
+		wantPaths: []string{"paths", "paths"},
+	}, {
+		inMessage: (*fmpb.FieldMask)(nil),
+		inPaths:   []string{"paths", "<INVALID>", "paths"},
+		wantPaths: []string{"paths"},
+		wantError: cmpopts.AnyError,
+	}, {
+		inMessage: (*testpb.TestAllTypes)(nil),
+		inPaths:   []string{"optional_int32", "OptionalGroup.optional_nested_message", "map_uint32_uint32", "map_string_nested_message.corecursive", "oneof_bool"},
+		wantPaths: []string{"optional_int32", "OptionalGroup.optional_nested_message", "map_uint32_uint32", "map_string_nested_message.corecursive", "oneof_bool"},
+	}, {
+		inMessage: (*testpb.TestAllTypes)(nil),
+		inPaths:   []string{"optional_nested_message", "optional_nested_message.corecursive", "optional_nested_message.corecursive.optional_nested_message", "optional_nested_message.corecursive.optional_nested_message.corecursive"},
+		wantPaths: []string{"optional_nested_message", "optional_nested_message.corecursive", "optional_nested_message.corecursive.optional_nested_message", "optional_nested_message.corecursive.optional_nested_message.corecursive"},
+	}, {
+		inMessage: (*testpb.TestAllTypes)(nil),
+		inPaths:   []string{"optional_int32", "optional_nested_message.corecursive.optional_int64", "optional_nested_message.corecursive.<INVALID>", "optional_int64"},
+		wantPaths: []string{"optional_int32", "optional_nested_message.corecursive.optional_int64"},
+		wantError: cmpopts.AnyError,
+	}, {
+		inMessage: (*testpb.TestAllTypes)(nil),
+		inPaths:   []string{"optional_int32", "optional_nested_message.corecursive.oneof_uint32", "optional_nested_message.oneof_field", "optional_int64"},
+		wantPaths: []string{"optional_int32", "optional_nested_message.corecursive.oneof_uint32"},
+		wantError: cmpopts.AnyError,
+	}}
+
+	for _, tt := range tests {
+		t.Run("", func(t *testing.T) {
+			var mask fmpb.FieldMask
+			gotError := mask.Append(tt.inMessage, tt.inPaths...)
+			gotPaths := mask.GetPaths()
+			if diff := cmp.Diff(tt.wantPaths, gotPaths, cmpopts.EquateEmpty()); diff != "" {
+				t.Errorf("Append() paths mismatch (-want +got):\n%s", diff)
+			}
+			if diff := cmp.Diff(tt.wantError, gotError, cmpopts.EquateErrors()); diff != "" {
+				t.Errorf("Append() error mismatch (-want +got):\n%s", diff)
+			}
+		})
+	}
+}
+
+func TestCombine(t *testing.T) {
+	tests := []struct {
+		in            [][]string
+		wantUnion     []string
+		wantIntersect []string
+	}{{
+		in: [][]string{
+			{},
+			{},
+		},
+		wantUnion:     []string{},
+		wantIntersect: []string{},
+	}, {
+		in: [][]string{
+			{"a"},
+			{},
+		},
+		wantUnion:     []string{"a"},
+		wantIntersect: []string{},
+	}, {
+		in: [][]string{
+			{"a"},
+			{"a"},
+		},
+		wantUnion:     []string{"a"},
+		wantIntersect: []string{"a"},
+	}, {
+		in: [][]string{
+			{"a"},
+			{"b"},
+			{"c"},
+		},
+		wantUnion:     []string{"a", "b", "c"},
+		wantIntersect: []string{},
+	}, {
+		in: [][]string{
+			{"a", "b"},
+			{"b.b"},
+			{"b"},
+			{"b", "a.A"},
+			{"b", "c", "c.a", "c.b"},
+		},
+		wantUnion:     []string{"a", "b", "c"},
+		wantIntersect: []string{"b.b"},
+	}, {
+		in: [][]string{
+			{"a.b", "a.c.d"},
+			{"a"},
+		},
+		wantUnion:     []string{"a"},
+		wantIntersect: []string{"a.b", "a.c.d"},
+	}, {
+		in: [][]string{
+			{},
+			{"a.b", "a.c", "d"},
+		},
+		wantUnion:     []string{"a.b", "a.c", "d"},
+		wantIntersect: []string{},
+	}}
+
+	for _, tt := range tests {
+		t.Run("", func(t *testing.T) {
+			var masks []*fmpb.FieldMask
+			for _, paths := range tt.in {
+				masks = append(masks, &fmpb.FieldMask{Paths: paths})
+			}
+
+			union := fmpb.Union(masks[0], masks[1], masks[2:]...)
+			gotUnion := union.GetPaths()
+			if diff := cmp.Diff(tt.wantUnion, gotUnion, cmpopts.EquateEmpty()); diff != "" {
+				t.Errorf("Union() mismatch (-want +got):\n%s", diff)
+			}
+
+			intersect := fmpb.Intersect(masks[0], masks[1], masks[2:]...)
+			gotIntersect := intersect.GetPaths()
+			if diff := cmp.Diff(tt.wantIntersect, gotIntersect, cmpopts.EquateEmpty()); diff != "" {
+				t.Errorf("Intersect() mismatch (-want +got):\n%s", diff)
+			}
+		})
+	}
+}
+
+func TestNormalize(t *testing.T) {
+	tests := []struct {
+		in   []string
+		want []string
+	}{{
+		in:   []string{},
+		want: []string{},
+	}, {
+		in:   []string{"a"},
+		want: []string{"a"},
+	}, {
+		in:   []string{"foo", "foo.bar", "foo.baz"},
+		want: []string{"foo"},
+	}, {
+		in:   []string{"foo.bar", "foo.baz"},
+		want: []string{"foo.bar", "foo.baz"},
+	}, {
+		in:   []string{"", "a.", ".b", "a.b", ".", "", "a.", ".b", "a.b", "."},
+		want: []string{"", "a.", "a.b"},
+	}, {
+		in:   []string{"e.a", "e.b", "e.c", "e.d", "e.f", "e.g", "e.b.a", "e$c", "e.b.c"},
+		want: []string{"e.a", "e.b", "e.c", "e.d", "e.f", "e.g", "e$c"},
+	}, {
+		in:   []string{"a", "aa", "aaa", "a$", "AAA", "aA.a", "a.a", "a", "aa", "aaa", "a$", "AAA", "aA.a"},
+		want: []string{"AAA", "a", "aA.a", "aa", "aaa", "a$"},
+	}, {
+		in:   []string{"a.b", "aa.bb.cc", ".", "a$b", "aa", "a.", "a", "b.c.d", ".a", "", "a$", "a$", "a.b", "a", "a.bb", ""},
+		want: []string{"", "a", "aa", "a$", "a$b", "b.c.d"},
+	}}
+
+	for _, tt := range tests {
+		t.Run("", func(t *testing.T) {
+			mask := &fmpb.FieldMask{
+				Paths: append([]string(nil), tt.in...),
+			}
+			mask.Normalize()
+			got := mask.GetPaths()
+			if diff := cmp.Diff(tt.want, got, cmpopts.EquateEmpty()); diff != "" {
+				t.Errorf("Normalize() mismatch (-want +got):\n%s", diff)
+			}
+		})
+	}
+}
diff --git a/types/known/structpb/struct.pb.go b/types/known/structpb/struct.pb.go
index df09813..f246b87 100644
--- a/types/known/structpb/struct.pb.go
+++ b/types/known/structpb/struct.pb.go
@@ -34,10 +34,14 @@
 package structpb
 
 import (
+	base64 "encoding/base64"
+	protojson "google.golang.org/protobuf/encoding/protojson"
 	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
 	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	math "math"
 	reflect "reflect"
 	sync "sync"
+	utf8 "unicode/utf8"
 )
 
 // `NullValue` is a singleton enumeration to represent the null value for the
@@ -105,6 +109,42 @@
 	Fields map[string]*Value `protobuf:"bytes,1,rep,name=fields,proto3" json:"fields,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
 }
 
+// NewStruct constructs a Struct from a general-purpose Go map.
+// The map keys must be valid UTF-8.
+// The map values are converted using NewValue.
+func NewStruct(v map[string]interface{}) (*Struct, error) {
+	x := &Struct{Fields: make(map[string]*Value, len(v))}
+	for k, v := range v {
+		if !utf8.ValidString(k) {
+			return nil, protoimpl.X.NewError("invalid UTF-8 in string: %q", k)
+		}
+		var err error
+		x.Fields[k], err = NewValue(v)
+		if err != nil {
+			return nil, err
+		}
+	}
+	return x, nil
+}
+
+// AsMap converts x to a general-purpose Go map.
+// The map values are converted by calling Value.AsInterface.
+func (x *Struct) AsMap() map[string]interface{} {
+	vs := make(map[string]interface{})
+	for k, v := range x.GetFields() {
+		vs[k] = v.AsInterface()
+	}
+	return vs
+}
+
+func (x *Struct) MarshalJSON() ([]byte, error) {
+	return protojson.Marshal(x)
+}
+
+func (x *Struct) UnmarshalJSON(b []byte) error {
+	return protojson.Unmarshal(b, x)
+}
+
 func (x *Struct) Reset() {
 	*x = Struct{}
 	if protoimpl.UnsafeEnabled {
@@ -167,6 +207,151 @@
 	Kind isValue_Kind `protobuf_oneof:"kind"`
 }
 
+// NewValue constructs a Value from a general-purpose Go interface.
+//
+//	╔════════════════════════╤════════════════════════════════════════════╗
+//	║ Go type                │ Conversion                                 ║
+//	╠════════════════════════╪════════════════════════════════════════════╣
+//	║ nil                    │ stored as NullValue                        ║
+//	║ bool                   │ stored as BoolValue                        ║
+//	║ int, int32, int64      │ stored as NumberValue                      ║
+//	║ uint, uint32, uint64   │ stored as NumberValue                      ║
+//	║ float32, float64       │ stored as NumberValue                      ║
+//	║ string                 │ stored as StringValue; must be valid UTF-8 ║
+//	║ []byte                 │ stored as StringValue; base64-encoded      ║
+//	║ map[string]interface{} │ stored as StructValue                      ║
+//	║ []interface{}          │ stored as ListValue                        ║
+//	╚════════════════════════╧════════════════════════════════════════════╝
+//
+// When converting an int64 or uint64 to a NumberValue, numeric precision loss
+// is possible since they are stored as a float64.
+func NewValue(v interface{}) (*Value, error) {
+	switch v := v.(type) {
+	case nil:
+		return NewNullValue(), nil
+	case bool:
+		return NewBoolValue(v), nil
+	case int:
+		return NewNumberValue(float64(v)), nil
+	case int32:
+		return NewNumberValue(float64(v)), nil
+	case int64:
+		return NewNumberValue(float64(v)), nil
+	case uint:
+		return NewNumberValue(float64(v)), nil
+	case uint32:
+		return NewNumberValue(float64(v)), nil
+	case uint64:
+		return NewNumberValue(float64(v)), nil
+	case float32:
+		return NewNumberValue(float64(v)), nil
+	case float64:
+		return NewNumberValue(float64(v)), nil
+	case string:
+		if !utf8.ValidString(v) {
+			return nil, protoimpl.X.NewError("invalid UTF-8 in string: %q", v)
+		}
+		return NewStringValue(v), nil
+	case []byte:
+		s := base64.StdEncoding.EncodeToString(v)
+		return NewStringValue(s), nil
+	case map[string]interface{}:
+		v2, err := NewStruct(v)
+		if err != nil {
+			return nil, err
+		}
+		return NewStructValue(v2), nil
+	case []interface{}:
+		v2, err := NewList(v)
+		if err != nil {
+			return nil, err
+		}
+		return NewListValue(v2), nil
+	default:
+		return nil, protoimpl.X.NewError("invalid type: %T", v)
+	}
+}
+
+// NewNullValue constructs a new null Value.
+func NewNullValue() *Value {
+	return &Value{Kind: &Value_NullValue{NullValue: NullValue_NULL_VALUE}}
+}
+
+// NewBoolValue constructs a new boolean Value.
+func NewBoolValue(v bool) *Value {
+	return &Value{Kind: &Value_BoolValue{BoolValue: v}}
+}
+
+// NewNumberValue constructs a new number Value.
+func NewNumberValue(v float64) *Value {
+	return &Value{Kind: &Value_NumberValue{NumberValue: v}}
+}
+
+// NewStringValue constructs a new string Value.
+func NewStringValue(v string) *Value {
+	return &Value{Kind: &Value_StringValue{StringValue: v}}
+}
+
+// NewStructValue constructs a new struct Value.
+func NewStructValue(v *Struct) *Value {
+	return &Value{Kind: &Value_StructValue{StructValue: v}}
+}
+
+// NewListValue constructs a new list Value.
+func NewListValue(v *ListValue) *Value {
+	return &Value{Kind: &Value_ListValue{ListValue: v}}
+}
+
+// AsInterface converts x to a general-purpose Go interface.
+//
+// Calling Value.MarshalJSON and "encoding/json".Marshal on this output produce
+// semantically equivalent JSON (assuming no errors occur).
+//
+// Floating-point values (i.e., "NaN", "Infinity", and "-Infinity") are
+// converted as strings to remain compatible with MarshalJSON.
+func (x *Value) AsInterface() interface{} {
+	switch v := x.GetKind().(type) {
+	case *Value_NumberValue:
+		if v != nil {
+			switch {
+			case math.IsNaN(v.NumberValue):
+				return "NaN"
+			case math.IsInf(v.NumberValue, +1):
+				return "Infinity"
+			case math.IsInf(v.NumberValue, -1):
+				return "-Infinity"
+			default:
+				return v.NumberValue
+			}
+		}
+	case *Value_StringValue:
+		if v != nil {
+			return v.StringValue
+		}
+	case *Value_BoolValue:
+		if v != nil {
+			return v.BoolValue
+		}
+	case *Value_StructValue:
+		if v != nil {
+			return v.StructValue.AsMap()
+		}
+	case *Value_ListValue:
+		if v != nil {
+			return v.ListValue.AsSlice()
+		}
+	}
+	return nil
+}
+
+func (x *Value) MarshalJSON() ([]byte, error) {
+	return protojson.Marshal(x)
+}
+
+func (x *Value) UnmarshalJSON(b []byte) error {
+	return protojson.Unmarshal(b, x)
+}
+
 func (x *Value) Reset() {
 	*x = Value{}
 	if protoimpl.UnsafeEnabled {
@@ -306,6 +491,38 @@
 	Values []*Value `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty"`
 }
 
+// NewList constructs a ListValue from a general-purpose Go slice.
+// The slice elements are converted using NewValue.
+func NewList(v []interface{}) (*ListValue, error) {
+	x := &ListValue{Values: make([]*Value, len(v))}
+	for i, v := range v {
+		var err error
+		x.Values[i], err = NewValue(v)
+		if err != nil {
+			return nil, err
+		}
+	}
+	return x, nil
+}
+
+// AsSlice converts x to a general-purpose Go slice.
+// The slice elements are converted by calling Value.AsInterface.
+func (x *ListValue) AsSlice() []interface{} {
+	vs := make([]interface{}, len(x.GetValues()))
+	for i, v := range x.GetValues() {
+		vs[i] = v.AsInterface()
+	}
+	return vs
+}
+
+func (x *ListValue) MarshalJSON() ([]byte, error) {
+	return protojson.Marshal(x)
+}
+
+func (x *ListValue) UnmarshalJSON(b []byte) error {
+	return protojson.Unmarshal(b, x)
+}
+
 func (x *ListValue) Reset() {
 	*x = ListValue{}
 	if protoimpl.UnsafeEnabled {
diff --git a/types/known/structpb/struct_test.go b/types/known/structpb/struct_test.go
new file mode 100644
index 0000000..643f740
--- /dev/null
+++ b/types/known/structpb/struct_test.go
@@ -0,0 +1,512 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package structpb_test
+
+import (
+	"encoding/json"
+	"math"
+	"testing"
+
+	"github.com/google/go-cmp/cmp"
+	"github.com/google/go-cmp/cmp/cmpopts"
+	"google.golang.org/protobuf/reflect/protoreflect"
+	"google.golang.org/protobuf/testing/protocmp"
+
+	spb "google.golang.org/protobuf/types/known/structpb"
+)
+
+var equateJSON = cmpopts.AcyclicTransformer("UnmarshalJSON", func(in []byte) (out interface{}) {
+	if err := json.Unmarshal(in, &out); err != nil {
+		return in
+	}
+	return out
+})
+
+func TestToStruct(t *testing.T) {
+	tests := []struct {
+		in      map[string]interface{}
+		wantPB  *spb.Struct
+		wantErr error
+	}{{
+		in:     nil,
+		wantPB: new(spb.Struct),
+	}, {
+		in:     make(map[string]interface{}),
+		wantPB: new(spb.Struct),
+	}, {
+		in: map[string]interface{}{
+			"nil":     nil,
+			"bool":    bool(false),
+			"int":     int(-123),
+			"int32":   int32(math.MinInt32),
+			"int64":   int64(math.MinInt64),
+			"uint":    uint(123),
+			"uint32":  uint32(math.MaxInt32),
+			"uint64":  uint64(math.MaxInt64),
+			"float32": float32(123.456),
+			"float64": float64(123.456),
+			"string":  string("hello, world!"),
+			"bytes":   []byte("\xde\xad\xbe\xef"),
+			"map":     map[string]interface{}{"k1": "v1", "k2": "v2"},
+			"slice":   []interface{}{"one", "two", "three"},
+		},
+		wantPB: &spb.Struct{Fields: map[string]*spb.Value{
+			"nil":     spb.NewNullValue(),
+			"bool":    spb.NewBoolValue(false),
+			"int":     spb.NewNumberValue(float64(-123)),
+			"int32":   spb.NewNumberValue(float64(math.MinInt32)),
+			"int64":   spb.NewNumberValue(float64(math.MinInt64)),
+			"uint":    spb.NewNumberValue(float64(123)),
+			"uint32":  spb.NewNumberValue(float64(math.MaxInt32)),
+			"uint64":  spb.NewNumberValue(float64(math.MaxInt64)),
+			"float32": spb.NewNumberValue(float64(float32(123.456))),
+			"float64": spb.NewNumberValue(float64(float64(123.456))),
+			"string":  spb.NewStringValue("hello, world!"),
+			"bytes":   spb.NewStringValue("3q2+7w=="),
+			"map": spb.NewStructValue(&spb.Struct{Fields: map[string]*spb.Value{
+				"k1": spb.NewStringValue("v1"),
+				"k2": spb.NewStringValue("v2"),
+			}}),
+			"slice": spb.NewListValue(&spb.ListValue{Values: []*spb.Value{
+				spb.NewStringValue("one"),
+				spb.NewStringValue("two"),
+				spb.NewStringValue("three"),
+			}}),
+		}},
+	}, {
+		in:      map[string]interface{}{"\xde\xad\xbe\xef": "<invalid UTF-8>"},
+		wantErr: cmpopts.AnyError,
+	}, {
+		in:      map[string]interface{}{"<invalid UTF-8>": "\xde\xad\xbe\xef"},
+		wantErr: cmpopts.AnyError,
+	}, {
+		in:      map[string]interface{}{"key": protoreflect.Name("named string")},
+		wantErr: cmpopts.AnyError,
+	}}
+
+	for _, tt := range tests {
+		gotPB, gotErr := spb.NewStruct(tt.in)
+		if diff := cmp.Diff(tt.wantPB, gotPB, protocmp.Transform()); diff != "" {
+			t.Errorf("NewStruct(%v) output mismatch (-want +got):\n%s", tt.in, diff)
+		}
+		if diff := cmp.Diff(tt.wantErr, gotErr, cmpopts.EquateErrors()); diff != "" {
+			t.Errorf("NewStruct(%v) error mismatch (-want +got):\n%s", tt.in, diff)
+		}
+	}
+}
+
+func TestFromStruct(t *testing.T) {
+	tests := []struct {
+		in   *spb.Struct
+		want map[string]interface{}
+	}{{
+		in:   nil,
+		want: make(map[string]interface{}),
+	}, {
+		in:   new(spb.Struct),
+		want: make(map[string]interface{}),
+	}, {
+		in:   &spb.Struct{Fields: make(map[string]*spb.Value)},
+		want: make(map[string]interface{}),
+	}, {
+		in: &spb.Struct{Fields: map[string]*spb.Value{
+			"nil":     spb.NewNullValue(),
+			"bool":    spb.NewBoolValue(false),
+			"int":     spb.NewNumberValue(float64(-123)),
+			"int32":   spb.NewNumberValue(float64(math.MinInt32)),
+			"int64":   spb.NewNumberValue(float64(math.MinInt64)),
+			"uint":    spb.NewNumberValue(float64(123)),
+			"uint32":  spb.NewNumberValue(float64(math.MaxInt32)),
+			"uint64":  spb.NewNumberValue(float64(math.MaxInt64)),
+			"float32": spb.NewNumberValue(float64(float32(123.456))),
+			"float64": spb.NewNumberValue(float64(float64(123.456))),
+			"string":  spb.NewStringValue("hello, world!"),
+			"bytes":   spb.NewStringValue("3q2+7w=="),
+			"map": spb.NewStructValue(&spb.Struct{Fields: map[string]*spb.Value{
+				"k1": spb.NewStringValue("v1"),
+				"k2": spb.NewStringValue("v2"),
+			}}),
+			"slice": spb.NewListValue(&spb.ListValue{Values: []*spb.Value{
+				spb.NewStringValue("one"),
+				spb.NewStringValue("two"),
+				spb.NewStringValue("three"),
+			}}),
+		}},
+		want: map[string]interface{}{
+			"nil":     nil,
+			"bool":    bool(false),
+			"int":     float64(-123),
+			"int32":   float64(math.MinInt32),
+			"int64":   float64(math.MinInt64),
+			"uint":    float64(123),
+			"uint32":  float64(math.MaxInt32),
+			"uint64":  float64(math.MaxInt64),
+			"float32": float64(float32(123.456)),
+			"float64": float64(float64(123.456)),
+			"string":  string("hello, world!"),
+			"bytes":   string("3q2+7w=="),
+			"map":     map[string]interface{}{"k1": "v1", "k2": "v2"},
+			"slice":   []interface{}{"one", "two", "three"},
+		},
+	}}
+
+	for _, tt := range tests {
+		got := tt.in.AsMap()
+		if diff := cmp.Diff(tt.want, got); diff != "" {
+			t.Errorf("AsMap(%v) mismatch (-want +got):\n%s", tt.in, diff)
+		}
+		gotJSON, err := json.Marshal(got)
+		if err != nil {
+			t.Errorf("Marshal error: %v", err)
+		}
+		wantJSON, err := tt.in.MarshalJSON()
+		if err != nil {
+			t.Errorf("Marshal error: %v", err)
+		}
+		if diff := cmp.Diff(wantJSON, gotJSON, equateJSON); diff != "" {
+			t.Errorf("MarshalJSON(%v) mismatch (-want +got):\n%s", tt.in, diff)
+		}
+	}
+}
+
+func TestToListValue(t *testing.T) {
+	tests := []struct {
+		in      []interface{}
+		wantPB  *spb.ListValue
+		wantErr error
+	}{{
+		in:     nil,
+		wantPB: new(spb.ListValue),
+	}, {
+		in:     make([]interface{}, 0),
+		wantPB: new(spb.ListValue),
+	}, {
+		in: []interface{}{
+			nil,
+			bool(false),
+			int(-123),
+			int32(math.MinInt32),
+			int64(math.MinInt64),
+			uint(123),
+			uint32(math.MaxInt32),
+			uint64(math.MaxInt64),
+			float32(123.456),
+			float64(123.456),
+			string("hello, world!"),
+			[]byte("\xde\xad\xbe\xef"),
+			map[string]interface{}{"k1": "v1", "k2": "v2"},
+			[]interface{}{"one", "two", "three"},
+		},
+		wantPB: &spb.ListValue{Values: []*spb.Value{
+			spb.NewNullValue(),
+			spb.NewBoolValue(false),
+			spb.NewNumberValue(float64(-123)),
+			spb.NewNumberValue(float64(math.MinInt32)),
+			spb.NewNumberValue(float64(math.MinInt64)),
+			spb.NewNumberValue(float64(123)),
+			spb.NewNumberValue(float64(math.MaxInt32)),
+			spb.NewNumberValue(float64(math.MaxInt64)),
+			spb.NewNumberValue(float64(float32(123.456))),
+			spb.NewNumberValue(float64(float64(123.456))),
+			spb.NewStringValue("hello, world!"),
+			spb.NewStringValue("3q2+7w=="),
+			spb.NewStructValue(&spb.Struct{Fields: map[string]*spb.Value{
+				"k1": spb.NewStringValue("v1"),
+				"k2": spb.NewStringValue("v2"),
+			}}),
+			spb.NewListValue(&spb.ListValue{Values: []*spb.Value{
+				spb.NewStringValue("one"),
+				spb.NewStringValue("two"),
+				spb.NewStringValue("three"),
+			}}),
+		}},
+	}, {
+		in:      []interface{}{"\xde\xad\xbe\xef"},
+		wantErr: cmpopts.AnyError,
+	}, {
+		in:      []interface{}{protoreflect.Name("named string")},
+		wantErr: cmpopts.AnyError,
+	}}
+
+	for _, tt := range tests {
+		gotPB, gotErr := spb.NewList(tt.in)
+		if diff := cmp.Diff(tt.wantPB, gotPB, protocmp.Transform()); diff != "" {
+			t.Errorf("NewListValue(%v) output mismatch (-want +got):\n%s", tt.in, diff)
+		}
+		if diff := cmp.Diff(tt.wantErr, gotErr, cmpopts.EquateErrors()); diff != "" {
+			t.Errorf("NewListValue(%v) error mismatch (-want +got):\n%s", tt.in, diff)
+		}
+	}
+}
+
+func TestFromListValue(t *testing.T) {
+	tests := []struct {
+		in   *spb.ListValue
+		want []interface{}
+	}{{
+		in:   nil,
+		want: make([]interface{}, 0),
+	}, {
+		in:   new(spb.ListValue),
+		want: make([]interface{}, 0),
+	}, {
+		in:   &spb.ListValue{Values: make([]*spb.Value, 0)},
+		want: make([]interface{}, 0),
+	}, {
+		in: &spb.ListValue{Values: []*spb.Value{
+			spb.NewNullValue(),
+			spb.NewBoolValue(false),
+			spb.NewNumberValue(float64(-123)),
+			spb.NewNumberValue(float64(math.MinInt32)),
+			spb.NewNumberValue(float64(math.MinInt64)),
+			spb.NewNumberValue(float64(123)),
+			spb.NewNumberValue(float64(math.MaxInt32)),
+			spb.NewNumberValue(float64(math.MaxInt64)),
+			spb.NewNumberValue(float64(float32(123.456))),
+			spb.NewNumberValue(float64(float64(123.456))),
+			spb.NewStringValue("hello, world!"),
+			spb.NewStringValue("3q2+7w=="),
+			spb.NewStructValue(&spb.Struct{Fields: map[string]*spb.Value{
+				"k1": spb.NewStringValue("v1"),
+				"k2": spb.NewStringValue("v2"),
+			}}),
+			spb.NewListValue(&spb.ListValue{Values: []*spb.Value{
+				spb.NewStringValue("one"),
+				spb.NewStringValue("two"),
+				spb.NewStringValue("three"),
+			}}),
+		}},
+		want: []interface{}{
+			nil,
+			bool(false),
+			float64(-123),
+			float64(math.MinInt32),
+			float64(math.MinInt64),
+			float64(123),
+			float64(math.MaxInt32),
+			float64(math.MaxInt64),
+			float64(float32(123.456)),
+			float64(float64(123.456)),
+			string("hello, world!"),
+			string("3q2+7w=="),
+			map[string]interface{}{"k1": "v1", "k2": "v2"},
+			[]interface{}{"one", "two", "three"},
+		},
+	}}
+
+	for _, tt := range tests {
+		got := tt.in.AsSlice()
+		if diff := cmp.Diff(tt.want, got); diff != "" {
+			t.Errorf("AsSlice(%v) mismatch (-want +got):\n%s", tt.in, diff)
+		}
+		gotJSON, err := json.Marshal(got)
+		if err != nil {
+			t.Errorf("Marshal error: %v", err)
+		}
+		wantJSON, err := tt.in.MarshalJSON()
+		if err != nil {
+			t.Errorf("Marshal error: %v", err)
+		}
+		if diff := cmp.Diff(wantJSON, gotJSON, equateJSON); diff != "" {
+			t.Errorf("MarshalJSON(%v) mismatch (-want +got):\n%s", tt.in, diff)
+		}
+	}
+}
+
+func TestToValue(t *testing.T) {
+	tests := []struct {
+		in      interface{}
+		wantPB  *spb.Value
+		wantErr error
+	}{{
+		in:     nil,
+		wantPB: spb.NewNullValue(),
+	}, {
+		in:     bool(false),
+		wantPB: spb.NewBoolValue(false),
+	}, {
+		in:     int(-123),
+		wantPB: spb.NewNumberValue(float64(-123)),
+	}, {
+		in:     int32(math.MinInt32),
+		wantPB: spb.NewNumberValue(float64(math.MinInt32)),
+	}, {
+		in:     int64(math.MinInt64),
+		wantPB: spb.NewNumberValue(float64(math.MinInt64)),
+	}, {
+		in:     uint(123),
+		wantPB: spb.NewNumberValue(float64(123)),
+	}, {
+		in:     uint32(math.MaxInt32),
+		wantPB: spb.NewNumberValue(float64(math.MaxInt32)),
+	}, {
+		in:     uint64(math.MaxInt64),
+		wantPB: spb.NewNumberValue(float64(math.MaxInt64)),
+	}, {
+		in:     float32(123.456),
+		wantPB: spb.NewNumberValue(float64(float32(123.456))),
+	}, {
+		in:     float64(123.456),
+		wantPB: spb.NewNumberValue(float64(float64(123.456))),
+	}, {
+		in:     string("hello, world!"),
+		wantPB: spb.NewStringValue("hello, world!"),
+	}, {
+		in:     []byte("\xde\xad\xbe\xef"),
+		wantPB: spb.NewStringValue("3q2+7w=="),
+	}, {
+		in:     map[string]interface{}(nil),
+		wantPB: spb.NewStructValue(nil),
+	}, {
+		in:     make(map[string]interface{}),
+		wantPB: spb.NewStructValue(nil),
+	}, {
+		in: map[string]interface{}{"k1": "v1", "k2": "v2"},
+		wantPB: spb.NewStructValue(&spb.Struct{Fields: map[string]*spb.Value{
+			"k1": spb.NewStringValue("v1"),
+			"k2": spb.NewStringValue("v2"),
+		}}),
+	}, {
+		in:     []interface{}(nil),
+		wantPB: spb.NewListValue(nil),
+	}, {
+		in:     make([]interface{}, 0),
+		wantPB: spb.NewListValue(nil),
+	}, {
+		in: []interface{}{"one", "two", "three"},
+		wantPB: spb.NewListValue(&spb.ListValue{Values: []*spb.Value{
+			spb.NewStringValue("one"),
+			spb.NewStringValue("two"),
+			spb.NewStringValue("three"),
+		}}),
+	}, {
+		in:      "\xde\xad\xbe\xef",
+		wantErr: cmpopts.AnyError,
+	}, {
+		in:      protoreflect.Name("named string"),
+		wantErr: cmpopts.AnyError,
+	}}
+
+	for _, tt := range tests {
+		gotPB, gotErr := spb.NewValue(tt.in)
+		if diff := cmp.Diff(tt.wantPB, gotPB, protocmp.Transform()); diff != "" {
+			t.Errorf("NewValue(%v) output mismatch (-want +got):\n%s", tt.in, diff)
+		}
+		if diff := cmp.Diff(tt.wantErr, gotErr, cmpopts.EquateErrors()); diff != "" {
+			t.Errorf("NewValue(%v) error mismatch (-want +got):\n%s", tt.in, diff)
+		}
+	}
+}
+
+func TestFromValue(t *testing.T) {
+	tests := []struct {
+		in   *spb.Value
+		want interface{}
+	}{{
+		in:   nil,
+		want: nil,
+	}, {
+		in:   new(spb.Value),
+		want: nil,
+	}, {
+		in:   &spb.Value{Kind: (*spb.Value_NullValue)(nil)},
+		want: nil,
+	}, {
+		in:   spb.NewNullValue(),
+		want: nil,
+	}, {
+		in:   &spb.Value{Kind: &spb.Value_NullValue{NullValue: math.MinInt32}},
+		want: nil,
+	}, {
+		in:   &spb.Value{Kind: (*spb.Value_BoolValue)(nil)},
+		want: nil,
+	}, {
+		in:   spb.NewBoolValue(false),
+		want: bool(false),
+	}, {
+		in:   &spb.Value{Kind: (*spb.Value_NumberValue)(nil)},
+		want: nil,
+	}, {
+		in:   spb.NewNumberValue(float64(math.MinInt32)),
+		want: float64(math.MinInt32),
+	}, {
+		in:   spb.NewNumberValue(float64(math.MinInt64)),
+		want: float64(math.MinInt64),
+	}, {
+		in:   spb.NewNumberValue(float64(123)),
+		want: float64(123),
+	}, {
+		in:   spb.NewNumberValue(float64(math.MaxInt32)),
+		want: float64(math.MaxInt32),
+	}, {
+		in:   spb.NewNumberValue(float64(math.MaxInt64)),
+		want: float64(math.MaxInt64),
+	}, {
+		in:   spb.NewNumberValue(float64(float32(123.456))),
+		want: float64(float32(123.456)),
+	}, {
+		in:   spb.NewNumberValue(float64(float64(123.456))),
+		want: float64(float64(123.456)),
+	}, {
+		in:   spb.NewNumberValue(math.NaN()),
+		want: string("NaN"),
+	}, {
+		in:   spb.NewNumberValue(math.Inf(-1)),
+		want: string("-Infinity"),
+	}, {
+		in:   spb.NewNumberValue(math.Inf(+1)),
+		want: string("Infinity"),
+	}, {
+		in:   &spb.Value{Kind: (*spb.Value_StringValue)(nil)},
+		want: nil,
+	}, {
+		in:   spb.NewStringValue("hello, world!"),
+		want: string("hello, world!"),
+	}, {
+		in:   spb.NewStringValue("3q2+7w=="),
+		want: string("3q2+7w=="),
+	}, {
+		in:   &spb.Value{Kind: (*spb.Value_StructValue)(nil)},
+		want: nil,
+	}, {
+		in:   &spb.Value{Kind: &spb.Value_StructValue{}},
+		want: make(map[string]interface{}),
+	}, {
+		in: spb.NewListValue(&spb.ListValue{Values: []*spb.Value{
+			spb.NewStringValue("one"),
+			spb.NewStringValue("two"),
+			spb.NewStringValue("three"),
+		}}),
+		want: []interface{}{"one", "two", "three"},
+	}, {
+		in:   &spb.Value{Kind: (*spb.Value_ListValue)(nil)},
+		want: nil,
+	}, {
+		in:   &spb.Value{Kind: &spb.Value_ListValue{}},
+		want: make([]interface{}, 0),
+	}, {
+		in: spb.NewListValue(&spb.ListValue{Values: []*spb.Value{
+			spb.NewStringValue("one"),
+			spb.NewStringValue("two"),
+			spb.NewStringValue("three"),
+		}}),
+		want: []interface{}{"one", "two", "three"},
+	}}
+
+	for _, tt := range tests {
+		got := tt.in.AsInterface()
+		if diff := cmp.Diff(tt.want, got); diff != "" {
+			t.Errorf("AsInterface(%v) mismatch (-want +got):\n%s", tt.in, diff)
+		}
+		gotJSON, gotErr := json.Marshal(got)
+		if gotErr != nil {
+			t.Errorf("Marshal error: %v", gotErr)
+		}
+		wantJSON, wantErr := tt.in.MarshalJSON()
+		if diff := cmp.Diff(wantJSON, gotJSON, equateJSON); diff != "" && wantErr == nil {
+			t.Errorf("MarshalJSON(%v) mismatch (-want +got):\n%s", tt.in, diff)
+		}
+	}
+}
diff --git a/types/known/timestamppb/timestamp.pb.go b/types/known/timestamppb/timestamp.pb.go
index 6fe6d42..0023d26 100644
--- a/types/known/timestamppb/timestamp.pb.go
+++ b/types/known/timestamppb/timestamp.pb.go
@@ -38,6 +38,7 @@
 	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
 	reflect "reflect"
 	sync "sync"
+	time "time"
 )
 
 // A Timestamp represents a point in time independent of any time zone or local
@@ -140,6 +141,64 @@
 	Nanos int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"`
 }
 
+// Now constructs a new Timestamp from the current time.
+func Now() *Timestamp {
+	return New(time.Now())
+}
+
+// New constructs a new Timestamp from the provided time.Time.
+func New(t time.Time) *Timestamp {
+	return &Timestamp{Seconds: int64(t.Unix()), Nanos: int32(t.Nanosecond())}
+}
+
+// AsTime converts x to a time.Time.
+func (x *Timestamp) AsTime() time.Time {
+	return time.Unix(int64(x.GetSeconds()), int64(x.GetNanos())).UTC()
+}
+
+// IsValid reports whether the timestamp is valid.
+// It is equivalent to CheckValid == nil.
+func (x *Timestamp) IsValid() bool {
+	return x.check() == 0
+}
+
+// CheckValid returns an error if the timestamp is invalid.
+// In particular, it checks whether the value represents a date that is
+// in the range of 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive.
+func (x *Timestamp) CheckValid() error {
+	switch x.check() {
+	case invalidUnderflow:
+		return protoimpl.X.NewError("timestamp (%v) before 0001-01-01", x)
+	case invalidOverflow:
+		return protoimpl.X.NewError("timestamp (%v) after 9999-12-31", x)
+	case invalidNanos:
+		return protoimpl.X.NewError("timestamp (%v) has out-of-range nanos", x)
+	default:
+		return nil
+	}
+}
+
+const invalidUnderflow = 1
+const invalidOverflow = 2
+const invalidNanos = 3
+
+func (x *Timestamp) check() uint {
+	const minTimestamp = -62135596800  // Seconds between 1970-01-01T00:00:00Z and 0001-01-01T00:00:00Z, inclusive
+	const maxTimestamp = +253402300799 // Seconds between 1970-01-01T00:00:00Z and 9999-12-31T23:59:59Z, inclusive
+	secs := x.GetSeconds()
+	nanos := x.GetNanos()
+	switch {
+	case secs < minTimestamp:
+		return invalidUnderflow
+	case secs > maxTimestamp:
+		return invalidOverflow
+	case nanos < 0 || nanos >= 1e9:
+		return invalidNanos
+	default:
+		return 0
+	}
+}
+
 func (x *Timestamp) Reset() {
 	*x = Timestamp{}
 	if protoimpl.UnsafeEnabled {
diff --git a/types/known/timestamppb/timestamp_test.go b/types/known/timestamppb/timestamp_test.go
new file mode 100644
index 0000000..a358aac
--- /dev/null
+++ b/types/known/timestamppb/timestamp_test.go
@@ -0,0 +1,104 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package timestamppb_test
+
+import (
+	"math"
+	"strings"
+	"testing"
+	"time"
+
+	"github.com/google/go-cmp/cmp"
+	"github.com/google/go-cmp/cmp/cmpopts"
+	"google.golang.org/protobuf/internal/detrand"
+	"google.golang.org/protobuf/testing/protocmp"
+
+	tspb "google.golang.org/protobuf/types/known/timestamppb"
+)
+
+func init() {
+	detrand.Disable()
+}
+
+const (
+	minTimestamp = -62135596800  // Seconds between 1970-01-01T00:00:00Z and 0001-01-01T00:00:00Z, inclusive
+	maxTimestamp = +253402300799 // Seconds between 1970-01-01T00:00:00Z and 9999-12-31T23:59:59Z, inclusive
+)
+
+func TestToTimestamp(t *testing.T) {
+	tests := []struct {
+		in   time.Time
+		want *tspb.Timestamp
+	}{
+		{in: time.Time{}, want: &tspb.Timestamp{Seconds: -62135596800, Nanos: 0}},
+		{in: time.Unix(0, 0), want: &tspb.Timestamp{Seconds: 0, Nanos: 0}},
+		{in: time.Unix(math.MinInt64, 0), want: &tspb.Timestamp{Seconds: math.MinInt64, Nanos: 0}},
+		{in: time.Unix(math.MaxInt64, 1e9-1), want: &tspb.Timestamp{Seconds: math.MaxInt64, Nanos: 1e9 - 1}},
+		{in: time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC), want: &tspb.Timestamp{Seconds: minTimestamp, Nanos: 0}},
+		{in: time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC).Add(-time.Nanosecond), want: &tspb.Timestamp{Seconds: minTimestamp - 1, Nanos: 1e9 - 1}},
+		{in: time.Date(9999, 12, 31, 23, 59, 59, 1e9-1, time.UTC), want: &tspb.Timestamp{Seconds: maxTimestamp, Nanos: 1e9 - 1}},
+		{in: time.Date(9999, 12, 31, 23, 59, 59, 1e9-1, time.UTC).Add(+time.Nanosecond), want: &tspb.Timestamp{Seconds: maxTimestamp + 1}},
+		{in: time.Date(1961, 1, 26, 0, 0, 0, 0, time.UTC), want: &tspb.Timestamp{Seconds: -281836800, Nanos: 0}},
+		{in: time.Date(2011, 1, 26, 0, 0, 0, 0, time.UTC), want: &tspb.Timestamp{Seconds: 1296000000, Nanos: 0}},
+		{in: time.Date(2011, 1, 26, 3, 25, 45, 940483, time.UTC), want: &tspb.Timestamp{Seconds: 1296012345, Nanos: 940483}},
+	}
+
+	for _, tt := range tests {
+		got := tspb.New(tt.in)
+		if diff := cmp.Diff(tt.want, got, protocmp.Transform()); diff != "" {
+			t.Errorf("New(%v) mismatch (-want +got):\n%s", tt.in, diff)
+		}
+	}
+}
+
+func TestFromTimestamp(t *testing.T) {
+	tests := []struct {
+		in       *tspb.Timestamp
+		wantTime time.Time
+		wantErr  error
+	}{
+		{in: nil, wantTime: time.Unix(0, 0)},
+		{in: new(tspb.Timestamp), wantTime: time.Unix(0, 0)},
+		{in: &tspb.Timestamp{Seconds: -62135596800, Nanos: 0}, wantTime: time.Time{}},
+		{in: &tspb.Timestamp{Seconds: -1, Nanos: -1}, wantTime: time.Unix(-1, -1), wantErr: textError("timestamp (seconds:-1 nanos:-1) has out-of-range nanos")},
+		{in: &tspb.Timestamp{Seconds: -1, Nanos: 0}, wantTime: time.Unix(-1, 0)},
+		{in: &tspb.Timestamp{Seconds: -1, Nanos: +1}, wantTime: time.Unix(-1, +1)},
+		{in: &tspb.Timestamp{Seconds: 0, Nanos: -1}, wantTime: time.Unix(0, -1), wantErr: textError("timestamp (nanos:-1) has out-of-range nanos")},
+		{in: &tspb.Timestamp{Seconds: 0, Nanos: 0}, wantTime: time.Unix(0, 0)},
+		{in: &tspb.Timestamp{Seconds: 0, Nanos: +1}, wantTime: time.Unix(0, +1)},
+		{in: &tspb.Timestamp{Seconds: +1, Nanos: -1}, wantTime: time.Unix(+1, -1), wantErr: textError("timestamp (seconds:1 nanos:-1) has out-of-range nanos")},
+		{in: &tspb.Timestamp{Seconds: +1, Nanos: 0}, wantTime: time.Unix(+1, 0)},
+		{in: &tspb.Timestamp{Seconds: +1, Nanos: +1}, wantTime: time.Unix(+1, +1)},
+		{in: &tspb.Timestamp{Seconds: -9876543210, Nanos: -1098765432}, wantTime: time.Unix(-9876543210, -1098765432), wantErr: textError("timestamp (seconds:-9876543210 nanos:-1098765432) has out-of-range nanos")},
+		{in: &tspb.Timestamp{Seconds: +9876543210, Nanos: -1098765432}, wantTime: time.Unix(+9876543210, -1098765432), wantErr: textError("timestamp (seconds:9876543210 nanos:-1098765432) has out-of-range nanos")},
+		{in: &tspb.Timestamp{Seconds: -9876543210, Nanos: +1098765432}, wantTime: time.Unix(-9876543210, +1098765432), wantErr: textError("timestamp (seconds:-9876543210 nanos:1098765432) has out-of-range nanos")},
+		{in: &tspb.Timestamp{Seconds: +9876543210, Nanos: +1098765432}, wantTime: time.Unix(+9876543210, +1098765432), wantErr: textError("timestamp (seconds:9876543210 nanos:1098765432) has out-of-range nanos")},
+		{in: &tspb.Timestamp{Seconds: math.MinInt64, Nanos: 0}, wantTime: time.Unix(math.MinInt64, 0), wantErr: textError("timestamp (seconds:-9223372036854775808) before 0001-01-01")},
+		{in: &tspb.Timestamp{Seconds: math.MaxInt64, Nanos: 1e9 - 1}, wantTime: time.Unix(math.MaxInt64, 1e9-1), wantErr: textError("timestamp (seconds:9223372036854775807 nanos:999999999) after 9999-12-31")},
+		{in: &tspb.Timestamp{Seconds: minTimestamp, Nanos: 0}, wantTime: time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)},
+		{in: &tspb.Timestamp{Seconds: minTimestamp - 1, Nanos: 1e9 - 1}, wantTime: time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC).Add(-time.Nanosecond), wantErr: textError("timestamp (seconds:-62135596801 nanos:999999999) before 0001-01-01")},
+		{in: &tspb.Timestamp{Seconds: maxTimestamp, Nanos: 1e9 - 1}, wantTime: time.Date(9999, 12, 31, 23, 59, 59, 1e9-1, time.UTC)},
+		{in: &tspb.Timestamp{Seconds: maxTimestamp + 1}, wantTime: time.Date(9999, 12, 31, 23, 59, 59, 1e9-1, time.UTC).Add(+time.Nanosecond), wantErr: textError("timestamp (seconds:253402300800) after 9999-12-31")},
+		{in: &tspb.Timestamp{Seconds: -281836800, Nanos: 0}, wantTime: time.Date(1961, 1, 26, 0, 0, 0, 0, time.UTC)},
+		{in: &tspb.Timestamp{Seconds: 1296000000, Nanos: 0}, wantTime: time.Date(2011, 1, 26, 0, 0, 0, 0, time.UTC)},
+		{in: &tspb.Timestamp{Seconds: 1296012345, Nanos: 940483}, wantTime: time.Date(2011, 1, 26, 3, 25, 45, 940483, time.UTC)},
+	}
+
+	for _, tt := range tests {
+		gotTime := tt.in.AsTime()
+		if diff := cmp.Diff(tt.wantTime, gotTime); diff != "" {
+			t.Errorf("AsTime(%v) mismatch (-want +got):\n%s", tt.in, diff)
+		}
+		gotErr := tt.in.CheckValid()
+		if diff := cmp.Diff(tt.wantErr, gotErr, cmpopts.EquateErrors()); diff != "" {
+			t.Errorf("CheckValid(%v) mismatch (-want +got):\n%s", tt.in, diff)
+		}
+	}
+}
+
+type textError string
+
+func (e textError) Error() string     { return string(e) }
+func (e textError) Is(err error) bool { return err != nil && strings.Contains(err.Error(), e.Error()) }
diff --git a/types/known/wrapperspb/wrappers.pb.go b/types/known/wrapperspb/wrappers.pb.go
index 5c5ec2f..2355adf 100644
--- a/types/known/wrapperspb/wrappers.pb.go
+++ b/types/known/wrapperspb/wrappers.pb.go
@@ -62,6 +62,11 @@
 	Value float64 `protobuf:"fixed64,1,opt,name=value,proto3" json:"value,omitempty"`
 }
 
+// Double stores v in a new DoubleValue and returns a pointer to it.
+func Double(v float64) *DoubleValue {
+	return &DoubleValue{Value: v}
+}
+
 func (x *DoubleValue) Reset() {
 	*x = DoubleValue{}
 	if protoimpl.UnsafeEnabled {
@@ -113,6 +118,11 @@
 	Value float32 `protobuf:"fixed32,1,opt,name=value,proto3" json:"value,omitempty"`
 }
 
+// Float stores v in a new FloatValue and returns a pointer to it.
+func Float(v float32) *FloatValue {
+	return &FloatValue{Value: v}
+}
+
 func (x *FloatValue) Reset() {
 	*x = FloatValue{}
 	if protoimpl.UnsafeEnabled {
@@ -164,6 +174,11 @@
 	Value int64 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
 }
 
+// Int64 stores v in a new Int64Value and returns a pointer to it.
+func Int64(v int64) *Int64Value {
+	return &Int64Value{Value: v}
+}
+
 func (x *Int64Value) Reset() {
 	*x = Int64Value{}
 	if protoimpl.UnsafeEnabled {
@@ -215,6 +230,11 @@
 	Value uint64 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
 }
 
+// UInt64 stores v in a new UInt64Value and returns a pointer to it.
+func UInt64(v uint64) *UInt64Value {
+	return &UInt64Value{Value: v}
+}
+
 func (x *UInt64Value) Reset() {
 	*x = UInt64Value{}
 	if protoimpl.UnsafeEnabled {
@@ -266,6 +286,11 @@
 	Value int32 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
 }
 
+// Int32 stores v in a new Int32Value and returns a pointer to it.
+func Int32(v int32) *Int32Value {
+	return &Int32Value{Value: v}
+}
+
 func (x *Int32Value) Reset() {
 	*x = Int32Value{}
 	if protoimpl.UnsafeEnabled {
@@ -317,6 +342,11 @@
 	Value uint32 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
 }
 
+// UInt32 stores v in a new UInt32Value and returns a pointer to it.
+func UInt32(v uint32) *UInt32Value {
+	return &UInt32Value{Value: v}
+}
+
 func (x *UInt32Value) Reset() {
 	*x = UInt32Value{}
 	if protoimpl.UnsafeEnabled {
@@ -368,6 +398,11 @@
 	Value bool `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
 }
 
+// Bool stores v in a new BoolValue and returns a pointer to it.
+func Bool(v bool) *BoolValue {
+	return &BoolValue{Value: v}
+}
+
 func (x *BoolValue) Reset() {
 	*x = BoolValue{}
 	if protoimpl.UnsafeEnabled {
@@ -419,6 +454,11 @@
 	Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"`
 }
 
+// String stores v in a new StringValue and returns a pointer to it.
+func String(v string) *StringValue {
+	return &StringValue{Value: v}
+}
+
 func (x *StringValue) Reset() {
 	*x = StringValue{}
 	if protoimpl.UnsafeEnabled {
@@ -470,6 +510,11 @@
 	Value []byte `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"`
 }
 
+// Bytes stores v in a new BytesValue and returns a pointer to it.
+func Bytes(v []byte) *BytesValue {
+	return &BytesValue{Value: v}
+}
+
 func (x *BytesValue) Reset() {
 	*x = BytesValue{}
 	if protoimpl.UnsafeEnabled {