Skip to content

A native Swift library for parsing Protocol Buffer (proto3) files into descriptors. SwiftProtoParser offers full proto3 syntax support, including services, RPC definitions, and custom options, with detailed error reporting and cross-platform compatibility. Designed as a Swift-idiomatic alternative to protoc with seamless Swift Protobuf integration.

License

Notifications You must be signed in to change notification settings

truewebber/swift-protoparser

Repository files navigation

SwiftProtoParser

πŸš€ Production-Ready Swift Library for parsing Protocol Buffers .proto files into Abstract Syntax Trees (AST) and Google Protocol Buffer descriptors.

Swift Platform Tests Coverage License

🎯 What is SwiftProtoParser?

SwiftProtoParser is a comprehensive Swift library that parses Protocol Buffers .proto files and converts them into structured data for Swift applications. Unlike other parsers, it provides complete proto3 specification support including advanced features like extend statements, qualified types, and enterprise-grade dependency resolution.

✨ Key Features

  • 🎯 Complete Proto3 Support - All syntax, semantics, and advanced features
  • πŸ”§ Extend Statements - Full custom options support for google.protobuf.* types
  • πŸ—οΈ Qualified Types - Well-known types (google.protobuf.Timestamp) and nested types
  • πŸ“¦ Dependency Resolution - Multi-file imports with circular dependency detection
  • ⚑ High Performance - Sub-millisecond parsing with intelligent caching
  • πŸ›‘οΈ Production Quality - Thread-safe, memory-efficient, comprehensive error handling
  • πŸ”„ SwiftProtobuf Integration - Generate descriptors compatible with swift-protobuf
  • πŸ“ˆ Advanced Features - Incremental parsing, streaming for large files, performance monitoring

πŸš€ Quick Start

Installation

Add SwiftProtoParser to your Swift Package:

dependencies: [
    .package(url: "https://github.com/truewebber/swift-protoparser", from: "0.1.0")
]

Basic Usage

import SwiftProtoParser

// Parse a single .proto file
let result = SwiftProtoParser.parseProtoFile("user.proto")
switch result {
case .success(let descriptor):
    print("Parsed successfully: \(descriptor.packageName)")
    print("Messages: \(descriptor.messageNames)")
case .failure(let error):
    print("Parse error: \(error.localizedDescription)")
}

// Parse with import dependencies
let resultWithImports = SwiftProtoParser.parseProtoFileWithImports(
    "main.proto", 
    importPaths: ["/path/to/imports", "/path/to/google/protobuf"]
)

// Parse entire directory
let directoryResult = SwiftProtoParser.parseProtoDirectory(
    "/path/to/proto/files", 
    recursive: true
)

Advanced Features

// Performance-optimized parsing with caching
let cachedResult = SwiftProtoParser.parseProtoFileWithCaching("user.proto")

// Incremental parsing for large projects
let incrementalResult = SwiftProtoParser.parseProtoDirectoryIncremental("/proto/dir")

// Streaming for very large files (>50MB)
let streamingResult = SwiftProtoParser.parseProtoFileStreaming("large_schema.proto")

// Get performance statistics
let stats = SwiftProtoParser.getCacheStatistics()
print("Cache hit rate: \(stats.hitRate)%")

πŸ“‹ Supported Proto3 Features

Core Language Features

syntax = "proto3";

package example.v1;

import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";

// Messages with all field types
message User {
  string name = 1;
  int32 age = 2;
  repeated string emails = 3;
  map<string, string> metadata = 4;
  google.protobuf.Timestamp created_at = 5;
  
  // Nested messages
  message Address {
    string street = 1;
    string city = 2;
  }
  Address address = 6;
  
  // Oneof groups
  oneof contact {
    string phone = 10;
    string slack = 11;
  }
}

// Enums
enum Status {
  STATUS_UNSPECIFIED = 0;
  STATUS_ACTIVE = 1;
  STATUS_INACTIVE = 2;
}

// Services with qualified types
service UserService {
  rpc GetUser(GetUserRequest) returns (User);
  rpc CreateUser(CreateUserRequest) returns (google.protobuf.Empty);
  rpc StreamUsers(google.protobuf.Empty) returns (stream User);
}

