// Copyright 2020 Google LLC.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Code generated file. DO NOT EDIT.

// Package documentai provides access to the Cloud Document AI API.
//
// For product documentation, see: https://cloud.google.com/document-ai/docs/
//
// Creating a client
//
// Usage example:
//
//   import "google.golang.org/api/documentai/v1beta2"
//   ...
//   ctx := context.Background()
//   documentaiService, err := documentai.NewService(ctx)
//
// In this example, Google Application Default Credentials are used for authentication.
//
// For information on how to create and obtain Application Default Credentials, see https://developers.google.com/identity/protocols/application-default-credentials.
//
// Other authentication options
//
// To use an API key for authentication (note: some APIs do not support API keys), use option.WithAPIKey:
//
//   documentaiService, err := documentai.NewService(ctx, option.WithAPIKey("AIza..."))
//
// To use an OAuth token (e.g., a user token obtained via a three-legged OAuth flow), use option.WithTokenSource:
//
//   config := &oauth2.Config{...}
//   // ...
//   token, err := config.Exchange(ctx, ...)
//   documentaiService, err := documentai.NewService(ctx, option.WithTokenSource(config.TokenSource(ctx, token)))
//
// See https://godoc.org/google.golang.org/api/option/ for details on options.
package documentai // import "google.golang.org/api/documentai/v1beta2"

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strconv"
	"strings"

	googleapi "google.golang.org/api/googleapi"
	gensupport "google.golang.org/api/internal/gensupport"
	option "google.golang.org/api/option"
	internaloption "google.golang.org/api/option/internaloption"
	htransport "google.golang.org/api/transport/http"
)

// Always reference these packages, just in case the auto-generated code
// below doesn't.
var _ = bytes.NewBuffer
var _ = strconv.Itoa
var _ = fmt.Sprintf
var _ = json.NewDecoder
var _ = io.Copy
var _ = url.Parse
var _ = gensupport.MarshalJSON
var _ = googleapi.Version
var _ = errors.New
var _ = strings.Replace
var _ = context.Canceled
var _ = internaloption.WithDefaultEndpoint

const apiId = "documentai:v1beta2"
const apiName = "documentai"
const apiVersion = "v1beta2"
const basePath = "https://documentai.googleapis.com/"
const mtlsBasePath = "https://documentai.mtls.googleapis.com/"

// OAuth2 scopes used by this API.
const (
	// View and manage your data across Google Cloud Platform services
	CloudPlatformScope = "https://www.googleapis.com/auth/cloud-platform"
)

// NewService creates a new Service.
func NewService(ctx context.Context, opts ...option.ClientOption) (*Service, error) {
	scopesOption := option.WithScopes(
		"https://www.googleapis.com/auth/cloud-platform",
	)
	// NOTE: prepend, so we don't override user-specified scopes.
	opts = append([]option.ClientOption{scopesOption}, opts...)
	opts = append(opts, internaloption.WithDefaultEndpoint(basePath))
	opts = append(opts, internaloption.WithDefaultMTLSEndpoint(mtlsBasePath))
	client, endpoint, err := htransport.NewClient(ctx, opts...)
	if err != nil {
		return nil, err
	}
	s, err := New(client)
	if err != nil {
		return nil, err
	}
	if endpoint != "" {
		s.BasePath = endpoint
	}
	return s, nil
}

// New creates a new Service. It uses the provided http.Client for requests.
//
// Deprecated: please use NewService instead.
// To provide a custom HTTP client, use option.WithHTTPClient.
// If you are using google.golang.org/api/googleapis/transport.APIKey, use option.WithAPIKey with NewService instead.
func New(client *http.Client) (*Service, error) {
	if client == nil {
		return nil, errors.New("client is nil")
	}
	s := &Service{client: client, BasePath: basePath}
	s.Projects = NewProjectsService(s)
	return s, nil
}

type Service struct {
	client    *http.Client
	BasePath  string // API endpoint base URL
	UserAgent string // optional additional User-Agent fragment

	Projects *ProjectsService
}

func (s *Service) userAgent() string {
	if s.UserAgent == "" {
		return googleapi.UserAgent
	}
	return googleapi.UserAgent + " " + s.UserAgent
}

func NewProjectsService(s *Service) *ProjectsService {
	rs := &ProjectsService{s: s}
	rs.Documents = NewProjectsDocumentsService(s)
	rs.Locations = NewProjectsLocationsService(s)
	rs.Operations = NewProjectsOperationsService(s)
	return rs
}

type ProjectsService struct {
	s *Service

	Documents *ProjectsDocumentsService

	Locations *ProjectsLocationsService

	Operations *ProjectsOperationsService
}

func NewProjectsDocumentsService(s *Service) *ProjectsDocumentsService {
	rs := &ProjectsDocumentsService{s: s}
	return rs
}

type ProjectsDocumentsService struct {
	s *Service
}

func NewProjectsLocationsService(s *Service) *ProjectsLocationsService {
	rs := &ProjectsLocationsService{s: s}
	rs.Documents = NewProjectsLocationsDocumentsService(s)
	rs.Operations = NewProjectsLocationsOperationsService(s)
	return rs
}

type ProjectsLocationsService struct {
	s *Service

	Documents *ProjectsLocationsDocumentsService

	Operations *ProjectsLocationsOperationsService
}

func NewProjectsLocationsDocumentsService(s *Service) *ProjectsLocationsDocumentsService {
	rs := &ProjectsLocationsDocumentsService{s: s}
	return rs
}

type ProjectsLocationsDocumentsService struct {
	s *Service
}

func NewProjectsLocationsOperationsService(s *Service) *ProjectsLocationsOperationsService {
	rs := &ProjectsLocationsOperationsService{s: s}
	return rs
}

type ProjectsLocationsOperationsService struct {
	s *Service
}

func NewProjectsOperationsService(s *Service) *ProjectsOperationsService {
	rs := &ProjectsOperationsService{s: s}
	return rs
}

type ProjectsOperationsService struct {
	s *Service
}

// GoogleCloudDocumentaiV1beta1BatchProcessDocumentsResponse: Response
// to an batch document processing request. This is returned in
// the LRO Operation after the operation is complete.
type GoogleCloudDocumentaiV1beta1BatchProcessDocumentsResponse struct {
	// Responses: Responses for each individual document.
	Responses []*GoogleCloudDocumentaiV1beta1ProcessDocumentResponse `json:"responses,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Responses") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Responses") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1BatchProcessDocumentsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1BatchProcessDocumentsResponse
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta1BoundingPoly: A bounding polygon for the
// detected image annotation.
type GoogleCloudDocumentaiV1beta1BoundingPoly struct {
	// NormalizedVertices: The bounding polygon normalized vertices.
	NormalizedVertices []*GoogleCloudDocumentaiV1beta1NormalizedVertex `json:"normalizedVertices,omitempty"`

	// Vertices: The bounding polygon vertices.
	Vertices []*GoogleCloudDocumentaiV1beta1Vertex `json:"vertices,omitempty"`

	// ForceSendFields is a list of field names (e.g. "NormalizedVertices")
	// to unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "NormalizedVertices") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1BoundingPoly) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1BoundingPoly
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta1Document: Document represents the
// canonical document resource in Document Understanding
// AI.
// It is an interchange format that provides insights into documents and
// allows
// for collaboration between users and Document Understanding AI to
// iterate and
// optimize for quality.
type GoogleCloudDocumentaiV1beta1Document struct {
	// Content: Inline document content, represented as a stream of
	// bytes.
	// Note: As with all `bytes` fields, protobuffers use a pure
	// binary
	// representation, whereas JSON representations use base64.
	Content string `json:"content,omitempty"`

	// Entities: A list of entities detected on Document.text. For document
	// shards,
	// entities in this list may cross shard boundaries.
	Entities []*GoogleCloudDocumentaiV1beta1DocumentEntity `json:"entities,omitempty"`

	// EntityRelations: Relationship among Document.entities.
	EntityRelations []*GoogleCloudDocumentaiV1beta1DocumentEntityRelation `json:"entityRelations,omitempty"`

	// Error: Any error that occurred while processing this document.
	Error *GoogleRpcStatus `json:"error,omitempty"`

	// MimeType: An IANA published MIME type (also referred to as media
	// type). For more
	// information,
	// see
	// https://www.iana.org/assignments/media-types/media-types.xhtml.
	MimeType string `json:"mimeType,omitempty"`

	// Pages: Visual page layout for the Document.
	Pages []*GoogleCloudDocumentaiV1beta1DocumentPage `json:"pages,omitempty"`

	// ShardInfo: Information about the sharding if this document is sharded
	// part of a larger
	// document. If the document is not sharded, this message is not
	// specified.
	ShardInfo *GoogleCloudDocumentaiV1beta1DocumentShardInfo `json:"shardInfo,omitempty"`

	// Text: UTF-8 encoded text in reading order from the document.
	Text string `json:"text,omitempty"`

	// TextStyles: Styles for the Document.text.
	TextStyles []*GoogleCloudDocumentaiV1beta1DocumentStyle `json:"textStyles,omitempty"`

	// Translations: A list of translations on Document.text. For document
	// shards,
	// translations in this list may cross shard boundaries.
	Translations []*GoogleCloudDocumentaiV1beta1DocumentTranslation `json:"translations,omitempty"`

	// Uri: Currently supports Google Cloud Storage URI of the form
	//    `gs://bucket_name/object_name`. Object versioning is not
	// supported.
	//    See [Google Cloud Storage Request
	//    URIs](https://cloud.google.com/storage/docs/reference-uris) for
	// more
	//    info.
	Uri string `json:"uri,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Content") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Content") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1Document) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1Document
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta1DocumentEntity: A phrase in the text that
// is a known entity type, such as a person, an
// organization, or location.
type GoogleCloudDocumentaiV1beta1DocumentEntity struct {
	// Confidence: Optional. Confidence of detected Schema entity. Range [0,
	// 1].
	Confidence float64 `json:"confidence,omitempty"`

	// MentionId: Deprecated.  Use `id` field instead.
	MentionId string `json:"mentionId,omitempty"`

	// MentionText: Text value in the document e.g. `1600 Amphitheatre
	// Pkwy`.
	MentionText string `json:"mentionText,omitempty"`

	// TextAnchor: Provenance of the entity.
	// Text anchor indexing into the Document.text.
	TextAnchor *GoogleCloudDocumentaiV1beta1DocumentTextAnchor `json:"textAnchor,omitempty"`

	// Type: Entity type from a schema e.g. `Address`.
	Type string `json:"type,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Confidence") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Confidence") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1DocumentEntity) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1DocumentEntity
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudDocumentaiV1beta1DocumentEntity) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudDocumentaiV1beta1DocumentEntity
	var s1 struct {
		Confidence gensupport.JSONFloat64 `json:"confidence"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.Confidence = float64(s1.Confidence)
	return nil
}

