diff --git a/buf.gen.yaml b/buf.gen.yaml new file mode 100644 index 0000000..e3a3e1d --- /dev/null +++ b/buf.gen.yaml @@ -0,0 +1,17 @@ +version: v2 +clean: true + +plugins: + - remote: buf.build/protocolbuffers/go:v1.36.11 + revision: 1 + out: gen + opt: + - module=git.pablu.de/pablu/zw-go/gen + - remote: buf.build/grpc/go:v1.6.2 + revision: 1 + out: gen + opt: + - module=git.pablu.de/pablu/zw-go/gen + +inputs: + - directory: ../zw diff --git a/client.go b/client.go new file mode 100644 index 0000000..f799f07 --- /dev/null +++ b/client.go @@ -0,0 +1,293 @@ +package zw + +import ( + "context" + "errors" + "fmt" + "io" + "net/url" + + zwdaemonv1 "git.pablu.de/pablu/zw-go/gen/zwdaemon/v1" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" +) + +const supportedAPIMajor uint32 = 1 + +func optionalString(value string) *string { + if value == "" { + return nil + } + return &value +} + +type Client struct { + conn *grpc.ClientConn + rpc zwdaemonv1.ZwDaemonServiceClient +} + +func Connect(ctx context.Context, socketPath string) (*Client, error) { + target := (&url.URL{ + Scheme: "unix", + Path: socketPath, + }).String() + + conn, err := grpc.NewClient( + target, + grpc.WithTransportCredentials(insecure.NewCredentials()), + ) + if err != nil { + return nil, fmt.Errorf("create daemon client: %w", err) + } + + client := &Client{ + conn: conn, + rpc: zwdaemonv1.NewZwDaemonServiceClient(conn), + } + + info, err := client.ServerInfo(ctx) + if err != nil { + _ = conn.Close() + return nil, err + } + + if info.APIMajor != supportedAPIMajor { + _ = conn.Close() + return nil, &IncompatibleAPIVersionError{ + ServerMajor: info.APIMajor, + ServerMinor: info.APIMinor, + SupportedMajor: supportedAPIMajor, + } + } + + return client, nil +} + +func (c *Client) Close() error { + return c.conn.Close() +} + +func (c *Client) ServerInfo(ctx context.Context) (ServerInfo, error) { + response, err := c.rpc.GetServerInfo(ctx, &zwdaemonv1.GetServerInfoRequest{}) + if err != nil { + return ServerInfo{}, convertRPCError(err) + } + + return ServerInfo{ + APIMajor: response.ApiMajor, + APIMinor: response.ApiMinor, + DaemonVersion: response.DaemonVersion, + }, nil +} + +func (c *Client) Create(ctx context.Context, vaultPath string, password string) error { + _, err := c.rpc.Create(ctx, &zwdaemonv1.CreateRequest{ + VaultPath: vaultPath, + Password: password, + }) + if err != nil { + return convertRPCError(err) + } + return nil +} + +func (c *Client) Unseal(ctx context.Context, vaultPath string, password string) error { + _, err := c.rpc.Unseal(ctx, &zwdaemonv1.UnsealRequest{ + VaultPath: vaultPath, + Password: password, + }) + if err != nil { + return convertRPCError(err) + } + return nil +} + +func (c *Client) Seal(ctx context.Context) error { + _, err := c.rpc.Seal(ctx, &zwdaemonv1.SealRequest{}) + if err != nil { + return convertRPCError(err) + } + return nil +} + +func (c *Client) ListFiles(ctx context.Context, filter ListFilter) ([]ListedFile, error) { + response, err := c.rpc.ListFiles(ctx, &zwdaemonv1.ListFilesRequest{ + Prefix: optionalString(filter.Prefix), + Contains: optionalString(filter.Contains), + }) + if err != nil { + return nil, convertRPCError(err) + } + + files := make([]ListedFile, len(response.GetFiles())) + for index, file := range response.GetFiles() { + files[index] = ListedFile{ + LogicalPath: file.GetLogicalPath(), + Size: file.GetSize(), + } + } + + return files, nil +} + +func (c *Client) ListPaths(ctx context.Context) ([]string, error) { + files, err := c.ListFiles(ctx, ListFilter{}) + if err != nil { + return nil, err + } + + paths := make([]string, len(files)) + for index, file := range files { + paths[index] = file.LogicalPath + } + + return paths, nil +} + +func (c *Client) DeleteFile(ctx context.Context, logicalPath string) error { + _, err := c.rpc.DeleteFile(ctx, &zwdaemonv1.DeleteFileRequest{ + LogicalPath: logicalPath, + }) + if err != nil { + return convertRPCError(err) + } + return nil +} + +func (c *Client) Compact(ctx context.Context) error { + _, err := c.rpc.Compact(ctx, &zwdaemonv1.CompactRequest{}) + if err != nil { + return convertRPCError(err) + } + return nil +} + +func (c *Client) GetFile( + ctx context.Context, + logicalPath string, +) (io.ReadCloser, error) { + streamCtx, cancel := context.WithCancel(ctx) + + stream, err := c.rpc.GetFile(streamCtx, &zwdaemonv1.GetFileRequest{ + LogicalPath: logicalPath, + }) + if err != nil { + cancel() + return nil, convertRPCError(err) + } + + return &downloadReader{ + cancel: cancel, + recv: func() ([]byte, error) { + response, err := stream.Recv() + if err != nil { + return nil, err + } + return response.GetData(), nil + }, + }, nil +} + +func (c *Client) GetFileRange( + ctx context.Context, + logicalPath string, + start uint64, + exclusiveEnd uint64, +) (io.ReadCloser, error) { + streamCtx, cancel := context.WithCancel(ctx) + + stream, err := c.rpc.GetFileRange(streamCtx, &zwdaemonv1.GetFileRangeRequest{ + LogicalPath: logicalPath, + Start: start, + ExclusiveEnd: exclusiveEnd, + }) + if err != nil { + cancel() + return nil, convertRPCError(err) + } + + return &downloadReader{ + cancel: cancel, + recv: func() ([]byte, error) { + response, err := stream.Recv() + if err != nil { + return nil, err + } + return response.GetData(), nil + }, + }, nil +} + +func (c *Client) AddFile( + ctx context.Context, + logicalPath string, + source io.Reader, + sourceLen uint64, +) error { + uploadCtx, cancel := context.WithCancel(ctx) + defer cancel() + + stream, err := c.rpc.AddFile(uploadCtx) + if err != nil { + return convertRPCError(err) + } + + send := func(request *zwdaemonv1.AddFileRequest) error { + err := stream.Send(request) + if err == nil { + return nil + } + + if errors.Is(err, io.EOF) { + _, receiveErr := stream.CloseAndRecv() + if receiveErr != nil { + return convertRPCError(receiveErr) + } + } + + return convertRPCError(err) + } + + err = send(&zwdaemonv1.AddFileRequest{ + Payload: &zwdaemonv1.AddFileRequest_Header{ + Header: &zwdaemonv1.AddFileHeader{ + LogicalPath: logicalPath, + SourceLen: sourceLen, + }, + }, + }) + if err != nil { + return err + } + + const chunkSize = 512 * 1024 + buffer := make([]byte, chunkSize) + + for { + n, readErr := source.Read(buffer) + + if n > 0 { + err := send(&zwdaemonv1.AddFileRequest{ + Payload: &zwdaemonv1.AddFileRequest_Chunk{ + Chunk: buffer[:n], + }, + }) + if err != nil { + return err + } + } + + switch { + case readErr == nil: + continue + case errors.Is(readErr, io.EOF): + _, err := stream.CloseAndRecv() + if err != nil { + return convertRPCError(err) + } + return nil + default: + return &UploadReadError{Err: readErr} + } + } +} diff --git a/client_test.go b/client_test.go new file mode 100644 index 0000000..af890f0 --- /dev/null +++ b/client_test.go @@ -0,0 +1,1024 @@ +package zw + +import ( + "bytes" + "context" + "errors" + "fmt" + "io" + "io/fs" + "net" + "path/filepath" + "sync/atomic" + "testing" + "time" + + zwdaemonv1 "git.pablu.de/pablu/zw-go/gen/zwdaemon/v1" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/anypb" +) + +const testZwErrorDetailTypeURL = "type.googleapis.com/zw.daemon.v1.ZwErrorDetail" + +type testService struct { + zwdaemonv1.UnimplementedZwDaemonServiceServer + + response *zwdaemonv1.GetServerInfoResponse + err error + + createRequests chan *zwdaemonv1.CreateRequest + createErr error + unsealRequests chan *zwdaemonv1.UnsealRequest + unsealErr error + sealCalls chan struct{} + sealErr error + + listFilesRequests chan *zwdaemonv1.ListFilesRequest + listFilesResponse *zwdaemonv1.ListFilesResponse + listFilesErr error + + deleteFileRequests chan *zwdaemonv1.DeleteFileRequest + deleteFileErr error + compactCalls chan struct{} + compactErr error + + getFile func(*zwdaemonv1.GetFileRequest, grpc.ServerStreamingServer[zwdaemonv1.GetFileResponse]) error + getFileRange func(*zwdaemonv1.GetFileRangeRequest, grpc.ServerStreamingServer[zwdaemonv1.GetFileRangeResponse]) error + addFile func(grpc.ClientStreamingServer[zwdaemonv1.AddFileRequest, zwdaemonv1.AddFileResponse]) error +} + +func (s *testService) GetServerInfo( + context.Context, + *zwdaemonv1.GetServerInfoRequest, +) (*zwdaemonv1.GetServerInfoResponse, error) { + return s.response, s.err +} + +func (s *testService) Create( + _ context.Context, + request *zwdaemonv1.CreateRequest, +) (*zwdaemonv1.CreateResponse, error) { + if s.createRequests != nil { + s.createRequests <- request + } + return &zwdaemonv1.CreateResponse{}, s.createErr +} + +func (s *testService) Unseal( + _ context.Context, + request *zwdaemonv1.UnsealRequest, +) (*zwdaemonv1.UnsealResponse, error) { + if s.unsealRequests != nil { + s.unsealRequests <- request + } + return &zwdaemonv1.UnsealResponse{}, s.unsealErr +} + +func (s *testService) Seal( + context.Context, + *zwdaemonv1.SealRequest, +) (*zwdaemonv1.SealResponse, error) { + if s.sealCalls != nil { + s.sealCalls <- struct{}{} + } + return &zwdaemonv1.SealResponse{}, s.sealErr +} + +func (s *testService) ListFiles( + _ context.Context, + request *zwdaemonv1.ListFilesRequest, +) (*zwdaemonv1.ListFilesResponse, error) { + if s.listFilesRequests != nil { + s.listFilesRequests <- request + } + if s.listFilesResponse == nil { + return &zwdaemonv1.ListFilesResponse{}, s.listFilesErr + } + return s.listFilesResponse, s.listFilesErr +} + +func (s *testService) DeleteFile( + _ context.Context, + request *zwdaemonv1.DeleteFileRequest, +) (*zwdaemonv1.DeleteFileResponse, error) { + if s.deleteFileRequests != nil { + s.deleteFileRequests <- request + } + return &zwdaemonv1.DeleteFileResponse{}, s.deleteFileErr +} + +func (s *testService) Compact( + context.Context, + *zwdaemonv1.CompactRequest, +) (*zwdaemonv1.CompactResponse, error) { + if s.compactCalls != nil { + s.compactCalls <- struct{}{} + } + return &zwdaemonv1.CompactResponse{}, s.compactErr +} + +func (s *testService) GetFile( + request *zwdaemonv1.GetFileRequest, + stream grpc.ServerStreamingServer[zwdaemonv1.GetFileResponse], +) error { + if s.getFile == nil { + return nil + } + return s.getFile(request, stream) +} + +func (s *testService) GetFileRange( + request *zwdaemonv1.GetFileRangeRequest, + stream grpc.ServerStreamingServer[zwdaemonv1.GetFileRangeResponse], +) error { + if s.getFileRange == nil { + return nil + } + return s.getFileRange(request, stream) +} + +func (s *testService) AddFile( + stream grpc.ClientStreamingServer[zwdaemonv1.AddFileRequest, zwdaemonv1.AddFileResponse], +) error { + if s.addFile == nil { + return stream.SendAndClose(&zwdaemonv1.AddFileResponse{}) + } + return s.addFile(stream) +} + +func startTestServer(t *testing.T, service *testService) string { + t.Helper() + + socketPath := filepath.Join(t.TempDir(), "daemon.sock") + listener, err := net.Listen("unix", socketPath) + if err != nil { + t.Fatalf("listen on Unix socket: %v", err) + } + + server := grpc.NewServer() + zwdaemonv1.RegisterZwDaemonServiceServer(server, service) + + serveErr := make(chan error, 1) + go func() { + serveErr <- server.Serve(listener) + }() + + t.Cleanup(func() { + server.Stop() + if err := <-serveErr; err != nil { + t.Errorf("serve gRPC test server: %v", err) + } + }) + + return socketPath +} + +func connectTestClient(t *testing.T, socketPath string) (*Client, error) { + t.Helper() + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + return Connect(ctx, socketPath) +} + +func startConnectedTestClient(t *testing.T, service *testService) *Client { + t.Helper() + + service.response = &zwdaemonv1.GetServerInfoResponse{ApiMajor: supportedAPIMajor} + client, err := connectTestClient(t, startTestServer(t, service)) + if err != nil { + t.Fatalf("Connect() error = %v", err) + } + t.Cleanup(func() { _ = client.Close() }) + return client +} + +func TestConnectAcceptsSupportedMajorAndMinorDifferences(t *testing.T) { + for _, minor := range []uint32{0, 99} { + t.Run(fmt.Sprintf("minor_%d", minor), func(t *testing.T) { + socketPath := startTestServer(t, &testService{ + response: &zwdaemonv1.GetServerInfoResponse{ + ApiMajor: supportedAPIMajor, + ApiMinor: minor, + DaemonVersion: "test-version", + }, + }) + + client, err := connectTestClient(t, socketPath) + if err != nil { + t.Fatalf("Connect() error = %v", err) + } + t.Cleanup(func() { _ = client.Close() }) + }) + } +} + +func TestConnectRejectsUnsupportedMajor(t *testing.T) { + socketPath := startTestServer(t, &testService{ + response: &zwdaemonv1.GetServerInfoResponse{ + ApiMajor: 2, + ApiMinor: 3, + }, + }) + + client, err := connectTestClient(t, socketPath) + if client != nil { + _ = client.Close() + t.Fatal("Connect() returned a client for an unsupported API major") + } + + var versionErr *IncompatibleAPIVersionError + if !errors.As(err, &versionErr) { + t.Fatalf("Connect() error = %T %v, want *IncompatibleAPIVersionError", err, err) + } + if versionErr.ServerMajor != 2 || versionErr.ServerMinor != 3 || versionErr.SupportedMajor != 1 { + t.Fatalf("version error = %#v", versionErr) + } +} + +func TestServerInfoMapsResponse(t *testing.T) { + socketPath := startTestServer(t, &testService{ + response: &zwdaemonv1.GetServerInfoResponse{ + ApiMajor: 1, + ApiMinor: 7, + DaemonVersion: "1.2.3-test", + }, + }) + + client, err := connectTestClient(t, socketPath) + if err != nil { + t.Fatalf("Connect() error = %v", err) + } + t.Cleanup(func() { _ = client.Close() }) + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + info, err := client.ServerInfo(ctx) + if err != nil { + t.Fatalf("ServerInfo() error = %v", err) + } + + want := ServerInfo{APIMajor: 1, APIMinor: 7, DaemonVersion: "1.2.3-test"} + if info != want { + t.Fatalf("ServerInfo() = %#v, want %#v", info, want) + } +} + +func TestConnectPreservesStructuredRPCError(t *testing.T) { + serverStatus, err := status.New(codes.FailedPrecondition, "vault is sealed").WithDetails( + &zwdaemonv1.ZwErrorDetail{ + Code: zwdaemonv1.ZwErrorCode_ZW_ERROR_CODE_VAULT_SEALED, + Retryable: true, + }, + ) + if err != nil { + t.Fatalf("create structured status: %v", err) + } + socketPath := startTestServer(t, &testService{err: serverStatus.Err()}) + + _, err = connectTestClient(t, socketPath) + rpcErr := requireRPCError(t, err) + + if rpcErr.GRPCCode != codes.FailedPrecondition { + t.Errorf("GRPCCode = %v, want %v", rpcErr.GRPCCode, codes.FailedPrecondition) + } + if rpcErr.ZwCode == nil || *rpcErr.ZwCode != ErrorCodeVaultSealed { + t.Errorf("ZwCode = %v, want %v", rpcErr.ZwCode, ErrorCodeVaultSealed) + } + if rpcErr.Message != "vault is sealed" { + t.Errorf("Message = %q, want %q", rpcErr.Message, "vault is sealed") + } + if !rpcErr.Retryable { + t.Error("Retryable = false, want true") + } + if got := status.Code(err); got != codes.FailedPrecondition { + t.Errorf("status.Code(error) = %v, want %v", got, codes.FailedPrecondition) + } +} + +func TestConnectPreservesUnknownZwErrorCode(t *testing.T) { + const unknownCode zwdaemonv1.ZwErrorCode = 999 + serverStatus, err := status.New(codes.Internal, "future daemon error").WithDetails( + &zwdaemonv1.ZwErrorDetail{Code: unknownCode}, + ) + if err != nil { + t.Fatalf("create structured status: %v", err) + } + socketPath := startTestServer(t, &testService{err: serverStatus.Err()}) + + _, err = connectTestClient(t, socketPath) + rpcErr := requireRPCError(t, err) + if rpcErr.ZwCode == nil || *rpcErr.ZwCode != unknownCode { + t.Fatalf("ZwCode = %v, want numeric value %d", rpcErr.ZwCode, unknownCode) + } +} + +func TestConnectHandlesStatusWithoutZwDetail(t *testing.T) { + socketPath := startTestServer(t, &testService{ + err: status.Error(codes.Unavailable, "daemon unavailable"), + }) + + _, err := connectTestClient(t, socketPath) + rpcErr := requireRPCError(t, err) + if rpcErr.ZwCode != nil { + t.Errorf("ZwCode = %v, want nil", rpcErr.ZwCode) + } + if rpcErr.Retryable { + t.Error("Retryable = true without ZwErrorDetail") + } +} + +func TestConnectIgnoresMalformedZwErrorDetail(t *testing.T) { + serverErr := statusWithRawDetail( + codes.Internal, + "malformed detail", + testZwErrorDetailTypeURL, + []byte{0xff}, + ) + socketPath := startTestServer(t, &testService{err: serverErr}) + + _, err := connectTestClient(t, socketPath) + rpcErr := requireRPCError(t, err) + if rpcErr.ZwCode != nil { + t.Errorf("ZwCode = %v, want nil", rpcErr.ZwCode) + } + if rpcErr.GRPCCode != codes.Internal || rpcErr.Message != "malformed detail" { + t.Errorf("base status was not preserved: %#v", rpcErr) + } +} + +func TestConnectRequiresExactZwErrorDetailTypeURL(t *testing.T) { + encoded, err := proto.Marshal(&zwdaemonv1.ZwErrorDetail{ + Code: zwdaemonv1.ZwErrorCode_ZW_ERROR_CODE_VAULT_SEALED, + Retryable: true, + }) + if err != nil { + t.Fatalf("marshal ZwErrorDetail: %v", err) + } + serverErr := statusWithRawDetail( + codes.FailedPrecondition, + "wrong type URL prefix", + "https://example.invalid/zw.daemon.v1.ZwErrorDetail", + encoded, + ) + socketPath := startTestServer(t, &testService{err: serverErr}) + + _, err = connectTestClient(t, socketPath) + rpcErr := requireRPCError(t, err) + if rpcErr.ZwCode != nil { + t.Errorf("ZwCode = %v for non-canonical type URL, want nil", rpcErr.ZwCode) + } + if rpcErr.Retryable { + t.Error("Retryable = true for non-canonical type URL") + } +} + +func TestCreateAndUnsealMapRequests(t *testing.T) { + service := &testService{ + createRequests: make(chan *zwdaemonv1.CreateRequest, 1), + unsealRequests: make(chan *zwdaemonv1.UnsealRequest, 1), + } + client := startConnectedTestClient(t, service) + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + if err := client.Create(ctx, "/vaults/new.zw", "create-password"); err != nil { + t.Fatalf("Create() error = %v", err) + } + createRequest := <-service.createRequests + if createRequest.GetVaultPath() != "/vaults/new.zw" { + t.Errorf("Create vault path = %q", createRequest.GetVaultPath()) + } + if createRequest.GetPassword() != "create-password" { + t.Errorf("Create password = %q", createRequest.GetPassword()) + } + + if err := client.Unseal(ctx, "/vaults/existing.zw", "unseal-password"); err != nil { + t.Fatalf("Unseal() error = %v", err) + } + unsealRequest := <-service.unsealRequests + if unsealRequest.GetVaultPath() != "/vaults/existing.zw" { + t.Errorf("Unseal vault path = %q", unsealRequest.GetVaultPath()) + } + if unsealRequest.GetPassword() != "unseal-password" { + t.Errorf("Unseal password = %q", unsealRequest.GetPassword()) + } +} + +func TestSealAndCompactCallDaemon(t *testing.T) { + service := &testService{ + sealCalls: make(chan struct{}, 1), + compactCalls: make(chan struct{}, 1), + } + client := startConnectedTestClient(t, service) + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + if err := client.Seal(ctx); err != nil { + t.Fatalf("Seal() error = %v", err) + } + <-service.sealCalls + + if err := client.Compact(ctx); err != nil { + t.Fatalf("Compact() error = %v", err) + } + <-service.compactCalls +} + +func TestListFilesMapsFilterAndPreservesResponseOrder(t *testing.T) { + service := &testService{ + listFilesRequests: make(chan *zwdaemonv1.ListFilesRequest, 1), + listFilesResponse: &zwdaemonv1.ListFilesResponse{ + Files: []*zwdaemonv1.ListedFile{ + {LogicalPath: "logs/second.txt", Size: 22}, + {LogicalPath: "logs/first.txt", Size: 11}, + }, + }, + } + client := startConnectedTestClient(t, service) + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + files, err := client.ListFiles(ctx, ListFilter{Prefix: "logs/", Contains: "txt"}) + if err != nil { + t.Fatalf("ListFiles() error = %v", err) + } + + request := <-service.listFilesRequests + if request.Prefix == nil || request.GetPrefix() != "logs/" { + t.Errorf("ListFiles prefix = %v", request.Prefix) + } + if request.Contains == nil || request.GetContains() != "txt" { + t.Errorf("ListFiles contains = %v", request.Contains) + } + + want := []ListedFile{ + {LogicalPath: "logs/second.txt", Size: 22}, + {LogicalPath: "logs/first.txt", Size: 11}, + } + if len(files) != len(want) { + t.Fatalf("ListFiles() returned %d files, want %d", len(files), len(want)) + } + for index := range want { + if files[index] != want[index] { + t.Errorf("ListFiles()[%d] = %#v, want %#v", index, files[index], want[index]) + } + } +} + +func TestListPathsOmitsEmptyFiltersAndMapsPaths(t *testing.T) { + service := &testService{ + listFilesRequests: make(chan *zwdaemonv1.ListFilesRequest, 1), + listFilesResponse: &zwdaemonv1.ListFilesResponse{ + Files: []*zwdaemonv1.ListedFile{ + {LogicalPath: "first", Size: 10}, + {LogicalPath: "second", Size: 20}, + }, + }, + } + client := startConnectedTestClient(t, service) + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + paths, err := client.ListPaths(ctx) + if err != nil { + t.Fatalf("ListPaths() error = %v", err) + } + + request := <-service.listFilesRequests + if request.Prefix != nil || request.Contains != nil { + t.Errorf("ListPaths request filters = prefix %v, contains %v; want both absent", request.Prefix, request.Contains) + } + want := []string{"first", "second"} + if len(paths) != len(want) { + t.Fatalf("ListPaths() returned %d paths, want %d", len(paths), len(want)) + } + for index := range want { + if paths[index] != want[index] { + t.Errorf("ListPaths()[%d] = %q, want %q", index, paths[index], want[index]) + } + } +} + +func TestDeleteFileMapsRequestAndStructuredError(t *testing.T) { + serverStatus, err := status.New(codes.NotFound, "entry not found").WithDetails( + &zwdaemonv1.ZwErrorDetail{ + Code: zwdaemonv1.ZwErrorCode_ZW_ERROR_CODE_ENTRY_NOT_FOUND, + }, + ) + if err != nil { + t.Fatalf("create structured status: %v", err) + } + service := &testService{ + deleteFileRequests: make(chan *zwdaemonv1.DeleteFileRequest, 1), + deleteFileErr: serverStatus.Err(), + } + client := startConnectedTestClient(t, service) + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + err = client.DeleteFile(ctx, "missing.txt") + request := <-service.deleteFileRequests + if request.GetLogicalPath() != "missing.txt" { + t.Errorf("DeleteFile logical path = %q", request.GetLogicalPath()) + } + + rpcErr := requireRPCError(t, err) + if rpcErr.GRPCCode != codes.NotFound { + t.Errorf("GRPCCode = %v, want %v", rpcErr.GRPCCode, codes.NotFound) + } + if rpcErr.ZwCode == nil || *rpcErr.ZwCode != ErrorCodeEntryNotFound { + t.Errorf("ZwCode = %v, want %v", rpcErr.ZwCode, ErrorCodeEntryNotFound) + } +} + +func TestConvertRPCErrorAcceptsNil(t *testing.T) { + if err := convertRPCError(nil); err != nil { + t.Fatalf("convertRPCError(nil) = %v", err) + } +} + +func TestGetFileReadsChunksAcrossBuffersAndSkipsEmptyChunks(t *testing.T) { + requests := make(chan *zwdaemonv1.GetFileRequest, 1) + service := &testService{ + getFile: func( + request *zwdaemonv1.GetFileRequest, + stream grpc.ServerStreamingServer[zwdaemonv1.GetFileResponse], + ) error { + requests <- request + for _, chunk := range [][]byte{[]byte("abc"), nil, []byte("defgh")} { + if err := stream.Send(&zwdaemonv1.GetFileResponse{Data: chunk}); err != nil { + return err + } + } + return nil + }, + } + client := startConnectedTestClient(t, service) + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + reader, err := client.GetFile(ctx, "folder/file.bin") + if err != nil { + t.Fatalf("GetFile() error = %v", err) + } + t.Cleanup(func() { _ = reader.Close() }) + + request := <-requests + if request.GetLogicalPath() != "folder/file.bin" { + t.Errorf("GetFile logical path = %q", request.GetLogicalPath()) + } + + buffer := make([]byte, 2) + var contents []byte + for { + n, err := reader.Read(buffer) + contents = append(contents, buffer[:n]...) + if err == io.EOF { + break + } + if err != nil { + t.Fatalf("Read() error = %v", err) + } + if n == 0 { + t.Fatal("Read() returned no bytes and no error") + } + } + if got, want := string(contents), "abcdefgh"; got != want { + t.Fatalf("download contents = %q, want %q", got, want) + } +} + +func TestGetFileRangeMapsRequestAndReadsResponse(t *testing.T) { + requests := make(chan *zwdaemonv1.GetFileRangeRequest, 1) + service := &testService{ + getFileRange: func( + request *zwdaemonv1.GetFileRangeRequest, + stream grpc.ServerStreamingServer[zwdaemonv1.GetFileRangeResponse], + ) error { + requests <- request + return stream.Send(&zwdaemonv1.GetFileRangeResponse{Data: []byte("range")}) + }, + } + client := startConnectedTestClient(t, service) + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + reader, err := client.GetFileRange(ctx, "large.bin", 10, 15) + if err != nil { + t.Fatalf("GetFileRange() error = %v", err) + } + t.Cleanup(func() { _ = reader.Close() }) + + contents, err := io.ReadAll(reader) + if err != nil { + t.Fatalf("read range: %v", err) + } + if got, want := string(contents), "range"; got != want { + t.Fatalf("range contents = %q, want %q", got, want) + } + + request := <-requests + if request.GetLogicalPath() != "large.bin" || request.GetStart() != 10 || request.GetExclusiveEnd() != 15 { + t.Fatalf("GetFileRange request = %#v", request) + } +} + +func TestGetFileReturnsTerminalStructuredErrorAfterReceivedData(t *testing.T) { + serverStatus, err := status.New(codes.DataLoss, "download failed").WithDetails( + &zwdaemonv1.ZwErrorDetail{ + Code: zwdaemonv1.ZwErrorCode_ZW_ERROR_CODE_INTERNAL, + Retryable: true, + }, + ) + if err != nil { + t.Fatalf("create structured status: %v", err) + } + service := &testService{ + getFile: func( + _ *zwdaemonv1.GetFileRequest, + stream grpc.ServerStreamingServer[zwdaemonv1.GetFileResponse], + ) error { + if err := stream.Send(&zwdaemonv1.GetFileResponse{Data: []byte("partial")}); err != nil { + return err + } + return serverStatus.Err() + }, + } + client := startConnectedTestClient(t, service) + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + reader, err := client.GetFile(ctx, "damaged.bin") + if err != nil { + t.Fatalf("GetFile() error = %v", err) + } + t.Cleanup(func() { _ = reader.Close() }) + + buffer := make([]byte, 32) + n, err := reader.Read(buffer) + if err != nil { + t.Fatalf("first Read() error = %v", err) + } + if got, want := string(buffer[:n]), "partial"; got != want { + t.Fatalf("first Read() = %q, want %q", got, want) + } + + n, err = reader.Read(buffer) + if n != 0 { + t.Errorf("terminal Read() returned %d bytes", n) + } + rpcErr := requireRPCError(t, err) + if rpcErr.GRPCCode != codes.DataLoss { + t.Errorf("GRPCCode = %v, want %v", rpcErr.GRPCCode, codes.DataLoss) + } + if rpcErr.ZwCode == nil || *rpcErr.ZwCode != ErrorCodeInternal { + t.Errorf("ZwCode = %v, want %v", rpcErr.ZwCode, ErrorCodeInternal) + } + if rpcErr.Message != "download failed" || !rpcErr.Retryable { + t.Errorf("terminal RPC error = %#v", rpcErr) + } + + infoCtx, infoCancel := context.WithTimeout(context.Background(), 5*time.Second) + defer infoCancel() + if _, err := client.ServerInfo(infoCtx); err != nil { + t.Fatalf("ServerInfo() after failed download = %v", err) + } +} + +func TestClosingDownloadCancelsStreamAndKeepsClientReusable(t *testing.T) { + started := make(chan struct{}, 1) + canceled := make(chan struct{}, 1) + service := &testService{ + getFile: func( + _ *zwdaemonv1.GetFileRequest, + stream grpc.ServerStreamingServer[zwdaemonv1.GetFileResponse], + ) error { + started <- struct{}{} + <-stream.Context().Done() + canceled <- struct{}{} + return stream.Context().Err() + }, + } + client := startConnectedTestClient(t, service) + + reader, err := client.GetFile(context.Background(), "abandoned.bin") + if err != nil { + t.Fatalf("GetFile() error = %v", err) + } + select { + case <-started: + case <-time.After(5 * time.Second): + t.Fatal("server did not start download") + } + + if err := reader.Close(); err != nil { + t.Fatalf("Close() error = %v", err) + } + if err := reader.Close(); err != nil { + t.Fatalf("second Close() error = %v", err) + } + if _, err := reader.Read(make([]byte, 1)); !errors.Is(err, fs.ErrClosed) { + t.Fatalf("Read() after Close() error = %v, want fs.ErrClosed", err) + } + + select { + case <-canceled: + case <-time.After(5 * time.Second): + t.Fatal("closing reader did not cancel server stream") + } + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + if _, err := client.ServerInfo(ctx); err != nil { + t.Fatalf("ServerInfo() after closing download = %v", err) + } +} + +func TestAddFileSendsHeaderBeforeEmptyAndMultiChunkBodies(t *testing.T) { + tests := []struct { + name string + contents []byte + chunkSizes []int + }{ + {name: "empty"}, + { + name: "multiple_chunks", + contents: bytes.Repeat([]byte("x"), 512*1024+137), + chunkSizes: []int{512 * 1024, 137}, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + received := make(chan receivedUpload, 1) + service := &testService{ + addFile: func( + stream grpc.ClientStreamingServer[zwdaemonv1.AddFileRequest, zwdaemonv1.AddFileResponse], + ) error { + upload, err := receiveUpload(stream) + if err != nil { + return err + } + received <- upload + return stream.SendAndClose(&zwdaemonv1.AddFileResponse{}) + }, + } + client := startConnectedTestClient(t, service) + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + err := client.AddFile(ctx, "upload.bin", bytes.NewReader(test.contents), uint64(len(test.contents))) + if err != nil { + t.Fatalf("AddFile() error = %v", err) + } + + upload := <-received + if upload.header.GetLogicalPath() != "upload.bin" { + t.Errorf("logical path = %q", upload.header.GetLogicalPath()) + } + if upload.header.GetSourceLen() != uint64(len(test.contents)) { + t.Errorf("source length = %d", upload.header.GetSourceLen()) + } + if !bytes.Equal(upload.contents, test.contents) { + t.Errorf("uploaded contents differ") + } + if len(upload.chunkSizes) != len(test.chunkSizes) { + t.Fatalf("chunk sizes = %v, want %v", upload.chunkSizes, test.chunkSizes) + } + for index := range test.chunkSizes { + if upload.chunkSizes[index] != test.chunkSizes[index] { + t.Errorf("chunk sizes = %v, want %v", upload.chunkSizes, test.chunkSizes) + } + } + }) + } +} + +func TestAddFileProcessesDataReturnedWithEOF(t *testing.T) { + received := make(chan receivedUpload, 1) + service := &testService{ + addFile: func( + stream grpc.ClientStreamingServer[zwdaemonv1.AddFileRequest, zwdaemonv1.AddFileResponse], + ) error { + upload, err := receiveUpload(stream) + if err != nil { + return err + } + received <- upload + return stream.SendAndClose(&zwdaemonv1.AddFileResponse{}) + }, + } + client := startConnectedTestClient(t, service) + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + err := client.AddFile(ctx, "combined.bin", &dataAndEOFReader{data: []byte("contents")}, 8) + if err != nil { + t.Fatalf("AddFile() error = %v", err) + } + upload := <-received + if got, want := string(upload.contents), "contents"; got != want { + t.Fatalf("uploaded contents = %q, want %q", got, want) + } +} + +func TestAddFileReturnsLengthRejectionFromCloseAndRecv(t *testing.T) { + serverStatus, err := status.New(codes.InvalidArgument, "declared length does not match source").WithDetails( + &zwdaemonv1.ZwErrorDetail{ + Code: zwdaemonv1.ZwErrorCode_ZW_ERROR_CODE_INVALID_REQUEST, + }, + ) + if err != nil { + t.Fatalf("create structured status: %v", err) + } + service := &testService{ + addFile: func( + stream grpc.ClientStreamingServer[zwdaemonv1.AddFileRequest, zwdaemonv1.AddFileResponse], + ) error { + if _, err := receiveUpload(stream); err != nil { + return err + } + return serverStatus.Err() + }, + } + client := startConnectedTestClient(t, service) + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + err = client.AddFile(ctx, "short.bin", bytes.NewReader([]byte("abc")), 4) + rpcErr := requireRPCError(t, err) + if rpcErr.GRPCCode != codes.InvalidArgument { + t.Errorf("GRPCCode = %v, want %v", rpcErr.GRPCCode, codes.InvalidArgument) + } + if rpcErr.ZwCode == nil || *rpcErr.ZwCode != ErrorCodeInvalidRequest { + t.Errorf("ZwCode = %v, want %v", rpcErr.ZwCode, ErrorCodeInvalidRequest) + } +} + +func TestUploadReadFailureCancelsRPCAndConnectionAndPathRemainReusable(t *testing.T) { + injectedErr := errors.New("injected source error") + firstStreamErr := make(chan error, 1) + headers := make(chan *zwdaemonv1.AddFileHeader, 2) + var calls atomic.Int32 + + service := &testService{ + addFile: func( + stream grpc.ClientStreamingServer[zwdaemonv1.AddFileRequest, zwdaemonv1.AddFileResponse], + ) error { + call := calls.Add(1) + if call == 1 { + first, err := stream.Recv() + if err != nil { + firstStreamErr <- err + return err + } + headers <- first.GetHeader() + + for { + _, err := stream.Recv() + if err != nil { + firstStreamErr <- err + return err + } + } + } + + upload, err := receiveUpload(stream) + if err != nil { + return err + } + headers <- upload.header + return stream.SendAndClose(&zwdaemonv1.AddFileResponse{}) + }, + } + client := startConnectedTestClient(t, service) + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + err := client.AddFile(ctx, "reusable.bin", &dataAndErrorReader{ + data: []byte("partial"), + err: injectedErr, + }, 7) + var readErr *UploadReadError + if !errors.As(err, &readErr) { + t.Fatalf("AddFile() error = %T %v, want *UploadReadError", err, err) + } + if !errors.Is(err, injectedErr) { + t.Fatalf("AddFile() error does not wrap source error: %v", err) + } + + select { + case err := <-firstStreamErr: + if errors.Is(err, io.EOF) { + t.Fatal("reader failure cleanly closed the upload stream") + } + if !errors.Is(err, context.Canceled) && status.Code(err) != codes.Canceled { + t.Fatalf("server stream error = %v, want cancellation", err) + } + case <-time.After(5 * time.Second): + t.Fatal("server did not observe upload cancellation") + } + + infoCtx, infoCancel := context.WithTimeout(context.Background(), 5*time.Second) + defer infoCancel() + if _, err := client.ServerInfo(infoCtx); err != nil { + t.Fatalf("ServerInfo() after reader failure = %v", err) + } + + if err := client.AddFile(ctx, "reusable.bin", bytes.NewReader([]byte("replacement")), 11); err != nil { + t.Fatalf("second AddFile() on same path = %v", err) + } + for index := 0; index < 2; index++ { + header := <-headers + if header == nil || header.GetLogicalPath() != "reusable.bin" { + t.Fatalf("upload header = %#v", header) + } + } +} + +type receivedUpload struct { + header *zwdaemonv1.AddFileHeader + contents []byte + chunkSizes []int +} + +func receiveUpload( + stream grpc.ClientStreamingServer[zwdaemonv1.AddFileRequest, zwdaemonv1.AddFileResponse], +) (receivedUpload, error) { + first, err := stream.Recv() + if err != nil { + return receivedUpload{}, err + } + header := first.GetHeader() + if header == nil { + return receivedUpload{}, status.Error(codes.InvalidArgument, "first upload message is not a header") + } + + upload := receivedUpload{header: header} + for { + request, err := stream.Recv() + if err == io.EOF { + return upload, nil + } + if err != nil { + return upload, err + } + payload, ok := request.GetPayload().(*zwdaemonv1.AddFileRequest_Chunk) + if !ok { + return upload, status.Error(codes.InvalidArgument, "upload message after header is not a chunk") + } + upload.contents = append(upload.contents, payload.Chunk...) + upload.chunkSizes = append(upload.chunkSizes, len(payload.Chunk)) + } +} + +type dataAndEOFReader struct { + data []byte + done bool +} + +func (r *dataAndEOFReader) Read(destination []byte) (int, error) { + if r.done { + return 0, io.EOF + } + r.done = true + return copy(destination, r.data), io.EOF +} + +type dataAndErrorReader struct { + data []byte + err error + done bool +} + +func (r *dataAndErrorReader) Read(destination []byte) (int, error) { + if r.done { + return 0, r.err + } + r.done = true + return copy(destination, r.data), r.err +} + +func requireRPCError(t *testing.T, err error) *RPCError { + t.Helper() + + var rpcErr *RPCError + if !errors.As(err, &rpcErr) { + t.Fatalf("error = %T %v, want *RPCError", err, err) + } + return rpcErr +} + +func statusWithRawDetail(code codes.Code, message, typeURL string, value []byte) error { + statusProto := status.New(code, message).Proto() + statusProto.Details = append(statusProto.Details, &anypb.Any{ + TypeUrl: typeURL, + Value: value, + }) + return status.FromProto(statusProto).Err() +} diff --git a/download.go b/download.go new file mode 100644 index 0000000..19dd1b2 --- /dev/null +++ b/download.go @@ -0,0 +1,71 @@ +package zw + +import ( + "context" + "io" + "io/fs" + "sync" + "sync/atomic" +) + +type downloadReader struct { + recv func() ([]byte, error) + cancel context.CancelFunc + + pending []byte + terminal error + + cancelOnce sync.Once + closed atomic.Bool +} + +func (r *downloadReader) Read(destination []byte) (int, error) { + if len(destination) == 0 { + return 0, nil + } + + if r.closed.Load() { + return 0, fs.ErrClosed + } + + if len(r.pending) > 0 { + n := copy(destination, r.pending) + r.pending = r.pending[n:] + return n, nil + } + + if r.terminal != nil { + return 0, r.terminal + } + + for { + chunk, err := r.recv() + if err != nil { + if r.closed.Load() { + return 0, fs.ErrClosed + } + + if err == io.EOF { + r.terminal = io.EOF + } else { + r.terminal = convertRPCError(err) + } + r.cancelOnce.Do(r.cancel) + return 0, r.terminal + } + + if len(chunk) == 0 { + continue + } + + n := copy(destination, chunk) + r.pending = chunk[n:] + return n, nil + } +} + +func (r *downloadReader) Close() error { + r.closed.Store(true) + r.cancelOnce.Do(r.cancel) + return nil +} diff --git a/errors.go b/errors.go new file mode 100644 index 0000000..d308853 --- /dev/null +++ b/errors.go @@ -0,0 +1,112 @@ +package zw + +import ( + "fmt" + + zwdaemonv1 "git.pablu.de/pablu/zw-go/gen/zwdaemon/v1" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +const zwErrorDetailTypeURL = "type.googleapis.com/zw.daemon.v1.ZwErrorDetail" + +type ErrorCode = zwdaemonv1.ZwErrorCode + +const ( + ErrorCodeUnspecified = zwdaemonv1.ZwErrorCode_ZW_ERROR_CODE_UNSPECIFIED + ErrorCodeVaultSealed = zwdaemonv1.ZwErrorCode_ZW_ERROR_CODE_VAULT_SEALED + ErrorCodeVaultAlreadyUnsealed = zwdaemonv1.ZwErrorCode_ZW_ERROR_CODE_VAULT_ALREADY_UNSEALED + ErrorCodeEntryNotFound = zwdaemonv1.ZwErrorCode_ZW_ERROR_CODE_ENTRY_NOT_FOUND + ErrorCodeEntryAlreadyExists = zwdaemonv1.ZwErrorCode_ZW_ERROR_CODE_ENTRY_ALREADY_EXISTS + ErrorCodeAuthenticationOrCorruption = zwdaemonv1.ZwErrorCode_ZW_ERROR_CODE_AUTHENTICATION_OR_CORRUPTION + ErrorCodeInvalidVaultFormat = zwdaemonv1.ZwErrorCode_ZW_ERROR_CODE_INVALID_VAULT_FORMAT + ErrorCodeUnsupportedVaultVersion = zwdaemonv1.ZwErrorCode_ZW_ERROR_CODE_UNSUPPORTED_VAULT_VERSION + ErrorCodeUnsupportedProtocolVersion = zwdaemonv1.ZwErrorCode_ZW_ERROR_CODE_UNSUPPORTED_PROTOCOL_VERSION + ErrorCodePermissionDenied = zwdaemonv1.ZwErrorCode_ZW_ERROR_CODE_PERMISSION_DENIED + ErrorCodeStorageFull = zwdaemonv1.ZwErrorCode_ZW_ERROR_CODE_STORAGE_FULL + ErrorCodeCommitFailed = zwdaemonv1.ZwErrorCode_ZW_ERROR_CODE_COMMIT_FAILED + ErrorCodeInvalidRequest = zwdaemonv1.ZwErrorCode_ZW_ERROR_CODE_INVALID_REQUEST + ErrorCodeInternal = zwdaemonv1.ZwErrorCode_ZW_ERROR_CODE_INTERNAL +) + +type RPCError struct { + GRPCCode codes.Code + ZwCode *ErrorCode + Message string + Retryable bool + + status *status.Status +} + +func (e *RPCError) Error() string { + return e.Message +} + +func (e *RPCError) GRPCStatus() *status.Status { + if e.status != nil { + return e.status + } + return status.New(e.GRPCCode, e.Message) +} + +type IncompatibleAPIVersionError struct { + ServerMajor uint32 + ServerMinor uint32 + SupportedMajor uint32 +} + +func (e *IncompatibleAPIVersionError) Error() string { + return fmt.Sprintf( + "daemon API version %d.%d is incompatible; this client supports major version %d", + e.ServerMajor, + e.ServerMinor, + e.SupportedMajor, + ) +} + +type UploadReadError struct { + Err error +} + +func (e *UploadReadError) Error() string { + return "read upload source: " + e.Err.Error() +} + +func (e *UploadReadError) Unwrap() error { + return e.Err +} + +func convertRPCError(err error) error { + if err == nil { + return nil + } + + grpcStatus, ok := status.FromError(err) + if !ok { + return err + } + + rpcErr := &RPCError{ + GRPCCode: grpcStatus.Code(), + Message: grpcStatus.Message(), + status: grpcStatus, + } + + for _, detail := range grpcStatus.Proto().GetDetails() { + if detail.GetTypeUrl() != zwErrorDetailTypeURL { + continue + } + + var zwDetail zwdaemonv1.ZwErrorDetail + if err := detail.UnmarshalTo(&zwDetail); err != nil { + continue + } + + code := zwDetail.GetCode() + rpcErr.ZwCode = &code + rpcErr.Retryable = zwDetail.GetRetryable() + break + } + + return rpcErr +} diff --git a/gen/zwdaemon/v1/daemon.pb.go b/gen/zwdaemon/v1/daemon.pb.go new file mode 100644 index 0000000..68fb3c3 --- /dev/null +++ b/gen/zwdaemon/v1/daemon.pb.go @@ -0,0 +1,1352 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: zw/daemon/v1/daemon.proto + +package zwdaemonv1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type ZwErrorCode int32 + +const ( + ZwErrorCode_ZW_ERROR_CODE_UNSPECIFIED ZwErrorCode = 0 + ZwErrorCode_ZW_ERROR_CODE_VAULT_SEALED ZwErrorCode = 1 + ZwErrorCode_ZW_ERROR_CODE_VAULT_ALREADY_UNSEALED ZwErrorCode = 2 + ZwErrorCode_ZW_ERROR_CODE_ENTRY_NOT_FOUND ZwErrorCode = 3 + ZwErrorCode_ZW_ERROR_CODE_ENTRY_ALREADY_EXISTS ZwErrorCode = 4 + ZwErrorCode_ZW_ERROR_CODE_AUTHENTICATION_OR_CORRUPTION ZwErrorCode = 5 + ZwErrorCode_ZW_ERROR_CODE_INVALID_VAULT_FORMAT ZwErrorCode = 6 + ZwErrorCode_ZW_ERROR_CODE_UNSUPPORTED_VAULT_VERSION ZwErrorCode = 7 + ZwErrorCode_ZW_ERROR_CODE_UNSUPPORTED_PROTOCOL_VERSION ZwErrorCode = 8 + ZwErrorCode_ZW_ERROR_CODE_PERMISSION_DENIED ZwErrorCode = 9 + ZwErrorCode_ZW_ERROR_CODE_STORAGE_FULL ZwErrorCode = 10 + ZwErrorCode_ZW_ERROR_CODE_COMMIT_FAILED ZwErrorCode = 11 + ZwErrorCode_ZW_ERROR_CODE_INVALID_REQUEST ZwErrorCode = 12 + ZwErrorCode_ZW_ERROR_CODE_INTERNAL ZwErrorCode = 13 +) + +// Enum value maps for ZwErrorCode. +var ( + ZwErrorCode_name = map[int32]string{ + 0: "ZW_ERROR_CODE_UNSPECIFIED", + 1: "ZW_ERROR_CODE_VAULT_SEALED", + 2: "ZW_ERROR_CODE_VAULT_ALREADY_UNSEALED", + 3: "ZW_ERROR_CODE_ENTRY_NOT_FOUND", + 4: "ZW_ERROR_CODE_ENTRY_ALREADY_EXISTS", + 5: "ZW_ERROR_CODE_AUTHENTICATION_OR_CORRUPTION", + 6: "ZW_ERROR_CODE_INVALID_VAULT_FORMAT", + 7: "ZW_ERROR_CODE_UNSUPPORTED_VAULT_VERSION", + 8: "ZW_ERROR_CODE_UNSUPPORTED_PROTOCOL_VERSION", + 9: "ZW_ERROR_CODE_PERMISSION_DENIED", + 10: "ZW_ERROR_CODE_STORAGE_FULL", + 11: "ZW_ERROR_CODE_COMMIT_FAILED", + 12: "ZW_ERROR_CODE_INVALID_REQUEST", + 13: "ZW_ERROR_CODE_INTERNAL", + } + ZwErrorCode_value = map[string]int32{ + "ZW_ERROR_CODE_UNSPECIFIED": 0, + "ZW_ERROR_CODE_VAULT_SEALED": 1, + "ZW_ERROR_CODE_VAULT_ALREADY_UNSEALED": 2, + "ZW_ERROR_CODE_ENTRY_NOT_FOUND": 3, + "ZW_ERROR_CODE_ENTRY_ALREADY_EXISTS": 4, + "ZW_ERROR_CODE_AUTHENTICATION_OR_CORRUPTION": 5, + "ZW_ERROR_CODE_INVALID_VAULT_FORMAT": 6, + "ZW_ERROR_CODE_UNSUPPORTED_VAULT_VERSION": 7, + "ZW_ERROR_CODE_UNSUPPORTED_PROTOCOL_VERSION": 8, + "ZW_ERROR_CODE_PERMISSION_DENIED": 9, + "ZW_ERROR_CODE_STORAGE_FULL": 10, + "ZW_ERROR_CODE_COMMIT_FAILED": 11, + "ZW_ERROR_CODE_INVALID_REQUEST": 12, + "ZW_ERROR_CODE_INTERNAL": 13, + } +) + +func (x ZwErrorCode) Enum() *ZwErrorCode { + p := new(ZwErrorCode) + *p = x + return p +} + +func (x ZwErrorCode) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ZwErrorCode) Descriptor() protoreflect.EnumDescriptor { + return file_zw_daemon_v1_daemon_proto_enumTypes[0].Descriptor() +} + +func (ZwErrorCode) Type() protoreflect.EnumType { + return &file_zw_daemon_v1_daemon_proto_enumTypes[0] +} + +func (x ZwErrorCode) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ZwErrorCode.Descriptor instead. +func (ZwErrorCode) EnumDescriptor() ([]byte, []int) { + return file_zw_daemon_v1_daemon_proto_rawDescGZIP(), []int{0} +} + +type GetServerInfoRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetServerInfoRequest) Reset() { + *x = GetServerInfoRequest{} + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetServerInfoRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetServerInfoRequest) ProtoMessage() {} + +func (x *GetServerInfoRequest) ProtoReflect() protoreflect.Message { + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetServerInfoRequest.ProtoReflect.Descriptor instead. +func (*GetServerInfoRequest) Descriptor() ([]byte, []int) { + return file_zw_daemon_v1_daemon_proto_rawDescGZIP(), []int{0} +} + +type SealRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SealRequest) Reset() { + *x = SealRequest{} + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SealRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SealRequest) ProtoMessage() {} + +func (x *SealRequest) ProtoReflect() protoreflect.Message { + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SealRequest.ProtoReflect.Descriptor instead. +func (*SealRequest) Descriptor() ([]byte, []int) { + return file_zw_daemon_v1_daemon_proto_rawDescGZIP(), []int{1} +} + +type SealResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SealResponse) Reset() { + *x = SealResponse{} + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SealResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SealResponse) ProtoMessage() {} + +func (x *SealResponse) ProtoReflect() protoreflect.Message { + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SealResponse.ProtoReflect.Descriptor instead. +func (*SealResponse) Descriptor() ([]byte, []int) { + return file_zw_daemon_v1_daemon_proto_rawDescGZIP(), []int{2} +} + +type CreateResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateResponse) Reset() { + *x = CreateResponse{} + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateResponse) ProtoMessage() {} + +func (x *CreateResponse) ProtoReflect() protoreflect.Message { + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateResponse.ProtoReflect.Descriptor instead. +func (*CreateResponse) Descriptor() ([]byte, []int) { + return file_zw_daemon_v1_daemon_proto_rawDescGZIP(), []int{3} +} + +type UnsealResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UnsealResponse) Reset() { + *x = UnsealResponse{} + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UnsealResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UnsealResponse) ProtoMessage() {} + +func (x *UnsealResponse) ProtoReflect() protoreflect.Message { + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UnsealResponse.ProtoReflect.Descriptor instead. +func (*UnsealResponse) Descriptor() ([]byte, []int) { + return file_zw_daemon_v1_daemon_proto_rawDescGZIP(), []int{4} +} + +type CompactResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CompactResponse) Reset() { + *x = CompactResponse{} + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CompactResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CompactResponse) ProtoMessage() {} + +func (x *CompactResponse) ProtoReflect() protoreflect.Message { + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CompactResponse.ProtoReflect.Descriptor instead. +func (*CompactResponse) Descriptor() ([]byte, []int) { + return file_zw_daemon_v1_daemon_proto_rawDescGZIP(), []int{5} +} + +type CompactRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CompactRequest) Reset() { + *x = CompactRequest{} + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CompactRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CompactRequest) ProtoMessage() {} + +func (x *CompactRequest) ProtoReflect() protoreflect.Message { + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CompactRequest.ProtoReflect.Descriptor instead. +func (*CompactRequest) Descriptor() ([]byte, []int) { + return file_zw_daemon_v1_daemon_proto_rawDescGZIP(), []int{6} +} + +type AddFileResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AddFileResponse) Reset() { + *x = AddFileResponse{} + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AddFileResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddFileResponse) ProtoMessage() {} + +func (x *AddFileResponse) ProtoReflect() protoreflect.Message { + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddFileResponse.ProtoReflect.Descriptor instead. +func (*AddFileResponse) Descriptor() ([]byte, []int) { + return file_zw_daemon_v1_daemon_proto_rawDescGZIP(), []int{7} +} + +type DeleteFileResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteFileResponse) Reset() { + *x = DeleteFileResponse{} + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteFileResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteFileResponse) ProtoMessage() {} + +func (x *DeleteFileResponse) ProtoReflect() protoreflect.Message { + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteFileResponse.ProtoReflect.Descriptor instead. +func (*DeleteFileResponse) Descriptor() ([]byte, []int) { + return file_zw_daemon_v1_daemon_proto_rawDescGZIP(), []int{8} +} + +type GetServerInfoResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + ApiMajor uint32 `protobuf:"varint,1,opt,name=api_major,json=apiMajor,proto3" json:"api_major,omitempty"` + ApiMinor uint32 `protobuf:"varint,2,opt,name=api_minor,json=apiMinor,proto3" json:"api_minor,omitempty"` + DaemonVersion string `protobuf:"bytes,3,opt,name=daemon_version,json=daemonVersion,proto3" json:"daemon_version,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetServerInfoResponse) Reset() { + *x = GetServerInfoResponse{} + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetServerInfoResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetServerInfoResponse) ProtoMessage() {} + +func (x *GetServerInfoResponse) ProtoReflect() protoreflect.Message { + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetServerInfoResponse.ProtoReflect.Descriptor instead. +func (*GetServerInfoResponse) Descriptor() ([]byte, []int) { + return file_zw_daemon_v1_daemon_proto_rawDescGZIP(), []int{9} +} + +func (x *GetServerInfoResponse) GetApiMajor() uint32 { + if x != nil { + return x.ApiMajor + } + return 0 +} + +func (x *GetServerInfoResponse) GetApiMinor() uint32 { + if x != nil { + return x.ApiMinor + } + return 0 +} + +func (x *GetServerInfoResponse) GetDaemonVersion() string { + if x != nil { + return x.DaemonVersion + } + return "" +} + +type CreateRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + VaultPath string `protobuf:"bytes,1,opt,name=vault_path,json=vaultPath,proto3" json:"vault_path,omitempty"` + Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateRequest) Reset() { + *x = CreateRequest{} + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateRequest) ProtoMessage() {} + +func (x *CreateRequest) ProtoReflect() protoreflect.Message { + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateRequest.ProtoReflect.Descriptor instead. +func (*CreateRequest) Descriptor() ([]byte, []int) { + return file_zw_daemon_v1_daemon_proto_rawDescGZIP(), []int{10} +} + +func (x *CreateRequest) GetVaultPath() string { + if x != nil { + return x.VaultPath + } + return "" +} + +func (x *CreateRequest) GetPassword() string { + if x != nil { + return x.Password + } + return "" +} + +type UnsealRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + VaultPath string `protobuf:"bytes,1,opt,name=vault_path,json=vaultPath,proto3" json:"vault_path,omitempty"` + Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UnsealRequest) Reset() { + *x = UnsealRequest{} + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UnsealRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UnsealRequest) ProtoMessage() {} + +func (x *UnsealRequest) ProtoReflect() protoreflect.Message { + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[11] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UnsealRequest.ProtoReflect.Descriptor instead. +func (*UnsealRequest) Descriptor() ([]byte, []int) { + return file_zw_daemon_v1_daemon_proto_rawDescGZIP(), []int{11} +} + +func (x *UnsealRequest) GetVaultPath() string { + if x != nil { + return x.VaultPath + } + return "" +} + +func (x *UnsealRequest) GetPassword() string { + if x != nil { + return x.Password + } + return "" +} + +type ListFilesRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Prefix *string `protobuf:"bytes,1,opt,name=prefix,proto3,oneof" json:"prefix,omitempty"` + Contains *string `protobuf:"bytes,2,opt,name=contains,proto3,oneof" json:"contains,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListFilesRequest) Reset() { + *x = ListFilesRequest{} + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListFilesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListFilesRequest) ProtoMessage() {} + +func (x *ListFilesRequest) ProtoReflect() protoreflect.Message { + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[12] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListFilesRequest.ProtoReflect.Descriptor instead. +func (*ListFilesRequest) Descriptor() ([]byte, []int) { + return file_zw_daemon_v1_daemon_proto_rawDescGZIP(), []int{12} +} + +func (x *ListFilesRequest) GetPrefix() string { + if x != nil && x.Prefix != nil { + return *x.Prefix + } + return "" +} + +func (x *ListFilesRequest) GetContains() string { + if x != nil && x.Contains != nil { + return *x.Contains + } + return "" +} + +type ListFilesResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Files []*ListedFile `protobuf:"bytes,1,rep,name=files,proto3" json:"files,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListFilesResponse) Reset() { + *x = ListFilesResponse{} + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListFilesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListFilesResponse) ProtoMessage() {} + +func (x *ListFilesResponse) ProtoReflect() protoreflect.Message { + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[13] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListFilesResponse.ProtoReflect.Descriptor instead. +func (*ListFilesResponse) Descriptor() ([]byte, []int) { + return file_zw_daemon_v1_daemon_proto_rawDescGZIP(), []int{13} +} + +func (x *ListFilesResponse) GetFiles() []*ListedFile { + if x != nil { + return x.Files + } + return nil +} + +type ListedFile struct { + state protoimpl.MessageState `protogen:"open.v1"` + LogicalPath string `protobuf:"bytes,1,opt,name=logical_path,json=logicalPath,proto3" json:"logical_path,omitempty"` + Size uint64 `protobuf:"varint,2,opt,name=size,proto3" json:"size,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListedFile) Reset() { + *x = ListedFile{} + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListedFile) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListedFile) ProtoMessage() {} + +func (x *ListedFile) ProtoReflect() protoreflect.Message { + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[14] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListedFile.ProtoReflect.Descriptor instead. +func (*ListedFile) Descriptor() ([]byte, []int) { + return file_zw_daemon_v1_daemon_proto_rawDescGZIP(), []int{14} +} + +func (x *ListedFile) GetLogicalPath() string { + if x != nil { + return x.LogicalPath + } + return "" +} + +func (x *ListedFile) GetSize() uint64 { + if x != nil { + return x.Size + } + return 0 +} + +type GetFileRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + LogicalPath string `protobuf:"bytes,1,opt,name=logical_path,json=logicalPath,proto3" json:"logical_path,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetFileRequest) Reset() { + *x = GetFileRequest{} + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetFileRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetFileRequest) ProtoMessage() {} + +func (x *GetFileRequest) ProtoReflect() protoreflect.Message { + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[15] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetFileRequest.ProtoReflect.Descriptor instead. +func (*GetFileRequest) Descriptor() ([]byte, []int) { + return file_zw_daemon_v1_daemon_proto_rawDescGZIP(), []int{15} +} + +func (x *GetFileRequest) GetLogicalPath() string { + if x != nil { + return x.LogicalPath + } + return "" +} + +type GetFileRangeRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + LogicalPath string `protobuf:"bytes,1,opt,name=logical_path,json=logicalPath,proto3" json:"logical_path,omitempty"` + Start uint64 `protobuf:"varint,2,opt,name=start,proto3" json:"start,omitempty"` + ExclusiveEnd uint64 `protobuf:"varint,3,opt,name=exclusive_end,json=exclusiveEnd,proto3" json:"exclusive_end,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetFileRangeRequest) Reset() { + *x = GetFileRangeRequest{} + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetFileRangeRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetFileRangeRequest) ProtoMessage() {} + +func (x *GetFileRangeRequest) ProtoReflect() protoreflect.Message { + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[16] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetFileRangeRequest.ProtoReflect.Descriptor instead. +func (*GetFileRangeRequest) Descriptor() ([]byte, []int) { + return file_zw_daemon_v1_daemon_proto_rawDescGZIP(), []int{16} +} + +func (x *GetFileRangeRequest) GetLogicalPath() string { + if x != nil { + return x.LogicalPath + } + return "" +} + +func (x *GetFileRangeRequest) GetStart() uint64 { + if x != nil { + return x.Start + } + return 0 +} + +func (x *GetFileRangeRequest) GetExclusiveEnd() uint64 { + if x != nil { + return x.ExclusiveEnd + } + return 0 +} + +type GetFileResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetFileResponse) Reset() { + *x = GetFileResponse{} + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetFileResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetFileResponse) ProtoMessage() {} + +func (x *GetFileResponse) ProtoReflect() protoreflect.Message { + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[17] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetFileResponse.ProtoReflect.Descriptor instead. +func (*GetFileResponse) Descriptor() ([]byte, []int) { + return file_zw_daemon_v1_daemon_proto_rawDescGZIP(), []int{17} +} + +func (x *GetFileResponse) GetData() []byte { + if x != nil { + return x.Data + } + return nil +} + +type GetFileRangeResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetFileRangeResponse) Reset() { + *x = GetFileRangeResponse{} + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetFileRangeResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetFileRangeResponse) ProtoMessage() {} + +func (x *GetFileRangeResponse) ProtoReflect() protoreflect.Message { + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[18] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetFileRangeResponse.ProtoReflect.Descriptor instead. +func (*GetFileRangeResponse) Descriptor() ([]byte, []int) { + return file_zw_daemon_v1_daemon_proto_rawDescGZIP(), []int{18} +} + +func (x *GetFileRangeResponse) GetData() []byte { + if x != nil { + return x.Data + } + return nil +} + +type AddFileRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Types that are valid to be assigned to Payload: + // + // *AddFileRequest_Header + // *AddFileRequest_Chunk + Payload isAddFileRequest_Payload `protobuf_oneof:"payload"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AddFileRequest) Reset() { + *x = AddFileRequest{} + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AddFileRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddFileRequest) ProtoMessage() {} + +func (x *AddFileRequest) ProtoReflect() protoreflect.Message { + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[19] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddFileRequest.ProtoReflect.Descriptor instead. +func (*AddFileRequest) Descriptor() ([]byte, []int) { + return file_zw_daemon_v1_daemon_proto_rawDescGZIP(), []int{19} +} + +func (x *AddFileRequest) GetPayload() isAddFileRequest_Payload { + if x != nil { + return x.Payload + } + return nil +} + +func (x *AddFileRequest) GetHeader() *AddFileHeader { + if x != nil { + if x, ok := x.Payload.(*AddFileRequest_Header); ok { + return x.Header + } + } + return nil +} + +func (x *AddFileRequest) GetChunk() []byte { + if x != nil { + if x, ok := x.Payload.(*AddFileRequest_Chunk); ok { + return x.Chunk + } + } + return nil +} + +type isAddFileRequest_Payload interface { + isAddFileRequest_Payload() +} + +type AddFileRequest_Header struct { + Header *AddFileHeader `protobuf:"bytes,1,opt,name=header,proto3,oneof"` +} + +type AddFileRequest_Chunk struct { + Chunk []byte `protobuf:"bytes,2,opt,name=chunk,proto3,oneof"` +} + +func (*AddFileRequest_Header) isAddFileRequest_Payload() {} + +func (*AddFileRequest_Chunk) isAddFileRequest_Payload() {} + +type AddFileHeader struct { + state protoimpl.MessageState `protogen:"open.v1"` + LogicalPath string `protobuf:"bytes,1,opt,name=logical_path,json=logicalPath,proto3" json:"logical_path,omitempty"` + SourceLen uint64 `protobuf:"varint,2,opt,name=source_len,json=sourceLen,proto3" json:"source_len,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AddFileHeader) Reset() { + *x = AddFileHeader{} + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AddFileHeader) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddFileHeader) ProtoMessage() {} + +func (x *AddFileHeader) ProtoReflect() protoreflect.Message { + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[20] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddFileHeader.ProtoReflect.Descriptor instead. +func (*AddFileHeader) Descriptor() ([]byte, []int) { + return file_zw_daemon_v1_daemon_proto_rawDescGZIP(), []int{20} +} + +func (x *AddFileHeader) GetLogicalPath() string { + if x != nil { + return x.LogicalPath + } + return "" +} + +func (x *AddFileHeader) GetSourceLen() uint64 { + if x != nil { + return x.SourceLen + } + return 0 +} + +type DeleteFileRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + LogicalPath string `protobuf:"bytes,1,opt,name=logical_path,json=logicalPath,proto3" json:"logical_path,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteFileRequest) Reset() { + *x = DeleteFileRequest{} + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteFileRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteFileRequest) ProtoMessage() {} + +func (x *DeleteFileRequest) ProtoReflect() protoreflect.Message { + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[21] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteFileRequest.ProtoReflect.Descriptor instead. +func (*DeleteFileRequest) Descriptor() ([]byte, []int) { + return file_zw_daemon_v1_daemon_proto_rawDescGZIP(), []int{21} +} + +func (x *DeleteFileRequest) GetLogicalPath() string { + if x != nil { + return x.LogicalPath + } + return "" +} + +type ZwErrorDetail struct { + state protoimpl.MessageState `protogen:"open.v1"` + Code ZwErrorCode `protobuf:"varint,1,opt,name=code,proto3,enum=zw.daemon.v1.ZwErrorCode" json:"code,omitempty"` + Retryable bool `protobuf:"varint,2,opt,name=retryable,proto3" json:"retryable,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ZwErrorDetail) Reset() { + *x = ZwErrorDetail{} + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ZwErrorDetail) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ZwErrorDetail) ProtoMessage() {} + +func (x *ZwErrorDetail) ProtoReflect() protoreflect.Message { + mi := &file_zw_daemon_v1_daemon_proto_msgTypes[22] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ZwErrorDetail.ProtoReflect.Descriptor instead. +func (*ZwErrorDetail) Descriptor() ([]byte, []int) { + return file_zw_daemon_v1_daemon_proto_rawDescGZIP(), []int{22} +} + +func (x *ZwErrorDetail) GetCode() ZwErrorCode { + if x != nil { + return x.Code + } + return ZwErrorCode_ZW_ERROR_CODE_UNSPECIFIED +} + +func (x *ZwErrorDetail) GetRetryable() bool { + if x != nil { + return x.Retryable + } + return false +} + +var File_zw_daemon_v1_daemon_proto protoreflect.FileDescriptor + +const file_zw_daemon_v1_daemon_proto_rawDesc = "" + + "\n" + + "\x19zw/daemon/v1/daemon.proto\x12\fzw.daemon.v1\"\x16\n" + + "\x14GetServerInfoRequest\"\r\n" + + "\vSealRequest\"\x0e\n" + + "\fSealResponse\"\x10\n" + + "\x0eCreateResponse\"\x10\n" + + "\x0eUnsealResponse\"\x11\n" + + "\x0fCompactResponse\"\x10\n" + + "\x0eCompactRequest\"\x11\n" + + "\x0fAddFileResponse\"\x14\n" + + "\x12DeleteFileResponse\"x\n" + + "\x15GetServerInfoResponse\x12\x1b\n" + + "\tapi_major\x18\x01 \x01(\rR\bapiMajor\x12\x1b\n" + + "\tapi_minor\x18\x02 \x01(\rR\bapiMinor\x12%\n" + + "\x0edaemon_version\x18\x03 \x01(\tR\rdaemonVersion\"J\n" + + "\rCreateRequest\x12\x1d\n" + + "\n" + + "vault_path\x18\x01 \x01(\tR\tvaultPath\x12\x1a\n" + + "\bpassword\x18\x02 \x01(\tR\bpassword\"J\n" + + "\rUnsealRequest\x12\x1d\n" + + "\n" + + "vault_path\x18\x01 \x01(\tR\tvaultPath\x12\x1a\n" + + "\bpassword\x18\x02 \x01(\tR\bpassword\"h\n" + + "\x10ListFilesRequest\x12\x1b\n" + + "\x06prefix\x18\x01 \x01(\tH\x00R\x06prefix\x88\x01\x01\x12\x1f\n" + + "\bcontains\x18\x02 \x01(\tH\x01R\bcontains\x88\x01\x01B\t\n" + + "\a_prefixB\v\n" + + "\t_contains\"C\n" + + "\x11ListFilesResponse\x12.\n" + + "\x05files\x18\x01 \x03(\v2\x18.zw.daemon.v1.ListedFileR\x05files\"C\n" + + "\n" + + "ListedFile\x12!\n" + + "\flogical_path\x18\x01 \x01(\tR\vlogicalPath\x12\x12\n" + + "\x04size\x18\x02 \x01(\x04R\x04size\"3\n" + + "\x0eGetFileRequest\x12!\n" + + "\flogical_path\x18\x01 \x01(\tR\vlogicalPath\"s\n" + + "\x13GetFileRangeRequest\x12!\n" + + "\flogical_path\x18\x01 \x01(\tR\vlogicalPath\x12\x14\n" + + "\x05start\x18\x02 \x01(\x04R\x05start\x12#\n" + + "\rexclusive_end\x18\x03 \x01(\x04R\fexclusiveEnd\"%\n" + + "\x0fGetFileResponse\x12\x12\n" + + "\x04data\x18\x01 \x01(\fR\x04data\"*\n" + + "\x14GetFileRangeResponse\x12\x12\n" + + "\x04data\x18\x01 \x01(\fR\x04data\"j\n" + + "\x0eAddFileRequest\x125\n" + + "\x06header\x18\x01 \x01(\v2\x1b.zw.daemon.v1.AddFileHeaderH\x00R\x06header\x12\x16\n" + + "\x05chunk\x18\x02 \x01(\fH\x00R\x05chunkB\t\n" + + "\apayload\"Q\n" + + "\rAddFileHeader\x12!\n" + + "\flogical_path\x18\x01 \x01(\tR\vlogicalPath\x12\x1d\n" + + "\n" + + "source_len\x18\x02 \x01(\x04R\tsourceLen\"6\n" + + "\x11DeleteFileRequest\x12!\n" + + "\flogical_path\x18\x01 \x01(\tR\vlogicalPath\"\\\n" + + "\rZwErrorDetail\x12-\n" + + "\x04code\x18\x01 \x01(\x0e2\x19.zw.daemon.v1.ZwErrorCodeR\x04code\x12\x1c\n" + + "\tretryable\x18\x02 \x01(\bR\tretryable*\x9b\x04\n" + + "\vZwErrorCode\x12\x1d\n" + + "\x19ZW_ERROR_CODE_UNSPECIFIED\x10\x00\x12\x1e\n" + + "\x1aZW_ERROR_CODE_VAULT_SEALED\x10\x01\x12(\n" + + "$ZW_ERROR_CODE_VAULT_ALREADY_UNSEALED\x10\x02\x12!\n" + + "\x1dZW_ERROR_CODE_ENTRY_NOT_FOUND\x10\x03\x12&\n" + + "\"ZW_ERROR_CODE_ENTRY_ALREADY_EXISTS\x10\x04\x12.\n" + + "*ZW_ERROR_CODE_AUTHENTICATION_OR_CORRUPTION\x10\x05\x12&\n" + + "\"ZW_ERROR_CODE_INVALID_VAULT_FORMAT\x10\x06\x12+\n" + + "'ZW_ERROR_CODE_UNSUPPORTED_VAULT_VERSION\x10\a\x12.\n" + + "*ZW_ERROR_CODE_UNSUPPORTED_PROTOCOL_VERSION\x10\b\x12#\n" + + "\x1fZW_ERROR_CODE_PERMISSION_DENIED\x10\t\x12\x1e\n" + + "\x1aZW_ERROR_CODE_STORAGE_FULL\x10\n" + + "\x12\x1f\n" + + "\x1bZW_ERROR_CODE_COMMIT_FAILED\x10\v\x12!\n" + + "\x1dZW_ERROR_CODE_INVALID_REQUEST\x10\f\x12\x1a\n" + + "\x16ZW_ERROR_CODE_INTERNAL\x10\r2\x88\x06\n" + + "\x0fZwDaemonService\x12X\n" + + "\rGetServerInfo\x12\".zw.daemon.v1.GetServerInfoRequest\x1a#.zw.daemon.v1.GetServerInfoResponse\x12C\n" + + "\x06Create\x12\x1b.zw.daemon.v1.CreateRequest\x1a\x1c.zw.daemon.v1.CreateResponse\x12C\n" + + "\x06Unseal\x12\x1b.zw.daemon.v1.UnsealRequest\x1a\x1c.zw.daemon.v1.UnsealResponse\x12=\n" + + "\x04Seal\x12\x19.zw.daemon.v1.SealRequest\x1a\x1a.zw.daemon.v1.SealResponse\x12L\n" + + "\tListFiles\x12\x1e.zw.daemon.v1.ListFilesRequest\x1a\x1f.zw.daemon.v1.ListFilesResponse\x12H\n" + + "\aGetFile\x12\x1c.zw.daemon.v1.GetFileRequest\x1a\x1d.zw.daemon.v1.GetFileResponse0\x01\x12W\n" + + "\fGetFileRange\x12!.zw.daemon.v1.GetFileRangeRequest\x1a\".zw.daemon.v1.GetFileRangeResponse0\x01\x12H\n" + + "\aAddFile\x12\x1c.zw.daemon.v1.AddFileRequest\x1a\x1d.zw.daemon.v1.AddFileResponse(\x01\x12O\n" + + "\n" + + "DeleteFile\x12\x1f.zw.daemon.v1.DeleteFileRequest\x1a .zw.daemon.v1.DeleteFileResponse\x12F\n" + + "\aCompact\x12\x1c.zw.daemon.v1.CompactRequest\x1a\x1d.zw.daemon.v1.CompactResponseB5Z3git.pablu.de/pablu/zw-go/gen/zwdaemon/v1;zwdaemonv1b\x06proto3" + +var ( + file_zw_daemon_v1_daemon_proto_rawDescOnce sync.Once + file_zw_daemon_v1_daemon_proto_rawDescData []byte +) + +func file_zw_daemon_v1_daemon_proto_rawDescGZIP() []byte { + file_zw_daemon_v1_daemon_proto_rawDescOnce.Do(func() { + file_zw_daemon_v1_daemon_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_zw_daemon_v1_daemon_proto_rawDesc), len(file_zw_daemon_v1_daemon_proto_rawDesc))) + }) + return file_zw_daemon_v1_daemon_proto_rawDescData +} + +var file_zw_daemon_v1_daemon_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_zw_daemon_v1_daemon_proto_msgTypes = make([]protoimpl.MessageInfo, 23) +var file_zw_daemon_v1_daemon_proto_goTypes = []any{ + (ZwErrorCode)(0), // 0: zw.daemon.v1.ZwErrorCode + (*GetServerInfoRequest)(nil), // 1: zw.daemon.v1.GetServerInfoRequest + (*SealRequest)(nil), // 2: zw.daemon.v1.SealRequest + (*SealResponse)(nil), // 3: zw.daemon.v1.SealResponse + (*CreateResponse)(nil), // 4: zw.daemon.v1.CreateResponse + (*UnsealResponse)(nil), // 5: zw.daemon.v1.UnsealResponse + (*CompactResponse)(nil), // 6: zw.daemon.v1.CompactResponse + (*CompactRequest)(nil), // 7: zw.daemon.v1.CompactRequest + (*AddFileResponse)(nil), // 8: zw.daemon.v1.AddFileResponse + (*DeleteFileResponse)(nil), // 9: zw.daemon.v1.DeleteFileResponse + (*GetServerInfoResponse)(nil), // 10: zw.daemon.v1.GetServerInfoResponse + (*CreateRequest)(nil), // 11: zw.daemon.v1.CreateRequest + (*UnsealRequest)(nil), // 12: zw.daemon.v1.UnsealRequest + (*ListFilesRequest)(nil), // 13: zw.daemon.v1.ListFilesRequest + (*ListFilesResponse)(nil), // 14: zw.daemon.v1.ListFilesResponse + (*ListedFile)(nil), // 15: zw.daemon.v1.ListedFile + (*GetFileRequest)(nil), // 16: zw.daemon.v1.GetFileRequest + (*GetFileRangeRequest)(nil), // 17: zw.daemon.v1.GetFileRangeRequest + (*GetFileResponse)(nil), // 18: zw.daemon.v1.GetFileResponse + (*GetFileRangeResponse)(nil), // 19: zw.daemon.v1.GetFileRangeResponse + (*AddFileRequest)(nil), // 20: zw.daemon.v1.AddFileRequest + (*AddFileHeader)(nil), // 21: zw.daemon.v1.AddFileHeader + (*DeleteFileRequest)(nil), // 22: zw.daemon.v1.DeleteFileRequest + (*ZwErrorDetail)(nil), // 23: zw.daemon.v1.ZwErrorDetail +} +var file_zw_daemon_v1_daemon_proto_depIdxs = []int32{ + 15, // 0: zw.daemon.v1.ListFilesResponse.files:type_name -> zw.daemon.v1.ListedFile + 21, // 1: zw.daemon.v1.AddFileRequest.header:type_name -> zw.daemon.v1.AddFileHeader + 0, // 2: zw.daemon.v1.ZwErrorDetail.code:type_name -> zw.daemon.v1.ZwErrorCode + 1, // 3: zw.daemon.v1.ZwDaemonService.GetServerInfo:input_type -> zw.daemon.v1.GetServerInfoRequest + 11, // 4: zw.daemon.v1.ZwDaemonService.Create:input_type -> zw.daemon.v1.CreateRequest + 12, // 5: zw.daemon.v1.ZwDaemonService.Unseal:input_type -> zw.daemon.v1.UnsealRequest + 2, // 6: zw.daemon.v1.ZwDaemonService.Seal:input_type -> zw.daemon.v1.SealRequest + 13, // 7: zw.daemon.v1.ZwDaemonService.ListFiles:input_type -> zw.daemon.v1.ListFilesRequest + 16, // 8: zw.daemon.v1.ZwDaemonService.GetFile:input_type -> zw.daemon.v1.GetFileRequest + 17, // 9: zw.daemon.v1.ZwDaemonService.GetFileRange:input_type -> zw.daemon.v1.GetFileRangeRequest + 20, // 10: zw.daemon.v1.ZwDaemonService.AddFile:input_type -> zw.daemon.v1.AddFileRequest + 22, // 11: zw.daemon.v1.ZwDaemonService.DeleteFile:input_type -> zw.daemon.v1.DeleteFileRequest + 7, // 12: zw.daemon.v1.ZwDaemonService.Compact:input_type -> zw.daemon.v1.CompactRequest + 10, // 13: zw.daemon.v1.ZwDaemonService.GetServerInfo:output_type -> zw.daemon.v1.GetServerInfoResponse + 4, // 14: zw.daemon.v1.ZwDaemonService.Create:output_type -> zw.daemon.v1.CreateResponse + 5, // 15: zw.daemon.v1.ZwDaemonService.Unseal:output_type -> zw.daemon.v1.UnsealResponse + 3, // 16: zw.daemon.v1.ZwDaemonService.Seal:output_type -> zw.daemon.v1.SealResponse + 14, // 17: zw.daemon.v1.ZwDaemonService.ListFiles:output_type -> zw.daemon.v1.ListFilesResponse + 18, // 18: zw.daemon.v1.ZwDaemonService.GetFile:output_type -> zw.daemon.v1.GetFileResponse + 19, // 19: zw.daemon.v1.ZwDaemonService.GetFileRange:output_type -> zw.daemon.v1.GetFileRangeResponse + 8, // 20: zw.daemon.v1.ZwDaemonService.AddFile:output_type -> zw.daemon.v1.AddFileResponse + 9, // 21: zw.daemon.v1.ZwDaemonService.DeleteFile:output_type -> zw.daemon.v1.DeleteFileResponse + 6, // 22: zw.daemon.v1.ZwDaemonService.Compact:output_type -> zw.daemon.v1.CompactResponse + 13, // [13:23] is the sub-list for method output_type + 3, // [3:13] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name +} + +func init() { file_zw_daemon_v1_daemon_proto_init() } +func file_zw_daemon_v1_daemon_proto_init() { + if File_zw_daemon_v1_daemon_proto != nil { + return + } + file_zw_daemon_v1_daemon_proto_msgTypes[12].OneofWrappers = []any{} + file_zw_daemon_v1_daemon_proto_msgTypes[19].OneofWrappers = []any{ + (*AddFileRequest_Header)(nil), + (*AddFileRequest_Chunk)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_zw_daemon_v1_daemon_proto_rawDesc), len(file_zw_daemon_v1_daemon_proto_rawDesc)), + NumEnums: 1, + NumMessages: 23, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_zw_daemon_v1_daemon_proto_goTypes, + DependencyIndexes: file_zw_daemon_v1_daemon_proto_depIdxs, + EnumInfos: file_zw_daemon_v1_daemon_proto_enumTypes, + MessageInfos: file_zw_daemon_v1_daemon_proto_msgTypes, + }.Build() + File_zw_daemon_v1_daemon_proto = out.File + file_zw_daemon_v1_daemon_proto_goTypes = nil + file_zw_daemon_v1_daemon_proto_depIdxs = nil +} diff --git a/gen/zwdaemon/v1/daemon_grpc.pb.go b/gen/zwdaemon/v1/daemon_grpc.pb.go new file mode 100644 index 0000000..73b99bf --- /dev/null +++ b/gen/zwdaemon/v1/daemon_grpc.pb.go @@ -0,0 +1,463 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.6.2 +// - protoc (unknown) +// source: zw/daemon/v1/daemon.proto + +package zwdaemonv1 + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + ZwDaemonService_GetServerInfo_FullMethodName = "/zw.daemon.v1.ZwDaemonService/GetServerInfo" + ZwDaemonService_Create_FullMethodName = "/zw.daemon.v1.ZwDaemonService/Create" + ZwDaemonService_Unseal_FullMethodName = "/zw.daemon.v1.ZwDaemonService/Unseal" + ZwDaemonService_Seal_FullMethodName = "/zw.daemon.v1.ZwDaemonService/Seal" + ZwDaemonService_ListFiles_FullMethodName = "/zw.daemon.v1.ZwDaemonService/ListFiles" + ZwDaemonService_GetFile_FullMethodName = "/zw.daemon.v1.ZwDaemonService/GetFile" + ZwDaemonService_GetFileRange_FullMethodName = "/zw.daemon.v1.ZwDaemonService/GetFileRange" + ZwDaemonService_AddFile_FullMethodName = "/zw.daemon.v1.ZwDaemonService/AddFile" + ZwDaemonService_DeleteFile_FullMethodName = "/zw.daemon.v1.ZwDaemonService/DeleteFile" + ZwDaemonService_Compact_FullMethodName = "/zw.daemon.v1.ZwDaemonService/Compact" +) + +// ZwDaemonServiceClient is the client API for ZwDaemonService 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 ZwDaemonServiceClient interface { + GetServerInfo(ctx context.Context, in *GetServerInfoRequest, opts ...grpc.CallOption) (*GetServerInfoResponse, error) + Create(ctx context.Context, in *CreateRequest, opts ...grpc.CallOption) (*CreateResponse, error) + Unseal(ctx context.Context, in *UnsealRequest, opts ...grpc.CallOption) (*UnsealResponse, error) + Seal(ctx context.Context, in *SealRequest, opts ...grpc.CallOption) (*SealResponse, error) + ListFiles(ctx context.Context, in *ListFilesRequest, opts ...grpc.CallOption) (*ListFilesResponse, error) + GetFile(ctx context.Context, in *GetFileRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[GetFileResponse], error) + GetFileRange(ctx context.Context, in *GetFileRangeRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[GetFileRangeResponse], error) + AddFile(ctx context.Context, opts ...grpc.CallOption) (grpc.ClientStreamingClient[AddFileRequest, AddFileResponse], error) + DeleteFile(ctx context.Context, in *DeleteFileRequest, opts ...grpc.CallOption) (*DeleteFileResponse, error) + Compact(ctx context.Context, in *CompactRequest, opts ...grpc.CallOption) (*CompactResponse, error) +} + +type zwDaemonServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewZwDaemonServiceClient(cc grpc.ClientConnInterface) ZwDaemonServiceClient { + return &zwDaemonServiceClient{cc} +} + +func (c *zwDaemonServiceClient) GetServerInfo(ctx context.Context, in *GetServerInfoRequest, opts ...grpc.CallOption) (*GetServerInfoResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetServerInfoResponse) + err := c.cc.Invoke(ctx, ZwDaemonService_GetServerInfo_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *zwDaemonServiceClient) Create(ctx context.Context, in *CreateRequest, opts ...grpc.CallOption) (*CreateResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(CreateResponse) + err := c.cc.Invoke(ctx, ZwDaemonService_Create_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *zwDaemonServiceClient) Unseal(ctx context.Context, in *UnsealRequest, opts ...grpc.CallOption) (*UnsealResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(UnsealResponse) + err := c.cc.Invoke(ctx, ZwDaemonService_Unseal_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *zwDaemonServiceClient) Seal(ctx context.Context, in *SealRequest, opts ...grpc.CallOption) (*SealResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(SealResponse) + err := c.cc.Invoke(ctx, ZwDaemonService_Seal_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *zwDaemonServiceClient) ListFiles(ctx context.Context, in *ListFilesRequest, opts ...grpc.CallOption) (*ListFilesResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListFilesResponse) + err := c.cc.Invoke(ctx, ZwDaemonService_ListFiles_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *zwDaemonServiceClient) GetFile(ctx context.Context, in *GetFileRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[GetFileResponse], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &ZwDaemonService_ServiceDesc.Streams[0], ZwDaemonService_GetFile_FullMethodName, cOpts...) + if err != nil { + return nil, err + } + x := &grpc.GenericClientStream[GetFileRequest, GetFileResponse]{ClientStream: stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type ZwDaemonService_GetFileClient = grpc.ServerStreamingClient[GetFileResponse] + +func (c *zwDaemonServiceClient) GetFileRange(ctx context.Context, in *GetFileRangeRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[GetFileRangeResponse], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &ZwDaemonService_ServiceDesc.Streams[1], ZwDaemonService_GetFileRange_FullMethodName, cOpts...) + if err != nil { + return nil, err + } + x := &grpc.GenericClientStream[GetFileRangeRequest, GetFileRangeResponse]{ClientStream: stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type ZwDaemonService_GetFileRangeClient = grpc.ServerStreamingClient[GetFileRangeResponse] + +func (c *zwDaemonServiceClient) AddFile(ctx context.Context, opts ...grpc.CallOption) (grpc.ClientStreamingClient[AddFileRequest, AddFileResponse], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &ZwDaemonService_ServiceDesc.Streams[2], ZwDaemonService_AddFile_FullMethodName, cOpts...) + if err != nil { + return nil, err + } + x := &grpc.GenericClientStream[AddFileRequest, AddFileResponse]{ClientStream: stream} + return x, nil +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type ZwDaemonService_AddFileClient = grpc.ClientStreamingClient[AddFileRequest, AddFileResponse] + +func (c *zwDaemonServiceClient) DeleteFile(ctx context.Context, in *DeleteFileRequest, opts ...grpc.CallOption) (*DeleteFileResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(DeleteFileResponse) + err := c.cc.Invoke(ctx, ZwDaemonService_DeleteFile_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *zwDaemonServiceClient) Compact(ctx context.Context, in *CompactRequest, opts ...grpc.CallOption) (*CompactResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(CompactResponse) + err := c.cc.Invoke(ctx, ZwDaemonService_Compact_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// ZwDaemonServiceServer is the server API for ZwDaemonService service. +// All implementations must embed UnimplementedZwDaemonServiceServer +// for forward compatibility. +type ZwDaemonServiceServer interface { + GetServerInfo(context.Context, *GetServerInfoRequest) (*GetServerInfoResponse, error) + Create(context.Context, *CreateRequest) (*CreateResponse, error) + Unseal(context.Context, *UnsealRequest) (*UnsealResponse, error) + Seal(context.Context, *SealRequest) (*SealResponse, error) + ListFiles(context.Context, *ListFilesRequest) (*ListFilesResponse, error) + GetFile(*GetFileRequest, grpc.ServerStreamingServer[GetFileResponse]) error + GetFileRange(*GetFileRangeRequest, grpc.ServerStreamingServer[GetFileRangeResponse]) error + AddFile(grpc.ClientStreamingServer[AddFileRequest, AddFileResponse]) error + DeleteFile(context.Context, *DeleteFileRequest) (*DeleteFileResponse, error) + Compact(context.Context, *CompactRequest) (*CompactResponse, error) + mustEmbedUnimplementedZwDaemonServiceServer() +} + +// UnimplementedZwDaemonServiceServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedZwDaemonServiceServer struct{} + +func (UnimplementedZwDaemonServiceServer) GetServerInfo(context.Context, *GetServerInfoRequest) (*GetServerInfoResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetServerInfo not implemented") +} +func (UnimplementedZwDaemonServiceServer) Create(context.Context, *CreateRequest) (*CreateResponse, error) { + return nil, status.Error(codes.Unimplemented, "method Create not implemented") +} +func (UnimplementedZwDaemonServiceServer) Unseal(context.Context, *UnsealRequest) (*UnsealResponse, error) { + return nil, status.Error(codes.Unimplemented, "method Unseal not implemented") +} +func (UnimplementedZwDaemonServiceServer) Seal(context.Context, *SealRequest) (*SealResponse, error) { + return nil, status.Error(codes.Unimplemented, "method Seal not implemented") +} +func (UnimplementedZwDaemonServiceServer) ListFiles(context.Context, *ListFilesRequest) (*ListFilesResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListFiles not implemented") +} +func (UnimplementedZwDaemonServiceServer) GetFile(*GetFileRequest, grpc.ServerStreamingServer[GetFileResponse]) error { + return status.Error(codes.Unimplemented, "method GetFile not implemented") +} +func (UnimplementedZwDaemonServiceServer) GetFileRange(*GetFileRangeRequest, grpc.ServerStreamingServer[GetFileRangeResponse]) error { + return status.Error(codes.Unimplemented, "method GetFileRange not implemented") +} +func (UnimplementedZwDaemonServiceServer) AddFile(grpc.ClientStreamingServer[AddFileRequest, AddFileResponse]) error { + return status.Error(codes.Unimplemented, "method AddFile not implemented") +} +func (UnimplementedZwDaemonServiceServer) DeleteFile(context.Context, *DeleteFileRequest) (*DeleteFileResponse, error) { + return nil, status.Error(codes.Unimplemented, "method DeleteFile not implemented") +} +func (UnimplementedZwDaemonServiceServer) Compact(context.Context, *CompactRequest) (*CompactResponse, error) { + return nil, status.Error(codes.Unimplemented, "method Compact not implemented") +} +func (UnimplementedZwDaemonServiceServer) mustEmbedUnimplementedZwDaemonServiceServer() {} +func (UnimplementedZwDaemonServiceServer) testEmbeddedByValue() {} + +// UnsafeZwDaemonServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to ZwDaemonServiceServer will +// result in compilation errors. +type UnsafeZwDaemonServiceServer interface { + mustEmbedUnimplementedZwDaemonServiceServer() +} + +func RegisterZwDaemonServiceServer(s grpc.ServiceRegistrar, srv ZwDaemonServiceServer) { + // If the following call panics, it indicates UnimplementedZwDaemonServiceServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&ZwDaemonService_ServiceDesc, srv) +} + +func _ZwDaemonService_GetServerInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetServerInfoRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ZwDaemonServiceServer).GetServerInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ZwDaemonService_GetServerInfo_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ZwDaemonServiceServer).GetServerInfo(ctx, req.(*GetServerInfoRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ZwDaemonService_Create_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ZwDaemonServiceServer).Create(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ZwDaemonService_Create_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ZwDaemonServiceServer).Create(ctx, req.(*CreateRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ZwDaemonService_Unseal_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UnsealRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ZwDaemonServiceServer).Unseal(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ZwDaemonService_Unseal_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ZwDaemonServiceServer).Unseal(ctx, req.(*UnsealRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ZwDaemonService_Seal_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SealRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ZwDaemonServiceServer).Seal(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ZwDaemonService_Seal_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ZwDaemonServiceServer).Seal(ctx, req.(*SealRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ZwDaemonService_ListFiles_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListFilesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ZwDaemonServiceServer).ListFiles(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ZwDaemonService_ListFiles_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ZwDaemonServiceServer).ListFiles(ctx, req.(*ListFilesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ZwDaemonService_GetFile_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(GetFileRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(ZwDaemonServiceServer).GetFile(m, &grpc.GenericServerStream[GetFileRequest, GetFileResponse]{ServerStream: stream}) +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type ZwDaemonService_GetFileServer = grpc.ServerStreamingServer[GetFileResponse] + +func _ZwDaemonService_GetFileRange_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(GetFileRangeRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(ZwDaemonServiceServer).GetFileRange(m, &grpc.GenericServerStream[GetFileRangeRequest, GetFileRangeResponse]{ServerStream: stream}) +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type ZwDaemonService_GetFileRangeServer = grpc.ServerStreamingServer[GetFileRangeResponse] + +func _ZwDaemonService_AddFile_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(ZwDaemonServiceServer).AddFile(&grpc.GenericServerStream[AddFileRequest, AddFileResponse]{ServerStream: stream}) +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type ZwDaemonService_AddFileServer = grpc.ClientStreamingServer[AddFileRequest, AddFileResponse] + +func _ZwDaemonService_DeleteFile_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteFileRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ZwDaemonServiceServer).DeleteFile(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ZwDaemonService_DeleteFile_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ZwDaemonServiceServer).DeleteFile(ctx, req.(*DeleteFileRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ZwDaemonService_Compact_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CompactRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ZwDaemonServiceServer).Compact(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ZwDaemonService_Compact_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ZwDaemonServiceServer).Compact(ctx, req.(*CompactRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// ZwDaemonService_ServiceDesc is the grpc.ServiceDesc for ZwDaemonService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var ZwDaemonService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "zw.daemon.v1.ZwDaemonService", + HandlerType: (*ZwDaemonServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetServerInfo", + Handler: _ZwDaemonService_GetServerInfo_Handler, + }, + { + MethodName: "Create", + Handler: _ZwDaemonService_Create_Handler, + }, + { + MethodName: "Unseal", + Handler: _ZwDaemonService_Unseal_Handler, + }, + { + MethodName: "Seal", + Handler: _ZwDaemonService_Seal_Handler, + }, + { + MethodName: "ListFiles", + Handler: _ZwDaemonService_ListFiles_Handler, + }, + { + MethodName: "DeleteFile", + Handler: _ZwDaemonService_DeleteFile_Handler, + }, + { + MethodName: "Compact", + Handler: _ZwDaemonService_Compact_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "GetFile", + Handler: _ZwDaemonService_GetFile_Handler, + ServerStreams: true, + }, + { + StreamName: "GetFileRange", + Handler: _ZwDaemonService_GetFileRange_Handler, + ServerStreams: true, + }, + { + StreamName: "AddFile", + Handler: _ZwDaemonService_AddFile_Handler, + ClientStreams: true, + }, + }, + Metadata: "zw/daemon/v1/daemon.proto", +} diff --git a/go.mod b/go.mod index a6af57a..75f976d 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,15 @@ module git.pablu.de/pablu/zw-go -go 1.25.0 +go 1.26.0 + +require ( + google.golang.org/grpc v1.83.0 + google.golang.org/protobuf v1.36.11 +) + +require ( + golang.org/x/net v0.55.0 // indirect + golang.org/x/sys v0.45.0 // indirect + golang.org/x/text v0.37.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..2010d3d --- /dev/null +++ b/go.sum @@ -0,0 +1,38 @@ +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU= +go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc= +go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc= +go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo= +go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58= +go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0= +go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI= +go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA= +go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk= +go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE= +golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8= +golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww= +golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY= +golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= +golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= +gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/grpc v1.83.0 h1:JeNZEKJFbQxArAMl+hiytHauacDNqJUllNfmIMmpqnQ= +google.golang.org/grpc v1.83.0/go.mod h1:kDyl6SKsiHKt0uylY5gtn5cEjkrIOhQOGDgIc4JGwzQ= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= diff --git a/mise.toml b/mise.toml index 93c2963..7fc8548 100644 --- a/mise.toml +++ b/mise.toml @@ -1,2 +1,8 @@ [tools] go = "1.26.0" +"go:golang.org/x/tools/gopls" = "latest" +buf = "1.72.0" + +[tasks.generate] +description = "Generate Go protobuf and gRPC bindings" +run = "buf generate" diff --git a/types.go b/types.go new file mode 100644 index 0000000..af04b54 --- /dev/null +++ b/types.go @@ -0,0 +1,17 @@ +package zw + +type ServerInfo struct { + APIMajor uint32 + APIMinor uint32 + DaemonVersion string +} + +type ListFilter struct { + Prefix string + Contains string +} + +type ListedFile struct { + LogicalPath string + Size uint64 +}