Advanced Features (Extend Statements)

// Custom options with extend statements
import "google/protobuf/descriptor.proto";

extend google.protobuf.FileOptions {
  string api_version = 50001;
}

extend google.protobuf.MessageOptions {
  bool enable_validation = 50002;
}

extend google.protobuf.FieldOptions {
  string validation_rule = 50003;
}

option (api_version) = "v1.0";

message ValidatedMessage {
  option (enable_validation) = true;
  
  string email = 1 [(validation_rule) = "email"];
  int32 age = 2 [(validation_rule) = "min:0,max:150"];
}

πŸ† Quality Metrics

Metric Value Status
Test Success Rate 1086/1086 βœ… Perfect
Line Coverage 95.01% βœ… Excellent
Function Coverage 93.00% βœ… Very Good
Region Coverage 91.84% βœ… Excellent
Performance Sub-millisecond βœ… Outstanding

⚑ Performance

File Size Parse Time Memory Usage
Small (< 10KB) 0.1-2ms < 1MB
Medium (10-100KB) 2-10ms 1-5MB
Large (100KB-1MB) 10-50ms 5-20MB
Very Large (> 1MB) 50-200ms 20-50MB

Performance Features:

  • 85%+ cache hit rate for repeated parsing
  • Content-based caching with automatic invalidation
  • Incremental parsing for development workflows
  • Parallel processing for directory parsing
  • Memory-efficient streaming for large files

πŸ”§ API Reference

Core Parsing Methods

// Basic parsing
static func parseProtoFile(_ filePath: String) -> Result<ProtoAST, ProtoParseError>
static func parseProtoString(_ content: String) -> Result<ProtoAST, ProtoParseError>

// With dependencies
static func parseProtoFileWithImports(_ filePath: String, importPaths: [String]) -> Result<ProtoAST, ProtoParseError>
static func parseProtoDirectory(_ directoryPath: String, recursive: Bool) -> Result<[ProtoAST], ProtoParseError>

// Descriptor generation (SwiftProtobuf compatible)
static func parseProtoToDescriptors(_ filePath: String) -> Result<[Google_Protobuf_DescriptorProto], ProtoParseError>
static func parseProtoStringToDescriptors(_ content: String) -> Result<[Google_Protobuf_DescriptorProto], ProtoParseError>

Performance Methods

// Caching
static func parseProtoFileWithCaching(_ filePath: String) -> Result<ProtoAST, ProtoParseError>
static func getCacheStatistics() -> CacheStatistics
static func clearPerformanceCaches()

// Incremental parsing
static func parseProtoDirectoryIncremental(_ directoryPath: String) -> Result<[String: ProtoAST], ProtoParseError>
static func detectChanges(in directoryPath: String) -> ChangeSet

// Streaming (for large files)
static func parseProtoFileStreaming(_ filePath: String) -> AsyncSequence<Result<ProtoAST, ProtoParseError>>

Utility Methods

// Metadata extraction
static func getProtoVersion(_ filePath: String) -> String?
static func getPackageName(_ filePath: String) -> String?
static func getMessageNames(_ filePath: String) -> [String]
static func getServiceNames(_ filePath: String) -> [String]

// Performance monitoring
static func benchmarkPerformance(_ path: String) -> PerformanceBenchmark

πŸ› οΈ Requirements

  • Swift 5.9+
  • macOS 12.0+, iOS 15.0+, or Linux (Ubuntu 20.04+)
  • SwiftProtobuf 1.29.0+ (for descriptor generation)

πŸ“– Documentation

🀝 Contributing

We welcome contributions! Please see our Contributing Guidelines for details.

πŸ“„ License

SwiftProtoParser is released under the MIT License.


Built with ❀️ by truewebber

About

A native Swift library for parsing Protocol Buffer (proto3) files into descriptors. SwiftProtoParser offers full proto3 syntax support, including services, RPC definitions, and custom options, with detailed error reporting and cross-platform compatibility. Designed as a Swift-idiomatic alternative to protoc with seamless Swift Protobuf integration.

Topics

Resources

License

Contributing

Stars

Watchers

Forks