// GoogleCloudDocumentaiV1beta1DocumentEntityRelation: Relationship
// between Entities.
type GoogleCloudDocumentaiV1beta1DocumentEntityRelation struct {
	// ObjectId: Object entity id.
	ObjectId string `json:"objectId,omitempty"`

	// Relation: Relationship description.
	Relation string `json:"relation,omitempty"`

	// SubjectId: Subject entity id.
	SubjectId string `json:"subjectId,omitempty"`

	// ForceSendFields is a list of field names (e.g. "ObjectId") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "ObjectId") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1DocumentEntityRelation) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1DocumentEntityRelation
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta1DocumentPage: A page in a Document.
type GoogleCloudDocumentaiV1beta1DocumentPage struct {
	// Blocks: A list of visually detected text blocks on the page.
	// A block has a set of lines (collected into paragraphs) that have a
	// common
	// line-spacing and orientation.
	Blocks []*GoogleCloudDocumentaiV1beta1DocumentPageBlock `json:"blocks,omitempty"`

	// DetectedLanguages: A list of detected languages together with
	// confidence.
	DetectedLanguages []*GoogleCloudDocumentaiV1beta1DocumentPageDetectedLanguage `json:"detectedLanguages,omitempty"`

	// Dimension: Physical dimension of the page.
	Dimension *GoogleCloudDocumentaiV1beta1DocumentPageDimension `json:"dimension,omitempty"`

	// FormFields: A list of visually detected form fields on the page.
	FormFields []*GoogleCloudDocumentaiV1beta1DocumentPageFormField `json:"formFields,omitempty"`

	// Layout: Layout for the page.
	Layout *GoogleCloudDocumentaiV1beta1DocumentPageLayout `json:"layout,omitempty"`

	// Lines: A list of visually detected text lines on the page.
	// A collection of tokens that a human would perceive as a line.
	Lines []*GoogleCloudDocumentaiV1beta1DocumentPageLine `json:"lines,omitempty"`

	// PageNumber: 1-based index for current Page in a parent
	// Document.
	// Useful when a page is taken out of a Document for
	// individual
	// processing.
	PageNumber int64 `json:"pageNumber,omitempty"`

	// Paragraphs: A list of visually detected text paragraphs on the
	// page.
	// A collection of lines that a human would perceive as a paragraph.
	Paragraphs []*GoogleCloudDocumentaiV1beta1DocumentPageParagraph `json:"paragraphs,omitempty"`

	// Tables: A list of visually detected tables on the page.
	Tables []*GoogleCloudDocumentaiV1beta1DocumentPageTable `json:"tables,omitempty"`

	// Tokens: A list of visually detected tokens on the page.
	Tokens []*GoogleCloudDocumentaiV1beta1DocumentPageToken `json:"tokens,omitempty"`

	// VisualElements: A list of detected non-text visual elements e.g.
	// checkbox,
	// signature etc. on the page.
	VisualElements []*GoogleCloudDocumentaiV1beta1DocumentPageVisualElement `json:"visualElements,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Blocks") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Blocks") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1DocumentPage) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1DocumentPage
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta1DocumentPageBlock: A block has a set of
// lines (collected into paragraphs) that have a
// common line-spacing and orientation.
type GoogleCloudDocumentaiV1beta1DocumentPageBlock struct {
	// DetectedLanguages: A list of detected languages together with
	// confidence.
	DetectedLanguages []*GoogleCloudDocumentaiV1beta1DocumentPageDetectedLanguage `json:"detectedLanguages,omitempty"`

	// Layout: Layout for Block.
	Layout *GoogleCloudDocumentaiV1beta1DocumentPageLayout `json:"layout,omitempty"`

	// ForceSendFields is a list of field names (e.g. "DetectedLanguages")
	// to unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "DetectedLanguages") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1DocumentPageBlock) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1DocumentPageBlock
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta1DocumentPageDetectedLanguage: Detected
// language for a structural component.
type GoogleCloudDocumentaiV1beta1DocumentPageDetectedLanguage struct {
	// Confidence: Confidence of detected language. Range [0, 1].
	Confidence float64 `json:"confidence,omitempty"`

	// LanguageCode: The BCP-47 language code, such as "en-US" or "sr-Latn".
	// For more
	// information,
	// see
	// http://www.unicode.org/reports/tr35/#Unicode_locale_identifier.
	LanguageCode string `json:"languageCode,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Confidence") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Confidence") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1DocumentPageDetectedLanguage) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1DocumentPageDetectedLanguage
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudDocumentaiV1beta1DocumentPageDetectedLanguage) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudDocumentaiV1beta1DocumentPageDetectedLanguage
	var s1 struct {
		Confidence gensupport.JSONFloat64 `json:"confidence"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.Confidence = float64(s1.Confidence)
	return nil
}

// GoogleCloudDocumentaiV1beta1DocumentPageDimension: Dimension for the
// page.
type GoogleCloudDocumentaiV1beta1DocumentPageDimension struct {
	// Height: Page height.
	Height float64 `json:"height,omitempty"`

	// Unit: Dimension unit.
	Unit string `json:"unit,omitempty"`

	// Width: Page width.
	Width float64 `json:"width,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Height") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Height") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1DocumentPageDimension) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1DocumentPageDimension
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudDocumentaiV1beta1DocumentPageDimension) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudDocumentaiV1beta1DocumentPageDimension
	var s1 struct {
		Height gensupport.JSONFloat64 `json:"height"`
		Width  gensupport.JSONFloat64 `json:"width"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.Height = float64(s1.Height)
	s.Width = float64(s1.Width)
	return nil
}

// GoogleCloudDocumentaiV1beta1DocumentPageFormField: A form field
// detected on the page.
type GoogleCloudDocumentaiV1beta1DocumentPageFormField struct {
	// FieldName: Layout for the FormField name. e.g. `Address`,
	// `Email`,
	// `Grand total`, `Phone number`, etc.
	FieldName *GoogleCloudDocumentaiV1beta1DocumentPageLayout `json:"fieldName,omitempty"`

	// FieldValue: Layout for the FormField value.
	FieldValue *GoogleCloudDocumentaiV1beta1DocumentPageLayout `json:"fieldValue,omitempty"`

	// NameDetectedLanguages: A list of detected languages for name together
	// with confidence.
	NameDetectedLanguages []*GoogleCloudDocumentaiV1beta1DocumentPageDetectedLanguage `json:"nameDetectedLanguages,omitempty"`

	// ValueDetectedLanguages: A list of detected languages for value
	// together with confidence.
	ValueDetectedLanguages []*GoogleCloudDocumentaiV1beta1DocumentPageDetectedLanguage `json:"valueDetectedLanguages,omitempty"`

	// ForceSendFields is a list of field names (e.g. "FieldName") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "FieldName") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1DocumentPageFormField) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1DocumentPageFormField
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta1DocumentPageLayout: Visual element
// describing a layout unit on a page.
type GoogleCloudDocumentaiV1beta1DocumentPageLayout struct {
	// BoundingPoly: The bounding polygon for the Layout.
	BoundingPoly *GoogleCloudDocumentaiV1beta1BoundingPoly `json:"boundingPoly,omitempty"`

	// Confidence: Confidence of the current Layout within context of the
	// object this
	// layout is for. e.g. confidence can be for a single token, a table,
	// a visual element, etc. depending on context. Range [0, 1].
	Confidence float64 `json:"confidence,omitempty"`

	// Orientation: Detected orientation for the Layout.
	//
	// Possible values:
	//   "ORIENTATION_UNSPECIFIED" - Unspecified orientation.
	//   "PAGE_UP" - Orientation is aligned with page up.
	//   "PAGE_RIGHT" - Orientation is aligned with page right.
	// Turn the head 90 degrees clockwise from upright to read.
	//   "PAGE_DOWN" - Orientation is aligned with page down.
	// Turn the head 180 degrees from upright to read.
	//   "PAGE_LEFT" - Orientation is aligned with page left.
	// Turn the head 90 degrees counterclockwise from upright to read.
	Orientation string `json:"orientation,omitempty"`

	// TextAnchor: Text anchor indexing into the Document.text.
	TextAnchor *GoogleCloudDocumentaiV1beta1DocumentTextAnchor `json:"textAnchor,omitempty"`

	// ForceSendFields is a list of field names (e.g. "BoundingPoly") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "BoundingPoly") to include
	// in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. However, any field with
	// an empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1DocumentPageLayout) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1DocumentPageLayout
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudDocumentaiV1beta1DocumentPageLayout) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudDocumentaiV1beta1DocumentPageLayout
	var s1 struct {
		Confidence gensupport.JSONFloat64 `json:"confidence"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.Confidence = float64(s1.Confidence)
	return nil
}

