// Code generated by svcdec; DO NOT EDIT.

package buildbucketpb

import (
	"context"

	proto "github.com/golang/protobuf/proto"
)

type DecoratedBuilds struct {
	// Service is the service to decorate.
	Service BuildsServer
	// Prelude is called for each method before forwarding the call to Service.
	// If Prelude returns an error, then the call is skipped and the error is
	// processed via the Postlude (if one is defined), or it is returned directly.
	Prelude func(ctx context.Context, methodName string, req proto.Message) (context.Context, error)
	// Postlude is called for each method after Service has processed the call, or
	// after the Prelude has returned an error. This takes the the Service's
	// response proto (which may be nil) and/or any error. The decorated
	// service will return the response (possibly mutated) and error that Postlude
	// returns.
	Postlude func(ctx context.Context, methodName string, rsp proto.Message, err error) error
}

func (s *DecoratedBuilds) GetBuild(ctx context.Context, req *GetBuildRequest) (rsp *Build, err error) {
	if s.Prelude != nil {
		var newCtx context.Context
		newCtx, err = s.Prelude(ctx, "GetBuild", req)
		if err == nil {
			ctx = newCtx
		}
	}
	if err == nil {
		rsp, err = s.Service.GetBuild(ctx, req)
	}
	if s.Postlude != nil {
		err = s.Postlude(ctx, "GetBuild", rsp, err)
	}
	return
}

func (s *DecoratedBuilds) SearchBuilds(ctx context.Context, req *SearchBuildsRequest) (rsp *SearchBuildsResponse, err error) {
	if s.Prelude != nil {
		var newCtx context.Context
		newCtx, err = s.Prelude(ctx, "SearchBuilds", req)
		if err == nil {
			ctx = newCtx
		}
	}
	if err == nil {
		rsp, err = s.Service.SearchBuilds(ctx, req)
	}
	if s.Postlude != nil {
		err = s.Postlude(ctx, "SearchBuilds", rsp, err)
	}
	return
}

func (s *DecoratedBuilds) UpdateBuild(ctx context.Context, req *UpdateBuildRequest) (rsp *Build, err error) {
	if s.Prelude != nil {
		var newCtx context.Context
		newCtx, err = s.Prelude(ctx, "UpdateBuild", req)
		if err == nil {
			ctx = newCtx
		}
	}
	if err == nil {
		rsp, err = s.Service.UpdateBuild(ctx, req)
	}
	if s.Postlude != nil {
		err = s.Postlude(ctx, "UpdateBuild", rsp, err)
	}
	return
}

func (s *DecoratedBuilds) ScheduleBuild(ctx context.Context, req *ScheduleBuildRequest) (rsp *Build, err error) {
	if s.Prelude != nil {
		var newCtx context.Context
		newCtx, err = s.Prelude(ctx, "ScheduleBuild", req)
		if err == nil {
			ctx = newCtx
		}
	}
	if err == nil {
		rsp, err = s.Service.ScheduleBuild(ctx, req)
	}
	if s.Postlude != nil {
		err = s.Postlude(ctx, "ScheduleBuild", rsp, err)
	}
	return
}

func (s *DecoratedBuilds) CancelBuild(ctx context.Context, req *CancelBuildRequest) (rsp *Build, err error) {
	if s.Prelude != nil {
		var newCtx context.Context
		newCtx, err = s.Prelude(ctx, "CancelBuild", req)
		if err == nil {
			ctx = newCtx
		}
	}
	if err == nil {
		rsp, err = s.Service.CancelBuild(ctx, req)
	}
	if s.Postlude != nil {
		err = s.Postlude(ctx, "CancelBuild", rsp, err)
	}
	return
}

func (s *DecoratedBuilds) Batch(ctx context.Context, req *BatchRequest) (rsp *BatchResponse, err error) {
	if s.Prelude != nil {
		var newCtx context.Context
		newCtx, err = s.Prelude(ctx, "Batch", req)
		if err == nil {
			ctx = newCtx
		}
	}
	if err == nil {
		rsp, err = s.Service.Batch(ctx, req)
	}
	if s.Postlude != nil {
		err = s.Postlude(ctx, "Batch", rsp, err)
	}
	return
}

func (s *DecoratedBuilds) CreateBuild(ctx context.Context, req *CreateBuildRequest) (rsp *Build, err error) {
	if s.Prelude != nil {
		var newCtx context.Context
		newCtx, err = s.Prelude(ctx, "CreateBuild", req)
		if err == nil {
			ctx = newCtx
		}
	}
	if err == nil {
		rsp, err = s.Service.CreateBuild(ctx, req)
	}
	if s.Postlude != nil {
		err = s.Postlude(ctx, "CreateBuild", rsp, err)
	}
	return
}
