/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// Code generated by protoc-gen-go-triple. DO NOT EDIT.
// versions:
// - protoc-gen-go-triple v1.0.8
// - protoc             v3.21.12
// source: mock.proto

package api

import (
	context "context"
	protocol "dubbo.apache.org/dubbo-go/v3/protocol"
	dubbo3 "dubbo.apache.org/dubbo-go/v3/protocol/dubbo3"
	invocation "dubbo.apache.org/dubbo-go/v3/protocol/invocation"
	grpc_go "github.com/dubbogo/grpc-go"
	codes "github.com/dubbogo/grpc-go/codes"
	metadata "github.com/dubbogo/grpc-go/metadata"
	status "github.com/dubbogo/grpc-go/status"
	common "github.com/dubbogo/triple/pkg/common"
	constant "github.com/dubbogo/triple/pkg/common/constant"
	triple "github.com/dubbogo/triple/pkg/triple"
)

// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc_go.SupportPackageIsVersion7

// MockServiceClient is the clientgen API for MockService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type MockServiceClient interface {
	GetMockData(ctx context.Context, in *GetMockDataReq, opts ...grpc_go.CallOption) (*GetMockDataResp, common.ErrorWithAttachment)
}

type mockServiceClient struct {
	cc *triple.TripleConn
}

type MockServiceClientImpl struct {
	GetMockData func(ctx context.Context, in *GetMockDataReq) (*GetMockDataResp, error)
}

func (c *MockServiceClientImpl) GetDubboStub(cc *triple.TripleConn) MockServiceClient {
	return NewMockServiceClient(cc)
}

func (c *MockServiceClientImpl) XXX_InterfaceName() string {
	return "api.MockService"
}

func NewMockServiceClient(cc *triple.TripleConn) MockServiceClient {
	return &mockServiceClient{cc}
}

func (c *mockServiceClient) GetMockData(ctx context.Context, in *GetMockDataReq, opts ...grpc_go.CallOption) (*GetMockDataResp, common.ErrorWithAttachment) {
	out := new(GetMockDataResp)
	interfaceKey := ctx.Value(constant.InterfaceKey).(string)
	return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/GetMockData", in, out)
}

// MockServiceServer is the cp-server API for MockService service.
// All implementations must embed UnimplementedMockServiceServer
// for forward compatibility
type MockServiceServer interface {
	GetMockData(context.Context, *GetMockDataReq) (*GetMockDataResp, error)
	mustEmbedUnimplementedMockServiceServer()
}

// UnimplementedMockServiceServer must be embedded to have forward compatible implementations.
type UnimplementedMockServiceServer struct {
	proxyImpl protocol.Invoker
}

func (UnimplementedMockServiceServer) GetMockData(context.Context, *GetMockDataReq) (*GetMockDataResp, error) {
	return nil, status.Errorf(codes.Unimplemented, "method GetMockData not implemented")
}
func (s *UnimplementedMockServiceServer) XXX_SetProxyImpl(impl protocol.Invoker) {
	s.proxyImpl = impl
}

func (s *UnimplementedMockServiceServer) XXX_GetProxyImpl() protocol.Invoker {
	return s.proxyImpl
}

func (s *UnimplementedMockServiceServer) XXX_ServiceDesc() *grpc_go.ServiceDesc {
	return &MockService_ServiceDesc
}
func (s *UnimplementedMockServiceServer) XXX_InterfaceName() string {
	return "org.apache.dubbo.mock.api.MockService"
}

func (UnimplementedMockServiceServer) mustEmbedUnimplementedMockServiceServer() {}

// UnsafeMockServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to MockServiceServer will
// result in compilation errors.
type UnsafeMockServiceServer interface {
	mustEmbedUnimplementedMockServiceServer()
}

func RegisterMockServiceServer(s grpc_go.ServiceRegistrar, srv MockServiceServer) {
	s.RegisterService(&MockService_ServiceDesc, srv)
}

func _MockService_GetMockData_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
	in := new(GetMockDataReq)
	if err := dec(in); err != nil {
		return nil, err
	}
	base := srv.(dubbo3.Dubbo3GrpcService)
	args := []interface{}{}
	args = append(args, in)
	md, _ := metadata.FromIncomingContext(ctx)
	invAttachment := make(map[string]interface{}, len(md))
	for k, v := range md {
		invAttachment[k] = v
	}
	invo := invocation.NewRPCInvocation("GetMockData", args, invAttachment)
	if interceptor == nil {
		result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
		return result, result.Error()
	}
	info := &grpc_go.UnaryServerInfo{
		Server:     srv,
		FullMethod: ctx.Value("XXX_TRIPLE_GO_INTERFACE_NAME").(string),
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
		return result, result.Error()
	}
	return interceptor(ctx, in, info, handler)
}

// MockService_ServiceDesc is the grpc_go.ServiceDesc for MockService service.
// It's only intended for direct use with grpc_go.RegisterService,
// and not to be introspected or modified (even as a copy)
var MockService_ServiceDesc = grpc_go.ServiceDesc{
	ServiceName: "api.MockService",
	HandlerType: (*MockServiceServer)(nil),
	Methods: []grpc_go.MethodDesc{
		{
			MethodName: "GetMockData",
			Handler:    _MockService_GetMockData_Handler,
		},
	},
	Streams:  []grpc_go.StreamDesc{},
	Metadata: "mock.proto",
}