// GoogleCloudDocumentaiV1beta1DocumentPageLine: A collection of tokens
// that a human would perceive as a line.
// Does not cross column boundaries, can be horizontal, vertical, etc.
type GoogleCloudDocumentaiV1beta1DocumentPageLine struct {
	// DetectedLanguages: A list of detected languages together with
	// confidence.
	DetectedLanguages []*GoogleCloudDocumentaiV1beta1DocumentPageDetectedLanguage `json:"detectedLanguages,omitempty"`

	// Layout: Layout for Line.
	Layout *GoogleCloudDocumentaiV1beta1DocumentPageLayout `json:"layout,omitempty"`

	// ForceSendFields is a list of field names (e.g. "DetectedLanguages")
	// to unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "DetectedLanguages") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1DocumentPageLine) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1DocumentPageLine
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta1DocumentPageParagraph: A collection of
// lines that a human would perceive as a paragraph.
type GoogleCloudDocumentaiV1beta1DocumentPageParagraph struct {
	// DetectedLanguages: A list of detected languages together with
	// confidence.
	DetectedLanguages []*GoogleCloudDocumentaiV1beta1DocumentPageDetectedLanguage `json:"detectedLanguages,omitempty"`

	// Layout: Layout for Paragraph.
	Layout *GoogleCloudDocumentaiV1beta1DocumentPageLayout `json:"layout,omitempty"`

	// ForceSendFields is a list of field names (e.g. "DetectedLanguages")
	// to unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "DetectedLanguages") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1DocumentPageParagraph) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1DocumentPageParagraph
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta1DocumentPageTable: A table representation
// similar to HTML table structure.
type GoogleCloudDocumentaiV1beta1DocumentPageTable struct {
	// BodyRows: Body rows of the table.
	BodyRows []*GoogleCloudDocumentaiV1beta1DocumentPageTableTableRow `json:"bodyRows,omitempty"`

	// DetectedLanguages: A list of detected languages together with
	// confidence.
	DetectedLanguages []*GoogleCloudDocumentaiV1beta1DocumentPageDetectedLanguage `json:"detectedLanguages,omitempty"`

	// HeaderRows: Header rows of the table.
	HeaderRows []*GoogleCloudDocumentaiV1beta1DocumentPageTableTableRow `json:"headerRows,omitempty"`

	// Layout: Layout for Table.
	Layout *GoogleCloudDocumentaiV1beta1DocumentPageLayout `json:"layout,omitempty"`

	// ForceSendFields is a list of field names (e.g. "BodyRows") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "BodyRows") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1DocumentPageTable) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1DocumentPageTable
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta1DocumentPageTableTableCell: A cell
// representation inside the table.
type GoogleCloudDocumentaiV1beta1DocumentPageTableTableCell struct {
	// ColSpan: How many columns this cell spans.
	ColSpan int64 `json:"colSpan,omitempty"`

	// DetectedLanguages: A list of detected languages together with
	// confidence.
	DetectedLanguages []*GoogleCloudDocumentaiV1beta1DocumentPageDetectedLanguage `json:"detectedLanguages,omitempty"`

	// Layout: Layout for TableCell.
	Layout *GoogleCloudDocumentaiV1beta1DocumentPageLayout `json:"layout,omitempty"`

	// RowSpan: How many rows this cell spans.
	RowSpan int64 `json:"rowSpan,omitempty"`

	// ForceSendFields is a list of field names (e.g. "ColSpan") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "ColSpan") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1DocumentPageTableTableCell) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1DocumentPageTableTableCell
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta1DocumentPageTableTableRow: A row of table
// cells.
type GoogleCloudDocumentaiV1beta1DocumentPageTableTableRow struct {
	// Cells: Cells that make up this row.
	Cells []*GoogleCloudDocumentaiV1beta1DocumentPageTableTableCell `json:"cells,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Cells") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Cells") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1DocumentPageTableTableRow) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1DocumentPageTableTableRow
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta1DocumentPageToken: A detected token.
type GoogleCloudDocumentaiV1beta1DocumentPageToken struct {
	// DetectedBreak: Detected break at the end of a Token.
	DetectedBreak *GoogleCloudDocumentaiV1beta1DocumentPageTokenDetectedBreak `json:"detectedBreak,omitempty"`

	// DetectedLanguages: A list of detected languages together with
	// confidence.
	DetectedLanguages []*GoogleCloudDocumentaiV1beta1DocumentPageDetectedLanguage `json:"detectedLanguages,omitempty"`

	// Layout: Layout for Token.
	Layout *GoogleCloudDocumentaiV1beta1DocumentPageLayout `json:"layout,omitempty"`

	// ForceSendFields is a list of field names (e.g. "DetectedBreak") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "DetectedBreak") to include
	// in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. However, any field with
	// an empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1DocumentPageToken) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1DocumentPageToken
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta1DocumentPageTokenDetectedBreak: Detected
// break at the end of a Token.
type GoogleCloudDocumentaiV1beta1DocumentPageTokenDetectedBreak struct {
	// Type: Detected break type.
	//
	// Possible values:
	//   "TYPE_UNSPECIFIED" - Unspecified break type.
	//   "SPACE" - A single whitespace.
	//   "WIDE_SPACE" - A wider whitespace.
	//   "HYPHEN" - A hyphen that indicates that a token has been split
	// across lines.
	Type string `json:"type,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Type") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Type") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1DocumentPageTokenDetectedBreak) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1DocumentPageTokenDetectedBreak
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta1DocumentPageVisualElement: Detected
// non-text visual elements e.g. checkbox, signature etc. on the
// page.
type GoogleCloudDocumentaiV1beta1DocumentPageVisualElement struct {
	// DetectedLanguages: A list of detected languages together with
	// confidence.
	DetectedLanguages []*GoogleCloudDocumentaiV1beta1DocumentPageDetectedLanguage `json:"detectedLanguages,omitempty"`

	// Layout: Layout for VisualElement.
	Layout *GoogleCloudDocumentaiV1beta1DocumentPageLayout `json:"layout,omitempty"`

	// Type: Type of the VisualElement.
	Type string `json:"type,omitempty"`

	// ForceSendFields is a list of field names (e.g. "DetectedLanguages")
	// to unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "DetectedLanguages") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1DocumentPageVisualElement) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1DocumentPageVisualElement
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta1DocumentShardInfo: For a large document,
// sharding may be performed to produce several
// document shards. Each document shard contains this field to detail
// which
// shard it is.
type GoogleCloudDocumentaiV1beta1DocumentShardInfo struct {
	// ShardCount: Total number of shards.
	ShardCount int64 `json:"shardCount,omitempty,string"`

	// ShardIndex: The 0-based index of this shard.
	ShardIndex int64 `json:"shardIndex,omitempty,string"`

	// TextOffset: The index of the first character in Document.text in the
	// overall
	// document global text.
	TextOffset int64 `json:"textOffset,omitempty,string"`

	// ForceSendFields is a list of field names (e.g. "ShardCount") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "ShardCount") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1DocumentShardInfo) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1DocumentShardInfo
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta1DocumentStyle: Annotation for common text
// style attributes. This adheres to CSS
// conventions as much as possible.
type GoogleCloudDocumentaiV1beta1DocumentStyle struct {
	// BackgroundColor: Text background color.
	BackgroundColor *GoogleTypeColor `json:"backgroundColor,omitempty"`

	// Color: Text color.
	Color *GoogleTypeColor `json:"color,omitempty"`

	// FontSize: Font size.
	FontSize *GoogleCloudDocumentaiV1beta1DocumentStyleFontSize `json:"fontSize,omitempty"`

	// FontWeight: Font weight. Possible values are normal, bold, bolder,
	// and lighter.
	// https://www.w3schools.com/cssref/pr_font_weight.asp
	FontWeight string `json:"fontWeight,omitempty"`

	// TextAnchor: Text anchor indexing into the Document.text.
	TextAnchor *GoogleCloudDocumentaiV1beta1DocumentTextAnchor `json:"textAnchor,omitempty"`

	// TextDecoration: Text decoration. Follows CSS
	// standard.
	// <text-decoration-line> <text-decoration-color>
	// <text-decoration-style>
	// https://www.w3schools.com/cssref/pr_text_text-
	// decoration.asp
	TextDecoration string `json:"textDecoration,omitempty"`

	// TextStyle: Text style. Possible values are normal, italic, and
	// oblique.
	// https://www.w3schools.com/cssref/pr_font_font-style.asp
	TextStyle string `json:"textStyle,omitempty"`

	// ForceSendFields is a list of field names (e.g. "BackgroundColor") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "BackgroundColor") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1DocumentStyle) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1DocumentStyle
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta1DocumentStyleFontSize: Font size with
// unit.
type GoogleCloudDocumentaiV1beta1DocumentStyleFontSize struct {
	// Size: Font size for the text.
	Size float64 `json:"size,omitempty"`

	// Unit: Unit for the font size. Follows CSS naming (in, px, pt, etc.).
	Unit string `json:"unit,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Size") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Size") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1DocumentStyleFontSize) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1DocumentStyleFontSize
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudDocumentaiV1beta1DocumentStyleFontSize) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudDocumentaiV1beta1DocumentStyleFontSize
	var s1 struct {
		Size gensupport.JSONFloat64 `json:"size"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.Size = float64(s1.Size)
	return nil
}

// GoogleCloudDocumentaiV1beta1DocumentTextAnchor: Text reference
// indexing into the Document.text.
type GoogleCloudDocumentaiV1beta1DocumentTextAnchor struct {
	// TextSegments: The text segments from the Document.text.
	TextSegments []*GoogleCloudDocumentaiV1beta1DocumentTextAnchorTextSegment `json:"textSegments,omitempty"`

	// ForceSendFields is a list of field names (e.g. "TextSegments") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "TextSegments") to include
	// in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. However, any field with
	// an empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1DocumentTextAnchor) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1DocumentTextAnchor
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta1DocumentTextAnchorTextSegment: A text
// segment in the Document.text. The indices may be out of bounds
// which indicate that the text extends into another document shard
// for
// large sharded documents. See ShardInfo.text_offset
type GoogleCloudDocumentaiV1beta1DocumentTextAnchorTextSegment struct {
	// EndIndex: TextSegment half open end UTF-8 char index in
	// the
	// Document.text.
	EndIndex int64 `json:"endIndex,omitempty,string"`

	// StartIndex: TextSegment start UTF-8 char index in the Document.text.
	StartIndex int64 `json:"startIndex,omitempty,string"`

	// ForceSendFields is a list of field names (e.g. "EndIndex") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "EndIndex") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1DocumentTextAnchorTextSegment) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1DocumentTextAnchorTextSegment
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta1DocumentTranslation: A translation of the
// text segment.
type GoogleCloudDocumentaiV1beta1DocumentTranslation struct {
	// LanguageCode: The BCP-47 language code, such as "en-US" or "sr-Latn".
	// For more
	// information,
	// see
	// http://www.unicode.org/reports/tr35/#Unicode_locale_identifier.
	LanguageCode string `json:"languageCode,omitempty"`

	// TextAnchor: Provenance of the translation.
	// Text anchor indexing into the Document.text.
	TextAnchor *GoogleCloudDocumentaiV1beta1DocumentTextAnchor `json:"textAnchor,omitempty"`

	// TranslatedText: Text translated into the target language.
	TranslatedText string `json:"translatedText,omitempty"`

	// ForceSendFields is a list of field names (e.g. "LanguageCode") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "LanguageCode") to include
	// in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. However, any field with
	// an empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1DocumentTranslation) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1DocumentTranslation
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta1GcsDestination: The Google Cloud Storage
// location where the output file will be written to.
type GoogleCloudDocumentaiV1beta1GcsDestination struct {
	Uri string `json:"uri,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Uri") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Uri") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1GcsDestination) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1GcsDestination
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta1GcsSource: The Google Cloud Storage
// location where the input file will be read from.
type GoogleCloudDocumentaiV1beta1GcsSource struct {
	Uri string `json:"uri,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Uri") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Uri") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1GcsSource) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1GcsSource
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta1InputConfig: The desired input location
// and metadata.
type GoogleCloudDocumentaiV1beta1InputConfig struct {
	// GcsSource: The Google Cloud Storage location to read the input from.
	// This must be a
	// single file.
	GcsSource *GoogleCloudDocumentaiV1beta1GcsSource `json:"gcsSource,omitempty"`

	// MimeType: Required. Mimetype of the input. Current supported
	// mimetypes are application/pdf,
	// image/tiff, and image/gif.
	// In addition, application/json type is supported for requests
	// with
	// ProcessDocumentRequest.automl_params field set. The JSON file needs
	// to
	// be in Document format.
	MimeType string `json:"mimeType,omitempty"`

	// ForceSendFields is a list of field names (e.g. "GcsSource") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "GcsSource") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1InputConfig) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1InputConfig
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta1NormalizedVertex: A vertex represents a
// 2D point in the image.
// NOTE: the normalized vertex coordinates are relative to the original
// image
// and range from 0 to 1.
type GoogleCloudDocumentaiV1beta1NormalizedVertex struct {
	// X: X coordinate.
	X float64 `json:"x,omitempty"`

	// Y: Y coordinate.
	Y float64 `json:"y,omitempty"`

	// ForceSendFields is a list of field names (e.g. "X") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "X") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1NormalizedVertex) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1NormalizedVertex
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudDocumentaiV1beta1NormalizedVertex) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudDocumentaiV1beta1NormalizedVertex
	var s1 struct {
		X gensupport.JSONFloat64 `json:"x"`
		Y gensupport.JSONFloat64 `json:"y"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.X = float64(s1.X)
	s.Y = float64(s1.Y)
	return nil
}

// GoogleCloudDocumentaiV1beta1OperationMetadata: Contains metadata for
// the BatchProcessDocuments operation.
type GoogleCloudDocumentaiV1beta1OperationMetadata struct {
	// CreateTime: The creation time of the operation.
	CreateTime string `json:"createTime,omitempty"`

	// State: The state of the current batch processing.
	//
	// Possible values:
	//   "STATE_UNSPECIFIED" - The default value. This value is used if the
	// state is omitted.
	//   "ACCEPTED" - Request is received.
	//   "WAITING" - Request operation is waiting for scheduling.
	//   "RUNNING" - Request is being processed.
	//   "SUCCEEDED" - The batch processing completed successfully.
	//   "CANCELLED" - The batch processing was cancelled.
	//   "FAILED" - The batch processing has failed.
	State string `json:"state,omitempty"`

	// StateMessage: A message providing more details about the current
	// state of processing.
	StateMessage string `json:"stateMessage,omitempty"`

	// UpdateTime: The last update time of the operation.
	UpdateTime string `json:"updateTime,omitempty"`

	// ForceSendFields is a list of field names (e.g. "CreateTime") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "CreateTime") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1OperationMetadata) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1OperationMetadata
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta1OutputConfig: The desired output location
// and metadata.
type GoogleCloudDocumentaiV1beta1OutputConfig struct {
	// GcsDestination: The Google Cloud Storage location to write the output
	// to.
	GcsDestination *GoogleCloudDocumentaiV1beta1GcsDestination `json:"gcsDestination,omitempty"`

	// PagesPerShard: The max number of pages to include into each output
	// Document shard JSON on
	// Google Cloud Storage.
	//
	// The valid range is [1, 100]. If not specified, the default value is
	// 20.
	//
	// For example, for one pdf file with 100 pages, 100 parsed pages will
	// be
	// produced. If `pages_per_shard` = 20, then 5 Document shard JSON files
	// each
	// containing 20 parsed pages will be written under the
	// prefix
	// OutputConfig.gcs_destination.uri and suffix pages-x-to-y.json where
	// x and y are 1-indexed page numbers.
	//
	// Example GCS outputs with 157 pages and pages_per_shard =
	// 50:
	//
	// <prefix>pages-001-to-050.json
	// <prefix>pages-051-to-100.json
	// <pref
	// ix>pages-101-to-150.json
	// <prefix>pages-151-to-157.json
	PagesPerShard int64 `json:"pagesPerShard,omitempty"`

	// ForceSendFields is a list of field names (e.g. "GcsDestination") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "GcsDestination") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1OutputConfig) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1OutputConfig
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta1ProcessDocumentResponse: Response to a
// single document processing request.
type GoogleCloudDocumentaiV1beta1ProcessDocumentResponse struct {
	// InputConfig: Information about the input file. This is the same as
	// the corresponding
	// input config in the request.
	InputConfig *GoogleCloudDocumentaiV1beta1InputConfig `json:"inputConfig,omitempty"`

	// OutputConfig: The output location of the parsed responses. The
	// responses are written to
	// this location as JSON-serialized `Document` objects.
	OutputConfig *GoogleCloudDocumentaiV1beta1OutputConfig `json:"outputConfig,omitempty"`

	// ForceSendFields is a list of field names (e.g. "InputConfig") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "InputConfig") to include
	// in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. However, any field with
	// an empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1ProcessDocumentResponse) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1ProcessDocumentResponse
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta1Vertex: A vertex represents a 2D point in
// the image.
// NOTE: the vertex coordinates are in the same scale as the original
// image.
type GoogleCloudDocumentaiV1beta1Vertex struct {
	// X: X coordinate.
	X int64 `json:"x,omitempty"`

	// Y: Y coordinate.
	Y int64 `json:"y,omitempty"`

	// ForceSendFields is a list of field names (e.g. "X") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "X") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta1Vertex) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta1Vertex
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2AutoMlParams: Parameters to control
// AutoML model prediction behavior.
type GoogleCloudDocumentaiV1beta2AutoMlParams struct {
	// Model: Resource name of the AutoML model.
	//
	// Format:
	// `projects/{project-id}/locations/{location-id}/models/{model-id}`.
	Model string `json:"model,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Model") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Model") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2AutoMlParams) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2AutoMlParams
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2BatchProcessDocumentsRequest: Request to
// batch process documents as an asynchronous operation. The output
// is written to Cloud Storage as JSON in the [Document] format.
type GoogleCloudDocumentaiV1beta2BatchProcessDocumentsRequest struct {
	// Requests: Required. Individual requests for each document.
	Requests []*GoogleCloudDocumentaiV1beta2ProcessDocumentRequest `json:"requests,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Requests") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Requests") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2BatchProcessDocumentsRequest) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2BatchProcessDocumentsRequest
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2BatchProcessDocumentsResponse: Response
// to an batch document processing request. This is returned in
// the LRO Operation after the operation is complete.
type GoogleCloudDocumentaiV1beta2BatchProcessDocumentsResponse struct {
	// Responses: Responses for each individual document.
	Responses []*GoogleCloudDocumentaiV1beta2ProcessDocumentResponse `json:"responses,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Responses") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Responses") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2BatchProcessDocumentsResponse) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2BatchProcessDocumentsResponse
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2BoundingPoly: A bounding polygon for the
// detected image annotation.
type GoogleCloudDocumentaiV1beta2BoundingPoly struct {
	// NormalizedVertices: The bounding polygon normalized vertices.
	NormalizedVertices []*GoogleCloudDocumentaiV1beta2NormalizedVertex `json:"normalizedVertices,omitempty"`

	// Vertices: The bounding polygon vertices.
	Vertices []*GoogleCloudDocumentaiV1beta2Vertex `json:"vertices,omitempty"`

	// ForceSendFields is a list of field names (e.g. "NormalizedVertices")
	// to unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "NormalizedVertices") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2BoundingPoly) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2BoundingPoly
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2Document: Document represents the
// canonical document resource in Document Understanding
// AI.
// It is an interchange format that provides insights into documents and
// allows
// for collaboration between users and Document Understanding AI to
// iterate and
// optimize for quality.
type GoogleCloudDocumentaiV1beta2Document struct {
	// Content: Inline document content, represented as a stream of
	// bytes.
	// Note: As with all `bytes` fields, protobuffers use a pure
	// binary
	// representation, whereas JSON representations use base64.
	Content string `json:"content,omitempty"`

	// Entities: A list of entities detected on Document.text. For document
	// shards,
	// entities in this list may cross shard boundaries.
	Entities []*GoogleCloudDocumentaiV1beta2DocumentEntity `json:"entities,omitempty"`

	// EntityRelations: Relationship among Document.entities.
	EntityRelations []*GoogleCloudDocumentaiV1beta2DocumentEntityRelation `json:"entityRelations,omitempty"`

	// Error: Any error that occurred while processing this document.
	Error *GoogleRpcStatus `json:"error,omitempty"`

	// Labels: Labels for this document.
	Labels []*GoogleCloudDocumentaiV1beta2DocumentLabel `json:"labels,omitempty"`

	// MimeType: An IANA published MIME type (also referred to as media
	// type). For more
	// information,
	// see
	// https://www.iana.org/assignments/media-types/media-types.xhtml.
	MimeType string `json:"mimeType,omitempty"`

	// Pages: Visual page layout for the Document.
	Pages []*GoogleCloudDocumentaiV1beta2DocumentPage `json:"pages,omitempty"`

	// ShardInfo: Information about the sharding if this document is sharded
	// part of a larger
	// document. If the document is not sharded, this message is not
	// specified.
	ShardInfo *GoogleCloudDocumentaiV1beta2DocumentShardInfo `json:"shardInfo,omitempty"`

	// Text: UTF-8 encoded text in reading order from the document.
	Text string `json:"text,omitempty"`

	// TextStyles: Styles for the Document.text.
	TextStyles []*GoogleCloudDocumentaiV1beta2DocumentStyle `json:"textStyles,omitempty"`

	// Translations: A list of translations on Document.text. For document
	// shards,
	// translations in this list may cross shard boundaries.
	Translations []*GoogleCloudDocumentaiV1beta2DocumentTranslation `json:"translations,omitempty"`

	// Uri: Currently supports Google Cloud Storage URI of the form
	//    `gs://bucket_name/object_name`. Object versioning is not
	// supported.
	//    See [Google Cloud Storage Request
	//    URIs](https://cloud.google.com/storage/docs/reference-uris) for
	// more
	//    info.
	Uri string `json:"uri,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the
	// server.
	googleapi.ServerResponse `json:"-"`

	// ForceSendFields is a list of field names (e.g. "Content") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Content") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2Document) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2Document
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2DocumentEntity: A phrase in the text that
// is a known entity type, such as a person, an
// organization, or location.
type GoogleCloudDocumentaiV1beta2DocumentEntity struct {
	// Confidence: Optional. Confidence of detected Schema entity. Range [0,
	// 1].
	Confidence float64 `json:"confidence,omitempty"`

	// MentionId: Deprecated.  Use `id` field instead.
	MentionId string `json:"mentionId,omitempty"`

	// MentionText: Text value in the document e.g. `1600 Amphitheatre
	// Pkwy`.
	MentionText string `json:"mentionText,omitempty"`

	// TextAnchor: Provenance of the entity.
	// Text anchor indexing into the Document.text.
	TextAnchor *GoogleCloudDocumentaiV1beta2DocumentTextAnchor `json:"textAnchor,omitempty"`

	// Type: Entity type from a schema e.g. `Address`.
	Type string `json:"type,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Confidence") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Confidence") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2DocumentEntity) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2DocumentEntity
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudDocumentaiV1beta2DocumentEntity) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudDocumentaiV1beta2DocumentEntity
	var s1 struct {
		Confidence gensupport.JSONFloat64 `json:"confidence"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.Confidence = float64(s1.Confidence)
	return nil
}

// GoogleCloudDocumentaiV1beta2DocumentEntityRelation: Relationship
// between Entities.
type GoogleCloudDocumentaiV1beta2DocumentEntityRelation struct {
	// ObjectId: Object entity id.
	ObjectId string `json:"objectId,omitempty"`

	// Relation: Relationship description.
	Relation string `json:"relation,omitempty"`

	// SubjectId: Subject entity id.
	SubjectId string `json:"subjectId,omitempty"`

	// ForceSendFields is a list of field names (e.g. "ObjectId") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "ObjectId") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2DocumentEntityRelation) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2DocumentEntityRelation
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2DocumentLabel: Label attaches schema
// information and/or other metadata to segments within
// a Document. Multiple Labels on a single field can denote
// either
// different labels, different instances of the same label created
// at
// different times, or some combination of both.
type GoogleCloudDocumentaiV1beta2DocumentLabel struct {
	// AutomlModel: Label is generated AutoML model. This field stores the
	// full resource
	// name of the AutoML
	// model.
	//
	// Format:
	// `projects/{project-id}/locations/{location-id}/models/
	// {model-id}`
	AutomlModel string `json:"automlModel,omitempty"`

	// Confidence: Confidence score between 0 and 1 for label assignment.
	Confidence float64 `json:"confidence,omitempty"`

	// Name: Name of the label.
	//
	// When the label is generated from AutoML Text Classification model,
	// this
	// field represents the name of the category.
	Name string `json:"name,omitempty"`

	// ForceSendFields is a list of field names (e.g. "AutomlModel") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "AutomlModel") to include
	// in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. However, any field with
	// an empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2DocumentLabel) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2DocumentLabel
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudDocumentaiV1beta2DocumentLabel) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudDocumentaiV1beta2DocumentLabel
	var s1 struct {
		Confidence gensupport.JSONFloat64 `json:"confidence"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.Confidence = float64(s1.Confidence)
	return nil
}

// GoogleCloudDocumentaiV1beta2DocumentPage: A page in a Document.
type GoogleCloudDocumentaiV1beta2DocumentPage struct {
	// Blocks: A list of visually detected text blocks on the page.
	// A block has a set of lines (collected into paragraphs) that have a
	// common
	// line-spacing and orientation.
	Blocks []*GoogleCloudDocumentaiV1beta2DocumentPageBlock `json:"blocks,omitempty"`

	// DetectedLanguages: A list of detected languages together with
	// confidence.
	DetectedLanguages []*GoogleCloudDocumentaiV1beta2DocumentPageDetectedLanguage `json:"detectedLanguages,omitempty"`

	// Dimension: Physical dimension of the page.
	Dimension *GoogleCloudDocumentaiV1beta2DocumentPageDimension `json:"dimension,omitempty"`

	// FormFields: A list of visually detected form fields on the page.
	FormFields []*GoogleCloudDocumentaiV1beta2DocumentPageFormField `json:"formFields,omitempty"`

	// Layout: Layout for the page.
	Layout *GoogleCloudDocumentaiV1beta2DocumentPageLayout `json:"layout,omitempty"`

	// Lines: A list of visually detected text lines on the page.
	// A collection of tokens that a human would perceive as a line.
	Lines []*GoogleCloudDocumentaiV1beta2DocumentPageLine `json:"lines,omitempty"`

	// PageNumber: 1-based index for current Page in a parent
	// Document.
	// Useful when a page is taken out of a Document for
	// individual
	// processing.
	PageNumber int64 `json:"pageNumber,omitempty"`

	// Paragraphs: A list of visually detected text paragraphs on the
	// page.
	// A collection of lines that a human would perceive as a paragraph.
	Paragraphs []*GoogleCloudDocumentaiV1beta2DocumentPageParagraph `json:"paragraphs,omitempty"`

	// Tables: A list of visually detected tables on the page.
	Tables []*GoogleCloudDocumentaiV1beta2DocumentPageTable `json:"tables,omitempty"`

	// Tokens: A list of visually detected tokens on the page.
	Tokens []*GoogleCloudDocumentaiV1beta2DocumentPageToken `json:"tokens,omitempty"`

	// VisualElements: A list of detected non-text visual elements e.g.
	// checkbox,
	// signature etc. on the page.
	VisualElements []*GoogleCloudDocumentaiV1beta2DocumentPageVisualElement `json:"visualElements,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Blocks") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Blocks") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2DocumentPage) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2DocumentPage
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2DocumentPageBlock: A block has a set of
// lines (collected into paragraphs) that have a
// common line-spacing and orientation.
type GoogleCloudDocumentaiV1beta2DocumentPageBlock struct {
	// DetectedLanguages: A list of detected languages together with
	// confidence.
	DetectedLanguages []*GoogleCloudDocumentaiV1beta2DocumentPageDetectedLanguage `json:"detectedLanguages,omitempty"`

	// Layout: Layout for Block.
	Layout *GoogleCloudDocumentaiV1beta2DocumentPageLayout `json:"layout,omitempty"`

	// ForceSendFields is a list of field names (e.g. "DetectedLanguages")
	// to unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "DetectedLanguages") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2DocumentPageBlock) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2DocumentPageBlock
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2DocumentPageDetectedLanguage: Detected
// language for a structural component.
type GoogleCloudDocumentaiV1beta2DocumentPageDetectedLanguage struct {
	// Confidence: Confidence of detected language. Range [0, 1].
	Confidence float64 `json:"confidence,omitempty"`

	// LanguageCode: The BCP-47 language code, such as "en-US" or "sr-Latn".
	// For more
	// information,
	// see
	// http://www.unicode.org/reports/tr35/#Unicode_locale_identifier.
	LanguageCode string `json:"languageCode,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Confidence") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Confidence") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2DocumentPageDetectedLanguage) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2DocumentPageDetectedLanguage
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudDocumentaiV1beta2DocumentPageDetectedLanguage) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudDocumentaiV1beta2DocumentPageDetectedLanguage
	var s1 struct {
		Confidence gensupport.JSONFloat64 `json:"confidence"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.Confidence = float64(s1.Confidence)
	return nil
}

// GoogleCloudDocumentaiV1beta2DocumentPageDimension: Dimension for the
// page.
type GoogleCloudDocumentaiV1beta2DocumentPageDimension struct {
	// Height: Page height.
	Height float64 `json:"height,omitempty"`

	// Unit: Dimension unit.
	Unit string `json:"unit,omitempty"`

	// Width: Page width.
	Width float64 `json:"width,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Height") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Height") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2DocumentPageDimension) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2DocumentPageDimension
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudDocumentaiV1beta2DocumentPageDimension) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudDocumentaiV1beta2DocumentPageDimension
	var s1 struct {
		Height gensupport.JSONFloat64 `json:"height"`
		Width  gensupport.JSONFloat64 `json:"width"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.Height = float64(s1.Height)
	s.Width = float64(s1.Width)
	return nil
}

// GoogleCloudDocumentaiV1beta2DocumentPageFormField: A form field
// detected on the page.
type GoogleCloudDocumentaiV1beta2DocumentPageFormField struct {
	// FieldName: Layout for the FormField name. e.g. `Address`,
	// `Email`,
	// `Grand total`, `Phone number`, etc.
	FieldName *GoogleCloudDocumentaiV1beta2DocumentPageLayout `json:"fieldName,omitempty"`

	// FieldValue: Layout for the FormField value.
	FieldValue *GoogleCloudDocumentaiV1beta2DocumentPageLayout `json:"fieldValue,omitempty"`

	// NameDetectedLanguages: A list of detected languages for name together
	// with confidence.
	NameDetectedLanguages []*GoogleCloudDocumentaiV1beta2DocumentPageDetectedLanguage `json:"nameDetectedLanguages,omitempty"`

	// ValueDetectedLanguages: A list of detected languages for value
	// together with confidence.
	ValueDetectedLanguages []*GoogleCloudDocumentaiV1beta2DocumentPageDetectedLanguage `json:"valueDetectedLanguages,omitempty"`

	// ValueType: If the value is non-textual, this field represents the
	// type. Current
	// valid values are:
	// - blank (this indicates the field_value is normal text)
	// - "unfilled_checkbox"
	// - "filled_checkbox"
	ValueType string `json:"valueType,omitempty"`

	// ForceSendFields is a list of field names (e.g. "FieldName") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "FieldName") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2DocumentPageFormField) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2DocumentPageFormField
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2DocumentPageLayout: Visual element
// describing a layout unit on a page.
type GoogleCloudDocumentaiV1beta2DocumentPageLayout struct {
	// BoundingPoly: The bounding polygon for the Layout.
	BoundingPoly *GoogleCloudDocumentaiV1beta2BoundingPoly `json:"boundingPoly,omitempty"`

	// Confidence: Confidence of the current Layout within context of the
	// object this
	// layout is for. e.g. confidence can be for a single token, a table,
	// a visual element, etc. depending on context. Range [0, 1].
	Confidence float64 `json:"confidence,omitempty"`

	// Orientation: Detected orientation for the Layout.
	//
	// Possible values:
	//   "ORIENTATION_UNSPECIFIED" - Unspecified orientation.
	//   "PAGE_UP" - Orientation is aligned with page up.
	//   "PAGE_RIGHT" - Orientation is aligned with page right.
	// Turn the head 90 degrees clockwise from upright to read.
	//   "PAGE_DOWN" - Orientation is aligned with page down.
	// Turn the head 180 degrees from upright to read.
	//   "PAGE_LEFT" - Orientation is aligned with page left.
	// Turn the head 90 degrees counterclockwise from upright to read.
	Orientation string `json:"orientation,omitempty"`

	// TextAnchor: Text anchor indexing into the Document.text.
	TextAnchor *GoogleCloudDocumentaiV1beta2DocumentTextAnchor `json:"textAnchor,omitempty"`

	// ForceSendFields is a list of field names (e.g. "BoundingPoly") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "BoundingPoly") to include
	// in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. However, any field with
	// an empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2DocumentPageLayout) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2DocumentPageLayout
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudDocumentaiV1beta2DocumentPageLayout) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudDocumentaiV1beta2DocumentPageLayout
	var s1 struct {
		Confidence gensupport.JSONFloat64 `json:"confidence"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.Confidence = float64(s1.Confidence)
	return nil
}

// GoogleCloudDocumentaiV1beta2DocumentPageLine: A collection of tokens
// that a human would perceive as a line.
// Does not cross column boundaries, can be horizontal, vertical, etc.
type GoogleCloudDocumentaiV1beta2DocumentPageLine struct {
	// DetectedLanguages: A list of detected languages together with
	// confidence.
	DetectedLanguages []*GoogleCloudDocumentaiV1beta2DocumentPageDetectedLanguage `json:"detectedLanguages,omitempty"`

	// Layout: Layout for Line.
	Layout *GoogleCloudDocumentaiV1beta2DocumentPageLayout `json:"layout,omitempty"`

	// ForceSendFields is a list of field names (e.g. "DetectedLanguages")
	// to unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "DetectedLanguages") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2DocumentPageLine) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2DocumentPageLine
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2DocumentPageParagraph: A collection of
// lines that a human would perceive as a paragraph.
type GoogleCloudDocumentaiV1beta2DocumentPageParagraph struct {
	// DetectedLanguages: A list of detected languages together with
	// confidence.
	DetectedLanguages []*GoogleCloudDocumentaiV1beta2DocumentPageDetectedLanguage `json:"detectedLanguages,omitempty"`

	// Layout: Layout for Paragraph.
	Layout *GoogleCloudDocumentaiV1beta2DocumentPageLayout `json:"layout,omitempty"`

	// ForceSendFields is a list of field names (e.g. "DetectedLanguages")
	// to unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "DetectedLanguages") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2DocumentPageParagraph) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2DocumentPageParagraph
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2DocumentPageTable: A table representation
// similar to HTML table structure.
type GoogleCloudDocumentaiV1beta2DocumentPageTable struct {
	// BodyRows: Body rows of the table.
	BodyRows []*GoogleCloudDocumentaiV1beta2DocumentPageTableTableRow `json:"bodyRows,omitempty"`

	// DetectedLanguages: A list of detected languages together with
	// confidence.
	DetectedLanguages []*GoogleCloudDocumentaiV1beta2DocumentPageDetectedLanguage `json:"detectedLanguages,omitempty"`

	// HeaderRows: Header rows of the table.
	HeaderRows []*GoogleCloudDocumentaiV1beta2DocumentPageTableTableRow `json:"headerRows,omitempty"`

	// Layout: Layout for Table.
	Layout *GoogleCloudDocumentaiV1beta2DocumentPageLayout `json:"layout,omitempty"`

	// ForceSendFields is a list of field names (e.g. "BodyRows") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "BodyRows") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2DocumentPageTable) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2DocumentPageTable
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2DocumentPageTableTableCell: A cell
// representation inside the table.
type GoogleCloudDocumentaiV1beta2DocumentPageTableTableCell struct {
	// ColSpan: How many columns this cell spans.
	ColSpan int64 `json:"colSpan,omitempty"`

	// DetectedLanguages: A list of detected languages together with
	// confidence.
	DetectedLanguages []*GoogleCloudDocumentaiV1beta2DocumentPageDetectedLanguage `json:"detectedLanguages,omitempty"`

	// Layout: Layout for TableCell.
	Layout *GoogleCloudDocumentaiV1beta2DocumentPageLayout `json:"layout,omitempty"`

	// RowSpan: How many rows this cell spans.
	RowSpan int64 `json:"rowSpan,omitempty"`

	// ForceSendFields is a list of field names (e.g. "ColSpan") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "ColSpan") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2DocumentPageTableTableCell) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2DocumentPageTableTableCell
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2DocumentPageTableTableRow: A row of table
// cells.
type GoogleCloudDocumentaiV1beta2DocumentPageTableTableRow struct {
	// Cells: Cells that make up this row.
	Cells []*GoogleCloudDocumentaiV1beta2DocumentPageTableTableCell `json:"cells,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Cells") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Cells") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2DocumentPageTableTableRow) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2DocumentPageTableTableRow
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2DocumentPageToken: A detected token.
type GoogleCloudDocumentaiV1beta2DocumentPageToken struct {
	// DetectedBreak: Detected break at the end of a Token.
	DetectedBreak *GoogleCloudDocumentaiV1beta2DocumentPageTokenDetectedBreak `json:"detectedBreak,omitempty"`

	// DetectedLanguages: A list of detected languages together with
	// confidence.
	DetectedLanguages []*GoogleCloudDocumentaiV1beta2DocumentPageDetectedLanguage `json:"detectedLanguages,omitempty"`

	// Layout: Layout for Token.
	Layout *GoogleCloudDocumentaiV1beta2DocumentPageLayout `json:"layout,omitempty"`

	// ForceSendFields is a list of field names (e.g. "DetectedBreak") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "DetectedBreak") to include
	// in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. However, any field with
	// an empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2DocumentPageToken) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2DocumentPageToken
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2DocumentPageTokenDetectedBreak: Detected
// break at the end of a Token.
type GoogleCloudDocumentaiV1beta2DocumentPageTokenDetectedBreak struct {
	// Type: Detected break type.
	//
	// Possible values:
	//   "TYPE_UNSPECIFIED" - Unspecified break type.
	//   "SPACE" - A single whitespace.
	//   "WIDE_SPACE" - A wider whitespace.
	//   "HYPHEN" - A hyphen that indicates that a token has been split
	// across lines.
	Type string `json:"type,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Type") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Type") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2DocumentPageTokenDetectedBreak) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2DocumentPageTokenDetectedBreak
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2DocumentPageVisualElement: Detected
// non-text visual elements e.g. checkbox, signature etc. on the
// page.
type GoogleCloudDocumentaiV1beta2DocumentPageVisualElement struct {
	// DetectedLanguages: A list of detected languages together with
	// confidence.
	DetectedLanguages []*GoogleCloudDocumentaiV1beta2DocumentPageDetectedLanguage `json:"detectedLanguages,omitempty"`

	// Layout: Layout for VisualElement.
	Layout *GoogleCloudDocumentaiV1beta2DocumentPageLayout `json:"layout,omitempty"`

	// Type: Type of the VisualElement.
	Type string `json:"type,omitempty"`

	// ForceSendFields is a list of field names (e.g. "DetectedLanguages")
	// to unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "DetectedLanguages") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2DocumentPageVisualElement) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2DocumentPageVisualElement
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2DocumentShardInfo: For a large document,
// sharding may be performed to produce several
// document shards. Each document shard contains this field to detail
// which
// shard it is.
type GoogleCloudDocumentaiV1beta2DocumentShardInfo struct {
	// ShardCount: Total number of shards.
	ShardCount int64 `json:"shardCount,omitempty,string"`

	// ShardIndex: The 0-based index of this shard.
	ShardIndex int64 `json:"shardIndex,omitempty,string"`

	// TextOffset: The index of the first character in Document.text in the
	// overall
	// document global text.
	TextOffset int64 `json:"textOffset,omitempty,string"`

	// ForceSendFields is a list of field names (e.g. "ShardCount") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "ShardCount") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2DocumentShardInfo) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2DocumentShardInfo
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2DocumentStyle: Annotation for common text
// style attributes. This adheres to CSS
// conventions as much as possible.
type GoogleCloudDocumentaiV1beta2DocumentStyle struct {
	// BackgroundColor: Text background color.
	BackgroundColor *GoogleTypeColor `json:"backgroundColor,omitempty"`

	// Color: Text color.
	Color *GoogleTypeColor `json:"color,omitempty"`

	// FontSize: Font size.
	FontSize *GoogleCloudDocumentaiV1beta2DocumentStyleFontSize `json:"fontSize,omitempty"`

	// FontWeight: Font weight. Possible values are normal, bold, bolder,
	// and lighter.
	// https://www.w3schools.com/cssref/pr_font_weight.asp
	FontWeight string `json:"fontWeight,omitempty"`

	// TextAnchor: Text anchor indexing into the Document.text.
	TextAnchor *GoogleCloudDocumentaiV1beta2DocumentTextAnchor `json:"textAnchor,omitempty"`

	// TextDecoration: Text decoration. Follows CSS
	// standard.
	// <text-decoration-line> <text-decoration-color>
	// <text-decoration-style>
	// https://www.w3schools.com/cssref/pr_text_text-
	// decoration.asp
	TextDecoration string `json:"textDecoration,omitempty"`

	// TextStyle: Text style. Possible values are normal, italic, and
	// oblique.
	// https://www.w3schools.com/cssref/pr_font_font-style.asp
	TextStyle string `json:"textStyle,omitempty"`

	// ForceSendFields is a list of field names (e.g. "BackgroundColor") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "BackgroundColor") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2DocumentStyle) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2DocumentStyle
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2DocumentStyleFontSize: Font size with
// unit.
type GoogleCloudDocumentaiV1beta2DocumentStyleFontSize struct {
	// Size: Font size for the text.
	Size float64 `json:"size,omitempty"`

	// Unit: Unit for the font size. Follows CSS naming (in, px, pt, etc.).
	Unit string `json:"unit,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Size") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Size") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2DocumentStyleFontSize) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2DocumentStyleFontSize
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudDocumentaiV1beta2DocumentStyleFontSize) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudDocumentaiV1beta2DocumentStyleFontSize
	var s1 struct {
		Size gensupport.JSONFloat64 `json:"size"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.Size = float64(s1.Size)
	return nil
}

// GoogleCloudDocumentaiV1beta2DocumentTextAnchor: Text reference
// indexing into the Document.text.
type GoogleCloudDocumentaiV1beta2DocumentTextAnchor struct {
	// TextSegments: The text segments from the Document.text.
	TextSegments []*GoogleCloudDocumentaiV1beta2DocumentTextAnchorTextSegment `json:"textSegments,omitempty"`

	// ForceSendFields is a list of field names (e.g. "TextSegments") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "TextSegments") to include
	// in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. However, any field with
	// an empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2DocumentTextAnchor) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2DocumentTextAnchor
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2DocumentTextAnchorTextSegment: A text
// segment in the Document.text. The indices may be out of bounds
// which indicate that the text extends into another document shard
// for
// large sharded documents. See ShardInfo.text_offset
type GoogleCloudDocumentaiV1beta2DocumentTextAnchorTextSegment struct {
	// EndIndex: TextSegment half open end UTF-8 char index in
	// the
	// Document.text.
	EndIndex int64 `json:"endIndex,omitempty,string"`

	// StartIndex: TextSegment start UTF-8 char index in the Document.text.
	StartIndex int64 `json:"startIndex,omitempty,string"`

	// ForceSendFields is a list of field names (e.g. "EndIndex") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "EndIndex") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2DocumentTextAnchorTextSegment) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2DocumentTextAnchorTextSegment
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2DocumentTranslation: A translation of the
// text segment.
type GoogleCloudDocumentaiV1beta2DocumentTranslation struct {
	// LanguageCode: The BCP-47 language code, such as "en-US" or "sr-Latn".
	// For more
	// information,
	// see
	// http://www.unicode.org/reports/tr35/#Unicode_locale_identifier.
	LanguageCode string `json:"languageCode,omitempty"`

	// TextAnchor: Provenance of the translation.
	// Text anchor indexing into the Document.text.
	TextAnchor *GoogleCloudDocumentaiV1beta2DocumentTextAnchor `json:"textAnchor,omitempty"`

	// TranslatedText: Text translated into the target language.
	TranslatedText string `json:"translatedText,omitempty"`

	// ForceSendFields is a list of field names (e.g. "LanguageCode") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "LanguageCode") to include
	// in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. However, any field with
	// an empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2DocumentTranslation) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2DocumentTranslation
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2EntityExtractionParams: Parameters to
// control entity extraction behavior.
type GoogleCloudDocumentaiV1beta2EntityExtractionParams struct {
	// Enabled: Whether to enable entity extraction.
	Enabled bool `json:"enabled,omitempty"`

	// ModelVersion: Model version of the entity extraction. Default
	// is
	// "builtin/stable". Specify "builtin/latest" for the latest model.
	ModelVersion string `json:"modelVersion,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Enabled") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Enabled") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2EntityExtractionParams) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2EntityExtractionParams
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2FormExtractionParams: Parameters to
// control form extraction behavior.
type GoogleCloudDocumentaiV1beta2FormExtractionParams struct {
	// Enabled: Whether to enable form extraction.
	Enabled bool `json:"enabled,omitempty"`

	// KeyValuePairHints: Reserved for future use.
	KeyValuePairHints []*GoogleCloudDocumentaiV1beta2KeyValuePairHint `json:"keyValuePairHints,omitempty"`

	// ModelVersion: Model version of the form extraction system. Default
	// is
	// "builtin/stable". Specify "builtin/latest" for the latest model.
	// For custom form models, specify: “custom/{model_name}". Model
	// name
	// format is "bucket_name/path/to/modeldir" corresponding
	// to
	// "gs://bucket_name/path/to/modeldir" where annotated examples are
	// stored.
	ModelVersion string `json:"modelVersion,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Enabled") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Enabled") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2FormExtractionParams) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2FormExtractionParams
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2GcsDestination: The Google Cloud Storage
// location where the output file will be written to.
type GoogleCloudDocumentaiV1beta2GcsDestination struct {
	Uri string `json:"uri,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Uri") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Uri") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2GcsDestination) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2GcsDestination
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2GcsSource: The Google Cloud Storage
// location where the input file will be read from.
type GoogleCloudDocumentaiV1beta2GcsSource struct {
	Uri string `json:"uri,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Uri") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Uri") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2GcsSource) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2GcsSource
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2InputConfig: The desired input location
// and metadata.
type GoogleCloudDocumentaiV1beta2InputConfig struct {
	// Contents: Content in bytes, represented as a stream of bytes.
	// Note: As with all `bytes` fields, proto buffer messages use a pure
	// binary
	// representation, whereas JSON representations use base64.
	//
	// This field only works for synchronous ProcessDocument method.
	Contents string `json:"contents,omitempty"`

	// GcsSource: The Google Cloud Storage location to read the input from.
	// This must be a
	// single file.
	GcsSource *GoogleCloudDocumentaiV1beta2GcsSource `json:"gcsSource,omitempty"`

	// MimeType: Required. Mimetype of the input. Current supported
	// mimetypes are application/pdf,
	// image/tiff, and image/gif.
	// In addition, application/json type is supported for requests
	// with
	// ProcessDocumentRequest.automl_params field set. The JSON file needs
	// to
	// be in Document format.
	MimeType string `json:"mimeType,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Contents") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Contents") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2InputConfig) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2InputConfig
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2KeyValuePairHint: Reserved for future
// use.
type GoogleCloudDocumentaiV1beta2KeyValuePairHint struct {
	// Key: The key text for the hint.
	Key string `json:"key,omitempty"`

	// ValueTypes: Type of the value. This is case-insensitive, and could be
	// one of:
	// ADDRESS, LOCATION, ORGANIZATION, PERSON, PHONE_NUMBER,
	// ID, NUMBER, EMAIL, PRICE, TERMS, DATE, NAME. Types not in this list
	// will
	// be ignored.
	ValueTypes []string `json:"valueTypes,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Key") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Key") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2KeyValuePairHint) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2KeyValuePairHint
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2NormalizedVertex: A vertex represents a
// 2D point in the image.
// NOTE: the normalized vertex coordinates are relative to the original
// image
// and range from 0 to 1.
type GoogleCloudDocumentaiV1beta2NormalizedVertex struct {
	// X: X coordinate.
	X float64 `json:"x,omitempty"`

	// Y: Y coordinate.
	Y float64 `json:"y,omitempty"`

	// ForceSendFields is a list of field names (e.g. "X") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "X") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2NormalizedVertex) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2NormalizedVertex
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

func (s *GoogleCloudDocumentaiV1beta2NormalizedVertex) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleCloudDocumentaiV1beta2NormalizedVertex
	var s1 struct {
		X gensupport.JSONFloat64 `json:"x"`
		Y gensupport.JSONFloat64 `json:"y"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.X = float64(s1.X)
	s.Y = float64(s1.Y)
	return nil
}

// GoogleCloudDocumentaiV1beta2OcrParams: Parameters to control Optical
// Character Recognition (OCR) behavior.
type GoogleCloudDocumentaiV1beta2OcrParams struct {
	// LanguageHints: List of languages to use for OCR. In most cases, an
	// empty value
	// yields the best results since it enables automatic language
	// detection. For
	// languages based on the Latin alphabet, setting `language_hints` is
	// not
	// needed. In rare cases, when the language of the text in the image is
	// known,
	// setting a hint will help get better results (although it will be
	// a
	// significant hindrance if the hint is wrong). Document processing
	// returns an
	// error if one or more of the specified languages is not one of
	// the
	// supported languages.
	LanguageHints []string `json:"languageHints,omitempty"`

	// ForceSendFields is a list of field names (e.g. "LanguageHints") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "LanguageHints") to include
	// in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. However, any field with
	// an empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2OcrParams) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2OcrParams
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2OperationMetadata: Contains metadata for
// the BatchProcessDocuments operation.
type GoogleCloudDocumentaiV1beta2OperationMetadata struct {
	// CreateTime: The creation time of the operation.
	CreateTime string `json:"createTime,omitempty"`

	// State: The state of the current batch processing.
	//
	// Possible values:
	//   "STATE_UNSPECIFIED" - The default value. This value is used if the
	// state is omitted.
	//   "ACCEPTED" - Request is received.
	//   "WAITING" - Request operation is waiting for scheduling.
	//   "RUNNING" - Request is being processed.
	//   "SUCCEEDED" - The batch processing completed successfully.
	//   "CANCELLED" - The batch processing was cancelled.
	//   "FAILED" - The batch processing has failed.
	State string `json:"state,omitempty"`

	// StateMessage: A message providing more details about the current
	// state of processing.
	StateMessage string `json:"stateMessage,omitempty"`

	// UpdateTime: The last update time of the operation.
	UpdateTime string `json:"updateTime,omitempty"`

	// ForceSendFields is a list of field names (e.g. "CreateTime") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "CreateTime") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2OperationMetadata) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2OperationMetadata
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2OutputConfig: The desired output location
// and metadata.
type GoogleCloudDocumentaiV1beta2OutputConfig struct {
	// GcsDestination: The Google Cloud Storage location to write the output
	// to.
	GcsDestination *GoogleCloudDocumentaiV1beta2GcsDestination `json:"gcsDestination,omitempty"`

	// PagesPerShard: The max number of pages to include into each output
	// Document shard JSON on
	// Google Cloud Storage.
	//
	// The valid range is [1, 100]. If not specified, the default value is
	// 20.
	//
	// For example, for one pdf file with 100 pages, 100 parsed pages will
	// be
	// produced. If `pages_per_shard` = 20, then 5 Document shard JSON files
	// each
	// containing 20 parsed pages will be written under the
	// prefix
	// OutputConfig.gcs_destination.uri and suffix pages-x-to-y.json where
	// x and y are 1-indexed page numbers.
	//
	// Example GCS outputs with 157 pages and pages_per_shard =
	// 50:
	//
	// <prefix>pages-001-to-050.json
	// <prefix>pages-051-to-100.json
	// <pref
	// ix>pages-101-to-150.json
	// <prefix>pages-151-to-157.json
	PagesPerShard int64 `json:"pagesPerShard,omitempty"`

	// ForceSendFields is a list of field names (e.g. "GcsDestination") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "GcsDestination") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2OutputConfig) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2OutputConfig
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2ProcessDocumentRequest: Request to
// process one document.
type GoogleCloudDocumentaiV1beta2ProcessDocumentRequest struct {
	// AutomlParams: Controls AutoML model prediction behavior. AutoMlParams
	// cannot be used
	// together with other Params.
	AutomlParams *GoogleCloudDocumentaiV1beta2AutoMlParams `json:"automlParams,omitempty"`

	// DocumentType: Specifies a known document type for deeper structure
	// detection. Valid
	// values are currently "general" and "invoice". If not provided,
	// "general"\
	// is used as default. If any other value is given, the request is
	// rejected.
	DocumentType string `json:"documentType,omitempty"`

	// EntityExtractionParams: Controls entity extraction behavior. If not
	// specified, the system will
	// decide reasonable defaults.
	EntityExtractionParams *GoogleCloudDocumentaiV1beta2EntityExtractionParams `json:"entityExtractionParams,omitempty"`

	// FormExtractionParams: Controls form extraction behavior. If not
	// specified, the system will
	// decide reasonable defaults.
	FormExtractionParams *GoogleCloudDocumentaiV1beta2FormExtractionParams `json:"formExtractionParams,omitempty"`

	// InputConfig: Required. Information about the input file.
	InputConfig *GoogleCloudDocumentaiV1beta2InputConfig `json:"inputConfig,omitempty"`

	// OcrParams: Controls OCR behavior. If not specified, the system will
	// decide reasonable
	// defaults.
	OcrParams *GoogleCloudDocumentaiV1beta2OcrParams `json:"ocrParams,omitempty"`

	// OutputConfig: The desired output location. This field is only needed
	// in
	// BatchProcessDocumentsRequest.
	OutputConfig *GoogleCloudDocumentaiV1beta2OutputConfig `json:"outputConfig,omitempty"`

	// Parent: Target project and location to make a call.
	//
	// Format: `projects/{project-id}/locations/{location-id}`.
	//
	// If no location is specified, a region will be chosen
	// automatically.
	// This field is only populated when used in ProcessDocument method.
	Parent string `json:"parent,omitempty"`

	// TableExtractionParams: Controls table extraction behavior. If not
	// specified, the system will
	// decide reasonable defaults.
	TableExtractionParams *GoogleCloudDocumentaiV1beta2TableExtractionParams `json:"tableExtractionParams,omitempty"`

	// ForceSendFields is a list of field names (e.g. "AutomlParams") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "AutomlParams") to include
	// in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. However, any field with
	// an empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2ProcessDocumentRequest) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2ProcessDocumentRequest
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2ProcessDocumentResponse: Response to a
// single document processing request.
type GoogleCloudDocumentaiV1beta2ProcessDocumentResponse struct {
	// InputConfig: Information about the input file. This is the same as
	// the corresponding
	// input config in the request.
	InputConfig *GoogleCloudDocumentaiV1beta2InputConfig `json:"inputConfig,omitempty"`

	// OutputConfig: The output location of the parsed responses. The
	// responses are written to
	// this location as JSON-serialized `Document` objects.
	OutputConfig *GoogleCloudDocumentaiV1beta2OutputConfig `json:"outputConfig,omitempty"`

	// ForceSendFields is a list of field names (e.g. "InputConfig") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "InputConfig") to include
	// in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. However, any field with
	// an empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2ProcessDocumentResponse) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2ProcessDocumentResponse
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2TableBoundHint: A hint for a table
// bounding box on the page for table parsing.
type GoogleCloudDocumentaiV1beta2TableBoundHint struct {
	// BoundingBox: Bounding box hint for a table on this page. The
	// coordinates must be
	// normalized to [0,1] and the bounding box must be an axis-aligned
	// rectangle.
	BoundingBox *GoogleCloudDocumentaiV1beta2BoundingPoly `json:"boundingBox,omitempty"`

	// PageNumber: Optional. Page number for multi-paged inputs this hint
	// applies to. If not
	// provided, this hint will apply to all pages by default. This value
	// is
	// 1-based.
	PageNumber int64 `json:"pageNumber,omitempty"`

	// ForceSendFields is a list of field names (e.g. "BoundingBox") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "BoundingBox") to include
	// in API requests with the JSON null value. By default, fields with
	// empty values are omitted from API requests. However, any field with
	// an empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2TableBoundHint) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2TableBoundHint
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2TableExtractionParams: Parameters to
// control table extraction behavior.
type GoogleCloudDocumentaiV1beta2TableExtractionParams struct {
	// Enabled: Whether to enable table extraction.
	Enabled bool `json:"enabled,omitempty"`

	// HeaderHints: Optional. Reserved for future use.
	HeaderHints []string `json:"headerHints,omitempty"`

	// ModelVersion: Model version of the table extraction system. Default
	// is "builtin/stable".
	// Specify "builtin/latest" for the latest model.
	ModelVersion string `json:"modelVersion,omitempty"`

	// TableBoundHints: Optional. Table bounding box hints that can be
	// provided to complex cases
	// which our algorithm cannot locate the table(s) in.
	TableBoundHints []*GoogleCloudDocumentaiV1beta2TableBoundHint `json:"tableBoundHints,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Enabled") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Enabled") to include in
	// API requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2TableExtractionParams) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2TableExtractionParams
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleCloudDocumentaiV1beta2Vertex: A vertex represents a 2D point in
// the image.
// NOTE: the vertex coordinates are in the same scale as the original
// image.
type GoogleCloudDocumentaiV1beta2Vertex struct {
	// X: X coordinate.
	X int64 `json:"x,omitempty"`

	// Y: Y coordinate.
	Y int64 `json:"y,omitempty"`

	// ForceSendFields is a list of field names (e.g. "X") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "X") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleCloudDocumentaiV1beta2Vertex) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleCloudDocumentaiV1beta2Vertex
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleLongrunningOperation: This resource represents a long-running
// operation that is the result of a
// network API call.
type GoogleLongrunningOperation struct {
	// Done: If the value is `false`, it means the operation is still in
	// progress.
	// If `true`, the operation is completed, and either `error` or
	// `response` is
	// available.
	Done bool `json:"done,omitempty"`

	// Error: The error result of the operation in case of failure or
	// cancellation.
	Error *GoogleRpcStatus `json:"error,omitempty"`

	// Metadata: Service-specific metadata associated with the operation.
	// It typically
	// contains progress information and common metadata such as create
	// time.
	// Some services might not provide such metadata.  Any method that
	// returns a
	// long-running operation should document the metadata type, if any.
	Metadata googleapi.RawMessage `json:"metadata,omitempty"`

	// Name: The server-assigned name, which is only unique within the same
	// service that
	// originally returns it. If you use the default HTTP mapping,
	// the
	// `name` should be a resource name ending with
	// `operations/{unique_id}`.
	Name string `json:"name,omitempty"`

	// Response: The normal response of the operation in case of success.
	// If the original
	// method returns no data on success, such as `Delete`, the response
	// is
	// `google.protobuf.Empty`.  If the original method is
	// standard
	// `Get`/`Create`/`Update`, the response should be the resource.  For
	// other
	// methods, the response should have the type `XxxResponse`, where
	// `Xxx`
	// is the original method name.  For example, if the original method
	// name
	// is `TakeSnapshot()`, the inferred response type
	// is
	// `TakeSnapshotResponse`.
	Response googleapi.RawMessage `json:"response,omitempty"`

	// ServerResponse contains the HTTP response code and headers from the
	// server.
	googleapi.ServerResponse `json:"-"`

	// ForceSendFields is a list of field names (e.g. "Done") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Done") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleLongrunningOperation) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleLongrunningOperation
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleRpcStatus: The `Status` type defines a logical error model that
// is suitable for
// different programming environments, including REST APIs and RPC APIs.
// It is
// used by [gRPC](https://github.com/grpc). Each `Status` message
// contains
// three pieces of data: error code, error message, and error
// details.
//
// You can find out more about this error model and how to work with it
// in the
// [API Design Guide](https://cloud.google.com/apis/design/errors).
type GoogleRpcStatus struct {
	// Code: The status code, which should be an enum value of
	// google.rpc.Code.
	Code int64 `json:"code,omitempty"`

	// Details: A list of messages that carry the error details.  There is a
	// common set of
	// message types for APIs to use.
	Details []googleapi.RawMessage `json:"details,omitempty"`

	// Message: A developer-facing error message, which should be in
	// English. Any
	// user-facing error message should be localized and sent in
	// the
	// google.rpc.Status.details field, or localized by the client.
	Message string `json:"message,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Code") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Code") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleRpcStatus) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleRpcStatus
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

// GoogleTypeColor: Represents a color in the RGBA color space. This
// representation is designed
// for simplicity of conversion to/from color representations in
// various
// languages over compactness; for example, the fields of this
// representation
// can be trivially provided to the constructor of "java.awt.Color" in
// Java; it
// can also be trivially provided to UIColor's
// "+colorWithRed:green:blue:alpha"
// method in iOS; and, with just a little work, it can be easily
// formatted into
// a CSS "rgba()" string in JavaScript, as well.
//
// Note: this proto does not carry information about the absolute color
// space
// that should be used to interpret the RGB value (e.g. sRGB, Adobe
// RGB,
// DCI-P3, BT.2020, etc.). By default, applications SHOULD assume the
// sRGB color
// space.
//
// Note: when color equality needs to be decided, implementations,
// unless
// documented otherwise, will treat two colors to be equal if all their
// red,
// green, blue and alpha values each differ by at most 1e-5.
//
// Example (Java):
//
//      import com.google.type.Color;
//
//      // ...
//      public static java.awt.Color fromProto(Color protocolor) {
//        float alpha = protocolor.hasAlpha()
//            ? protocolor.getAlpha().getValue()
//            : 1.0;
//
//        return new java.awt.Color(
//            protocolor.getRed(),
//            protocolor.getGreen(),
//            protocolor.getBlue(),
//            alpha);
//      }
//
//      public static Color toProto(java.awt.Color color) {
//        float red = (float) color.getRed();
//        float green = (float) color.getGreen();
//        float blue = (float) color.getBlue();
//        float denominator = 255.0;
//        Color.Builder resultBuilder =
//            Color
//                .newBuilder()
//                .setRed(red / denominator)
//                .setGreen(green / denominator)
//                .setBlue(blue / denominator);
//        int alpha = color.getAlpha();
//        if (alpha != 255) {
//          result.setAlpha(
//              FloatValue
//                  .newBuilder()
//                  .setValue(((float) alpha) / denominator)
//                  .build());
//        }
//        return resultBuilder.build();
//      }
//      // ...
//
// Example (iOS / Obj-C):
//
//      // ...
//      static UIColor* fromProto(Color* protocolor) {
//         float red = [protocolor red];
//         float green = [protocolor green];
//         float blue = [protocolor blue];
//         FloatValue* alpha_wrapper = [protocolor alpha];
//         float alpha = 1.0;
//         if (alpha_wrapper != nil) {
//           alpha = [alpha_wrapper value];
//         }
//         return [UIColor colorWithRed:red green:green blue:blue
// alpha:alpha];
//      }
//
//      static Color* toProto(UIColor* color) {
//          CGFloat red, green, blue, alpha;
//          if (![color getRed:&red green:&green blue:&blue
// alpha:&alpha]) {
//            return nil;
//          }
//          Color* result = [[Color alloc] init];
//          [result setRed:red];
//          [result setGreen:green];
//          [result setBlue:blue];
//          if (alpha <= 0.9999) {
//            [result setAlpha:floatWrapperWithValue(alpha)];
//          }
//          [result autorelease];
//          return result;
//     }
//     // ...
//
//  Example (JavaScript):
//
//     // ...
//
//     var protoToCssColor = function(rgb_color) {
//        var redFrac = rgb_color.red || 0.0;
//        var greenFrac = rgb_color.green || 0.0;
//        var blueFrac = rgb_color.blue || 0.0;
//        var red = Math.floor(redFrac * 255);
//        var green = Math.floor(greenFrac * 255);
//        var blue = Math.floor(blueFrac * 255);
//
//        if (!('alpha' in rgb_color)) {
//           return rgbToCssColor_(red, green, blue);
//        }
//
//        var alphaFrac = rgb_color.alpha.value || 0.0;
//        var rgbParams = [red, green, blue].join(',');
//        return ['rgba(', rgbParams, ',', alphaFrac, ')'].join('');
//     };
//
//     var rgbToCssColor_ = function(red, green, blue) {
//       var rgbNumber = new Number((red << 16) | (green << 8) | blue);
//       var hexString = rgbNumber.toString(16);
//       var missingZeros = 6 - hexString.length;
//       var resultBuilder = ['#'];
//       for (var i = 0; i < missingZeros; i++) {
//          resultBuilder.push('0');
//       }
//       resultBuilder.push(hexString);
//       return resultBuilder.join('');
//     };
//
//     // ...
type GoogleTypeColor struct {
	// Alpha: The fraction of this color that should be applied to the
	// pixel. That is,
	// the final pixel color is defined by the equation:
	//
	//   pixel color = alpha * (this color) + (1.0 - alpha) * (background
	// color)
	//
	// This means that a value of 1.0 corresponds to a solid color,
	// whereas
	// a value of 0.0 corresponds to a completely transparent color.
	// This
	// uses a wrapper message rather than a simple float scalar so that it
	// is
	// possible to distinguish between a default value and the value being
	// unset.
	// If omitted, this color object is to be rendered as a solid color
	// (as if the alpha value had been explicitly given with a value of
	// 1.0).
	Alpha float64 `json:"alpha,omitempty"`

	// Blue: The amount of blue in the color as a value in the interval [0,
	// 1].
	Blue float64 `json:"blue,omitempty"`

	// Green: The amount of green in the color as a value in the interval
	// [0, 1].
	Green float64 `json:"green,omitempty"`

	// Red: The amount of red in the color as a value in the interval [0,
	// 1].
	Red float64 `json:"red,omitempty"`

	// ForceSendFields is a list of field names (e.g. "Alpha") to
	// unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "Alpha") to include in API
	// requests with the JSON null value. By default, fields with empty
	// values are omitted from API requests. However, any field with an
	// empty value appearing in NullFields will be sent to the server as
	// null. It is an error if a field in this list has a non-empty value.
	// This may be used to include null fields in Patch requests.
	NullFields []string `json:"-"`
}

func (s *GoogleTypeColor) MarshalJSON() ([]byte, error) {
	type NoMethod GoogleTypeColor
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

func (s *GoogleTypeColor) UnmarshalJSON(data []byte) error {
	type NoMethod GoogleTypeColor
	var s1 struct {
		Alpha gensupport.JSONFloat64 `json:"alpha"`
		Blue  gensupport.JSONFloat64 `json:"blue"`
		Green gensupport.JSONFloat64 `json:"green"`
		Red   gensupport.JSONFloat64 `json:"red"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.Alpha = float64(s1.Alpha)
	s.Blue = float64(s1.Blue)
	s.Green = float64(s1.Green)
	s.Red = float64(s1.Red)
	return nil
}

// method id "documentai.projects.documents.batchProcess":

type ProjectsDocumentsBatchProcessCall struct {
	s                                                        *Service
	parent                                                   string
	googleclouddocumentaiv1beta2batchprocessdocumentsrequest *GoogleCloudDocumentaiV1beta2BatchProcessDocumentsRequest
	urlParams_                                               gensupport.URLParams
	ctx_                                                     context.Context
	header_                                                  http.Header
}

// BatchProcess: LRO endpoint to batch process many documents. The
// output is written
// to Cloud Storage as JSON in the [Document] format.
func (r *ProjectsDocumentsService) BatchProcess(parent string, googleclouddocumentaiv1beta2batchprocessdocumentsrequest *GoogleCloudDocumentaiV1beta2BatchProcessDocumentsRequest) *ProjectsDocumentsBatchProcessCall {
	c := &ProjectsDocumentsBatchProcessCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.googleclouddocumentaiv1beta2batchprocessdocumentsrequest = googleclouddocumentaiv1beta2batchprocessdocumentsrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsDocumentsBatchProcessCall) Fields(s ...googleapi.Field) *ProjectsDocumentsBatchProcessCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsDocumentsBatchProcessCall) Context(ctx context.Context) *ProjectsDocumentsBatchProcessCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsDocumentsBatchProcessCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsDocumentsBatchProcessCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200716")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	var body io.Reader = nil
	body, err := googleapi.WithoutDataWrapper.JSONReader(c.googleclouddocumentaiv1beta2batchprocessdocumentsrequest)
	if err != nil {
		return nil, err
	}
	reqHeaders.Set("Content-Type", "application/json")
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta2/{+parent}/documents:batchProcess")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "documentai.projects.documents.batchProcess" call.
// Exactly one of *GoogleLongrunningOperation or error will be non-nil.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleLongrunningOperation.ServerResponse.Header or (if a response
// was returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was
// because http.StatusNotModified was returned.
func (c *ProjectsDocumentsBatchProcessCall) Do(opts ...googleapi.CallOption) (*GoogleLongrunningOperation, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleLongrunningOperation{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "LRO endpoint to batch process many documents. The output is written\nto Cloud Storage as JSON in the [Document] format.",
	//   "flatPath": "v1beta2/projects/{projectsId}/documents:batchProcess",
	//   "httpMethod": "POST",
	//   "id": "documentai.projects.documents.batchProcess",
	//   "parameterOrder": [
	//     "parent"
	//   ],
	//   "parameters": {
	//     "parent": {
	//       "description": "Target project and location to make a call.\n\nFormat: `projects/{project-id}/locations/{location-id}`.\n\nIf no location is specified, a region will be chosen automatically.",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta2/{+parent}/documents:batchProcess",
	//   "request": {
	//     "$ref": "GoogleCloudDocumentaiV1beta2BatchProcessDocumentsRequest"
	//   },
	//   "response": {
	//     "$ref": "GoogleLongrunningOperation"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// method id "documentai.projects.documents.process":

type ProjectsDocumentsProcessCall struct {
	s                                                  *Service
	parent                                             string
	googleclouddocumentaiv1beta2processdocumentrequest *GoogleCloudDocumentaiV1beta2ProcessDocumentRequest
	urlParams_                                         gensupport.URLParams
	ctx_                                               context.Context
	header_                                            http.Header
}

// Process: Processes a single document.
func (r *ProjectsDocumentsService) Process(parent string, googleclouddocumentaiv1beta2processdocumentrequest *GoogleCloudDocumentaiV1beta2ProcessDocumentRequest) *ProjectsDocumentsProcessCall {
	c := &ProjectsDocumentsProcessCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.googleclouddocumentaiv1beta2processdocumentrequest = googleclouddocumentaiv1beta2processdocumentrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsDocumentsProcessCall) Fields(s ...googleapi.Field) *ProjectsDocumentsProcessCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsDocumentsProcessCall) Context(ctx context.Context) *ProjectsDocumentsProcessCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsDocumentsProcessCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsDocumentsProcessCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200716")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	var body io.Reader = nil
	body, err := googleapi.WithoutDataWrapper.JSONReader(c.googleclouddocumentaiv1beta2processdocumentrequest)
	if err != nil {
		return nil, err
	}
	reqHeaders.Set("Content-Type", "application/json")
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta2/{+parent}/documents:process")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "documentai.projects.documents.process" call.
// Exactly one of *GoogleCloudDocumentaiV1beta2Document or error will be
// non-nil. Any non-2xx status code is an error. Response headers are in
// either *GoogleCloudDocumentaiV1beta2Document.ServerResponse.Header or
// (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsDocumentsProcessCall) Do(opts ...googleapi.CallOption) (*GoogleCloudDocumentaiV1beta2Document, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleCloudDocumentaiV1beta2Document{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Processes a single document.",
	//   "flatPath": "v1beta2/projects/{projectsId}/documents:process",
	//   "httpMethod": "POST",
	//   "id": "documentai.projects.documents.process",
	//   "parameterOrder": [
	//     "parent"
	//   ],
	//   "parameters": {
	//     "parent": {
	//       "description": "Target project and location to make a call.\n\nFormat: `projects/{project-id}/locations/{location-id}`.\n\nIf no location is specified, a region will be chosen automatically.\nThis field is only populated when used in ProcessDocument method.",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta2/{+parent}/documents:process",
	//   "request": {
	//     "$ref": "GoogleCloudDocumentaiV1beta2ProcessDocumentRequest"
	//   },
	//   "response": {
	//     "$ref": "GoogleCloudDocumentaiV1beta2Document"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// method id "documentai.projects.locations.documents.batchProcess":

type ProjectsLocationsDocumentsBatchProcessCall struct {
	s                                                        *Service
	parent                                                   string
	googleclouddocumentaiv1beta2batchprocessdocumentsrequest *GoogleCloudDocumentaiV1beta2BatchProcessDocumentsRequest
	urlParams_                                               gensupport.URLParams
	ctx_                                                     context.Context
	header_                                                  http.Header
}

// BatchProcess: LRO endpoint to batch process many documents. The
// output is written
// to Cloud Storage as JSON in the [Document] format.
func (r *ProjectsLocationsDocumentsService) BatchProcess(parent string, googleclouddocumentaiv1beta2batchprocessdocumentsrequest *GoogleCloudDocumentaiV1beta2BatchProcessDocumentsRequest) *ProjectsLocationsDocumentsBatchProcessCall {
	c := &ProjectsLocationsDocumentsBatchProcessCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.googleclouddocumentaiv1beta2batchprocessdocumentsrequest = googleclouddocumentaiv1beta2batchprocessdocumentsrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsLocationsDocumentsBatchProcessCall) Fields(s ...googleapi.Field) *ProjectsLocationsDocumentsBatchProcessCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsLocationsDocumentsBatchProcessCall) Context(ctx context.Context) *ProjectsLocationsDocumentsBatchProcessCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsLocationsDocumentsBatchProcessCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsDocumentsBatchProcessCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200716")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	var body io.Reader = nil
	body, err := googleapi.WithoutDataWrapper.JSONReader(c.googleclouddocumentaiv1beta2batchprocessdocumentsrequest)
	if err != nil {
		return nil, err
	}
	reqHeaders.Set("Content-Type", "application/json")
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta2/{+parent}/documents:batchProcess")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "documentai.projects.locations.documents.batchProcess" call.
// Exactly one of *GoogleLongrunningOperation or error will be non-nil.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleLongrunningOperation.ServerResponse.Header or (if a response
// was returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was
// because http.StatusNotModified was returned.
func (c *ProjectsLocationsDocumentsBatchProcessCall) Do(opts ...googleapi.CallOption) (*GoogleLongrunningOperation, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleLongrunningOperation{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "LRO endpoint to batch process many documents. The output is written\nto Cloud Storage as JSON in the [Document] format.",
	//   "flatPath": "v1beta2/projects/{projectsId}/locations/{locationsId}/documents:batchProcess",
	//   "httpMethod": "POST",
	//   "id": "documentai.projects.locations.documents.batchProcess",
	//   "parameterOrder": [
	//     "parent"
	//   ],
	//   "parameters": {
	//     "parent": {
	//       "description": "Target project and location to make a call.\n\nFormat: `projects/{project-id}/locations/{location-id}`.\n\nIf no location is specified, a region will be chosen automatically.",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta2/{+parent}/documents:batchProcess",
	//   "request": {
	//     "$ref": "GoogleCloudDocumentaiV1beta2BatchProcessDocumentsRequest"
	//   },
	//   "response": {
	//     "$ref": "GoogleLongrunningOperation"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// method id "documentai.projects.locations.documents.process":

type ProjectsLocationsDocumentsProcessCall struct {
	s                                                  *Service
	parent                                             string
	googleclouddocumentaiv1beta2processdocumentrequest *GoogleCloudDocumentaiV1beta2ProcessDocumentRequest
	urlParams_                                         gensupport.URLParams
	ctx_                                               context.Context
	header_                                            http.Header
}

// Process: Processes a single document.
func (r *ProjectsLocationsDocumentsService) Process(parent string, googleclouddocumentaiv1beta2processdocumentrequest *GoogleCloudDocumentaiV1beta2ProcessDocumentRequest) *ProjectsLocationsDocumentsProcessCall {
	c := &ProjectsLocationsDocumentsProcessCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.parent = parent
	c.googleclouddocumentaiv1beta2processdocumentrequest = googleclouddocumentaiv1beta2processdocumentrequest
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsLocationsDocumentsProcessCall) Fields(s ...googleapi.Field) *ProjectsLocationsDocumentsProcessCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsLocationsDocumentsProcessCall) Context(ctx context.Context) *ProjectsLocationsDocumentsProcessCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsLocationsDocumentsProcessCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsDocumentsProcessCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200716")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	var body io.Reader = nil
	body, err := googleapi.WithoutDataWrapper.JSONReader(c.googleclouddocumentaiv1beta2processdocumentrequest)
	if err != nil {
		return nil, err
	}
	reqHeaders.Set("Content-Type", "application/json")
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta2/{+parent}/documents:process")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("POST", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"parent": c.parent,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "documentai.projects.locations.documents.process" call.
// Exactly one of *GoogleCloudDocumentaiV1beta2Document or error will be
// non-nil. Any non-2xx status code is an error. Response headers are in
// either *GoogleCloudDocumentaiV1beta2Document.ServerResponse.Header or
// (if a response was returned at all) in
// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check
// whether the returned error was because http.StatusNotModified was
// returned.
func (c *ProjectsLocationsDocumentsProcessCall) Do(opts ...googleapi.CallOption) (*GoogleCloudDocumentaiV1beta2Document, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleCloudDocumentaiV1beta2Document{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Processes a single document.",
	//   "flatPath": "v1beta2/projects/{projectsId}/locations/{locationsId}/documents:process",
	//   "httpMethod": "POST",
	//   "id": "documentai.projects.locations.documents.process",
	//   "parameterOrder": [
	//     "parent"
	//   ],
	//   "parameters": {
	//     "parent": {
	//       "description": "Target project and location to make a call.\n\nFormat: `projects/{project-id}/locations/{location-id}`.\n\nIf no location is specified, a region will be chosen automatically.\nThis field is only populated when used in ProcessDocument method.",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta2/{+parent}/documents:process",
	//   "request": {
	//     "$ref": "GoogleCloudDocumentaiV1beta2ProcessDocumentRequest"
	//   },
	//   "response": {
	//     "$ref": "GoogleCloudDocumentaiV1beta2Document"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// method id "documentai.projects.locations.operations.get":

type ProjectsLocationsOperationsGetCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// Get: Gets the latest state of a long-running operation.  Clients can
// use this
// method to poll the operation result at intervals as recommended by
// the API
// service.
func (r *ProjectsLocationsOperationsService) Get(name string) *ProjectsLocationsOperationsGetCall {
	c := &ProjectsLocationsOperationsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsLocationsOperationsGetCall) Fields(s ...googleapi.Field) *ProjectsLocationsOperationsGetCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets the optional parameter which makes the operation
// fail if the object's ETag matches the given value. This is useful for
// getting updates only after the object has changed since the last
// request. Use googleapi.IsNotModified to check whether the response
// error from Do is the result of In-None-Match.
func (c *ProjectsLocationsOperationsGetCall) IfNoneMatch(entityTag string) *ProjectsLocationsOperationsGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsLocationsOperationsGetCall) Context(ctx context.Context) *ProjectsLocationsOperationsGetCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsLocationsOperationsGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsLocationsOperationsGetCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200716")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	var body io.Reader = nil
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta2/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "documentai.projects.locations.operations.get" call.
// Exactly one of *GoogleLongrunningOperation or error will be non-nil.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleLongrunningOperation.ServerResponse.Header or (if a response
// was returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was
// because http.StatusNotModified was returned.
func (c *ProjectsLocationsOperationsGetCall) Do(opts ...googleapi.CallOption) (*GoogleLongrunningOperation, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleLongrunningOperation{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Gets the latest state of a long-running operation.  Clients can use this\nmethod to poll the operation result at intervals as recommended by the API\nservice.",
	//   "flatPath": "v1beta2/projects/{projectsId}/locations/{locationsId}/operations/{operationsId}",
	//   "httpMethod": "GET",
	//   "id": "documentai.projects.locations.operations.get",
	//   "parameterOrder": [
	//     "name"
	//   ],
	//   "parameters": {
	//     "name": {
	//       "description": "The name of the operation resource.",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/locations/[^/]+/operations/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta2/{+name}",
	//   "response": {
	//     "$ref": "GoogleLongrunningOperation"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}

// method id "documentai.projects.operations.get":

type ProjectsOperationsGetCall struct {
	s            *Service
	name         string
	urlParams_   gensupport.URLParams
	ifNoneMatch_ string
	ctx_         context.Context
	header_      http.Header
}

// Get: Gets the latest state of a long-running operation.  Clients can
// use this
// method to poll the operation result at intervals as recommended by
// the API
// service.
func (r *ProjectsOperationsService) Get(name string) *ProjectsOperationsGetCall {
	c := &ProjectsOperationsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
	c.name = name
	return c
}

// Fields allows partial responses to be retrieved. See
// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
// for more information.
func (c *ProjectsOperationsGetCall) Fields(s ...googleapi.Field) *ProjectsOperationsGetCall {
	c.urlParams_.Set("fields", googleapi.CombineFields(s))
	return c
}

// IfNoneMatch sets the optional parameter which makes the operation
// fail if the object's ETag matches the given value. This is useful for
// getting updates only after the object has changed since the last
// request. Use googleapi.IsNotModified to check whether the response
// error from Do is the result of In-None-Match.
func (c *ProjectsOperationsGetCall) IfNoneMatch(entityTag string) *ProjectsOperationsGetCall {
	c.ifNoneMatch_ = entityTag
	return c
}

// Context sets the context to be used in this call's Do method. Any
// pending HTTP request will be aborted if the provided context is
// canceled.
func (c *ProjectsOperationsGetCall) Context(ctx context.Context) *ProjectsOperationsGetCall {
	c.ctx_ = ctx
	return c
}

// Header returns an http.Header that can be modified by the caller to
// add HTTP headers to the request.
func (c *ProjectsOperationsGetCall) Header() http.Header {
	if c.header_ == nil {
		c.header_ = make(http.Header)
	}
	return c.header_
}

func (c *ProjectsOperationsGetCall) doRequest(alt string) (*http.Response, error) {
	reqHeaders := make(http.Header)
	reqHeaders.Set("x-goog-api-client", "gl-go/"+gensupport.GoVersion()+" gdcl/20200716")
	for k, v := range c.header_ {
		reqHeaders[k] = v
	}
	reqHeaders.Set("User-Agent", c.s.userAgent())
	if c.ifNoneMatch_ != "" {
		reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
	}
	var body io.Reader = nil
	c.urlParams_.Set("alt", alt)
	c.urlParams_.Set("prettyPrint", "false")
	urls := googleapi.ResolveRelative(c.s.BasePath, "v1beta2/{+name}")
	urls += "?" + c.urlParams_.Encode()
	req, err := http.NewRequest("GET", urls, body)
	if err != nil {
		return nil, err
	}
	req.Header = reqHeaders
	googleapi.Expand(req.URL, map[string]string{
		"name": c.name,
	})
	return gensupport.SendRequest(c.ctx_, c.s.client, req)
}

// Do executes the "documentai.projects.operations.get" call.
// Exactly one of *GoogleLongrunningOperation or error will be non-nil.
// Any non-2xx status code is an error. Response headers are in either
// *GoogleLongrunningOperation.ServerResponse.Header or (if a response
// was returned at all) in error.(*googleapi.Error).Header. Use
// googleapi.IsNotModified to check whether the returned error was
// because http.StatusNotModified was returned.
func (c *ProjectsOperationsGetCall) Do(opts ...googleapi.CallOption) (*GoogleLongrunningOperation, error) {
	gensupport.SetOptions(c.urlParams_, opts...)
	res, err := c.doRequest("json")
	if res != nil && res.StatusCode == http.StatusNotModified {
		if res.Body != nil {
			res.Body.Close()
		}
		return nil, &googleapi.Error{
			Code:   res.StatusCode,
			Header: res.Header,
		}
	}
	if err != nil {
		return nil, err
	}
	defer googleapi.CloseBody(res)
	if err := googleapi.CheckResponse(res); err != nil {
		return nil, err
	}
	ret := &GoogleLongrunningOperation{
		ServerResponse: googleapi.ServerResponse{
			Header:         res.Header,
			HTTPStatusCode: res.StatusCode,
		},
	}
	target := &ret
	if err := gensupport.DecodeResponse(target, res); err != nil {
		return nil, err
	}
	return ret, nil
	// {
	//   "description": "Gets the latest state of a long-running operation.  Clients can use this\nmethod to poll the operation result at intervals as recommended by the API\nservice.",
	//   "flatPath": "v1beta2/projects/{projectsId}/operations/{operationsId}",
	//   "httpMethod": "GET",
	//   "id": "documentai.projects.operations.get",
	//   "parameterOrder": [
	//     "name"
	//   ],
	//   "parameters": {
	//     "name": {
	//       "description": "The name of the operation resource.",
	//       "location": "path",
	//       "pattern": "^projects/[^/]+/operations/[^/]+$",
	//       "required": true,
	//       "type": "string"
	//     }
	//   },
	//   "path": "v1beta2/{+name}",
	//   "response": {
	//     "$ref": "GoogleLongrunningOperation"
	//   },
	//   "scopes": [
	//     "https://www.googleapis.com/auth/cloud-platform"
	//   ]
	// }

}
