Add LND test wallet

This commit is contained in:
adrianaepure
2023-06-08 09:36:06 +03:00
commit 1313d727cf
251 changed files with 57518 additions and 0 deletions

20
Pods/Manifest.lock generated Normal file
View File

@ -0,0 +1,20 @@
PODS:
- QR-Code-Scanner-iOS (1.0.0)
- SwiftProtobuf (1.12.0)
DEPENDENCIES:
- QR-Code-Scanner-iOS
- SwiftProtobuf (~> 1.0)
SPEC REPOS:
trunk:
- QR-Code-Scanner-iOS
- SwiftProtobuf
SPEC CHECKSUMS:
QR-Code-Scanner-iOS: 6633d5157a50467d66ab357af2432b576c702e5e
SwiftProtobuf: 4ef85479c18ca85b5482b343df9c319c62bda699
PODFILE CHECKSUM: d7310fa0d2b536b55397de242eb9357089f5f87c
COCOAPODS: 1.11.3

1523
Pods/Pods.xcodeproj/project.pbxproj generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1240"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "693D2B0034E6B7BD37FCF5DEA7D2B0F9"
BuildableName = "Pods_wallet_walletUITests.framework"
BlueprintName = "Pods-wallet-walletUITests"
ReferencedContainer = "container:Pods.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1240"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "4179979D0E7E44B4D103FAD5DF24E7E8"
BuildableName = "Pods_wallet.framework"
BlueprintName = "Pods-wallet"
ReferencedContainer = "container:Pods.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1240"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E41B0A6CFA9B0917167875ECF1B1A50D"
BuildableName = "Pods_walletTests.framework"
BlueprintName = "Pods-walletTests"
ReferencedContainer = "container:Pods.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1240"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "03F8264CAE2EC0684FD64871C2FF793E"
BuildableName = "QRCodeScanner.framework"
BlueprintName = "QR-Code-Scanner-iOS"
ReferencedContainer = "container:Pods.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1240"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A5F702E0DA383BC1479572581615A916"
BuildableName = "SwiftProtobuf.framework"
BlueprintName = "SwiftProtobuf"
ReferencedContainer = "container:Pods.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>Pods-wallet-walletUITests.xcscheme</key>
<dict>
<key>isShown</key>
<false/>
<key>orderHint</key>
<integer>1</integer>
</dict>
<key>Pods-wallet.xcscheme</key>
<dict>
<key>isShown</key>
<false/>
<key>orderHint</key>
<integer>0</integer>
</dict>
<key>Pods-walletTests.xcscheme</key>
<dict>
<key>isShown</key>
<false/>
<key>orderHint</key>
<integer>2</integer>
</dict>
<key>QR-Code-Scanner-iOS.xcscheme</key>
<dict>
<key>isShown</key>
<false/>
<key>orderHint</key>
<integer>3</integer>
</dict>
<key>SwiftProtobuf.xcscheme</key>
<dict>
<key>isShown</key>
<false/>
<key>orderHint</key>
<integer>4</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict/>
</dict>
</plist>

19
Pods/QR-Code-Scanner-iOS/LICENSE generated Normal file
View File

@ -0,0 +1,19 @@
Copyright (c) 2020 Applied Recognition, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,160 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16096" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="y2r-2W-Kfy">
<device id="retina4_0" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16086"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Scan Code-->
<scene sceneID="I2H-Ea-9of">
<objects>
<viewController storyboardIdentifier="scanCode" id="y2r-2W-Kfy" customClass="QRCodeScanViewController" customModule="QR_Code_Scanner" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="7Dr-tT-ym7">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="dHG-WP-6So">
<rect key="frame" x="0.0" y="0.0" width="320" height="284"/>
<color key="backgroundColor" white="0.33333333329999998" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Please scan the QR code on your computer's screen." textAlignment="center" lineBreakMode="wordWrap" numberOfLines="4" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="aFZ-zX-6H0">
<rect key="frame" x="24" y="444" width="272" height="100"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="100" id="dau-SG-XQW"/>
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="256" id="m0W-NA-pcB"/>
<constraint firstAttribute="height" constant="100" id="sUP-Zr-vJJ"/>
<constraint firstAttribute="width" constant="272" id="wss-GD-Qsm"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="1000" image="qr_code" translatesAutoresizingMaskIntoConstraints="NO" id="idD-yC-9NX">
<rect key="frame" x="96" y="316" width="128" height="128"/>
<constraints>
<constraint firstAttribute="height" constant="128" id="3zz-o7-Irj"/>
<constraint firstAttribute="width" constant="128" id="inb-Nw-PSU"/>
</constraints>
</imageView>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<constraints>
<constraint firstItem="HcW-ma-4Y9" firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="aFZ-zX-6H0" secondAttribute="bottom" constant="24" id="3Gx-Mz-RjT"/>
<constraint firstItem="aFZ-zX-6H0" firstAttribute="top" secondItem="idD-yC-9NX" secondAttribute="bottom" id="4d2-CW-bq6"/>
<constraint firstItem="dHG-WP-6So" firstAttribute="height" secondItem="7Dr-tT-ym7" secondAttribute="height" multiplier="0.5" id="6D2-cL-pfV"/>
<constraint firstItem="aFZ-zX-6H0" firstAttribute="centerY" secondItem="HcW-ma-4Y9" secondAttribute="centerY" priority="999" constant="200" id="7vv-ud-cQ4"/>
<constraint firstItem="dHG-WP-6So" firstAttribute="leading" secondItem="HcW-ma-4Y9" secondAttribute="leading" id="Cgk-Md-0az"/>
<constraint firstItem="idD-yC-9NX" firstAttribute="centerX" secondItem="7Dr-tT-ym7" secondAttribute="centerX" id="KHv-xR-1AC"/>
<constraint firstItem="dHG-WP-6So" firstAttribute="top" secondItem="7Dr-tT-ym7" secondAttribute="top" id="ZH3-TS-kWK"/>
<constraint firstItem="dHG-WP-6So" firstAttribute="trailing" secondItem="HcW-ma-4Y9" secondAttribute="trailing" id="cy7-ek-IRs"/>
<constraint firstItem="aFZ-zX-6H0" firstAttribute="centerX" secondItem="7Dr-tT-ym7" secondAttribute="centerX" id="dDa-0M-NuA"/>
</constraints>
<viewLayoutGuide key="safeArea" id="HcW-ma-4Y9"/>
</view>
<navigationItem key="navigationItem" title="Scan Code" id="d0Z-d3-Eu5"/>
<simulatedNavigationBarMetrics key="simulatedTopBarMetrics" prompted="NO"/>
<connections>
<outlet property="cameraView" destination="dHG-WP-6So" id="UUo-WY-Ziq"/>
<outlet property="promptLabel" destination="aFZ-zX-6H0" id="Wp8-wK-c3f"/>
<segue destination="ksr-ra-by9" kind="show" identifier="denied" id="hci-Jh-Lpx"/>
<segue destination="JmV-9f-Gyt" kind="show" identifier="restricted" id="N0x-0E-lxh"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="lxj-g1-dsq" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="886.875" y="27.464788732394368"/>
</scene>
<!--Camera Access Denied View Controller-->
<scene sceneID="gyq-DK-avj">
<objects>
<viewController id="ksr-ra-by9" customClass="CameraAccessDeniedViewController" customModule="QR_Code_Scanner" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="anx-7h-CQ8">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Camera access denied. Please go to settings and enable camera." textAlignment="center" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ivo-nD-I5y">
<rect key="frame" x="24" y="444" width="272" height="100"/>
<constraints>
<constraint firstAttribute="width" constant="272" id="R3x-dE-PeA"/>
<constraint firstAttribute="height" constant="100" id="koy-m2-Odt"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="RIk-vx-R8e">
<rect key="frame" x="81.5" y="276" width="157" height="60"/>
<color key="backgroundColor" red="0.21176470589999999" green="0.68627450980000004" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="height" constant="60" id="UgE-k4-NXY"/>
</constraints>
<fontDescription key="fontDescription" type="boldSystem" pointSize="24"/>
<inset key="contentEdgeInsets" minX="20" minY="0.0" maxX="20" maxY="0.0"/>
<state key="normal" title="SETTINGS">
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</state>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="boolean" keyPath="layer.masksToBounds" value="YES"/>
<userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
<integer key="value" value="20"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
<connections>
<action selector="openSettings" destination="ksr-ra-by9" eventType="touchUpInside" id="b3c-NX-isc"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<constraints>
<constraint firstItem="RIk-vx-R8e" firstAttribute="centerY" secondItem="Nn2-2b-I7a" secondAttribute="centerY" id="6xx-R6-0l2"/>
<constraint firstItem="ivo-nD-I5y" firstAttribute="centerX" secondItem="anx-7h-CQ8" secondAttribute="centerX" id="91s-0E-NIN"/>
<constraint firstItem="ivo-nD-I5y" firstAttribute="centerY" secondItem="Nn2-2b-I7a" secondAttribute="centerY" priority="999" constant="200" id="JCs-2s-LNF"/>
<constraint firstItem="RIk-vx-R8e" firstAttribute="centerX" secondItem="Nn2-2b-I7a" secondAttribute="centerX" id="JJQ-e4-tMz"/>
<constraint firstItem="Nn2-2b-I7a" firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="ivo-nD-I5y" secondAttribute="bottom" constant="24" id="QdZ-8V-aTQ"/>
</constraints>
<viewLayoutGuide key="safeArea" id="Nn2-2b-I7a"/>
</view>
<connections>
<outlet property="label" destination="ivo-nD-I5y" id="oS7-BJ-FpM"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="DcX-Tj-tVf" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1748" y="-128"/>
</scene>
<!--View Controller-->
<scene sceneID="2JM-NP-OiX">
<objects>
<viewController id="JmV-9f-Gyt" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="LIk-Xe-Kkl">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Camera access on your device is restricted. Please contact the system administrator." textAlignment="center" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="NV9-3Y-dJa">
<rect key="frame" x="16" y="253.5" width="288" height="61"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<constraints>
<constraint firstItem="NV9-3Y-dJa" firstAttribute="centerY" secondItem="LIk-Xe-Kkl" secondAttribute="centerY" id="9MO-I6-xou"/>
<constraint firstItem="NV9-3Y-dJa" firstAttribute="trailing" secondItem="LIk-Xe-Kkl" secondAttribute="trailingMargin" id="MeX-Ws-kZV"/>
<constraint firstItem="NV9-3Y-dJa" firstAttribute="leading" secondItem="LIk-Xe-Kkl" secondAttribute="leadingMargin" id="gQu-7O-TO6"/>
</constraints>
<viewLayoutGuide key="safeArea" id="jdU-SE-06w"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="LYY-O2-PHk" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1748" y="598"/>
</scene>
</scenes>
<resources>
<image name="qr_code" width="272" height="272"/>
</resources>
</document>

View File

@ -0,0 +1,27 @@
//
// CameraAccessDeniedViewController.swift
//
// Created by Jakub Dolejs on 28/03/2018.
// Copyright © 2018 Applied Recognition Inc. All rights reserved.
//
import UIKit
class CameraAccessDeniedViewController: UIViewController {
@IBOutlet var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
if let appName = Bundle.main.infoDictionary?[kCFBundleNameKey as String] as? String {
label.text = String(format: "Camera access denied. Please go to settings and enable camera for %@.", appName)
}
}
@IBAction func openSettings() {
if let settingsURL = URL(string: UIApplication.openSettingsURLString) {
UIApplication.shared.open(settingsURL, options: [:], completionHandler: nil)
}
}
}

View File

@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "qr_code.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "qr_code@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "qr_code@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 KiB

View File

@ -0,0 +1,186 @@
//
// QRCodeScanViewController.swift
// BFL Authenticator
//
// Created by Jakub Dolejs on 28/03/2018.
// Copyright © 2018 Applied Recognition Inc. All rights reserved.
//
import UIKit
import AVFoundation
public class QRCodeScanViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate {
public weak var delegate: QRCodeScanViewControllerDelegate?
public var prompt: String?
public static func create() -> QRCodeScanViewController {
let storyboard = UIStoryboard(name: "QRCode", bundle: Bundle(for: QRCodeScanViewController.self))
return storyboard.instantiateInitialViewController() as! QRCodeScanViewController
}
private override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
@IBOutlet var cameraView: UIView!
@IBOutlet var promptLabel: UILabel!
var captureSession: AVCaptureSession!
lazy var barcodeScanQueue: DispatchQueue = {
let queue = DispatchQueue.init(label: "com.appliedrec.qrcodescan")
return queue
}()
var avCaptureVideoOrientation: AVCaptureVideoOrientation {
switch UIApplication.shared.statusBarOrientation {
case .portraitUpsideDown:
return AVCaptureVideoOrientation.portraitUpsideDown
case .landscapeRight:
return AVCaptureVideoOrientation.landscapeRight
case .landscapeLeft:
return AVCaptureVideoOrientation.landscapeLeft
default:
return AVCaptureVideoOrientation.portrait
}
}
public override func viewDidLoad() {
super.viewDidLoad()
if let prompt = self.prompt {
self.promptLabel.text = prompt
}
}
public override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
public override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
startCamera()
}
func startCamera() {
let status = AVCaptureDevice.authorizationStatus(for: .video)
switch status {
case .authorized:
self.startScan()
case .notDetermined:
AVCaptureDevice.requestAccess(for: .video) { granted in
if granted {
self.startScan()
} else {
self.showCameraAccessDenied()
}
}
case .denied:
self.showCameraAccessDenied()
case .restricted:
self.showCameraAccessRestricted()
@unknown default:
fatalError()
}
}
public override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.stopCamera()
}
@IBAction func restartQRCodeScan(_ segue: UIStoryboardSegue) {
}
func showCameraAccessDenied() {
DispatchQueue.main.async {
self.performSegue(withIdentifier: "denied", sender: nil)
}
}
func showCameraAccessRestricted() {
DispatchQueue.main.async {
self.performSegue(withIdentifier: "restricted", sender: nil)
}
}
private func startScan() {
self.barcodeScanQueue.async {
self.captureSession = AVCaptureSession()
guard let camera = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) else {
return
}
guard let videoInput = try? AVCaptureDeviceInput(device: camera) else {
return
}
do {
try camera.lockForConfiguration()
if camera.isAutoFocusRangeRestrictionSupported {
camera.autoFocusRangeRestriction = .near
}
if camera.isFocusModeSupported(AVCaptureDevice.FocusMode.continuousAutoFocus) {
camera.focusMode = .continuousAutoFocus
} else if camera.isFocusModeSupported(AVCaptureDevice.FocusMode.autoFocus) {
camera.focusMode = .autoFocus
}
if camera.isFocusPointOfInterestSupported {
camera.focusPointOfInterest = CGPoint(x: 0.5, y: 0.5)
}
camera.unlockForConfiguration()
} catch {
}
if self.captureSession.canAddInput(videoInput) {
self.captureSession.addInput(videoInput)
}
let barcodeOutput = AVCaptureMetadataOutput()
barcodeOutput.setMetadataObjectsDelegate(self, queue: self.barcodeScanQueue)
if self.captureSession.canAddOutput(barcodeOutput) {
self.captureSession.addOutput(barcodeOutput)
if barcodeOutput.availableMetadataObjectTypes.contains(where: { (val) -> Bool in return val == AVMetadataObject.ObjectType.qr }) {
barcodeOutput.metadataObjectTypes = [.qr]
}
}
self.captureSession.startRunning()
DispatchQueue.main.async {
let previewLayer = AVCaptureVideoPreviewLayer(session: self.captureSession)
previewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
previewLayer.frame = self.cameraView.bounds
if previewLayer.connection != nil && previewLayer.connection!.isVideoOrientationSupported {
previewLayer.connection!.videoOrientation = self.avCaptureVideoOrientation
}
self.cameraView.layer.masksToBounds = true
while let sub = self.cameraView.layer.sublayers?.first {
sub.removeFromSuperlayer()
}
self.cameraView.layer.addSublayer(previewLayer)
}
}
}
func stopCamera() {
self.barcodeScanQueue.async {
if self.captureSession != nil {
self.captureSession.stopRunning()
self.captureSession = nil
}
}
}
public func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
if let codeValue = (metadataObjects.first(where: { $0 is AVMetadataMachineReadableCodeObject && $0.type == AVMetadataObject.ObjectType.qr }) as? AVMetadataMachineReadableCodeObject)?.stringValue {
self.stopCamera()
DispatchQueue.main.async {
self.delegate?.qrCodeScanViewController(self, didScanQRCode: codeValue)
self.delegate = nil
}
}
}
}
public protocol QRCodeScanViewControllerDelegate: class {
func qrCodeScanViewController(_ viewController: QRCodeScanViewController, didScanQRCode value: String)
}

54
Pods/QR-Code-Scanner-iOS/README.md generated Normal file
View File

@ -0,0 +1,54 @@
# QR Code Scanner for iOS
Scans QR codes using the device's camera and returns a string value.
## Installation
1. Install [CocoaPods](https://cocoapods.org).
2. Add the following dependency in your **Podspec** file:
~~~ruby
pod 'QR-Code-Scanner-iOS', '~> 1.0'
~~~
3. Run `pod install`.
## Usage
~~~swift
import UIKit
import QRCodeScanner
class MyViewController: UIViewController, QRCodeScanViewControllerDelegate {
/// Start the QR code scan
func scanQRCode() {
// Create an instance of QRCodeScanViewController
let viewController = QRCodeScanViewController.create()
// Set itself as delegate
viewController.delegate = self
// Present the view controller
self.present(viewController, animated: true)
}
// MARK: QRCodeScanViewControllerDelegate
/// Called when the camera scans a QR code
/// - Parameters:
/// - viewController: View controller that scanned the QR code
/// - value: String encoded in the QR code
func qrCodeScanViewController(_ viewController: QRCodeScanViewController, didScanQRCode value: String) {
// Dismiss the view controller
viewController.dismiss(animated: true) {
// Show an alert with the scanned value
let alert = UIAlertController(title: "Scanned value", message: value, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(alert, animated: true)
}
}
}
~~~

211
Pods/SwiftProtobuf/LICENSE.txt generated Normal file
View File

@ -0,0 +1,211 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
## Runtime Library Exception to the Apache 2.0 License: ##
As an exception, if you use this Software to compile your source code and
portions of this Software are embedded into the binary product as a result,
you may redistribute such product without providing attribution as would
otherwise be required by Sections 4(a), 4(b) and 4(d) of the License.

303
Pods/SwiftProtobuf/README.md generated Normal file
View File

@ -0,0 +1,303 @@
<img src="https://swift.org/assets/images/swift.svg" alt="Swift logo" height="70" >
# Swift Protobuf
**Welcome to Swift Protobuf!**
[Apple's Swift programming language](https://swift.org/) is a perfect
complement to [Google's Protocol
Buffer](https://developers.google.com/protocol-buffers/) ("protobuf") serialization
technology.
They both emphasize high performance and programmer safety.
This project provides both the command-line program that adds Swift
code generation to Google's `protoc` and the runtime library that is
necessary for using the generated code.
After using the protoc plugin to generate Swift code from your .proto
files, you will need to add this library to your project.
[![Build and Test](https://github.com/apple/swift-protobuf/workflows/Build%20and%20Test/badge.svg)](https://github.com/apple/swift-protobuf/actions?query=workflow%3A%22Build+and+Test%22)
[![Check Upstream Protos](https://github.com/apple/swift-protobuf/workflows/Check%20Upstream%20Proto%20Files/badge.svg)](https://github.com/apple/swift-protobuf/actions?query=workflow%3A%22Check+Upstream+Proto+Files%22)
[![Run Conformance Tests](https://github.com/apple/swift-protobuf/workflows/Run%20Conformance%20Tests/badge.svg)](https://github.com/apple/swift-protobuf/actions?query=workflow%3A%22Run+Conformance+Tests%22)
# Features of SwiftProtobuf
SwiftProtobuf offers many advantages over alternative serialization
systems:
* Safety: The protobuf code-generation system avoids the
errors that are common with hand-built serialization code.
* Correctness: SwiftProtobuf passes both its own extensive
test suite and Google's full conformance test for protobuf
correctness.
* Schema-driven: Defining your data structures in a separate
`.proto` schema file clearly documents your communications
conventions.
* Idiomatic: SwiftProtobuf takes full advantage of the Swift language.
In particular, all generated types provide full Swift copy-on-write
value semantics.
* Efficient binary serialization: The `.serializedData()`
method returns a `Data` with a compact binary form of your data.
You can deserialize the data using the `init(serializedData:)`
initializer.
* Standard JSON serialization: The `.jsonUTF8Data()` method returns a JSON
form of your data that can be parsed with the `init(jsonUTF8Data:)`
initializer.
* Hashable, Equatable: The generated struct can be put into a
`Set<>` or `Dictionary<>`.
* Performant: The binary and JSON serializers have been
extensively optimized.
* Extensible: You can add your own Swift extensions to any
of the generated types.
Best of all, you can take the same `.proto` file and generate
Java, C++, Python, or Objective-C for use on other platforms. The
generated code for those languages will use the exact same
serialization and deserialization conventions as SwiftProtobuf, making
it easy to exchange serialized data in binary or JSON forms, with no
additional effort on your part.
# Documentation
More information is available in the associated documentation:
* [Google's protobuf documentation](https://developers.google.com/protocol-buffers/)
provides general information about protocol buffers, the protoc compiler,
and how to use protocol buffers with C++, Java, and other languages.
* [PLUGIN.md](Documentation/PLUGIN.md) documents the `protoc-gen-swift`
plugin that adds Swift support to the `protoc` program
* [API.md](Documentation/API.md) documents how to use the generated code.
This is recommended reading for anyone using SwiftProtobuf in their
project.
* [cocoadocs.org](http://cocoadocs.org/docsets/SwiftProtobuf/) has the generated
API documentation
* [INTERNALS.md](Documentation/INTERNALS.md) documents the internal structure
of the generated code and the library. This
should only be needed by folks interested in working on SwiftProtobuf
itself.
* [STYLE_GUIDELINES.md](Documentation/STYLE_GUIDELINES.md) documents the style
guidelines we have adopted in our codebase if you are interested in
contributing
# Getting Started
If you've worked with Protocol Buffers before, adding Swift support is very
simple: you just need to build the `protoc-gen-swift` program and copy it into
your PATH.
The `protoc` program will find and use it automatically, allowing you
to build Swift sources for your proto files.
You will also, of course, need to add the SwiftProtobuf runtime library to
your project as explained below.
## System Requirements
To use Swift with Protocol buffers, you'll need:
* A Swift 4.2 or later compiler (Xcode 10.0 or later). Support is included
for the Swift Package Manager; or using the included Xcode project. The Swift
protobuf project is being developed and tested against the latest release
version of Swift available from [Swift.org](https://swift.org)
* Google's protoc compiler. The Swift protoc plugin is being actively
developed and tested against the latest protobuf sources.
The SwiftProtobuf tests need a version of protoc which supports the
`swift_prefix` option (introduced in protoc 3.2.0).
It may work with earlier versions of protoc.
You can get recent versions from
[Google's github repository](https://github.com/protocolbuffers/protobuf).
## Building and Installing the Code Generator Plugin
To translate `.proto` files into Swift, you will need both Google's
protoc compiler and the SwiftProtobuf code generator plugin.
Building the plugin should be simple on any supported Swift platform:
```
$ git clone https://github.com/apple/swift-protobuf.git
$ cd swift-protobuf
```
Pick what released version of SwiftProtobuf you are going to use. You can get
a list of tags with:
```
$ git tag -l
```
Once you pick the version you will use, set your local state to match, and
build the protoc plugin:
```
$ git checkout tags/[tag_name]
$ swift build -c release
```
This will create a binary called `protoc-gen-swift` in the `.build/release`
directory.
To install, just copy this one executable into a directory that is
part of your `PATH` environment variable.
NOTE: The Swift runtime support is now included with macOS. If you are
using old Xcode versions or are on older system versions, you might need
to use also use `--static-swift-stdlib` with `swift build`.
### Alternatively install via Homebrew
If you prefer using [Homebrew](https://brew.sh):
```
$ brew install swift-protobuf
```
This will install `protoc` compiler and Swift code generator plugin.
## Converting .proto files into Swift
To generate Swift output for your .proto files, you run the `protoc` command as
usual, using the `--swift_out=<directory>` option:
```
$ protoc --swift_out=. my.proto
```
The `protoc` program will automatically look for `protoc-gen-swift` in your
`PATH` and use it.
Each `.proto` input file will get translated to a corresponding `.pb.swift`
file in the output directory.
More information about building and using `protoc-gen-swift` can be found
in the [detailed Plugin documentation](Documentation/PLUGIN.md).
## Adding the SwiftProtobuf library to your project...
To use the generated code, you need to include the `SwiftProtobuf` library
module in your project. How you do this will vary depending on how
you're building your project. Note that in all cases, we strongly recommend
that you use the version of the SwiftProtobuf library that corresponds to
the version of `protoc-gen-swift` you used to generate the code.
### ...using `swift build`
After copying the `.pb.swift` files into your project, you will need to add the
[SwiftProtobuf library](https://github.com/apple/swift-protobuf) to your
project to support the generated code.
If you are using the Swift Package Manager, add a dependency to your
`Package.swift` file and import the `SwiftProtobuf` library into the desired
targets. Adjust the `"1.6.0"` here to match the `[tag_name]` you used to build
the plugin above:
```swift
dependencies: [
.package(name: "SwiftProtobuf", url: "https://github.com/apple/swift-protobuf.git", from: "1.6.0"),
],
targets: [
.target(name: "MyTarget", dependencies: ["SwiftProtobuf"]),
]
```
### ...using Xcode
If you are using Xcode, then you should:
* Add the `.pb.swift` source files generated from your protos directly to your
project
* Add the appropriate `SwiftProtobuf_<platform>` target from the Xcode project
in this package to your project.
### ...using CocoaPods
If you're using CocoaPods, add this to your `Podfile` adjusting the `:tag` to
match the `[tag_name]` you used to build the plugin above:
```ruby
pod 'SwiftProtobuf', '~> 1.0'
```
And run `pod install`.
NOTE: CocoaPods 1.7 or newer is required.
### ...using Carthage
If you're using Carthage, add this to your `Cartfile` but adjust the tag to match the `[tag_name]` you used to build the plugin above:
```ruby
github "apple/swift-protobuf" ~> 1.0
```
Run `carthage update` and drag `SwiftProtobuf.framework` into your Xcode.project.
# Quick Start
Once you have installed the code generator, used it to
generate Swift code from your `.proto` file, and
added the SwiftProtobuf library to your project, you can
just use the generated types as you would any other Swift
struct.
For example, you might start with the following very simple
proto file:
```protobuf
syntax = "proto3";
message BookInfo {
int64 id = 1;
string title = 2;
string author = 3;
}
```
Then generate Swift code using:
```
$ protoc --swift_out=. DataModel.proto
```
The generated code will expose a Swift property for
each of the proto fields as well as a selection
of serialization and deserialization capabilities:
```swift
// Create a BookInfo object and populate it:
var info = BookInfo()
info.id = 1734
info.title = "Really Interesting Book"
info.author = "Jane Smith"
// As above, but generating a read-only value:
let info2 = BookInfo.with {
$0.id = 1735
$0.title = "Even More Interesting"
$0.author = "Jane Q. Smith"
}
// Serialize to binary protobuf format:
let binaryData: Data = try info.serializedData()
// Deserialize a received Data object from `binaryData`
let decodedInfo = try BookInfo(serializedData: binaryData)
// Serialize to JSON format as a Data object
let jsonData: Data = try info.jsonUTF8Data()
// Deserialize from JSON format from `jsonData`
let receivedFromJSON = try BookInfo(jsonUTF8Data: jsonData)
```
You can find more information in the detailed
[API Documentation](Documentation/API.md).
## Report any issues
If you run into problems, please send us a detailed report.
At a minimum, please include:
* The specific operating system and version (for example, "macOS 10.12.1" or
"Ubuntu 16.10")
* The version of Swift you have installed (from `swift --version`)
* The version of the protoc compiler you are working with from
`protoc --version`
* The specific version of this source code (you can use `git log -1` to get the
latest commit ID)
* Any local changes you may have

View File

@ -0,0 +1,476 @@
// Sources/SwiftProtobuf/AnyMessageStorage.swift - Custom stroage for Any WKT
//
// Copyright (c) 2014 - 2017 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Hand written storage class for Google_Protobuf_Any to support on demand
/// transforms between the formats.
///
// -----------------------------------------------------------------------------
import Foundation
#if !swift(>=4.2)
private let i_2166136261 = Int(bitPattern: 2166136261)
private let i_16777619 = Int(16777619)
#endif
fileprivate func serializeAnyJSON(
for message: Message,
typeURL: String,
options: JSONEncodingOptions
) throws -> String {
var visitor = try JSONEncodingVisitor(type: type(of: message), options: options)
visitor.startObject(message: message)
visitor.encodeField(name: "@type", stringValue: typeURL)
if let m = message as? _CustomJSONCodable {
let value = try m.encodedJSONString(options: options)
visitor.encodeField(name: "value", jsonText: value)
} else {
try message.traverse(visitor: &visitor)
}
visitor.endObject()
return visitor.stringResult
}
fileprivate func emitVerboseTextForm(visitor: inout TextFormatEncodingVisitor, message: Message, typeURL: String) {
let url: String
if typeURL.isEmpty {
url = buildTypeURL(forMessage: message, typePrefix: defaultAnyTypeURLPrefix)
} else {
url = typeURL
}
visitor.visitAnyVerbose(value: message, typeURL: url)
}
fileprivate func asJSONObject(body: Data) -> Data {
let asciiOpenCurlyBracket = UInt8(ascii: "{")
let asciiCloseCurlyBracket = UInt8(ascii: "}")
var result = Data([asciiOpenCurlyBracket])
result.append(body)
result.append(asciiCloseCurlyBracket)
return result
}
fileprivate func unpack(contentJSON: Data,
extensions: ExtensionMap,
options: JSONDecodingOptions,
as messageType: Message.Type) throws -> Message {
guard messageType is _CustomJSONCodable.Type else {
let contentJSONAsObject = asJSONObject(body: contentJSON)
return try messageType.init(jsonUTF8Data: contentJSONAsObject, extensions: extensions, options: options)
}
var value = String()
try contentJSON.withUnsafeBytes { (body: UnsafeRawBufferPointer) in
if body.count > 0 {
var scanner = JSONScanner(source: body, options: options, extensions: extensions)
let key = try scanner.nextQuotedString()
if key != "value" {
// The only thing within a WKT should be "value".
throw AnyUnpackError.malformedWellKnownTypeJSON
}
try scanner.skipRequiredColon() // Can't fail
value = try scanner.skip()
if !scanner.complete {
// If that wasn't the end, then there was another key,
// and WKTs should only have the one.
throw AnyUnpackError.malformedWellKnownTypeJSON
}
}
}
return try messageType.init(jsonString: value, extensions: extensions, options: options)
}
internal class AnyMessageStorage {
// The two properties generated Google_Protobuf_Any will reference.
var _typeURL = String()
var _value: Data {
// Remapped to the internal `state`.
get {
switch state {
case .binary(let value):
return value
case .message(let message):
do {
return try message.serializedData(partial: true)
} catch {
return Data()
}
case .contentJSON(let contentJSON, let options):
guard let messageType = Google_Protobuf_Any.messageType(forTypeURL: _typeURL) else {
return Data()
}
do {
let m = try unpack(contentJSON: contentJSON,
extensions: SimpleExtensionMap(),
options: options,
as: messageType)
return try m.serializedData(partial: true)
} catch {
return Data()
}
}
}
set {
state = .binary(newValue)
}
}
enum InternalState {
// a serialized binary
// Note: Unlike contentJSON below, binary does not bother to capture the
// decoding options. This is because the actual binary format is the binary
// blob, i.e. - when decoding from binary, the spec doesn't include decoding
// the binary blob, it is pass through. Instead there is a public api for
// unpacking that takes new options when a developer decides to decode it.
case binary(Data)
// a message
case message(Message)
// parsed JSON with the @type removed and the decoding options.
case contentJSON(Data, JSONDecodingOptions)
}
var state: InternalState = .binary(Data())
static let defaultInstance = AnyMessageStorage()
private init() {}
init(copying source: AnyMessageStorage) {
_typeURL = source._typeURL
state = source.state
}
func isA<M: Message>(_ type: M.Type) -> Bool {
if _typeURL.isEmpty {
return false
}
let encodedType = typeName(fromURL: _typeURL)
return encodedType == M.protoMessageName
}
// This is only ever called with the expectation that target will be fully
// replaced during the unpacking and never as a merge.
func unpackTo<M: Message>(
target: inout M,
extensions: ExtensionMap?,
options: BinaryDecodingOptions
) throws {
guard isA(M.self) else {
throw AnyUnpackError.typeMismatch
}
switch state {
case .binary(let data):
target = try M(serializedData: data, extensions: extensions, partial: true, options: options)
case .message(let msg):
if let message = msg as? M {
// Already right type, copy it over.
target = message
} else {
// Different type, serialize and parse.
let data = try msg.serializedData(partial: true)
target = try M(serializedData: data, extensions: extensions, partial: true)
}
case .contentJSON(let contentJSON, let options):
target = try unpack(contentJSON: contentJSON,
extensions: extensions ?? SimpleExtensionMap(),
options: options,
as: M.self) as! M
}
}
// Called before the message is traversed to do any error preflights.
// Since traverse() will use _value, this is our chance to throw
// when _value can't.
func preTraverse() throws {
switch state {
case .binary:
// Nothing to be checked.
break
case .message:
// When set from a developer provided message, partial support
// is done. Any message that comes in from another format isn't
// checked, and transcoding the isInitialized requirement is
// never inserted.
break
case .contentJSON(let contentJSON, let options):
// contentJSON requires we have the type available for decoding
guard let messageType = Google_Protobuf_Any.messageType(forTypeURL: _typeURL) else {
throw BinaryEncodingError.anyTranscodeFailure
}
do {
// Decodes the full JSON and then discard the result.
// The regular traversal will decode this again by querying the
// `value` field, but that has no way to fail. As a result,
// we need this to accurately handle decode errors.
_ = try unpack(contentJSON: contentJSON,
extensions: SimpleExtensionMap(),
options: options,
as: messageType)
} catch {
throw BinaryEncodingError.anyTranscodeFailure
}
}
}
}
/// Custom handling for Text format.
extension AnyMessageStorage {
func decodeTextFormat(typeURL url: String, decoder: inout TextFormatDecoder) throws {
// Decoding the verbose form requires knowing the type.
_typeURL = url
guard let messageType = Google_Protobuf_Any.messageType(forTypeURL: url) else {
// The type wasn't registered, can't parse it.
throw TextFormatDecodingError.malformedText
}
let terminator = try decoder.scanner.skipObjectStart()
var subDecoder = try TextFormatDecoder(messageType: messageType, scanner: decoder.scanner, terminator: terminator)
if messageType == Google_Protobuf_Any.self {
var any = Google_Protobuf_Any()
try any.decodeTextFormat(decoder: &subDecoder)
state = .message(any)
} else {
var m = messageType.init()
try m.decodeMessage(decoder: &subDecoder)
state = .message(m)
}
decoder.scanner = subDecoder.scanner
if try decoder.nextFieldNumber() != nil {
// Verbose any can never have additional keys.
throw TextFormatDecodingError.malformedText
}
}
// Specialized traverse for writing out a Text form of the Any.
// This prefers the more-legible "verbose" format if it can
// use it, otherwise will fall back to simpler forms.
internal func textTraverse(visitor: inout TextFormatEncodingVisitor) {
switch state {
case .binary(let valueData):
if let messageType = Google_Protobuf_Any.messageType(forTypeURL: _typeURL) {
// If we can decode it, we can write the readable verbose form:
do {
let m = try messageType.init(serializedData: valueData, partial: true)
emitVerboseTextForm(visitor: &visitor, message: m, typeURL: _typeURL)
return
} catch {
// Fall through to just print the type and raw binary data
}
}
if !_typeURL.isEmpty {
try! visitor.visitSingularStringField(value: _typeURL, fieldNumber: 1)
}
if !valueData.isEmpty {
try! visitor.visitSingularBytesField(value: valueData, fieldNumber: 2)
}
case .message(let msg):
emitVerboseTextForm(visitor: &visitor, message: msg, typeURL: _typeURL)
case .contentJSON(let contentJSON, let options):
// If we can decode it, we can write the readable verbose form:
if let messageType = Google_Protobuf_Any.messageType(forTypeURL: _typeURL) {
do {
let m = try unpack(contentJSON: contentJSON,
extensions: SimpleExtensionMap(),
options: options,
as: messageType)
emitVerboseTextForm(visitor: &visitor, message: m, typeURL: _typeURL)
return
} catch {
// Fall through to just print the raw JSON data
}
}
if !_typeURL.isEmpty {
try! visitor.visitSingularStringField(value: _typeURL, fieldNumber: 1)
}
// Build a readable form of the JSON:
let contentJSONAsObject = asJSONObject(body: contentJSON)
visitor.visitAnyJSONDataField(value: contentJSONAsObject)
}
}
}
/// The obvious goal for Hashable/Equatable conformance would be for
/// hash and equality to behave as if we always decoded the inner
/// object and hashed or compared that. Unfortunately, Any typically
/// stores serialized contents and we don't always have the ability to
/// deserialize it. Since none of our supported serializations are
/// fully deterministic, we can't even ensure that equality will
/// behave this way when the Any contents are in the same
/// serialization.
///
/// As a result, we can only really perform a "best effort" equality
/// test. Of course, regardless of the above, we must guarantee that
/// hashValue is compatible with equality.
extension AnyMessageStorage {
#if swift(>=4.2)
// Can't use _valueData for a few reasons:
// 1. Since decode is done on demand, two objects could be equal
// but created differently (one from JSON, one for Message, etc.),
// and the hash values have to be equal even if we don't have data
// yet.
// 2. map<> serialization order is undefined. At the time of writing
// the Swift, Objective-C, and Go runtimes all tend to have random
// orders, so the messages could be identical, but in binary form
// they could differ.
public func hash(into hasher: inout Hasher) {
if !_typeURL.isEmpty {
hasher.combine(_typeURL)
}
}
#else // swift(>=4.2)
var hashValue: Int {
var hash: Int = i_2166136261
if !_typeURL.isEmpty {
hash = (hash &* i_16777619) ^ _typeURL.hashValue
}
return hash
}
#endif // swift(>=4.2)
func isEqualTo(other: AnyMessageStorage) -> Bool {
if (_typeURL != other._typeURL) {
return false
}
// Since the library does lazy Any decode, equality is a very hard problem.
// It things exactly match, that's pretty easy, otherwise, one ends up having
// to error on saying they aren't equal.
//
// The best option would be to have Message forms and compare those, as that
// removes issues like map<> serialization order, some other protocol buffer
// implementation details/bugs around serialized form order, etc.; but that
// would also greatly slow down equality tests.
//
// Do our best to compare what is present have...
// If both have messages, check if they are the same.
if case .message(let myMsg) = state, case .message(let otherMsg) = other.state, type(of: myMsg) == type(of: otherMsg) {
// Since the messages are known to be same type, we can claim both equal and
// not equal based on the equality comparison.
return myMsg.isEqualTo(message: otherMsg)
}
// If both have serialized data, and they exactly match; the messages are equal.
// Because there could be map in the message, the fact that the data isn't the
// same doesn't always mean the messages aren't equal. Likewise, the binary could
// have been created by a library that doesn't order the fields, or the binary was
// created using the appending ability in of the binary format.
if case .binary(let myValue) = state, case .binary(let otherValue) = other.state, myValue == otherValue {
return true
}
// If both have contentJSON, and they exactly match; the messages are equal.
// Because there could be map in the message (or the JSON could just be in a different
// order), the fact that the JSON isn't the same doesn't always mean the messages
// aren't equal.
if case .contentJSON(let myJSON, _) = state,
case .contentJSON(let otherJSON, _) = other.state,
myJSON == otherJSON {
return true
}
// Out of options. To do more compares, the states conversions would have to be
// done to do comparisions; and since equality can be used somewhat removed from
// a developer (if they put protos in a Set, use them as keys to a Dictionary, etc),
// the conversion cost might be to high for those uses. Give up and say they aren't equal.
return false
}
}
// _CustomJSONCodable support for Google_Protobuf_Any
extension AnyMessageStorage {
// Override the traversal-based JSON encoding
// This builds an Any JSON representation from one of:
// * The message we were initialized with,
// * The JSON fields we last deserialized, or
// * The protobuf field we were deserialized from.
// The last case requires locating the type, deserializing
// into an object, then reserializing back to JSON.
func encodedJSONString(options: JSONEncodingOptions) throws -> String {
switch state {
case .binary(let valueData):
// Transcode by decoding the binary data to a message object
// and then recode back into JSON.
guard let messageType = Google_Protobuf_Any.messageType(forTypeURL: _typeURL) else {
// If we don't have the type available, we can't decode the
// binary value, so we're stuck. (The Google spec does not
// provide a way to just package the binary value for someone
// else to decode later.)
throw JSONEncodingError.anyTranscodeFailure
}
let m = try messageType.init(serializedData: valueData, partial: true)
return try serializeAnyJSON(for: m, typeURL: _typeURL, options: options)
case .message(let msg):
// We should have been initialized with a typeURL, but
// ensure it wasn't cleared.
let url = !_typeURL.isEmpty ? _typeURL : buildTypeURL(forMessage: msg, typePrefix: defaultAnyTypeURLPrefix)
return try serializeAnyJSON(for: msg, typeURL: url, options: options)
case .contentJSON(let contentJSON, _):
var jsonEncoder = JSONEncoder()
jsonEncoder.startObject()
jsonEncoder.startField(name: "@type")
jsonEncoder.putStringValue(value: _typeURL)
if !contentJSON.isEmpty {
jsonEncoder.append(staticText: ",")
// NOTE: This doesn't really take `options` into account since it is
// just reflecting out what was taken in originally.
jsonEncoder.append(utf8Data: contentJSON)
}
jsonEncoder.endObject()
return jsonEncoder.stringResult
}
}
// TODO: If the type is well-known or has already been registered,
// we should consider decoding eagerly. Eager decoding would
// catch certain errors earlier (good) but would probably be
// a performance hit if the Any contents were never accessed (bad).
// Of course, we can't always decode eagerly (we don't always have the
// message type available), so the deferred logic here is still needed.
func decodeJSON(from decoder: inout JSONDecoder) throws {
try decoder.scanner.skipRequiredObjectStart()
// Reset state
_typeURL = String()
state = .binary(Data())
if decoder.scanner.skipOptionalObjectEnd() {
return
}
var jsonEncoder = JSONEncoder()
while true {
let key = try decoder.scanner.nextQuotedString()
try decoder.scanner.skipRequiredColon()
if key == "@type" {
_typeURL = try decoder.scanner.nextQuotedString()
} else {
jsonEncoder.startField(name: key)
let keyValueJSON = try decoder.scanner.skip()
jsonEncoder.append(text: keyValueJSON)
}
if decoder.scanner.skipOptionalObjectEnd() {
// Capture the options, but set the messageDepthLimit to be what
// was left right now, as that is the limit when the JSON is finally
// parsed.
var updatedOptions = decoder.options
updatedOptions.messageDepthLimit = decoder.scanner.recursionBudget
state = .contentJSON(jsonEncoder.dataResult, updatedOptions)
return
}
try decoder.scanner.skipRequiredComma()
}
}
}

View File

@ -0,0 +1,37 @@
// Sources/SwiftProtobuf/AnyUnpackError.swift - Any Unpacking Errors
//
// Copyright (c) 2014 - 2017 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Errors that can be throw when unpacking a Google_Protobuf_Any.
///
// -----------------------------------------------------------------------------
/// Describes errors that can occur when unpacking an `Google_Protobuf_Any`
/// message.
///
/// `Google_Protobuf_Any` messages can be decoded from protobuf binary, text
/// format, or JSON. The contents are not parsed immediately; the raw data is
/// held in the `Google_Protobuf_Any` message until you `unpack()` it into a
/// message. At this time, any error can occur that might have occurred from a
/// regular decoding operation. There are also other errors that can occur due
/// to problems with the `Any` value's structure.
public enum AnyUnpackError: Error {
/// The `type_url` field in the `Google_Protobuf_Any` message did not match
/// the message type provided to the `unpack()` method.
case typeMismatch
/// Well-known types being decoded from JSON must have only two fields: the
/// `@type` field and a `value` field containing the specialized JSON coding
/// of the well-known type.
case malformedWellKnownTypeJSON
/// The `Google_Protobuf_Any` message was malformed in some other way not
/// covered by the other error cases.
case malformedAnyField
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,44 @@
// Sources/SwiftProtobuf/BinaryDecodingError.swift - Protobuf binary decoding errors
//
// Copyright (c) 2014 - 2017 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Protobuf binary format decoding errors
///
// -----------------------------------------------------------------------------
/// Describes errors that can occur when decoding a message from binary format.
public enum BinaryDecodingError: Error {
/// Extraneous data remained after decoding should have been complete.
case trailingGarbage
/// The decoder unexpectedly reached the end of the data before it was
/// expected.
case truncated
/// A string field was not encoded as valid UTF-8.
case invalidUTF8
/// The binary data was malformed in some way, such as an invalid wire format
/// or field tag.
case malformedProtobuf
/// The definition of the message or one of its nested messages has required
/// fields but the binary data did not include values for them. You must pass
/// `partial: true` during decoding if you wish to explicitly ignore missing
/// required fields.
case missingRequiredFields
/// An internal error happened while decoding. If this is ever encountered,
/// please file an issue with SwiftProtobuf with as much details as possible
/// for what happened (proto definitions, bytes being decoded (if possible)).
case internalExtensionError
/// Reached the nesting limit for messages within messages while decoding.
case messageDepthLimit
}

View File

@ -0,0 +1,39 @@
// Sources/SwiftProtobuf/BinaryDecodingOptions.swift - Binary decoding options
//
// Copyright (c) 2014 - 2017 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Binary decoding options
///
// -----------------------------------------------------------------------------
/// Options for JSONDecoding.
public struct BinaryDecodingOptions {
/// The maximum nesting of message with messages. The default is 100.
///
/// To prevent corrupt or malicious messages from causing stack overflows,
/// this controls how deep messages can be nested within other messages
/// while parsing.
public var messageDepthLimit: Int = 100
/// Discard unknown fields while parsing. The default is false, so parsering
/// does not discard unknown fields.
///
/// The Protobuf binary format allows unknown fields to be still parsed
/// so the schema can be expanded without requiring all readers to be updated.
/// This works in part by haivng any unknown fields preserved so they can
/// be relayed on without loss. For a while the proto3 syntax definition
/// called for unknown fields to be dropped, but that lead to problems in
/// some case. The default is to follow the spec and keep them, but setting
/// this option to `true` allows a developer to strip them during a parse
/// in case they have a specific need to drop the unknown fields from the
/// object graph being created.
public var discardUnknownFields: Bool = false
public init() {}
}

View File

@ -0,0 +1,232 @@
// Sources/SwiftProtobuf/BinaryDelimited.swift - Delimited support
//
// Copyright (c) 2014 - 2017 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Helpers to read/write message with a length prefix.
///
// -----------------------------------------------------------------------------
import Foundation
/// Helper methods for reading/writing messages with a length prefix.
public enum BinaryDelimited {
/// Additional errors for delimited message handing.
public enum Error: Swift.Error {
/// If a read/write to the stream fails, but the stream's `streamError` is nil,
/// this error will be throw instead since the stream didn't provide anything
/// more specific. A common cause for this can be failing to open the stream
/// before trying to read/write to it.
case unknownStreamError
/// While reading/writing to the stream, less than the expected bytes was
/// read/written.
case truncated
}
/// Serialize a single size-delimited message from the given stream. Delimited
/// format allows a single file or stream to contain multiple messages,
/// whereas normally writing multiple non-delimited messages to the same
/// stream would cause them to be merged. A delimited message is a varint
/// encoding the message size followed by a message of exactly that size.
///
/// - Parameters:
/// - message: The message to be written.
/// - to: The `OutputStream` to write the message to. The stream is
/// is assumed to be ready to be written to.
/// - partial: If `false` (the default), this method will check
/// `Message.isInitialized` before encoding to verify that all required
/// fields are present. If any are missing, this method throws
/// `BinaryEncodingError.missingRequiredFields`.
/// - Throws: `BinaryEncodingError` if encoding fails, throws
/// `BinaryDelimited.Error` for some writing errors, or the
/// underlying `OutputStream.streamError` for a stream error.
public static func serialize(
message: Message,
to stream: OutputStream,
partial: Bool = false
) throws {
// TODO: Revisit to avoid the extra buffering when encoding is streamed in general.
let serialized = try message.serializedData(partial: partial)
let totalSize = Varint.encodedSize(of: UInt64(serialized.count)) + serialized.count
var data = Data(count: totalSize)
data.withUnsafeMutableBytes { (body: UnsafeMutableRawBufferPointer) in
if let baseAddress = body.baseAddress, body.count > 0 {
var encoder = BinaryEncoder(forWritingInto: baseAddress)
encoder.putBytesValue(value: serialized)
}
}
var written: Int = 0
data.withUnsafeBytes { (body: UnsafeRawBufferPointer) in
if let baseAddress = body.baseAddress, body.count > 0 {
// This assumingMemoryBound is technically unsafe, but without SR-11078
// (https://bugs.swift.org/browse/SR-11087) we don't have another option.
// It should be "safe enough".
let pointer = baseAddress.assumingMemoryBound(to: UInt8.self)
written = stream.write(pointer, maxLength: totalSize)
}
}
if written != totalSize {
if written == -1 {
if let streamError = stream.streamError {
throw streamError
}
throw BinaryDelimited.Error.unknownStreamError
}
throw BinaryDelimited.Error.truncated
}
}
/// Reads a single size-delimited message from the given stream. Delimited
/// format allows a single file or stream to contain multiple messages,
/// whereas normally parsing consumes the entire input. A delimited message
/// is a varint encoding the message size followed by a message of exactly
/// exactly that size.
///
/// - Parameters:
/// - messageType: The type of message to read.
/// - from: The `InputStream` to read the data from. The stream is assumed
/// to be ready to read from.
/// - extensions: An `ExtensionMap` used to look up and decode any
/// extensions in this message or messages nested within this message's
/// fields.
/// - partial: If `false` (the default), this method will check
/// `Message.isInitialized` before encoding to verify that all required
/// fields are present. If any are missing, this method throws
/// `BinaryEncodingError.missingRequiredFields`.
/// - options: The BinaryDecodingOptions to use.
/// - Returns: The message read.
/// - Throws: `BinaryDecodingError` if decoding fails, throws
/// `BinaryDelimited.Error` for some reading errors, and the
/// underlying InputStream.streamError for a stream error.
public static func parse<M: Message>(
messageType: M.Type,
from stream: InputStream,
extensions: ExtensionMap? = nil,
partial: Bool = false,
options: BinaryDecodingOptions = BinaryDecodingOptions()
) throws -> M {
var message = M()
try merge(into: &message,
from: stream,
extensions: extensions,
partial: partial,
options: options)
return message
}
/// Updates the message by reading a single size-delimited message from
/// the given stream. Delimited format allows a single file or stream to
/// contain multiple messages, whereas normally parsing consumes the entire
/// input. A delimited message is a varint encoding the message size
/// followed by a message of exactly that size.
///
/// - Note: If this method throws an error, the message may still have been
/// partially mutated by the binary data that was decoded before the error
/// occurred.
///
/// - Parameters:
/// - mergingTo: The message to merge the data into.
/// - from: The `InputStream` to read the data from. The stream is assumed
/// to be ready to read from.
/// - extensions: An `ExtensionMap` used to look up and decode any
/// extensions in this message or messages nested within this message's
/// fields.
/// - partial: If `false` (the default), this method will check
/// `Message.isInitialized` before encoding to verify that all required
/// fields are present. If any are missing, this method throws
/// `BinaryEncodingError.missingRequiredFields`.
/// - options: The BinaryDecodingOptions to use.
/// - Throws: `BinaryDecodingError` if decoding fails, throws
/// `BinaryDelimited.Error` for some reading errors, and the
/// underlying InputStream.streamError for a stream error.
public static func merge<M: Message>(
into message: inout M,
from stream: InputStream,
extensions: ExtensionMap? = nil,
partial: Bool = false,
options: BinaryDecodingOptions = BinaryDecodingOptions()
) throws {
let length = try Int(decodeVarint(stream))
if length == 0 {
// The message was all defaults, nothing to actually read.
return
}
var data = Data(count: length)
var bytesRead: Int = 0
data.withUnsafeMutableBytes { (body: UnsafeMutableRawBufferPointer) in
if let baseAddress = body.baseAddress, body.count > 0 {
// This assumingMemoryBound is technically unsafe, but without SR-11078
// (https://bugs.swift.org/browse/SR-11087) we don't have another option.
// It should be "safe enough".
let pointer = baseAddress.assumingMemoryBound(to: UInt8.self)
bytesRead = stream.read(pointer, maxLength: length)
}
}
if bytesRead != length {
if bytesRead == -1 {
if let streamError = stream.streamError {
throw streamError
}
throw BinaryDelimited.Error.unknownStreamError
}
throw BinaryDelimited.Error.truncated
}
try message.merge(serializedData: data,
extensions: extensions,
partial: partial,
options: options)
}
}
// TODO: This should go away when encoding/decoding are more stream based
// as that should provide a more direct way to do this. This is basically
// a rewrite of BinaryDecoder.decodeVarint().
internal func decodeVarint(_ stream: InputStream) throws -> UInt64 {
// Buffer to reuse within nextByte.
let readBuffer = UnsafeMutablePointer<UInt8>.allocate(capacity: 1)
#if swift(>=4.1)
defer { readBuffer.deallocate() }
#else
defer { readBuffer.deallocate(capacity: 1) }
#endif
func nextByte() throws -> UInt8 {
let bytesRead = stream.read(readBuffer, maxLength: 1)
if bytesRead != 1 {
if bytesRead == -1 {
if let streamError = stream.streamError {
throw streamError
}
throw BinaryDelimited.Error.unknownStreamError
}
throw BinaryDelimited.Error.truncated
}
return readBuffer[0]
}
var value: UInt64 = 0
var shift: UInt64 = 0
while true {
let c = try nextByte()
value |= UInt64(c & 0x7f) << shift
if c & 0x80 == 0 {
return value
}
shift += 7
if shift > 63 {
throw BinaryDecodingError.malformedProtobuf
}
}
}

View File

@ -0,0 +1,155 @@
// Sources/SwiftProtobuf/BinaryEncoder.swift - Binary encoding support
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Core support for protobuf binary encoding. Note that this is built
/// on the general traversal machinery.
///
// -----------------------------------------------------------------------------
import Foundation
/*
* Encoder for Binary Protocol Buffer format
*/
internal struct BinaryEncoder {
private var pointer: UnsafeMutableRawPointer
init(forWritingInto pointer: UnsafeMutableRawPointer) {
self.pointer = pointer
}
private mutating func append(_ byte: UInt8) {
pointer.storeBytes(of: byte, as: UInt8.self)
pointer = pointer.advanced(by: 1)
}
private mutating func append(contentsOf data: Data) {
data.withUnsafeBytes { dataPointer in
if let baseAddress = dataPointer.baseAddress, dataPointer.count > 0 {
pointer.copyMemory(from: baseAddress, byteCount: dataPointer.count)
pointer = pointer.advanced(by: dataPointer.count)
}
}
}
@discardableResult
private mutating func append(contentsOf bufferPointer: UnsafeRawBufferPointer) -> Int {
let count = bufferPointer.count
if let baseAddress = bufferPointer.baseAddress, count > 0 {
memcpy(pointer, baseAddress, count)
}
pointer = pointer.advanced(by: count)
return count
}
func distance(pointer: UnsafeMutableRawPointer) -> Int {
return pointer.distance(to: self.pointer)
}
mutating func appendUnknown(data: Data) {
append(contentsOf: data)
}
mutating func startField(fieldNumber: Int, wireFormat: WireFormat) {
startField(tag: FieldTag(fieldNumber: fieldNumber, wireFormat: wireFormat))
}
mutating func startField(tag: FieldTag) {
putVarInt(value: UInt64(tag.rawValue))
}
mutating func putVarInt(value: UInt64) {
var v = value
while v > 127 {
append(UInt8(v & 0x7f | 0x80))
v >>= 7
}
append(UInt8(v))
}
mutating func putVarInt(value: Int64) {
putVarInt(value: UInt64(bitPattern: value))
}
mutating func putVarInt(value: Int) {
putVarInt(value: Int64(value))
}
mutating func putZigZagVarInt(value: Int64) {
let coded = ZigZag.encoded(value)
putVarInt(value: coded)
}
mutating func putBoolValue(value: Bool) {
append(value ? 1 : 0)
}
mutating func putFixedUInt64(value: UInt64) {
var v = value.littleEndian
let n = MemoryLayout<UInt64>.size
memcpy(pointer, &v, n)
pointer = pointer.advanced(by: n)
}
mutating func putFixedUInt32(value: UInt32) {
var v = value.littleEndian
let n = MemoryLayout<UInt32>.size
memcpy(pointer, &v, n)
pointer = pointer.advanced(by: n)
}
mutating func putFloatValue(value: Float) {
let n = MemoryLayout<Float>.size
var v = value
var nativeBytes: UInt32 = 0
memcpy(&nativeBytes, &v, n)
var littleEndianBytes = nativeBytes.littleEndian
memcpy(pointer, &littleEndianBytes, n)
pointer = pointer.advanced(by: n)
}
mutating func putDoubleValue(value: Double) {
let n = MemoryLayout<Double>.size
var v = value
var nativeBytes: UInt64 = 0
memcpy(&nativeBytes, &v, n)
var littleEndianBytes = nativeBytes.littleEndian
memcpy(pointer, &littleEndianBytes, n)
pointer = pointer.advanced(by: n)
}
// Write a string field, including the leading index/tag value.
mutating func putStringValue(value: String) {
let utf8 = value.utf8
#if swift(>=5.0)
// If the String does not support an internal representation in a form
// of contiguous storage, body is not called and nil is returned.
let isAvailable = utf8.withContiguousStorageIfAvailable { (body: UnsafeBufferPointer<UInt8>) -> Int in
putVarInt(value: body.count)
return append(contentsOf: UnsafeRawBufferPointer(body))
}
#else
let isAvailable: Int? = nil
#endif
if isAvailable == nil {
let count = utf8.count
putVarInt(value: count)
for b in utf8 {
pointer.storeBytes(of: b, as: UInt8.self)
pointer = pointer.advanced(by: 1)
}
}
}
mutating func putBytesValue(value: Data) {
putVarInt(value: value.count)
append(contentsOf: value)
}
}

View File

@ -0,0 +1,27 @@
// Sources/SwiftProtobuf/BinaryEncodingError.swift - Error constants
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Enum constants that identify the particular error.
///
// -----------------------------------------------------------------------------
/// Describes errors that can occur when decoding a message from binary format.
public enum BinaryEncodingError: Error {
/// `Any` fields that were decoded from JSON cannot be re-encoded to binary
/// unless the object they hold is a well-known type or a type registered via
/// `Google_Protobuf_Any.register()`.
case anyTranscodeFailure
/// The definition of the message or one of its nested messages has required
/// fields but the message being encoded did not include values for them. You
/// must pass `partial: true` during encoding if you wish to explicitly ignore
/// missing required fields.
case missingRequiredFields
}

View File

@ -0,0 +1,473 @@
// Sources/SwiftProtobuf/BinaryEncodingSizeVisitor.swift - Binary size calculation support
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Visitor used during binary encoding that precalcuates the size of a
/// serialized message.
///
// -----------------------------------------------------------------------------
import Foundation
/// Visitor that calculates the binary-encoded size of a message so that a
/// properly sized `Data` or `UInt8` array can be pre-allocated before
/// serialization.
internal struct BinaryEncodingSizeVisitor: Visitor {
/// Accumulates the required size of the message during traversal.
var serializedSize: Int = 0
init() {}
mutating func visitUnknown(bytes: Data) throws {
serializedSize += bytes.count
}
mutating func visitSingularFloatField(value: Float, fieldNumber: Int) throws {
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed32).encodedSize
serializedSize += tagSize + MemoryLayout<Float>.size
}
mutating func visitSingularDoubleField(value: Double, fieldNumber: Int) throws {
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed64).encodedSize
serializedSize += tagSize + MemoryLayout<Double>.size
}
mutating func visitSingularInt32Field(value: Int32, fieldNumber: Int) throws {
try visitSingularInt64Field(value: Int64(value), fieldNumber: fieldNumber)
}
mutating func visitSingularInt64Field(value: Int64, fieldNumber: Int) throws {
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
serializedSize += tagSize + Varint.encodedSize(of: value)
}
mutating func visitSingularUInt32Field(value: UInt32, fieldNumber: Int) throws {
try visitSingularUInt64Field(value: UInt64(value), fieldNumber: fieldNumber)
}
mutating func visitSingularUInt64Field(value: UInt64, fieldNumber: Int) throws {
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
serializedSize += tagSize + Varint.encodedSize(of: value)
}
mutating func visitSingularSInt32Field(value: Int32, fieldNumber: Int) throws {
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
serializedSize += tagSize + Varint.encodedSize(of: ZigZag.encoded(value))
}
mutating func visitSingularSInt64Field(value: Int64, fieldNumber: Int) throws {
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
serializedSize += tagSize + Varint.encodedSize(of: ZigZag.encoded(value))
}
mutating func visitSingularFixed32Field(value: UInt32, fieldNumber: Int) throws {
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed32).encodedSize
serializedSize += tagSize + MemoryLayout<UInt32>.size
}
mutating func visitSingularFixed64Field(value: UInt64, fieldNumber: Int) throws {
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed64).encodedSize
serializedSize += tagSize + MemoryLayout<UInt64>.size
}
mutating func visitSingularSFixed32Field(value: Int32, fieldNumber: Int) throws {
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed32).encodedSize
serializedSize += tagSize + MemoryLayout<Int32>.size
}
mutating func visitSingularSFixed64Field(value: Int64, fieldNumber: Int) throws {
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed64).encodedSize
serializedSize += tagSize + MemoryLayout<Int64>.size
}
mutating func visitSingularBoolField(value: Bool, fieldNumber: Int) throws {
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
serializedSize += tagSize + 1
}
mutating func visitSingularStringField(value: String, fieldNumber: Int) throws {
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
let count = value.utf8.count
serializedSize += tagSize + Varint.encodedSize(of: Int64(count)) + count
}
mutating func visitSingularBytesField(value: Data, fieldNumber: Int) throws {
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
let count = value.count
serializedSize += tagSize + Varint.encodedSize(of: Int64(count)) + count
}
// The default impls for visitRepeated*Field would work, but by implementing
// these directly, the calculation for the tag overhead can be optimized and
// the fixed width fields can be simple multiplication.
mutating func visitRepeatedFloatField(value: [Float], fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed32).encodedSize
serializedSize += tagSize * value.count + MemoryLayout<Float>.size * value.count
}
mutating func visitRepeatedDoubleField(value: [Double], fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed64).encodedSize
serializedSize += tagSize * value.count + MemoryLayout<Double>.size * value.count
}
mutating func visitRepeatedInt32Field(value: [Int32], fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
serializedSize += tagSize * value.count + dataSize
}
mutating func visitRepeatedInt64Field(value: [Int64], fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
serializedSize += tagSize * value.count + dataSize
}
mutating func visitRepeatedUInt32Field(value: [UInt32], fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
serializedSize += tagSize * value.count + dataSize
}
mutating func visitRepeatedUInt64Field(value: [UInt64], fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
serializedSize += tagSize * value.count + dataSize
}
mutating func visitRepeatedSInt32Field(value: [Int32], fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: ZigZag.encoded($1)) }
serializedSize += tagSize * value.count + dataSize
}
mutating func visitRepeatedSInt64Field(value: [Int64], fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: ZigZag.encoded($1)) }
serializedSize += tagSize * value.count + dataSize
}
mutating func visitRepeatedFixed32Field(value: [UInt32], fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed32).encodedSize
serializedSize += tagSize * value.count + MemoryLayout<UInt32>.size * value.count
}
mutating func visitRepeatedFixed64Field(value: [UInt64], fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed64).encodedSize
serializedSize += tagSize * value.count + MemoryLayout<UInt64>.size * value.count
}
mutating func visitRepeatedSFixed32Field(value: [Int32], fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed32).encodedSize
serializedSize += tagSize * value.count + MemoryLayout<Int32>.size * value.count
}
mutating func visitRepeatedSFixed64Field(value: [Int64], fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed64).encodedSize
serializedSize += tagSize * value.count + MemoryLayout<Int64>.size * value.count
}
mutating func visitRepeatedBoolField(value: [Bool], fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
serializedSize += tagSize * value.count + 1 * value.count
}
mutating func visitRepeatedStringField(value: [String], fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
let dataSize = value.reduce(0) {
let count = $1.utf8.count
return $0 + Varint.encodedSize(of: Int64(count)) + count
}
serializedSize += tagSize * value.count + dataSize
}
mutating func visitRepeatedBytesField(value: [Data], fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
let dataSize = value.reduce(0) {
let count = $1.count
return $0 + Varint.encodedSize(of: Int64(count)) + count
}
serializedSize += tagSize * value.count + dataSize
}
// Packed field handling.
mutating func visitPackedFloatField(value: [Float], fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
let dataSize = value.count * MemoryLayout<Float>.size
serializedSize += tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
}
mutating func visitPackedDoubleField(value: [Double], fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
let dataSize = value.count * MemoryLayout<Double>.size
serializedSize += tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
}
mutating func visitPackedInt32Field(value: [Int32], fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
serializedSize +=
tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
}
mutating func visitPackedInt64Field(value: [Int64], fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
serializedSize +=
tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
}
mutating func visitPackedSInt32Field(value: [Int32], fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: ZigZag.encoded($1)) }
serializedSize +=
tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
}
mutating func visitPackedSInt64Field(value: [Int64], fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: ZigZag.encoded($1)) }
serializedSize +=
tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
}
mutating func visitPackedUInt32Field(value: [UInt32], fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
serializedSize +=
tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
}
mutating func visitPackedUInt64Field(value: [UInt64], fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
serializedSize +=
tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
}
mutating func visitPackedFixed32Field(value: [UInt32], fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
let dataSize = value.count * MemoryLayout<UInt32>.size
serializedSize += tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
}
mutating func visitPackedFixed64Field(value: [UInt64], fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
let dataSize = value.count * MemoryLayout<UInt64>.size
serializedSize += tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
}
mutating func visitPackedSFixed32Field(value: [Int32], fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
let dataSize = value.count * MemoryLayout<Int32>.size
serializedSize += tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
}
mutating func visitPackedSFixed64Field(value: [Int64], fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
let dataSize = value.count * MemoryLayout<Int64>.size
serializedSize += tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
}
mutating func visitPackedBoolField(value: [Bool], fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
let dataSize = value.count
serializedSize += tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
}
mutating func visitSingularEnumField<E: Enum>(value: E,
fieldNumber: Int) throws {
let tagSize = FieldTag(fieldNumber: fieldNumber,
wireFormat: .varint).encodedSize
serializedSize += tagSize
let dataSize = Varint.encodedSize(of: Int32(truncatingIfNeeded: value.rawValue))
serializedSize += dataSize
}
mutating func visitRepeatedEnumField<E: Enum>(value: [E],
fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber,
wireFormat: .varint).encodedSize
serializedSize += value.count * tagSize
let dataSize = value.reduce(0) {
$0 + Varint.encodedSize(of: Int32(truncatingIfNeeded: $1.rawValue))
}
serializedSize += dataSize
}
mutating func visitPackedEnumField<E: Enum>(value: [E],
fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber,
wireFormat: .varint).encodedSize
serializedSize += tagSize
let dataSize = value.reduce(0) {
$0 + Varint.encodedSize(of: Int32(truncatingIfNeeded: $1.rawValue))
}
serializedSize += Varint.encodedSize(of: Int64(dataSize)) + dataSize
}
mutating func visitSingularMessageField<M: Message>(value: M,
fieldNumber: Int) throws {
let tagSize = FieldTag(fieldNumber: fieldNumber,
wireFormat: .lengthDelimited).encodedSize
let messageSize = try value.serializedDataSize()
serializedSize +=
tagSize + Varint.encodedSize(of: UInt64(messageSize)) + messageSize
}
mutating func visitRepeatedMessageField<M: Message>(value: [M],
fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber,
wireFormat: .lengthDelimited).encodedSize
serializedSize += value.count * tagSize
let dataSize = try value.reduce(0) {
let messageSize = try $1.serializedDataSize()
return $0 + Varint.encodedSize(of: UInt64(messageSize)) + messageSize
}
serializedSize += dataSize
}
mutating func visitSingularGroupField<G: Message>(value: G, fieldNumber: Int) throws {
// The wire format doesn't matter here because the encoded size of the
// integer won't change based on the low three bits.
let tagSize = FieldTag(fieldNumber: fieldNumber,
wireFormat: .startGroup).encodedSize
serializedSize += 2 * tagSize
try value.traverse(visitor: &self)
}
mutating func visitRepeatedGroupField<G: Message>(value: [G],
fieldNumber: Int) throws {
assert(!value.isEmpty)
let tagSize = FieldTag(fieldNumber: fieldNumber,
wireFormat: .startGroup).encodedSize
serializedSize += 2 * value.count * tagSize
for v in value {
try v.traverse(visitor: &self)
}
}
mutating func visitMapField<KeyType, ValueType: MapValueType>(
fieldType: _ProtobufMap<KeyType, ValueType>.Type,
value: _ProtobufMap<KeyType, ValueType>.BaseType,
fieldNumber: Int
) throws {
let tagSize = FieldTag(fieldNumber: fieldNumber,
wireFormat: .lengthDelimited).encodedSize
for (k,v) in value {
var sizer = BinaryEncodingSizeVisitor()
try KeyType.visitSingular(value: k, fieldNumber: 1, with: &sizer)
try ValueType.visitSingular(value: v, fieldNumber: 2, with: &sizer)
let entrySize = sizer.serializedSize
serializedSize += Varint.encodedSize(of: Int64(entrySize)) + entrySize
}
serializedSize += value.count * tagSize
}
mutating func visitMapField<KeyType, ValueType>(
fieldType: _ProtobufEnumMap<KeyType, ValueType>.Type,
value: _ProtobufEnumMap<KeyType, ValueType>.BaseType,
fieldNumber: Int
) throws where ValueType.RawValue == Int {
let tagSize = FieldTag(fieldNumber: fieldNumber,
wireFormat: .lengthDelimited).encodedSize
for (k,v) in value {
var sizer = BinaryEncodingSizeVisitor()
try KeyType.visitSingular(value: k, fieldNumber: 1, with: &sizer)
try sizer.visitSingularEnumField(value: v, fieldNumber: 2)
let entrySize = sizer.serializedSize
serializedSize += Varint.encodedSize(of: Int64(entrySize)) + entrySize
}
serializedSize += value.count * tagSize
}
mutating func visitMapField<KeyType, ValueType>(
fieldType: _ProtobufMessageMap<KeyType, ValueType>.Type,
value: _ProtobufMessageMap<KeyType, ValueType>.BaseType,
fieldNumber: Int
) throws {
let tagSize = FieldTag(fieldNumber: fieldNumber,
wireFormat: .lengthDelimited).encodedSize
for (k,v) in value {
var sizer = BinaryEncodingSizeVisitor()
try KeyType.visitSingular(value: k, fieldNumber: 1, with: &sizer)
try sizer.visitSingularMessageField(value: v, fieldNumber: 2)
let entrySize = sizer.serializedSize
serializedSize += Varint.encodedSize(of: Int64(entrySize)) + entrySize
}
serializedSize += value.count * tagSize
}
mutating func visitExtensionFieldsAsMessageSet(
fields: ExtensionFieldValueSet,
start: Int,
end: Int
) throws {
var sizer = BinaryEncodingMessageSetSizeVisitor()
try fields.traverse(visitor: &sizer, start: start, end: end)
serializedSize += sizer.serializedSize
}
}
extension BinaryEncodingSizeVisitor {
// Helper Visitor to compute the sizes when writing out the extensions as MessageSets.
internal struct BinaryEncodingMessageSetSizeVisitor: SelectiveVisitor {
var serializedSize: Int = 0
init() {}
mutating func visitSingularMessageField<M: Message>(value: M, fieldNumber: Int) throws {
var groupSize = WireFormat.MessageSet.itemTagsEncodedSize
groupSize += Varint.encodedSize(of: Int32(fieldNumber))
let messageSize = try value.serializedDataSize()
groupSize += Varint.encodedSize(of: UInt64(messageSize)) + messageSize
serializedSize += groupSize
}
// SelectiveVisitor handles the rest.
}
}

View File

@ -0,0 +1,355 @@
// Sources/SwiftProtobuf/BinaryEncodingVisitor.swift - Binary encoding support
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Core support for protobuf binary encoding. Note that this is built
/// on the general traversal machinery.
///
// -----------------------------------------------------------------------------
import Foundation
/// Visitor that encodes a message graph in the protobuf binary wire format.
internal struct BinaryEncodingVisitor: Visitor {
var encoder: BinaryEncoder
/// Creates a new visitor that writes the binary-coded message into the memory
/// at the given pointer.
///
/// - Precondition: `pointer` must point to an allocated block of memory that
/// is large enough to hold the entire encoded message. For performance
/// reasons, the encoder does not make any attempts to verify this.
init(forWritingInto pointer: UnsafeMutableRawPointer) {
encoder = BinaryEncoder(forWritingInto: pointer)
}
init(encoder: BinaryEncoder) {
self.encoder = encoder
}
mutating func visitUnknown(bytes: Data) throws {
encoder.appendUnknown(data: bytes)
}
mutating func visitSingularFloatField(value: Float, fieldNumber: Int) throws {
encoder.startField(fieldNumber: fieldNumber, wireFormat: .fixed32)
encoder.putFloatValue(value: value)
}
mutating func visitSingularDoubleField(value: Double, fieldNumber: Int) throws {
encoder.startField(fieldNumber: fieldNumber, wireFormat: .fixed64)
encoder.putDoubleValue(value: value)
}
mutating func visitSingularInt64Field(value: Int64, fieldNumber: Int) throws {
try visitSingularUInt64Field(value: UInt64(bitPattern: value), fieldNumber: fieldNumber)
}
mutating func visitSingularUInt64Field(value: UInt64, fieldNumber: Int) throws {
encoder.startField(fieldNumber: fieldNumber, wireFormat: .varint)
encoder.putVarInt(value: value)
}
mutating func visitSingularSInt32Field(value: Int32, fieldNumber: Int) throws {
try visitSingularSInt64Field(value: Int64(value), fieldNumber: fieldNumber)
}
mutating func visitSingularSInt64Field(value: Int64, fieldNumber: Int) throws {
try visitSingularUInt64Field(value: ZigZag.encoded(value), fieldNumber: fieldNumber)
}
mutating func visitSingularFixed32Field(value: UInt32, fieldNumber: Int) throws {
encoder.startField(fieldNumber: fieldNumber, wireFormat: .fixed32)
encoder.putFixedUInt32(value: value)
}
mutating func visitSingularFixed64Field(value: UInt64, fieldNumber: Int) throws {
encoder.startField(fieldNumber: fieldNumber, wireFormat: .fixed64)
encoder.putFixedUInt64(value: value)
}
mutating func visitSingularSFixed32Field(value: Int32, fieldNumber: Int) throws {
try visitSingularFixed32Field(value: UInt32(bitPattern: value), fieldNumber: fieldNumber)
}
mutating func visitSingularSFixed64Field(value: Int64, fieldNumber: Int) throws {
try visitSingularFixed64Field(value: UInt64(bitPattern: value), fieldNumber: fieldNumber)
}
mutating func visitSingularBoolField(value: Bool, fieldNumber: Int) throws {
try visitSingularUInt64Field(value: value ? 1 : 0, fieldNumber: fieldNumber)
}
mutating func visitSingularStringField(value: String, fieldNumber: Int) throws {
encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
encoder.putStringValue(value: value)
}
mutating func visitSingularBytesField(value: Data, fieldNumber: Int) throws {
encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
encoder.putBytesValue(value: value)
}
mutating func visitSingularEnumField<E: Enum>(value: E,
fieldNumber: Int) throws {
try visitSingularUInt64Field(value: UInt64(bitPattern: Int64(value.rawValue)),
fieldNumber: fieldNumber)
}
mutating func visitSingularMessageField<M: Message>(value: M,
fieldNumber: Int) throws {
encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
let length = try value.serializedDataSize()
encoder.putVarInt(value: length)
try value.traverse(visitor: &self)
}
mutating func visitSingularGroupField<G: Message>(value: G, fieldNumber: Int) throws {
encoder.startField(fieldNumber: fieldNumber, wireFormat: .startGroup)
try value.traverse(visitor: &self)
encoder.startField(fieldNumber: fieldNumber, wireFormat: .endGroup)
}
// Repeated fields are handled by the default implementations in Visitor.swift
// Packed Fields
mutating func visitPackedFloatField(value: [Float], fieldNumber: Int) throws {
assert(!value.isEmpty)
encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
encoder.putVarInt(value: value.count * MemoryLayout<Float>.size)
for v in value {
encoder.putFloatValue(value: v)
}
}
mutating func visitPackedDoubleField(value: [Double], fieldNumber: Int) throws {
assert(!value.isEmpty)
encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
encoder.putVarInt(value: value.count * MemoryLayout<Double>.size)
for v in value {
encoder.putDoubleValue(value: v)
}
}
mutating func visitPackedInt32Field(value: [Int32], fieldNumber: Int) throws {
assert(!value.isEmpty)
encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
let packedSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
encoder.putVarInt(value: packedSize)
for v in value {
encoder.putVarInt(value: Int64(v))
}
}
mutating func visitPackedInt64Field(value: [Int64], fieldNumber: Int) throws {
assert(!value.isEmpty)
encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
let packedSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
encoder.putVarInt(value: packedSize)
for v in value {
encoder.putVarInt(value: v)
}
}
mutating func visitPackedSInt32Field(value: [Int32], fieldNumber: Int) throws {
assert(!value.isEmpty)
encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
let packedSize = value.reduce(0) { $0 + Varint.encodedSize(of: ZigZag.encoded($1)) }
encoder.putVarInt(value: packedSize)
for v in value {
encoder.putZigZagVarInt(value: Int64(v))
}
}
mutating func visitPackedSInt64Field(value: [Int64], fieldNumber: Int) throws {
assert(!value.isEmpty)
encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
let packedSize = value.reduce(0) { $0 + Varint.encodedSize(of: ZigZag.encoded($1)) }
encoder.putVarInt(value: packedSize)
for v in value {
encoder.putZigZagVarInt(value: v)
}
}
mutating func visitPackedUInt32Field(value: [UInt32], fieldNumber: Int) throws {
assert(!value.isEmpty)
encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
let packedSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
encoder.putVarInt(value: packedSize)
for v in value {
encoder.putVarInt(value: UInt64(v))
}
}
mutating func visitPackedUInt64Field(value: [UInt64], fieldNumber: Int) throws {
assert(!value.isEmpty)
encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
let packedSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
encoder.putVarInt(value: packedSize)
for v in value {
encoder.putVarInt(value: v)
}
}
mutating func visitPackedFixed32Field(value: [UInt32], fieldNumber: Int) throws {
assert(!value.isEmpty)
encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
encoder.putVarInt(value: value.count * MemoryLayout<UInt32>.size)
for v in value {
encoder.putFixedUInt32(value: v)
}
}
mutating func visitPackedFixed64Field(value: [UInt64], fieldNumber: Int) throws {
assert(!value.isEmpty)
encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
encoder.putVarInt(value: value.count * MemoryLayout<UInt64>.size)
for v in value {
encoder.putFixedUInt64(value: v)
}
}
mutating func visitPackedSFixed32Field(value: [Int32], fieldNumber: Int) throws {
assert(!value.isEmpty)
encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
encoder.putVarInt(value: value.count * MemoryLayout<Int32>.size)
for v in value {
encoder.putFixedUInt32(value: UInt32(bitPattern: v))
}
}
mutating func visitPackedSFixed64Field(value: [Int64], fieldNumber: Int) throws {
assert(!value.isEmpty)
encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
encoder.putVarInt(value: value.count * MemoryLayout<Int64>.size)
for v in value {
encoder.putFixedUInt64(value: UInt64(bitPattern: v))
}
}
mutating func visitPackedBoolField(value: [Bool], fieldNumber: Int) throws {
assert(!value.isEmpty)
encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
encoder.putVarInt(value: value.count)
for v in value {
encoder.putVarInt(value: v ? 1 : 0)
}
}
mutating func visitPackedEnumField<E: Enum>(value: [E], fieldNumber: Int) throws {
assert(!value.isEmpty)
encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
let packedSize = value.reduce(0) {
$0 + Varint.encodedSize(of: Int32(truncatingIfNeeded: $1.rawValue))
}
encoder.putVarInt(value: packedSize)
for v in value {
encoder.putVarInt(value: v.rawValue)
}
}
mutating func visitMapField<KeyType, ValueType: MapValueType>(
fieldType: _ProtobufMap<KeyType, ValueType>.Type,
value: _ProtobufMap<KeyType, ValueType>.BaseType,
fieldNumber: Int
) throws {
for (k,v) in value {
encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
var sizer = BinaryEncodingSizeVisitor()
try KeyType.visitSingular(value: k, fieldNumber: 1, with: &sizer)
try ValueType.visitSingular(value: v, fieldNumber: 2, with: &sizer)
let entrySize = sizer.serializedSize
encoder.putVarInt(value: entrySize)
try KeyType.visitSingular(value: k, fieldNumber: 1, with: &self)
try ValueType.visitSingular(value: v, fieldNumber: 2, with: &self)
}
}
mutating func visitMapField<KeyType, ValueType>(
fieldType: _ProtobufEnumMap<KeyType, ValueType>.Type,
value: _ProtobufEnumMap<KeyType, ValueType>.BaseType,
fieldNumber: Int
) throws where ValueType.RawValue == Int {
for (k,v) in value {
encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
var sizer = BinaryEncodingSizeVisitor()
try KeyType.visitSingular(value: k, fieldNumber: 1, with: &sizer)
try sizer.visitSingularEnumField(value: v, fieldNumber: 2)
let entrySize = sizer.serializedSize
encoder.putVarInt(value: entrySize)
try KeyType.visitSingular(value: k, fieldNumber: 1, with: &self)
try visitSingularEnumField(value: v, fieldNumber: 2)
}
}
mutating func visitMapField<KeyType, ValueType>(
fieldType: _ProtobufMessageMap<KeyType, ValueType>.Type,
value: _ProtobufMessageMap<KeyType, ValueType>.BaseType,
fieldNumber: Int
) throws {
for (k,v) in value {
encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
var sizer = BinaryEncodingSizeVisitor()
try KeyType.visitSingular(value: k, fieldNumber: 1, with: &sizer)
try sizer.visitSingularMessageField(value: v, fieldNumber: 2)
let entrySize = sizer.serializedSize
encoder.putVarInt(value: entrySize)
try KeyType.visitSingular(value: k, fieldNumber: 1, with: &self)
try visitSingularMessageField(value: v, fieldNumber: 2)
}
}
mutating func visitExtensionFieldsAsMessageSet(
fields: ExtensionFieldValueSet,
start: Int,
end: Int
) throws {
var subVisitor = BinaryEncodingMessageSetVisitor(encoder: encoder)
try fields.traverse(visitor: &subVisitor, start: start, end: end)
encoder = subVisitor.encoder
}
}
extension BinaryEncodingVisitor {
// Helper Visitor to when writing out the extensions as MessageSets.
internal struct BinaryEncodingMessageSetVisitor: SelectiveVisitor {
var encoder: BinaryEncoder
init(encoder: BinaryEncoder) {
self.encoder = encoder
}
mutating func visitSingularMessageField<M: Message>(value: M, fieldNumber: Int) throws {
encoder.putVarInt(value: Int64(WireFormat.MessageSet.Tags.itemStart.rawValue))
encoder.putVarInt(value: Int64(WireFormat.MessageSet.Tags.typeId.rawValue))
encoder.putVarInt(value: fieldNumber)
encoder.putVarInt(value: Int64(WireFormat.MessageSet.Tags.message.rawValue))
// Use a normal BinaryEncodingVisitor so any message fields end up in the
// normal wire format (instead of MessageSet format).
let length = try value.serializedDataSize()
encoder.putVarInt(value: length)
// Create the sub encoder after writing the length.
var subVisitor = BinaryEncodingVisitor(encoder: encoder)
try value.traverse(visitor: &subVisitor)
encoder = subVisitor.encoder
encoder.putVarInt(value: Int64(WireFormat.MessageSet.Tags.itemEnd.rawValue))
}
// SelectiveVisitor handles the rest.
}
}

View File

@ -0,0 +1,36 @@
// Sources/SwiftProtobuf/CustomJSONCodable.swift - Custom JSON support for WKTs
//
// Copyright (c) 2014 - 2017 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Custom protocol for the WKTs to support their custom JSON encodings.
///
// -----------------------------------------------------------------------------
/// Allows WKTs to provide their custom JSON encodings.
internal protocol _CustomJSONCodable {
func encodedJSONString(options: JSONEncodingOptions) throws -> String
mutating func decodeJSON(from: inout JSONDecoder) throws
/// Called when the JSON `null` literal is encountered in a position where
/// a message of the conforming type is expected. The message type can then
/// handle the `null` value differently, if needed; for example,
/// `Google_Protobuf_Value` returns a special instance whose `kind` is set to
/// `.nullValue(.nullValue)`.
///
/// The default behavior is to return `nil`, which indicates that `null`
/// should be treated as the absence of a message.
static func decodedFromJSONNull() throws -> Self?
}
extension _CustomJSONCodable {
internal static func decodedFromJSONNull() -> Self? {
// Return nil by default. Concrete types can provide custom logic.
return nil
}
}

View File

@ -0,0 +1,34 @@
// Sources/SwiftProtobuf/Data+Extensions.swift - Extension exposing new Data API
//
// Copyright (c) 2014 - 2019 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Extension exposing new Data API to Swift versions < 5.0.
///
// -----------------------------------------------------------------------------
import Foundation
#if !swift(>=5.0)
internal extension Data {
@usableFromInline
func withUnsafeBytes<T>(_ body: (UnsafeRawBufferPointer) throws -> T) rethrows -> T {
let c = count
return try withUnsafeBytes { (p: UnsafePointer<UInt8>) throws -> T in
try body(UnsafeRawBufferPointer(start: p, count: c))
}
}
mutating func withUnsafeMutableBytes<T>(_ body: (UnsafeMutableRawBufferPointer) throws -> T) rethrows -> T {
let c = count
return try withUnsafeMutableBytes { (p: UnsafeMutablePointer<UInt8>) throws -> T in
try body(UnsafeMutableRawBufferPointer(start: p, count: c))
}
}
}
#endif

View File

@ -0,0 +1,150 @@
// Sources/SwiftProtobuf/Decoder.swift - Basic field setting
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// In this way, the generated code only knows about schema
/// information; the decoder logic knows how to decode particular
/// wire types based on that information.
///
// -----------------------------------------------------------------------------
import Foundation
/// This is the abstract protocol used by the generated code
/// to deserialize data.
///
/// The generated code looks roughly like this:
///
/// ```
/// while fieldNumber = try decoder.nextFieldNumber() {
/// switch fieldNumber {
/// case 1: decoder.decodeRepeatedInt32Field(value: &_field)
/// ... etc ...
/// }
/// ```
///
/// For performance, this is mostly broken out into a separate method
/// for singular/repeated fields of every supported type. Note that
/// we don't distinguish "packed" here, since all existing decoders
/// treat "packed" the same as "repeated" at this level. (That is,
/// even when the serializer distinguishes packed and non-packed
/// forms, the deserializer always accepts both.)
///
/// Generics come into play at only a few points: `Enum`s and `Message`s
/// use a generic type to locate the correct initializer. Maps and
/// extensions use generics to avoid the method explosion of having to
/// support a separate method for every map and extension type. Maps
/// do distinguish `Enum`-valued and `Message`-valued maps to avoid
/// polluting the generated `Enum` and `Message` types with all of the
/// necessary generic methods to support this.
public protocol Decoder {
/// Called by a `oneof` when it already has a value and is being asked to
/// accept a new value. Some formats require `oneof` decoding to fail in this
/// case.
mutating func handleConflictingOneOf() throws
/// Returns the next field number, or nil when the end of the input is
/// reached.
///
/// For JSON and text format, the decoder translates the field name to a
/// number at this point, based on information it obtained from the message
/// when it was initialized.
mutating func nextFieldNumber() throws -> Int?
// Primitive field decoders
mutating func decodeSingularFloatField(value: inout Float) throws
mutating func decodeSingularFloatField(value: inout Float?) throws
mutating func decodeRepeatedFloatField(value: inout [Float]) throws
mutating func decodeSingularDoubleField(value: inout Double) throws
mutating func decodeSingularDoubleField(value: inout Double?) throws
mutating func decodeRepeatedDoubleField(value: inout [Double]) throws
mutating func decodeSingularInt32Field(value: inout Int32) throws
mutating func decodeSingularInt32Field(value: inout Int32?) throws
mutating func decodeRepeatedInt32Field(value: inout [Int32]) throws
mutating func decodeSingularInt64Field(value: inout Int64) throws
mutating func decodeSingularInt64Field(value: inout Int64?) throws
mutating func decodeRepeatedInt64Field(value: inout [Int64]) throws
mutating func decodeSingularUInt32Field(value: inout UInt32) throws
mutating func decodeSingularUInt32Field(value: inout UInt32?) throws
mutating func decodeRepeatedUInt32Field(value: inout [UInt32]) throws
mutating func decodeSingularUInt64Field(value: inout UInt64) throws
mutating func decodeSingularUInt64Field(value: inout UInt64?) throws
mutating func decodeRepeatedUInt64Field(value: inout [UInt64]) throws
mutating func decodeSingularSInt32Field(value: inout Int32) throws
mutating func decodeSingularSInt32Field(value: inout Int32?) throws
mutating func decodeRepeatedSInt32Field(value: inout [Int32]) throws
mutating func decodeSingularSInt64Field(value: inout Int64) throws
mutating func decodeSingularSInt64Field(value: inout Int64?) throws
mutating func decodeRepeatedSInt64Field(value: inout [Int64]) throws
mutating func decodeSingularFixed32Field(value: inout UInt32) throws
mutating func decodeSingularFixed32Field(value: inout UInt32?) throws
mutating func decodeRepeatedFixed32Field(value: inout [UInt32]) throws
mutating func decodeSingularFixed64Field(value: inout UInt64) throws
mutating func decodeSingularFixed64Field(value: inout UInt64?) throws
mutating func decodeRepeatedFixed64Field(value: inout [UInt64]) throws
mutating func decodeSingularSFixed32Field(value: inout Int32) throws
mutating func decodeSingularSFixed32Field(value: inout Int32?) throws
mutating func decodeRepeatedSFixed32Field(value: inout [Int32]) throws
mutating func decodeSingularSFixed64Field(value: inout Int64) throws
mutating func decodeSingularSFixed64Field(value: inout Int64?) throws
mutating func decodeRepeatedSFixed64Field(value: inout [Int64]) throws
mutating func decodeSingularBoolField(value: inout Bool) throws
mutating func decodeSingularBoolField(value: inout Bool?) throws
mutating func decodeRepeatedBoolField(value: inout [Bool]) throws
mutating func decodeSingularStringField(value: inout String) throws
mutating func decodeSingularStringField(value: inout String?) throws
mutating func decodeRepeatedStringField(value: inout [String]) throws
mutating func decodeSingularBytesField(value: inout Data) throws
mutating func decodeSingularBytesField(value: inout Data?) throws
mutating func decodeRepeatedBytesField(value: inout [Data]) throws
// Decode Enum fields
mutating func decodeSingularEnumField<E: Enum>(value: inout E) throws where E.RawValue == Int
mutating func decodeSingularEnumField<E: Enum>(value: inout E?) throws where E.RawValue == Int
mutating func decodeRepeatedEnumField<E: Enum>(value: inout [E]) throws where E.RawValue == Int
// Decode Message fields
mutating func decodeSingularMessageField<M: Message>(value: inout M?) throws
mutating func decodeRepeatedMessageField<M: Message>(value: inout [M]) throws
// Decode Group fields
mutating func decodeSingularGroupField<G: Message>(value: inout G?) throws
mutating func decodeRepeatedGroupField<G: Message>(value: inout [G]) throws
// Decode Map fields.
// This is broken into separate methods depending on whether the value
// type is primitive (_ProtobufMap), enum (_ProtobufEnumMap), or message
// (_ProtobufMessageMap)
mutating func decodeMapField<KeyType, ValueType: MapValueType>(fieldType: _ProtobufMap<KeyType, ValueType>.Type, value: inout _ProtobufMap<KeyType, ValueType>.BaseType) throws
mutating func decodeMapField<KeyType, ValueType>(fieldType: _ProtobufEnumMap<KeyType, ValueType>.Type, value: inout _ProtobufEnumMap<KeyType, ValueType>.BaseType) throws where ValueType.RawValue == Int
mutating func decodeMapField<KeyType, ValueType>(fieldType: _ProtobufMessageMap<KeyType, ValueType>.Type, value: inout _ProtobufMessageMap<KeyType, ValueType>.BaseType) throws
// Decode extension fields
mutating func decodeExtensionField(values: inout ExtensionFieldValueSet, messageType: Message.Type, fieldNumber: Int) throws
// Run a decode loop decoding the MessageSet format for Extensions.
mutating func decodeExtensionFieldsAsMessageSet(values: inout ExtensionFieldValueSet,
messageType: Message.Type) throws
}
/// Most Decoders won't care about Extension handing as in MessageSet
/// format, so provide a default implementation simply looping on the
/// fieldNumbers and feeding through to extension decoding.
extension Decoder {
public mutating func decodeExtensionFieldsAsMessageSet(
values: inout ExtensionFieldValueSet,
messageType: Message.Type
) throws {
while let fieldNumber = try self.nextFieldNumber() {
try self.decodeExtensionField(values: &values,
messageType: messageType,
fieldNumber: fieldNumber)
}
}
}

View File

@ -0,0 +1,61 @@
// Sources/SwiftProtobuf/DoubleParser.swift - Generally useful mathematical functions
//
// Copyright (c) 2014 - 2019 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Numeric parsing helper for float and double strings
///
// -----------------------------------------------------------------------------
import Foundation
/// Support parsing float/double values from UTF-8
internal class DoubleParser {
// Temporary buffer so we can null-terminate the UTF-8 string
// before calling the C standard libray to parse it.
// In theory, JSON writers should be able to represent any IEEE Double
// in at most 25 bytes, but many writers will emit more digits than
// necessary, so we size this generously.
private var work =
UnsafeMutableBufferPointer<Int8>.allocate(capacity: 128)
deinit {
work.deallocate()
}
func utf8ToDouble(bytes: UnsafeRawBufferPointer,
start: UnsafeRawBufferPointer.Index,
end: UnsafeRawBufferPointer.Index) -> Double? {
return utf8ToDouble(bytes: UnsafeRawBufferPointer(rebasing: bytes[start..<end]))
}
func utf8ToDouble(bytes: UnsafeRawBufferPointer) -> Double? {
// Reject unreasonably long or short UTF8 number
if work.count <= bytes.count || bytes.count < 1 {
return nil
}
#if swift(>=4.1)
UnsafeMutableRawBufferPointer(work).copyMemory(from: bytes)
#else
UnsafeMutableRawBufferPointer(work).copyBytes(from: bytes)
#endif
work[bytes.count] = 0
// Use C library strtod() to parse it
var e: UnsafeMutablePointer<Int8>? = work.baseAddress
let d = strtod(work.baseAddress!, &e)
// Fail if strtod() did not consume everything we expected
// or if strtod() thought the number was out of range.
if e != work.baseAddress! + bytes.count || !d.isFinite {
return nil
}
return d
}
}

View File

@ -0,0 +1,93 @@
// Sources/SwiftProtobuf/Enum.swift - Enum support
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Generated enums conform to SwiftProtobuf.Enum
///
/// See ProtobufTypes and JSONTypes for extension
/// methods to support binary and JSON coding.
///
// -----------------------------------------------------------------------------
/// Generated enum types conform to this protocol.
public protocol Enum: RawRepresentable, Hashable {
/// Creates a new instance of the enum initialized to its default value.
init()
/// Creates a new instance of the enum from the given raw integer value.
///
/// For proto2 enums, this initializer will fail if the raw value does not
/// correspond to a valid enum value. For proto3 enums, this initializer never
/// fails; unknown values are created as instances of the `UNRECOGNIZED` case.
///
/// - Parameter rawValue: The raw integer value from which to create the enum
/// value.
init?(rawValue: Int)
/// The raw integer value of the enum value.
///
/// For a recognized enum case, this is the integer value of the case as
/// defined in the .proto file. For `UNRECOGNIZED` cases in proto3, this is
/// the value that was originally decoded.
var rawValue: Int { get }
}
extension Enum {
#if swift(>=4.2)
public func hash(into hasher: inout Hasher) {
hasher.combine(rawValue)
}
#else // swift(>=4.2)
public var hashValue: Int {
return rawValue
}
#endif // swift(>=4.2)
/// Internal convenience property representing the name of the enum value (or
/// `nil` if it is an `UNRECOGNIZED` value or doesn't provide names).
///
/// Since the text format and JSON names are always identical, we don't need
/// to distinguish them.
internal var name: _NameMap.Name? {
guard let nameProviding = Self.self as? _ProtoNameProviding.Type else {
return nil
}
return nameProviding._protobuf_nameMap.names(for: rawValue)?.proto
}
/// Internal convenience initializer that returns the enum value with the
/// given name, if it provides names.
///
/// Since the text format and JSON names are always identical, we don't need
/// to distinguish them.
///
/// - Parameter name: The name of the enum case.
internal init?(name: String) {
guard let nameProviding = Self.self as? _ProtoNameProviding.Type,
let number = nameProviding._protobuf_nameMap.number(forJSONName: name) else {
return nil
}
self.init(rawValue: number)
}
/// Internal convenience initializer that returns the enum value with the
/// given name, if it provides names.
///
/// Since the text format and JSON names are always identical, we don't need
/// to distinguish them.
///
/// - Parameter name: Buffer holding the UTF-8 bytes of the desired name.
internal init?(rawUTF8: UnsafeRawBufferPointer) {
guard let nameProviding = Self.self as? _ProtoNameProviding.Type,
let number = nameProviding._protobuf_nameMap.number(forJSONName: rawUTF8) else {
return nil
}
self.init(rawValue: number)
}
}

View File

@ -0,0 +1,73 @@
// Sources/SwiftProtobuf/ExtensibleMessage.swift - Extension support
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Additional capabilities needed by messages that allow extensions.
///
// -----------------------------------------------------------------------------
// Messages that support extensions implement this protocol
public protocol ExtensibleMessage: Message {
var _protobuf_extensionFieldValues: ExtensionFieldValueSet { get set }
}
extension ExtensibleMessage {
public mutating func setExtensionValue<F: ExtensionField>(ext: MessageExtension<F, Self>, value: F.ValueType) {
_protobuf_extensionFieldValues[ext.fieldNumber] = F(protobufExtension: ext, value: value)
}
public func getExtensionValue<F: ExtensionField>(ext: MessageExtension<F, Self>) -> F.ValueType? {
if let fieldValue = _protobuf_extensionFieldValues[ext.fieldNumber] as? F {
return fieldValue.value
}
return nil
}
public func hasExtensionValue<F: ExtensionField>(ext: MessageExtension<F, Self>) -> Bool {
return _protobuf_extensionFieldValues[ext.fieldNumber] is F
}
public mutating func clearExtensionValue<F: ExtensionField>(ext: MessageExtension<F, Self>) {
_protobuf_extensionFieldValues[ext.fieldNumber] = nil
}
}
// Additional specializations for the different types of repeated fields so
// setting them to an empty array clears them from the map.
extension ExtensibleMessage {
public mutating func setExtensionValue<T>(ext: MessageExtension<RepeatedExtensionField<T>, Self>, value: [T.BaseType]) {
_protobuf_extensionFieldValues[ext.fieldNumber] =
value.isEmpty ? nil : RepeatedExtensionField<T>(protobufExtension: ext, value: value)
}
public mutating func setExtensionValue<T>(ext: MessageExtension<PackedExtensionField<T>, Self>, value: [T.BaseType]) {
_protobuf_extensionFieldValues[ext.fieldNumber] =
value.isEmpty ? nil : PackedExtensionField<T>(protobufExtension: ext, value: value)
}
public mutating func setExtensionValue<E>(ext: MessageExtension<RepeatedEnumExtensionField<E>, Self>, value: [E]) {
_protobuf_extensionFieldValues[ext.fieldNumber] =
value.isEmpty ? nil : RepeatedEnumExtensionField<E>(protobufExtension: ext, value: value)
}
public mutating func setExtensionValue<E>(ext: MessageExtension<PackedEnumExtensionField<E>, Self>, value: [E]) {
_protobuf_extensionFieldValues[ext.fieldNumber] =
value.isEmpty ? nil : PackedEnumExtensionField<E>(protobufExtension: ext, value: value)
}
public mutating func setExtensionValue<M>(ext: MessageExtension<RepeatedMessageExtensionField<M>, Self>, value: [M]) {
_protobuf_extensionFieldValues[ext.fieldNumber] =
value.isEmpty ? nil : RepeatedMessageExtensionField<M>(protobufExtension: ext, value: value)
}
public mutating func setExtensionValue<M>(ext: MessageExtension<RepeatedGroupExtensionField<M>, Self>, value: [M]) {
_protobuf_extensionFieldValues[ext.fieldNumber] =
value.isEmpty ? nil : RepeatedGroupExtensionField<M>(protobufExtension: ext, value: value)
}
}

View File

@ -0,0 +1,89 @@
// Sources/SwiftProtobuf/ExtensionFieldValueSet.swift - Extension support
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// A collection of extension field values on a particular object.
/// This is only used within messages to manage the values of extension fields;
/// it does not need to be very sophisticated.
///
// -----------------------------------------------------------------------------
public struct ExtensionFieldValueSet: Hashable {
fileprivate var values = [Int : AnyExtensionField]()
public static func ==(lhs: ExtensionFieldValueSet,
rhs: ExtensionFieldValueSet) -> Bool {
guard lhs.values.count == rhs.values.count else {
return false
}
for (index, l) in lhs.values {
if let r = rhs.values[index] {
if type(of: l) != type(of: r) {
return false
}
if !l.isEqual(other: r) {
return false
}
} else {
return false
}
}
return true
}
public init() {}
#if swift(>=4.2)
public func hash(into hasher: inout Hasher) {
// AnyExtensionField is not Hashable, and the Self constraint that would
// add breaks some of the uses of it; so the only choice is to manually
// mix things in. However, one must remember to do things in an order
// independent manner.
var hash = 16777619
for (fieldNumber, v) in values {
var localHasher = hasher
localHasher.combine(fieldNumber)
v.hash(into: &localHasher)
hash = hash &+ localHasher.finalize()
}
hasher.combine(hash)
}
#else // swift(>=4.2)
public var hashValue: Int {
var hash = 16777619
for (fieldNumber, v) in values {
// Note: This calculation cannot depend on the order of the items.
hash = hash &+ fieldNumber &+ v.hashValue
}
return hash
}
#endif // swift(>=4.2)
public func traverse<V: Visitor>(visitor: inout V, start: Int, end: Int) throws {
let validIndexes = values.keys.filter {$0 >= start && $0 < end}
for i in validIndexes.sorted() {
let value = values[i]!
try value.traverse(visitor: &visitor)
}
}
public subscript(index: Int) -> AnyExtensionField? {
get { return values[index] }
set { values[index] = newValue }
}
public var isInitialized: Bool {
for (_, v) in values {
if !v.isInitialized {
return false
}
}
return true
}
}

View File

@ -0,0 +1,708 @@
// Sources/SwiftProtobuf/ExtensionFields.swift - Extension support
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Core protocols implemented by generated extensions.
///
// -----------------------------------------------------------------------------
#if !swift(>=4.2)
private let i_2166136261 = Int(bitPattern: 2166136261)
private let i_16777619 = Int(16777619)
#endif
//
// Type-erased Extension field implementation.
// Note that it has no "self or associated type" references, so can
// be used as a protocol type. (In particular, although it does have
// a hashValue property, it cannot be Hashable.)
//
// This can encode, decode, return a hashValue and test for
// equality with some other extension field; but it's type-sealed
// so you can't actually access the contained value itself.
//
public protocol AnyExtensionField: CustomDebugStringConvertible {
#if swift(>=4.2)
func hash(into hasher: inout Hasher)
#else
var hashValue: Int { get }
#endif
var protobufExtension: AnyMessageExtension { get }
func isEqual(other: AnyExtensionField) -> Bool
/// Merging field decoding
mutating func decodeExtensionField<T: Decoder>(decoder: inout T) throws
/// Fields know their own type, so can dispatch to a visitor
func traverse<V: Visitor>(visitor: inout V) throws
/// Check if the field is initialized.
var isInitialized: Bool { get }
}
extension AnyExtensionField {
// Default implementation for extensions fields. The message types below provide
// custom versions.
public var isInitialized: Bool { return true }
}
///
/// The regular ExtensionField type exposes the value directly.
///
public protocol ExtensionField: AnyExtensionField, Hashable {
associatedtype ValueType
var value: ValueType { get set }
init(protobufExtension: AnyMessageExtension, value: ValueType)
init?<D: Decoder>(protobufExtension: AnyMessageExtension, decoder: inout D) throws
}
///
/// Singular field
///
public struct OptionalExtensionField<T: FieldType>: ExtensionField {
public typealias BaseType = T.BaseType
public typealias ValueType = BaseType
public var value: ValueType
public var protobufExtension: AnyMessageExtension
public static func ==(lhs: OptionalExtensionField,
rhs: OptionalExtensionField) -> Bool {
return lhs.value == rhs.value
}
public init(protobufExtension: AnyMessageExtension, value: ValueType) {
self.protobufExtension = protobufExtension
self.value = value
}
public var debugDescription: String {
get {
return String(reflecting: value)
}
}
#if swift(>=4.2)
public func hash(into hasher: inout Hasher) {
hasher.combine(value)
}
#else // swift(>=4.2)
public var hashValue: Int {
get { return value.hashValue }
}
#endif // swift(>=4.2)
public func isEqual(other: AnyExtensionField) -> Bool {
let o = other as! OptionalExtensionField<T>
return self == o
}
public mutating func decodeExtensionField<D: Decoder>(decoder: inout D) throws {
var v: ValueType?
try T.decodeSingular(value: &v, from: &decoder)
if let v = v {
value = v
}
}
public init?<D: Decoder>(protobufExtension: AnyMessageExtension, decoder: inout D) throws {
var v: ValueType?
try T.decodeSingular(value: &v, from: &decoder)
if let v = v {
self.init(protobufExtension: protobufExtension, value: v)
} else {
return nil
}
}
public func traverse<V: Visitor>(visitor: inout V) throws {
try T.visitSingular(value: value, fieldNumber: protobufExtension.fieldNumber, with: &visitor)
}
}
///
/// Repeated fields
///
public struct RepeatedExtensionField<T: FieldType>: ExtensionField {
public typealias BaseType = T.BaseType
public typealias ValueType = [BaseType]
public var value: ValueType
public var protobufExtension: AnyMessageExtension
public static func ==(lhs: RepeatedExtensionField,
rhs: RepeatedExtensionField) -> Bool {
return lhs.value == rhs.value
}
public init(protobufExtension: AnyMessageExtension, value: ValueType) {
self.protobufExtension = protobufExtension
self.value = value
}
#if swift(>=4.2)
public func hash(into hasher: inout Hasher) {
hasher.combine(value)
}
#else // swift(>=4.2)
public var hashValue: Int {
get {
var hash = i_2166136261
for e in value {
hash = (hash &* i_16777619) ^ e.hashValue
}
return hash
}
}
#endif // swift(>=4.2)
public func isEqual(other: AnyExtensionField) -> Bool {
let o = other as! RepeatedExtensionField<T>
return self == o
}
public var debugDescription: String {
return "[" + value.map{String(reflecting: $0)}.joined(separator: ",") + "]"
}
public mutating func decodeExtensionField<D: Decoder>(decoder: inout D) throws {
try T.decodeRepeated(value: &value, from: &decoder)
}
public init?<D: Decoder>(protobufExtension: AnyMessageExtension, decoder: inout D) throws {
var v: ValueType = []
try T.decodeRepeated(value: &v, from: &decoder)
self.init(protobufExtension: protobufExtension, value: v)
}
public func traverse<V: Visitor>(visitor: inout V) throws {
if value.count > 0 {
try T.visitRepeated(value: value, fieldNumber: protobufExtension.fieldNumber, with: &visitor)
}
}
}
///
/// Packed Repeated fields
///
/// TODO: This is almost (but not quite) identical to RepeatedFields;
/// find a way to collapse the implementations.
///
public struct PackedExtensionField<T: FieldType>: ExtensionField {
public typealias BaseType = T.BaseType
public typealias ValueType = [BaseType]
public var value: ValueType
public var protobufExtension: AnyMessageExtension
public static func ==(lhs: PackedExtensionField,
rhs: PackedExtensionField) -> Bool {
return lhs.value == rhs.value
}
public init(protobufExtension: AnyMessageExtension, value: ValueType) {
self.protobufExtension = protobufExtension
self.value = value
}
#if swift(>=4.2)
public func hash(into hasher: inout Hasher) {
hasher.combine(value)
}
#else // swift(>=4.2)
public var hashValue: Int {
get {
var hash = i_2166136261
for e in value {
hash = (hash &* i_16777619) ^ e.hashValue
}
return hash
}
}
#endif // swift(>=4.2)
public func isEqual(other: AnyExtensionField) -> Bool {
let o = other as! PackedExtensionField<T>
return self == o
}
public var debugDescription: String {
return "[" + value.map{String(reflecting: $0)}.joined(separator: ",") + "]"
}
public mutating func decodeExtensionField<D: Decoder>(decoder: inout D) throws {
try T.decodeRepeated(value: &value, from: &decoder)
}
public init?<D: Decoder>(protobufExtension: AnyMessageExtension, decoder: inout D) throws {
var v: ValueType = []
try T.decodeRepeated(value: &v, from: &decoder)
self.init(protobufExtension: protobufExtension, value: v)
}
public func traverse<V: Visitor>(visitor: inout V) throws {
if value.count > 0 {
try T.visitPacked(value: value, fieldNumber: protobufExtension.fieldNumber, with: &visitor)
}
}
}
///
/// Enum extensions
///
public struct OptionalEnumExtensionField<E: Enum>: ExtensionField where E.RawValue == Int {
public typealias BaseType = E
public typealias ValueType = E
public var value: ValueType
public var protobufExtension: AnyMessageExtension
public static func ==(lhs: OptionalEnumExtensionField,
rhs: OptionalEnumExtensionField) -> Bool {
return lhs.value == rhs.value
}
public init(protobufExtension: AnyMessageExtension, value: ValueType) {
self.protobufExtension = protobufExtension
self.value = value
}
public var debugDescription: String {
get {
return String(reflecting: value)
}
}
#if swift(>=4.2)
public func hash(into hasher: inout Hasher) {
hasher.combine(value)
}
#else // swift(>=4.2)
public var hashValue: Int {
get { return value.hashValue }
}
#endif // swift(>=4.2)
public func isEqual(other: AnyExtensionField) -> Bool {
let o = other as! OptionalEnumExtensionField<E>
return self == o
}
public mutating func decodeExtensionField<D: Decoder>(decoder: inout D) throws {
var v: ValueType?
try decoder.decodeSingularEnumField(value: &v)
if let v = v {
value = v
}
}
public init?<D: Decoder>(protobufExtension: AnyMessageExtension, decoder: inout D) throws {
var v: ValueType?
try decoder.decodeSingularEnumField(value: &v)
if let v = v {
self.init(protobufExtension: protobufExtension, value: v)
} else {
return nil
}
}
public func traverse<V: Visitor>(visitor: inout V) throws {
try visitor.visitSingularEnumField(
value: value,
fieldNumber: protobufExtension.fieldNumber)
}
}
///
/// Repeated Enum fields
///
public struct RepeatedEnumExtensionField<E: Enum>: ExtensionField where E.RawValue == Int {
public typealias BaseType = E
public typealias ValueType = [E]
public var value: ValueType
public var protobufExtension: AnyMessageExtension
public static func ==(lhs: RepeatedEnumExtensionField,
rhs: RepeatedEnumExtensionField) -> Bool {
return lhs.value == rhs.value
}
public init(protobufExtension: AnyMessageExtension, value: ValueType) {
self.protobufExtension = protobufExtension
self.value = value
}
#if swift(>=4.2)
public func hash(into hasher: inout Hasher) {
hasher.combine(value)
}
#else // swift(>=4.2)
public var hashValue: Int {
get {
var hash = i_2166136261
for e in value {
hash = (hash &* i_16777619) ^ e.hashValue
}
return hash
}
}
#endif // swift(>=4.2)
public func isEqual(other: AnyExtensionField) -> Bool {
let o = other as! RepeatedEnumExtensionField<E>
return self == o
}
public var debugDescription: String {
return "[" + value.map{String(reflecting: $0)}.joined(separator: ",") + "]"
}
public mutating func decodeExtensionField<D: Decoder>(decoder: inout D) throws {
try decoder.decodeRepeatedEnumField(value: &value)
}
public init?<D: Decoder>(protobufExtension: AnyMessageExtension, decoder: inout D) throws {
var v: ValueType = []
try decoder.decodeRepeatedEnumField(value: &v)
self.init(protobufExtension: protobufExtension, value: v)
}
public func traverse<V: Visitor>(visitor: inout V) throws {
if value.count > 0 {
try visitor.visitRepeatedEnumField(
value: value,
fieldNumber: protobufExtension.fieldNumber)
}
}
}
///
/// Packed Repeated Enum fields
///
/// TODO: This is almost (but not quite) identical to RepeatedEnumFields;
/// find a way to collapse the implementations.
///
public struct PackedEnumExtensionField<E: Enum>: ExtensionField where E.RawValue == Int {
public typealias BaseType = E
public typealias ValueType = [E]
public var value: ValueType
public var protobufExtension: AnyMessageExtension
public static func ==(lhs: PackedEnumExtensionField,
rhs: PackedEnumExtensionField) -> Bool {
return lhs.value == rhs.value
}
public init(protobufExtension: AnyMessageExtension, value: ValueType) {
self.protobufExtension = protobufExtension
self.value = value
}
#if swift(>=4.2)
public func hash(into hasher: inout Hasher) {
hasher.combine(value)
}
#else // swift(>=4.2)
public var hashValue: Int {
get {
var hash = i_2166136261
for e in value {
hash = (hash &* i_16777619) ^ e.hashValue
}
return hash
}
}
#endif // swift(>=4.2)
public func isEqual(other: AnyExtensionField) -> Bool {
let o = other as! PackedEnumExtensionField<E>
return self == o
}
public var debugDescription: String {
return "[" + value.map{String(reflecting: $0)}.joined(separator: ",") + "]"
}
public mutating func decodeExtensionField<D: Decoder>(decoder: inout D) throws {
try decoder.decodeRepeatedEnumField(value: &value)
}
public init?<D: Decoder>(protobufExtension: AnyMessageExtension, decoder: inout D) throws {
var v: ValueType = []
try decoder.decodeRepeatedEnumField(value: &v)
self.init(protobufExtension: protobufExtension, value: v)
}
public func traverse<V: Visitor>(visitor: inout V) throws {
if value.count > 0 {
try visitor.visitPackedEnumField(
value: value,
fieldNumber: protobufExtension.fieldNumber)
}
}
}
//
// ========== Message ==========
//
public struct OptionalMessageExtensionField<M: Message & Equatable>:
ExtensionField {
public typealias BaseType = M
public typealias ValueType = BaseType
public var value: ValueType
public var protobufExtension: AnyMessageExtension
public static func ==(lhs: OptionalMessageExtensionField,
rhs: OptionalMessageExtensionField) -> Bool {
return lhs.value == rhs.value
}
public init(protobufExtension: AnyMessageExtension, value: ValueType) {
self.protobufExtension = protobufExtension
self.value = value
}
public var debugDescription: String {
get {
return String(reflecting: value)
}
}
#if swift(>=4.2)
public func hash(into hasher: inout Hasher) {
value.hash(into: &hasher)
}
#else // swift(>=4.2)
public var hashValue: Int {return value.hashValue}
#endif // swift(>=4.2)
public func isEqual(other: AnyExtensionField) -> Bool {
let o = other as! OptionalMessageExtensionField<M>
return self == o
}
public mutating func decodeExtensionField<D: Decoder>(decoder: inout D) throws {
var v: ValueType? = value
try decoder.decodeSingularMessageField(value: &v)
if let v = v {
self.value = v
}
}
public init?<D: Decoder>(protobufExtension: AnyMessageExtension, decoder: inout D) throws {
var v: ValueType?
try decoder.decodeSingularMessageField(value: &v)
if let v = v {
self.init(protobufExtension: protobufExtension, value: v)
} else {
return nil
}
}
public func traverse<V: Visitor>(visitor: inout V) throws {
try visitor.visitSingularMessageField(
value: value, fieldNumber: protobufExtension.fieldNumber)
}
public var isInitialized: Bool {
return value.isInitialized
}
}
public struct RepeatedMessageExtensionField<M: Message & Equatable>:
ExtensionField {
public typealias BaseType = M
public typealias ValueType = [BaseType]
public var value: ValueType
public var protobufExtension: AnyMessageExtension
public static func ==(lhs: RepeatedMessageExtensionField,
rhs: RepeatedMessageExtensionField) -> Bool {
return lhs.value == rhs.value
}
public init(protobufExtension: AnyMessageExtension, value: ValueType) {
self.protobufExtension = protobufExtension
self.value = value
}
#if swift(>=4.2)
public func hash(into hasher: inout Hasher) {
for e in value {
e.hash(into: &hasher)
}
}
#else // swift(>=4.2)
public var hashValue: Int {
get {
var hash = i_2166136261
for e in value {
hash = (hash &* i_16777619) ^ e.hashValue
}
return hash
}
}
#endif // swift(>=4.2)
public func isEqual(other: AnyExtensionField) -> Bool {
let o = other as! RepeatedMessageExtensionField<M>
return self == o
}
public var debugDescription: String {
return "[" + value.map{String(reflecting: $0)}.joined(separator: ",") + "]"
}
public mutating func decodeExtensionField<D: Decoder>(decoder: inout D) throws {
try decoder.decodeRepeatedMessageField(value: &value)
}
public init?<D: Decoder>(protobufExtension: AnyMessageExtension, decoder: inout D) throws {
var v: ValueType = []
try decoder.decodeRepeatedMessageField(value: &v)
self.init(protobufExtension: protobufExtension, value: v)
}
public func traverse<V: Visitor>(visitor: inout V) throws {
if value.count > 0 {
try visitor.visitRepeatedMessageField(
value: value, fieldNumber: protobufExtension.fieldNumber)
}
}
public var isInitialized: Bool {
return Internal.areAllInitialized(value)
}
}
//
// ======== Groups within Messages ========
//
// Protoc internally treats groups the same as messages, but
// they serialize very differently, so we have separate serialization
// handling here...
public struct OptionalGroupExtensionField<G: Message & Hashable>:
ExtensionField {
public typealias BaseType = G
public typealias ValueType = BaseType
public var value: G
public var protobufExtension: AnyMessageExtension
public static func ==(lhs: OptionalGroupExtensionField,
rhs: OptionalGroupExtensionField) -> Bool {
return lhs.value == rhs.value
}
public init(protobufExtension: AnyMessageExtension, value: ValueType) {
self.protobufExtension = protobufExtension
self.value = value
}
#if swift(>=4.2)
public func hash(into hasher: inout Hasher) {
hasher.combine(value)
}
#else // swift(>=4.2)
public var hashValue: Int {return value.hashValue}
#endif // swift(>=4.2)
public var debugDescription: String { get {return value.debugDescription} }
public func isEqual(other: AnyExtensionField) -> Bool {
let o = other as! OptionalGroupExtensionField<G>
return self == o
}
public mutating func decodeExtensionField<D: Decoder>(decoder: inout D) throws {
var v: ValueType? = value
try decoder.decodeSingularGroupField(value: &v)
if let v = v {
value = v
}
}
public init?<D: Decoder>(protobufExtension: AnyMessageExtension, decoder: inout D) throws {
var v: ValueType?
try decoder.decodeSingularGroupField(value: &v)
if let v = v {
self.init(protobufExtension: protobufExtension, value: v)
} else {
return nil
}
}
public func traverse<V: Visitor>(visitor: inout V) throws {
try visitor.visitSingularGroupField(
value: value, fieldNumber: protobufExtension.fieldNumber)
}
public var isInitialized: Bool {
return value.isInitialized
}
}
public struct RepeatedGroupExtensionField<G: Message & Hashable>:
ExtensionField {
public typealias BaseType = G
public typealias ValueType = [BaseType]
public var value: ValueType
public var protobufExtension: AnyMessageExtension
public static func ==(lhs: RepeatedGroupExtensionField,
rhs: RepeatedGroupExtensionField) -> Bool {
return lhs.value == rhs.value
}
public init(protobufExtension: AnyMessageExtension, value: ValueType) {
self.protobufExtension = protobufExtension
self.value = value
}
#if swift(>=4.2)
public func hash(into hasher: inout Hasher) {
hasher.combine(value)
}
#else // swift(>=4.2)
public var hashValue: Int {
get {
var hash = i_2166136261
for e in value {
hash = (hash &* i_16777619) ^ e.hashValue
}
return hash
}
}
#endif // swift(>=4.2)
public var debugDescription: String {
return "[" + value.map{$0.debugDescription}.joined(separator: ",") + "]"
}
public func isEqual(other: AnyExtensionField) -> Bool {
let o = other as! RepeatedGroupExtensionField<G>
return self == o
}
public mutating func decodeExtensionField<D: Decoder>(decoder: inout D) throws {
try decoder.decodeRepeatedGroupField(value: &value)
}
public init?<D: Decoder>(protobufExtension: AnyMessageExtension, decoder: inout D) throws {
var v: ValueType = []
try decoder.decodeRepeatedGroupField(value: &v)
self.init(protobufExtension: protobufExtension, value: v)
}
public func traverse<V: Visitor>(visitor: inout V) throws {
if value.count > 0 {
try visitor.visitRepeatedGroupField(
value: value, fieldNumber: protobufExtension.fieldNumber)
}
}
public var isInitialized: Bool {
return Internal.areAllInitialized(value)
}
}

View File

@ -0,0 +1,38 @@
// Sources/SwiftProtobuf/ExtensionMap.swift - Extension support
//
// Copyright (c) 2014 - 2017 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// A set of extensions that can be passed into deserializers
/// to provide details of the particular extensions that should
/// be recognized.
///
// -----------------------------------------------------------------------------
/// A collection of extension objects.
///
/// An `ExtensionMap` is used during decoding to look up
/// extension objects corresponding to the serialized data.
///
/// This is a protocol so that developers can build their own
/// extension handling if they need something more complex than the
/// standard `SimpleExtensionMap` implementation.
public protocol ExtensionMap {
/// Returns the extension object describing an extension or nil
subscript(messageType: Message.Type, fieldNumber: Int) -> AnyMessageExtension? { get }
/// Returns the field number for a message with a specific field name
///
/// The field name here matches the format used by the protobuf
/// Text serialization: it typically looks like
/// `package.message.field_name`, where `package` is the package
/// for the proto file and `message` is the name of the message in
/// which the extension was defined. (This is different from the
/// message that is being extended!)
func fieldNumberForProto(messageType: Message.Type, protoFieldName: String) -> Int?
}

View File

@ -0,0 +1,69 @@
// Sources/SwiftProtobuf/FieldTag.swift - Describes a binary field tag
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Types related to binary encoded tags (field numbers and wire formats).
///
// -----------------------------------------------------------------------------
/// Encapsulates the number and wire format of a field, which together form the
/// "tag".
///
/// This type also validates tags in that it will never allow a tag with an
/// improper field number (such as zero) or wire format (such as 6 or 7) to
/// exist. In other words, a `FieldTag`'s properties never need to be tested
/// for validity because they are guaranteed correct at initialization time.
internal struct FieldTag: RawRepresentable {
typealias RawValue = UInt32
/// The raw numeric value of the tag, which contains both the field number and
/// wire format.
let rawValue: UInt32
/// The field number component of the tag.
var fieldNumber: Int {
return Int(rawValue >> 3)
}
/// The wire format component of the tag.
var wireFormat: WireFormat {
// This force-unwrap is safe because there are only two initialization
// paths: one that takes a WireFormat directly (and is guaranteed valid at
// compile-time), or one that takes a raw value but which only lets valid
// wire formats through.
return WireFormat(rawValue: UInt8(rawValue & 7))!
}
/// A helper property that returns the number of bytes required to
/// varint-encode this tag.
var encodedSize: Int {
return Varint.encodedSize(of: rawValue)
}
/// Creates a new tag from its raw numeric representation.
///
/// Note that if the raw value given here is not a valid tag (for example, it
/// has an invalid wire format), this initializer will fail.
init?(rawValue: UInt32) {
// Verify that the field number and wire format are valid and fail if they
// are not.
guard rawValue & ~0x07 != 0,
let _ = WireFormat(rawValue: UInt8(rawValue % 8)) else {
return nil
}
self.rawValue = rawValue
}
/// Creates a new tag by composing the given field number and wire format.
init(fieldNumber: Int, wireFormat: WireFormat) {
self.rawValue = UInt32(truncatingIfNeeded: fieldNumber) << 3 |
UInt32(wireFormat.rawValue)
}
}

View File

@ -0,0 +1,412 @@
// Sources/SwiftProtobuf/FieldTypes.swift - Proto data types
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Serialization/deserialization support for each proto field type.
///
/// Note that we cannot just extend the standard Int32, etc, types
/// with serialization information since proto language supports
/// distinct types (with different codings) that use the same
/// in-memory representation. For example, proto "sint32" and
/// "sfixed32" both are represented in-memory as Int32.
///
/// These types are used generically and also passed into
/// various coding/decoding functions to provide type-specific
/// information.
///
// -----------------------------------------------------------------------------
import Foundation
// Note: The protobuf- and JSON-specific methods here are defined
// in ProtobufTypeAdditions.swift and JSONTypeAdditions.swift
public protocol FieldType {
// The Swift type used to store data for this field. For example,
// proto "sint32" fields use Swift "Int32" type.
associatedtype BaseType: Hashable
// The default value for this field type before it has been set.
// This is also used, for example, when JSON decodes a "null"
// value for a field.
static var proto3DefaultValue: BaseType { get }
// Generic reflector methods for looking up the correct
// encoding/decoding for extension fields, map keys, and map
// values.
static func decodeSingular<D: Decoder>(value: inout BaseType?, from decoder: inout D) throws
static func decodeRepeated<D: Decoder>(value: inout [BaseType], from decoder: inout D) throws
static func visitSingular<V: Visitor>(value: BaseType, fieldNumber: Int, with visitor: inout V) throws
static func visitRepeated<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws
static func visitPacked<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws
}
///
/// Marker protocol for types that can be used as map keys
///
public protocol MapKeyType: FieldType {
}
///
/// Marker Protocol for types that can be used as map values.
///
public protocol MapValueType: FieldType {
}
//
// We have a struct for every basic proto field type which provides
// serialization/deserialization support as static methods.
//
///
/// Float traits
///
public struct ProtobufFloat: FieldType, MapValueType {
public typealias BaseType = Float
public static var proto3DefaultValue: Float {return 0.0}
public static func decodeSingular<D: Decoder>(value: inout BaseType?, from decoder: inout D) throws {
try decoder.decodeSingularFloatField(value: &value)
}
public static func decodeRepeated<D: Decoder>(value: inout [BaseType], from decoder: inout D) throws {
try decoder.decodeRepeatedFloatField(value: &value)
}
public static func visitSingular<V: Visitor>(value: BaseType, fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitSingularFloatField(value: value, fieldNumber: fieldNumber)
}
public static func visitRepeated<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitRepeatedFloatField(value: value, fieldNumber: fieldNumber)
}
public static func visitPacked<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitPackedFloatField(value: value, fieldNumber: fieldNumber)
}
}
///
/// Double
///
public struct ProtobufDouble: FieldType, MapValueType {
public typealias BaseType = Double
public static var proto3DefaultValue: Double {return 0.0}
public static func decodeSingular<D: Decoder>(value: inout BaseType?, from decoder: inout D) throws {
try decoder.decodeSingularDoubleField(value: &value)
}
public static func decodeRepeated<D: Decoder>(value: inout [BaseType], from decoder: inout D) throws {
try decoder.decodeRepeatedDoubleField(value: &value)
}
public static func visitSingular<V: Visitor>(value: BaseType, fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitSingularDoubleField(value: value, fieldNumber: fieldNumber)
}
public static func visitRepeated<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitRepeatedDoubleField(value: value, fieldNumber: fieldNumber)
}
public static func visitPacked<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitPackedDoubleField(value: value, fieldNumber: fieldNumber)
}
}
///
/// Int32
///
public struct ProtobufInt32: FieldType, MapKeyType, MapValueType {
public typealias BaseType = Int32
public static var proto3DefaultValue: Int32 {return 0}
public static func decodeSingular<D: Decoder>(value: inout BaseType?, from decoder: inout D) throws {
try decoder.decodeSingularInt32Field(value: &value)
}
public static func decodeRepeated<D: Decoder>(value: inout [BaseType], from decoder: inout D) throws {
try decoder.decodeRepeatedInt32Field(value: &value)
}
public static func visitSingular<V: Visitor>(value: BaseType, fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitSingularInt32Field(value: value, fieldNumber: fieldNumber)
}
public static func visitRepeated<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitRepeatedInt32Field(value: value, fieldNumber: fieldNumber)
}
public static func visitPacked<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitPackedInt32Field(value: value, fieldNumber: fieldNumber)
}
}
///
/// Int64
///
public struct ProtobufInt64: FieldType, MapKeyType, MapValueType {
public typealias BaseType = Int64
public static var proto3DefaultValue: Int64 {return 0}
public static func decodeSingular<D: Decoder>(value: inout BaseType?, from decoder: inout D) throws {
try decoder.decodeSingularInt64Field(value: &value)
}
public static func decodeRepeated<D: Decoder>(value: inout [BaseType], from decoder: inout D) throws {
try decoder.decodeRepeatedInt64Field(value: &value)
}
public static func visitSingular<V: Visitor>(value: BaseType, fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitSingularInt64Field(value: value, fieldNumber: fieldNumber)
}
public static func visitRepeated<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitRepeatedInt64Field(value: value, fieldNumber: fieldNumber)
}
public static func visitPacked<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitPackedInt64Field(value: value, fieldNumber: fieldNumber)
}
}
///
/// UInt32
///
public struct ProtobufUInt32: FieldType, MapKeyType, MapValueType {
public typealias BaseType = UInt32
public static var proto3DefaultValue: UInt32 {return 0}
public static func decodeSingular<D: Decoder>(value: inout BaseType?, from decoder: inout D) throws {
try decoder.decodeSingularUInt32Field(value: &value)
}
public static func decodeRepeated<D: Decoder>(value: inout [BaseType], from decoder: inout D) throws {
try decoder.decodeRepeatedUInt32Field(value: &value)
}
public static func visitSingular<V: Visitor>(value: BaseType, fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitSingularUInt32Field(value: value, fieldNumber: fieldNumber)
}
public static func visitRepeated<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitRepeatedUInt32Field(value: value, fieldNumber: fieldNumber)
}
public static func visitPacked<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitPackedUInt32Field(value: value, fieldNumber: fieldNumber)
}
}
///
/// UInt64
///
public struct ProtobufUInt64: FieldType, MapKeyType, MapValueType {
public typealias BaseType = UInt64
public static var proto3DefaultValue: UInt64 {return 0}
public static func decodeSingular<D: Decoder>(value: inout BaseType?, from decoder: inout D) throws {
try decoder.decodeSingularUInt64Field(value: &value)
}
public static func decodeRepeated<D: Decoder>(value: inout [BaseType], from decoder: inout D) throws {
try decoder.decodeRepeatedUInt64Field(value: &value)
}
public static func visitSingular<V: Visitor>(value: BaseType, fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitSingularUInt64Field(value: value, fieldNumber: fieldNumber)
}
public static func visitRepeated<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitRepeatedUInt64Field(value: value, fieldNumber: fieldNumber)
}
public static func visitPacked<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitPackedUInt64Field(value: value, fieldNumber: fieldNumber)
}
}
///
/// SInt32
///
public struct ProtobufSInt32: FieldType, MapKeyType, MapValueType {
public typealias BaseType = Int32
public static var proto3DefaultValue: Int32 {return 0}
public static func decodeSingular<D: Decoder>(value: inout BaseType?, from decoder: inout D) throws {
try decoder.decodeSingularSInt32Field(value: &value)
}
public static func decodeRepeated<D: Decoder>(value: inout [BaseType], from decoder: inout D) throws {
try decoder.decodeRepeatedSInt32Field(value: &value)
}
public static func visitSingular<V: Visitor>(value: BaseType, fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitSingularSInt32Field(value: value, fieldNumber: fieldNumber)
}
public static func visitRepeated<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitRepeatedSInt32Field(value: value, fieldNumber: fieldNumber)
}
public static func visitPacked<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitPackedSInt32Field(value: value, fieldNumber: fieldNumber)
}
}
///
/// SInt64
///
public struct ProtobufSInt64: FieldType, MapKeyType, MapValueType {
public typealias BaseType = Int64
public static var proto3DefaultValue: Int64 {return 0}
public static func decodeSingular<D: Decoder>(value: inout BaseType?, from decoder: inout D) throws {
try decoder.decodeSingularSInt64Field(value: &value)
}
public static func decodeRepeated<D: Decoder>(value: inout [BaseType], from decoder: inout D) throws {
try decoder.decodeRepeatedSInt64Field(value: &value)
}
public static func visitSingular<V: Visitor>(value: BaseType, fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitSingularSInt64Field(value: value, fieldNumber: fieldNumber)
}
public static func visitRepeated<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitRepeatedSInt64Field(value: value, fieldNumber: fieldNumber)
}
public static func visitPacked<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitPackedSInt64Field(value: value, fieldNumber: fieldNumber)
}
}
///
/// Fixed32
///
public struct ProtobufFixed32: FieldType, MapKeyType, MapValueType {
public typealias BaseType = UInt32
public static var proto3DefaultValue: UInt32 {return 0}
public static func decodeSingular<D: Decoder>(value: inout BaseType?, from decoder: inout D) throws {
try decoder.decodeSingularFixed32Field(value: &value)
}
public static func decodeRepeated<D: Decoder>(value: inout [BaseType], from decoder: inout D) throws {
try decoder.decodeRepeatedFixed32Field(value: &value)
}
public static func visitSingular<V: Visitor>(value: BaseType, fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitSingularFixed32Field(value: value, fieldNumber: fieldNumber)
}
public static func visitRepeated<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitRepeatedFixed32Field(value: value, fieldNumber: fieldNumber)
}
public static func visitPacked<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitPackedFixed32Field(value: value, fieldNumber: fieldNumber)
}
}
///
/// Fixed64
///
public struct ProtobufFixed64: FieldType, MapKeyType, MapValueType {
public typealias BaseType = UInt64
public static var proto3DefaultValue: UInt64 {return 0}
public static func decodeSingular<D: Decoder>(value: inout BaseType?, from decoder: inout D) throws {
try decoder.decodeSingularFixed64Field(value: &value)
}
public static func decodeRepeated<D: Decoder>(value: inout [BaseType], from decoder: inout D) throws {
try decoder.decodeRepeatedFixed64Field(value: &value)
}
public static func visitSingular<V: Visitor>(value: BaseType, fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitSingularFixed64Field(value: value, fieldNumber: fieldNumber)
}
public static func visitRepeated<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitRepeatedFixed64Field(value: value, fieldNumber: fieldNumber)
}
public static func visitPacked<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitPackedFixed64Field(value: value, fieldNumber: fieldNumber)
}
}
///
/// SFixed32
///
public struct ProtobufSFixed32: FieldType, MapKeyType, MapValueType {
public typealias BaseType = Int32
public static var proto3DefaultValue: Int32 {return 0}
public static func decodeSingular<D: Decoder>(value: inout BaseType?, from decoder: inout D) throws {
try decoder.decodeSingularSFixed32Field(value: &value)
}
public static func decodeRepeated<D: Decoder>(value: inout [BaseType], from decoder: inout D) throws {
try decoder.decodeRepeatedSFixed32Field(value: &value)
}
public static func visitSingular<V: Visitor>(value: BaseType, fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitSingularSFixed32Field(value: value, fieldNumber: fieldNumber)
}
public static func visitRepeated<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitRepeatedSFixed32Field(value: value, fieldNumber: fieldNumber)
}
public static func visitPacked<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitPackedSFixed32Field(value: value, fieldNumber: fieldNumber)
}
}
///
/// SFixed64
///
public struct ProtobufSFixed64: FieldType, MapKeyType, MapValueType {
public typealias BaseType = Int64
public static var proto3DefaultValue: Int64 {return 0}
public static func decodeSingular<D: Decoder>(value: inout BaseType?, from decoder: inout D) throws {
try decoder.decodeSingularSFixed64Field(value: &value)
}
public static func decodeRepeated<D: Decoder>(value: inout [BaseType], from decoder: inout D) throws {
try decoder.decodeRepeatedSFixed64Field(value: &value)
}
public static func visitSingular<V: Visitor>(value: BaseType, fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitSingularSFixed64Field(value: value, fieldNumber: fieldNumber)
}
public static func visitRepeated<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitRepeatedSFixed64Field(value: value, fieldNumber: fieldNumber)
}
public static func visitPacked<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitPackedSFixed64Field(value: value, fieldNumber: fieldNumber)
}
}
///
/// Bool
///
public struct ProtobufBool: FieldType, MapKeyType, MapValueType {
public typealias BaseType = Bool
public static var proto3DefaultValue: Bool {return false}
public static func decodeSingular<D: Decoder>(value: inout BaseType?, from decoder: inout D) throws {
try decoder.decodeSingularBoolField(value: &value)
}
public static func decodeRepeated<D: Decoder>(value: inout [BaseType], from decoder: inout D) throws {
try decoder.decodeRepeatedBoolField(value: &value)
}
public static func visitSingular<V: Visitor>(value: BaseType, fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitSingularBoolField(value: value, fieldNumber: fieldNumber)
}
public static func visitRepeated<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitRepeatedBoolField(value: value, fieldNumber: fieldNumber)
}
public static func visitPacked<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitPackedBoolField(value: value, fieldNumber: fieldNumber)
}
}
///
/// String
///
public struct ProtobufString: FieldType, MapKeyType, MapValueType {
public typealias BaseType = String
public static var proto3DefaultValue: String {return String()}
public static func decodeSingular<D: Decoder>(value: inout BaseType?, from decoder: inout D) throws {
try decoder.decodeSingularStringField(value: &value)
}
public static func decodeRepeated<D: Decoder>(value: inout [BaseType], from decoder: inout D) throws {
try decoder.decodeRepeatedStringField(value: &value)
}
public static func visitSingular<V: Visitor>(value: BaseType, fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitSingularStringField(value: value, fieldNumber: fieldNumber)
}
public static func visitRepeated<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitRepeatedStringField(value: value, fieldNumber: fieldNumber)
}
public static func visitPacked<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws {
assert(false)
}
}
///
/// Bytes
///
public struct ProtobufBytes: FieldType, MapValueType {
public typealias BaseType = Data
public static var proto3DefaultValue: Data {return Data()}
public static func decodeSingular<D: Decoder>(value: inout BaseType?, from decoder: inout D) throws {
try decoder.decodeSingularBytesField(value: &value)
}
public static func decodeRepeated<D: Decoder>(value: inout [BaseType], from decoder: inout D) throws {
try decoder.decodeRepeatedBytesField(value: &value)
}
public static func visitSingular<V: Visitor>(value: BaseType, fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitSingularBytesField(value: value, fieldNumber: fieldNumber)
}
public static func visitRepeated<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws {
try visitor.visitRepeatedBytesField(value: value, fieldNumber: fieldNumber)
}
public static func visitPacked<V: Visitor>(value: [BaseType], fieldNumber: Int, with visitor: inout V) throws {
assert(false)
}
}

View File

@ -0,0 +1,143 @@
// Sources/SwiftProtobuf/Google_Protobuf_Any+Extensions.swift - Well-known Any type
//
// Copyright (c) 2014 - 2017 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Extends the `Google_Protobuf_Any` type with various custom behaviors.
///
// -----------------------------------------------------------------------------
// Explicit import of Foundation is necessary on Linux,
// don't remove unless obsolete on all platforms
import Foundation
public let defaultAnyTypeURLPrefix: String = "type.googleapis.com"
extension Google_Protobuf_Any {
/// Initialize an Any object from the provided message.
///
/// This corresponds to the `pack` operation in the C++ API.
///
/// Unlike the C++ implementation, the message is not immediately
/// serialized; it is merely stored until the Any object itself
/// needs to be serialized. This design avoids unnecessary
/// decoding/recoding when writing JSON format.
///
/// - Parameters:
/// - partial: If `false` (the default), this method will check
/// `Message.isInitialized` before encoding to verify that all required
/// fields are present. If any are missing, this method throws
/// `BinaryEncodingError.missingRequiredFields`.
/// - typePrefix: The prefix to be used when building the `type_url`.
/// Defaults to "type.googleapis.com".
/// - Throws: `BinaryEncodingError.missingRequiredFields` if `partial` is
/// false and `message` wasn't fully initialized.
public init(
message: Message,
partial: Bool = false,
typePrefix: String = defaultAnyTypeURLPrefix
) throws {
if !partial && !message.isInitialized {
throw BinaryEncodingError.missingRequiredFields
}
self.init()
typeURL = buildTypeURL(forMessage:message, typePrefix: typePrefix)
_storage.state = .message(message)
}
/// Creates a new `Google_Protobuf_Any` by decoding the given string
/// containing a serialized message in Protocol Buffer text format.
///
/// - Parameters:
/// - textFormatString: The text format string to decode.
/// - extensions: An `ExtensionMap` used to look up and decode any
/// extensions in this message or messages nested within this message's
/// fields.
/// - Throws: an instance of `TextFormatDecodingError` on failure.
public init(
textFormatString: String,
extensions: ExtensionMap? = nil
) throws {
self.init()
if !textFormatString.isEmpty {
if let data = textFormatString.data(using: String.Encoding.utf8) {
try data.withUnsafeBytes { (body: UnsafeRawBufferPointer) in
if let baseAddress = body.baseAddress, body.count > 0 {
var textDecoder = try TextFormatDecoder(
messageType: Google_Protobuf_Any.self,
utf8Pointer: baseAddress,
count: body.count,
extensions: extensions)
try decodeTextFormat(decoder: &textDecoder)
if !textDecoder.complete {
throw TextFormatDecodingError.trailingGarbage
}
}
}
}
}
}
/// Returns true if this `Google_Protobuf_Any` message contains the given
/// message type.
///
/// The check is performed by looking at the passed `Message.Type` and the
/// `typeURL` of this message.
///
/// - Parameter type: The concrete message type.
/// - Returns: True if the receiver contains the given message type.
public func isA<M: Message>(_ type: M.Type) -> Bool {
return _storage.isA(type)
}
#if swift(>=4.2)
public func hash(into hasher: inout Hasher) {
_storage.hash(into: &hasher)
}
#else // swift(>=4.2)
public var hashValue: Int {
return _storage.hashValue
}
#endif // swift(>=4.2)
}
extension Google_Protobuf_Any {
internal func textTraverse(visitor: inout TextFormatEncodingVisitor) {
_storage.textTraverse(visitor: &visitor)
try! unknownFields.traverse(visitor: &visitor)
}
}
extension Google_Protobuf_Any: _CustomJSONCodable {
// Custom text format decoding support for Any objects.
// (Note: This is not a part of any protocol; it's invoked
// directly from TextFormatDecoder whenever it sees an attempt
// to decode an Any object)
internal mutating func decodeTextFormat(
decoder: inout TextFormatDecoder
) throws {
// First, check if this uses the "verbose" Any encoding.
// If it does, and we have the type available, we can
// eagerly decode the contained Message object.
if let url = try decoder.scanner.nextOptionalAnyURL() {
try _uniqueStorage().decodeTextFormat(typeURL: url, decoder: &decoder)
} else {
// This is not using the specialized encoding, so we can use the
// standard path to decode the binary value.
try decodeMessage(decoder: &decoder)
}
}
internal func encodedJSONString(options: JSONEncodingOptions) throws -> String {
return try _storage.encodedJSONString(options: options)
}
internal mutating func decodeJSON(from decoder: inout JSONDecoder) throws {
try _uniqueStorage().decodeJSON(from: &decoder)
}
}

View File

@ -0,0 +1,135 @@
// Sources/SwiftProtobuf/Google_Protobuf_Any+Registry.swift - Registry for JSON support
//
// Copyright (c) 2014 - 2017 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Support for registering and looking up Message types. Used
/// in support of Google_Protobuf_Any.
///
// -----------------------------------------------------------------------------
import Foundation
import Dispatch
// TODO: Should these first four be exposed as methods to go with
// the general registry support?
internal func buildTypeURL(forMessage message: Message, typePrefix: String) -> String {
var url = typePrefix
let needsSlash = typePrefix.isEmpty || typePrefix.last != "/"
if needsSlash {
url += "/"
}
return url + typeName(fromMessage: message)
}
internal func typeName(fromMessage message: Message) -> String {
let messageType = type(of: message)
return messageType.protoMessageName
}
internal func typeName(fromURL s: String) -> String {
var typeStart = s.startIndex
var i = typeStart
while i < s.endIndex {
let c = s[i]
i = s.index(after: i)
if c == "/" {
typeStart = i
}
}
return String(s[typeStart..<s.endIndex])
}
fileprivate var serialQueue = DispatchQueue(label: "org.swift.protobuf.typeRegistry")
// All access to this should be done on `serialQueue`.
fileprivate var knownTypes: [String:Message.Type] = [
// Seeded with the Well Known Types.
"google.protobuf.Any": Google_Protobuf_Any.self,
"google.protobuf.BoolValue": Google_Protobuf_BoolValue.self,
"google.protobuf.BytesValue": Google_Protobuf_BytesValue.self,
"google.protobuf.DoubleValue": Google_Protobuf_DoubleValue.self,
"google.protobuf.Duration": Google_Protobuf_Duration.self,
"google.protobuf.Empty": Google_Protobuf_Empty.self,
"google.protobuf.FieldMask": Google_Protobuf_FieldMask.self,
"google.protobuf.FloatValue": Google_Protobuf_FloatValue.self,
"google.protobuf.Int32Value": Google_Protobuf_Int32Value.self,
"google.protobuf.Int64Value": Google_Protobuf_Int64Value.self,
"google.protobuf.ListValue": Google_Protobuf_ListValue.self,
"google.protobuf.StringValue": Google_Protobuf_StringValue.self,
"google.protobuf.Struct": Google_Protobuf_Struct.self,
"google.protobuf.Timestamp": Google_Protobuf_Timestamp.self,
"google.protobuf.UInt32Value": Google_Protobuf_UInt32Value.self,
"google.protobuf.UInt64Value": Google_Protobuf_UInt64Value.self,
"google.protobuf.Value": Google_Protobuf_Value.self,
]
extension Google_Protobuf_Any {
/// Register a message type so that Any objects can use
/// them for decoding contents.
///
/// This is currently only required in two cases:
///
/// * When decoding Protobuf Text format. Currently,
/// Any objects do not defer deserialization from Text
/// format. Depending on how the Any objects are stored
/// in text format, the Any object may need to look up
/// the message type in order to deserialize itself.
///
/// * When re-encoding an Any object into a different
/// format than it was decoded from. For example, if
/// you decode a message containing an Any object from
/// JSON format and then re-encode the message into Protobuf
/// Binary format, the Any object will need to complete the
/// deferred deserialization of the JSON object before it
/// can re-encode.
///
/// Note that well-known types are pre-registered for you and
/// you do not need to register them from your code.
///
/// Also note that this is not needed if you only decode and encode
/// to and from the same format.
///
/// Returns: true if the type was registered, false if something
/// else was already registered for the messageName.
@discardableResult public static func register(messageType: Message.Type) -> Bool {
let messageTypeName = messageType.protoMessageName
var result: Bool = false
serialQueue.sync {
if let alreadyRegistered = knownTypes[messageTypeName] {
// Success/failure when something was already registered is
// based on if they are registering the same class or trying
// to register a different type
result = alreadyRegistered == messageType
} else {
knownTypes[messageTypeName] = messageType
result = true
}
}
return result
}
/// Returns the Message.Type expected for the given type URL.
public static func messageType(forTypeURL url: String) -> Message.Type? {
let messageTypeName = typeName(fromURL: url)
return messageType(forMessageName: messageTypeName)
}
/// Returns the Message.Type expected for the given proto message name.
public static func messageType(forMessageName name: String) -> Message.Type? {
var result: Message.Type?
serialQueue.sync {
result = knownTypes[name]
}
return result
}
}

View File

@ -0,0 +1,234 @@
// Sources/SwiftProtobuf/Google_Protobuf_Duration+Extensions.swift - Extensions for Duration type
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Extends the generated Duration struct with various custom behaviors:
/// * JSON coding and decoding
/// * Arithmetic operations
///
// -----------------------------------------------------------------------------
import Foundation
private let minDurationSeconds: Int64 = -maxDurationSeconds
private let maxDurationSeconds: Int64 = 315576000000
private func parseDuration(text: String) throws -> (Int64, Int32) {
var digits = [Character]()
var digitCount = 0
var total = 0
var chars = text.makeIterator()
var seconds: Int64?
var nanos: Int32 = 0
while let c = chars.next() {
switch c {
case "-":
// Only accept '-' as very first character
if total > 0 {
throw JSONDecodingError.malformedDuration
}
digits.append(c)
case "0", "1", "2", "3", "4", "5", "6", "7", "8", "9":
digits.append(c)
digitCount += 1
case ".":
if let _ = seconds {
throw JSONDecodingError.malformedDuration
}
let digitString = String(digits)
if let s = Int64(digitString),
s >= minDurationSeconds && s <= maxDurationSeconds {
seconds = s
} else {
throw JSONDecodingError.malformedDuration
}
digits.removeAll()
digitCount = 0
case "s":
if let seconds = seconds {
// Seconds already set, digits holds nanos
while (digitCount < 9) {
digits.append(Character("0"))
digitCount += 1
}
while digitCount > 9 {
digits.removeLast()
digitCount -= 1
}
let digitString = String(digits)
if let rawNanos = Int32(digitString) {
if seconds < 0 {
nanos = -rawNanos
} else {
nanos = rawNanos
}
} else {
throw JSONDecodingError.malformedDuration
}
} else {
// No fraction, we just have an integral number of seconds
let digitString = String(digits)
if let s = Int64(digitString),
s >= minDurationSeconds && s <= maxDurationSeconds {
seconds = s
} else {
throw JSONDecodingError.malformedDuration
}
}
// Fail if there are characters after 's'
if chars.next() != nil {
throw JSONDecodingError.malformedDuration
}
return (seconds!, nanos)
default:
throw JSONDecodingError.malformedDuration
}
total += 1
}
throw JSONDecodingError.malformedDuration
}
private func formatDuration(seconds: Int64, nanos: Int32) -> String? {
let (seconds, nanos) = normalizeForDuration(seconds: seconds, nanos: nanos)
guard seconds >= minDurationSeconds && seconds <= maxDurationSeconds else {
return nil
}
if nanos == 0 {
return String(format: "%llds", seconds)
} else if nanos % 1000000 == 0 {
return String(format: "%lld.%03ds", seconds, abs(nanos) / 1000000)
} else if nanos % 1000 == 0 {
return String(format: "%lld.%06ds", seconds, abs(nanos) / 1000)
} else {
return String(format: "%lld.%09ds", seconds, abs(nanos))
}
}
extension Google_Protobuf_Duration {
/// Creates a new `Google_Protobuf_Duration` equal to the given number of
/// seconds and nanoseconds.
///
/// - Parameter seconds: The number of seconds.
/// - Parameter nanos: The number of nanoseconds.
public init(seconds: Int64 = 0, nanos: Int32 = 0) {
self.init()
self.seconds = seconds
self.nanos = nanos
}
}
extension Google_Protobuf_Duration: _CustomJSONCodable {
mutating func decodeJSON(from decoder: inout JSONDecoder) throws {
let s = try decoder.scanner.nextQuotedString()
(seconds, nanos) = try parseDuration(text: s)
}
func encodedJSONString(options: JSONEncodingOptions) throws -> String {
if let formatted = formatDuration(seconds: seconds, nanos: nanos) {
return "\"\(formatted)\""
} else {
throw JSONEncodingError.durationRange
}
}
}
extension Google_Protobuf_Duration: ExpressibleByFloatLiteral {
public typealias FloatLiteralType = Double
/// Creates a new `Google_Protobuf_Duration` from a floating point literal
/// that is interpreted as a duration in seconds, rounded to the nearest
/// nanosecond.
public init(floatLiteral value: Double) {
let sd = trunc(value)
let nd = round((value - sd) * TimeInterval(nanosPerSecond))
let (s, n) = normalizeForDuration(seconds: Int64(sd), nanos: Int32(nd))
self.init(seconds: s, nanos: n)
}
}
extension Google_Protobuf_Duration {
/// Creates a new `Google_Protobuf_Duration` that is equal to the given
/// `TimeInterval` (measured in seconds), rounded to the nearest nanosecond.
///
/// - Parameter timeInterval: The `TimeInterval`.
public init(timeInterval: TimeInterval) {
let sd = trunc(timeInterval)
let nd = round((timeInterval - sd) * TimeInterval(nanosPerSecond))
let (s, n) = normalizeForDuration(seconds: Int64(sd), nanos: Int32(nd))
self.init(seconds: s, nanos: n)
}
/// The `TimeInterval` (measured in seconds) equal to this duration.
public var timeInterval: TimeInterval {
return TimeInterval(self.seconds) +
TimeInterval(self.nanos) / TimeInterval(nanosPerSecond)
}
}
private func normalizeForDuration(
seconds: Int64,
nanos: Int32
) -> (seconds: Int64, nanos: Int32) {
var s = seconds
var n = nanos
// If the magnitude of n exceeds a second then
// we need to factor it into s instead.
if n >= nanosPerSecond || n <= -nanosPerSecond {
s += Int64(n / nanosPerSecond)
n = n % nanosPerSecond
}
// The Duration spec says that when s != 0, s and
// n must have the same sign.
if s > 0 && n < 0 {
n += nanosPerSecond
s -= 1
} else if s < 0 && n > 0 {
n -= nanosPerSecond
s += 1
}
return (seconds: s, nanos: n)
}
public prefix func - (
operand: Google_Protobuf_Duration
) -> Google_Protobuf_Duration {
let (s, n) = normalizeForDuration(seconds: -operand.seconds,
nanos: -operand.nanos)
return Google_Protobuf_Duration(seconds: s, nanos: n)
}
public func + (
lhs: Google_Protobuf_Duration,
rhs: Google_Protobuf_Duration
) -> Google_Protobuf_Duration {
let (s, n) = normalizeForDuration(seconds: lhs.seconds + rhs.seconds,
nanos: lhs.nanos + rhs.nanos)
return Google_Protobuf_Duration(seconds: s, nanos: n)
}
public func - (
lhs: Google_Protobuf_Duration,
rhs: Google_Protobuf_Duration
) -> Google_Protobuf_Duration {
let (s, n) = normalizeForDuration(seconds: lhs.seconds - rhs.seconds,
nanos: lhs.nanos - rhs.nanos)
return Google_Protobuf_Duration(seconds: s, nanos: n)
}
public func - (
lhs: Google_Protobuf_Timestamp,
rhs: Google_Protobuf_Timestamp
) -> Google_Protobuf_Duration {
let (s, n) = normalizeForDuration(seconds: lhs.seconds - rhs.seconds,
nanos: lhs.nanos - rhs.nanos)
return Google_Protobuf_Duration(seconds: s, nanos: n)
}

View File

@ -0,0 +1,163 @@
// Sources/SwiftProtobuf/Google_Protobuf_FieldMask+Extensions.swift - Fieldmask extensions
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Extend the generated FieldMask message with customized JSON coding and
/// convenience methods.
///
// -----------------------------------------------------------------------------
// TODO: We should have utilities to apply a fieldmask to an arbitrary
// message, intersect two fieldmasks, etc.
private func ProtoToJSON(name: String) -> String? {
var jsonPath = String()
var chars = name.makeIterator()
while let c = chars.next() {
switch c {
case "_":
if let toupper = chars.next() {
switch toupper {
case "a"..."z":
jsonPath.append(String(toupper).uppercased())
default:
return nil
}
} else {
return nil
}
case "A"..."Z":
return nil
default:
jsonPath.append(c)
}
}
return jsonPath
}
private func JSONToProto(name: String) -> String? {
var path = String()
for c in name {
switch c {
case "_":
return nil
case "A"..."Z":
path.append(Character("_"))
path.append(String(c).lowercased())
default:
path.append(c)
}
}
return path
}
private func parseJSONFieldNames(names: String) -> [String]? {
// An empty field mask is the empty string (no paths).
guard !names.isEmpty else { return [] }
var fieldNameCount = 0
var fieldName = String()
var split = [String]()
for c in names {
switch c {
case ",":
if fieldNameCount == 0 {
return nil
}
if let pbName = JSONToProto(name: fieldName) {
split.append(pbName)
} else {
return nil
}
fieldName = String()
fieldNameCount = 0
default:
fieldName.append(c)
fieldNameCount += 1
}
}
if fieldNameCount == 0 { // Last field name can't be empty
return nil
}
if let pbName = JSONToProto(name: fieldName) {
split.append(pbName)
} else {
return nil
}
return split
}
extension Google_Protobuf_FieldMask {
/// Creates a new `Google_Protobuf_FieldMask` from the given array of paths.
///
/// The paths should match the names used in the .proto file, which may be
/// different than the corresponding Swift property names.
///
/// - Parameter protoPaths: The paths from which to create the field mask,
/// defined using the .proto names for the fields.
public init(protoPaths: [String]) {
self.init()
paths = protoPaths
}
/// Creates a new `Google_Protobuf_FieldMask` from the given paths.
///
/// The paths should match the names used in the .proto file, which may be
/// different than the corresponding Swift property names.
///
/// - Parameter protoPaths: The paths from which to create the field mask,
/// defined using the .proto names for the fields.
public init(protoPaths: String...) {
self.init(protoPaths: protoPaths)
}
/// Creates a new `Google_Protobuf_FieldMask` from the given paths.
///
/// The paths should match the JSON names of the fields, which may be
/// different than the corresponding Swift property names.
///
/// - Parameter jsonPaths: The paths from which to create the field mask,
/// defined using the JSON names for the fields.
public init?(jsonPaths: String...) {
// TODO: This should fail if any of the conversions from JSON fails
#if swift(>=4.1)
self.init(protoPaths: jsonPaths.compactMap(JSONToProto))
#else
self.init(protoPaths: jsonPaths.flatMap(JSONToProto))
#endif
}
// It would be nice if to have an initializer that accepted Swift property
// names, but translating between swift and protobuf/json property
// names is not entirely deterministic.
}
extension Google_Protobuf_FieldMask: _CustomJSONCodable {
mutating func decodeJSON(from decoder: inout JSONDecoder) throws {
let s = try decoder.scanner.nextQuotedString()
if let names = parseJSONFieldNames(names: s) {
paths = names
} else {
throw JSONDecodingError.malformedFieldMask
}
}
func encodedJSONString(options: JSONEncodingOptions) throws -> String {
// Note: Proto requires alphanumeric field names, so there
// cannot be a ',' or '"' character to mess up this formatting.
var jsonPaths = [String]()
for p in paths {
if let jsonPath = ProtoToJSON(name: p) {
jsonPaths.append(jsonPath)
} else {
throw JSONEncodingError.fieldMaskConversion
}
}
return "\"" + jsonPaths.joined(separator: ",") + "\""
}
}

View File

@ -0,0 +1,80 @@
// Sources/SwiftProtobuf/Google_Protobuf_ListValue+Extensions.swift - ListValue extensions
//
// Copyright (c) 2014 - 2017 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// ListValue is a well-known message type that can be used to parse or encode
/// arbitrary JSON arrays without a predefined schema.
///
// -----------------------------------------------------------------------------
extension Google_Protobuf_ListValue: ExpressibleByArrayLiteral {
// TODO: Give this a direct array interface by proxying the interesting
// bits down to values
public typealias Element = Google_Protobuf_Value
/// Creates a new `Google_Protobuf_ListValue` from an array literal containing
/// `Google_Protobuf_Value` elements.
public init(arrayLiteral elements: Element...) {
self.init(values: elements)
}
}
extension Google_Protobuf_ListValue: _CustomJSONCodable {
internal func encodedJSONString(options: JSONEncodingOptions) throws -> String {
var jsonEncoder = JSONEncoder()
jsonEncoder.append(text: "[")
var separator: StaticString = ""
for v in values {
jsonEncoder.append(staticText: separator)
try v.serializeJSONValue(to: &jsonEncoder, options: options)
separator = ","
}
jsonEncoder.append(text: "]")
return jsonEncoder.stringResult
}
internal mutating func decodeJSON(from decoder: inout JSONDecoder) throws {
if decoder.scanner.skipOptionalNull() {
return
}
try decoder.scanner.skipRequiredArrayStart()
if decoder.scanner.skipOptionalArrayEnd() {
return
}
while true {
var v = Google_Protobuf_Value()
try v.decodeJSON(from: &decoder)
values.append(v)
if decoder.scanner.skipOptionalArrayEnd() {
return
}
try decoder.scanner.skipRequiredComma()
}
}
}
extension Google_Protobuf_ListValue {
/// Creates a new `Google_Protobuf_ListValue` from the given array of
/// `Google_Protobuf_Value` elements.
///
/// - Parameter values: The list of `Google_Protobuf_Value` messages from
/// which to create the `Google_Protobuf_ListValue`.
public init(values: [Google_Protobuf_Value]) {
self.init()
self.values = values
}
/// Accesses the `Google_Protobuf_Value` at the specified position.
///
/// - Parameter index: The position of the element to access.
public subscript(index: Int) -> Google_Protobuf_Value {
get {return values[index]}
set(newValue) {values[index] = newValue}
}
}

View File

@ -0,0 +1,28 @@
// Sources/SwiftProtobuf/Google_Protobuf_NullValue+Extensions.swift - NullValue extensions
//
// Copyright (c) 2014 - 2020 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// NullValue is a well-known message type that can be used to parse or encode
/// JSON Null values.
///
// -----------------------------------------------------------------------------
extension Google_Protobuf_NullValue: _CustomJSONCodable {
internal func encodedJSONString(options: JSONEncodingOptions) throws -> String {
return "null"
}
internal mutating func decodeJSON(from decoder: inout JSONDecoder) throws {
if decoder.scanner.skipOptionalNull() {
return
}
}
static func decodedFromJSONNull() -> Google_Protobuf_NullValue? {
return .nullValue
}
}

View File

@ -0,0 +1,85 @@
// Sources/SwiftProtobuf/Google_Protobuf_Struct+Extensions.swift - Struct extensions
//
// Copyright (c) 2014 - 2017 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Struct is a well-known message type that can be used to parse or encode
/// arbitrary JSON objects without a predefined schema.
///
// -----------------------------------------------------------------------------
extension Google_Protobuf_Struct: ExpressibleByDictionaryLiteral {
public typealias Key = String
public typealias Value = Google_Protobuf_Value
/// Creates a new `Google_Protobuf_Struct` from a dictionary of string keys to
/// values of type `Google_Protobuf_Value`.
public init(dictionaryLiteral: (String, Google_Protobuf_Value)...) {
self.init()
for (k,v) in dictionaryLiteral {
fields[k] = v
}
}
}
extension Google_Protobuf_Struct: _CustomJSONCodable {
internal func encodedJSONString(options: JSONEncodingOptions) throws -> String {
var jsonEncoder = JSONEncoder()
jsonEncoder.startObject()
var mapVisitor = JSONMapEncodingVisitor(encoder: jsonEncoder, options: options)
for (k,v) in fields {
try mapVisitor.visitSingularStringField(value: k, fieldNumber: 1)
try mapVisitor.visitSingularMessageField(value: v, fieldNumber: 2)
}
mapVisitor.encoder.endObject()
return mapVisitor.encoder.stringResult
}
internal mutating func decodeJSON(from decoder: inout JSONDecoder) throws {
try decoder.scanner.skipRequiredObjectStart()
if decoder.scanner.skipOptionalObjectEnd() {
return
}
while true {
let key = try decoder.scanner.nextQuotedString()
try decoder.scanner.skipRequiredColon()
var value = Google_Protobuf_Value()
try value.decodeJSON(from: &decoder)
fields[key] = value
if decoder.scanner.skipOptionalObjectEnd() {
return
}
try decoder.scanner.skipRequiredComma()
}
}
}
extension Google_Protobuf_Struct {
/// Creates a new `Google_Protobuf_Struct` from a dictionary of string keys to
/// values of type `Google_Protobuf_Value`.
///
/// - Parameter fields: The dictionary from field names to
/// `Google_Protobuf_Value` messages that should be used to create the
/// `Struct`.
public init(fields: [String: Google_Protobuf_Value]) {
self.init()
self.fields = fields
}
/// Accesses the `Google_Protobuf_Value` with the given key for reading and
/// writing.
///
/// This key-based subscript returns the `Value` for the given key if the key
/// is found in the `Struct`, or nil if the key is not found. If you assign
/// nil as the `Value` for the given key, the `Struct` removes that key and
/// its associated `Value`.
public subscript(key: String) -> Google_Protobuf_Value? {
get {return fields[key]}
set(newValue) {fields[key] = newValue}
}
}

View File

@ -0,0 +1,337 @@
// Sources/SwiftProtobuf/Google_Protobuf_Timestamp+Extensions.swift - Timestamp extensions
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Extend the generated Timestamp message with customized JSON coding,
/// arithmetic operations, and convenience methods.
///
// -----------------------------------------------------------------------------
import Foundation
private let minTimestampSeconds: Int64 = -62135596800 // 0001-01-01T00:00:00Z
private let maxTimestampSeconds: Int64 = 253402300799 // 9999-12-31T23:59:59Z
// TODO: Add convenience methods to interoperate with standard
// date/time classes: an initializer that accepts Unix timestamp as
// Int or Double, an easy way to convert to/from Foundation's
// NSDateTime (on Apple platforms only?), others?
// Parse an RFC3339 timestamp into a pair of seconds-since-1970 and nanos.
private func parseTimestamp(s: String) throws -> (Int64, Int32) {
// Convert to an array of integer character values
let value = s.utf8.map{Int($0)}
if value.count < 20 {
throw JSONDecodingError.malformedTimestamp
}
// Since the format is fixed-layout, we can just decode
// directly as follows.
let zero = Int(48)
let nine = Int(57)
let dash = Int(45)
let colon = Int(58)
let plus = Int(43)
let letterT = Int(84)
let letterZ = Int(90)
let period = Int(46)
func fromAscii2(_ digit0: Int, _ digit1: Int) throws -> Int {
if digit0 < zero || digit0 > nine || digit1 < zero || digit1 > nine {
throw JSONDecodingError.malformedTimestamp
}
return digit0 * 10 + digit1 - 528
}
func fromAscii4(
_ digit0: Int,
_ digit1: Int,
_ digit2: Int,
_ digit3: Int
) throws -> Int {
if (digit0 < zero || digit0 > nine
|| digit1 < zero || digit1 > nine
|| digit2 < zero || digit2 > nine
|| digit3 < zero || digit3 > nine) {
throw JSONDecodingError.malformedTimestamp
}
return digit0 * 1000 + digit1 * 100 + digit2 * 10 + digit3 - 53328
}
// Year: 4 digits followed by '-'
let year = try fromAscii4(value[0], value[1], value[2], value[3])
if value[4] != dash || year < Int(1) || year > Int(9999) {
throw JSONDecodingError.malformedTimestamp
}
// Month: 2 digits followed by '-'
let month = try fromAscii2(value[5], value[6])
if value[7] != dash || month < Int(1) || month > Int(12) {
throw JSONDecodingError.malformedTimestamp
}
// Day: 2 digits followed by 'T'
let mday = try fromAscii2(value[8], value[9])
if value[10] != letterT || mday < Int(1) || mday > Int(31) {
throw JSONDecodingError.malformedTimestamp
}
// Hour: 2 digits followed by ':'
let hour = try fromAscii2(value[11], value[12])
if value[13] != colon || hour > Int(23) {
throw JSONDecodingError.malformedTimestamp
}
// Minute: 2 digits followed by ':'
let minute = try fromAscii2(value[14], value[15])
if value[16] != colon || minute > Int(59) {
throw JSONDecodingError.malformedTimestamp
}
// Second: 2 digits (following char is checked below)
let second = try fromAscii2(value[17], value[18])
if second > Int(61) {
throw JSONDecodingError.malformedTimestamp
}
// timegm() is almost entirely useless. It's nonexistent on
// some platforms, broken on others. Everything else I've tried
// is even worse. Hence the code below.
// (If you have a better way to do this, try it and see if it
// passes the test suite on both Linux and OS X.)
// Day of year
let mdayStart: [Int] = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]
var yday = Int64(mdayStart[month - 1])
let isleap = (year % 400 == 0) || ((year % 100 != 0) && (year % 4 == 0))
if isleap && (month > 2) {
yday += 1
}
yday += Int64(mday - 1)
// Days since start of epoch (including leap days)
var daysSinceEpoch = yday
daysSinceEpoch += Int64(365 * year) - Int64(719527)
daysSinceEpoch += Int64((year - 1) / 4)
daysSinceEpoch -= Int64((year - 1) / 100)
daysSinceEpoch += Int64((year - 1) / 400)
// Second within day
var daySec = Int64(hour)
daySec *= 60
daySec += Int64(minute)
daySec *= 60
daySec += Int64(second)
// Seconds since start of epoch
let t = daysSinceEpoch * Int64(86400) + daySec
// After seconds, comes various optional bits
var pos = 19
var nanos: Int32 = 0
if value[pos] == period { // "." begins fractional seconds
pos += 1
var digitValue = 100000000
while pos < value.count && value[pos] >= zero && value[pos] <= nine {
nanos += Int32(digitValue * (value[pos] - zero))
digitValue /= 10
pos += 1
}
}
var seconds: Int64 = 0
// "+" or "-" starts Timezone offset
if value[pos] == plus || value[pos] == dash {
if pos + 6 > value.count {
throw JSONDecodingError.malformedTimestamp
}
let hourOffset = try fromAscii2(value[pos + 1], value[pos + 2])
let minuteOffset = try fromAscii2(value[pos + 4], value[pos + 5])
if hourOffset > Int(13) || minuteOffset > Int(59) || value[pos + 3] != colon {
throw JSONDecodingError.malformedTimestamp
}
var adjusted: Int64 = t
if value[pos] == plus {
adjusted -= Int64(hourOffset) * Int64(3600)
adjusted -= Int64(minuteOffset) * Int64(60)
} else {
adjusted += Int64(hourOffset) * Int64(3600)
adjusted += Int64(minuteOffset) * Int64(60)
}
if adjusted < minTimestampSeconds || adjusted > maxTimestampSeconds {
throw JSONDecodingError.malformedTimestamp
}
seconds = adjusted
pos += 6
} else if value[pos] == letterZ { // "Z" indicator for UTC
seconds = t
pos += 1
} else {
throw JSONDecodingError.malformedTimestamp
}
if pos != value.count {
throw JSONDecodingError.malformedTimestamp
}
return (seconds, nanos)
}
private func formatTimestamp(seconds: Int64, nanos: Int32) -> String? {
let (seconds, nanos) = normalizeForTimestamp(seconds: seconds, nanos: nanos)
guard seconds >= minTimestampSeconds && seconds <= maxTimestampSeconds else {
return nil
}
let (hh, mm, ss) = timeOfDayFromSecondsSince1970(seconds: seconds)
let (YY, MM, DD) = gregorianDateFromSecondsSince1970(seconds: seconds)
if nanos == 0 {
return String(format: "%04d-%02d-%02dT%02d:%02d:%02dZ",
YY, MM, DD, hh, mm, ss)
} else if nanos % 1000000 == 0 {
return String(format: "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ",
YY, MM, DD, hh, mm, ss, nanos / 1000000)
} else if nanos % 1000 == 0 {
return String(format: "%04d-%02d-%02dT%02d:%02d:%02d.%06dZ",
YY, MM, DD, hh, mm, ss, nanos / 1000)
} else {
return String(format: "%04d-%02d-%02dT%02d:%02d:%02d.%09dZ",
YY, MM, DD, hh, mm, ss, nanos)
}
}
extension Google_Protobuf_Timestamp {
/// Creates a new `Google_Protobuf_Timestamp` equal to the given number of
/// seconds and nanoseconds.
///
/// - Parameter seconds: The number of seconds.
/// - Parameter nanos: The number of nanoseconds.
public init(seconds: Int64 = 0, nanos: Int32 = 0) {
self.init()
self.seconds = seconds
self.nanos = nanos
}
}
extension Google_Protobuf_Timestamp: _CustomJSONCodable {
mutating func decodeJSON(from decoder: inout JSONDecoder) throws {
let s = try decoder.scanner.nextQuotedString()
(seconds, nanos) = try parseTimestamp(s: s)
}
func encodedJSONString(options: JSONEncodingOptions) throws -> String {
if let formatted = formatTimestamp(seconds: seconds, nanos: nanos) {
return "\"\(formatted)\""
} else {
throw JSONEncodingError.timestampRange
}
}
}
extension Google_Protobuf_Timestamp {
/// Creates a new `Google_Protobuf_Timestamp` initialized relative to 00:00:00
/// UTC on 1 January 1970 by a given number of seconds.
///
/// - Parameter timeIntervalSince1970: The `TimeInterval`, interpreted as
/// seconds relative to 00:00:00 UTC on 1 January 1970.
public init(timeIntervalSince1970: TimeInterval) {
let sd = floor(timeIntervalSince1970)
let nd = round((timeIntervalSince1970 - sd) * TimeInterval(nanosPerSecond))
let (s, n) = normalizeForTimestamp(seconds: Int64(sd), nanos: Int32(nd))
self.init(seconds: s, nanos: n)
}
/// Creates a new `Google_Protobuf_Timestamp` initialized relative to 00:00:00
/// UTC on 1 January 2001 by a given number of seconds.
///
/// - Parameter timeIntervalSinceReferenceDate: The `TimeInterval`,
/// interpreted as seconds relative to 00:00:00 UTC on 1 January 2001.
public init(timeIntervalSinceReferenceDate: TimeInterval) {
let sd = floor(timeIntervalSinceReferenceDate)
let nd = round(
(timeIntervalSinceReferenceDate - sd) * TimeInterval(nanosPerSecond))
// The addition of timeIntervalBetween1970And... is deliberately delayed
// until the input is separated into an integer part and a fraction
// part, so that we don't unnecessarily lose precision.
let (s, n) = normalizeForTimestamp(
seconds: Int64(sd) + Int64(Date.timeIntervalBetween1970AndReferenceDate),
nanos: Int32(nd))
self.init(seconds: s, nanos: n)
}
/// Creates a new `Google_Protobuf_Timestamp` initialized to the same time as
/// the given `Date`.
///
/// - Parameter date: The `Date` with which to initialize the timestamp.
public init(date: Date) {
// Note: Internally, Date uses the "reference date," not the 1970 date.
// We use it when interacting with Dates so that Date doesn't perform
// any double arithmetic on our behalf, which might cost us precision.
self.init(
timeIntervalSinceReferenceDate: date.timeIntervalSinceReferenceDate)
}
/// The interval between the timestamp and 00:00:00 UTC on 1 January 1970.
public var timeIntervalSince1970: TimeInterval {
return TimeInterval(self.seconds) +
TimeInterval(self.nanos) / TimeInterval(nanosPerSecond)
}
/// The interval between the timestamp and 00:00:00 UTC on 1 January 2001.
public var timeIntervalSinceReferenceDate: TimeInterval {
return TimeInterval(
self.seconds - Int64(Date.timeIntervalBetween1970AndReferenceDate)) +
TimeInterval(self.nanos) / TimeInterval(nanosPerSecond)
}
/// A `Date` initialized to the same time as the timestamp.
public var date: Date {
return Date(
timeIntervalSinceReferenceDate: self.timeIntervalSinceReferenceDate)
}
}
private func normalizeForTimestamp(
seconds: Int64,
nanos: Int32
) -> (seconds: Int64, nanos: Int32) {
// The Timestamp spec says that nanos must be in the range [0, 999999999),
// as in actual modular arithmetic.
let s = seconds + Int64(div(nanos, nanosPerSecond))
let n = mod(nanos, nanosPerSecond)
return (seconds: s, nanos: n)
}
public func + (
lhs: Google_Protobuf_Timestamp,
rhs: Google_Protobuf_Duration
) -> Google_Protobuf_Timestamp {
let (s, n) = normalizeForTimestamp(seconds: lhs.seconds + rhs.seconds,
nanos: lhs.nanos + rhs.nanos)
return Google_Protobuf_Timestamp(seconds: s, nanos: n)
}
public func + (
lhs: Google_Protobuf_Duration,
rhs: Google_Protobuf_Timestamp
) -> Google_Protobuf_Timestamp {
let (s, n) = normalizeForTimestamp(seconds: lhs.seconds + rhs.seconds,
nanos: lhs.nanos + rhs.nanos)
return Google_Protobuf_Timestamp(seconds: s, nanos: n)
}
public func - (
lhs: Google_Protobuf_Timestamp,
rhs: Google_Protobuf_Duration
) -> Google_Protobuf_Timestamp {
let (s, n) = normalizeForTimestamp(seconds: lhs.seconds - rhs.seconds,
nanos: lhs.nanos - rhs.nanos)
return Google_Protobuf_Timestamp(seconds: s, nanos: n)
}

View File

@ -0,0 +1,163 @@
// Sources/SwiftProtobuf/Google_Protobuf_Value+Extensions.swift - Value extensions
//
// Copyright (c) 2014 - 2017 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Value is a well-known message type that can be used to parse or encode
/// arbitrary JSON without a predefined schema.
///
// -----------------------------------------------------------------------------
extension Google_Protobuf_Value: ExpressibleByIntegerLiteral {
public typealias IntegerLiteralType = Int64
/// Creates a new `Google_Protobuf_Value` from an integer literal.
public init(integerLiteral value: Int64) {
self.init(kind: .numberValue(Double(value)))
}
}
extension Google_Protobuf_Value: ExpressibleByFloatLiteral {
public typealias FloatLiteralType = Double
/// Creates a new `Google_Protobuf_Value` from a floating point literal.
public init(floatLiteral value: Double) {
self.init(kind: .numberValue(value))
}
}
extension Google_Protobuf_Value: ExpressibleByBooleanLiteral {
public typealias BooleanLiteralType = Bool
/// Creates a new `Google_Protobuf_Value` from a boolean literal.
public init(booleanLiteral value: Bool) {
self.init(kind: .boolValue(value))
}
}
extension Google_Protobuf_Value: ExpressibleByStringLiteral {
public typealias StringLiteralType = String
public typealias ExtendedGraphemeClusterLiteralType = String
public typealias UnicodeScalarLiteralType = String
/// Creates a new `Google_Protobuf_Value` from a string literal.
public init(stringLiteral value: String) {
self.init(kind: .stringValue(value))
}
/// Creates a new `Google_Protobuf_Value` from a Unicode scalar literal.
public init(unicodeScalarLiteral value: String) {
self.init(kind: .stringValue(value))
}
/// Creates a new `Google_Protobuf_Value` from a character literal.
public init(extendedGraphemeClusterLiteral value: String) {
self.init(kind: .stringValue(value))
}
}
extension Google_Protobuf_Value: ExpressibleByNilLiteral {
/// Creates a new `Google_Protobuf_Value` from the nil literal.
public init(nilLiteral: ()) {
self.init(kind: .nullValue(.nullValue))
}
}
extension Google_Protobuf_Value: _CustomJSONCodable {
internal func encodedJSONString(options: JSONEncodingOptions) throws -> String {
var jsonEncoder = JSONEncoder()
try serializeJSONValue(to: &jsonEncoder, options: options)
return jsonEncoder.stringResult
}
internal mutating func decodeJSON(from decoder: inout JSONDecoder) throws {
let c = try decoder.scanner.peekOneCharacter()
switch c {
case "n":
if !decoder.scanner.skipOptionalNull() {
throw JSONDecodingError.failure
}
kind = .nullValue(.nullValue)
case "[":
var l = Google_Protobuf_ListValue()
try l.decodeJSON(from: &decoder)
kind = .listValue(l)
case "{":
var s = Google_Protobuf_Struct()
try s.decodeJSON(from: &decoder)
kind = .structValue(s)
case "t", "f":
let b = try decoder.scanner.nextBool()
kind = .boolValue(b)
case "\"":
let s = try decoder.scanner.nextQuotedString()
kind = .stringValue(s)
default:
let d = try decoder.scanner.nextDouble()
kind = .numberValue(d)
}
}
internal static func decodedFromJSONNull() -> Google_Protobuf_Value? {
return Google_Protobuf_Value(kind: .nullValue(.nullValue))
}
}
extension Google_Protobuf_Value {
/// Creates a new `Google_Protobuf_Value` with the given kind.
fileprivate init(kind: OneOf_Kind) {
self.init()
self.kind = kind
}
/// Creates a new `Google_Protobuf_Value` whose `kind` is `numberValue` with
/// the given floating-point value.
public init(numberValue: Double) {
self.init(kind: .numberValue(numberValue))
}
/// Creates a new `Google_Protobuf_Value` whose `kind` is `stringValue` with
/// the given string value.
public init(stringValue: String) {
self.init(kind: .stringValue(stringValue))
}
/// Creates a new `Google_Protobuf_Value` whose `kind` is `boolValue` with the
/// given boolean value.
public init(boolValue: Bool) {
self.init(kind: .boolValue(boolValue))
}
/// Creates a new `Google_Protobuf_Value` whose `kind` is `structValue` with
/// the given `Google_Protobuf_Struct` value.
public init(structValue: Google_Protobuf_Struct) {
self.init(kind: .structValue(structValue))
}
/// Creates a new `Google_Protobuf_Value` whose `kind` is `listValue` with the
/// given `Google_Struct_ListValue` value.
public init(listValue: Google_Protobuf_ListValue) {
self.init(kind: .listValue(listValue))
}
/// Writes out the JSON representation of the value to the given encoder.
internal func serializeJSONValue(
to encoder: inout JSONEncoder,
options: JSONEncodingOptions
) throws {
switch kind {
case .nullValue?: encoder.putNullValue()
case .numberValue(let v)?: encoder.putDoubleValue(value: v)
case .stringValue(let v)?: encoder.putStringValue(value: v)
case .boolValue(let v)?: encoder.putBoolValue(value: v)
case .structValue(let v)?: encoder.append(text: try v.jsonString(options: options))
case .listValue(let v)?: encoder.append(text: try v.jsonString(options: options))
case nil: throw JSONEncodingError.missingValue
}
}
}

View File

@ -0,0 +1,247 @@
// Sources/SwiftProtobuf/Google_Protobuf_Wrappers+Extensions.swift - Well-known wrapper type extensions
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Extensions to the well-known types in wrapper.proto that customize the JSON
/// format of those messages and provide convenience initializers from literals.
///
// -----------------------------------------------------------------------------
import Foundation
/// Internal protocol that minimizes the code duplication across the multiple
/// wrapper types extended below.
protocol ProtobufWrapper {
/// The wrapped protobuf type (for example, `ProtobufDouble`).
associatedtype WrappedType: FieldType
/// Exposes the generated property to the extensions here.
var value: WrappedType.BaseType { get set }
/// Exposes the parameterless initializer to the extensions here.
init()
/// Creates a new instance of the wrapper with the given value.
init(_ value: WrappedType.BaseType)
}
extension ProtobufWrapper {
mutating func decodeJSON(from decoder: inout JSONDecoder) throws {
var v: WrappedType.BaseType?
try WrappedType.decodeSingular(value: &v, from: &decoder)
value = v ?? WrappedType.proto3DefaultValue
}
}
extension Google_Protobuf_DoubleValue:
ProtobufWrapper, ExpressibleByFloatLiteral, _CustomJSONCodable {
public typealias WrappedType = ProtobufDouble
public typealias FloatLiteralType = WrappedType.BaseType
public init(_ value: WrappedType.BaseType) {
self.init()
self.value = value
}
public init(floatLiteral: FloatLiteralType) {
self.init(floatLiteral)
}
func encodedJSONString(options: JSONEncodingOptions) throws -> String {
if value.isFinite {
// Swift 4.2 and later guarantees that this is accurate
// enough to parse back to the exact value on the other end.
return value.description
} else {
// Protobuf-specific handling of NaN and infinities
var encoder = JSONEncoder()
encoder.putDoubleValue(value: value)
return encoder.stringResult
}
}
}
extension Google_Protobuf_FloatValue:
ProtobufWrapper, ExpressibleByFloatLiteral, _CustomJSONCodable {
public typealias WrappedType = ProtobufFloat
public typealias FloatLiteralType = Float
public init(_ value: WrappedType.BaseType) {
self.init()
self.value = value
}
public init(floatLiteral: FloatLiteralType) {
self.init(floatLiteral)
}
func encodedJSONString(options: JSONEncodingOptions) throws -> String {
if value.isFinite {
// Swift 4.2 and later guarantees that this is accurate
// enough to parse back to the exact value on the other end.
return value.description
} else {
// Protobuf-specific handling of NaN and infinities
var encoder = JSONEncoder()
encoder.putFloatValue(value: value)
return encoder.stringResult
}
}
}
extension Google_Protobuf_Int64Value:
ProtobufWrapper, ExpressibleByIntegerLiteral, _CustomJSONCodable {
public typealias WrappedType = ProtobufInt64
public typealias IntegerLiteralType = WrappedType.BaseType
public init(_ value: WrappedType.BaseType) {
self.init()
self.value = value
}
public init(integerLiteral: IntegerLiteralType) {
self.init(integerLiteral)
}
func encodedJSONString(options: JSONEncodingOptions) throws -> String {
return "\"" + String(value) + "\""
}
}
extension Google_Protobuf_UInt64Value:
ProtobufWrapper, ExpressibleByIntegerLiteral, _CustomJSONCodable {
public typealias WrappedType = ProtobufUInt64
public typealias IntegerLiteralType = WrappedType.BaseType
public init(_ value: WrappedType.BaseType) {
self.init()
self.value = value
}
public init(integerLiteral: IntegerLiteralType) {
self.init(integerLiteral)
}
func encodedJSONString(options: JSONEncodingOptions) throws -> String {
return "\"" + String(value) + "\""
}
}
extension Google_Protobuf_Int32Value:
ProtobufWrapper, ExpressibleByIntegerLiteral, _CustomJSONCodable {
public typealias WrappedType = ProtobufInt32
public typealias IntegerLiteralType = WrappedType.BaseType
public init(_ value: WrappedType.BaseType) {
self.init()
self.value = value
}
public init(integerLiteral: IntegerLiteralType) {
self.init(integerLiteral)
}
func encodedJSONString(options: JSONEncodingOptions) throws -> String {
return String(value)
}
}
extension Google_Protobuf_UInt32Value:
ProtobufWrapper, ExpressibleByIntegerLiteral, _CustomJSONCodable {
public typealias WrappedType = ProtobufUInt32
public typealias IntegerLiteralType = WrappedType.BaseType
public init(_ value: WrappedType.BaseType) {
self.init()
self.value = value
}
public init(integerLiteral: IntegerLiteralType) {
self.init(integerLiteral)
}
func encodedJSONString(options: JSONEncodingOptions) throws -> String {
return String(value)
}
}
extension Google_Protobuf_BoolValue:
ProtobufWrapper, ExpressibleByBooleanLiteral, _CustomJSONCodable {
public typealias WrappedType = ProtobufBool
public typealias BooleanLiteralType = Bool
public init(_ value: WrappedType.BaseType) {
self.init()
self.value = value
}
public init(booleanLiteral: Bool) {
self.init(booleanLiteral)
}
func encodedJSONString(options: JSONEncodingOptions) throws -> String {
return value ? "true" : "false"
}
}
extension Google_Protobuf_StringValue:
ProtobufWrapper, ExpressibleByStringLiteral, _CustomJSONCodable {
public typealias WrappedType = ProtobufString
public typealias StringLiteralType = String
public typealias ExtendedGraphemeClusterLiteralType = String
public typealias UnicodeScalarLiteralType = String
public init(_ value: WrappedType.BaseType) {
self.init()
self.value = value
}
public init(stringLiteral: String) {
self.init(stringLiteral)
}
public init(extendedGraphemeClusterLiteral: String) {
self.init(extendedGraphemeClusterLiteral)
}
public init(unicodeScalarLiteral: String) {
self.init(unicodeScalarLiteral)
}
func encodedJSONString(options: JSONEncodingOptions) throws -> String {
var encoder = JSONEncoder()
encoder.putStringValue(value: value)
return encoder.stringResult
}
}
extension Google_Protobuf_BytesValue: ProtobufWrapper, _CustomJSONCodable {
public typealias WrappedType = ProtobufBytes
public init(_ value: WrappedType.BaseType) {
self.init()
self.value = value
}
func encodedJSONString(options: JSONEncodingOptions) throws -> String {
var encoder = JSONEncoder()
encoder.putBytesValue(value: value)
return encoder.stringResult
}
}

View File

@ -0,0 +1,426 @@
// Sources/SwiftProtobuf/HashVisitor.swift - Hashing support
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Hashing is basically a serialization problem, so we can leverage the
/// generated traversal methods for that.
///
// -----------------------------------------------------------------------------
import Foundation
private let i_2166136261 = Int(bitPattern: 2166136261)
private let i_16777619 = Int(16777619)
/// Computes the hash of a message by visiting its fields recursively.
///
/// Note that because this visits every field, it has the potential to be slow
/// for large or deeply nested messages. Users who need to use such messages as
/// dictionary keys or set members can use a wrapper struct around the message
/// and use a custom Hashable implementation that looks at the subset of the
/// message fields they want to include.
internal struct HashVisitor: Visitor {
#if swift(>=4.2)
internal private(set) var hasher: Hasher
#else // swift(>=4.2)
// Roughly based on FNV hash: http://tools.ietf.org/html/draft-eastlake-fnv-03
private(set) var hashValue = i_2166136261
private mutating func mix(_ hash: Int) {
hashValue = (hashValue ^ hash) &* i_16777619
}
private mutating func mixMap<K, V: Hashable>(map: Dictionary<K,V>) {
var mapHash = 0
for (k, v) in map {
// Note: This calculation cannot depend on the order of the items.
mapHash = mapHash &+ (k.hashValue ^ v.hashValue)
}
mix(mapHash)
}
#endif // swift(>=4.2)
#if swift(>=4.2)
init(_ hasher: Hasher) {
self.hasher = hasher
}
#else
init() {}
#endif
mutating func visitUnknown(bytes: Data) throws {
#if swift(>=4.2)
hasher.combine(bytes)
#else
mix(bytes.hashValue)
#endif
}
mutating func visitSingularDoubleField(value: Double, fieldNumber: Int) throws {
#if swift(>=4.2)
hasher.combine(fieldNumber)
hasher.combine(value)
#else
mix(fieldNumber)
mix(value.hashValue)
#endif
}
mutating func visitSingularInt64Field(value: Int64, fieldNumber: Int) throws {
#if swift(>=4.2)
hasher.combine(fieldNumber)
hasher.combine(value)
#else
mix(fieldNumber)
mix(value.hashValue)
#endif
}
mutating func visitSingularUInt64Field(value: UInt64, fieldNumber: Int) throws {
#if swift(>=4.2)
hasher.combine(fieldNumber)
hasher.combine(value)
#else
mix(fieldNumber)
mix(value.hashValue)
#endif
}
mutating func visitSingularBoolField(value: Bool, fieldNumber: Int) throws {
#if swift(>=4.2)
hasher.combine(fieldNumber)
hasher.combine(value)
#else
mix(fieldNumber)
mix(value.hashValue)
#endif
}
mutating func visitSingularStringField(value: String, fieldNumber: Int) throws {
#if swift(>=4.2)
hasher.combine(fieldNumber)
hasher.combine(value)
#else
mix(fieldNumber)
mix(value.hashValue)
#endif
}
mutating func visitSingularBytesField(value: Data, fieldNumber: Int) throws {
#if swift(>=4.2)
hasher.combine(fieldNumber)
hasher.combine(value)
#else
mix(fieldNumber)
mix(value.hashValue)
#endif
}
mutating func visitSingularEnumField<E: Enum>(value: E,
fieldNumber: Int) {
#if swift(>=4.2)
hasher.combine(fieldNumber)
hasher.combine(value)
#else
mix(fieldNumber)
mix(value.hashValue)
#endif
}
mutating func visitSingularMessageField<M: Message>(value: M, fieldNumber: Int) {
#if swift(>=4.2)
hasher.combine(fieldNumber)
value.hash(into: &hasher)
#else
mix(fieldNumber)
mix(value.hashValue)
#endif
}
mutating func visitRepeatedFloatField(value: [Float], fieldNumber: Int) throws {
assert(!value.isEmpty)
#if swift(>=4.2)
hasher.combine(fieldNumber)
hasher.combine(value)
#else
mix(fieldNumber)
for v in value {
mix(v.hashValue)
}
#endif
}
mutating func visitRepeatedDoubleField(value: [Double], fieldNumber: Int) throws {
assert(!value.isEmpty)
#if swift(>=4.2)
hasher.combine(fieldNumber)
hasher.combine(value)
#else
mix(fieldNumber)
for v in value {
mix(v.hashValue)
}
#endif
}
mutating func visitRepeatedInt32Field(value: [Int32], fieldNumber: Int) throws {
assert(!value.isEmpty)
#if swift(>=4.2)
hasher.combine(fieldNumber)
hasher.combine(value)
#else
mix(fieldNumber)
for v in value {
mix(v.hashValue)
}
#endif
}
mutating func visitRepeatedInt64Field(value: [Int64], fieldNumber: Int) throws {
assert(!value.isEmpty)
#if swift(>=4.2)
hasher.combine(fieldNumber)
hasher.combine(value)
#else
mix(fieldNumber)
for v in value {
mix(v.hashValue)
}
#endif
}
mutating func visitRepeatedUInt32Field(value: [UInt32], fieldNumber: Int) throws {
assert(!value.isEmpty)
#if swift(>=4.2)
hasher.combine(fieldNumber)
hasher.combine(value)
#else
mix(fieldNumber)
for v in value {
mix(v.hashValue)
}
#endif
}
mutating func visitRepeatedUInt64Field(value: [UInt64], fieldNumber: Int) throws {
assert(!value.isEmpty)
#if swift(>=4.2)
hasher.combine(fieldNumber)
hasher.combine(value)
#else
mix(fieldNumber)
for v in value {
mix(v.hashValue)
}
#endif
}
mutating func visitRepeatedSInt32Field(value: [Int32], fieldNumber: Int) throws {
assert(!value.isEmpty)
#if swift(>=4.2)
hasher.combine(fieldNumber)
hasher.combine(value)
#else
mix(fieldNumber)
for v in value {
mix(v.hashValue)
}
#endif
}
mutating func visitRepeatedSInt64Field(value: [Int64], fieldNumber: Int) throws {
assert(!value.isEmpty)
#if swift(>=4.2)
hasher.combine(fieldNumber)
hasher.combine(value)
#else
mix(fieldNumber)
for v in value {
mix(v.hashValue)
}
#endif
}
mutating func visitRepeatedFixed32Field(value: [UInt32], fieldNumber: Int) throws {
assert(!value.isEmpty)
#if swift(>=4.2)
hasher.combine(fieldNumber)
hasher.combine(value)
#else
mix(fieldNumber)
for v in value {
mix(v.hashValue)
}
#endif
}
mutating func visitRepeatedFixed64Field(value: [UInt64], fieldNumber: Int) throws {
assert(!value.isEmpty)
#if swift(>=4.2)
hasher.combine(fieldNumber)
hasher.combine(value)
#else
mix(fieldNumber)
for v in value {
mix(v.hashValue)
}
#endif
}
mutating func visitRepeatedSFixed32Field(value: [Int32], fieldNumber: Int) throws {
assert(!value.isEmpty)
#if swift(>=4.2)
hasher.combine(fieldNumber)
hasher.combine(value)
#else
mix(fieldNumber)
for v in value {
mix(v.hashValue)
}
#endif
}
mutating func visitRepeatedSFixed64Field(value: [Int64], fieldNumber: Int) throws {
assert(!value.isEmpty)
#if swift(>=4.2)
hasher.combine(fieldNumber)
hasher.combine(value)
#else
mix(fieldNumber)
for v in value {
mix(v.hashValue)
}
#endif
}
mutating func visitRepeatedBoolField(value: [Bool], fieldNumber: Int) throws {
assert(!value.isEmpty)
#if swift(>=4.2)
hasher.combine(fieldNumber)
hasher.combine(value)
#else
mix(fieldNumber)
for v in value {
mix(v.hashValue)
}
#endif
}
mutating func visitRepeatedStringField(value: [String], fieldNumber: Int) throws {
assert(!value.isEmpty)
#if swift(>=4.2)
hasher.combine(fieldNumber)
hasher.combine(value)
#else
mix(fieldNumber)
for v in value {
mix(v.hashValue)
}
#endif
}
mutating func visitRepeatedBytesField(value: [Data], fieldNumber: Int) throws {
assert(!value.isEmpty)
#if swift(>=4.2)
hasher.combine(fieldNumber)
hasher.combine(value)
#else
mix(fieldNumber)
for v in value {
mix(v.hashValue)
}
#endif
}
mutating func visitRepeatedEnumField<E: Enum>(value: [E], fieldNumber: Int) throws {
assert(!value.isEmpty)
#if swift(>=4.2)
hasher.combine(fieldNumber)
hasher.combine(value)
#else
mix(fieldNumber)
for v in value {
mix(v.hashValue)
}
#endif
}
mutating func visitRepeatedMessageField<M: Message>(value: [M], fieldNumber: Int) throws {
assert(!value.isEmpty)
#if swift(>=4.2)
hasher.combine(fieldNumber)
for v in value {
v.hash(into: &hasher)
}
#else
mix(fieldNumber)
for v in value {
mix(v.hashValue)
}
#endif
}
mutating func visitRepeatedGroupField<G: Message>(value: [G], fieldNumber: Int) throws {
assert(!value.isEmpty)
#if swift(>=4.2)
hasher.combine(fieldNumber)
for v in value {
v.hash(into: &hasher)
}
#else
mix(fieldNumber)
for v in value {
mix(v.hashValue)
}
#endif
}
mutating func visitMapField<KeyType, ValueType: MapValueType>(
fieldType: _ProtobufMap<KeyType, ValueType>.Type,
value: _ProtobufMap<KeyType, ValueType>.BaseType,
fieldNumber: Int
) throws {
#if swift(>=4.2)
hasher.combine(fieldNumber)
hasher.combine(value)
#else
mix(fieldNumber)
mixMap(map: value)
#endif
}
mutating func visitMapField<KeyType, ValueType>(
fieldType: _ProtobufEnumMap<KeyType, ValueType>.Type,
value: _ProtobufEnumMap<KeyType, ValueType>.BaseType,
fieldNumber: Int
) throws where ValueType.RawValue == Int {
#if swift(>=4.2)
hasher.combine(fieldNumber)
hasher.combine(value)
#else
mix(fieldNumber)
mixMap(map: value)
#endif
}
mutating func visitMapField<KeyType, ValueType>(
fieldType: _ProtobufMessageMap<KeyType, ValueType>.Type,
value: _ProtobufMessageMap<KeyType, ValueType>.BaseType,
fieldNumber: Int
) throws {
#if swift(>=4.2)
hasher.combine(fieldNumber)
hasher.combine(value)
#else
mix(fieldNumber)
mixMap(map: value)
#endif
}
}

View File

@ -0,0 +1,51 @@
// Sources/SwiftProtobuf/Internal.swift - Message support
//
// Copyright (c) 2014 - 2017 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Internal helpers on Messages for the library. These are public
/// just so the generated code can call them, but shouldn't be called
/// by developers directly.
///
// -----------------------------------------------------------------------------
import Foundation
/// Functions that are public only because they are used by generated message
/// implementations. NOT INTENDED TO BE CALLED BY CLIENTS.
public enum Internal {
/// A singleton instance of an empty data that is used by the generated code
/// for default values. This is a performance enhancement to work around the
/// fact that the `Data` type in Swift involves a new heap allocation every
/// time an empty instance is initialized, instead of sharing a common empty
/// backing storage.
public static let emptyData = Data()
/// Helper to loop over a list of Messages to see if they are all
/// initialized (see Message.isInitialized for what that means).
public static func areAllInitialized(_ listOfMessages: [Message]) -> Bool {
for msg in listOfMessages {
if !msg.isInitialized {
return false
}
}
return true
}
/// Helper to loop over dictionary with values that are Messages to see if
/// they are all initialized (see Message.isInitialized for what that means).
public static func areAllInitialized<K>(_ mapToMessages: [K: Message]) -> Bool {
for (_, msg) in mapToMessages {
if !msg.isInitialized {
return false
}
}
return true
}
}

View File

@ -0,0 +1,735 @@
// Sources/SwiftProtobuf/JSONDecoder.swift - JSON format decoding
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// JSON format decoding engine.
///
// -----------------------------------------------------------------------------
import Foundation
internal struct JSONDecoder: Decoder {
internal var scanner: JSONScanner
internal var messageType: Message.Type
private var fieldCount = 0
private var isMapKey = false
private var fieldNameMap: _NameMap?
internal var options: JSONDecodingOptions {
return scanner.options
}
mutating func handleConflictingOneOf() throws {
throw JSONDecodingError.conflictingOneOf
}
internal init(source: UnsafeRawBufferPointer, options: JSONDecodingOptions,
messageType: Message.Type, extensions: ExtensionMap?) {
let scanner = JSONScanner(source: source,
options: options,
extensions: extensions)
self.init(scanner: scanner, messageType: messageType)
}
private init(scanner: JSONScanner, messageType: Message.Type) {
self.scanner = scanner
self.messageType = messageType
}
mutating func nextFieldNumber() throws -> Int? {
if scanner.skipOptionalObjectEnd() {
return nil
}
if fieldCount > 0 {
try scanner.skipRequiredComma()
}
let fieldNumber = try scanner.nextFieldNumber(names: fieldNameMap!,
messageType: messageType)
if let fieldNumber = fieldNumber {
fieldCount += 1
return fieldNumber
}
return nil
}
mutating func decodeSingularFloatField(value: inout Float) throws {
if scanner.skipOptionalNull() {
value = 0
return
}
value = try scanner.nextFloat()
}
mutating func decodeSingularFloatField(value: inout Float?) throws {
if scanner.skipOptionalNull() {
value = nil
return
}
value = try scanner.nextFloat()
}
mutating func decodeRepeatedFloatField(value: inout [Float]) throws {
if scanner.skipOptionalNull() {
return
}
try scanner.skipRequiredArrayStart()
if scanner.skipOptionalArrayEnd() {
return
}
while true {
let n = try scanner.nextFloat()
value.append(n)
if scanner.skipOptionalArrayEnd() {
return
}
try scanner.skipRequiredComma()
}
}
mutating func decodeSingularDoubleField(value: inout Double) throws {
if scanner.skipOptionalNull() {
value = 0
return
}
value = try scanner.nextDouble()
}
mutating func decodeSingularDoubleField(value: inout Double?) throws {
if scanner.skipOptionalNull() {
value = nil
return
}
value = try scanner.nextDouble()
}
mutating func decodeRepeatedDoubleField(value: inout [Double]) throws {
if scanner.skipOptionalNull() {
return
}
try scanner.skipRequiredArrayStart()
if scanner.skipOptionalArrayEnd() {
return
}
while true {
let n = try scanner.nextDouble()
value.append(n)
if scanner.skipOptionalArrayEnd() {
return
}
try scanner.skipRequiredComma()
}
}
mutating func decodeSingularInt32Field(value: inout Int32) throws {
if scanner.skipOptionalNull() {
value = 0
return
}
let n = try scanner.nextSInt()
if n > Int64(Int32.max) || n < Int64(Int32.min) {
throw JSONDecodingError.numberRange
}
value = Int32(truncatingIfNeeded: n)
}
mutating func decodeSingularInt32Field(value: inout Int32?) throws {
if scanner.skipOptionalNull() {
value = nil
return
}
let n = try scanner.nextSInt()
if n > Int64(Int32.max) || n < Int64(Int32.min) {
throw JSONDecodingError.numberRange
}
value = Int32(truncatingIfNeeded: n)
}
mutating func decodeRepeatedInt32Field(value: inout [Int32]) throws {
if scanner.skipOptionalNull() {
return
}
try scanner.skipRequiredArrayStart()
if scanner.skipOptionalArrayEnd() {
return
}
while true {
let n = try scanner.nextSInt()
if n > Int64(Int32.max) || n < Int64(Int32.min) {
throw JSONDecodingError.numberRange
}
value.append(Int32(truncatingIfNeeded: n))
if scanner.skipOptionalArrayEnd() {
return
}
try scanner.skipRequiredComma()
}
}
mutating func decodeSingularInt64Field(value: inout Int64) throws {
if scanner.skipOptionalNull() {
value = 0
return
}
value = try scanner.nextSInt()
}
mutating func decodeSingularInt64Field(value: inout Int64?) throws {
if scanner.skipOptionalNull() {
value = nil
return
}
value = try scanner.nextSInt()
}
mutating func decodeRepeatedInt64Field(value: inout [Int64]) throws {
if scanner.skipOptionalNull() {
return
}
try scanner.skipRequiredArrayStart()
if scanner.skipOptionalArrayEnd() {
return
}
while true {
let n = try scanner.nextSInt()
value.append(n)
if scanner.skipOptionalArrayEnd() {
return
}
try scanner.skipRequiredComma()
}
}
mutating func decodeSingularUInt32Field(value: inout UInt32) throws {
if scanner.skipOptionalNull() {
value = 0
return
}
let n = try scanner.nextUInt()
if n > UInt64(UInt32.max) {
throw JSONDecodingError.numberRange
}
value = UInt32(truncatingIfNeeded: n)
}
mutating func decodeSingularUInt32Field(value: inout UInt32?) throws {
if scanner.skipOptionalNull() {
value = nil
return
}
let n = try scanner.nextUInt()
if n > UInt64(UInt32.max) {
throw JSONDecodingError.numberRange
}
value = UInt32(truncatingIfNeeded: n)
}
mutating func decodeRepeatedUInt32Field(value: inout [UInt32]) throws {
if scanner.skipOptionalNull() {
return
}
try scanner.skipRequiredArrayStart()
if scanner.skipOptionalArrayEnd() {
return
}
while true {
let n = try scanner.nextUInt()
if n > UInt64(UInt32.max) {
throw JSONDecodingError.numberRange
}
value.append(UInt32(truncatingIfNeeded: n))
if scanner.skipOptionalArrayEnd() {
return
}
try scanner.skipRequiredComma()
}
}
mutating func decodeSingularUInt64Field(value: inout UInt64) throws {
if scanner.skipOptionalNull() {
value = 0
return
}
value = try scanner.nextUInt()
}
mutating func decodeSingularUInt64Field(value: inout UInt64?) throws {
if scanner.skipOptionalNull() {
value = nil
return
}
value = try scanner.nextUInt()
}
mutating func decodeRepeatedUInt64Field(value: inout [UInt64]) throws {
if scanner.skipOptionalNull() {
return
}
try scanner.skipRequiredArrayStart()
if scanner.skipOptionalArrayEnd() {
return
}
while true {
let n = try scanner.nextUInt()
value.append(n)
if scanner.skipOptionalArrayEnd() {
return
}
try scanner.skipRequiredComma()
}
}
mutating func decodeSingularSInt32Field(value: inout Int32) throws {
try decodeSingularInt32Field(value: &value)
}
mutating func decodeSingularSInt32Field(value: inout Int32?) throws {
try decodeSingularInt32Field(value: &value)
}
mutating func decodeRepeatedSInt32Field(value: inout [Int32]) throws {
try decodeRepeatedInt32Field(value: &value)
}
mutating func decodeSingularSInt64Field(value: inout Int64) throws {
try decodeSingularInt64Field(value: &value)
}
mutating func decodeSingularSInt64Field(value: inout Int64?) throws {
try decodeSingularInt64Field(value: &value)
}
mutating func decodeRepeatedSInt64Field(value: inout [Int64]) throws {
try decodeRepeatedInt64Field(value: &value)
}
mutating func decodeSingularFixed32Field(value: inout UInt32) throws {
try decodeSingularUInt32Field(value: &value)
}
mutating func decodeSingularFixed32Field(value: inout UInt32?) throws {
try decodeSingularUInt32Field(value: &value)
}
mutating func decodeRepeatedFixed32Field(value: inout [UInt32]) throws {
try decodeRepeatedUInt32Field(value: &value)
}
mutating func decodeSingularFixed64Field(value: inout UInt64) throws {
try decodeSingularUInt64Field(value: &value)
}
mutating func decodeSingularFixed64Field(value: inout UInt64?) throws {
try decodeSingularUInt64Field(value: &value)
}
mutating func decodeRepeatedFixed64Field(value: inout [UInt64]) throws {
try decodeRepeatedUInt64Field(value: &value)
}
mutating func decodeSingularSFixed32Field(value: inout Int32) throws {
try decodeSingularInt32Field(value: &value)
}
mutating func decodeSingularSFixed32Field(value: inout Int32?) throws {
try decodeSingularInt32Field(value: &value)
}
mutating func decodeRepeatedSFixed32Field(value: inout [Int32]) throws {
try decodeRepeatedInt32Field(value: &value)
}
mutating func decodeSingularSFixed64Field(value: inout Int64) throws {
try decodeSingularInt64Field(value: &value)
}
mutating func decodeSingularSFixed64Field(value: inout Int64?) throws {
try decodeSingularInt64Field(value: &value)
}
mutating func decodeRepeatedSFixed64Field(value: inout [Int64]) throws {
try decodeRepeatedInt64Field(value: &value)
}
mutating func decodeSingularBoolField(value: inout Bool) throws {
if scanner.skipOptionalNull() {
value = false
return
}
if isMapKey {
value = try scanner.nextQuotedBool()
} else {
value = try scanner.nextBool()
}
}
mutating func decodeSingularBoolField(value: inout Bool?) throws {
if scanner.skipOptionalNull() {
value = nil
return
}
if isMapKey {
value = try scanner.nextQuotedBool()
} else {
value = try scanner.nextBool()
}
}
mutating func decodeRepeatedBoolField(value: inout [Bool]) throws {
if scanner.skipOptionalNull() {
return
}
try scanner.skipRequiredArrayStart()
if scanner.skipOptionalArrayEnd() {
return
}
while true {
let n = try scanner.nextBool()
value.append(n)
if scanner.skipOptionalArrayEnd() {
return
}
try scanner.skipRequiredComma()
}
}
mutating func decodeSingularStringField(value: inout String) throws {
if scanner.skipOptionalNull() {
value = String()
return
}
value = try scanner.nextQuotedString()
}
mutating func decodeSingularStringField(value: inout String?) throws {
if scanner.skipOptionalNull() {
value = nil
return
}
value = try scanner.nextQuotedString()
}
mutating func decodeRepeatedStringField(value: inout [String]) throws {
if scanner.skipOptionalNull() {
return
}
try scanner.skipRequiredArrayStart()
if scanner.skipOptionalArrayEnd() {
return
}
while true {
let n = try scanner.nextQuotedString()
value.append(n)
if scanner.skipOptionalArrayEnd() {
return
}
try scanner.skipRequiredComma()
}
}
mutating func decodeSingularBytesField(value: inout Data) throws {
if scanner.skipOptionalNull() {
value = Data()
return
}
value = try scanner.nextBytesValue()
}
mutating func decodeSingularBytesField(value: inout Data?) throws {
if scanner.skipOptionalNull() {
value = nil
return
}
value = try scanner.nextBytesValue()
}
mutating func decodeRepeatedBytesField(value: inout [Data]) throws {
if scanner.skipOptionalNull() {
return
}
try scanner.skipRequiredArrayStart()
if scanner.skipOptionalArrayEnd() {
return
}
while true {
let n = try scanner.nextBytesValue()
value.append(n)
if scanner.skipOptionalArrayEnd() {
return
}
try scanner.skipRequiredComma()
}
}
mutating func decodeSingularEnumField<E: Enum>(value: inout E?) throws
where E.RawValue == Int {
if scanner.skipOptionalNull() {
if let customDecodable = E.self as? _CustomJSONCodable.Type {
value = try customDecodable.decodedFromJSONNull() as? E
return
}
value = nil
return
}
value = try scanner.nextEnumValue() as E
}
mutating func decodeSingularEnumField<E: Enum>(value: inout E) throws
where E.RawValue == Int {
if scanner.skipOptionalNull() {
if let customDecodable = E.self as? _CustomJSONCodable.Type {
value = try customDecodable.decodedFromJSONNull() as! E
return
}
value = E()
return
}
value = try scanner.nextEnumValue()
}
mutating func decodeRepeatedEnumField<E: Enum>(value: inout [E]) throws
where E.RawValue == Int {
if scanner.skipOptionalNull() {
return
}
try scanner.skipRequiredArrayStart()
if scanner.skipOptionalArrayEnd() {
return
}
let maybeCustomDecodable = E.self as? _CustomJSONCodable.Type
while true {
if scanner.skipOptionalNull() {
if let customDecodable = maybeCustomDecodable {
let e = try customDecodable.decodedFromJSONNull() as! E
value.append(e)
} else {
throw JSONDecodingError.illegalNull
}
} else {
let e: E = try scanner.nextEnumValue()
value.append(e)
}
if scanner.skipOptionalArrayEnd() {
return
}
try scanner.skipRequiredComma()
}
}
internal mutating func decodeFullObject<M: Message>(message: inout M) throws {
guard let nameProviding = (M.self as? _ProtoNameProviding.Type) else {
throw JSONDecodingError.missingFieldNames
}
fieldNameMap = nameProviding._protobuf_nameMap
if let m = message as? _CustomJSONCodable {
var customCodable = m
try customCodable.decodeJSON(from: &self)
message = customCodable as! M
} else {
try scanner.skipRequiredObjectStart()
if scanner.skipOptionalObjectEnd() {
return
}
try message.decodeMessage(decoder: &self)
}
}
mutating func decodeSingularMessageField<M: Message>(value: inout M?) throws {
if scanner.skipOptionalNull() {
if M.self is _CustomJSONCodable.Type {
value =
try (M.self as! _CustomJSONCodable.Type).decodedFromJSONNull() as? M
return
}
// All other message field types treat 'null' as an unset
value = nil
return
}
if value == nil {
value = M()
}
var subDecoder = JSONDecoder(scanner: scanner, messageType: M.self)
try subDecoder.decodeFullObject(message: &value!)
assert(scanner.recursionBudget == subDecoder.scanner.recursionBudget)
scanner = subDecoder.scanner
}
mutating func decodeRepeatedMessageField<M: Message>(
value: inout [M]
) throws {
if scanner.skipOptionalNull() {
return
}
try scanner.skipRequiredArrayStart()
if scanner.skipOptionalArrayEnd() {
return
}
while true {
if scanner.skipOptionalNull() {
var appended = false
if M.self is _CustomJSONCodable.Type {
if let message = try (M.self as! _CustomJSONCodable.Type)
.decodedFromJSONNull() as? M {
value.append(message)
appended = true
}
}
if !appended {
throw JSONDecodingError.illegalNull
}
} else {
var message = M()
var subDecoder = JSONDecoder(scanner: scanner, messageType: M.self)
try subDecoder.decodeFullObject(message: &message)
value.append(message)
assert(scanner.recursionBudget == subDecoder.scanner.recursionBudget)
scanner = subDecoder.scanner
}
if scanner.skipOptionalArrayEnd() {
return
}
try scanner.skipRequiredComma()
}
}
mutating func decodeSingularGroupField<G: Message>(value: inout G?) throws {
throw JSONDecodingError.schemaMismatch
}
mutating func decodeRepeatedGroupField<G: Message>(value: inout [G]) throws {
throw JSONDecodingError.schemaMismatch
}
mutating func decodeMapField<KeyType, ValueType: MapValueType>(
fieldType: _ProtobufMap<KeyType, ValueType>.Type,
value: inout _ProtobufMap<KeyType, ValueType>.BaseType
) throws {
if scanner.skipOptionalNull() {
return
}
try scanner.skipRequiredObjectStart()
if scanner.skipOptionalObjectEnd() {
return
}
while true {
// Next character must be double quote, because
// map keys must always be quoted strings.
let c = try scanner.peekOneCharacter()
if c != "\"" {
throw JSONDecodingError.unquotedMapKey
}
isMapKey = true
var keyField: KeyType.BaseType?
try KeyType.decodeSingular(value: &keyField, from: &self)
isMapKey = false
try scanner.skipRequiredColon()
var valueField: ValueType.BaseType?
try ValueType.decodeSingular(value: &valueField, from: &self)
if let keyField = keyField, let valueField = valueField {
value[keyField] = valueField
} else {
throw JSONDecodingError.malformedMap
}
if scanner.skipOptionalObjectEnd() {
return
}
try scanner.skipRequiredComma()
}
}
mutating func decodeMapField<KeyType, ValueType>(
fieldType: _ProtobufEnumMap<KeyType, ValueType>.Type,
value: inout _ProtobufEnumMap<KeyType, ValueType>.BaseType
) throws where ValueType.RawValue == Int {
if scanner.skipOptionalNull() {
return
}
try scanner.skipRequiredObjectStart()
if scanner.skipOptionalObjectEnd() {
return
}
while true {
// Next character must be double quote, because
// map keys must always be quoted strings.
let c = try scanner.peekOneCharacter()
if c != "\"" {
throw JSONDecodingError.unquotedMapKey
}
isMapKey = true
var keyField: KeyType.BaseType?
try KeyType.decodeSingular(value: &keyField, from: &self)
isMapKey = false
try scanner.skipRequiredColon()
var valueField: ValueType?
try decodeSingularEnumField(value: &valueField)
if let keyField = keyField, let valueField = valueField {
value[keyField] = valueField
} else {
throw JSONDecodingError.malformedMap
}
if scanner.skipOptionalObjectEnd() {
return
}
try scanner.skipRequiredComma()
}
}
mutating func decodeMapField<KeyType, ValueType>(
fieldType: _ProtobufMessageMap<KeyType, ValueType>.Type,
value: inout _ProtobufMessageMap<KeyType, ValueType>.BaseType
) throws {
if scanner.skipOptionalNull() {
return
}
try scanner.skipRequiredObjectStart()
if scanner.skipOptionalObjectEnd() {
return
}
while true {
// Next character must be double quote, because
// map keys must always be quoted strings.
let c = try scanner.peekOneCharacter()
if c != "\"" {
throw JSONDecodingError.unquotedMapKey
}
isMapKey = true
var keyField: KeyType.BaseType?
try KeyType.decodeSingular(value: &keyField, from: &self)
isMapKey = false
try scanner.skipRequiredColon()
var valueField: ValueType?
try decodeSingularMessageField(value: &valueField)
if let keyField = keyField, let valueField = valueField {
value[keyField] = valueField
} else {
throw JSONDecodingError.malformedMap
}
if scanner.skipOptionalObjectEnd() {
return
}
try scanner.skipRequiredComma()
}
}
mutating func decodeExtensionField(
values: inout ExtensionFieldValueSet,
messageType: Message.Type,
fieldNumber: Int
) throws {
// Force-unwrap: we can only get here if the extension exists.
let ext = scanner.extensions[messageType, fieldNumber]!
var fieldValue = values[fieldNumber]
if fieldValue != nil {
try fieldValue!.decodeExtensionField(decoder: &self)
} else {
fieldValue = try ext._protobuf_newField(decoder: &self)
}
values[fieldNumber] = fieldValue!
}
}

View File

@ -0,0 +1,62 @@
// Sources/SwiftProtobuf/JSONDecodingError.swift - JSON decoding errors
//
// Copyright (c) 2014 - 2017 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// JSON decoding errors
///
// -----------------------------------------------------------------------------
public enum JSONDecodingError: Error {
/// Something was wrong
case failure
/// A number could not be parsed
case malformedNumber
/// Numeric value was out of range or was not an integer value when expected
case numberRange
/// A map could not be parsed
case malformedMap
/// A bool could not be parsed
case malformedBool
/// We expected a quoted string, or a quoted string has a malformed backslash sequence
case malformedString
/// We encountered malformed UTF8
case invalidUTF8
/// The message does not have fieldName information
case missingFieldNames
/// The data type does not match the schema description
case schemaMismatch
/// A value (text or numeric) for an enum was not found on the enum
case unrecognizedEnumValue
/// A 'null' token appeared in an illegal location.
/// For example, Protobuf JSON does not allow 'null' tokens to appear
/// in lists.
case illegalNull
/// A map key was not quoted
case unquotedMapKey
/// JSON RFC 7519 does not allow numbers to have extra leading zeros
case leadingZero
/// We hit the end of the JSON string and expected something more...
case truncated
/// A JSON Duration could not be parsed
case malformedDuration
/// A JSON Timestamp could not be parsed
case malformedTimestamp
/// A FieldMask could not be parsed
case malformedFieldMask
/// Extraneous data remained after decoding should have been complete
case trailingGarbage
/// More than one value was specified for the same oneof field
case conflictingOneOf
/// Reached the nesting limit for messages within messages while decoding.
case messageDepthLimit
/// Encountered an unknown field with the given name. When parsing JSON, you
/// can instead instruct the library to ignore this via
/// JSONDecodingOptions.ignoreUnknownFields.
case unknownField(String)
}

View File

@ -0,0 +1,29 @@
// Sources/SwiftProtobuf/JSONDecodingOptions.swift - JSON decoding options
//
// Copyright (c) 2014 - 2017 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// JSON decoding options
///
// -----------------------------------------------------------------------------
/// Options for JSONDecoding.
public struct JSONDecodingOptions {
/// The maximum nesting of message with messages. The default is 100.
///
/// To prevent corrupt or malicious messages from causing stack overflows,
/// this controls how deep messages can be nested within other messages
/// while parsing.
public var messageDepthLimit: Int = 100
/// If unknown fields in the JSON should be ignored. If they aren't
/// ignored, an error will be raised if one is encountered.
public var ignoreUnknownFields: Bool = false
public init() {}
}

View File

@ -0,0 +1,386 @@
// Sources/SwiftProtobuf/JSONEncoder.swift - JSON Encoding support
//
// Copyright (c) 2014 - 2019 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// JSON serialization engine.
///
// -----------------------------------------------------------------------------
import Foundation
private let asciiZero = UInt8(ascii: "0")
private let asciiOne = UInt8(ascii: "1")
private let asciiTwo = UInt8(ascii: "2")
private let asciiThree = UInt8(ascii: "3")
private let asciiFour = UInt8(ascii: "4")
private let asciiFive = UInt8(ascii: "5")
private let asciiSix = UInt8(ascii: "6")
private let asciiSeven = UInt8(ascii: "7")
private let asciiEight = UInt8(ascii: "8")
private let asciiNine = UInt8(ascii: "9")
private let asciiMinus = UInt8(ascii: "-")
private let asciiPlus = UInt8(ascii: "+")
private let asciiEquals = UInt8(ascii: "=")
private let asciiColon = UInt8(ascii: ":")
private let asciiComma = UInt8(ascii: ",")
private let asciiDoubleQuote = UInt8(ascii: "\"")
private let asciiBackslash = UInt8(ascii: "\\")
private let asciiForwardSlash = UInt8(ascii: "/")
private let asciiOpenSquareBracket = UInt8(ascii: "[")
private let asciiCloseSquareBracket = UInt8(ascii: "]")
private let asciiOpenCurlyBracket = UInt8(ascii: "{")
private let asciiCloseCurlyBracket = UInt8(ascii: "}")
private let asciiUpperA = UInt8(ascii: "A")
private let asciiUpperB = UInt8(ascii: "B")
private let asciiUpperC = UInt8(ascii: "C")
private let asciiUpperD = UInt8(ascii: "D")
private let asciiUpperE = UInt8(ascii: "E")
private let asciiUpperF = UInt8(ascii: "F")
private let asciiUpperZ = UInt8(ascii: "Z")
private let asciiLowerA = UInt8(ascii: "a")
private let asciiLowerZ = UInt8(ascii: "z")
private let base64Digits: [UInt8] = {
var digits = [UInt8]()
digits.append(contentsOf: asciiUpperA...asciiUpperZ)
digits.append(contentsOf: asciiLowerA...asciiLowerZ)
digits.append(contentsOf: asciiZero...asciiNine)
digits.append(asciiPlus)
digits.append(asciiForwardSlash)
return digits
}()
private let hexDigits: [UInt8] = {
var digits = [UInt8]()
digits.append(contentsOf: asciiZero...asciiNine)
digits.append(contentsOf: asciiUpperA...asciiUpperF)
return digits
}()
internal struct JSONEncoder {
private var data = [UInt8]()
private var separator: UInt8?
internal init() {}
internal var dataResult: Data { return Data(data) }
internal var stringResult: String {
get {
return String(bytes: data, encoding: String.Encoding.utf8)!
}
}
/// Append a `StaticString` to the JSON text. Because
/// `StaticString` is already UTF8 internally, this is faster
/// than appending a regular `String`.
internal mutating func append(staticText: StaticString) {
let buff = UnsafeBufferPointer(start: staticText.utf8Start, count: staticText.utf8CodeUnitCount)
data.append(contentsOf: buff)
}
/// Append a `_NameMap.Name` to the JSON text surrounded by quotes.
/// As with StaticString above, a `_NameMap.Name` provides pre-converted
/// UTF8 bytes, so this is much faster than appending a regular
/// `String`.
internal mutating func appendQuoted(name: _NameMap.Name) {
data.append(asciiDoubleQuote)
data.append(contentsOf: name.utf8Buffer)
data.append(asciiDoubleQuote)
}
/// Append a `String` to the JSON text.
internal mutating func append(text: String) {
data.append(contentsOf: text.utf8)
}
/// Append a raw utf8 in a `Data` to the JSON text.
internal mutating func append(utf8Data: Data) {
data.append(contentsOf: utf8Data)
}
/// Begin a new field whose name is given as a `_NameMap.Name`
internal mutating func startField(name: _NameMap.Name) {
if let s = separator {
data.append(s)
}
appendQuoted(name: name)
data.append(asciiColon)
separator = asciiComma
}
/// Begin a new field whose name is given as a `String`.
internal mutating func startField(name: String) {
if let s = separator {
data.append(s)
}
data.append(asciiDoubleQuote)
// Can avoid overhead of putStringValue, since
// the JSON field names are always clean ASCII.
data.append(contentsOf: name.utf8)
append(staticText: "\":")
separator = asciiComma
}
/// Begin a new extension field
internal mutating func startExtensionField(name: String) {
if let s = separator {
data.append(s)
}
append(staticText: "\"[")
data.append(contentsOf: name.utf8)
append(staticText: "]\":")
separator = asciiComma
}
/// Append an open square bracket `[` to the JSON.
internal mutating func startArray() {
data.append(asciiOpenSquareBracket)
separator = nil
}
/// Append a close square bracket `]` to the JSON.
internal mutating func endArray() {
data.append(asciiCloseSquareBracket)
separator = asciiComma
}
/// Append a comma `,` to the JSON.
internal mutating func comma() {
data.append(asciiComma)
}
/// Append an open curly brace `{` to the JSON.
/// Assumes this object is part of an array of objects.
internal mutating func startArrayObject() {
if let s = separator {
data.append(s)
}
data.append(asciiOpenCurlyBracket)
separator = nil
}
/// Append an open curly brace `{` to the JSON.
internal mutating func startObject() {
data.append(asciiOpenCurlyBracket)
separator = nil
}
/// Append a close curly brace `}` to the JSON.
internal mutating func endObject() {
data.append(asciiCloseCurlyBracket)
separator = asciiComma
}
/// Write a JSON `null` token to the output.
internal mutating func putNullValue() {
append(staticText: "null")
}
/// Append a float value to the output.
/// This handles Nan and infinite values by
/// writing well-known string values.
internal mutating func putFloatValue(value: Float) {
if value.isNaN {
append(staticText: "\"NaN\"")
} else if !value.isFinite {
if value < 0 {
append(staticText: "\"-Infinity\"")
} else {
append(staticText: "\"Infinity\"")
}
} else {
data.append(contentsOf: value.debugDescription.utf8)
}
}
/// Append a double value to the output.
/// This handles Nan and infinite values by
/// writing well-known string values.
internal mutating func putDoubleValue(value: Double) {
if value.isNaN {
append(staticText: "\"NaN\"")
} else if !value.isFinite {
if value < 0 {
append(staticText: "\"-Infinity\"")
} else {
append(staticText: "\"Infinity\"")
}
} else {
data.append(contentsOf: value.debugDescription.utf8)
}
}
/// Append a UInt64 to the output (without quoting).
private mutating func appendUInt(value: UInt64) {
if value >= 10 {
appendUInt(value: value / 10)
}
data.append(asciiZero + UInt8(value % 10))
}
/// Append an Int64 to the output (without quoting).
private mutating func appendInt(value: Int64) {
if value < 0 {
data.append(asciiMinus)
// This is the twos-complement negation of value,
// computed in a way that won't overflow a 64-bit
// signed integer.
appendUInt(value: 1 + ~UInt64(bitPattern: value))
} else {
appendUInt(value: UInt64(bitPattern: value))
}
}
/// Write an Enum as an int.
internal mutating func putEnumInt(value: Int) {
appendInt(value: Int64(value))
}
/// Write an `Int64` using protobuf JSON quoting conventions.
internal mutating func putInt64(value: Int64) {
data.append(asciiDoubleQuote)
appendInt(value: value)
data.append(asciiDoubleQuote)
}
/// Write an `Int32` with quoting suitable for
/// using the value as a map key.
internal mutating func putQuotedInt32(value: Int32) {
data.append(asciiDoubleQuote)
appendInt(value: Int64(value))
data.append(asciiDoubleQuote)
}
/// Write an `Int32` in the default format.
internal mutating func putInt32(value: Int32) {
appendInt(value: Int64(value))
}
/// Write a `UInt64` using protobuf JSON quoting conventions.
internal mutating func putUInt64(value: UInt64) {
data.append(asciiDoubleQuote)
appendUInt(value: value)
data.append(asciiDoubleQuote)
}
/// Write a `UInt32` with quoting suitable for
/// using the value as a map key.
internal mutating func putQuotedUInt32(value: UInt32) {
data.append(asciiDoubleQuote)
appendUInt(value: UInt64(value))
data.append(asciiDoubleQuote)
}
/// Write a `UInt32` in the default format.
internal mutating func putUInt32(value: UInt32) {
appendUInt(value: UInt64(value))
}
/// Write a `Bool` with quoting suitable for
/// using the value as a map key.
internal mutating func putQuotedBoolValue(value: Bool) {
data.append(asciiDoubleQuote)
putBoolValue(value: value)
data.append(asciiDoubleQuote)
}
/// Write a `Bool` in the default format.
internal mutating func putBoolValue(value: Bool) {
if value {
append(staticText: "true")
} else {
append(staticText: "false")
}
}
/// Append a string value escaping special characters as needed.
internal mutating func putStringValue(value: String) {
data.append(asciiDoubleQuote)
for c in value.unicodeScalars {
switch c.value {
// Special two-byte escapes
case 8: append(staticText: "\\b")
case 9: append(staticText: "\\t")
case 10: append(staticText: "\\n")
case 12: append(staticText: "\\f")
case 13: append(staticText: "\\r")
case 34: append(staticText: "\\\"")
case 92: append(staticText: "\\\\")
case 0...31, 127...159: // Hex form for C0 control chars
append(staticText: "\\u00")
data.append(hexDigits[Int(c.value / 16)])
data.append(hexDigits[Int(c.value & 15)])
case 23...126:
data.append(UInt8(truncatingIfNeeded: c.value))
case 0x80...0x7ff:
data.append(0xc0 + UInt8(truncatingIfNeeded: c.value >> 6))
data.append(0x80 + UInt8(truncatingIfNeeded: c.value & 0x3f))
case 0x800...0xffff:
data.append(0xe0 + UInt8(truncatingIfNeeded: c.value >> 12))
data.append(0x80 + UInt8(truncatingIfNeeded: (c.value >> 6) & 0x3f))
data.append(0x80 + UInt8(truncatingIfNeeded: c.value & 0x3f))
default:
data.append(0xf0 + UInt8(truncatingIfNeeded: c.value >> 18))
data.append(0x80 + UInt8(truncatingIfNeeded: (c.value >> 12) & 0x3f))
data.append(0x80 + UInt8(truncatingIfNeeded: (c.value >> 6) & 0x3f))
data.append(0x80 + UInt8(truncatingIfNeeded: c.value & 0x3f))
}
}
data.append(asciiDoubleQuote)
}
/// Append a bytes value using protobuf JSON Base-64 encoding.
internal mutating func putBytesValue(value: Data) {
data.append(asciiDoubleQuote)
if value.count > 0 {
value.withUnsafeBytes { (body: UnsafeRawBufferPointer) in
if let p = body.baseAddress, body.count > 0 {
var t: Int = 0
var bytesInGroup: Int = 0
for i in 0..<body.count {
if bytesInGroup == 3 {
data.append(base64Digits[(t >> 18) & 63])
data.append(base64Digits[(t >> 12) & 63])
data.append(base64Digits[(t >> 6) & 63])
data.append(base64Digits[t & 63])
t = 0
bytesInGroup = 0
}
t = (t << 8) + Int(p[i])
bytesInGroup += 1
}
switch bytesInGroup {
case 3:
data.append(base64Digits[(t >> 18) & 63])
data.append(base64Digits[(t >> 12) & 63])
data.append(base64Digits[(t >> 6) & 63])
data.append(base64Digits[t & 63])
case 2:
t <<= 8
data.append(base64Digits[(t >> 18) & 63])
data.append(base64Digits[(t >> 12) & 63])
data.append(base64Digits[(t >> 6) & 63])
data.append(asciiEquals)
case 1:
t <<= 16
data.append(base64Digits[(t >> 18) & 63])
data.append(base64Digits[(t >> 12) & 63])
data.append(asciiEquals)
data.append(asciiEquals)
default:
break
}
}
}
}
data.append(asciiDoubleQuote)
}
}

View File

@ -0,0 +1,35 @@
// Sources/SwiftProtobuf/JSONEncodingError.swift - Error constants
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Enum constants that identify the particular error.
///
// -----------------------------------------------------------------------------
public enum JSONEncodingError: Error {
/// Any fields that were decoded from binary format cannot be
/// re-encoded into JSON unless the object they hold is a
/// well-known type or a type registered with via
/// Google_Protobuf_Any.register()
case anyTranscodeFailure
/// Timestamp values can only be JSON encoded if they hold a value
/// between 0001-01-01Z00:00:00 and 9999-12-31Z23:59:59.
case timestampRange
/// Duration values can only be JSON encoded if they hold a value
/// less than +/- 100 years.
case durationRange
/// Field masks get edited when converting between JSON and protobuf
case fieldMaskConversion
/// Field names were not compiled into the binary
case missingFieldNames
/// Instances of `Google_Protobuf_Value` can only be encoded if they have a
/// valid `kind` (that is, they represent a null value, number, boolean,
/// string, struct, or list).
case missingValue
}

View File

@ -0,0 +1,26 @@
// Sources/SwiftProtobuf/JSONEncodingOptions.swift - JSON encoding options
//
// Copyright (c) 2014 - 2018 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// JSON encoding options
///
// -----------------------------------------------------------------------------
/// Options for JSONEncoding.
public struct JSONEncodingOptions {
/// Always print enums as ints. By default they are printed as strings.
public var alwaysPrintEnumsAsInts: Bool = false
/// Whether to preserve proto field names.
/// By default they are converted to JSON(lowerCamelCase) names.
public var preserveProtoFieldNames: Bool = false
public init() {}
}

View File

@ -0,0 +1,404 @@
// Sources/SwiftProtobuf/JSONEncodingVisitor.swift - JSON encoding visitor
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Visitor that writes a message in JSON format.
///
// -----------------------------------------------------------------------------
import Foundation
/// Visitor that serializes a message into JSON format.
internal struct JSONEncodingVisitor: Visitor {
private var encoder = JSONEncoder()
private var nameMap: _NameMap
private var extensions: ExtensionFieldValueSet?
private let options: JSONEncodingOptions
/// The JSON text produced by the visitor, as raw UTF8 bytes.
var dataResult: Data {
return encoder.dataResult
}
/// The JSON text produced by the visitor, as a String.
internal var stringResult: String {
return encoder.stringResult
}
/// Creates a new visitor for serializing a message of the given type to JSON
/// format.
init(type: Message.Type, options: JSONEncodingOptions) throws {
if let nameProviding = type as? _ProtoNameProviding.Type {
self.nameMap = nameProviding._protobuf_nameMap
} else {
throw JSONEncodingError.missingFieldNames
}
self.options = options
}
mutating func startArray() {
encoder.startArray()
}
mutating func endArray() {
encoder.endArray()
}
mutating func startObject(message: Message) {
self.extensions = (message as? ExtensibleMessage)?._protobuf_extensionFieldValues
encoder.startObject()
}
mutating func startArrayObject(message: Message) {
self.extensions = (message as? ExtensibleMessage)?._protobuf_extensionFieldValues
encoder.startArrayObject()
}
mutating func endObject() {
encoder.endObject()
}
mutating func encodeField(name: String, stringValue value: String) {
encoder.startField(name: name)
encoder.putStringValue(value: value)
}
mutating func encodeField(name: String, jsonText text: String) {
encoder.startField(name: name)
encoder.append(text: text)
}
mutating func visitUnknown(bytes: Data) throws {
// JSON encoding has no provision for carrying proto2 unknown fields.
}
mutating func visitSingularFloatField(value: Float, fieldNumber: Int) throws {
try startField(for: fieldNumber)
encoder.putFloatValue(value: value)
}
mutating func visitSingularDoubleField(value: Double, fieldNumber: Int) throws {
try startField(for: fieldNumber)
encoder.putDoubleValue(value: value)
}
mutating func visitSingularInt32Field(value: Int32, fieldNumber: Int) throws {
try startField(for: fieldNumber)
encoder.putInt32(value: value)
}
mutating func visitSingularInt64Field(value: Int64, fieldNumber: Int) throws {
try startField(for: fieldNumber)
encoder.putInt64(value: value)
}
mutating func visitSingularUInt32Field(value: UInt32, fieldNumber: Int) throws {
try startField(for: fieldNumber)
encoder.putUInt32(value: value)
}
mutating func visitSingularUInt64Field(value: UInt64, fieldNumber: Int) throws {
try startField(for: fieldNumber)
encoder.putUInt64(value: value)
}
mutating func visitSingularFixed32Field(value: UInt32, fieldNumber: Int) throws {
try startField(for: fieldNumber)
encoder.putUInt32(value: value)
}
mutating func visitSingularSFixed32Field(value: Int32, fieldNumber: Int) throws {
try startField(for: fieldNumber)
encoder.putInt32(value: value)
}
mutating func visitSingularBoolField(value: Bool, fieldNumber: Int) throws {
try startField(for: fieldNumber)
encoder.putBoolValue(value: value)
}
mutating func visitSingularStringField(value: String, fieldNumber: Int) throws {
try startField(for: fieldNumber)
encoder.putStringValue(value: value)
}
mutating func visitSingularBytesField(value: Data, fieldNumber: Int) throws {
try startField(for: fieldNumber)
encoder.putBytesValue(value: value)
}
private mutating func _visitRepeated<T>(
value: [T],
fieldNumber: Int,
encode: (inout JSONEncoder, T) throws -> ()
) throws {
assert(!value.isEmpty)
try startField(for: fieldNumber)
var comma = false
encoder.startArray()
for v in value {
if comma {
encoder.comma()
}
comma = true
try encode(&encoder, v)
}
encoder.endArray()
}
mutating func visitSingularEnumField<E: Enum>(value: E, fieldNumber: Int) throws {
try startField(for: fieldNumber)
if let e = value as? _CustomJSONCodable {
let json = try e.encodedJSONString(options: options)
encoder.append(text: json)
} else if !options.alwaysPrintEnumsAsInts, let n = value.name {
encoder.appendQuoted(name: n)
} else {
encoder.putEnumInt(value: value.rawValue)
}
}
mutating func visitSingularMessageField<M: Message>(value: M, fieldNumber: Int) throws {
try startField(for: fieldNumber)
if let m = value as? _CustomJSONCodable {
let json = try m.encodedJSONString(options: options)
encoder.append(text: json)
} else if let newNameMap = (M.self as? _ProtoNameProviding.Type)?._protobuf_nameMap {
// Preserve outer object's name and extension maps; restore them before returning
let oldNameMap = self.nameMap
let oldExtensions = self.extensions
defer {
self.nameMap = oldNameMap
self.extensions = oldExtensions
}
// Install inner object's name and extension maps
self.nameMap = newNameMap
startObject(message: value)
try value.traverse(visitor: &self)
endObject()
} else {
throw JSONEncodingError.missingFieldNames
}
}
mutating func visitSingularGroupField<G: Message>(value: G, fieldNumber: Int) throws {
// Google does not serialize groups into JSON
}
mutating func visitRepeatedFloatField(value: [Float], fieldNumber: Int) throws {
try _visitRepeated(value: value, fieldNumber: fieldNumber) {
(encoder: inout JSONEncoder, v: Float) in
encoder.putFloatValue(value: v)
}
}
mutating func visitRepeatedDoubleField(value: [Double], fieldNumber: Int) throws {
try _visitRepeated(value: value, fieldNumber: fieldNumber) {
(encoder: inout JSONEncoder, v: Double) in
encoder.putDoubleValue(value: v)
}
}
mutating func visitRepeatedInt32Field(value: [Int32], fieldNumber: Int) throws {
try _visitRepeated(value: value, fieldNumber: fieldNumber) {
(encoder: inout JSONEncoder, v: Int32) in
encoder.putInt32(value: v)
}
}
mutating func visitRepeatedInt64Field(value: [Int64], fieldNumber: Int) throws {
try _visitRepeated(value: value, fieldNumber: fieldNumber) {
(encoder: inout JSONEncoder, v: Int64) in
encoder.putInt64(value: v)
}
}
mutating func visitRepeatedUInt32Field(value: [UInt32], fieldNumber: Int) throws {
try _visitRepeated(value: value, fieldNumber: fieldNumber) {
(encoder: inout JSONEncoder, v: UInt32) in
encoder.putUInt32(value: v)
}
}
mutating func visitRepeatedUInt64Field(value: [UInt64], fieldNumber: Int) throws {
try _visitRepeated(value: value, fieldNumber: fieldNumber) {
(encoder: inout JSONEncoder, v: UInt64) in
encoder.putUInt64(value: v)
}
}
mutating func visitRepeatedSInt32Field(value: [Int32], fieldNumber: Int) throws {
try visitRepeatedInt32Field(value: value, fieldNumber: fieldNumber)
}
mutating func visitRepeatedSInt64Field(value: [Int64], fieldNumber: Int) throws {
try visitRepeatedInt64Field(value: value, fieldNumber: fieldNumber)
}
mutating func visitRepeatedFixed32Field(value: [UInt32], fieldNumber: Int) throws {
try visitRepeatedUInt32Field(value: value, fieldNumber: fieldNumber)
}
mutating func visitRepeatedFixed64Field(value: [UInt64], fieldNumber: Int) throws {
try visitRepeatedUInt64Field(value: value, fieldNumber: fieldNumber)
}
mutating func visitRepeatedSFixed32Field(value: [Int32], fieldNumber: Int) throws {
try visitRepeatedInt32Field(value: value, fieldNumber: fieldNumber)
}
mutating func visitRepeatedSFixed64Field(value: [Int64], fieldNumber: Int) throws {
try visitRepeatedInt64Field(value: value, fieldNumber: fieldNumber)
}
mutating func visitRepeatedBoolField(value: [Bool], fieldNumber: Int) throws {
try _visitRepeated(value: value, fieldNumber: fieldNumber) {
(encoder: inout JSONEncoder, v: Bool) in
encoder.putBoolValue(value: v)
}
}
mutating func visitRepeatedStringField(value: [String], fieldNumber: Int) throws {
try _visitRepeated(value: value, fieldNumber: fieldNumber) {
(encoder: inout JSONEncoder, v: String) in
encoder.putStringValue(value: v)
}
}
mutating func visitRepeatedBytesField(value: [Data], fieldNumber: Int) throws {
try _visitRepeated(value: value, fieldNumber: fieldNumber) {
(encoder: inout JSONEncoder, v: Data) in
encoder.putBytesValue(value: v)
}
}
mutating func visitRepeatedEnumField<E: Enum>(value: [E], fieldNumber: Int) throws {
if let _ = E.self as? _CustomJSONCodable.Type {
let options = self.options
try _visitRepeated(value: value, fieldNumber: fieldNumber) {
(encoder: inout JSONEncoder, v: E) throws in
let e = v as! _CustomJSONCodable
let json = try e.encodedJSONString(options: options)
encoder.append(text: json)
}
} else {
let alwaysPrintEnumsAsInts = options.alwaysPrintEnumsAsInts
try _visitRepeated(value: value, fieldNumber: fieldNumber) {
(encoder: inout JSONEncoder, v: E) throws in
if !alwaysPrintEnumsAsInts, let n = v.name {
encoder.appendQuoted(name: n)
} else {
encoder.putEnumInt(value: v.rawValue)
}
}
}
}
mutating func visitRepeatedMessageField<M: Message>(value: [M], fieldNumber: Int) throws {
assert(!value.isEmpty)
try startField(for: fieldNumber)
var comma = false
encoder.startArray()
if let _ = M.self as? _CustomJSONCodable.Type {
for v in value {
if comma {
encoder.comma()
}
comma = true
let json = try v.jsonString(options: options)
encoder.append(text: json)
}
} else if let newNameMap = (M.self as? _ProtoNameProviding.Type)?._protobuf_nameMap {
// Preserve name and extension maps for outer object
let oldNameMap = self.nameMap
let oldExtensions = self.extensions
// Restore outer object's name and extension maps before returning
defer {
self.nameMap = oldNameMap
self.extensions = oldExtensions
}
self.nameMap = newNameMap
for v in value {
startArrayObject(message: v)
try v.traverse(visitor: &self)
encoder.endObject()
}
} else {
throw JSONEncodingError.missingFieldNames
}
encoder.endArray()
}
mutating func visitRepeatedGroupField<G: Message>(value: [G], fieldNumber: Int) throws {
assert(!value.isEmpty)
// Google does not serialize groups into JSON
}
// Packed fields are handled the same as non-packed fields, so JSON just
// relies on the default implementations in Visitor.swift
mutating func visitMapField<KeyType, ValueType: MapValueType>(fieldType: _ProtobufMap<KeyType, ValueType>.Type, value: _ProtobufMap<KeyType, ValueType>.BaseType, fieldNumber: Int) throws {
try startField(for: fieldNumber)
encoder.append(text: "{")
var mapVisitor = JSONMapEncodingVisitor(encoder: encoder, options: options)
for (k,v) in value {
try KeyType.visitSingular(value: k, fieldNumber: 1, with: &mapVisitor)
try ValueType.visitSingular(value: v, fieldNumber: 2, with: &mapVisitor)
}
encoder = mapVisitor.encoder
encoder.append(text: "}")
}
mutating func visitMapField<KeyType, ValueType>(fieldType: _ProtobufEnumMap<KeyType, ValueType>.Type, value: _ProtobufEnumMap<KeyType, ValueType>.BaseType, fieldNumber: Int) throws where ValueType.RawValue == Int {
try startField(for: fieldNumber)
encoder.append(text: "{")
var mapVisitor = JSONMapEncodingVisitor(encoder: encoder, options: options)
for (k, v) in value {
try KeyType.visitSingular(value: k, fieldNumber: 1, with: &mapVisitor)
try mapVisitor.visitSingularEnumField(value: v, fieldNumber: 2)
}
encoder = mapVisitor.encoder
encoder.append(text: "}")
}
mutating func visitMapField<KeyType, ValueType>(fieldType: _ProtobufMessageMap<KeyType, ValueType>.Type, value: _ProtobufMessageMap<KeyType, ValueType>.BaseType, fieldNumber: Int) throws {
try startField(for: fieldNumber)
encoder.append(text: "{")
var mapVisitor = JSONMapEncodingVisitor(encoder: encoder, options: options)
for (k,v) in value {
try KeyType.visitSingular(value: k, fieldNumber: 1, with: &mapVisitor)
try mapVisitor.visitSingularMessageField(value: v, fieldNumber: 2)
}
encoder = mapVisitor.encoder
encoder.append(text: "}")
}
/// Helper function that throws an error if the field number could not be
/// resolved.
private mutating func startField(for number: Int) throws {
let name: _NameMap.Name?
if options.preserveProtoFieldNames {
name = nameMap.names(for: number)?.proto
} else {
name = nameMap.names(for: number)?.json
}
if let name = name {
encoder.startField(name: name)
} else if let name = extensions?[number]?.protobufExtension.fieldName {
encoder.startExtensionField(name: name)
} else {
throw JSONEncodingError.missingFieldNames
}
}
}

View File

@ -0,0 +1,174 @@
// Sources/SwiftProtobuf/JSONMapEncodingVisitor.swift - JSON map encoding visitor
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Visitor that writes out the key/value pairs for a JSON map.
///
// -----------------------------------------------------------------------------
import Foundation
/// Visitor that serializes a message into JSON map format.
///
/// This expects to alternately visit the keys and values for a JSON
/// map. It only accepts singular values. Keys should be identified
/// as `fieldNumber:1`, values should be identified as `fieldNumber:2`
///
internal struct JSONMapEncodingVisitor: SelectiveVisitor {
private var separator: StaticString?
internal var encoder: JSONEncoder
private let options: JSONEncodingOptions
init(encoder: JSONEncoder, options: JSONEncodingOptions) {
self.encoder = encoder
self.options = options
}
private mutating func startKey() {
if let s = separator {
encoder.append(staticText: s)
} else {
separator = ","
}
}
private mutating func startValue() {
encoder.append(staticText: ":")
}
mutating func visitSingularFloatField(value: Float, fieldNumber: Int) throws {
// Doubles/Floats can never be map keys, only values
assert(fieldNumber == 2)
startValue()
encoder.putFloatValue(value: value)
}
mutating func visitSingularDoubleField(value: Double, fieldNumber: Int) throws {
// Doubles/Floats can never be map keys, only values
assert(fieldNumber == 2)
startValue()
encoder.putDoubleValue(value: value)
}
mutating func visitSingularInt32Field(value: Int32, fieldNumber: Int) throws {
if fieldNumber == 1 {
startKey()
encoder.putQuotedInt32(value: value)
} else {
startValue()
encoder.putInt32(value: value)
}
}
mutating func visitSingularInt64Field(value: Int64, fieldNumber: Int) throws {
if fieldNumber == 1 {
startKey()
} else {
startValue()
}
// Int64 fields are always quoted anyway
encoder.putInt64(value: value)
}
mutating func visitSingularUInt32Field(value: UInt32, fieldNumber: Int) throws {
if fieldNumber == 1 {
startKey()
encoder.putQuotedUInt32(value: value)
} else {
startValue()
encoder.putUInt32(value: value)
}
}
mutating func visitSingularUInt64Field(value: UInt64, fieldNumber: Int) throws {
if fieldNumber == 1 {
startKey()
} else {
startValue()
}
encoder.putUInt64(value: value)
}
mutating func visitSingularSInt32Field(value: Int32, fieldNumber: Int) throws {
try visitSingularInt32Field(value: value, fieldNumber: fieldNumber)
}
mutating func visitSingularSInt64Field(value: Int64, fieldNumber: Int) throws {
try visitSingularInt64Field(value: value, fieldNumber: fieldNumber)
}
mutating func visitSingularFixed32Field(value: UInt32, fieldNumber: Int) throws {
try visitSingularUInt32Field(value: value, fieldNumber: fieldNumber)
}
mutating func visitSingularFixed64Field(value: UInt64, fieldNumber: Int) throws {
try visitSingularUInt64Field(value: value, fieldNumber: fieldNumber)
}
mutating func visitSingularSFixed32Field(value: Int32, fieldNumber: Int) throws {
try visitSingularInt32Field(value: value, fieldNumber: fieldNumber)
}
mutating func visitSingularSFixed64Field(value: Int64, fieldNumber: Int) throws {
try visitSingularInt64Field(value: value, fieldNumber: fieldNumber)
}
mutating func visitSingularBoolField(value: Bool, fieldNumber: Int) throws {
if fieldNumber == 1 {
startKey()
encoder.putQuotedBoolValue(value: value)
} else {
startValue()
encoder.putBoolValue(value: value)
}
}
mutating func visitSingularStringField(value: String, fieldNumber: Int) throws {
if fieldNumber == 1 {
startKey()
} else {
startValue()
}
encoder.putStringValue(value: value)
}
mutating func visitSingularBytesField(value: Data, fieldNumber: Int) throws {
// Bytes can only be map values, never keys
assert(fieldNumber == 2)
startValue()
encoder.putBytesValue(value: value)
}
mutating func visitSingularEnumField<E: Enum>(value: E, fieldNumber: Int) throws {
// Enums can only be map values, never keys
assert(fieldNumber == 2)
startValue()
if !options.alwaysPrintEnumsAsInts, let n = value.name {
encoder.putStringValue(value: String(describing: n))
} else {
encoder.putEnumInt(value: value.rawValue)
}
}
mutating func visitSingularMessageField<M: Message>(value: M, fieldNumber: Int) throws {
// Messages can only be map values, never keys
assert(fieldNumber == 2)
startValue()
let json = try value.jsonString(options: options)
encoder.append(text: json)
}
// SelectiveVisitor will block:
// - single Groups
// - everything repeated
// - everything packed
// - all maps
// - unknown fields
// - extensions
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,40 @@
// Sources/SwiftProtobuf/MathUtils.swift - Generally useful mathematical functions
//
// Copyright (c) 2014 - 2017 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Generally useful mathematical and arithmetic functions.
///
// -----------------------------------------------------------------------------
import Foundation
/// Remainder in standard modular arithmetic (modulo). This coincides with (%)
/// when a > 0.
///
/// - Parameters:
/// - a: The dividend. Can be positive, 0 or negative.
/// - b: The divisor. This must be positive, and is an error if 0 or negative.
/// - Returns: The unique value r such that 0 <= r < b and b * q + r = a for some q.
internal func mod<T : SignedInteger>(_ a: T, _ b: T) -> T {
assert(b > 0)
let r = a % b
return r >= 0 ? r : r + b
}
/// Quotient in standard modular arithmetic (Euclidean division). This coincides
/// with (/) when a > 0.
///
/// - Parameters:
/// - a: The dividend. Can be positive, 0 or negative.
/// - b: The divisor. This must be positive, and is an error if 0 or negative.
/// - Returns: The unique value q such that for some 0 <= r < b, b * q + r = a.
internal func div<T : SignedInteger>(_ a: T, _ b: T) -> T {
assert(b > 0)
return a >= 0 ? a / b : (a + 1) / b - 1
}

View File

@ -0,0 +1,45 @@
// Sources/SwiftProtobuf/Message+AnyAdditions.swift - Any-related Message extensions
//
// Copyright (c) 2014 - 2017 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Extends the `Message` type with `Google_Protobuf_Any`-specific behavior.
///
// -----------------------------------------------------------------------------
extension Message {
/// Initialize this message from the provided `google.protobuf.Any`
/// well-known type.
///
/// This corresponds to the `unpack` method in the Google C++ API.
///
/// If the Any object was decoded from Protobuf Binary or JSON
/// format, then the enclosed field data was stored and is not
/// fully decoded until you unpack the Any object into a message.
/// As such, this method will typically need to perform a full
/// deserialization of the enclosed data and can fail for any
/// reason that deserialization can fail.
///
/// See `Google_Protobuf_Any.unpackTo()` for more discussion.
///
/// - Parameter unpackingAny: the message to decode.
/// - Parameter extensions: An `ExtensionMap` used to look up and decode any
/// extensions in this message or messages nested within this message's
/// fields.
/// - Parameter options: The BinaryDecodingOptions to use.
/// - Throws: an instance of `AnyUnpackError`, `JSONDecodingError`, or
/// `BinaryDecodingError` on failure.
public init(
unpackingAny: Google_Protobuf_Any,
extensions: ExtensionMap? = nil,
options: BinaryDecodingOptions = BinaryDecodingOptions()
) throws {
self.init()
try unpackingAny._storage.unpackTo(target: &self, extensions: extensions, options: options)
}
}

View File

@ -0,0 +1,204 @@
// Sources/SwiftProtobuf/Message+BinaryAdditions.swift - Per-type binary coding
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Extensions to `Message` to provide binary coding and decoding.
///
// -----------------------------------------------------------------------------
import Foundation
/// Binary encoding and decoding methods for messages.
extension Message {
/// Returns a `Data` value containing the Protocol Buffer binary format
/// serialization of the message.
///
/// - Parameters:
/// - partial: If `false` (the default), this method will check
/// `Message.isInitialized` before encoding to verify that all required
/// fields are present. If any are missing, this method throws
/// `BinaryEncodingError.missingRequiredFields`.
/// - Returns: A `Data` value containing the binary serialization of the
/// message.
/// - Throws: `BinaryEncodingError` if encoding fails.
public func serializedData(partial: Bool = false) throws -> Data {
if !partial && !isInitialized {
throw BinaryEncodingError.missingRequiredFields
}
let requiredSize = try serializedDataSize()
var data = Data(count: requiredSize)
try data.withUnsafeMutableBytes { (body: UnsafeMutableRawBufferPointer) in
if let baseAddress = body.baseAddress, body.count > 0 {
var visitor = BinaryEncodingVisitor(forWritingInto: baseAddress)
try traverse(visitor: &visitor)
// Currently not exposing this from the api because it really would be
// an internal error in the library and should never happen.
assert(requiredSize == visitor.encoder.distance(pointer: baseAddress))
}
}
return data
}
/// Returns the size in bytes required to encode the message in binary format.
/// This is used by `serializedData()` to precalculate the size of the buffer
/// so that encoding can proceed without bounds checks or reallocation.
internal func serializedDataSize() throws -> Int {
// Note: since this api is internal, it doesn't currently worry about
// needing a partial argument to handle proto2 syntax required fields.
// If this become public, it will need that added.
var visitor = BinaryEncodingSizeVisitor()
try traverse(visitor: &visitor)
return visitor.serializedSize
}
/// Creates a new message by decoding the given `Data` value containing a
/// serialized message in Protocol Buffer binary format.
///
/// - Parameters:
/// - serializedData: The binary-encoded message data to decode.
/// - extensions: An `ExtensionMap` used to look up and decode any
/// extensions in this message or messages nested within this message's
/// fields.
/// - partial: If `false` (the default), this method will check
/// `Message.isInitialized` before encoding to verify that all required
/// fields are present. If any are missing, this method throws
/// `BinaryEncodingError.missingRequiredFields`.
/// - options: The BinaryDecodingOptions to use.
/// - Throws: `BinaryDecodingError` if decoding fails.
@inlinable
public init(
serializedData data: Data,
extensions: ExtensionMap? = nil,
partial: Bool = false,
options: BinaryDecodingOptions = BinaryDecodingOptions()
) throws {
self.init()
#if swift(>=5.0)
try merge(contiguousBytes: data, extensions: extensions, partial: partial, options: options)
#else
try merge(serializedData: data, extensions: extensions, partial: partial, options: options)
#endif
}
#if swift(>=5.0)
/// Creates a new message by decoding the given `ContiguousBytes` value
/// containing a serialized message in Protocol Buffer binary format.
///
/// - Parameters:
/// - contiguousBytes: The binary-encoded message data to decode.
/// - extensions: An `ExtensionMap` used to look up and decode any
/// extensions in this message or messages nested within this message's
/// fields.
/// - partial: If `false` (the default), this method will check
/// `Message.isInitialized` before encoding to verify that all required
/// fields are present. If any are missing, this method throws
/// `BinaryEncodingError.missingRequiredFields`.
/// - options: The BinaryDecodingOptions to use.
/// - Throws: `BinaryDecodingError` if decoding fails.
@inlinable
public init<Bytes: ContiguousBytes>(
contiguousBytes bytes: Bytes,
extensions: ExtensionMap? = nil,
partial: Bool = false,
options: BinaryDecodingOptions = BinaryDecodingOptions()
) throws {
self.init()
try merge(contiguousBytes: bytes, extensions: extensions, partial: partial, options: options)
}
#endif // #if swift(>=5.0)
/// Updates the message by decoding the given `Data` value containing a
/// serialized message in Protocol Buffer binary format into the receiver.
///
/// - Note: If this method throws an error, the message may still have been
/// partially mutated by the binary data that was decoded before the error
/// occurred.
///
/// - Parameters:
/// - serializedData: The binary-encoded message data to decode.
/// - extensions: An `ExtensionMap` used to look up and decode any
/// extensions in this message or messages nested within this message's
/// fields.
/// - partial: If `false` (the default), this method will check
/// `Message.isInitialized` before encoding to verify that all required
/// fields are present. If any are missing, this method throws
/// `BinaryEncodingError.missingRequiredFields`.
/// - options: The BinaryDecodingOptions to use.
/// - Throws: `BinaryDecodingError` if decoding fails.
@inlinable
public mutating func merge(
serializedData data: Data,
extensions: ExtensionMap? = nil,
partial: Bool = false,
options: BinaryDecodingOptions = BinaryDecodingOptions()
) throws {
#if swift(>=5.0)
try merge(contiguousBytes: data, extensions: extensions, partial: partial, options: options)
#else
try data.withUnsafeBytes { (body: UnsafeRawBufferPointer) in
try _merge(rawBuffer: body, extensions: extensions, partial: partial, options: options)
}
#endif // swift(>=5.0)
}
#if swift(>=5.0)
/// Updates the message by decoding the given `ContiguousBytes` value
/// containing a serialized message in Protocol Buffer binary format into the
/// receiver.
///
/// - Note: If this method throws an error, the message may still have been
/// partially mutated by the binary data that was decoded before the error
/// occurred.
///
/// - Parameters:
/// - contiguousBytes: The binary-encoded message data to decode.
/// - extensions: An `ExtensionMap` used to look up and decode any
/// extensions in this message or messages nested within this message's
/// fields.
/// - partial: If `false` (the default), this method will check
/// `Message.isInitialized` before encoding to verify that all required
/// fields are present. If any are missing, this method throws
/// `BinaryEncodingError.missingRequiredFields`.
/// - options: The BinaryDecodingOptions to use.
/// - Throws: `BinaryDecodingError` if decoding fails.
@inlinable
public mutating func merge<Bytes: ContiguousBytes>(
contiguousBytes bytes: Bytes,
extensions: ExtensionMap? = nil,
partial: Bool = false,
options: BinaryDecodingOptions = BinaryDecodingOptions()
) throws {
try bytes.withUnsafeBytes { (body: UnsafeRawBufferPointer) in
try _merge(rawBuffer: body, extensions: extensions, partial: partial, options: options)
}
}
#endif // swift(>=5.0)
// Helper for `merge()`s to keep the Decoder internal to SwiftProtobuf while
// allowing the generic over ContiguousBytes to get better codegen from the
// compiler by being `@inlinable`.
@usableFromInline
internal mutating func _merge(
rawBuffer body: UnsafeRawBufferPointer,
extensions: ExtensionMap?,
partial: Bool,
options: BinaryDecodingOptions
) throws {
if let baseAddress = body.baseAddress, body.count > 0 {
var decoder = BinaryDecoder(forReadingFrom: baseAddress,
count: body.count,
options: options,
extensions: extensions)
try decoder.decodeFullMessage(message: &self)
}
if !partial && !isInitialized {
throw BinaryDecodingError.missingRequiredFields
}
}
}

View File

@ -0,0 +1,150 @@
// Sources/SwiftProtobuf/Message+JSONAdditions.swift - JSON format primitive types
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Extensions to `Message` to support JSON encoding/decoding.
///
// -----------------------------------------------------------------------------
import Foundation
/// JSON encoding and decoding methods for messages.
extension Message {
/// Returns a string containing the JSON serialization of the message.
///
/// Unlike binary encoding, presence of required fields is not enforced when
/// serializing to JSON.
///
/// - Returns: A string containing the JSON serialization of the message.
/// - Parameters:
/// - options: The JSONEncodingOptions to use.
/// - Throws: `JSONEncodingError` if encoding fails.
public func jsonString(
options: JSONEncodingOptions = JSONEncodingOptions()
) throws -> String {
if let m = self as? _CustomJSONCodable {
return try m.encodedJSONString(options: options)
}
let data = try jsonUTF8Data(options: options)
return String(data: data, encoding: String.Encoding.utf8)!
}
/// Returns a Data containing the UTF-8 JSON serialization of the message.
///
/// Unlike binary encoding, presence of required fields is not enforced when
/// serializing to JSON.
///
/// - Returns: A Data containing the JSON serialization of the message.
/// - Parameters:
/// - options: The JSONEncodingOptions to use.
/// - Throws: `JSONEncodingError` if encoding fails.
public func jsonUTF8Data(
options: JSONEncodingOptions = JSONEncodingOptions()
) throws -> Data {
if let m = self as? _CustomJSONCodable {
let string = try m.encodedJSONString(options: options)
let data = string.data(using: String.Encoding.utf8)! // Cannot fail!
return data
}
var visitor = try JSONEncodingVisitor(type: Self.self, options: options)
visitor.startObject(message: self)
try traverse(visitor: &visitor)
visitor.endObject()
return visitor.dataResult
}
/// Creates a new message by decoding the given string containing a
/// serialized message in JSON format.
///
/// - Parameter jsonString: The JSON-formatted string to decode.
/// - Parameter options: The JSONDecodingOptions to use.
/// - Throws: `JSONDecodingError` if decoding fails.
public init(
jsonString: String,
options: JSONDecodingOptions = JSONDecodingOptions()
) throws {
try self.init(jsonString: jsonString, extensions: nil, options: options)
}
/// Creates a new message by decoding the given string containing a
/// serialized message in JSON format.
///
/// - Parameter jsonString: The JSON-formatted string to decode.
/// - Parameter extensions: An ExtensionMap for looking up extensions by name
/// - Parameter options: The JSONDecodingOptions to use.
/// - Throws: `JSONDecodingError` if decoding fails.
public init(
jsonString: String,
extensions: ExtensionMap? = nil,
options: JSONDecodingOptions = JSONDecodingOptions()
) throws {
if jsonString.isEmpty {
throw JSONDecodingError.truncated
}
if let data = jsonString.data(using: String.Encoding.utf8) {
try self.init(jsonUTF8Data: data, extensions: extensions, options: options)
} else {
throw JSONDecodingError.truncated
}
}
/// Creates a new message by decoding the given `Data` containing a
/// serialized message in JSON format, interpreting the data as UTF-8 encoded
/// text.
///
/// - Parameter jsonUTF8Data: The JSON-formatted data to decode, represented
/// as UTF-8 encoded text.
/// - Parameter options: The JSONDecodingOptions to use.
/// - Throws: `JSONDecodingError` if decoding fails.
public init(
jsonUTF8Data: Data,
options: JSONDecodingOptions = JSONDecodingOptions()
) throws {
try self.init(jsonUTF8Data: jsonUTF8Data, extensions: nil, options: options)
}
/// Creates a new message by decoding the given `Data` containing a
/// serialized message in JSON format, interpreting the data as UTF-8 encoded
/// text.
///
/// - Parameter jsonUTF8Data: The JSON-formatted data to decode, represented
/// as UTF-8 encoded text.
/// - Parameter extensions: The extension map to use with this decode
/// - Parameter options: The JSONDecodingOptions to use.
/// - Throws: `JSONDecodingError` if decoding fails.
public init(
jsonUTF8Data: Data,
extensions: ExtensionMap? = nil,
options: JSONDecodingOptions = JSONDecodingOptions()
) throws {
self.init()
try jsonUTF8Data.withUnsafeBytes { (body: UnsafeRawBufferPointer) in
// Empty input is valid for binary, but not for JSON.
guard body.count > 0 else {
throw JSONDecodingError.truncated
}
var decoder = JSONDecoder(source: body, options: options,
messageType: Self.self, extensions: extensions)
if decoder.scanner.skipOptionalNull() {
if let customCodable = Self.self as? _CustomJSONCodable.Type,
let message = try customCodable.decodedFromJSONNull() {
self = message as! Self
} else {
throw JSONDecodingError.illegalNull
}
} else {
try decoder.decodeFullObject(message: &self)
}
if !decoder.scanner.complete {
throw JSONDecodingError.trailingGarbage
}
}
}
}

View File

@ -0,0 +1,146 @@
// Sources/SwiftProtobuf/Array+JSONAdditions.swift - JSON format primitive types
//
// Copyright (c) 2014 - 2017 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Extensions to `Array` to support JSON encoding/decoding.
///
// -----------------------------------------------------------------------------
import Foundation
/// JSON encoding and decoding methods for arrays of messages.
extension Message {
/// Returns a string containing the JSON serialization of the messages.
///
/// Unlike binary encoding, presence of required fields is not enforced when
/// serializing to JSON.
///
/// - Returns: A string containing the JSON serialization of the messages.
/// - Parameters:
/// - collection: The list of messages to encode.
/// - options: The JSONEncodingOptions to use.
/// - Throws: `JSONEncodingError` if encoding fails.
public static func jsonString<C: Collection>(
from collection: C,
options: JSONEncodingOptions = JSONEncodingOptions()
) throws -> String where C.Iterator.Element == Self {
let data = try jsonUTF8Data(from: collection, options: options)
return String(data: data, encoding: String.Encoding.utf8)!
}
/// Returns a Data containing the UTF-8 JSON serialization of the messages.
///
/// Unlike binary encoding, presence of required fields is not enforced when
/// serializing to JSON.
///
/// - Returns: A Data containing the JSON serialization of the messages.
/// - Parameters:
/// - collection: The list of messages to encode.
/// - options: The JSONEncodingOptions to use.
/// - Throws: `JSONEncodingError` if encoding fails.
public static func jsonUTF8Data<C: Collection>(
from collection: C,
options: JSONEncodingOptions = JSONEncodingOptions()
) throws -> Data where C.Iterator.Element == Self {
var visitor = try JSONEncodingVisitor(type: Self.self, options: options)
visitor.startArray()
for message in collection {
visitor.startArrayObject(message: message)
try message.traverse(visitor: &visitor)
visitor.endObject()
}
visitor.endArray()
return visitor.dataResult
}
/// Creates a new array of messages by decoding the given string containing a
/// serialized array of messages in JSON format.
///
/// - Parameter jsonString: The JSON-formatted string to decode.
/// - Parameter options: The JSONDecodingOptions to use.
/// - Throws: `JSONDecodingError` if decoding fails.
public static func array(
fromJSONString jsonString: String,
options: JSONDecodingOptions = JSONDecodingOptions()
) throws -> [Self] {
return try self.array(fromJSONString: jsonString,
extensions: SimpleExtensionMap(),
options: options)
}
/// Creates a new array of messages by decoding the given string containing a
/// serialized array of messages in JSON format.
///
/// - Parameter jsonString: The JSON-formatted string to decode.
/// - Parameter extensions: The extension map to use with this decode
/// - Parameter options: The JSONDecodingOptions to use.
/// - Throws: `JSONDecodingError` if decoding fails.
public static func array(
fromJSONString jsonString: String,
extensions: ExtensionMap = SimpleExtensionMap(),
options: JSONDecodingOptions = JSONDecodingOptions()
) throws -> [Self] {
if jsonString.isEmpty {
throw JSONDecodingError.truncated
}
if let data = jsonString.data(using: String.Encoding.utf8) {
return try array(fromJSONUTF8Data: data, extensions: extensions, options: options)
} else {
throw JSONDecodingError.truncated
}
}
/// Creates a new array of messages by decoding the given `Data` containing a
/// serialized array of messages in JSON format, interpreting the data as
/// UTF-8 encoded text.
///
/// - Parameter jsonUTF8Data: The JSON-formatted data to decode, represented
/// as UTF-8 encoded text.
/// - Parameter options: The JSONDecodingOptions to use.
/// - Throws: `JSONDecodingError` if decoding fails.
public static func array(
fromJSONUTF8Data jsonUTF8Data: Data,
options: JSONDecodingOptions = JSONDecodingOptions()
) throws -> [Self] {
return try self.array(fromJSONUTF8Data: jsonUTF8Data,
extensions: SimpleExtensionMap(),
options: options)
}
/// Creates a new array of messages by decoding the given `Data` containing a
/// serialized array of messages in JSON format, interpreting the data as
/// UTF-8 encoded text.
///
/// - Parameter jsonUTF8Data: The JSON-formatted data to decode, represented
/// as UTF-8 encoded text.
/// - Parameter extensions: The extension map to use with this decode
/// - Parameter options: The JSONDecodingOptions to use.
/// - Throws: `JSONDecodingError` if decoding fails.
public static func array(
fromJSONUTF8Data jsonUTF8Data: Data,
extensions: ExtensionMap = SimpleExtensionMap(),
options: JSONDecodingOptions = JSONDecodingOptions()
) throws -> [Self] {
return try jsonUTF8Data.withUnsafeBytes { (body: UnsafeRawBufferPointer) in
var array = [Self]()
if body.count > 0 {
var decoder = JSONDecoder(source: body, options: options,
messageType: Self.self, extensions: extensions)
try decoder.decodeRepeatedMessageField(value: &array)
if !decoder.scanner.complete {
throw JSONDecodingError.trailingGarbage
}
}
return array
}
}
}

View File

@ -0,0 +1,88 @@
// Sources/SwiftProtobuf/Message+TextFormatAdditions.swift - Text format primitive types
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Extensions to `Message` to support text format encoding/decoding.
///
// -----------------------------------------------------------------------------
import Foundation
/// Text format encoding and decoding methods for messages.
extension Message {
/// Returns a string containing the Protocol Buffer text format serialization
/// of the message.
///
/// Unlike binary encoding, presence of required fields is not enforced when
/// serializing to text format.
///
/// - Returns: A string containing the text format serialization of the
/// message.
public func textFormatString() -> String {
// This is implemented as a separate zero-argument function
// to preserve binary compatibility.
return textFormatString(options: TextFormatEncodingOptions())
}
/// Returns a string containing the Protocol Buffer text format serialization
/// of the message.
///
/// Unlike binary encoding, presence of required fields is not enforced when
/// serializing to JSON.
///
/// - Returns: A string containing the text format serialization of the message.
/// - Parameters:
/// - options: The TextFormatEncodingOptions to use.
public func textFormatString(
options: TextFormatEncodingOptions
) -> String {
var visitor = TextFormatEncodingVisitor(message: self, options: options)
if let any = self as? Google_Protobuf_Any {
any._storage.textTraverse(visitor: &visitor)
} else {
// Although the general traversal/encoding infrastructure supports
// throwing errors (needed for JSON/Binary WKTs support, binary format
// missing required fields); TextEncoding never actually does throw.
try! traverse(visitor: &visitor)
}
return visitor.result
}
/// Creates a new message by decoding the given string containing a
/// serialized message in Protocol Buffer text format.
///
/// - Parameters:
/// - textFormatString: The text format string to decode.
/// - extensions: An `ExtensionMap` used to look up and decode any
/// extensions in this message or messages nested within this message's
/// fields.
/// - Throws: an instance of `TextFormatDecodingError` on failure.
public init(
textFormatString: String,
extensions: ExtensionMap? = nil
) throws {
self.init()
if !textFormatString.isEmpty {
if let data = textFormatString.data(using: String.Encoding.utf8) {
try data.withUnsafeBytes { (body: UnsafeRawBufferPointer) in
if let baseAddress = body.baseAddress, body.count > 0 {
var decoder = try TextFormatDecoder(messageType: Self.self,
utf8Pointer: baseAddress,
count: body.count,
extensions: extensions)
try decodeMessage(decoder: &decoder)
if !decoder.complete {
throw TextFormatDecodingError.trailingGarbage
}
}
}
}
}
}
}

View File

@ -0,0 +1,216 @@
// Sources/SwiftProtobuf/Message.swift - Message support
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
/// The protocol which all generated protobuf messages implement.
/// `Message` is the protocol type you should use whenever
/// you need an argument or variable which holds "some message".
///
/// Generated messages also implement `Hashable`, and thus `Equatable`.
/// However, the protocol conformance is declared on a different protocol.
/// This allows you to use `Message` as a type directly:
///
/// func consume(message: Message) { ... }
///
/// Instead of needing to use it as a type constraint on a generic declaration:
///
/// func consume<M: Message>(message: M) { ... }
///
/// If you need to convince the compiler that your message is `Hashable` so
/// you can insert it into a `Set` or use it as a `Dictionary` key, use
/// a generic declaration with a type constraint:
///
/// func insertIntoSet<M: Message & Hashable>(message: M) {
/// mySet.insert(message)
/// }
///
/// The actual functionality is implemented either in the generated code or in
/// default implementations of the below methods and properties.
public protocol Message: CustomDebugStringConvertible {
/// Creates a new message with all of its fields initialized to their default
/// values.
init()
// Metadata
// Basic facts about this class and the proto message it was generated from
// Used by various encoders and decoders
/// The fully-scoped name of the message from the original .proto file,
/// including any relevant package name.
static var protoMessageName: String { get }
/// True if all required fields (if any) on this message and any nested
/// messages (recursively) have values set; otherwise, false.
var isInitialized: Bool { get }
/// Some formats include enough information to transport fields that were
/// not known at generation time. When encountered, they are stored here.
var unknownFields: UnknownStorage { get set }
//
// General serialization/deserialization machinery
//
/// Decode all of the fields from the given decoder.
///
/// This is a simple loop that repeatedly gets the next field number
/// from `decoder.nextFieldNumber()` and then uses the number returned
/// and the type information from the original .proto file to decide
/// what type of data should be decoded for that field. The corresponding
/// method on the decoder is then called to get the field value.
///
/// This is the core method used by the deserialization machinery. It is
/// `public` to enable users to implement their own encoding formats by
/// conforming to `Decoder`; it should not be called otherwise.
///
/// Note that this is not specific to binary encodng; formats that use
/// textual identifiers translate those to field numbers and also go
/// through this to decode messages.
///
/// - Parameters:
/// - decoder: a `Decoder`; the `Message` will call the method
/// corresponding to the type of this field.
/// - Throws: an error on failure or type mismatch. The type of error
/// thrown depends on which decoder is used.
mutating func decodeMessage<D: Decoder>(decoder: inout D) throws
/// Traverses the fields of the message, calling the appropriate methods
/// of the passed `Visitor` object.
///
/// This is used internally by:
///
/// * Protobuf binary serialization
/// * JSON serialization (with some twists to account for specialty JSON)
/// * Protobuf Text serialization
/// * `Hashable` computation
///
/// Conceptually, serializers create visitor objects that are
/// then passed recursively to every message and field via generated
/// `traverse` methods. The details get a little involved due to
/// the need to allow particular messages to override particular
/// behaviors for specific encodings, but the general idea is quite simple.
func traverse<V: Visitor>(visitor: inout V) throws
// Standard utility properties and methods.
// Most of these are simple wrappers on top of the visitor machinery.
// They are implemented in the protocol, not in the generated structs,
// so can be overridden in user code by defining custom extensions to
// the generated struct.
#if swift(>=4.2)
/// An implementation of hash(into:) to provide conformance with the
/// `Hashable` protocol.
func hash(into hasher: inout Hasher)
#else // swift(>=4.2)
/// The hash value generated from this message's contents, for conformance
/// with the `Hashable` protocol.
var hashValue: Int { get }
#endif // swift(>=4.2)
/// Helper to compare `Message`s when not having a specific type to use
/// normal `Equatable`. `Equatable` is provided with specific generated
/// types.
func isEqualTo(message: Message) -> Bool
}
extension Message {
/// Generated proto2 messages that contain required fields, nested messages
/// that contain required fields, and/or extensions will provide their own
/// implementation of this property that tests that all required fields are
/// set. Users of the generated code SHOULD NOT override this property.
public var isInitialized: Bool {
// The generated code will include a specialization as needed.
return true
}
/// A hash based on the message's full contents.
#if swift(>=4.2)
public func hash(into hasher: inout Hasher) {
var visitor = HashVisitor(hasher)
try? traverse(visitor: &visitor)
hasher = visitor.hasher
}
#else // swift(>=4.2)
public var hashValue: Int {
var visitor = HashVisitor()
try? traverse(visitor: &visitor)
return visitor.hashValue
}
#endif // swift(>=4.2)
/// A description generated by recursively visiting all fields in the message,
/// including messages.
public var debugDescription: String {
// TODO Ideally there would be something like serializeText() that can
// take a prefix so we could do something like:
// [class name](
// [text format]
// )
let className = String(reflecting: type(of: self))
let header = "\(className):\n"
return header + textFormatString()
}
/// Creates an instance of the message type on which this method is called,
/// executes the given block passing the message in as its sole `inout`
/// argument, and then returns the message.
///
/// This method acts essentially as a "builder" in that the initialization of
/// the message is captured within the block, allowing the returned value to
/// be set in an immutable variable. For example,
///
/// let msg = MyMessage.with { $0.myField = "foo" }
/// msg.myOtherField = 5 // error: msg is immutable
///
/// - Parameter populator: A block or function that populates the new message,
/// which is passed into the block as an `inout` argument.
/// - Returns: The message after execution of the block.
public static func with(
_ populator: (inout Self) throws -> ()
) rethrows -> Self {
var message = Self()
try populator(&message)
return message
}
}
/// Implementation base for all messages; not intended for client use.
///
/// In general, use `SwiftProtobuf.Message` instead when you need a variable or
/// argument that can hold any type of message. Occasionally, you can use
/// `SwiftProtobuf.Message & Equatable` or `SwiftProtobuf.Message & Hashable` as
/// generic constraints if you need to write generic code that can be applied to
/// multiple message types that uses equality tests, puts messages in a `Set`,
/// or uses them as `Dictionary` keys.
public protocol _MessageImplementationBase: Message, Hashable {
// Legacy function; no longer used, but left to maintain source compatibility.
func _protobuf_generated_isEqualTo(other: Self) -> Bool
}
extension _MessageImplementationBase {
public func isEqualTo(message: Message) -> Bool {
guard let other = message as? Self else {
return false
}
return self == other
}
// Legacy default implementation that is used by old generated code, current
// versions of the plugin/generator provide this directly, but this is here
// just to avoid breaking source compatibility.
public static func ==(lhs: Self, rhs: Self) -> Bool {
return lhs._protobuf_generated_isEqualTo(other: rhs)
}
// Legacy function that is generated by old versions of the plugin/generator,
// defaulted to keep things simple without changing the api surface.
public func _protobuf_generated_isEqualTo(other: Self) -> Bool {
return self == other
}
}

View File

@ -0,0 +1,41 @@
// Sources/SwiftProtobuf/MessageExtension.swift - Extension support
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// A 'Message Extension' is an immutable class object that describes
/// a particular extension field, including string and number
/// identifiers, serialization details, and the identity of the
/// message that is being extended.
///
// -----------------------------------------------------------------------------
/// Type-erased MessageExtension field implementation.
public protocol AnyMessageExtension {
var fieldNumber: Int { get }
var fieldName: String { get }
var messageType: Message.Type { get }
func _protobuf_newField<D: Decoder>(decoder: inout D) throws -> AnyExtensionField?
}
/// A "Message Extension" relates a particular extension field to
/// a particular message. The generic constraints allow
/// compile-time compatibility checks.
public class MessageExtension<FieldType: ExtensionField, MessageType: Message>: AnyMessageExtension {
public let fieldNumber: Int
public let fieldName: String
public let messageType: Message.Type
public init(_protobuf_fieldNumber: Int, fieldName: String) {
self.fieldNumber = _protobuf_fieldNumber
self.fieldName = fieldName
self.messageType = MessageType.self
}
public func _protobuf_newField<D: Decoder>(decoder: inout D) throws -> AnyExtensionField? {
return try FieldType(protobufExtension: self, decoder: &decoder)
}
}

View File

@ -0,0 +1,310 @@
// Sources/SwiftProtobuf/NameMap.swift - Bidirectional number/name mapping
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
/// TODO: Right now, only the NameMap and the NameDescription enum
/// (which are directly used by the generated code) are public.
/// This means that code outside the library has no way to actually
/// use this data. We should develop and publicize a suitable API
/// for that purpose. (Which might be the same as the internal API.)
/// This must be exactly the same as the corresponding code in the
/// protoc-gen-swift code generator. Changing it will break
/// compatibility of the library with older generated code.
///
/// It does not necessarily need to match protoc's JSON field naming
/// logic, however.
private func toJsonFieldName(_ s: String) -> String {
var result = String()
var capitalizeNext = false
for c in s {
if c == "_" {
capitalizeNext = true
} else if capitalizeNext {
result.append(String(c).uppercased())
capitalizeNext = false
} else {
result.append(String(c))
}
}
return result
}
/// Allocate static memory buffers to intern UTF-8
/// string data. Track the buffers and release all of those buffers
/// in case we ever get deallocated.
fileprivate class InternPool {
private var interned = [UnsafeRawBufferPointer]()
func intern(utf8: String.UTF8View) -> UnsafeRawBufferPointer {
#if swift(>=4.1)
let mutable = UnsafeMutableRawBufferPointer.allocate(byteCount: utf8.count,
alignment: MemoryLayout<UInt8>.alignment)
#else
let mutable = UnsafeMutableRawBufferPointer.allocate(count: utf8.count)
#endif
mutable.copyBytes(from: utf8)
let immutable = UnsafeRawBufferPointer(mutable)
interned.append(immutable)
return immutable
}
func intern(utf8Ptr: UnsafeBufferPointer<UInt8>) -> UnsafeRawBufferPointer {
#if swift(>=4.1)
let mutable = UnsafeMutableRawBufferPointer.allocate(byteCount: utf8Ptr.count,
alignment: MemoryLayout<UInt8>.alignment)
#else
let mutable = UnsafeMutableRawBufferPointer.allocate(count: utf8.count)
#endif
mutable.copyBytes(from: utf8Ptr)
let immutable = UnsafeRawBufferPointer(mutable)
interned.append(immutable)
return immutable
}
deinit {
for buff in interned {
#if swift(>=4.1)
buff.deallocate()
#else
let p = UnsafeMutableRawPointer(mutating: buff.baseAddress)!
p.deallocate(bytes: buff.count, alignedTo: 1)
#endif
}
}
}
#if !swift(>=4.2)
// Constants for FNV hash http://tools.ietf.org/html/draft-eastlake-fnv-03
private let i_2166136261 = Int(bitPattern: 2166136261)
private let i_16777619 = Int(16777619)
#endif
/// An immutable bidirectional mapping between field/enum-case names
/// and numbers, used to record field names for text-based
/// serialization (JSON and text). These maps are lazily instantiated
/// for each message as needed, so there is no run-time overhead for
/// users who do not use text-based serialization formats.
public struct _NameMap: ExpressibleByDictionaryLiteral {
/// An immutable interned string container. The `utf8Start` pointer
/// is guaranteed valid for the lifetime of the `NameMap` that you
/// fetched it from. Since `NameMap`s are only instantiated as
/// immutable static values, that should be the lifetime of the
/// program.
///
/// Internally, this uses `StaticString` (which refers to a fixed
/// block of UTF-8 data) where possible. In cases where the string
/// has to be computed, it caches the UTF-8 bytes in an
/// unmovable and immutable heap area.
internal struct Name: Hashable, CustomStringConvertible {
// This should not be used outside of this file, as it requires
// coordinating the lifecycle with the lifecycle of the pool
// where the raw UTF8 gets interned.
fileprivate init(staticString: StaticString, pool: InternPool) {
self.nameString = .staticString(staticString)
if staticString.hasPointerRepresentation {
self.utf8Buffer = UnsafeRawBufferPointer(start: staticString.utf8Start,
count: staticString.utf8CodeUnitCount)
} else {
self.utf8Buffer = staticString.withUTF8Buffer { pool.intern(utf8Ptr: $0) }
}
}
// This should not be used outside of this file, as it requires
// coordinating the lifecycle with the lifecycle of the pool
// where the raw UTF8 gets interned.
fileprivate init(string: String, pool: InternPool) {
let utf8 = string.utf8
self.utf8Buffer = pool.intern(utf8: utf8)
self.nameString = .string(string)
}
// This is for building a transient `Name` object sufficient for lookup purposes.
// It MUST NOT be exposed outside of this file.
fileprivate init(transientUtf8Buffer: UnsafeRawBufferPointer) {
self.nameString = .staticString("")
self.utf8Buffer = transientUtf8Buffer
}
private(set) var utf8Buffer: UnsafeRawBufferPointer
private enum NameString {
case string(String)
case staticString(StaticString)
}
private var nameString: NameString
public var description: String {
switch nameString {
case .string(let s): return s
case .staticString(let s): return s.description
}
}
#if swift(>=4.2)
public func hash(into hasher: inout Hasher) {
for byte in utf8Buffer {
hasher.combine(byte)
}
}
#else // swift(>=4.2)
public var hashValue: Int {
var h = i_2166136261
for byte in utf8Buffer {
h = (h ^ Int(byte)) &* i_16777619
}
return h
}
#endif // swift(>=4.2)
public static func ==(lhs: Name, rhs: Name) -> Bool {
if lhs.utf8Buffer.count != rhs.utf8Buffer.count {
return false
}
return lhs.utf8Buffer.elementsEqual(rhs.utf8Buffer)
}
}
/// The JSON and proto names for a particular field, enum case, or extension.
internal struct Names {
private(set) var json: Name?
private(set) var proto: Name
}
/// A description of the names for a particular field or enum case.
/// The different forms here let us minimize the amount of string
/// data that we store in the binary.
///
/// These are only used in the generated code to initialize a NameMap.
public enum NameDescription {
/// The proto (text format) name and the JSON name are the same string.
case same(proto: StaticString)
/// The JSON name can be computed from the proto string
case standard(proto: StaticString)
/// The JSON and text format names are just different.
case unique(proto: StaticString, json: StaticString)
/// Used for enum cases only to represent a value's primary proto name (the
/// first defined case) and its aliases. The JSON and text format names for
/// enums are always the same.
case aliased(proto: StaticString, aliases: [StaticString])
}
private var internPool = InternPool()
/// The mapping from field/enum-case numbers to names.
private var numberToNameMap: [Int: Names] = [:]
/// The mapping from proto/text names to field/enum-case numbers.
private var protoToNumberMap: [Name: Int] = [:]
/// The mapping from JSON names to field/enum-case numbers.
/// Note that this also contains all of the proto/text names,
/// as required by Google's spec for protobuf JSON.
private var jsonToNumberMap: [Name: Int] = [:]
/// Creates a new empty field/enum-case name/number mapping.
public init() {}
/// Build the bidirectional maps between numbers and proto/JSON names.
public init(dictionaryLiteral elements: (Int, NameDescription)...) {
for (number, description) in elements {
switch description {
case .same(proto: let p):
let protoName = Name(staticString: p, pool: internPool)
let names = Names(json: protoName, proto: protoName)
numberToNameMap[number] = names
protoToNumberMap[protoName] = number
jsonToNumberMap[protoName] = number
case .standard(proto: let p):
let protoName = Name(staticString: p, pool: internPool)
let jsonString = toJsonFieldName(protoName.description)
let jsonName = Name(string: jsonString, pool: internPool)
let names = Names(json: jsonName, proto: protoName)
numberToNameMap[number] = names
protoToNumberMap[protoName] = number
jsonToNumberMap[protoName] = number
jsonToNumberMap[jsonName] = number
case .unique(proto: let p, json: let j):
let jsonName = Name(staticString: j, pool: internPool)
let protoName = Name(staticString: p, pool: internPool)
let names = Names(json: jsonName, proto: protoName)
numberToNameMap[number] = names
protoToNumberMap[protoName] = number
jsonToNumberMap[protoName] = number
jsonToNumberMap[jsonName] = number
case .aliased(proto: let p, aliases: let aliases):
let protoName = Name(staticString: p, pool: internPool)
let names = Names(json: protoName, proto: protoName)
numberToNameMap[number] = names
protoToNumberMap[protoName] = number
jsonToNumberMap[protoName] = number
for alias in aliases {
let protoName = Name(staticString: alias, pool: internPool)
protoToNumberMap[protoName] = number
jsonToNumberMap[protoName] = number
}
}
}
}
/// Returns the name bundle for the field/enum-case with the given number, or
/// `nil` if there is no match.
internal func names(for number: Int) -> Names? {
return numberToNameMap[number]
}
/// Returns the field/enum-case number that has the given JSON name,
/// or `nil` if there is no match.
///
/// This is used by the Text format parser to look up field or enum
/// names using a direct reference to the un-decoded UTF8 bytes.
internal func number(forProtoName raw: UnsafeRawBufferPointer) -> Int? {
let n = Name(transientUtf8Buffer: raw)
return protoToNumberMap[n]
}
/// Returns the field/enum-case number that has the given JSON name,
/// or `nil` if there is no match.
///
/// This accepts a regular `String` and is used in JSON parsing
/// only when a field name or enum name was decoded from a string
/// containing backslash escapes.
///
/// JSON parsing must interpret *both* the JSON name of the
/// field/enum-case provided by the descriptor *as well as* its
/// original proto/text name.
internal func number(forJSONName name: String) -> Int? {
let utf8 = Array(name.utf8)
return utf8.withUnsafeBytes { (buffer: UnsafeRawBufferPointer) in
let n = Name(transientUtf8Buffer: buffer)
return jsonToNumberMap[n]
}
}
/// Returns the field/enum-case number that has the given JSON name,
/// or `nil` if there is no match.
///
/// This is used by the JSON parser when a field name or enum name
/// required no special processing. As a result, we can avoid
/// copying the name and look up the number using a direct reference
/// to the un-decoded UTF8 bytes.
internal func number(forJSONName raw: UnsafeRawBufferPointer) -> Int? {
let n = Name(transientUtf8Buffer: raw)
return jsonToNumberMap[n]
}
}

View File

@ -0,0 +1,23 @@
// Sources/SwiftProtobuf/ProtoNameProviding.swift - Support for accessing proto names
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
/// SwiftProtobuf Internal: Common support looking up field names.
///
/// Messages conform to this protocol to provide the proto/text and JSON field
/// names for their fields. This allows these names to be pulled out into
/// extensions in separate files so that users can omit them in release builds
/// (reducing bloat and minimizing leaks of field names).
public protocol _ProtoNameProviding {
/// The mapping between field numbers and proto/JSON field names defined in
/// the conforming message type.
static var _protobuf_nameMap: _NameMap { get }
}

View File

@ -0,0 +1,43 @@
// Sources/SwiftProtobuf/ProtobufAPIVersionCheck.swift - Version checking
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// A scheme that ensures that generated protos cannot be compiled or linked
/// against a version of the runtime with which they are not compatible.
///
/// In many cases, API changes themselves might introduce incompatibilities
/// between generated code and the runtime library, but we also want to protect
/// against cases where breaking behavioral changes (without affecting the API)
/// would cause generated code to be incompatible with a particular version of
/// the runtime.
///
// -----------------------------------------------------------------------------
/// An empty protocol that encodes the version of the runtime library.
///
/// This protocol will be replaced with one containing a different version
/// number any time that breaking changes are made to the Swift Protobuf API.
/// Combined with the protocol below, this lets us verify that generated code is
/// never compiled against a version of the API with which it is incompatible.
///
/// The version associated with a particular build of the compiler is defined as
/// `Version.compatibilityVersion` in `protoc-gen-swift`. That version and this
/// version must match for the generated protos to be compatible, so if you
/// update one, make sure to update it here and in the associated type below.
public protocol ProtobufAPIVersion_2 {}
/// This protocol is expected to be implemented by a `fileprivate` type in each
/// source file emitted by `protoc-gen-swift`. It effectively creates a binding
/// between the version of the generated code and the version of this library,
/// causing a compile-time error (with reasonable diagnostics) if they are
/// incompatible.
public protocol ProtobufAPIVersionCheck {
associatedtype Version: ProtobufAPIVersion_2
}

View File

@ -0,0 +1,39 @@
// Sources/SwiftProtobuf/ProtobufMap.swift - Map<> support
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Generic type representing proto map<> fields.
///
// -----------------------------------------------------------------------------
import Foundation
/// SwiftProtobuf Internal: Support for Encoding/Decoding.
public struct _ProtobufMap<KeyType: MapKeyType, ValueType: FieldType>
{
public typealias Key = KeyType.BaseType
public typealias Value = ValueType.BaseType
public typealias BaseType = Dictionary<Key, Value>
}
/// SwiftProtobuf Internal: Support for Encoding/Decoding.
public struct _ProtobufMessageMap<KeyType: MapKeyType, ValueType: Message & Hashable>
{
public typealias Key = KeyType.BaseType
public typealias Value = ValueType
public typealias BaseType = Dictionary<Key, Value>
}
/// SwiftProtobuf Internal: Support for Encoding/Decoding.
public struct _ProtobufEnumMap<KeyType: MapKeyType, ValueType: Enum>
{
public typealias Key = KeyType.BaseType
public typealias Value = ValueType
public typealias BaseType = Dictionary<Key, Value>
}

View File

@ -0,0 +1,268 @@
// Sources/SwiftProtobuf/SelectiveVisitor.swift - Base for custom Visitors
//
// Copyright (c) 2014 - 2017 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// A base for Visitors that only expect a subset of things to called.
///
// -----------------------------------------------------------------------------
import Foundation
/// A base for Visitors that only expects a subset of things to called.
internal protocol SelectiveVisitor: Visitor {
// Adds nothing.
}
/// Default impls for everything so things using this only have to write the
/// methods they expect. Asserts to catch developer errors, but becomes
/// nothing in release to keep code size small.
///
/// NOTE: This is an impl for *everything*. This means the default impls
/// provided by Visitor to bridge packed->repeated, repeated->singular, etc
/// won't kick in.
extension SelectiveVisitor {
internal mutating func visitSingularFloatField(value: Float, fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitSingularDoubleField(value: Double, fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitSingularInt32Field(value: Int32, fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitSingularInt64Field(value: Int64, fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitSingularUInt32Field(value: UInt32, fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitSingularUInt64Field(value: UInt64, fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitSingularSInt32Field(value: Int32, fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitSingularSInt64Field(value: Int64, fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitSingularFixed32Field(value: UInt32, fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitSingularFixed64Field(value: UInt64, fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitSingularSFixed32Field(value: Int32, fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitSingularSFixed64Field(value: Int64, fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitSingularBoolField(value: Bool, fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitSingularStringField(value: String, fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitSingularBytesField(value: Data, fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitSingularEnumField<E: Enum>(value: E, fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitSingularMessageField<M: Message>(value: M, fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitSingularGroupField<G: Message>(value: G, fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitRepeatedFloatField(value: [Float], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitRepeatedDoubleField(value: [Double], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitRepeatedInt32Field(value: [Int32], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitRepeatedInt64Field(value: [Int64], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitRepeatedUInt32Field(value: [UInt32], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitRepeatedUInt64Field(value: [UInt64], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitRepeatedSInt32Field(value: [Int32], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitRepeatedSInt64Field(value: [Int64], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitRepeatedFixed32Field(value: [UInt32], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitRepeatedFixed64Field(value: [UInt64], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitRepeatedSFixed32Field(value: [Int32], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitRepeatedSFixed64Field(value: [Int64], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitRepeatedBoolField(value: [Bool], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitRepeatedStringField(value: [String], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitRepeatedBytesField(value: [Data], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitRepeatedEnumField<E: Enum>(value: [E], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitRepeatedMessageField<M: Message>(value: [M], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitRepeatedGroupField<G: Message>(value: [G], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitPackedFloatField(value: [Float], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitPackedDoubleField(value: [Double], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitPackedInt32Field(value: [Int32], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitPackedInt64Field(value: [Int64], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitPackedUInt32Field(value: [UInt32], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitPackedUInt64Field(value: [UInt64], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitPackedSInt32Field(value: [Int32], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitPackedSInt64Field(value: [Int64], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitPackedFixed32Field(value: [UInt32], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitPackedFixed64Field(value: [UInt64], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitPackedSFixed32Field(value: [Int32], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitPackedSFixed64Field(value: [Int64], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitPackedBoolField(value: [Bool], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitPackedEnumField<E: Enum>(value: [E], fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitMapField<KeyType, ValueType: MapValueType>(
fieldType: _ProtobufMap<KeyType, ValueType>.Type,
value: _ProtobufMap<KeyType, ValueType>.BaseType,
fieldNumber: Int) throws {
assert(false)
}
internal mutating func visitMapField<KeyType, ValueType>(
fieldType: _ProtobufEnumMap<KeyType, ValueType>.Type,
value: _ProtobufEnumMap<KeyType, ValueType>.BaseType,
fieldNumber: Int
) throws where ValueType.RawValue == Int {
assert(false)
}
internal mutating func visitMapField<KeyType, ValueType>(
fieldType: _ProtobufMessageMap<KeyType, ValueType>.Type,
value: _ProtobufMessageMap<KeyType, ValueType>.BaseType,
fieldNumber: Int
) throws {
assert(false)
}
internal mutating func visitExtensionFields(fields: ExtensionFieldValueSet, start: Int, end: Int) throws {
assert(false)
}
internal mutating func visitExtensionFieldsAsMessageSet(
fields: ExtensionFieldValueSet,
start: Int,
end: Int
) throws {
assert(false)
}
internal mutating func visitUnknown(bytes: Data) throws {
assert(false)
}
}

View File

@ -0,0 +1,112 @@
// Sources/SwiftProtobuf/SimpleExtensionMap.swift - Extension support
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// A default implementation of ExtensionMap.
///
// -----------------------------------------------------------------------------
// Note: The generated code only relies on ExpressibleByArrayLiteral
public struct SimpleExtensionMap: ExtensionMap, ExpressibleByArrayLiteral, CustomDebugStringConvertible {
public typealias Element = AnyMessageExtension
// Since type objects aren't Hashable, we can't do much better than this...
internal var fields = [Int: Array<AnyMessageExtension>]()
public init() {}
public init(arrayLiteral: Element...) {
insert(contentsOf: arrayLiteral)
}
public init(_ others: SimpleExtensionMap...) {
for other in others {
formUnion(other)
}
}
public subscript(messageType: Message.Type, fieldNumber: Int) -> AnyMessageExtension? {
get {
if let l = fields[fieldNumber] {
for e in l {
if messageType == e.messageType {
return e
}
}
}
return nil
}
}
public func fieldNumberForProto(messageType: Message.Type, protoFieldName: String) -> Int? {
// TODO: Make this faster...
for (_, list) in fields {
for e in list {
if e.fieldName == protoFieldName && e.messageType == messageType {
return e.fieldNumber
}
}
}
return nil
}
public mutating func insert(_ newValue: Element) {
let fieldNumber = newValue.fieldNumber
if let l = fields[fieldNumber] {
let messageType = newValue.messageType
var newL = l.filter { return $0.messageType != messageType }
newL.append(newValue)
fields[fieldNumber] = newL
} else {
fields[fieldNumber] = [newValue]
}
}
public mutating func insert(contentsOf: [Element]) {
for e in contentsOf {
insert(e)
}
}
public mutating func formUnion(_ other: SimpleExtensionMap) {
for (fieldNumber, otherList) in other.fields {
if let list = fields[fieldNumber] {
var newList = list.filter {
for o in otherList {
if $0.messageType == o.messageType { return false }
}
return true
}
newList.append(contentsOf: otherList)
fields[fieldNumber] = newList
} else {
fields[fieldNumber] = otherList
}
}
}
public func union(_ other: SimpleExtensionMap) -> SimpleExtensionMap {
var out = self
out.formUnion(other)
return out
}
public var debugDescription: String {
var names = [String]()
for (_, list) in fields {
for e in list {
names.append("\(e.fieldName):(\(e.fieldNumber))")
}
}
let d = names.joined(separator: ",")
return "SimpleExtensionMap(\(d))"
}
}

View File

@ -0,0 +1,73 @@
// Sources/SwiftProtobuf/StringUtils.swift - String utility functions
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Utility functions for converting UTF8 bytes into Strings.
/// These functions must:
/// * Accept any valid UTF8, including a zero byte (which is
/// a valid UTF8 encoding of U+0000)
/// * Return nil for any invalid UTF8
/// * Be fast (since they're extensively used by all decoders
/// and even some of the encoders)
///
// -----------------------------------------------------------------------------
import Foundation
// Wrapper that takes a buffer and start/end offsets
internal func utf8ToString(
bytes: UnsafeRawBufferPointer,
start: UnsafeRawBufferPointer.Index,
end: UnsafeRawBufferPointer.Index
) -> String? {
return utf8ToString(bytes: bytes.baseAddress! + start, count: end - start)
}
// Swift 4 introduced new faster String facilities
// that seem to work consistently across all platforms.
// Notes on performance:
//
// The pre-verification here only takes about 10% of
// the time needed for constructing the string.
// Eliminating it would provide only a very minor
// speed improvement.
//
// On macOS, this is only about 25% faster than
// the Foundation initializer used below for Swift 3.
// On Linux, the Foundation initializer is much
// slower than on macOS, so this is a much bigger
// win there.
internal func utf8ToString(bytes: UnsafeRawPointer, count: Int) -> String? {
if count == 0 {
return String()
}
let codeUnits = UnsafeRawBufferPointer(start: bytes, count: count)
let sourceEncoding = Unicode.UTF8.self
// Verify that the UTF-8 is valid.
var p = sourceEncoding.ForwardParser()
var i = codeUnits.makeIterator()
Loop:
while true {
switch p.parseScalar(from: &i) {
case .valid(_):
break
case .error:
return nil
case .emptyInput:
break Loop
}
}
// This initializer is fast but does not reject broken
// UTF-8 (which is why we validate the UTF-8 above).
return String(decoding: codeUnits, as: sourceEncoding)
}

View File

@ -0,0 +1,713 @@
// Sources/SwiftProtobuf/TextFormatDecoder.swift - Text format decoding
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Test format decoding engine.
///
// -----------------------------------------------------------------------------
import Foundation
///
/// Provides a higher-level interface to the token stream coming
/// from a TextFormatScanner. In particular, this provides
/// single-token pushback and convenience functions for iterating
/// over complex structures.
///
internal struct TextFormatDecoder: Decoder {
internal var scanner: TextFormatScanner
private var fieldCount = 0
private var terminator: UInt8?
private var fieldNameMap: _NameMap?
private var messageType: Message.Type?
internal var complete: Bool {
mutating get {
return scanner.complete
}
}
internal init(messageType: Message.Type, utf8Pointer: UnsafeRawPointer, count: Int, extensions: ExtensionMap?) throws {
scanner = TextFormatScanner(utf8Pointer: utf8Pointer, count: count, extensions: extensions)
guard let nameProviding = (messageType as? _ProtoNameProviding.Type) else {
throw TextFormatDecodingError.missingFieldNames
}
fieldNameMap = nameProviding._protobuf_nameMap
self.messageType = messageType
}
internal init(messageType: Message.Type, scanner: TextFormatScanner, terminator: UInt8?) throws {
self.scanner = scanner
self.terminator = terminator
guard let nameProviding = (messageType as? _ProtoNameProviding.Type) else {
throw TextFormatDecodingError.missingFieldNames
}
fieldNameMap = nameProviding._protobuf_nameMap
self.messageType = messageType
}
mutating func handleConflictingOneOf() throws {
throw TextFormatDecodingError.conflictingOneOf
}
mutating func nextFieldNumber() throws -> Int? {
if let terminator = terminator {
if scanner.skipOptionalObjectEnd(terminator) {
return nil
}
}
if fieldCount > 0 {
scanner.skipOptionalSeparator()
}
if let key = try scanner.nextOptionalExtensionKey() {
// Extension key; look up in the extension registry
if let fieldNumber = scanner.extensions?.fieldNumberForProto(messageType: messageType!, protoFieldName: key) {
fieldCount += 1
return fieldNumber
} else {
throw TextFormatDecodingError.unknownField
}
} else if let fieldNumber = try scanner.nextFieldNumber(names: fieldNameMap!) {
fieldCount += 1
return fieldNumber
} else if terminator == nil {
return nil
} else {
throw TextFormatDecodingError.truncated
}
}
mutating func decodeSingularFloatField(value: inout Float) throws {
try scanner.skipRequiredColon()
value = try scanner.nextFloat()
}
mutating func decodeSingularFloatField(value: inout Float?) throws {
try scanner.skipRequiredColon()
value = try scanner.nextFloat()
}
mutating func decodeRepeatedFloatField(value: inout [Float]) throws {
try scanner.skipRequiredColon()
if scanner.skipOptionalBeginArray() {
var firstItem = true
while true {
if scanner.skipOptionalEndArray() {
return
}
if firstItem {
firstItem = false
} else {
try scanner.skipRequiredComma()
}
let n = try scanner.nextFloat()
value.append(n)
}
} else {
let n = try scanner.nextFloat()
value.append(n)
}
}
mutating func decodeSingularDoubleField(value: inout Double) throws {
try scanner.skipRequiredColon()
value = try scanner.nextDouble()
}
mutating func decodeSingularDoubleField(value: inout Double?) throws {
try scanner.skipRequiredColon()
value = try scanner.nextDouble()
}
mutating func decodeRepeatedDoubleField(value: inout [Double]) throws {
try scanner.skipRequiredColon()
if scanner.skipOptionalBeginArray() {
var firstItem = true
while true {
if scanner.skipOptionalEndArray() {
return
}
if firstItem {
firstItem = false
} else {
try scanner.skipRequiredComma()
}
let n = try scanner.nextDouble()
value.append(n)
}
} else {
let n = try scanner.nextDouble()
value.append(n)
}
}
mutating func decodeSingularInt32Field(value: inout Int32) throws {
try scanner.skipRequiredColon()
let n = try scanner.nextSInt()
if n > Int64(Int32.max) || n < Int64(Int32.min) {
throw TextFormatDecodingError.malformedNumber
}
value = Int32(truncatingIfNeeded: n)
}
mutating func decodeSingularInt32Field(value: inout Int32?) throws {
try scanner.skipRequiredColon()
let n = try scanner.nextSInt()
if n > Int64(Int32.max) || n < Int64(Int32.min) {
throw TextFormatDecodingError.malformedNumber
}
value = Int32(truncatingIfNeeded: n)
}
mutating func decodeRepeatedInt32Field(value: inout [Int32]) throws {
try scanner.skipRequiredColon()
if scanner.skipOptionalBeginArray() {
var firstItem = true
while true {
if scanner.skipOptionalEndArray() {
return
}
if firstItem {
firstItem = false
} else {
try scanner.skipRequiredComma()
}
let n = try scanner.nextSInt()
if n > Int64(Int32.max) || n < Int64(Int32.min) {
throw TextFormatDecodingError.malformedNumber
}
value.append(Int32(truncatingIfNeeded: n))
}
} else {
let n = try scanner.nextSInt()
if n > Int64(Int32.max) || n < Int64(Int32.min) {
throw TextFormatDecodingError.malformedNumber
}
value.append(Int32(truncatingIfNeeded: n))
}
}
mutating func decodeSingularInt64Field(value: inout Int64) throws {
try scanner.skipRequiredColon()
value = try scanner.nextSInt()
}
mutating func decodeSingularInt64Field(value: inout Int64?) throws {
try scanner.skipRequiredColon()
value = try scanner.nextSInt()
}
mutating func decodeRepeatedInt64Field(value: inout [Int64]) throws {
try scanner.skipRequiredColon()
if scanner.skipOptionalBeginArray() {
var firstItem = true
while true {
if scanner.skipOptionalEndArray() {
return
}
if firstItem {
firstItem = false
} else {
try scanner.skipRequiredComma()
}
let n = try scanner.nextSInt()
value.append(n)
}
} else {
let n = try scanner.nextSInt()
value.append(n)
}
}
mutating func decodeSingularUInt32Field(value: inout UInt32) throws {
try scanner.skipRequiredColon()
let n = try scanner.nextUInt()
if n > UInt64(UInt32.max) {
throw TextFormatDecodingError.malformedNumber
}
value = UInt32(truncatingIfNeeded: n)
}
mutating func decodeSingularUInt32Field(value: inout UInt32?) throws {
try scanner.skipRequiredColon()
let n = try scanner.nextUInt()
if n > UInt64(UInt32.max) {
throw TextFormatDecodingError.malformedNumber
}
value = UInt32(truncatingIfNeeded: n)
}
mutating func decodeRepeatedUInt32Field(value: inout [UInt32]) throws {
try scanner.skipRequiredColon()
if scanner.skipOptionalBeginArray() {
var firstItem = true
while true {
if scanner.skipOptionalEndArray() {
return
}
if firstItem {
firstItem = false
} else {
try scanner.skipRequiredComma()
}
let n = try scanner.nextUInt()
if n > UInt64(UInt32.max) {
throw TextFormatDecodingError.malformedNumber
}
value.append(UInt32(truncatingIfNeeded: n))
}
} else {
let n = try scanner.nextUInt()
if n > UInt64(UInt32.max) {
throw TextFormatDecodingError.malformedNumber
}
value.append(UInt32(truncatingIfNeeded: n))
}
}
mutating func decodeSingularUInt64Field(value: inout UInt64) throws {
try scanner.skipRequiredColon()
value = try scanner.nextUInt()
}
mutating func decodeSingularUInt64Field(value: inout UInt64?) throws {
try scanner.skipRequiredColon()
value = try scanner.nextUInt()
}
mutating func decodeRepeatedUInt64Field(value: inout [UInt64]) throws {
try scanner.skipRequiredColon()
if scanner.skipOptionalBeginArray() {
var firstItem = true
while true {
if scanner.skipOptionalEndArray() {
return
}
if firstItem {
firstItem = false
} else {
try scanner.skipRequiredComma()
}
let n = try scanner.nextUInt()
value.append(n)
}
} else {
let n = try scanner.nextUInt()
value.append(n)
}
}
mutating func decodeSingularSInt32Field(value: inout Int32) throws {
try decodeSingularInt32Field(value: &value)
}
mutating func decodeSingularSInt32Field(value: inout Int32?) throws {
try decodeSingularInt32Field(value: &value)
}
mutating func decodeRepeatedSInt32Field(value: inout [Int32]) throws {
try decodeRepeatedInt32Field(value: &value)
}
mutating func decodeSingularSInt64Field(value: inout Int64) throws {
try decodeSingularInt64Field(value: &value)
}
mutating func decodeSingularSInt64Field(value: inout Int64?) throws {
try decodeSingularInt64Field(value: &value)
}
mutating func decodeRepeatedSInt64Field(value: inout [Int64]) throws {
try decodeRepeatedInt64Field(value: &value)
}
mutating func decodeSingularFixed32Field(value: inout UInt32) throws {
try decodeSingularUInt32Field(value: &value)
}
mutating func decodeSingularFixed32Field(value: inout UInt32?) throws {
try decodeSingularUInt32Field(value: &value)
}
mutating func decodeRepeatedFixed32Field(value: inout [UInt32]) throws {
try decodeRepeatedUInt32Field(value: &value)
}
mutating func decodeSingularFixed64Field(value: inout UInt64) throws {
try decodeSingularUInt64Field(value: &value)
}
mutating func decodeSingularFixed64Field(value: inout UInt64?) throws {
try decodeSingularUInt64Field(value: &value)
}
mutating func decodeRepeatedFixed64Field(value: inout [UInt64]) throws {
try decodeRepeatedUInt64Field(value: &value)
}
mutating func decodeSingularSFixed32Field(value: inout Int32) throws {
try decodeSingularInt32Field(value: &value)
}
mutating func decodeSingularSFixed32Field(value: inout Int32?) throws {
try decodeSingularInt32Field(value: &value)
}
mutating func decodeRepeatedSFixed32Field(value: inout [Int32]) throws {
try decodeRepeatedInt32Field(value: &value)
}
mutating func decodeSingularSFixed64Field(value: inout Int64) throws {
try decodeSingularInt64Field(value: &value)
}
mutating func decodeSingularSFixed64Field(value: inout Int64?) throws {
try decodeSingularInt64Field(value: &value)
}
mutating func decodeRepeatedSFixed64Field(value: inout [Int64]) throws {
try decodeRepeatedInt64Field(value: &value)
}
mutating func decodeSingularBoolField(value: inout Bool) throws {
try scanner.skipRequiredColon()
value = try scanner.nextBool()
}
mutating func decodeSingularBoolField(value: inout Bool?) throws {
try scanner.skipRequiredColon()
value = try scanner.nextBool()
}
mutating func decodeRepeatedBoolField(value: inout [Bool]) throws {
try scanner.skipRequiredColon()
if scanner.skipOptionalBeginArray() {
var firstItem = true
while true {
if scanner.skipOptionalEndArray() {
return
}
if firstItem {
firstItem = false
} else {
try scanner.skipRequiredComma()
}
let n = try scanner.nextBool()
value.append(n)
}
} else {
let n = try scanner.nextBool()
value.append(n)
}
}
mutating func decodeSingularStringField(value: inout String) throws {
try scanner.skipRequiredColon()
value = try scanner.nextStringValue()
}
mutating func decodeSingularStringField(value: inout String?) throws {
try scanner.skipRequiredColon()
value = try scanner.nextStringValue()
}
mutating func decodeRepeatedStringField(value: inout [String]) throws {
try scanner.skipRequiredColon()
if scanner.skipOptionalBeginArray() {
var firstItem = true
while true {
if scanner.skipOptionalEndArray() {
return
}
if firstItem {
firstItem = false
} else {
try scanner.skipRequiredComma()
}
let n = try scanner.nextStringValue()
value.append(n)
}
} else {
let n = try scanner.nextStringValue()
value.append(n)
}
}
mutating func decodeSingularBytesField(value: inout Data) throws {
try scanner.skipRequiredColon()
value = try scanner.nextBytesValue()
}
mutating func decodeSingularBytesField(value: inout Data?) throws {
try scanner.skipRequiredColon()
value = try scanner.nextBytesValue()
}
mutating func decodeRepeatedBytesField(value: inout [Data]) throws {
try scanner.skipRequiredColon()
if scanner.skipOptionalBeginArray() {
var firstItem = true
while true {
if scanner.skipOptionalEndArray() {
return
}
if firstItem {
firstItem = false
} else {
try scanner.skipRequiredComma()
}
let n = try scanner.nextBytesValue()
value.append(n)
}
} else {
let n = try scanner.nextBytesValue()
value.append(n)
}
}
private mutating func decodeEnum<E: Enum>() throws -> E where E.RawValue == Int {
if let name = try scanner.nextOptionalEnumName() {
if let b = E(rawUTF8: name) {
return b
} else {
throw TextFormatDecodingError.unrecognizedEnumValue
}
}
let number = try scanner.nextSInt()
if number >= Int64(Int32.min) && number <= Int64(Int32.max) {
let n = Int32(truncatingIfNeeded: number)
if let e = E(rawValue: Int(n)) {
return e
} else {
throw TextFormatDecodingError.unrecognizedEnumValue
}
}
throw TextFormatDecodingError.malformedText
}
mutating func decodeSingularEnumField<E: Enum>(value: inout E?) throws where E.RawValue == Int {
try scanner.skipRequiredColon()
let e: E = try decodeEnum()
value = e
}
mutating func decodeSingularEnumField<E: Enum>(value: inout E) throws where E.RawValue == Int {
try scanner.skipRequiredColon()
let e: E = try decodeEnum()
value = e
}
mutating func decodeRepeatedEnumField<E: Enum>(value: inout [E]) throws where E.RawValue == Int {
try scanner.skipRequiredColon()
if scanner.skipOptionalBeginArray() {
var firstItem = true
while true {
if scanner.skipOptionalEndArray() {
return
}
if firstItem {
firstItem = false
} else {
try scanner.skipRequiredComma()
}
let e: E = try decodeEnum()
value.append(e)
}
} else {
let e: E = try decodeEnum()
value.append(e)
}
}
mutating func decodeSingularMessageField<M: Message>(value: inout M?) throws {
_ = scanner.skipOptionalColon()
if value == nil {
value = M()
}
let terminator = try scanner.skipObjectStart()
var subDecoder = try TextFormatDecoder(messageType: M.self,scanner: scanner, terminator: terminator)
if M.self == Google_Protobuf_Any.self {
var any = value as! Google_Protobuf_Any?
try any!.decodeTextFormat(decoder: &subDecoder)
value = any as! M?
} else {
try value!.decodeMessage(decoder: &subDecoder)
}
scanner = subDecoder.scanner
}
mutating func decodeRepeatedMessageField<M: Message>(value: inout [M]) throws {
_ = scanner.skipOptionalColon()
if scanner.skipOptionalBeginArray() {
var firstItem = true
while true {
if scanner.skipOptionalEndArray() {
return
}
if firstItem {
firstItem = false
} else {
try scanner.skipRequiredComma()
}
let terminator = try scanner.skipObjectStart()
var subDecoder = try TextFormatDecoder(messageType: M.self,scanner: scanner, terminator: terminator)
if M.self == Google_Protobuf_Any.self {
var message = Google_Protobuf_Any()
try message.decodeTextFormat(decoder: &subDecoder)
value.append(message as! M)
} else {
var message = M()
try message.decodeMessage(decoder: &subDecoder)
value.append(message)
}
scanner = subDecoder.scanner
}
} else {
let terminator = try scanner.skipObjectStart()
var subDecoder = try TextFormatDecoder(messageType: M.self,scanner: scanner, terminator: terminator)
if M.self == Google_Protobuf_Any.self {
var message = Google_Protobuf_Any()
try message.decodeTextFormat(decoder: &subDecoder)
value.append(message as! M)
} else {
var message = M()
try message.decodeMessage(decoder: &subDecoder)
value.append(message)
}
scanner = subDecoder.scanner
}
}
mutating func decodeSingularGroupField<G: Message>(value: inout G?) throws {
try decodeSingularMessageField(value: &value)
}
mutating func decodeRepeatedGroupField<G: Message>(value: inout [G]) throws {
try decodeRepeatedMessageField(value: &value)
}
private mutating func decodeMapEntry<KeyType, ValueType: MapValueType>(mapType: _ProtobufMap<KeyType, ValueType>.Type, value: inout _ProtobufMap<KeyType, ValueType>.BaseType) throws {
var keyField: KeyType.BaseType?
var valueField: ValueType.BaseType?
let terminator = try scanner.skipObjectStart()
while true {
if scanner.skipOptionalObjectEnd(terminator) {
if let keyField = keyField, let valueField = valueField {
value[keyField] = valueField
return
} else {
throw TextFormatDecodingError.malformedText
}
}
if let key = try scanner.nextKey() {
switch key {
case "key", "1":
try KeyType.decodeSingular(value: &keyField, from: &self)
case "value", "2":
try ValueType.decodeSingular(value: &valueField, from: &self)
default:
throw TextFormatDecodingError.unknownField
}
scanner.skipOptionalSeparator()
}
}
}
mutating func decodeMapField<KeyType, ValueType: MapValueType>(fieldType: _ProtobufMap<KeyType, ValueType>.Type, value: inout _ProtobufMap<KeyType, ValueType>.BaseType) throws {
_ = scanner.skipOptionalColon()
if scanner.skipOptionalBeginArray() {
var firstItem = true
while true {
if scanner.skipOptionalEndArray() {
return
}
if firstItem {
firstItem = false
} else {
try scanner.skipRequiredComma()
}
try decodeMapEntry(mapType: fieldType, value: &value)
}
} else {
try decodeMapEntry(mapType: fieldType, value: &value)
}
}
private mutating func decodeMapEntry<KeyType, ValueType>(mapType: _ProtobufEnumMap<KeyType, ValueType>.Type, value: inout _ProtobufEnumMap<KeyType, ValueType>.BaseType) throws where ValueType.RawValue == Int {
var keyField: KeyType.BaseType?
var valueField: ValueType?
let terminator = try scanner.skipObjectStart()
while true {
if scanner.skipOptionalObjectEnd(terminator) {
if let keyField = keyField, let valueField = valueField {
value[keyField] = valueField
return
} else {
throw TextFormatDecodingError.malformedText
}
}
if let key = try scanner.nextKey() {
switch key {
case "key", "1":
try KeyType.decodeSingular(value: &keyField, from: &self)
case "value", "2":
try decodeSingularEnumField(value: &valueField)
default:
throw TextFormatDecodingError.unknownField
}
scanner.skipOptionalSeparator()
}
}
}
mutating func decodeMapField<KeyType, ValueType>(fieldType: _ProtobufEnumMap<KeyType, ValueType>.Type, value: inout _ProtobufEnumMap<KeyType, ValueType>.BaseType) throws where ValueType.RawValue == Int {
_ = scanner.skipOptionalColon()
if scanner.skipOptionalBeginArray() {
var firstItem = true
while true {
if scanner.skipOptionalEndArray() {
return
}
if firstItem {
firstItem = false
} else {
try scanner.skipRequiredComma()
}
try decodeMapEntry(mapType: fieldType, value: &value)
}
} else {
try decodeMapEntry(mapType: fieldType, value: &value)
}
}
private mutating func decodeMapEntry<KeyType, ValueType>(mapType: _ProtobufMessageMap<KeyType, ValueType>.Type, value: inout _ProtobufMessageMap<KeyType, ValueType>.BaseType) throws {
var keyField: KeyType.BaseType?
var valueField: ValueType?
let terminator = try scanner.skipObjectStart()
while true {
if scanner.skipOptionalObjectEnd(terminator) {
if let keyField = keyField, let valueField = valueField {
value[keyField] = valueField
return
} else {
throw TextFormatDecodingError.malformedText
}
}
if let key = try scanner.nextKey() {
switch key {
case "key", "1":
try KeyType.decodeSingular(value: &keyField, from: &self)
case "value", "2":
try decodeSingularMessageField(value: &valueField)
default:
throw TextFormatDecodingError.unknownField
}
scanner.skipOptionalSeparator()
}
}
}
mutating func decodeMapField<KeyType, ValueType>(fieldType: _ProtobufMessageMap<KeyType, ValueType>.Type, value: inout _ProtobufMessageMap<KeyType, ValueType>.BaseType) throws {
_ = scanner.skipOptionalColon()
if scanner.skipOptionalBeginArray() {
var firstItem = true
while true {
if scanner.skipOptionalEndArray() {
return
}
if firstItem {
firstItem = false
} else {
try scanner.skipRequiredComma()
}
try decodeMapEntry(mapType: fieldType, value: &value)
}
} else {
try decodeMapEntry(mapType: fieldType, value: &value)
}
}
mutating func decodeExtensionField(values: inout ExtensionFieldValueSet, messageType: Message.Type, fieldNumber: Int) throws {
if let ext = scanner.extensions?[messageType, fieldNumber] {
var fieldValue = values[fieldNumber]
if fieldValue != nil {
try fieldValue!.decodeExtensionField(decoder: &self)
} else {
fieldValue = try ext._protobuf_newField(decoder: &self)
}
if fieldValue != nil {
values[fieldNumber] = fieldValue
} else {
// Really things should never get here, for TextFormat, decoding
// the value should always work or throw an error. This specific
// error result is to allow this to be more detectable.
throw TextFormatDecodingError.internalExtensionError
}
}
}
}

View File

@ -0,0 +1,40 @@
// Sources/SwiftProtobuf/TextFormatDecodingError.swift - Protobuf text format decoding errors
//
// Copyright (c) 2014 - 2017 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Protobuf text format decoding errors
///
// -----------------------------------------------------------------------------
public enum TextFormatDecodingError: Error {
/// Text data could not be parsed
case malformedText
/// A number could not be parsed
case malformedNumber
/// Extraneous data remained after decoding should have been complete
case trailingGarbage
/// The data stopped before we expected
case truncated
/// A string was not valid UTF8
case invalidUTF8
/// The data being parsed does not match the type specified in the proto file
case schemaMismatch
/// Field names were not compiled into the binary
case missingFieldNames
/// A field identifier (name or number) was not found on the message
case unknownField
/// The enum value was not recognized
case unrecognizedEnumValue
/// Text format rejects conflicting values for the same oneof field
case conflictingOneOf
/// An internal error happened while decoding. If this is ever encountered,
/// please file an issue with SwiftProtobuf with as much details as possible
/// for what happened (proto definitions, bytes being decoded (if possible)).
case internalExtensionError
}

View File

@ -0,0 +1,296 @@
// Sources/SwiftProtobuf/TextFormatEncoder.swift - Text format encoding support
//
// Copyright (c) 2014 - 2019 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Text format serialization engine.
///
// -----------------------------------------------------------------------------
import Foundation
private let asciiSpace = UInt8(ascii: " ")
private let asciiColon = UInt8(ascii: ":")
private let asciiComma = UInt8(ascii: ",")
private let asciiMinus = UInt8(ascii: "-")
private let asciiBackslash = UInt8(ascii: "\\")
private let asciiDoubleQuote = UInt8(ascii: "\"")
private let asciiZero = UInt8(ascii: "0")
private let asciiOpenCurlyBracket = UInt8(ascii: "{")
private let asciiCloseCurlyBracket = UInt8(ascii: "}")
private let asciiOpenSquareBracket = UInt8(ascii: "[")
private let asciiCloseSquareBracket = UInt8(ascii: "]")
private let asciiNewline = UInt8(ascii: "\n")
private let asciiUpperA = UInt8(ascii: "A")
private let tabSize = 2
private let tab = [UInt8](repeating: asciiSpace, count: tabSize)
/// TextFormatEncoder has no public members.
internal struct TextFormatEncoder {
private var data = [UInt8]()
private var indentString: [UInt8] = []
var stringResult: String {
get {
return String(bytes: data, encoding: String.Encoding.utf8)!
}
}
internal mutating func append(staticText: StaticString) {
let buff = UnsafeBufferPointer(start: staticText.utf8Start, count: staticText.utf8CodeUnitCount)
data.append(contentsOf: buff)
}
internal mutating func append(name: _NameMap.Name) {
data.append(contentsOf: name.utf8Buffer)
}
internal mutating func append(bytes: [UInt8]) {
data.append(contentsOf: bytes)
}
private mutating func append(text: String) {
data.append(contentsOf: text.utf8)
}
init() {}
internal mutating func indent() {
data.append(contentsOf: indentString)
}
mutating func emitFieldName(name: UnsafeRawBufferPointer) {
indent()
data.append(contentsOf: name)
}
mutating func emitFieldName(name: StaticString) {
let buff = UnsafeRawBufferPointer(start: name.utf8Start, count: name.utf8CodeUnitCount)
emitFieldName(name: buff)
}
mutating func emitFieldName(name: [UInt8]) {
indent()
data.append(contentsOf: name)
}
mutating func emitExtensionFieldName(name: String) {
indent()
data.append(asciiOpenSquareBracket)
append(text: name)
data.append(asciiCloseSquareBracket)
}
mutating func emitFieldNumber(number: Int) {
indent()
appendUInt(value: UInt64(number))
}
mutating func startRegularField() {
append(staticText: ": ")
}
mutating func endRegularField() {
data.append(asciiNewline)
}
// In Text format, a message-valued field writes the name
// without a trailing colon:
// name_of_field {key: value key2: value2}
mutating func startMessageField() {
append(staticText: " {\n")
indentString.append(contentsOf: tab)
}
mutating func endMessageField() {
indentString.removeLast(tabSize)
indent()
append(staticText: "}\n")
}
mutating func startArray() {
data.append(asciiOpenSquareBracket)
}
mutating func arraySeparator() {
append(staticText: ", ")
}
mutating func endArray() {
data.append(asciiCloseSquareBracket)
}
mutating func putEnumValue<E: Enum>(value: E) {
if let name = value.name {
data.append(contentsOf: name.utf8Buffer)
} else {
appendInt(value: Int64(value.rawValue))
}
}
mutating func putFloatValue(value: Float) {
if value.isNaN {
append(staticText: "nan")
} else if !value.isFinite {
if value < 0 {
append(staticText: "-inf")
} else {
append(staticText: "inf")
}
} else {
data.append(contentsOf: value.debugDescription.utf8)
}
}
mutating func putDoubleValue(value: Double) {
if value.isNaN {
append(staticText: "nan")
} else if !value.isFinite {
if value < 0 {
append(staticText: "-inf")
} else {
append(staticText: "inf")
}
} else {
data.append(contentsOf: value.debugDescription.utf8)
}
}
private mutating func appendUInt(value: UInt64) {
if value >= 1000 {
appendUInt(value: value / 1000)
}
if value >= 100 {
data.append(asciiZero + UInt8((value / 100) % 10))
}
if value >= 10 {
data.append(asciiZero + UInt8((value / 10) % 10))
}
data.append(asciiZero + UInt8(value % 10))
}
private mutating func appendInt(value: Int64) {
if value < 0 {
data.append(asciiMinus)
// This is the twos-complement negation of value,
// computed in a way that won't overflow a 64-bit
// signed integer.
appendUInt(value: 1 + ~UInt64(bitPattern: value))
} else {
appendUInt(value: UInt64(bitPattern: value))
}
}
mutating func putInt64(value: Int64) {
appendInt(value: value)
}
mutating func putUInt64(value: UInt64) {
appendUInt(value: value)
}
mutating func appendUIntHex(value: UInt64, digits: Int) {
if digits == 0 {
append(staticText: "0x")
} else {
appendUIntHex(value: value >> 4, digits: digits - 1)
let d = UInt8(truncatingIfNeeded: value % 16)
data.append(d < 10 ? asciiZero + d : asciiUpperA + d - 10)
}
}
mutating func putUInt64Hex(value: UInt64, digits: Int) {
appendUIntHex(value: value, digits: digits)
}
mutating func putBoolValue(value: Bool) {
append(staticText: value ? "true" : "false")
}
mutating func putStringValue(value: String) {
data.append(asciiDoubleQuote)
for c in value.unicodeScalars {
switch c.value {
// Special two-byte escapes
case 8:
append(staticText: "\\b")
case 9:
append(staticText: "\\t")
case 10:
append(staticText: "\\n")
case 11:
append(staticText: "\\v")
case 12:
append(staticText: "\\f")
case 13:
append(staticText: "\\r")
case 34:
append(staticText: "\\\"")
case 92:
append(staticText: "\\\\")
case 0...31, 127: // Octal form for C0 control chars
data.append(asciiBackslash)
data.append(asciiZero + UInt8(c.value / 64))
data.append(asciiZero + UInt8(c.value / 8 % 8))
data.append(asciiZero + UInt8(c.value % 8))
case 0...127: // ASCII
data.append(UInt8(truncatingIfNeeded: c.value))
case 0x80...0x7ff:
data.append(0xc0 + UInt8(c.value / 64))
data.append(0x80 + UInt8(c.value % 64))
case 0x800...0xffff:
data.append(0xe0 + UInt8(truncatingIfNeeded: c.value >> 12))
data.append(0x80 + UInt8(truncatingIfNeeded: (c.value >> 6) & 0x3f))
data.append(0x80 + UInt8(truncatingIfNeeded: c.value & 0x3f))
default:
data.append(0xf0 + UInt8(truncatingIfNeeded: c.value >> 18))
data.append(0x80 + UInt8(truncatingIfNeeded: (c.value >> 12) & 0x3f))
data.append(0x80 + UInt8(truncatingIfNeeded: (c.value >> 6) & 0x3f))
data.append(0x80 + UInt8(truncatingIfNeeded: c.value & 0x3f))
}
}
data.append(asciiDoubleQuote)
}
mutating func putBytesValue(value: Data) {
data.append(asciiDoubleQuote)
value.withUnsafeBytes { (body: UnsafeRawBufferPointer) in
if let p = body.baseAddress, body.count > 0 {
for i in 0..<body.count {
let c = p[i]
switch c {
// Special two-byte escapes
case 8:
append(staticText: "\\b")
case 9:
append(staticText: "\\t")
case 10:
append(staticText: "\\n")
case 11:
append(staticText: "\\v")
case 12:
append(staticText: "\\f")
case 13:
append(staticText: "\\r")
case 34:
append(staticText: "\\\"")
case 92:
append(staticText: "\\\\")
case 32...126: // printable ASCII
data.append(c)
default: // Octal form for non-printable chars
data.append(asciiBackslash)
data.append(asciiZero + UInt8(c / 64))
data.append(asciiZero + UInt8(c / 8 % 8))
data.append(asciiZero + UInt8(c % 8))
}
}
}
}
data.append(asciiDoubleQuote)
}
}

View File

@ -0,0 +1,22 @@
// Sources/SwiftProtobuf/TextFormatEncodingOptions.swift - Text format encoding options
//
// Copyright (c) 2014 - 2019 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Text format encoding options
///
// -----------------------------------------------------------------------------
/// Options for TextFormatEncoding.
public struct TextFormatEncodingOptions {
/// Default: Do print unknown fields using numeric notation
public var printUnknownFields: Bool = true
public init() {}
}

View File

@ -0,0 +1,661 @@
// Sources/SwiftProtobuf/TextFormatEncodingVisitor.swift - Text format encoding support
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Text format serialization engine.
///
// -----------------------------------------------------------------------------
import Foundation
private let mapNameResolver: [Int:StaticString] = [1: "key", 2: "value"]
/// Visitor that serializes a message into protobuf text format.
internal struct TextFormatEncodingVisitor: Visitor {
private var encoder: TextFormatEncoder
private var nameMap: _NameMap?
private var nameResolver: [Int:StaticString]
private var extensions: ExtensionFieldValueSet?
private let options: TextFormatEncodingOptions
/// The protobuf text produced by the visitor.
var result: String {
return encoder.stringResult
}
/// Creates a new visitor that serializes the given message to protobuf text
/// format.
init(message: Message, options: TextFormatEncodingOptions) {
self.init(message: message, encoder: TextFormatEncoder(), options: options)
}
/// Creates a new visitor that serializes the given message to protobuf text
/// format, using an existing encoder.
private init(message: Message, encoder: TextFormatEncoder, options: TextFormatEncodingOptions) {
let nameMap: _NameMap?
if let nameProviding = message as? _ProtoNameProviding {
nameMap = type(of: nameProviding)._protobuf_nameMap
} else {
nameMap = nil
}
let extensions = (message as? ExtensibleMessage)?._protobuf_extensionFieldValues
self.init(nameMap: nameMap, nameResolver: [:], extensions: extensions, encoder: encoder, options: options)
}
private init(
nameMap: _NameMap?,
nameResolver: [Int:StaticString],
extensions: ExtensionFieldValueSet?,
encoder: TextFormatEncoder,
options: TextFormatEncodingOptions
) {
self.nameMap = nameMap
self.nameResolver = nameResolver
self.extensions = extensions
self.encoder = encoder
self.options = options
}
// TODO: This largely duplicates emitFieldName() below.
// But, it's slower so we don't want to just have emitFieldName() use
// formatFieldName(). Also, we need to measure whether the optimization
// this provides to repeated fields is worth the effort; consider just
// removing this and having repeated fields just re-run emitFieldName()
// for each item.
private func formatFieldName(lookingUp fieldNumber: Int) -> [UInt8] {
var bytes = [UInt8]()
if let protoName = nameMap?.names(for: fieldNumber)?.proto {
bytes.append(contentsOf: protoName.utf8Buffer)
} else if let protoName = nameResolver[fieldNumber] {
let buff = UnsafeBufferPointer(start: protoName.utf8Start, count: protoName.utf8CodeUnitCount)
bytes.append(contentsOf: buff)
} else if let extensionName = extensions?[fieldNumber]?.protobufExtension.fieldName {
bytes.append(UInt8(ascii: "["))
bytes.append(contentsOf: extensionName.utf8)
bytes.append(UInt8(ascii: "]"))
} else {
bytes.append(contentsOf: fieldNumber.description.utf8)
}
return bytes
}
private mutating func emitFieldName(lookingUp fieldNumber: Int) {
if let protoName = nameMap?.names(for: fieldNumber)?.proto {
encoder.emitFieldName(name: protoName.utf8Buffer)
} else if let protoName = nameResolver[fieldNumber] {
encoder.emitFieldName(name: protoName)
} else if let extensionName = extensions?[fieldNumber]?.protobufExtension.fieldName {
encoder.emitExtensionFieldName(name: extensionName)
} else {
encoder.emitFieldNumber(number: fieldNumber)
}
}
mutating func visitUnknown(bytes: Data) throws {
if options.printUnknownFields {
try bytes.withUnsafeBytes { (body: UnsafeRawBufferPointer) -> () in
if let baseAddress = body.baseAddress, body.count > 0 {
// All fields will be directly handled, so there is no need for
// the unknown field buffering/collection (when scannings to see
// if something is a message, this would be extremely wasteful).
var binaryOptions = BinaryDecodingOptions()
binaryOptions.discardUnknownFields = true
var decoder = BinaryDecoder(forReadingFrom: baseAddress,
count: body.count,
options: binaryOptions)
try visitUnknown(decoder: &decoder)
}
}
}
}
/// Helper for printing out unknowns.
///
/// The implementation tries to be "helpful" and if a length delimited field
/// appears to be a submessage, it prints it as such. However, that opens the
/// door to someone sending a message with an unknown field that is a stack
/// bomb, i.e. - it causes this code to recurse, exhausing the stack and
/// thus opening up an attack vector. To keep this "help", but avoid the
/// attack, a limit is placed on how many times it will recurse before just
/// treating the length delimted fields as bytes and not trying to decode
/// them.
private mutating func visitUnknown(
decoder: inout BinaryDecoder,
recursionBudget: Int = 10
) throws {
// This stack serves to avoid recursion for groups within groups within
// groups..., this avoid the stack attack that the message detection
// hits. No limit is placed on this because there is no stack risk with
// recursion, and because if a limit was hit, there is no other way to
// encode the group (the message field can just print as length
// delimited, groups don't have an option like that).
var groupFieldNumberStack: [Int] = []
while let tag = try decoder.getTag() {
switch tag.wireFormat {
case .varint:
encoder.emitFieldNumber(number: tag.fieldNumber)
var value: UInt64 = 0
encoder.startRegularField()
try decoder.decodeSingularUInt64Field(value: &value)
encoder.putUInt64(value: value)
encoder.endRegularField()
case .fixed64:
encoder.emitFieldNumber(number: tag.fieldNumber)
var value: UInt64 = 0
encoder.startRegularField()
try decoder.decodeSingularFixed64Field(value: &value)
encoder.putUInt64Hex(value: value, digits: 16)
encoder.endRegularField()
case .lengthDelimited:
encoder.emitFieldNumber(number: tag.fieldNumber)
var bytes = Data()
try decoder.decodeSingularBytesField(value: &bytes)
bytes.withUnsafeBytes { (body: UnsafeRawBufferPointer) -> () in
if let baseAddress = body.baseAddress, body.count > 0 {
var encodeAsBytes: Bool
if (recursionBudget > 0) {
do {
// Walk all the fields to test if it looks like a message
var testDecoder = BinaryDecoder(forReadingFrom: baseAddress,
count: body.count,
parent: decoder)
while let _ = try testDecoder.nextFieldNumber() {
}
// No error? Output the message body.
encodeAsBytes = false
var subDecoder = BinaryDecoder(forReadingFrom: baseAddress,
count: bytes.count,
parent: decoder)
encoder.startMessageField()
try visitUnknown(decoder: &subDecoder,
recursionBudget: recursionBudget - 1)
encoder.endMessageField()
} catch {
encodeAsBytes = true
}
} else {
encodeAsBytes = true
}
if (encodeAsBytes) {
encoder.startRegularField()
encoder.putBytesValue(value: bytes)
encoder.endRegularField()
}
}
}
case .startGroup:
encoder.emitFieldNumber(number: tag.fieldNumber)
encoder.startMessageField()
groupFieldNumberStack.append(tag.fieldNumber)
case .endGroup:
let groupFieldNumber = groupFieldNumberStack.popLast()
// Unknown data is scanned and verified by the
// binary parser, so this can never fail.
assert(tag.fieldNumber == groupFieldNumber)
encoder.endMessageField()
case .fixed32:
encoder.emitFieldNumber(number: tag.fieldNumber)
var value: UInt32 = 0
encoder.startRegularField()
try decoder.decodeSingularFixed32Field(value: &value)
encoder.putUInt64Hex(value: UInt64(value), digits: 8)
encoder.endRegularField()
}
}
// Unknown data is scanned and verified by the binary parser, so this can
// never fail.
assert(groupFieldNumberStack.isEmpty)
}
// Visitor.swift defines default versions for other singular field types
// that simply widen and dispatch to one of the following. Since Text format
// does not distinguish e.g., Fixed64 vs. UInt64, this is sufficient.
mutating func visitSingularFloatField(value: Float, fieldNumber: Int) throws {
emitFieldName(lookingUp: fieldNumber)
encoder.startRegularField()
encoder.putFloatValue(value: value)
encoder.endRegularField()
}
mutating func visitSingularDoubleField(value: Double, fieldNumber: Int) throws {
emitFieldName(lookingUp: fieldNumber)
encoder.startRegularField()
encoder.putDoubleValue(value: value)
encoder.endRegularField()
}
mutating func visitSingularInt64Field(value: Int64, fieldNumber: Int) throws {
emitFieldName(lookingUp: fieldNumber)
encoder.startRegularField()
encoder.putInt64(value: value)
encoder.endRegularField()
}
mutating func visitSingularUInt64Field(value: UInt64, fieldNumber: Int) throws {
emitFieldName(lookingUp: fieldNumber)
encoder.startRegularField()
encoder.putUInt64(value: value)
encoder.endRegularField()
}
mutating func visitSingularBoolField(value: Bool, fieldNumber: Int) throws {
emitFieldName(lookingUp: fieldNumber)
encoder.startRegularField()
encoder.putBoolValue(value: value)
encoder.endRegularField()
}
mutating func visitSingularStringField(value: String, fieldNumber: Int) throws {
emitFieldName(lookingUp: fieldNumber)
encoder.startRegularField()
encoder.putStringValue(value: value)
encoder.endRegularField()
}
mutating func visitSingularBytesField(value: Data, fieldNumber: Int) throws {
emitFieldName(lookingUp: fieldNumber)
encoder.startRegularField()
encoder.putBytesValue(value: value)
encoder.endRegularField()
}
mutating func visitSingularEnumField<E: Enum>(value: E, fieldNumber: Int) throws {
emitFieldName(lookingUp: fieldNumber)
encoder.startRegularField()
encoder.putEnumValue(value: value)
encoder.endRegularField()
}
mutating func visitSingularMessageField<M: Message>(value: M,
fieldNumber: Int) throws {
emitFieldName(lookingUp: fieldNumber)
// Cache old encoder state
let oldNameMap = self.nameMap
let oldNameResolver = self.nameResolver
let oldExtensions = self.extensions
// Update encoding state for new message
self.nameMap = (M.self as? _ProtoNameProviding.Type)?._protobuf_nameMap
self.nameResolver = [:]
self.extensions = (value as? ExtensibleMessage)?._protobuf_extensionFieldValues
// Restore state before returning
defer {
self.extensions = oldExtensions
self.nameResolver = oldNameResolver
self.nameMap = oldNameMap
}
// Encode submessage
encoder.startMessageField()
if let any = value as? Google_Protobuf_Any {
any.textTraverse(visitor: &self)
} else {
try! value.traverse(visitor: &self)
}
encoder.endMessageField()
}
// Emit the full "verbose" form of an Any. This writes the typeURL
// as a field name in `[...]` followed by the fields of the
// contained message.
internal mutating func visitAnyVerbose(value: Message, typeURL: String) {
encoder.emitExtensionFieldName(name: typeURL)
encoder.startMessageField()
var visitor = TextFormatEncodingVisitor(message: value, encoder: encoder, options: options)
if let any = value as? Google_Protobuf_Any {
any.textTraverse(visitor: &visitor)
} else {
try! value.traverse(visitor: &visitor)
}
encoder = visitor.encoder
encoder.endMessageField()
}
// Write a single special field called "#json". This
// is used for Any objects with undecoded JSON contents.
internal mutating func visitAnyJSONDataField(value: Data) {
encoder.indent()
encoder.append(staticText: "#json: ")
encoder.putBytesValue(value: value)
encoder.append(staticText: "\n")
}
// The default implementations in Visitor.swift provide the correct
// results, but we get significantly better performance by only doing
// the name lookup once for the array, rather than once for each element:
mutating func visitRepeatedFloatField(value: [Float], fieldNumber: Int) throws {
assert(!value.isEmpty)
let fieldName = formatFieldName(lookingUp: fieldNumber)
for v in value {
encoder.emitFieldName(name: fieldName)
encoder.startRegularField()
encoder.putFloatValue(value: v)
encoder.endRegularField()
}
}
mutating func visitRepeatedDoubleField(value: [Double], fieldNumber: Int) throws {
assert(!value.isEmpty)
let fieldName = formatFieldName(lookingUp: fieldNumber)
for v in value {
encoder.emitFieldName(name: fieldName)
encoder.startRegularField()
encoder.putDoubleValue(value: v)
encoder.endRegularField()
}
}
mutating func visitRepeatedInt32Field(value: [Int32], fieldNumber: Int) throws {
assert(!value.isEmpty)
let fieldName = formatFieldName(lookingUp: fieldNumber)
for v in value {
encoder.emitFieldName(name: fieldName)
encoder.startRegularField()
encoder.putInt64(value: Int64(v))
encoder.endRegularField()
}
}
mutating func visitRepeatedInt64Field(value: [Int64], fieldNumber: Int) throws {
assert(!value.isEmpty)
let fieldName = formatFieldName(lookingUp: fieldNumber)
for v in value {
encoder.emitFieldName(name: fieldName)
encoder.startRegularField()
encoder.putInt64(value: v)
encoder.endRegularField()
}
}
mutating func visitRepeatedUInt32Field(value: [UInt32], fieldNumber: Int) throws {
assert(!value.isEmpty)
let fieldName = formatFieldName(lookingUp: fieldNumber)
for v in value {
encoder.emitFieldName(name: fieldName)
encoder.startRegularField()
encoder.putUInt64(value: UInt64(v))
encoder.endRegularField()
}
}
mutating func visitRepeatedUInt64Field(value: [UInt64], fieldNumber: Int) throws {
assert(!value.isEmpty)
let fieldName = formatFieldName(lookingUp: fieldNumber)
for v in value {
encoder.emitFieldName(name: fieldName)
encoder.startRegularField()
encoder.putUInt64(value: v)
encoder.endRegularField()
}
}
mutating func visitRepeatedSInt32Field(value: [Int32], fieldNumber: Int) throws {
try visitRepeatedInt32Field(value: value, fieldNumber: fieldNumber)
}
mutating func visitRepeatedSInt64Field(value: [Int64], fieldNumber: Int) throws {
try visitRepeatedInt64Field(value: value, fieldNumber: fieldNumber)
}
mutating func visitRepeatedFixed32Field(value: [UInt32], fieldNumber: Int) throws {
try visitRepeatedUInt32Field(value: value, fieldNumber: fieldNumber)
}
mutating func visitRepeatedFixed64Field(value: [UInt64], fieldNumber: Int) throws {
try visitRepeatedUInt64Field(value: value, fieldNumber: fieldNumber)
}
mutating func visitRepeatedSFixed32Field(value: [Int32], fieldNumber: Int) throws {
try visitRepeatedInt32Field(value: value, fieldNumber: fieldNumber)
}
mutating func visitRepeatedSFixed64Field(value: [Int64], fieldNumber: Int) throws {
try visitRepeatedInt64Field(value: value, fieldNumber: fieldNumber)
}
mutating func visitRepeatedBoolField(value: [Bool], fieldNumber: Int) throws {
assert(!value.isEmpty)
let fieldName = formatFieldName(lookingUp: fieldNumber)
for v in value {
encoder.emitFieldName(name: fieldName)
encoder.startRegularField()
encoder.putBoolValue(value: v)
encoder.endRegularField()
}
}
mutating func visitRepeatedStringField(value: [String], fieldNumber: Int) throws {
assert(!value.isEmpty)
let fieldName = formatFieldName(lookingUp: fieldNumber)
for v in value {
encoder.emitFieldName(name: fieldName)
encoder.startRegularField()
encoder.putStringValue(value: v)
encoder.endRegularField()
}
}
mutating func visitRepeatedBytesField(value: [Data], fieldNumber: Int) throws {
assert(!value.isEmpty)
let fieldName = formatFieldName(lookingUp: fieldNumber)
for v in value {
encoder.emitFieldName(name: fieldName)
encoder.startRegularField()
encoder.putBytesValue(value: v)
encoder.endRegularField()
}
}
mutating func visitRepeatedEnumField<E: Enum>(value: [E], fieldNumber: Int) throws {
assert(!value.isEmpty)
let fieldName = formatFieldName(lookingUp: fieldNumber)
for v in value {
encoder.emitFieldName(name: fieldName)
encoder.startRegularField()
encoder.putEnumValue(value: v)
encoder.endRegularField()
}
}
// Messages and groups
mutating func visitRepeatedMessageField<M: Message>(value: [M],
fieldNumber: Int) throws {
assert(!value.isEmpty)
// Look up field name against outer message encoding state
let fieldName = formatFieldName(lookingUp: fieldNumber)
// Cache old encoder state
let oldNameMap = self.nameMap
let oldNameResolver = self.nameResolver
let oldExtensions = self.extensions
// Update encoding state for new message type
self.nameMap = (M.self as? _ProtoNameProviding.Type)?._protobuf_nameMap
self.nameResolver = [:]
self.extensions = (value as? ExtensibleMessage)?._protobuf_extensionFieldValues
// Iterate and encode each message
for v in value {
encoder.emitFieldName(name: fieldName)
encoder.startMessageField()
if let any = v as? Google_Protobuf_Any {
any.textTraverse(visitor: &self)
} else {
try! v.traverse(visitor: &self)
}
encoder.endMessageField()
}
// Restore state
self.extensions = oldExtensions
self.nameResolver = oldNameResolver
self.nameMap = oldNameMap
}
// Google's C++ implementation of Text format supports two formats
// for repeated numeric fields: "short" format writes the list as a
// single field with values enclosed in `[...]`, "long" format
// writes a separate field name/value for each item. They provide
// an option for callers to select which output version they prefer.
// Since this distinction mirrors the difference in Protobuf Binary
// between "packed" and "non-packed", I've chosen to use the short
// format for packed fields and the long version for repeated
// fields. This provides a clear visual distinction between these
// fields (including proto3's default use of packed) without
// introducing the baggage of a separate option.
private mutating func _visitPacked<T>(
value: [T], fieldNumber: Int,
encode: (T, inout TextFormatEncoder) -> ()
) throws {
assert(!value.isEmpty)
emitFieldName(lookingUp: fieldNumber)
encoder.startRegularField()
var firstItem = true
encoder.startArray()
for v in value {
if !firstItem {
encoder.arraySeparator()
}
encode(v, &encoder)
firstItem = false
}
encoder.endArray()
encoder.endRegularField()
}
mutating func visitPackedFloatField(value: [Float], fieldNumber: Int) throws {
try _visitPacked(value: value, fieldNumber: fieldNumber) {
(v: Float, encoder: inout TextFormatEncoder) in
encoder.putFloatValue(value: v)
}
}
mutating func visitPackedDoubleField(value: [Double], fieldNumber: Int) throws {
try _visitPacked(value: value, fieldNumber: fieldNumber) {
(v: Double, encoder: inout TextFormatEncoder) in
encoder.putDoubleValue(value: v)
}
}
mutating func visitPackedInt32Field(value: [Int32], fieldNumber: Int) throws {
try _visitPacked(value: value, fieldNumber: fieldNumber) {
(v: Int32, encoder: inout TextFormatEncoder) in
encoder.putInt64(value: Int64(v))
}
}
mutating func visitPackedInt64Field(value: [Int64], fieldNumber: Int) throws {
try _visitPacked(value: value, fieldNumber: fieldNumber) {
(v: Int64, encoder: inout TextFormatEncoder) in
encoder.putInt64(value: v)
}
}
mutating func visitPackedUInt32Field(value: [UInt32], fieldNumber: Int) throws {
try _visitPacked(value: value, fieldNumber: fieldNumber) {
(v: UInt32, encoder: inout TextFormatEncoder) in
encoder.putUInt64(value: UInt64(v))
}
}
mutating func visitPackedUInt64Field(value: [UInt64], fieldNumber: Int) throws {
try _visitPacked(value: value, fieldNumber: fieldNumber) {
(v: UInt64, encoder: inout TextFormatEncoder) in
encoder.putUInt64(value: v)
}
}
mutating func visitPackedSInt32Field(value: [Int32], fieldNumber: Int) throws {
try visitPackedInt32Field(value: value, fieldNumber: fieldNumber)
}
mutating func visitPackedSInt64Field(value: [Int64], fieldNumber: Int) throws {
try visitPackedInt64Field(value: value, fieldNumber: fieldNumber)
}
mutating func visitPackedFixed32Field(value: [UInt32], fieldNumber: Int) throws {
try visitPackedUInt32Field(value: value, fieldNumber: fieldNumber)
}
mutating func visitPackedFixed64Field(value: [UInt64], fieldNumber: Int) throws {
try visitPackedUInt64Field(value: value, fieldNumber: fieldNumber)
}
mutating func visitPackedSFixed32Field(value: [Int32], fieldNumber: Int) throws {
try visitPackedInt32Field(value: value, fieldNumber: fieldNumber)
}
mutating func visitPackedSFixed64Field(value: [Int64], fieldNumber: Int) throws {
try visitPackedInt64Field(value: value, fieldNumber: fieldNumber)
}
mutating func visitPackedBoolField(value: [Bool], fieldNumber: Int) throws {
try _visitPacked(value: value, fieldNumber: fieldNumber) {
(v: Bool, encoder: inout TextFormatEncoder) in
encoder.putBoolValue(value: v)
}
}
mutating func visitPackedEnumField<E: Enum>(value: [E], fieldNumber: Int) throws {
try _visitPacked(value: value, fieldNumber: fieldNumber) {
(v: E, encoder: inout TextFormatEncoder) in
encoder.putEnumValue(value: v)
}
}
/// Helper to encapsulate the common structure of iterating over a map
/// and encoding the keys and values.
private mutating func _visitMap<K, V>(
map: Dictionary<K, V>,
fieldNumber: Int,
coder: (inout TextFormatEncodingVisitor, K, V) throws -> ()
) throws {
for (k,v) in map {
emitFieldName(lookingUp: fieldNumber)
encoder.startMessageField()
var visitor = TextFormatEncodingVisitor(nameMap: nil, nameResolver: mapNameResolver, extensions: nil, encoder: encoder, options: options)
try coder(&visitor, k, v)
encoder = visitor.encoder
encoder.endMessageField()
}
}
mutating func visitMapField<KeyType, ValueType: MapValueType>(
fieldType: _ProtobufMap<KeyType, ValueType>.Type,
value: _ProtobufMap<KeyType, ValueType>.BaseType,
fieldNumber: Int
) throws {
try _visitMap(map: value, fieldNumber: fieldNumber) {
(visitor: inout TextFormatEncodingVisitor, key, value) throws -> () in
try KeyType.visitSingular(value: key, fieldNumber: 1, with: &visitor)
try ValueType.visitSingular(value: value, fieldNumber: 2, with: &visitor)
}
}
mutating func visitMapField<KeyType, ValueType>(
fieldType: _ProtobufEnumMap<KeyType, ValueType>.Type,
value: _ProtobufEnumMap<KeyType, ValueType>.BaseType,
fieldNumber: Int
) throws where ValueType.RawValue == Int {
try _visitMap(map: value, fieldNumber: fieldNumber) {
(visitor: inout TextFormatEncodingVisitor, key, value) throws -> () in
try KeyType.visitSingular(value: key, fieldNumber: 1, with: &visitor)
try visitor.visitSingularEnumField(value: value, fieldNumber: 2)
}
}
mutating func visitMapField<KeyType, ValueType>(
fieldType: _ProtobufMessageMap<KeyType, ValueType>.Type,
value: _ProtobufMessageMap<KeyType, ValueType>.BaseType,
fieldNumber: Int
) throws {
try _visitMap(map: value, fieldNumber: fieldNumber) {
(visitor: inout TextFormatEncodingVisitor, key, value) throws -> () in
try KeyType.visitSingular(value: key, fieldNumber: 1, with: &visitor)
try visitor.visitSingularMessageField(value: value, fieldNumber: 2)
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,53 @@
// Sources/SwiftProtobuf/TimeUtils.swift - Generally useful time/calendar functions
//
// Copyright (c) 2014 - 2017 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Generally useful time/calendar functions and constants
///
// -----------------------------------------------------------------------------
let minutesPerDay: Int32 = 1440
let minutesPerHour: Int32 = 60
let secondsPerDay: Int32 = 86400
let secondsPerHour: Int32 = 3600
let secondsPerMinute: Int32 = 60
let nanosPerSecond: Int32 = 1000000000
internal func timeOfDayFromSecondsSince1970(seconds: Int64) -> (hh: Int32, mm: Int32, ss: Int32) {
let secondsSinceMidnight = Int32(mod(seconds, Int64(secondsPerDay)))
let ss = mod(secondsSinceMidnight, secondsPerMinute)
let mm = mod(div(secondsSinceMidnight, secondsPerMinute), minutesPerHour)
let hh = Int32(div(secondsSinceMidnight, secondsPerHour))
return (hh: hh, mm: mm, ss: ss)
}
internal func julianDayNumberFromSecondsSince1970(seconds: Int64) -> Int64 {
// January 1, 1970 is Julian Day Number 2440588.
// See http://aa.usno.navy.mil/faq/docs/JD_Formula.php
return div(seconds + 2440588 * Int64(secondsPerDay), Int64(secondsPerDay))
}
internal func gregorianDateFromSecondsSince1970(seconds: Int64) -> (YY: Int32, MM: Int32, DD: Int32) {
// The following implements Richards' algorithm (see the Wikipedia article
// for "Julian day").
// If you touch this code, please test it exhaustively by playing with
// Test_Timestamp.testJSON_range.
let JJ = julianDayNumberFromSecondsSince1970(seconds: seconds)
let f = JJ + 1401 + div(div(4 * JJ + 274277, 146097) * 3, 4) - 38
let e = 4 * f + 3
let g = Int64(div(mod(e, 1461), 4))
let h = 5 * g + 2
let DD = div(mod(h, 153), 5) + 1
let MM = mod(div(h, 153) + 2, 12) + 1
let YY = div(e, 1461) - 4716 + div(12 + 2 - MM, 12)
return (YY: Int32(YY), MM: Int32(MM), DD: Int32(DD))
}

View File

@ -0,0 +1,46 @@
// Sources/SwiftProtobuf/UnknownStorage.swift - Handling unknown fields
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Proto2 binary coding requires storing and recoding of unknown fields.
/// This simple support class handles that requirement. A property of this type
/// is compiled into every proto2 message.
///
// -----------------------------------------------------------------------------
import Foundation
/// Contains any unknown fields in a decoded message; that is, fields that were
/// sent on the wire but were not recognized by the generated message
/// implementation or were valid field numbers but with mismatching wire
/// formats (for example, a field encoded as a varint when a fixed32 integer
/// was expected).
public struct UnknownStorage: Equatable {
/// The raw protocol buffer binary-encoded bytes that represent the unknown
/// fields of a decoded message.
public private(set) var data = Data()
#if !swift(>=4.1)
public static func ==(lhs: UnknownStorage, rhs: UnknownStorage) -> Bool {
return lhs.data == rhs.data
}
#endif
public init() {}
internal mutating func append(protobufData: Data) {
data.append(protobufData)
}
public func traverse<V: Visitor>(visitor: inout V) throws {
if !data.isEmpty {
try visitor.visitUnknown(bytes: data)
}
}
}

View File

@ -0,0 +1,37 @@
// Sources/SwiftProtobuf/UnsafeBufferPointer+Shims.swift - Shims for UnsafeBufferPointer
//
// Copyright (c) 2019 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Shims for UnsafeBufferPointer
///
// -----------------------------------------------------------------------------
extension UnsafeMutableBufferPointer {
#if !swift(>=4.2)
internal static func allocate(capacity: Int) -> UnsafeMutableBufferPointer<Element> {
let pointer = UnsafeMutablePointer<Element>.allocate(capacity: capacity)
return UnsafeMutableBufferPointer(start: pointer, count: capacity)
}
#endif
#if !swift(>=4.1)
internal func deallocate() {
self.baseAddress?.deallocate(capacity: self.count)
}
#endif
}
extension UnsafeMutableRawBufferPointer {
#if !swift(>=4.1)
internal func copyMemory<C: Collection>(from source: C) where C.Element == UInt8 {
self.copyBytes(from: source)
}
#endif
}

View File

@ -0,0 +1,45 @@
// Sources/SwiftProtobuf/UnsafeRawPointer+Shims.swift - Shims for UnsafeRawPointer and friends
//
// Copyright (c) 2019 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Shims for UnsafeRawPointer and friends.
///
// -----------------------------------------------------------------------------
extension UnsafeRawPointer {
/// A shim subscript for UnsafeRawPointer aiming to maintain code consistency.
///
/// We can remove this shim when we rewrite the code to use buffer pointers.
internal subscript(_ offset: Int) -> UInt8 {
get {
return self.load(fromByteOffset: offset, as: UInt8.self)
}
}
}
extension UnsafeMutableRawPointer {
/// A shim subscript for UnsafeMutableRawPointer aiming to maintain code consistency.
///
/// We can remove this shim when we rewrite the code to use buffer pointers.
internal subscript(_ offset: Int) -> UInt8 {
get {
return self.load(fromByteOffset: offset, as: UInt8.self)
}
set {
self.storeBytes(of: newValue, toByteOffset: offset, as: UInt8.self)
}
}
#if !swift(>=4.1)
internal mutating func copyMemory(from source: UnsafeRawPointer, byteCount: Int) {
self.copyBytes(from: source, count: byteCount)
}
#endif
}

View File

@ -0,0 +1,108 @@
// Sources/SwiftProtobuf/Varint.swift - Varint encoding/decoding helpers
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Helper functions to varint-encode and decode integers.
///
// -----------------------------------------------------------------------------
/// Contains helper methods to varint-encode and decode integers.
internal enum Varint {
/// Computes the number of bytes that would be needed to store a 32-bit varint.
///
/// - Parameter value: The number whose varint size should be calculated.
/// - Returns: The size, in bytes, of the 32-bit varint.
static func encodedSize(of value: UInt32) -> Int {
if (value & (~0 << 7)) == 0 {
return 1
}
if (value & (~0 << 14)) == 0 {
return 2
}
if (value & (~0 << 21)) == 0 {
return 3
}
if (value & (~0 << 28)) == 0 {
return 4
}
return 5
}
/// Computes the number of bytes that would be needed to store a signed 32-bit varint, if it were
/// treated as an unsigned integer with the same bit pattern.
///
/// - Parameter value: The number whose varint size should be calculated.
/// - Returns: The size, in bytes, of the 32-bit varint.
static func encodedSize(of value: Int32) -> Int {
if value >= 0 {
return encodedSize(of: UInt32(bitPattern: value))
} else {
// Must sign-extend.
return encodedSize(of: Int64(value))
}
}
/// Computes the number of bytes that would be needed to store a 64-bit varint.
///
/// - Parameter value: The number whose varint size should be calculated.
/// - Returns: The size, in bytes, of the 64-bit varint.
static func encodedSize(of value: Int64) -> Int {
// Handle two common special cases up front.
if (value & (~0 << 7)) == 0 {
return 1
}
if value < 0 {
return 10
}
// Divide and conquer the remaining eight cases.
var value = value
var n = 2
if (value & (~0 << 35)) != 0 {
n += 4
value >>= 28
}
if (value & (~0 << 21)) != 0 {
n += 2
value >>= 14
}
if (value & (~0 << 14)) != 0 {
n += 1
}
return n
}
/// Computes the number of bytes that would be needed to store an unsigned 64-bit varint, if it
/// were treated as a signed integer witht he same bit pattern.
///
/// - Parameter value: The number whose varint size should be calculated.
/// - Returns: The size, in bytes, of the 64-bit varint.
static func encodedSize(of value: UInt64) -> Int {
return encodedSize(of: Int64(bitPattern: value))
}
/// Counts the number of distinct varints in a packed byte buffer.
static func countVarintsInBuffer(start: UnsafeRawPointer, count: Int) -> Int {
// We don't need to decode all the varints to count how many there
// are. Just observe that every varint has exactly one byte with
// value < 128. So we just count those...
var n = 0
var ints = 0
while n < count {
if start.load(fromByteOffset: n, as: UInt8.self) < 128 {
ints += 1
}
n += 1
}
return ints
}
}

View File

@ -0,0 +1,28 @@
// Sources/SwiftProtobuf/Version.swift - Runtime Version info
//
// Copyright (c) 2014 - 2017 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// A interface for exposing the version of the runtime.
///
// -----------------------------------------------------------------------------
import Foundation
// Expose version information about the library.
public struct Version {
/// Major version.
public static let major = 1
/// Minor version.
public static let minor = 12
/// Revision number.
public static let revision = 0
/// String form of the version number.
public static let versionString = "\(major).\(minor).\(revision)"
}

View File

@ -0,0 +1,725 @@
// Sources/SwiftProtobuf/Visitor.swift - Basic serialization machinery
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Protocol for traversing the object tree.
///
/// This is used by:
/// = Protobuf serialization
/// = JSON serialization (with some twists to account for specialty JSON
/// encodings)
/// = Protobuf text serialization
/// = Hashable computation
///
/// Conceptually, serializers create visitor objects that are
/// then passed recursively to every message and field via generated
/// 'traverse' methods. The details get a little involved due to
/// the need to allow particular messages to override particular
/// behaviors for specific encodings, but the general idea is quite simple.
///
// -----------------------------------------------------------------------------
import Foundation
/// This is the key interface used by the generated `traverse()` methods
/// used for serialization. It is implemented by each serialization protocol:
/// Protobuf Binary, Protobuf Text, JSON, and the Hash encoder.
public protocol Visitor {
/// Called for each non-repeated float field
///
/// A default implementation is provided that just widens the value
/// and calls `visitSingularDoubleField`
mutating func visitSingularFloatField(value: Float, fieldNumber: Int) throws
/// Called for each non-repeated double field
///
/// There is no default implementation. This must be implemented.
mutating func visitSingularDoubleField(value: Double, fieldNumber: Int) throws
/// Called for each non-repeated int32 field
///
/// A default implementation is provided that just widens the value
/// and calls `visitSingularInt64Field`
mutating func visitSingularInt32Field(value: Int32, fieldNumber: Int) throws
/// Called for each non-repeated int64 field
///
/// There is no default implementation. This must be implemented.
mutating func visitSingularInt64Field(value: Int64, fieldNumber: Int) throws
/// Called for each non-repeated uint32 field
///
/// A default implementation is provided that just widens the value
/// and calls `visitSingularUInt64Field`
mutating func visitSingularUInt32Field(value: UInt32, fieldNumber: Int) throws
/// Called for each non-repeated uint64 field
///
/// There is no default implementation. This must be implemented.
mutating func visitSingularUInt64Field(value: UInt64, fieldNumber: Int) throws
/// Called for each non-repeated sint32 field
///
/// A default implementation is provided that just forwards to
/// `visitSingularInt32Field`
mutating func visitSingularSInt32Field(value: Int32, fieldNumber: Int) throws
/// Called for each non-repeated sint64 field
///
/// A default implementation is provided that just forwards to
/// `visitSingularInt64Field`
mutating func visitSingularSInt64Field(value: Int64, fieldNumber: Int) throws
/// Called for each non-repeated fixed32 field
///
/// A default implementation is provided that just forwards to
/// `visitSingularUInt32Field`
mutating func visitSingularFixed32Field(value: UInt32, fieldNumber: Int) throws
/// Called for each non-repeated fixed64 field
///
/// A default implementation is provided that just forwards to
/// `visitSingularUInt64Field`
mutating func visitSingularFixed64Field(value: UInt64, fieldNumber: Int) throws
/// Called for each non-repeated sfixed32 field
///
/// A default implementation is provided that just forwards to
/// `visitSingularInt32Field`
mutating func visitSingularSFixed32Field(value: Int32, fieldNumber: Int) throws
/// Called for each non-repeated sfixed64 field
///
/// A default implementation is provided that just forwards to
/// `visitSingularInt64Field`
mutating func visitSingularSFixed64Field(value: Int64, fieldNumber: Int) throws
/// Called for each non-repeated bool field
///
/// There is no default implementation. This must be implemented.
mutating func visitSingularBoolField(value: Bool, fieldNumber: Int) throws
/// Called for each non-repeated string field
///
/// There is no default implementation. This must be implemented.
mutating func visitSingularStringField(value: String, fieldNumber: Int) throws
/// Called for each non-repeated bytes field
///
/// There is no default implementation. This must be implemented.
mutating func visitSingularBytesField(value: Data, fieldNumber: Int) throws
/// Called for each non-repeated enum field
///
/// There is no default implementation. This must be implemented.
mutating func visitSingularEnumField<E: Enum>(value: E, fieldNumber: Int) throws
/// Called for each non-repeated nested message field.
///
/// There is no default implementation. This must be implemented.
mutating func visitSingularMessageField<M: Message>(value: M, fieldNumber: Int) throws
/// Called for each non-repeated proto2 group field.
///
/// A default implementation is provided that simply forwards to
/// `visitSingularMessageField`. Implementors who need to handle groups
/// differently than nested messages can override this and provide distinct
/// implementations.
mutating func visitSingularGroupField<G: Message>(value: G, fieldNumber: Int) throws
// Called for each non-packed repeated float field.
/// The method is called once with the complete array of values for
/// the field.
///
/// A default implementation is provided that simply calls
/// `visitSingularFloatField` once for each item in the array.
mutating func visitRepeatedFloatField(value: [Float], fieldNumber: Int) throws
// Called for each non-packed repeated double field.
/// The method is called once with the complete array of values for
/// the field.
///
/// A default implementation is provided that simply calls
/// `visitSingularDoubleField` once for each item in the array.
mutating func visitRepeatedDoubleField(value: [Double], fieldNumber: Int) throws
// Called for each non-packed repeated int32 field.
/// The method is called once with the complete array of values for
/// the field.
///
/// A default implementation is provided that simply calls
/// `visitSingularInt32Field` once for each item in the array.
mutating func visitRepeatedInt32Field(value: [Int32], fieldNumber: Int) throws
// Called for each non-packed repeated int64 field.
/// The method is called once with the complete array of values for
/// the field.
///
/// A default implementation is provided that simply calls
/// `visitSingularInt64Field` once for each item in the array.
mutating func visitRepeatedInt64Field(value: [Int64], fieldNumber: Int) throws
// Called for each non-packed repeated uint32 field.
/// The method is called once with the complete array of values for
/// the field.
///
/// A default implementation is provided that simply calls
/// `visitSingularUInt32Field` once for each item in the array.
mutating func visitRepeatedUInt32Field(value: [UInt32], fieldNumber: Int) throws
// Called for each non-packed repeated uint64 field.
/// The method is called once with the complete array of values for
/// the field.
///
/// A default implementation is provided that simply calls
/// `visitSingularUInt64Field` once for each item in the array.
mutating func visitRepeatedUInt64Field(value: [UInt64], fieldNumber: Int) throws
// Called for each non-packed repeated sint32 field.
/// The method is called once with the complete array of values for
/// the field.
///
/// A default implementation is provided that simply calls
/// `visitSingularSInt32Field` once for each item in the array.
mutating func visitRepeatedSInt32Field(value: [Int32], fieldNumber: Int) throws
// Called for each non-packed repeated sint64 field.
/// The method is called once with the complete array of values for
/// the field.
///
/// A default implementation is provided that simply calls
/// `visitSingularSInt64Field` once for each item in the array.
mutating func visitRepeatedSInt64Field(value: [Int64], fieldNumber: Int) throws
// Called for each non-packed repeated fixed32 field.
/// The method is called once with the complete array of values for
/// the field.
///
/// A default implementation is provided that simply calls
/// `visitSingularFixed32Field` once for each item in the array.
mutating func visitRepeatedFixed32Field(value: [UInt32], fieldNumber: Int) throws
// Called for each non-packed repeated fixed64 field.
/// The method is called once with the complete array of values for
/// the field.
///
/// A default implementation is provided that simply calls
/// `visitSingularFixed64Field` once for each item in the array.
mutating func visitRepeatedFixed64Field(value: [UInt64], fieldNumber: Int) throws
// Called for each non-packed repeated sfixed32 field.
/// The method is called once with the complete array of values for
/// the field.
///
/// A default implementation is provided that simply calls
/// `visitSingularSFixed32Field` once for each item in the array.
mutating func visitRepeatedSFixed32Field(value: [Int32], fieldNumber: Int) throws
// Called for each non-packed repeated sfixed64 field.
/// The method is called once with the complete array of values for
/// the field.
///
/// A default implementation is provided that simply calls
/// `visitSingularSFixed64Field` once for each item in the array.
mutating func visitRepeatedSFixed64Field(value: [Int64], fieldNumber: Int) throws
// Called for each non-packed repeated bool field.
/// The method is called once with the complete array of values for
/// the field.
///
/// A default implementation is provided that simply calls
/// `visitSingularBoolField` once for each item in the array.
mutating func visitRepeatedBoolField(value: [Bool], fieldNumber: Int) throws
// Called for each non-packed repeated string field.
/// The method is called once with the complete array of values for
/// the field.
///
/// A default implementation is provided that simply calls
/// `visitSingularStringField` once for each item in the array.
mutating func visitRepeatedStringField(value: [String], fieldNumber: Int) throws
// Called for each non-packed repeated bytes field.
/// The method is called once with the complete array of values for
/// the field.
///
/// A default implementation is provided that simply calls
/// `visitSingularBytesField` once for each item in the array.
mutating func visitRepeatedBytesField(value: [Data], fieldNumber: Int) throws
/// Called for each repeated, unpacked enum field.
/// The method is called once with the complete array of values for
/// the field.
///
/// A default implementation is provided that simply calls
/// `visitSingularEnumField` once for each item in the array.
mutating func visitRepeatedEnumField<E: Enum>(value: [E], fieldNumber: Int) throws
/// Called for each repeated nested message field. The method is called once
/// with the complete array of values for the field.
///
/// A default implementation is provided that simply calls
/// `visitSingularMessageField` once for each item in the array.
mutating func visitRepeatedMessageField<M: Message>(value: [M],
fieldNumber: Int) throws
/// Called for each repeated proto2 group field.
///
/// A default implementation is provided that simply calls
/// `visitSingularGroupField` once for each item in the array.
mutating func visitRepeatedGroupField<G: Message>(value: [G], fieldNumber: Int) throws
// Called for each packed, repeated float field.
///
/// This is called once with the complete array of values for
/// the field.
///
/// There is a default implementation that forwards to the non-packed
/// function.
mutating func visitPackedFloatField(value: [Float], fieldNumber: Int) throws
// Called for each packed, repeated double field.
///
/// This is called once with the complete array of values for
/// the field.
///
/// There is a default implementation that forwards to the non-packed
/// function.
mutating func visitPackedDoubleField(value: [Double], fieldNumber: Int) throws
// Called for each packed, repeated int32 field.
///
/// This is called once with the complete array of values for
/// the field.
///
/// There is a default implementation that forwards to the non-packed
/// function.
mutating func visitPackedInt32Field(value: [Int32], fieldNumber: Int) throws
// Called for each packed, repeated int64 field.
///
/// This is called once with the complete array of values for
/// the field.
///
/// There is a default implementation that forwards to the non-packed
/// function.
mutating func visitPackedInt64Field(value: [Int64], fieldNumber: Int) throws
// Called for each packed, repeated uint32 field.
///
/// This is called once with the complete array of values for
/// the field.
///
/// There is a default implementation that forwards to the non-packed
/// function.
mutating func visitPackedUInt32Field(value: [UInt32], fieldNumber: Int) throws
// Called for each packed, repeated uint64 field.
///
/// This is called once with the complete array of values for
/// the field.
///
/// There is a default implementation that forwards to the non-packed
/// function.
mutating func visitPackedUInt64Field(value: [UInt64], fieldNumber: Int) throws
// Called for each packed, repeated sint32 field.
///
/// This is called once with the complete array of values for
/// the field.
///
/// There is a default implementation that forwards to the non-packed
/// function.
mutating func visitPackedSInt32Field(value: [Int32], fieldNumber: Int) throws
// Called for each packed, repeated sint64 field.
///
/// This is called once with the complete array of values for
/// the field.
///
/// There is a default implementation that forwards to the non-packed
/// function.
mutating func visitPackedSInt64Field(value: [Int64], fieldNumber: Int) throws
// Called for each packed, repeated fixed32 field.
///
/// This is called once with the complete array of values for
/// the field.
///
/// There is a default implementation that forwards to the non-packed
/// function.
mutating func visitPackedFixed32Field(value: [UInt32], fieldNumber: Int) throws
// Called for each packed, repeated fixed64 field.
///
/// This is called once with the complete array of values for
/// the field.
///
/// There is a default implementation that forwards to the non-packed
/// function.
mutating func visitPackedFixed64Field(value: [UInt64], fieldNumber: Int) throws
// Called for each packed, repeated sfixed32 field.
///
/// This is called once with the complete array of values for
/// the field.
///
/// There is a default implementation that forwards to the non-packed
/// function.
mutating func visitPackedSFixed32Field(value: [Int32], fieldNumber: Int) throws
// Called for each packed, repeated sfixed64 field.
///
/// This is called once with the complete array of values for
/// the field.
///
/// There is a default implementation that forwards to the non-packed
/// function.
mutating func visitPackedSFixed64Field(value: [Int64], fieldNumber: Int) throws
// Called for each packed, repeated bool field.
///
/// This is called once with the complete array of values for
/// the field.
///
/// There is a default implementation that forwards to the non-packed
/// function.
mutating func visitPackedBoolField(value: [Bool], fieldNumber: Int) throws
/// Called for each repeated, packed enum field.
/// The method is called once with the complete array of values for
/// the field.
///
/// A default implementation is provided that simply forwards to
/// `visitRepeatedEnumField`. Implementors who need to handle packed fields
/// differently than unpacked fields can override this and provide distinct
/// implementations.
mutating func visitPackedEnumField<E: Enum>(value: [E], fieldNumber: Int) throws
/// Called for each map field with primitive values. The method is
/// called once with the complete dictionary of keys/values for the
/// field.
///
/// There is no default implementation. This must be implemented.
mutating func visitMapField<KeyType, ValueType: MapValueType>(
fieldType: _ProtobufMap<KeyType, ValueType>.Type,
value: _ProtobufMap<KeyType, ValueType>.BaseType,
fieldNumber: Int) throws
/// Called for each map field with enum values. The method is called
/// once with the complete dictionary of keys/values for the field.
///
/// There is no default implementation. This must be implemented.
mutating func visitMapField<KeyType, ValueType>(
fieldType: _ProtobufEnumMap<KeyType, ValueType>.Type,
value: _ProtobufEnumMap<KeyType, ValueType>.BaseType,
fieldNumber: Int) throws where ValueType.RawValue == Int
/// Called for each map field with message values. The method is
/// called once with the complete dictionary of keys/values for the
/// field.
///
/// There is no default implementation. This must be implemented.
mutating func visitMapField<KeyType, ValueType>(
fieldType: _ProtobufMessageMap<KeyType, ValueType>.Type,
value: _ProtobufMessageMap<KeyType, ValueType>.BaseType,
fieldNumber: Int) throws
/// Called for each extension range.
mutating func visitExtensionFields(fields: ExtensionFieldValueSet, start: Int, end: Int) throws
/// Called for each extension range.
mutating func visitExtensionFieldsAsMessageSet(
fields: ExtensionFieldValueSet,
start: Int,
end: Int) throws
/// Called with the raw bytes that represent any unknown fields.
mutating func visitUnknown(bytes: Data) throws
}
/// Forwarding default implementations of some visitor methods, for convenience.
extension Visitor {
// Default definitions of numeric serializations.
//
// The 32-bit versions widen and delegate to 64-bit versions.
// The specialized integer codings delegate to standard Int/UInt.
//
// These "just work" for Hash and Text formats. Most of these work
// for JSON (32-bit integers are overridden to suppress quoting),
// and a few even work for Protobuf Binary (thanks to varint coding
// which erases the size difference between 32-bit and 64-bit ints).
public mutating func visitSingularFloatField(value: Float, fieldNumber: Int) throws {
try visitSingularDoubleField(value: Double(value), fieldNumber: fieldNumber)
}
public mutating func visitSingularInt32Field(value: Int32, fieldNumber: Int) throws {
try visitSingularInt64Field(value: Int64(value), fieldNumber: fieldNumber)
}
public mutating func visitSingularUInt32Field(value: UInt32, fieldNumber: Int) throws {
try visitSingularUInt64Field(value: UInt64(value), fieldNumber: fieldNumber)
}
public mutating func visitSingularSInt32Field(value: Int32, fieldNumber: Int) throws {
try visitSingularInt32Field(value: value, fieldNumber: fieldNumber)
}
public mutating func visitSingularSInt64Field(value: Int64, fieldNumber: Int) throws {
try visitSingularInt64Field(value: value, fieldNumber: fieldNumber)
}
public mutating func visitSingularFixed32Field(value: UInt32, fieldNumber: Int) throws {
try visitSingularUInt32Field(value: value, fieldNumber: fieldNumber)
}
public mutating func visitSingularFixed64Field(value: UInt64, fieldNumber: Int) throws {
try visitSingularUInt64Field(value: value, fieldNumber: fieldNumber)
}
public mutating func visitSingularSFixed32Field(value: Int32, fieldNumber: Int) throws {
try visitSingularInt32Field(value: value, fieldNumber: fieldNumber)
}
public mutating func visitSingularSFixed64Field(value: Int64, fieldNumber: Int) throws {
try visitSingularInt64Field(value: value, fieldNumber: fieldNumber)
}
// Default definitions of repeated serializations that just iterate and
// invoke the singular encoding. These "just work" for Protobuf Binary (encoder
// and size visitor), Protobuf Text, and Hash visitors. JSON format stores
// repeated values differently from singular, so overrides these.
public mutating func visitRepeatedFloatField(value: [Float], fieldNumber: Int) throws {
assert(!value.isEmpty)
for v in value {
try visitSingularFloatField(value: v, fieldNumber: fieldNumber)
}
}
public mutating func visitRepeatedDoubleField(value: [Double], fieldNumber: Int) throws {
assert(!value.isEmpty)
for v in value {
try visitSingularDoubleField(value: v, fieldNumber: fieldNumber)
}
}
public mutating func visitRepeatedInt32Field(value: [Int32], fieldNumber: Int) throws {
assert(!value.isEmpty)
for v in value {
try visitSingularInt32Field(value: v, fieldNumber: fieldNumber)
}
}
public mutating func visitRepeatedInt64Field(value: [Int64], fieldNumber: Int) throws {
assert(!value.isEmpty)
for v in value {
try visitSingularInt64Field(value: v, fieldNumber: fieldNumber)
}
}
public mutating func visitRepeatedUInt32Field(value: [UInt32], fieldNumber: Int) throws {
assert(!value.isEmpty)
for v in value {
try visitSingularUInt32Field(value: v, fieldNumber: fieldNumber)
}
}
public mutating func visitRepeatedUInt64Field(value: [UInt64], fieldNumber: Int) throws {
assert(!value.isEmpty)
for v in value {
try visitSingularUInt64Field(value: v, fieldNumber: fieldNumber)
}
}
public mutating func visitRepeatedSInt32Field(value: [Int32], fieldNumber: Int) throws {
assert(!value.isEmpty)
for v in value {
try visitSingularSInt32Field(value: v, fieldNumber: fieldNumber)
}
}
public mutating func visitRepeatedSInt64Field(value: [Int64], fieldNumber: Int) throws {
assert(!value.isEmpty)
for v in value {
try visitSingularSInt64Field(value: v, fieldNumber: fieldNumber)
}
}
public mutating func visitRepeatedFixed32Field(value: [UInt32], fieldNumber: Int) throws {
assert(!value.isEmpty)
for v in value {
try visitSingularFixed32Field(value: v, fieldNumber: fieldNumber)
}
}
public mutating func visitRepeatedFixed64Field(value: [UInt64], fieldNumber: Int) throws {
assert(!value.isEmpty)
for v in value {
try visitSingularFixed64Field(value: v, fieldNumber: fieldNumber)
}
}
public mutating func visitRepeatedSFixed32Field(value: [Int32], fieldNumber: Int) throws {
assert(!value.isEmpty)
for v in value {
try visitSingularSFixed32Field(value: v, fieldNumber: fieldNumber)
}
}
public mutating func visitRepeatedSFixed64Field(value: [Int64], fieldNumber: Int) throws {
assert(!value.isEmpty)
for v in value {
try visitSingularSFixed64Field(value: v, fieldNumber: fieldNumber)
}
}
public mutating func visitRepeatedBoolField(value: [Bool], fieldNumber: Int) throws {
assert(!value.isEmpty)
for v in value {
try visitSingularBoolField(value: v, fieldNumber: fieldNumber)
}
}
public mutating func visitRepeatedStringField(value: [String], fieldNumber: Int) throws {
assert(!value.isEmpty)
for v in value {
try visitSingularStringField(value: v, fieldNumber: fieldNumber)
}
}
public mutating func visitRepeatedBytesField(value: [Data], fieldNumber: Int) throws {
assert(!value.isEmpty)
for v in value {
try visitSingularBytesField(value: v, fieldNumber: fieldNumber)
}
}
public mutating func visitRepeatedEnumField<E: Enum>(value: [E], fieldNumber: Int) throws {
assert(!value.isEmpty)
for v in value {
try visitSingularEnumField(value: v, fieldNumber: fieldNumber)
}
}
public mutating func visitRepeatedMessageField<M: Message>(value: [M], fieldNumber: Int) throws {
assert(!value.isEmpty)
for v in value {
try visitSingularMessageField(value: v, fieldNumber: fieldNumber)
}
}
public mutating func visitRepeatedGroupField<G: Message>(value: [G], fieldNumber: Int) throws {
assert(!value.isEmpty)
for v in value {
try visitSingularGroupField(value: v, fieldNumber: fieldNumber)
}
}
// Default definitions of packed serialization just defer to the
// repeated implementation. This works for Hash and JSON visitors
// (which do not distinguish packed vs. non-packed) but are
// overridden by Protobuf Binary and Text.
public mutating func visitPackedFloatField(value: [Float], fieldNumber: Int) throws {
assert(!value.isEmpty)
try visitRepeatedFloatField(value: value, fieldNumber: fieldNumber)
}
public mutating func visitPackedDoubleField(value: [Double], fieldNumber: Int) throws {
assert(!value.isEmpty)
try visitRepeatedDoubleField(value: value, fieldNumber: fieldNumber)
}
public mutating func visitPackedInt32Field(value: [Int32], fieldNumber: Int) throws {
assert(!value.isEmpty)
try visitRepeatedInt32Field(value: value, fieldNumber: fieldNumber)
}
public mutating func visitPackedInt64Field(value: [Int64], fieldNumber: Int) throws {
assert(!value.isEmpty)
try visitRepeatedInt64Field(value: value, fieldNumber: fieldNumber)
}
public mutating func visitPackedUInt32Field(value: [UInt32], fieldNumber: Int) throws {
assert(!value.isEmpty)
try visitRepeatedUInt32Field(value: value, fieldNumber: fieldNumber)
}
public mutating func visitPackedUInt64Field(value: [UInt64], fieldNumber: Int) throws {
assert(!value.isEmpty)
try visitRepeatedUInt64Field(value: value, fieldNumber: fieldNumber)
}
public mutating func visitPackedSInt32Field(value: [Int32], fieldNumber: Int) throws {
assert(!value.isEmpty)
try visitPackedInt32Field(value: value, fieldNumber: fieldNumber)
}
public mutating func visitPackedSInt64Field(value: [Int64], fieldNumber: Int) throws {
assert(!value.isEmpty)
try visitPackedInt64Field(value: value, fieldNumber: fieldNumber)
}
public mutating func visitPackedFixed32Field(value: [UInt32], fieldNumber: Int) throws {
assert(!value.isEmpty)
try visitPackedUInt32Field(value: value, fieldNumber: fieldNumber)
}
public mutating func visitPackedFixed64Field(value: [UInt64], fieldNumber: Int) throws {
assert(!value.isEmpty)
try visitPackedUInt64Field(value: value, fieldNumber: fieldNumber)
}
public mutating func visitPackedSFixed32Field(value: [Int32], fieldNumber: Int) throws {
assert(!value.isEmpty)
try visitPackedInt32Field(value: value, fieldNumber: fieldNumber)
}
public mutating func visitPackedSFixed64Field(value: [Int64], fieldNumber: Int) throws {
assert(!value.isEmpty)
try visitPackedInt64Field(value: value, fieldNumber: fieldNumber)
}
public mutating func visitPackedBoolField(value: [Bool], fieldNumber: Int) throws {
assert(!value.isEmpty)
try visitRepeatedBoolField(value: value, fieldNumber: fieldNumber)
}
public mutating func visitPackedEnumField<E: Enum>(value: [E],
fieldNumber: Int) throws {
assert(!value.isEmpty)
try visitRepeatedEnumField(value: value, fieldNumber: fieldNumber)
}
// Default handling for Groups is to treat them just like messages.
// This works for Text and Hash, but is overridden by Protobuf Binary
// format (which has a different encoding for groups) and JSON
// (which explicitly ignores all groups).
public mutating func visitSingularGroupField<G: Message>(value: G,
fieldNumber: Int) throws {
try visitSingularMessageField(value: value, fieldNumber: fieldNumber)
}
// Default handling of Extensions as a MessageSet to handing them just
// as plain extensions. Formats that what custom behavior can override
// it.
public mutating func visitExtensionFieldsAsMessageSet(
fields: ExtensionFieldValueSet,
start: Int,
end: Int) throws {
try visitExtensionFields(fields: fields, start: start, end: end)
}
// Default handling for Extensions is to forward the traverse to
// the ExtensionFieldValueSet. Formats that don't care about extensions
// can override to avoid it.
/// Called for each extension range.
public mutating func visitExtensionFields(fields: ExtensionFieldValueSet, start: Int, end: Int) throws {
try fields.traverse(visitor: &self, start: start, end: end)
}
}

View File

@ -0,0 +1,70 @@
// Sources/SwiftProtobuf/WireFormat.swift - Describes proto wire formats
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Types related to binary wire formats of encoded values.
///
// -----------------------------------------------------------------------------
/// Denotes the wire format by which a value is encoded in binary form.
internal enum WireFormat: UInt8 {
case varint = 0
case fixed64 = 1
case lengthDelimited = 2
case startGroup = 3
case endGroup = 4
case fixed32 = 5
}
extension WireFormat {
/// Information about the "MessageSet" format. Used when a Message has
/// the message_set_wire_format option enabled.
///
/// Writing in MessageSet form means instead of writing the Extesions
/// normally as a simple fields, each gets written wrapped in a group:
/// repeated group Item = 1 {
/// required int32 type_id = 2;
/// required bytes message = 3;
/// }
/// Where the field number is the type_id, and the message is serilaized
/// into the bytes.
///
/// The handling of unknown fields is ill defined. In proto1, they were
/// dropped. In the C++ for proto2, since it stores them in the unknowns
/// storage, if preserves any that are length delimited data (since that's
/// how the message also goes out). While the C++ is parsing, where the
/// unknowns fall in the flow of the group, sorta decides what happens.
/// Since it is ill defined, currently SwiftProtobuf will reflect out
/// anything set in the unknownStorage. During parsing, unknowns on the
/// message are preserved, but unknowns within the group are dropped (like
/// map items). Any extension in the MessageSet that isn't in the Regisry
/// being used at parse time will remain in a group and go into the
/// Messages's unknown fields (this way it reflects back out correctly).
internal enum MessageSet {
enum FieldNumbers {
static let item = 1;
static let typeId = 2;
static let message = 3;
}
enum Tags {
static let itemStart = FieldTag(fieldNumber: FieldNumbers.item, wireFormat: .startGroup)
static let itemEnd = FieldTag(fieldNumber: FieldNumbers.item, wireFormat: .endGroup)
static let typeId = FieldTag(fieldNumber: FieldNumbers.typeId, wireFormat: .varint)
static let message = FieldTag(fieldNumber: FieldNumbers.message, wireFormat: .lengthDelimited)
}
// The size of all the tags needed to write out an Extension in MessageSet format.
static let itemTagsEncodedSize =
Tags.itemStart.encodedSize + Tags.itemEnd.encodedSize +
Tags.typeId.encodedSize +
Tags.message.encodedSize
}
}

View File

@ -0,0 +1,66 @@
// Sources/SwiftProtobuf/ZigZag.swift - ZigZag encoding/decoding helpers
//
// Copyright (c) 2014 - 2016 Apple Inc. and the project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See LICENSE.txt for license information:
// https://github.com/apple/swift-protobuf/blob/master/LICENSE.txt
//
// -----------------------------------------------------------------------------
///
/// Helper functions to ZigZag encode and decode signed integers.
///
// -----------------------------------------------------------------------------
/// Contains helper methods to ZigZag encode and decode signed integers.
internal enum ZigZag {
/// Return a 32-bit ZigZag-encoded value.
///
/// ZigZag encodes signed integers into values that can be efficiently encoded with varint.
/// (Otherwise, negative values must be sign-extended to 64 bits to be varint encoded, always
/// taking 10 bytes on the wire.)
///
/// - Parameter value: A signed 32-bit integer.
/// - Returns: An unsigned 32-bit integer representing the ZigZag-encoded value.
static func encoded(_ value: Int32) -> UInt32 {
return UInt32(bitPattern: (value << 1) ^ (value >> 31))
}
/// Return a 64-bit ZigZag-encoded value.
///
/// ZigZag encodes signed integers into values that can be efficiently encoded with varint.
/// (Otherwise, negative values must be sign-extended to 64 bits to be varint encoded, always
/// taking 10 bytes on the wire.)
///
/// - Parameter value: A signed 64-bit integer.
/// - Returns: An unsigned 64-bit integer representing the ZigZag-encoded value.
static func encoded(_ value: Int64) -> UInt64 {
return UInt64(bitPattern: (value << 1) ^ (value >> 63))
}
/// Return a 32-bit ZigZag-decoded value.
///
/// ZigZag enocdes signed integers into values that can be efficiently encoded with varint.
/// (Otherwise, negative values must be sign-extended to 64 bits to be varint encoded, always
/// taking 10 bytes on the wire.)
///
/// - Parameter value: An unsigned 32-bit ZagZag-encoded integer.
/// - Returns: The signed 32-bit decoded value.
static func decoded(_ value: UInt32) -> Int32 {
return Int32(value >> 1) ^ -Int32(value & 1)
}
/// Return a 64-bit ZigZag-decoded value.
///
/// ZigZag enocdes signed integers into values that can be efficiently encoded with varint.
/// (Otherwise, negative values must be sign-extended to 64 bits to be varint encoded, always
/// taking 10 bytes on the wire.)
///
/// - Parameter value: An unsigned 64-bit ZigZag-encoded integer.
/// - Returns: The signed 64-bit decoded value.
static func decoded(_ value: UInt64) -> Int64 {
return Int64(value >> 1) ^ -Int64(value & 1)
}
}

View File

@ -0,0 +1,241 @@
// DO NOT EDIT.
// swift-format-ignore-file
//
// Generated by the Swift generator plugin for the protocol buffer compiler.
// Source: google/protobuf/any.proto
//
// For information on using the generated types, please see the documentation:
// https://github.com/apple/swift-protobuf/
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import Foundation
// If the compiler emits an error on this type, it is because this file
// was generated by a version of the `protoc` Swift plug-in that is
// incompatible with the version of SwiftProtobuf to which you are linking.
// Please ensure that you are building against the same version of the API
// that was used to generate this file.
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
/// `Any` contains an arbitrary serialized protocol buffer message along with a
/// URL that describes the type of the serialized message.
///
/// Protobuf library provides support to pack/unpack Any values in the form
/// of utility functions or additional generated methods of the Any type.
///
/// Example 1: Pack and unpack a message in C++.
///
/// Foo foo = ...;
/// Any any;
/// any.PackFrom(foo);
/// ...
/// if (any.UnpackTo(&foo)) {
/// ...
/// }
///
/// Example 2: Pack and unpack a message in Java.
///
/// Foo foo = ...;
/// Any any = Any.pack(foo);
/// ...
/// if (any.is(Foo.class)) {
/// foo = any.unpack(Foo.class);
/// }
///
/// Example 3: Pack and unpack a message in Python.
///
/// foo = Foo(...)
/// any = Any()
/// any.Pack(foo)
/// ...
/// if any.Is(Foo.DESCRIPTOR):
/// any.Unpack(foo)
/// ...
///
/// Example 4: Pack and unpack a message in Go
///
/// foo := &pb.Foo{...}
/// any, err := anypb.New(foo)
/// if err != nil {
/// ...
/// }
/// ...
/// foo := &pb.Foo{}
/// if err := any.UnmarshalTo(foo); err != nil {
/// ...
/// }
///
/// The pack methods provided by protobuf library will by default use
/// 'type.googleapis.com/full.type.name' as the type URL and the unpack
/// methods only use the fully qualified type name after the last '/'
/// in the type URL, for example "foo.bar.com/x/y.z" will yield type
/// name "y.z".
///
///
/// JSON
/// ====
/// The JSON representation of an `Any` value uses the regular
/// representation of the deserialized, embedded message, with an
/// additional field `@type` which contains the type URL. Example:
///
/// package google.profile;
/// message Person {
/// string first_name = 1;
/// string last_name = 2;
/// }
///
/// {
/// "@type": "type.googleapis.com/google.profile.Person",
/// "firstName": <string>,
/// "lastName": <string>
/// }
///
/// If the embedded message type is well-known and has a custom JSON
/// representation, that representation will be embedded adding a field
/// `value` which holds the custom JSON in addition to the `@type`
/// field. Example (for message [google.protobuf.Duration][]):
///
/// {
/// "@type": "type.googleapis.com/google.protobuf.Duration",
/// "value": "1.212s"
/// }
public struct Google_Protobuf_Any {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
/// A URL/resource name that uniquely identifies the type of the serialized
/// protocol buffer message. This string must contain at least
/// one "/" character. The last segment of the URL's path must represent
/// the fully qualified name of the type (as in
/// `path/google.protobuf.Duration`). The name should be in a canonical form
/// (e.g., leading "." is not accepted).
///
/// In practice, teams usually precompile into the binary all types that they
/// expect it to use in the context of Any. However, for URLs which use the
/// scheme `http`, `https`, or no scheme, one can optionally set up a type
/// server that maps type URLs to message definitions as follows:
///
/// * If no scheme is provided, `https` is assumed.
/// * An HTTP GET on the URL must yield a [google.protobuf.Type][]
/// value in binary format, or produce an error.
/// * Applications are allowed to cache lookup results based on the
/// URL, or have them precompiled into a binary to avoid any
/// lookup. Therefore, binary compatibility needs to be preserved
/// on changes to types. (Use versioned type names to manage
/// breaking changes.)
///
/// Note: this functionality is not currently available in the official
/// protobuf release, and it is not used for type URLs beginning with
/// type.googleapis.com.
///
/// Schemes other than `http`, `https` (or the empty scheme) might be
/// used with implementation specific semantics.
public var typeURL: String {
get {return _storage._typeURL}
set {_uniqueStorage()._typeURL = newValue}
}
/// Must be a valid serialized protocol buffer of the above specified type.
public var value: Data {
get {return _storage._value}
set {_uniqueStorage()._value = newValue}
}
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
internal var _storage = _StorageClass.defaultInstance
}
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "google.protobuf"
extension Google_Protobuf_Any: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".Any"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "type_url"),
2: .same(proto: "value"),
]
typealias _StorageClass = AnyMessageStorage
internal mutating func _uniqueStorage() -> _StorageClass {
if !isKnownUniquelyReferenced(&_storage) {
_storage = _StorageClass(copying: _storage)
}
return _storage
}
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
_ = _uniqueStorage()
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeSingularStringField(value: &_storage._typeURL) }()
case 2: try { try decoder.decodeSingularBytesField(value: &_storage._value) }()
default: break
}
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
try _storage.preTraverse()
if !_storage._typeURL.isEmpty {
try visitor.visitSingularStringField(value: _storage._typeURL, fieldNumber: 1)
}
if !_storage._value.isEmpty {
try visitor.visitSingularBytesField(value: _storage._value, fieldNumber: 2)
}
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Google_Protobuf_Any, rhs: Google_Protobuf_Any) -> Bool {
if lhs._storage !== rhs._storage {
let storagesAreEqual: Bool = lhs._storage.isEqualTo(other: rhs._storage)
if !storagesAreEqual {return false}
}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}

View File

@ -0,0 +1,424 @@
// DO NOT EDIT.
// swift-format-ignore-file
//
// Generated by the Swift generator plugin for the protocol buffer compiler.
// Source: google/protobuf/api.proto
//
// For information on using the generated types, please see the documentation:
// https://github.com/apple/swift-protobuf/
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import Foundation
// If the compiler emits an error on this type, it is because this file
// was generated by a version of the `protoc` Swift plug-in that is
// incompatible with the version of SwiftProtobuf to which you are linking.
// Please ensure that you are building against the same version of the API
// that was used to generate this file.
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
/// Api is a light-weight descriptor for an API Interface.
///
/// Interfaces are also described as "protocol buffer services" in some contexts,
/// such as by the "service" keyword in a .proto file, but they are different
/// from API Services, which represent a concrete implementation of an interface
/// as opposed to simply a description of methods and bindings. They are also
/// sometimes simply referred to as "APIs" in other contexts, such as the name of
/// this message itself. See https://cloud.google.com/apis/design/glossary for
/// detailed terminology.
public struct Google_Protobuf_Api {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
/// The fully qualified name of this interface, including package name
/// followed by the interface's simple name.
public var name: String = String()
/// The methods of this interface, in unspecified order.
public var methods: [Google_Protobuf_Method] = []
/// Any metadata attached to the interface.
public var options: [Google_Protobuf_Option] = []
/// A version string for this interface. If specified, must have the form
/// `major-version.minor-version`, as in `1.10`. If the minor version is
/// omitted, it defaults to zero. If the entire version field is empty, the
/// major version is derived from the package name, as outlined below. If the
/// field is not empty, the version in the package name will be verified to be
/// consistent with what is provided here.
///
/// The versioning schema uses [semantic
/// versioning](http://semver.org) where the major version number
/// indicates a breaking change and the minor version an additive,
/// non-breaking change. Both version numbers are signals to users
/// what to expect from different versions, and should be carefully
/// chosen based on the product plan.
///
/// The major version is also reflected in the package name of the
/// interface, which must end in `v<major-version>`, as in
/// `google.feature.v1`. For major versions 0 and 1, the suffix can
/// be omitted. Zero major versions must only be used for
/// experimental, non-GA interfaces.
public var version: String = String()
/// Source context for the protocol buffer service represented by this
/// message.
public var sourceContext: Google_Protobuf_SourceContext {
get {return _sourceContext ?? Google_Protobuf_SourceContext()}
set {_sourceContext = newValue}
}
/// Returns true if `sourceContext` has been explicitly set.
public var hasSourceContext: Bool {return self._sourceContext != nil}
/// Clears the value of `sourceContext`. Subsequent reads from it will return its default value.
public mutating func clearSourceContext() {self._sourceContext = nil}
/// Included interfaces. See [Mixin][].
public var mixins: [Google_Protobuf_Mixin] = []
/// The source syntax of the service.
public var syntax: Google_Protobuf_Syntax = .proto2
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
fileprivate var _sourceContext: Google_Protobuf_SourceContext? = nil
}
/// Method represents a method of an API interface.
public struct Google_Protobuf_Method {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
/// The simple name of this method.
public var name: String = String()
/// A URL of the input message type.
public var requestTypeURL: String = String()
/// If true, the request is streamed.
public var requestStreaming: Bool = false
/// The URL of the output message type.
public var responseTypeURL: String = String()
/// If true, the response is streamed.
public var responseStreaming: Bool = false
/// Any metadata attached to the method.
public var options: [Google_Protobuf_Option] = []
/// The source syntax of this method.
public var syntax: Google_Protobuf_Syntax = .proto2
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
/// Declares an API Interface to be included in this interface. The including
/// interface must redeclare all the methods from the included interface, but
/// documentation and options are inherited as follows:
///
/// - If after comment and whitespace stripping, the documentation
/// string of the redeclared method is empty, it will be inherited
/// from the original method.
///
/// - Each annotation belonging to the service config (http,
/// visibility) which is not set in the redeclared method will be
/// inherited.
///
/// - If an http annotation is inherited, the path pattern will be
/// modified as follows. Any version prefix will be replaced by the
/// version of the including interface plus the [root][] path if
/// specified.
///
/// Example of a simple mixin:
///
/// package google.acl.v1;
/// service AccessControl {
/// // Get the underlying ACL object.
/// rpc GetAcl(GetAclRequest) returns (Acl) {
/// option (google.api.http).get = "/v1/{resource=**}:getAcl";
/// }
/// }
///
/// package google.storage.v2;
/// service Storage {
/// rpc GetAcl(GetAclRequest) returns (Acl);
///
/// // Get a data record.
/// rpc GetData(GetDataRequest) returns (Data) {
/// option (google.api.http).get = "/v2/{resource=**}";
/// }
/// }
///
/// Example of a mixin configuration:
///
/// apis:
/// - name: google.storage.v2.Storage
/// mixins:
/// - name: google.acl.v1.AccessControl
///
/// The mixin construct implies that all methods in `AccessControl` are
/// also declared with same name and request/response types in
/// `Storage`. A documentation generator or annotation processor will
/// see the effective `Storage.GetAcl` method after inheriting
/// documentation and annotations as follows:
///
/// service Storage {
/// // Get the underlying ACL object.
/// rpc GetAcl(GetAclRequest) returns (Acl) {
/// option (google.api.http).get = "/v2/{resource=**}:getAcl";
/// }
/// ...
/// }
///
/// Note how the version in the path pattern changed from `v1` to `v2`.
///
/// If the `root` field in the mixin is specified, it should be a
/// relative path under which inherited HTTP paths are placed. Example:
///
/// apis:
/// - name: google.storage.v2.Storage
/// mixins:
/// - name: google.acl.v1.AccessControl
/// root: acls
///
/// This implies the following inherited HTTP annotation:
///
/// service Storage {
/// // Get the underlying ACL object.
/// rpc GetAcl(GetAclRequest) returns (Acl) {
/// option (google.api.http).get = "/v2/acls/{resource=**}:getAcl";
/// }
/// ...
/// }
public struct Google_Protobuf_Mixin {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
/// The fully qualified name of the interface which is included.
public var name: String = String()
/// If non-empty specifies a path under which inherited HTTP paths
/// are rooted.
public var root: String = String()
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "google.protobuf"
extension Google_Protobuf_Api: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".Api"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "name"),
2: .same(proto: "methods"),
3: .same(proto: "options"),
4: .same(proto: "version"),
5: .standard(proto: "source_context"),
6: .same(proto: "mixins"),
7: .same(proto: "syntax"),
]
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeSingularStringField(value: &self.name) }()
case 2: try { try decoder.decodeRepeatedMessageField(value: &self.methods) }()
case 3: try { try decoder.decodeRepeatedMessageField(value: &self.options) }()
case 4: try { try decoder.decodeSingularStringField(value: &self.version) }()
case 5: try { try decoder.decodeSingularMessageField(value: &self._sourceContext) }()
case 6: try { try decoder.decodeRepeatedMessageField(value: &self.mixins) }()
case 7: try { try decoder.decodeSingularEnumField(value: &self.syntax) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.name.isEmpty {
try visitor.visitSingularStringField(value: self.name, fieldNumber: 1)
}
if !self.methods.isEmpty {
try visitor.visitRepeatedMessageField(value: self.methods, fieldNumber: 2)
}
if !self.options.isEmpty {
try visitor.visitRepeatedMessageField(value: self.options, fieldNumber: 3)
}
if !self.version.isEmpty {
try visitor.visitSingularStringField(value: self.version, fieldNumber: 4)
}
if let v = self._sourceContext {
try visitor.visitSingularMessageField(value: v, fieldNumber: 5)
}
if !self.mixins.isEmpty {
try visitor.visitRepeatedMessageField(value: self.mixins, fieldNumber: 6)
}
if self.syntax != .proto2 {
try visitor.visitSingularEnumField(value: self.syntax, fieldNumber: 7)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Google_Protobuf_Api, rhs: Google_Protobuf_Api) -> Bool {
if lhs.name != rhs.name {return false}
if lhs.methods != rhs.methods {return false}
if lhs.options != rhs.options {return false}
if lhs.version != rhs.version {return false}
if lhs._sourceContext != rhs._sourceContext {return false}
if lhs.mixins != rhs.mixins {return false}
if lhs.syntax != rhs.syntax {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Google_Protobuf_Method: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".Method"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "name"),
2: .standard(proto: "request_type_url"),
3: .standard(proto: "request_streaming"),
4: .standard(proto: "response_type_url"),
5: .standard(proto: "response_streaming"),
6: .same(proto: "options"),
7: .same(proto: "syntax"),
]
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeSingularStringField(value: &self.name) }()
case 2: try { try decoder.decodeSingularStringField(value: &self.requestTypeURL) }()
case 3: try { try decoder.decodeSingularBoolField(value: &self.requestStreaming) }()
case 4: try { try decoder.decodeSingularStringField(value: &self.responseTypeURL) }()
case 5: try { try decoder.decodeSingularBoolField(value: &self.responseStreaming) }()
case 6: try { try decoder.decodeRepeatedMessageField(value: &self.options) }()
case 7: try { try decoder.decodeSingularEnumField(value: &self.syntax) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.name.isEmpty {
try visitor.visitSingularStringField(value: self.name, fieldNumber: 1)
}
if !self.requestTypeURL.isEmpty {
try visitor.visitSingularStringField(value: self.requestTypeURL, fieldNumber: 2)
}
if self.requestStreaming != false {
try visitor.visitSingularBoolField(value: self.requestStreaming, fieldNumber: 3)
}
if !self.responseTypeURL.isEmpty {
try visitor.visitSingularStringField(value: self.responseTypeURL, fieldNumber: 4)
}
if self.responseStreaming != false {
try visitor.visitSingularBoolField(value: self.responseStreaming, fieldNumber: 5)
}
if !self.options.isEmpty {
try visitor.visitRepeatedMessageField(value: self.options, fieldNumber: 6)
}
if self.syntax != .proto2 {
try visitor.visitSingularEnumField(value: self.syntax, fieldNumber: 7)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Google_Protobuf_Method, rhs: Google_Protobuf_Method) -> Bool {
if lhs.name != rhs.name {return false}
if lhs.requestTypeURL != rhs.requestTypeURL {return false}
if lhs.requestStreaming != rhs.requestStreaming {return false}
if lhs.responseTypeURL != rhs.responseTypeURL {return false}
if lhs.responseStreaming != rhs.responseStreaming {return false}
if lhs.options != rhs.options {return false}
if lhs.syntax != rhs.syntax {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Google_Protobuf_Mixin: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".Mixin"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "name"),
2: .same(proto: "root"),
]
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeSingularStringField(value: &self.name) }()
case 2: try { try decoder.decodeSingularStringField(value: &self.root) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.name.isEmpty {
try visitor.visitSingularStringField(value: self.name, fieldNumber: 1)
}
if !self.root.isEmpty {
try visitor.visitSingularStringField(value: self.root, fieldNumber: 2)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Google_Protobuf_Mixin, rhs: Google_Protobuf_Mixin) -> Bool {
if lhs.name != rhs.name {return false}
if lhs.root != rhs.root {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,173 @@
// DO NOT EDIT.
// swift-format-ignore-file
//
// Generated by the Swift generator plugin for the protocol buffer compiler.
// Source: google/protobuf/duration.proto
//
// For information on using the generated types, please see the documentation:
// https://github.com/apple/swift-protobuf/
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import Foundation
// If the compiler emits an error on this type, it is because this file
// was generated by a version of the `protoc` Swift plug-in that is
// incompatible with the version of SwiftProtobuf to which you are linking.
// Please ensure that you are building against the same version of the API
// that was used to generate this file.
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
/// A Duration represents a signed, fixed-length span of time represented
/// as a count of seconds and fractions of seconds at nanosecond
/// resolution. It is independent of any calendar and concepts like "day"
/// or "month". It is related to Timestamp in that the difference between
/// two Timestamp values is a Duration and it can be added or subtracted
/// from a Timestamp. Range is approximately +-10,000 years.
///
/// # Examples
///
/// Example 1: Compute Duration from two Timestamps in pseudo code.
///
/// Timestamp start = ...;
/// Timestamp end = ...;
/// Duration duration = ...;
///
/// duration.seconds = end.seconds - start.seconds;
/// duration.nanos = end.nanos - start.nanos;
///
/// if (duration.seconds < 0 && duration.nanos > 0) {
/// duration.seconds += 1;
/// duration.nanos -= 1000000000;
/// } else if (duration.seconds > 0 && duration.nanos < 0) {
/// duration.seconds -= 1;
/// duration.nanos += 1000000000;
/// }
///
/// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code.
///
/// Timestamp start = ...;
/// Duration duration = ...;
/// Timestamp end = ...;
///
/// end.seconds = start.seconds + duration.seconds;
/// end.nanos = start.nanos + duration.nanos;
///
/// if (end.nanos < 0) {
/// end.seconds -= 1;
/// end.nanos += 1000000000;
/// } else if (end.nanos >= 1000000000) {
/// end.seconds += 1;
/// end.nanos -= 1000000000;
/// }
///
/// Example 3: Compute Duration from datetime.timedelta in Python.
///
/// td = datetime.timedelta(days=3, minutes=10)
/// duration = Duration()
/// duration.FromTimedelta(td)
///
/// # JSON Mapping
///
/// In JSON format, the Duration type is encoded as a string rather than an
/// object, where the string ends in the suffix "s" (indicating seconds) and
/// is preceded by the number of seconds, with nanoseconds expressed as
/// fractional seconds. For example, 3 seconds with 0 nanoseconds should be
/// encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should
/// be expressed in JSON format as "3.000000001s", and 3 seconds and 1
/// microsecond should be expressed in JSON format as "3.000001s".
public struct Google_Protobuf_Duration {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
/// Signed seconds of the span of time. Must be from -315,576,000,000
/// to +315,576,000,000 inclusive. Note: these bounds are computed from:
/// 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years
public var seconds: Int64 = 0
/// Signed fractions of a second at nanosecond resolution of the span
/// of time. Durations less than one second are represented with a 0
/// `seconds` field and a positive or negative `nanos` field. For durations
/// of one second or more, a non-zero value for the `nanos` field must be
/// of the same sign as the `seconds` field. Must be from -999,999,999
/// to +999,999,999 inclusive.
public var nanos: Int32 = 0
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "google.protobuf"
extension Google_Protobuf_Duration: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".Duration"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "seconds"),
2: .same(proto: "nanos"),
]
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeSingularInt64Field(value: &self.seconds) }()
case 2: try { try decoder.decodeSingularInt32Field(value: &self.nanos) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if self.seconds != 0 {
try visitor.visitSingularInt64Field(value: self.seconds, fieldNumber: 1)
}
if self.nanos != 0 {
try visitor.visitSingularInt32Field(value: self.nanos, fieldNumber: 2)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Google_Protobuf_Duration, rhs: Google_Protobuf_Duration) -> Bool {
if lhs.seconds != rhs.seconds {return false}
if lhs.nanos != rhs.nanos {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}

View File

@ -0,0 +1,92 @@
// DO NOT EDIT.
// swift-format-ignore-file
//
// Generated by the Swift generator plugin for the protocol buffer compiler.
// Source: google/protobuf/empty.proto
//
// For information on using the generated types, please see the documentation:
// https://github.com/apple/swift-protobuf/
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import Foundation
// If the compiler emits an error on this type, it is because this file
// was generated by a version of the `protoc` Swift plug-in that is
// incompatible with the version of SwiftProtobuf to which you are linking.
// Please ensure that you are building against the same version of the API
// that was used to generate this file.
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
/// A generic empty message that you can re-use to avoid defining duplicated
/// empty messages in your APIs. A typical example is to use it as the request
/// or the response type of an API method. For instance:
///
/// service Foo {
/// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);
/// }
///
/// The JSON representation for `Empty` is empty JSON object `{}`.
public struct Google_Protobuf_Empty {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "google.protobuf"
extension Google_Protobuf_Empty: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".Empty"
public static let _protobuf_nameMap = SwiftProtobuf._NameMap()
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let _ = try decoder.nextFieldNumber() {
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Google_Protobuf_Empty, rhs: Google_Protobuf_Empty) -> Bool {
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}

View File

@ -0,0 +1,298 @@
// DO NOT EDIT.
// swift-format-ignore-file
//
// Generated by the Swift generator plugin for the protocol buffer compiler.
// Source: google/protobuf/field_mask.proto
//
// For information on using the generated types, please see the documentation:
// https://github.com/apple/swift-protobuf/
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import Foundation
// If the compiler emits an error on this type, it is because this file
// was generated by a version of the `protoc` Swift plug-in that is
// incompatible with the version of SwiftProtobuf to which you are linking.
// Please ensure that you are building against the same version of the API
// that was used to generate this file.
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
/// `FieldMask` represents a set of symbolic field paths, for example:
///
/// paths: "f.a"
/// paths: "f.b.d"
///
/// Here `f` represents a field in some root message, `a` and `b`
/// fields in the message found in `f`, and `d` a field found in the
/// message in `f.b`.
///
/// Field masks are used to specify a subset of fields that should be
/// returned by a get operation or modified by an update operation.
/// Field masks also have a custom JSON encoding (see below).
///
/// # Field Masks in Projections
///
/// When used in the context of a projection, a response message or
/// sub-message is filtered by the API to only contain those fields as
/// specified in the mask. For example, if the mask in the previous
/// example is applied to a response message as follows:
///
/// f {
/// a : 22
/// b {
/// d : 1
/// x : 2
/// }
/// y : 13
/// }
/// z: 8
///
/// The result will not contain specific values for fields x,y and z
/// (their value will be set to the default, and omitted in proto text
/// output):
///
///
/// f {
/// a : 22
/// b {
/// d : 1
/// }
/// }
///
/// A repeated field is not allowed except at the last position of a
/// paths string.
///
/// If a FieldMask object is not present in a get operation, the
/// operation applies to all fields (as if a FieldMask of all fields
/// had been specified).
///
/// Note that a field mask does not necessarily apply to the
/// top-level response message. In case of a REST get operation, the
/// field mask applies directly to the response, but in case of a REST
/// list operation, the mask instead applies to each individual message
/// in the returned resource list. In case of a REST custom method,
/// other definitions may be used. Where the mask applies will be
/// clearly documented together with its declaration in the API. In
/// any case, the effect on the returned resource/resources is required
/// behavior for APIs.
///
/// # Field Masks in Update Operations
///
/// A field mask in update operations specifies which fields of the
/// targeted resource are going to be updated. The API is required
/// to only change the values of the fields as specified in the mask
/// and leave the others untouched. If a resource is passed in to
/// describe the updated values, the API ignores the values of all
/// fields not covered by the mask.
///
/// If a repeated field is specified for an update operation, new values will
/// be appended to the existing repeated field in the target resource. Note that
/// a repeated field is only allowed in the last position of a `paths` string.
///
/// If a sub-message is specified in the last position of the field mask for an
/// update operation, then new value will be merged into the existing sub-message
/// in the target resource.
///
/// For example, given the target message:
///
/// f {
/// b {
/// d: 1
/// x: 2
/// }
/// c: [1]
/// }
///
/// And an update message:
///
/// f {
/// b {
/// d: 10
/// }
/// c: [2]
/// }
///
/// then if the field mask is:
///
/// paths: ["f.b", "f.c"]
///
/// then the result will be:
///
/// f {
/// b {
/// d: 10
/// x: 2
/// }
/// c: [1, 2]
/// }
///
/// An implementation may provide options to override this default behavior for
/// repeated and message fields.
///
/// In order to reset a field's value to the default, the field must
/// be in the mask and set to the default value in the provided resource.
/// Hence, in order to reset all fields of a resource, provide a default
/// instance of the resource and set all fields in the mask, or do
/// not provide a mask as described below.
///
/// If a field mask is not present on update, the operation applies to
/// all fields (as if a field mask of all fields has been specified).
/// Note that in the presence of schema evolution, this may mean that
/// fields the client does not know and has therefore not filled into
/// the request will be reset to their default. If this is unwanted
/// behavior, a specific service may require a client to always specify
/// a field mask, producing an error if not.
///
/// As with get operations, the location of the resource which
/// describes the updated values in the request message depends on the
/// operation kind. In any case, the effect of the field mask is
/// required to be honored by the API.
///
/// ## Considerations for HTTP REST
///
/// The HTTP kind of an update operation which uses a field mask must
/// be set to PATCH instead of PUT in order to satisfy HTTP semantics
/// (PUT must only be used for full updates).
///
/// # JSON Encoding of Field Masks
///
/// In JSON, a field mask is encoded as a single string where paths are
/// separated by a comma. Fields name in each path are converted
/// to/from lower-camel naming conventions.
///
/// As an example, consider the following message declarations:
///
/// message Profile {
/// User user = 1;
/// Photo photo = 2;
/// }
/// message User {
/// string display_name = 1;
/// string address = 2;
/// }
///
/// In proto a field mask for `Profile` may look as such:
///
/// mask {
/// paths: "user.display_name"
/// paths: "photo"
/// }
///
/// In JSON, the same mask is represented as below:
///
/// {
/// mask: "user.displayName,photo"
/// }
///
/// # Field Masks and Oneof Fields
///
/// Field masks treat fields in oneofs just as regular fields. Consider the
/// following message:
///
/// message SampleMessage {
/// oneof test_oneof {
/// string name = 4;
/// SubMessage sub_message = 9;
/// }
/// }
///
/// The field mask can be:
///
/// mask {
/// paths: "name"
/// }
///
/// Or:
///
/// mask {
/// paths: "sub_message"
/// }
///
/// Note that oneof type names ("test_oneof" in this case) cannot be used in
/// paths.
///
/// ## Field Mask Verification
///
/// The implementation of any API method which has a FieldMask type field in the
/// request should verify the included field paths, and return an
/// `INVALID_ARGUMENT` error if any path is unmappable.
public struct Google_Protobuf_FieldMask {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
/// The set of field mask paths.
public var paths: [String] = []
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "google.protobuf"
extension Google_Protobuf_FieldMask: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".FieldMask"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "paths"),
]
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeRepeatedStringField(value: &self.paths) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.paths.isEmpty {
try visitor.visitRepeatedStringField(value: self.paths, fieldNumber: 1)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Google_Protobuf_FieldMask, rhs: Google_Protobuf_FieldMask) -> Bool {
if lhs.paths != rhs.paths {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}

View File

@ -0,0 +1,102 @@
// DO NOT EDIT.
// swift-format-ignore-file
//
// Generated by the Swift generator plugin for the protocol buffer compiler.
// Source: google/protobuf/source_context.proto
//
// For information on using the generated types, please see the documentation:
// https://github.com/apple/swift-protobuf/
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import Foundation
// If the compiler emits an error on this type, it is because this file
// was generated by a version of the `protoc` Swift plug-in that is
// incompatible with the version of SwiftProtobuf to which you are linking.
// Please ensure that you are building against the same version of the API
// that was used to generate this file.
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
/// `SourceContext` represents information about the source of a
/// protobuf element, like the file in which it is defined.
public struct Google_Protobuf_SourceContext {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
/// The path-qualified name of the .proto file that contained the associated
/// protobuf element. For example: `"google/protobuf/source_context.proto"`.
public var fileName: String = String()
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "google.protobuf"
extension Google_Protobuf_SourceContext: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".SourceContext"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "file_name"),
]
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeSingularStringField(value: &self.fileName) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.fileName.isEmpty {
try visitor.visitSingularStringField(value: self.fileName, fieldNumber: 1)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Google_Protobuf_SourceContext, rhs: Google_Protobuf_SourceContext) -> Bool {
if lhs.fileName != rhs.fileName {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}

View File

@ -0,0 +1,432 @@
// DO NOT EDIT.
// swift-format-ignore-file
//
// Generated by the Swift generator plugin for the protocol buffer compiler.
// Source: google/protobuf/struct.proto
//
// For information on using the generated types, please see the documentation:
// https://github.com/apple/swift-protobuf/
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import Foundation
// If the compiler emits an error on this type, it is because this file
// was generated by a version of the `protoc` Swift plug-in that is
// incompatible with the version of SwiftProtobuf to which you are linking.
// Please ensure that you are building against the same version of the API
// that was used to generate this file.
fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAPIVersionCheck {
struct _2: SwiftProtobuf.ProtobufAPIVersion_2 {}
typealias Version = _2
}
/// `NullValue` is a singleton enumeration to represent the null value for the
/// `Value` type union.
///
/// The JSON representation for `NullValue` is JSON `null`.
public enum Google_Protobuf_NullValue: SwiftProtobuf.Enum {
public typealias RawValue = Int
/// Null value.
case nullValue // = 0
case UNRECOGNIZED(Int)
public init() {
self = .nullValue
}
public init?(rawValue: Int) {
switch rawValue {
case 0: self = .nullValue
default: self = .UNRECOGNIZED(rawValue)
}
}
public var rawValue: Int {
switch self {
case .nullValue: return 0
case .UNRECOGNIZED(let i): return i
}
}
}
#if swift(>=4.2)
extension Google_Protobuf_NullValue: CaseIterable {
// The compiler won't synthesize support with the UNRECOGNIZED case.
public static var allCases: [Google_Protobuf_NullValue] = [
.nullValue,
]
}
#endif // swift(>=4.2)
/// `Struct` represents a structured data value, consisting of fields
/// which map to dynamically typed values. In some languages, `Struct`
/// might be supported by a native representation. For example, in
/// scripting languages like JS a struct is represented as an
/// object. The details of that representation are described together
/// with the proto support for the language.
///
/// The JSON representation for `Struct` is JSON object.
public struct Google_Protobuf_Struct {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
/// Unordered map of dynamically typed values.
public var fields: Dictionary<String,Google_Protobuf_Value> = [:]
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
/// `Value` represents a dynamically typed value which can be either
/// null, a number, a string, a boolean, a recursive struct value, or a
/// list of values. A producer of value is expected to set one of that
/// variants, absence of any variant indicates an error.
///
/// The JSON representation for `Value` is JSON value.
public struct Google_Protobuf_Value {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
/// The kind of value.
public var kind: Google_Protobuf_Value.OneOf_Kind? = nil
/// Represents a null value.
public var nullValue: Google_Protobuf_NullValue {
get {
if case .nullValue(let v)? = kind {return v}
return .nullValue
}
set {kind = .nullValue(newValue)}
}
/// Represents a double value.
public var numberValue: Double {
get {
if case .numberValue(let v)? = kind {return v}
return 0
}
set {kind = .numberValue(newValue)}
}
/// Represents a string value.
public var stringValue: String {
get {
if case .stringValue(let v)? = kind {return v}
return String()
}
set {kind = .stringValue(newValue)}
}
/// Represents a boolean value.
public var boolValue: Bool {
get {
if case .boolValue(let v)? = kind {return v}
return false
}
set {kind = .boolValue(newValue)}
}
/// Represents a structured value.
public var structValue: Google_Protobuf_Struct {
get {
if case .structValue(let v)? = kind {return v}
return Google_Protobuf_Struct()
}
set {kind = .structValue(newValue)}
}
/// Represents a repeated `Value`.
public var listValue: Google_Protobuf_ListValue {
get {
if case .listValue(let v)? = kind {return v}
return Google_Protobuf_ListValue()
}
set {kind = .listValue(newValue)}
}
public var unknownFields = SwiftProtobuf.UnknownStorage()
/// The kind of value.
public enum OneOf_Kind: Equatable {
/// Represents a null value.
case nullValue(Google_Protobuf_NullValue)
/// Represents a double value.
case numberValue(Double)
/// Represents a string value.
case stringValue(String)
/// Represents a boolean value.
case boolValue(Bool)
/// Represents a structured value.
case structValue(Google_Protobuf_Struct)
/// Represents a repeated `Value`.
case listValue(Google_Protobuf_ListValue)
#if !swift(>=4.1)
public static func ==(lhs: Google_Protobuf_Value.OneOf_Kind, rhs: Google_Protobuf_Value.OneOf_Kind) -> Bool {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch (lhs, rhs) {
case (.nullValue, .nullValue): return {
guard case .nullValue(let l) = lhs, case .nullValue(let r) = rhs else { preconditionFailure() }
return l == r
}()
case (.numberValue, .numberValue): return {
guard case .numberValue(let l) = lhs, case .numberValue(let r) = rhs else { preconditionFailure() }
return l == r
}()
case (.stringValue, .stringValue): return {
guard case .stringValue(let l) = lhs, case .stringValue(let r) = rhs else { preconditionFailure() }
return l == r
}()
case (.boolValue, .boolValue): return {
guard case .boolValue(let l) = lhs, case .boolValue(let r) = rhs else { preconditionFailure() }
return l == r
}()
case (.structValue, .structValue): return {
guard case .structValue(let l) = lhs, case .structValue(let r) = rhs else { preconditionFailure() }
return l == r
}()
case (.listValue, .listValue): return {
guard case .listValue(let l) = lhs, case .listValue(let r) = rhs else { preconditionFailure() }
return l == r
}()
default: return false
}
}
#endif
}
public init() {}
}
/// `ListValue` is a wrapper around a repeated field of values.
///
/// The JSON representation for `ListValue` is JSON array.
public struct Google_Protobuf_ListValue {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
/// Repeated field of dynamically typed values.
public var values: [Google_Protobuf_Value] = []
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
}
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "google.protobuf"
extension Google_Protobuf_NullValue: SwiftProtobuf._ProtoNameProviding {
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
0: .same(proto: "NULL_VALUE"),
]
}
extension Google_Protobuf_Struct: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".Struct"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "fields"),
]
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeMapField(fieldType: SwiftProtobuf._ProtobufMessageMap<SwiftProtobuf.ProtobufString,Google_Protobuf_Value>.self, value: &self.fields) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.fields.isEmpty {
try visitor.visitMapField(fieldType: SwiftProtobuf._ProtobufMessageMap<SwiftProtobuf.ProtobufString,Google_Protobuf_Value>.self, value: self.fields, fieldNumber: 1)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Google_Protobuf_Struct, rhs: Google_Protobuf_Struct) -> Bool {
if lhs.fields != rhs.fields {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Google_Protobuf_Value: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".Value"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "null_value"),
2: .standard(proto: "number_value"),
3: .standard(proto: "string_value"),
4: .standard(proto: "bool_value"),
5: .standard(proto: "struct_value"),
6: .standard(proto: "list_value"),
]
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try {
if self.kind != nil {try decoder.handleConflictingOneOf()}
var v: Google_Protobuf_NullValue?
try decoder.decodeSingularEnumField(value: &v)
if let v = v {self.kind = .nullValue(v)}
}()
case 2: try {
if self.kind != nil {try decoder.handleConflictingOneOf()}
var v: Double?
try decoder.decodeSingularDoubleField(value: &v)
if let v = v {self.kind = .numberValue(v)}
}()
case 3: try {
if self.kind != nil {try decoder.handleConflictingOneOf()}
var v: String?
try decoder.decodeSingularStringField(value: &v)
if let v = v {self.kind = .stringValue(v)}
}()
case 4: try {
if self.kind != nil {try decoder.handleConflictingOneOf()}
var v: Bool?
try decoder.decodeSingularBoolField(value: &v)
if let v = v {self.kind = .boolValue(v)}
}()
case 5: try {
var v: Google_Protobuf_Struct?
if let current = self.kind {
try decoder.handleConflictingOneOf()
if case .structValue(let m) = current {v = m}
}
try decoder.decodeSingularMessageField(value: &v)
if let v = v {self.kind = .structValue(v)}
}()
case 6: try {
var v: Google_Protobuf_ListValue?
if let current = self.kind {
try decoder.handleConflictingOneOf()
if case .listValue(let m) = current {v = m}
}
try decoder.decodeSingularMessageField(value: &v)
if let v = v {self.kind = .listValue(v)}
}()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch self.kind {
case .nullValue?: try {
guard case .nullValue(let v)? = self.kind else { preconditionFailure() }
try visitor.visitSingularEnumField(value: v, fieldNumber: 1)
}()
case .numberValue?: try {
guard case .numberValue(let v)? = self.kind else { preconditionFailure() }
try visitor.visitSingularDoubleField(value: v, fieldNumber: 2)
}()
case .stringValue?: try {
guard case .stringValue(let v)? = self.kind else { preconditionFailure() }
try visitor.visitSingularStringField(value: v, fieldNumber: 3)
}()
case .boolValue?: try {
guard case .boolValue(let v)? = self.kind else { preconditionFailure() }
try visitor.visitSingularBoolField(value: v, fieldNumber: 4)
}()
case .structValue?: try {
guard case .structValue(let v)? = self.kind else { preconditionFailure() }
try visitor.visitSingularMessageField(value: v, fieldNumber: 5)
}()
case .listValue?: try {
guard case .listValue(let v)? = self.kind else { preconditionFailure() }
try visitor.visitSingularMessageField(value: v, fieldNumber: 6)
}()
case nil: break
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Google_Protobuf_Value, rhs: Google_Protobuf_Value) -> Bool {
if lhs.kind != rhs.kind {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension Google_Protobuf_ListValue: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".ListValue"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "values"),
]
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeRepeatedMessageField(value: &self.values) }()
default: break
}
}
}
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if !self.values.isEmpty {
try visitor.visitRepeatedMessageField(value: self.values, fieldNumber: 1)
}
try unknownFields.traverse(visitor: &visitor)
}
public static func ==(lhs: Google_Protobuf_ListValue, rhs: Google_Protobuf_ListValue) -> Bool {
if lhs.values != rhs.values {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}

Some files were not shown because too many files have changed in this diff Show More