├── .gitignore ├── .project ├── .properties ├── .smalltalk.ston ├── .travis.yml ├── BaselineOfProtobuf ├── BaselineOfProtobuf.class.st └── package.st ├── LICENSE ├── Protobuf-Core-Tests ├── PBCodedStreamTest.class.st ├── PBCodedWriteStreamTest.class.st ├── PBProtobufCoderTest.class.st ├── PBProtobufTestMessage1.class.st ├── PBSmalltalkClassInfoMessage.class.st ├── PBSmalltalkClassInfoMessageTest.class.st ├── PBSmalltalkPackageMessage.class.st └── package.st ├── Protobuf-Core ├── PBCodedReadStream.class.st ├── PBCodedWriteStream.class.st ├── PBEnum.class.st ├── PBMessage.class.st ├── PBProtobufCoder.class.st ├── PBProtobufConstants.class.st ├── PBType.class.st └── package.st ├── Protobuf-Tools-Tests ├── PBProtobufCodeGeneratorTest.class.st ├── PBProtobufGoogleApiImporter.class.st ├── PBProtobufGrammarTest.class.st ├── PBProtobufParserTest.class.st └── package.st ├── Protobuf-Tools ├── PBAddEnumClassRefactoring.class.st ├── PBAddMessageClassRefactoring.class.st ├── PBGoogleProtobufResources.class.st ├── PBProtobufCodeGenerator.class.st ├── PBProtobufCommentNode.class.st ├── PBProtobufEnum.class.st ├── PBProtobufEnumValue.class.st ├── PBProtobufFieldNode.class.st ├── PBProtobufFileNode.class.st ├── PBProtobufGrammar.class.st ├── PBProtobufImportNode.class.st ├── PBProtobufMessageNode.class.st ├── PBProtobufNode.class.st ├── PBProtobufOptionNode.class.st ├── PBProtobufPackageNode.class.st ├── PBProtobufParser.class.st ├── PBProtobufTypeNode.class.st ├── PBSmalltalkEnumType.class.st ├── PBSmalltalkEnumValueType.class.st ├── PBSmalltalkFieldType.class.st ├── PBSmalltalkMessageType.class.st ├── PBSmalltalkNodeWrapper.class.st ├── PBSmalltalkPackage.class.st ├── PBUpdateEnumClassRefactoring.class.st ├── PBUpdateMessageClassRefactoring.class.st └── package.st └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | protobuf-smalltalk.iml 2 | .idea -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | { 2 | 'srcDirectory' : '' 3 | } -------------------------------------------------------------------------------- /.properties: -------------------------------------------------------------------------------- 1 | { 2 | #format : #tonel 3 | } -------------------------------------------------------------------------------- /.smalltalk.ston: -------------------------------------------------------------------------------- 1 | SmalltalkCISpec { 2 | #loading : [ 3 | SCIMetacelloLoadSpec { 4 | #baseline : 'Protobuf', 5 | #platforms : [ #pharo ] 6 | } 7 | ] 8 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: smalltalk 2 | sudo: false 3 | 4 | os: 5 | - linux 6 | 7 | smalltalk: 8 | - Pharo-7.0 9 | - Pharo64-7.0 10 | - Pharo64-8.0 11 | 12 | cache: 13 | directories: 14 | $HOME/package-cache 15 | -------------------------------------------------------------------------------- /BaselineOfProtobuf/BaselineOfProtobuf.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #BaselineOfProtobuf, 3 | #superclass : #BaselineOf, 4 | #category : #BaselineOfProtobuf 5 | } 6 | 7 | { #category : #baselines } 8 | BaselineOfProtobuf >> baselineOf: spec [ 9 | 10 | spec for: #common do: [ 11 | 12 | spec baseline: 'PetitParser2Core' with: [ 13 | spec repository: 'github://kursjan/petitparser2' ]. 14 | 15 | spec package: 'Protobuf-Core'. 16 | spec package: 'Protobuf-Core-Tests' with: [ spec requires: #( 'Protobuf-Core' ) ]. 17 | spec package: 'Protobuf-Tools' with: [ spec requires: #( 'Protobuf-Core' 'PetitParser2Core' ) ]. 18 | spec package: 'Protobuf-Tools-Tests' with: [ spec requires: #( 'Protobuf-Tools' 'Protobuf-Core-Tests' ) ]. 19 | 20 | spec group: 'default' with: #( 'Protobuf-Tools-Tests' ). 21 | spec group: 'runtime' with: #( 'Protobuf-Core-Tests' ) ] 22 | ] 23 | -------------------------------------------------------------------------------- /BaselineOfProtobuf/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #BaselineOfProtobuf } 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Protobuf-Core-Tests/PBCodedStreamTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBCodedStreamTest, 3 | #superclass : #TestCase, 4 | #pools : [ 5 | 'PBProtobufConstants' 6 | ], 7 | #category : #'Protobuf-Core-Tests' 8 | } 9 | 10 | { #category : #tests } 11 | PBCodedStreamTest >> testBool [ 12 | 13 | self testWriter: [ :output | 14 | output writeField: 1 bool: true. 15 | output writeField: 2 int32: 12345 ] 16 | reader: [ :input | 17 | self assert: input readTag equals: (input coder makeTag: 1 wireType: WireTypeVarint). 18 | self assert: input readBool equals: true. 19 | self assert: input readTag equals: (input coder makeTag: 2 wireType: WireTypeVarint). 20 | self assert: input readInt32 equals: 12345 ] 21 | ] 22 | 23 | { #category : #tests } 24 | PBCodedStreamTest >> testDouble [ 25 | 26 | self testWriter: [ :output | 27 | output writeField: 1 double: 123.456. 28 | output writeField: 2 int32: 12345 ] 29 | reader: [ :input | 30 | self assert: input readTag equals: (input coder makeTag: 1 wireType: WireType64bit). 31 | self assert: input readDouble equals: 123.456. 32 | self assert: input readTag equals: (input coder makeTag: 2 wireType: WireTypeVarint). 33 | self assert: input readInt32 equals: 12345 ] 34 | ] 35 | 36 | { #category : #tests } 37 | PBCodedStreamTest >> testFloat [ 38 | 39 | self testWriter: [ :output | 40 | output writeField: 1 float: 123.456. 41 | output writeField: 2 int32: 12345 ] 42 | reader: [ :input | 43 | self assert: input readTag equals: (input coder makeTag: 1 wireType: WireType64bit). 44 | self assert: (input readFloat - 123.456) abs < 0.001. 45 | self assert: input readTag equals: (input coder makeTag: 2 wireType: WireTypeVarint). 46 | self assert: input readInt32 equals: 12345 ] 47 | ] 48 | 49 | { #category : #tests } 50 | PBCodedStreamTest >> testIntegers32 [ 51 | self 52 | testWriter: [ :output | 53 | output writeField: 1 int32: 12345. 54 | output writeField: 2 uint32: 12345. 55 | output writeField: 3 sint32: -12345. 56 | output writeField: 4 fixed32: 12345. 57 | output writeField: 5 sfixed32: -12345 ] 58 | reader: [ :input | 59 | self 60 | assert: input readTag 61 | equals: (input coder makeTag: 1 wireType: WireTypeVarint). 62 | self assert: input readInt32 equals: 12345. 63 | self 64 | assert: input readTag 65 | equals: (input coder makeTag: 2 wireType: WireTypeVarint). 66 | self assert: input readUint32 equals: 12345. 67 | self 68 | assert: input readTag 69 | equals: (input coder makeTag: 3 wireType: WireTypeVarint). 70 | self assert: input readSint32 equals: -12345. 71 | self 72 | assert: input readTag 73 | equals: (input coder makeTag: 4 wireType: WireType32bit). 74 | self assert: input readFixed32 equals: 12345. 75 | self 76 | assert: input readTag 77 | equals: (input coder makeTag: 5 wireType: WireType32bit). 78 | self assert: input readSfixed32 equals: -12345 ] 79 | ] 80 | 81 | { #category : #tests } 82 | PBCodedStreamTest >> testIntegers64 [ 83 | 84 | self testWriter: [ :output | 85 | output writeField: 1 int64: 12345. 86 | output writeField: 2 uint64: 12345. 87 | output writeField: 3 sint64: -12345. 88 | output writeField: 4 fixed64: 12345. 89 | output writeField: 5 sfixed64: -12345 ] 90 | reader: [ :input | 91 | self assert: input readTag equals: (input coder makeTag: 1 wireType: WireTypeVarint). 92 | self assert: input readInt64 equals: 12345. 93 | self assert: input readTag equals: (input coder makeTag: 2 wireType: WireTypeVarint). 94 | self assert: input readUint64 equals: 12345. 95 | self assert: input readTag equals: (input coder makeTag: 3 wireType: WireTypeVarint). 96 | self assert: input readSint64 equals: -12345. 97 | self assert: input readTag equals: (input coder makeTag: 4 wireType: WireType64bit). 98 | self assert: input readFixed64 equals: 12345. 99 | self assert: input readTag equals: (input coder makeTag: 5 wireType: WireType64bit). 100 | self assert: input readSfixed64 equals: -12345 ] 101 | ] 102 | 103 | { #category : #tests } 104 | PBCodedStreamTest >> testMessage [ 105 | 106 | | msg | 107 | 108 | msg := PBProtobufTestMessage1 new 109 | fieldOne: 'Hello World!'; 110 | fieldTwo: 42; 111 | yourself. 112 | 113 | self testWriter: [ :output | 114 | output writeField: 1 message: msg. 115 | output writeField: 2 int32: 12345 ] 116 | reader: [ :input | 117 | self assert: input readTag equals: (input coder makeTag: 1 wireType: WireTypeLengthDelimited). 118 | self assert: (input readMessage: msg class) equals: msg. 119 | self assert: input readTag equals: (input coder makeTag: 2 wireType: WireTypeVarint). 120 | self assert: input readInt32 equals: 12345 ] 121 | ] 122 | 123 | { #category : #tests } 124 | PBCodedStreamTest >> testMessageList [ 125 | 126 | | msgList | 127 | 128 | msgList := (1 to: 10) collect: [ :index | 129 | PBProtobufTestMessage1 new 130 | fieldOne: 'Hello World ', index asString; 131 | fieldTwo: 42 * index; 132 | yourself ]. 133 | 134 | self testWriter: [ :output | 135 | output writeField: 1 messageList: msgList. 136 | output writeField: 2 int32: 12345 ] 137 | reader: [ :input | 138 | | resultList | 139 | resultList := (1 to: msgList size) collect: [ :index | 140 | self assert: input readTag equals: (input coder makeTag: 1 wireType: WireTypeLengthDelimited). 141 | input readMessage: PBProtobufTestMessage1 ]. 142 | self assert: resultList equals: msgList. 143 | self assert: input readTag equals: (input coder makeTag: 2 wireType: WireTypeVarint). 144 | self assert: input readInt32 equals: 12345 ] 145 | ] 146 | 147 | { #category : #tests } 148 | PBCodedStreamTest >> testScalarLists [ 149 | 150 | self testWriter: [ :output | 151 | output writeField: 1 int32List: #( -100 0 1 20000 ). 152 | output writeField: 2 boolList: #( true false true ). 153 | output writeField: 3 doubleList: #( -10.9 0.0 123.456 ) ] 154 | reader: [ :input | 155 | self assert: input readTag equals: (input coder makeTag: 1 wireType: WireTypeLengthDelimited). 156 | self assert: input readInt32List asArray equals: #( -100 0 1 20000 ). 157 | self assert: input readTag equals: (input coder makeTag: 2 wireType: WireTypeLengthDelimited). 158 | self assert: input readBoolList asArray equals: #( true false true ). 159 | self assert: input readTag equals: (input coder makeTag: 3 wireType: WireTypeLengthDelimited). 160 | self assert: input readDoubleList asArray equals: #( -10.9 0.0 123.456 ) ] 161 | ] 162 | 163 | { #category : #tests } 164 | PBCodedStreamTest >> testScalarListsEmpty [ 165 | 166 | | bytes | 167 | 168 | bytes := self testWriter: [ :output | 169 | output writeField: 1 int32List: #( ). 170 | output writeField: 2 boolList: #( ). 171 | output writeField: 3 doubleList: #( ) ] 172 | reader: [ :input | ]. 173 | 174 | self assert: bytes equals: #[ ] 175 | ] 176 | 177 | { #category : #tests } 178 | PBCodedStreamTest >> testString [ 179 | 180 | self testWriter: [ :output | 181 | output writeField: 1 string: 'Testing 1-2-3'. 182 | output writeField: 2 int32: 12345 ] 183 | reader: [ :input | 184 | self assert: input readTag equals: (input coder makeTag: 1 wireType: WireTypeLengthDelimited). 185 | self assert: input readString equals: 'Testing 1-2-3'. 186 | self assert: input readTag equals: (input coder makeTag: 2 wireType: WireTypeVarint). 187 | self assert: input readInt32 equals: 12345 ] 188 | ] 189 | 190 | { #category : #tests } 191 | PBCodedStreamTest >> testStringUtf8 [ 192 | 193 | self testWriter: [ :output | 194 | output writeField: 1 string: 'één'. 195 | output writeField: 2 int32: 12345 ] 196 | reader: [ :input | 197 | self assert: input readTag equals: (input coder makeTag: 1 wireType: WireTypeLengthDelimited). 198 | self assert: input readString equals: 'één'. 199 | self assert: input readTag equals: (input coder makeTag: 2 wireType: WireTypeVarint). 200 | self assert: input readInt32 equals: 12345 ] 201 | ] 202 | 203 | { #category : #tests } 204 | PBCodedStreamTest >> testStringWide [ 205 | 206 | | wideString | 207 | 208 | wideString := WideString withAll: { 300 asCharacter. 400 asCharacter. 500 asCharacter }. 209 | 210 | self testWriter: [ :output | 211 | output writeField: 1 string: wideString. 212 | output writeField: 2 int32: 12345 ] 213 | reader: [ :input | 214 | self assert: input readTag equals: (input coder makeTag: 1 wireType: WireTypeLengthDelimited). 215 | self assert: input readString equals: wideString. 216 | self assert: input readTag equals: (input coder makeTag: 2 wireType: WireTypeVarint). 217 | self assert: input readInt32 equals: 12345 ] 218 | ] 219 | 220 | { #category : #tests } 221 | PBCodedStreamTest >> testWriter: aWriteBlock reader: aReadBlock [ 222 | 223 | | bytes | 224 | 225 | bytes := ByteArray streamContents: [ :s | 226 | aWriteBlock value: (PBCodedWriteStream on: s) ]. 227 | 228 | aReadBlock value: (PBCodedReadStream on: bytes readStream). 229 | 230 | ^ bytes 231 | ] 232 | -------------------------------------------------------------------------------- /Protobuf-Core-Tests/PBCodedWriteStreamTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBCodedWriteStreamTest, 3 | #superclass : #TestCase, 4 | #category : #'Protobuf-Core-Tests' 5 | } 6 | 7 | { #category : #tests } 8 | PBCodedWriteStreamTest >> newStream [ 9 | 10 | ^PBCodedWriteStream on: (WriteStream on: (ByteArray new: 1000)) 11 | ] 12 | 13 | { #category : #tests } 14 | PBCodedWriteStreamTest >> testInteger32Fields [ 15 | 16 | | stream | 17 | 18 | stream := self newStream. 19 | stream writeField: 1 int32: 1. 20 | self assert: stream contents equals: #[ 2r00001000 2r00000001 ]. 21 | 22 | stream := self newStream. 23 | stream writeField: 1 uint32: 1. 24 | self assert: stream contents equals: #[ 2r00001000 2r00000001 ]. 25 | 26 | stream := self newStream. 27 | stream writeField: 1 sint32: 1. 28 | self assert: stream contents equals: #[ 2r1000 2r00000010 ]. 29 | 30 | stream := self newStream. 31 | stream writeField: 1 fixed32: 1. 32 | self assert: stream contents equals: #[ 2r00001101 0 0 0 1 ]. 33 | 34 | stream := self newStream. 35 | stream writeField: 1 int32: nil. 36 | self assert: stream contents equals: #[ ]. 37 | 38 | ] 39 | 40 | { #category : #tests } 41 | PBCodedWriteStreamTest >> testInteger64Fields [ 42 | 43 | | stream | 44 | 45 | stream := self newStream. 46 | stream writeField: 1 int64: 1. 47 | self assert: stream contents equals: #[ 2r00001000 2r00000001 ]. 48 | 49 | stream := self newStream. 50 | stream writeField: 1 uint64: 1. 51 | self assert: stream contents equals: #[ 2r00001000 2r00000001 ]. 52 | 53 | stream := self newStream. 54 | stream writeField: 1 sint64: 1. 55 | self assert: stream contents equals: #[ 2r1000 2r00000010 ]. 56 | 57 | stream := self newStream. 58 | stream writeField: 1 fixed64: 1. 59 | self assert: stream contents equals: #[ 2r00001001 0 0 0 0 0 0 0 1 ]. 60 | 61 | stream := self newStream. 62 | stream writeField: 1 int64: nil. 63 | self assert: stream contents equals: #[ ]. 64 | 65 | ] 66 | -------------------------------------------------------------------------------- /Protobuf-Core-Tests/PBProtobufCoderTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBProtobufCoderTest, 3 | #superclass : #TestCase, 4 | #instVars : [ 5 | 'coder' 6 | ], 7 | #category : #'Protobuf-Core-Tests' 8 | } 9 | 10 | { #category : #tests } 11 | PBProtobufCoderTest >> assertStream: aBlock equals: aByteArray [ 12 | 13 | self assert: (ByteArray streamContents: aBlock) equals: aByteArray 14 | ] 15 | 16 | { #category : #accessing } 17 | PBProtobufCoderTest >> coder [ 18 | 19 | ^ coder 20 | ] 21 | 22 | { #category : #initialization } 23 | PBProtobufCoderTest >> createCoder [ 24 | 25 | ^ PBProtobufCoder 26 | ] 27 | 28 | { #category : #initialization } 29 | PBProtobufCoderTest >> setUp [ 30 | 31 | super setUp. 32 | coder := self createCoder 33 | ] 34 | 35 | { #category : #tests } 36 | PBProtobufCoderTest >> testDouble [ 37 | 38 | | stream bytes | 39 | 40 | stream := WriteStream on: (ByteArray new: 100). 41 | coder writeDouble: 12345.67 on: stream. 42 | bytes := stream contents. 43 | 44 | self assert: bytes size equals: 8. 45 | self assert: (coder readDouble: bytes readStream) equals: 12345.67. 46 | 47 | ] 48 | 49 | { #category : #tests } 50 | PBProtobufCoderTest >> testEncodeZigZag [ 51 | 52 | self assert: (coder encodeZigZag32: 0) equals: 0. 53 | self assert: (coder encodeZigZag32: -1) equals: 1. 54 | self assert: (coder encodeZigZag32: 1) equals: 2. 55 | self assert: (coder encodeZigZag32: -2) equals: 3. 56 | self assert: (coder encodeZigZag32: 16r3FFFFFFF) equals: 16r7FFFFFFE. 57 | self assert: (coder encodeZigZag32: -16r40000000) equals: 16r7FFFFFFF. 58 | self assert: (coder encodeZigZag32: 16r7FFFFFFF) equals: 16rFFFFFFFE. 59 | self assert: (coder encodeZigZag32: -16r80000000) equals: 16rFFFFFFFF. 60 | 61 | self assert: (coder encodeZigZag64: 0) equals: 0. 62 | self assert: (coder encodeZigZag64: -1) equals: 1. 63 | self assert: (coder encodeZigZag64: 1) equals: 2. 64 | self assert: (coder encodeZigZag64: -2) equals: 3. 65 | 66 | self assert: (coder decodeZigZag32: 0) equals: 0. 67 | self assert: (coder decodeZigZag32: 1) equals: -1. 68 | self assert: (coder decodeZigZag32: 2) equals: 1. 69 | self assert: (coder decodeZigZag32: 3) equals: -2. 70 | 71 | self assert: (coder encodeZigZag32: (coder decodeZigZag32: 0)) equals: 0. 72 | self assert: (coder encodeZigZag32: (coder decodeZigZag32: 1)) equals: 1. 73 | "self assert: (coder encodeZigZag32: (coder decodeZigZag32: -1)) equals: -1." 74 | self assert: (coder encodeZigZag32: (coder decodeZigZag32: 14927)) equals: 14927. 75 | "self assert: (coder encodeZigZag32: (coder decodeZigZag32: -3612)) equals: -3612." 76 | 77 | ] 78 | 79 | { #category : #tests } 80 | PBProtobufCoderTest >> testFixed32 [ 81 | 82 | self assertStream: [ :s | coder writeFixed32: 0 on: s ] equals: #[ 0 0 0 0 ]. 83 | self assertStream: [ :s | coder writeFixed32: 1 on: s ] equals: #[ 0 0 0 1 ]. 84 | self assertStream: [ :s | coder writeFixed32: 16rFFFFFFFF on: s ] equals: #[ 16rFF 16rFF 16rFF 16rFF ]. 85 | 86 | self assert: (coder readFixed32: #[ 0 0 0 0 ] readStream) equals: 0. 87 | self assert: (coder readFixed32: #[ 0 0 0 1 ] readStream) equals: 1. 88 | self assert: (coder readFixed32: #[ 0 0 1 0 ] readStream) equals: 256. 89 | self assert: (coder readFixed32: #[ 16rFF 16rFF 16rFF 16rFF ] readStream) equals: 16rFFFFFFFF. 90 | ] 91 | 92 | { #category : #tests } 93 | PBProtobufCoderTest >> testFixed64 [ 94 | 95 | self assertStream: [ :s | coder writeFixed64: 0 on: s ] equals: #[ 0 0 0 0 0 0 0 0 ]. 96 | self assertStream: [ :s | coder writeFixed64: 1 on: s ] equals: #[ 0 0 0 0 0 0 0 1 ]. 97 | self assertStream: [ :s | coder writeFixed64: 16rFFFFFFFF on: s ] equals: #[ 0 0 0 0 16rFF 16rFF 16rFF 16rFF ]. 98 | self assertStream: [ :s | coder writeFixed64: 16rFFFFFFFFFFFFFFFF on: s ] equals: #[ 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF ]. 99 | 100 | self assert: (coder readFixed64: #[ 0 0 0 0 0 0 0 0 ] readStream) equals: 0. 101 | self assert: (coder readFixed64: #[ 0 0 0 0 0 0 0 1 ] readStream) equals: 1. 102 | 103 | 104 | ] 105 | 106 | { #category : #tests } 107 | PBProtobufCoderTest >> testFloat [ 108 | 109 | | stream bytes | 110 | 111 | stream := WriteStream on: (ByteArray new: 100). 112 | coder writeFloat: 123.67 on: stream. 113 | bytes := stream contents. 114 | 115 | self assert: bytes size equals: 4. 116 | self assert: ((coder readFloat: bytes readStream) - 123.67) abs < 0.001. 117 | 118 | ] 119 | 120 | { #category : #tests } 121 | PBProtobufCoderTest >> testSFixed32 [ 122 | 123 | self assertStream: [ :s | coder writeSFixed32: 0 on: s ] equals: #[ 0 0 0 0 ]. 124 | self assertStream: [ :s | coder writeSFixed32: 1 on: s ] equals: #[ 0 0 0 1 ]. 125 | self assertStream: [ :s | coder writeSFixed32: -1 on: s ] equals: #[ 16rFF 16rFF 16rFF 16rFF ]. 126 | self assertStream: [ :s | coder writeSFixed32: 16r00FFFFFF on: s ] equals: #[ 16r00 16rFF 16rFF 16rFF ]. 127 | 128 | self assert: (coder readSFixed32: #[ 0 0 0 0 ] readStream) equals: 0. 129 | self assert: (coder readSFixed32: #[ 0 0 0 1 ] readStream) equals: 1. 130 | self assert: (coder readSFixed32: #[ 0 0 1 0 ] readStream) equals: 256. 131 | self assert: (coder readSFixed32: #[ 16r00 16rFF 16rFF 16rFF ] readStream) equals: 16r00FFFFFF. 132 | self assert: (coder readSFixed32: #[ 16rFF 16rFF 16rFF 16rFF ] readStream) equals: -1. 133 | ] 134 | 135 | { #category : #tests } 136 | PBProtobufCoderTest >> testSFixed64 [ 137 | 138 | self assertStream: [ :s | coder writeSFixed64: 0 on: s ] equals: #[ 0 0 0 0 0 0 0 0 ]. 139 | self assertStream: [ :s | coder writeSFixed64: 1 on: s ] equals: #[ 0 0 0 0 0 0 0 1 ]. 140 | self assertStream: [ :s | coder writeSFixed64: -1 on: s ] equals: #[ 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF ]. 141 | self assertStream: [ :s | coder writeSFixed64: 16r00FFFFFF on: s ] equals: #[ 0 0 0 0 0 16rFF 16rFF 16rFF ]. 142 | 143 | self assert: (coder readSFixed64: #[ 0 0 0 0 0 0 0 0 ] readStream) equals: 0. 144 | self assert: (coder readSFixed64: #[ 0 0 0 0 0 0 0 1 ] readStream) equals: 1. 145 | self assert: (coder readSFixed64: #[ 0 0 0 0 0 0 1 0 ] readStream) equals: 256. 146 | self assert: (coder readSFixed64: #[ 16r00 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF ] readStream) equals: 16r00FFFFFFFFFFFFFF. 147 | self assert: (coder readSFixed64: #[ 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF ] readStream) equals: -1. 148 | ] 149 | 150 | { #category : #tests } 151 | PBProtobufCoderTest >> testVarInt32 [ 152 | 153 | self assert: (coder encodeVarint32: 0) equals: #[ 0 ]. 154 | self assert: (coder encodeVarint32: 1) equals: #[ 1 ]. 155 | self assert: (coder encodeVarint32: 300) equals: #[ 2r10101100 2r00000010 ]. 156 | self assert: (coder encodeVarint32: 16r7FFFFFFF) equals: #[ 16rFF 16rFF 16rFF 16rFF 16r07 ]. 157 | 158 | self assert: (coder encodeVarint32: -1) equals: #[ 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16r01 ]. 159 | 160 | #( 0 1 100 100000 16r7FFFFFF -1 -100 -100000 -16r7FFFFFF -16r80000000 ) do: [ :eachInt | 161 | self assert: (coder decodeVarint32: (coder encodeVarint32: eachInt)) equals: eachInt ]. 162 | 163 | ] 164 | 165 | { #category : #tests } 166 | PBProtobufCoderTest >> testVarInt64 [ 167 | 168 | self assert: (coder encodeVarint32: 0) equals: #[ 0 ]. 169 | self assert: (coder encodeVarint64: 1) equals: #[ 1 ]. 170 | self assert: (coder encodeVarint64: 300) equals: #[ 2r10101100 2r00000010 ]. 171 | 172 | self assert: (coder encodeVarint64: -1) size equals: 10. 173 | self assert: (coder encodeVarint64: -1) equals: #[ 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16r01 ]. 174 | 175 | #( 0 1 100 100000 16rFFFFFFFF 16r7fffFFFFffffFFFF -1 -100 -100000 -16rFFFFFFFF -16r7FFFFFFFFFFFFFF -16r8000000000000000 ) do: [ :eachInt | 176 | self assert: (coder decodeVarint64: (coder encodeVarint64: eachInt)) equals: eachInt ]. 177 | 178 | ] 179 | -------------------------------------------------------------------------------- /Protobuf-Core-Tests/PBProtobufTestMessage1.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBProtobufTestMessage1, 3 | #superclass : #PBMessage, 4 | #instVars : [ 5 | 'fieldOne', 6 | 'fieldTwo' 7 | ], 8 | #category : #'Protobuf-Core-Tests' 9 | } 10 | 11 | { #category : #writing } 12 | PBProtobufTestMessage1 >> clear [ 13 | 14 | fieldOne := ''. 15 | fieldTwo := 0 16 | ] 17 | 18 | { #category : #accessing } 19 | PBProtobufTestMessage1 >> fieldOne [ 20 | ^ fieldOne 21 | ] 22 | 23 | { #category : #accessing } 24 | PBProtobufTestMessage1 >> fieldOne: anObject [ 25 | fieldOne := anObject 26 | ] 27 | 28 | { #category : #accessing } 29 | PBProtobufTestMessage1 >> fieldTwo [ 30 | ^ fieldTwo 31 | ] 32 | 33 | { #category : #accessing } 34 | PBProtobufTestMessage1 >> fieldTwo: anObject [ 35 | fieldTwo := anObject 36 | ] 37 | 38 | { #category : #'input-output' } 39 | PBProtobufTestMessage1 >> readFrom: input [ 40 | 41 | | done dict | 42 | 43 | dict := Dictionary new 44 | add: 10 -> [ fieldOne := input readString ]; 45 | add: 16 -> [ fieldTwo := input readInt32 ]; 46 | yourself. 47 | 48 | self clear. 49 | done := false. 50 | [ done ] whileFalse: [ 51 | | tag | 52 | tag := input readTag. 53 | (dict at: tag ifAbsent: [ self readUnknownField: tag from: input ]) value. 54 | done := input atEnd ] 55 | ] 56 | 57 | { #category : #'input-output' } 58 | PBProtobufTestMessage1 >> writeTo: outputStream [ 59 | 60 | outputStream 61 | writeField: 1 string: fieldOne; 62 | writeField: 2 int32: fieldTwo 63 | ] 64 | -------------------------------------------------------------------------------- /Protobuf-Core-Tests/PBSmalltalkClassInfoMessage.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBSmalltalkClassInfoMessage, 3 | #superclass : #PBMessage, 4 | #instVars : [ 5 | 'name', 6 | 'superclassName', 7 | 'subclassNameList', 8 | 'instVarNameList', 9 | 'infoSize', 10 | 'infoIndexList', 11 | 'infoFinal' 12 | ], 13 | #category : #'Protobuf-Core-Tests' 14 | } 15 | 16 | { #category : #accessing } 17 | PBSmalltalkClassInfoMessage >> clear [ 18 | 19 | name := nil. 20 | superclassName := nil. 21 | subclassNameList := OrderedCollection new. 22 | instVarNameList := OrderedCollection new. 23 | infoSize := 0. 24 | infoIndexList := OrderedCollection new. 25 | infoFinal := false. 26 | 27 | ] 28 | 29 | { #category : #accessing } 30 | PBSmalltalkClassInfoMessage >> infoIndexList [ 31 | ^ infoIndexList 32 | ] 33 | 34 | { #category : #accessing } 35 | PBSmalltalkClassInfoMessage >> infoIndexList: anObject [ 36 | infoIndexList := anObject 37 | ] 38 | 39 | { #category : #accessing } 40 | PBSmalltalkClassInfoMessage >> infoSize [ 41 | ^ infoSize 42 | ] 43 | 44 | { #category : #accessing } 45 | PBSmalltalkClassInfoMessage >> infoSize: anObject [ 46 | ^ infoSize := anObject 47 | ] 48 | 49 | { #category : #accessing } 50 | PBSmalltalkClassInfoMessage >> instVarNameList [ 51 | ^ instVarNameList 52 | ] 53 | 54 | { #category : #accessing } 55 | PBSmalltalkClassInfoMessage >> instVarNameList: anObject [ 56 | instVarNameList := anObject 57 | ] 58 | 59 | { #category : #accessing } 60 | PBSmalltalkClassInfoMessage >> name [ 61 | ^ name 62 | ] 63 | 64 | { #category : #accessing } 65 | PBSmalltalkClassInfoMessage >> name: anObject [ 66 | ^ name := anObject 67 | ] 68 | 69 | { #category : #'input-output' } 70 | PBSmalltalkClassInfoMessage >> readFrom: input [ 71 | 72 | | done dict | 73 | 74 | dict := Dictionary new 75 | add: 10 -> [ name := input readString ]; 76 | add: 18 -> [ superclassName := input readString ]; 77 | add: 26 -> [ subclassNameList add: input readString ]; 78 | add: 34 -> [ instVarNameList add: input readString ]; 79 | add: 40 -> [ infoSize := input readUint64 ]; 80 | add: 72 -> [ infoIndexList add: input readInt32 ]; 81 | add: 74 -> [ infoIndexList addAll: input readInt32List ]; 82 | add: 80 -> [ infoFinal := input readBool ]; 83 | yourself. 84 | 85 | self clear. 86 | done := false. 87 | [ done ] whileFalse: [ 88 | | tag | 89 | tag := input readTag. 90 | (dict at: tag ifAbsent: [ self readUnknownField: tag from: input ]) value. 91 | done := input atEnd ] 92 | ] 93 | 94 | { #category : #accessing } 95 | PBSmalltalkClassInfoMessage >> subclassNameList [ 96 | ^ subclassNameList 97 | ] 98 | 99 | { #category : #accessing } 100 | PBSmalltalkClassInfoMessage >> subclassNameList: anObject [ 101 | subclassNameList := anObject 102 | ] 103 | 104 | { #category : #accessing } 105 | PBSmalltalkClassInfoMessage >> superclassName [ 106 | ^ superclassName 107 | ] 108 | 109 | { #category : #accessing } 110 | PBSmalltalkClassInfoMessage >> superclassName: anObject [ 111 | ^ superclassName := anObject 112 | ] 113 | 114 | { #category : #'input-output' } 115 | PBSmalltalkClassInfoMessage >> writeTo: output [ 116 | 117 | output writeField: 1 string: name. 118 | output writeField: 2 string: superclassName. 119 | output writeField: 3 stringList: subclassNameList. 120 | output writeField: 4 stringList: instVarNameList. 121 | output writeField: 5 uint64: infoSize. 122 | output writeField: 9 int32List: infoIndexList. 123 | output writeField: 10 bool: infoFinal 124 | ] 125 | -------------------------------------------------------------------------------- /Protobuf-Core-Tests/PBSmalltalkClassInfoMessageTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBSmalltalkClassInfoMessageTest, 3 | #superclass : #TestCase, 4 | #category : #'Protobuf-Core-Tests' 5 | } 6 | 7 | { #category : #resources } 8 | PBSmalltalkClassInfoMessageTest >> messageBytes [ 9 | "'C:\Stuff\pbdemo-java\ExportProtobufTest.pb' asFileReference binaryReadStream contents" 10 | 11 | ^#[ 10 10 68 105 99 116 105 111 110 97 114 121 18 10 67 111 108 108 101 99 116 105 111 110 34 5 105 110 100 101 120 34 5 97 114 114 97 121 40 149 154 239 58 74 14 100 162 254 255 255 255 255 255 255 255 1 159 141 6 80 1 ] 12 | ] 13 | 14 | { #category : #resources } 15 | PBSmalltalkClassInfoMessageTest >> packageMessageBytes [ 16 | "'C:\Stuff\pbdemo-java\ExportProtobufPackage.pb' asFileReference binaryReadStream contents" 17 | 18 | ^#[ 10 18 77 121 83 109 97 108 108 116 97 108 107 80 97 99 107 97 103 101 18 38 10 10 68 105 99 116 105 111 110 97 114 121 18 10 67 111 108 108 101 99 116 105 111 110 34 5 105 110 100 101 120 34 5 97 114 114 97 121 18 61 10 17 79 114 100 101 114 101 100 67 111 108 108 101 99 116 105 111 110 18 10 67 111 108 108 101 99 116 105 111 110 34 5 97 114 114 97 121 34 10 102 105 114 115 116 73 110 100 101 120 34 9 108 97 115 116 73 110 100 101 120 ] 19 | ] 20 | 21 | { #category : #tests } 22 | PBSmalltalkClassInfoMessageTest >> testRead [ 23 | 24 | | input info1 | 25 | 26 | input := PBCodedReadStream on: self messageBytes readStream. 27 | 28 | info1 := PBSmalltalkClassInfoMessage readFrom: input. 29 | 30 | self assert: info1 name equals: 'Dictionary'. 31 | self assert: info1 instVarNameList asArray equals: #( 'index' 'array' ). 32 | self assert: info1 infoSize equals: 123456789. 33 | self assert: info1 infoIndexList asArray equals: #( 100 -222 99999 ). 34 | 35 | 36 | ] 37 | 38 | { #category : #tests } 39 | PBSmalltalkClassInfoMessageTest >> testReadPackage [ 40 | 41 | | input p1 | 42 | 43 | input := PBCodedReadStream on: self packageMessageBytes readStream. 44 | 45 | p1 := PBSmalltalkPackageMessage readFrom: input. 46 | 47 | self assert: p1 name equals: 'MySmalltalkPackage'. 48 | self assert: p1 classList size equals: 2. 49 | self assert: p1 classList first name equals: 'Dictionary'. 50 | self assert: p1 classList last name equals: 'OrderedCollection'. 51 | 52 | ] 53 | 54 | { #category : #tests } 55 | PBSmalltalkClassInfoMessageTest >> testWriteClassInfo [ 56 | 57 | | msg bytes result | 58 | 59 | msg := PBSmalltalkClassInfoMessage new 60 | name: 'C'; 61 | instVarNameList: #( 't' 'n' ); 62 | yourself. 63 | 64 | bytes := ByteArray streamContents: [ :s | 65 | (PBCodedWriteStream on: s) writeField: 1 message: msg ]. 66 | 67 | self assert: bytes equals: #[10 9 10 1 67 34 1 116 34 1 110]. 68 | 69 | result := (PBCodedReadStream on: bytes readStream) 70 | readTag; 71 | readMessage: PBSmalltalkClassInfoMessage. 72 | 73 | self assert: msg name equals: result name. 74 | self assert: msg instVarNameList asArray equals: result instVarNameList asArray. 75 | ] 76 | 77 | { #category : #tests } 78 | PBSmalltalkClassInfoMessageTest >> testWriteClassInfoList [ 79 | 80 | | list bytes input result | 81 | 82 | list := Number withAllSubclasses collect: [ :eachClass | 83 | PBSmalltalkClassInfoMessage new 84 | name: eachClass name asString; 85 | instVarNameList: eachClass instVarNames; 86 | yourself ]. 87 | 88 | bytes := ByteArray streamContents: [ :s | 89 | (PBCodedWriteStream on: s) writeField: 1 messageList: list ]. 90 | 91 | input := PBCodedReadStream on: bytes readStream. 92 | result := (1 to: list size) collect: [ :index | 93 | self assert: input readTag equals: 2r1010. 94 | input readMessage: PBSmalltalkClassInfoMessage ]. 95 | 96 | 1 to: list size do: [ :index | 97 | self assert: (list at: index) name equals: (result at: index) name. 98 | self assert: (list at: index) instVarNameList asArray equals: (result at: index) instVarNameList asArray ] 99 | ] 100 | -------------------------------------------------------------------------------- /Protobuf-Core-Tests/PBSmalltalkPackageMessage.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBSmalltalkPackageMessage, 3 | #superclass : #PBMessage, 4 | #instVars : [ 5 | 'name', 6 | 'classList' 7 | ], 8 | #category : #'Protobuf-Core-Tests' 9 | } 10 | 11 | { #category : #accessing } 12 | PBSmalltalkPackageMessage >> classList [ 13 | ^ classList 14 | ] 15 | 16 | { #category : #accessing } 17 | PBSmalltalkPackageMessage >> classList: anObject [ 18 | classList := anObject 19 | ] 20 | 21 | { #category : #'instance creation' } 22 | PBSmalltalkPackageMessage >> clear [ 23 | 24 | name := nil. 25 | classList := OrderedCollection new. 26 | ] 27 | 28 | { #category : #accessing } 29 | PBSmalltalkPackageMessage >> name [ 30 | ^ name 31 | ] 32 | 33 | { #category : #accessing } 34 | PBSmalltalkPackageMessage >> name: anObject [ 35 | name := anObject 36 | ] 37 | 38 | { #category : #'instance creation' } 39 | PBSmalltalkPackageMessage >> readFrom: input [ 40 | 41 | | done dict | 42 | 43 | dict := Dictionary new 44 | add: 10 -> [ name := input readString ]; 45 | add: 18 -> [ classList add: (input readMessage: PBSmalltalkClassInfoMessage) ]; 46 | yourself. 47 | 48 | self clear. 49 | done := false. 50 | [ done ] whileFalse: [ 51 | | tag | 52 | tag := input readTag. 53 | (dict at: tag ifAbsent: [ self readUnknownField: tag from: input ]) value. 54 | done := input atEnd ] 55 | ] 56 | 57 | { #category : #writing } 58 | PBSmalltalkPackageMessage >> writeTo: output [ 59 | 60 | output writeField: 1 string: name. 61 | output writeField: 2 messageList: classList 62 | 63 | ] 64 | -------------------------------------------------------------------------------- /Protobuf-Core-Tests/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Protobuf-Core-Tests' } 2 | -------------------------------------------------------------------------------- /Protobuf-Core/PBCodedReadStream.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBCodedReadStream, 3 | #superclass : #Object, 4 | #instVars : [ 5 | 'stream', 6 | 'coder' 7 | ], 8 | #pools : [ 9 | 'PBProtobufConstants' 10 | ], 11 | #category : #'Protobuf-Core' 12 | } 13 | 14 | { #category : #'instance creation' } 15 | PBCodedReadStream class >> on: aByteStream [ 16 | 17 | ^self new on: aByteStream 18 | ] 19 | 20 | { #category : #accessing } 21 | PBCodedReadStream >> atEnd [ 22 | 23 | ^ stream atEnd 24 | ] 25 | 26 | { #category : #accessing } 27 | PBCodedReadStream >> coder [ 28 | 29 | ^ coder 30 | ] 31 | 32 | { #category : #'instance creation' } 33 | PBCodedReadStream >> on: aByteStream [ 34 | 35 | self on: aByteStream coder: PBProtobufCoder 36 | ] 37 | 38 | { #category : #'instance creation' } 39 | PBCodedReadStream >> on: aByteStream coder: aCoder [ 40 | 41 | stream := aByteStream. 42 | coder := aCoder 43 | ] 44 | 45 | { #category : #'write and read' } 46 | PBCodedReadStream >> readBool [ 47 | 48 | ^ (coder readVarintRaw: stream) ~= 0 49 | ] 50 | 51 | { #category : #'write and read' } 52 | PBCodedReadStream >> readBoolList [ 53 | 54 | | size list limit | 55 | 56 | size := coder readVarintRaw: stream. 57 | list := OrderedCollection new: size. 58 | limit := stream position + size. 59 | [ stream position < limit ] 60 | whileTrue: [ list add: (coder readVarintRaw: stream) ~= 0 ]. 61 | stream position = limit 62 | ifFalse: [ self error: 'wrong' ]. 63 | ^ list 64 | ] 65 | 66 | { #category : #'write and read' } 67 | PBCodedReadStream >> readBytes [ 68 | | byteCount | 69 | byteCount := coder readVarintRaw: stream. 70 | ^ stream next: byteCount 71 | ] 72 | 73 | { #category : #'write and read' } 74 | PBCodedReadStream >> readDouble [ 75 | 76 | ^coder readDouble: stream 77 | ] 78 | 79 | { #category : #'write and read' } 80 | PBCodedReadStream >> readDoubleList [ 81 | 82 | | length size list | 83 | 84 | length := coder readVarintRaw: stream. 85 | length \\ 8 ~= 0 86 | ifTrue: [ self error: 'Invalid double list length' ]. 87 | size := length / 8. 88 | 89 | list := OrderedCollection new: size. 90 | size timesRepeat: [ 91 | list add: (coder readDouble: stream) ]. 92 | 93 | ^ list 94 | ] 95 | 96 | { #category : #'write and read' } 97 | PBCodedReadStream >> readFixed32 [ 98 | 99 | ^coder readFixed32: stream 100 | ] 101 | 102 | { #category : #'write and read' } 103 | PBCodedReadStream >> readFixed32List [ 104 | 105 | | length size list | 106 | 107 | length := coder readVarintRaw: stream. 108 | length \\ 4 ~= 0 109 | ifTrue: [ self error: 'Invalid fixed32 list length' ]. 110 | size := length / 4. 111 | 112 | list := OrderedCollection new: size. 113 | size timesRepeat: [ 114 | list add: (coder readFixed32: stream) ]. 115 | 116 | ^ list 117 | ] 118 | 119 | { #category : #'write and read' } 120 | PBCodedReadStream >> readFixed64 [ 121 | 122 | ^coder readFixed64: stream 123 | ] 124 | 125 | { #category : #'write and read' } 126 | PBCodedReadStream >> readFixed64List [ 127 | 128 | | length size list | 129 | 130 | length := coder readVarintRaw: stream. 131 | length \\ 8 ~= 0 132 | ifTrue: [ self error: 'Invalid fixed64 list length' ]. 133 | size := length // 8. 134 | 135 | list := OrderedCollection new: size. 136 | size timesRepeat: [ 137 | list add: (coder readFixed64: stream) ]. 138 | 139 | ^ list 140 | ] 141 | 142 | { #category : #'write and read' } 143 | PBCodedReadStream >> readFloat [ 144 | 145 | ^coder readFloat: stream 146 | ] 147 | 148 | { #category : #'write and read' } 149 | PBCodedReadStream >> readFloatList [ 150 | 151 | | length size list | 152 | 153 | length := coder readVarintRaw: stream. 154 | length \\ 4 ~= 0 155 | ifTrue: [ self error: 'Invalid float list length' ]. 156 | size := length / 4. 157 | 158 | list := OrderedCollection new: size. 159 | size timesRepeat: [ 160 | list add: (coder readFloat: stream) ]. 161 | 162 | ^ list 163 | ] 164 | 165 | { #category : #'write and read' } 166 | PBCodedReadStream >> readInt32 [ 167 | 168 | ^self coder readVarint32: stream 169 | ] 170 | 171 | { #category : #'write and read' } 172 | PBCodedReadStream >> readInt32List [ 173 | 174 | | length list limit | 175 | 176 | length := self coder readVarintRaw: stream. 177 | list := OrderedCollection new: length. 178 | limit := stream position + length. 179 | [ stream position < limit ] 180 | whileTrue: [ list add: (self coder readVarint32: stream) ]. 181 | stream position = limit 182 | ifFalse: [ self error: 'wrong' ]. 183 | ^ list 184 | ] 185 | 186 | { #category : #'write and read' } 187 | PBCodedReadStream >> readInt64 [ 188 | 189 | ^self coder readVarint64: stream 190 | ] 191 | 192 | { #category : #'write and read' } 193 | PBCodedReadStream >> readMessage: aMessageClass [ 194 | 195 | | length substream | 196 | 197 | length := self coder readVarintRaw: stream. 198 | 199 | substream := ReadStream on: stream originalContents 200 | from: stream position + 1 201 | to: stream position + length. 202 | 203 | stream skip: length. 204 | 205 | ^ aMessageClass readFrom: (self class on: substream) 206 | 207 | ] 208 | 209 | { #category : #'write and read' } 210 | PBCodedReadStream >> readSfixed32 [ 211 | 212 | ^coder readSFixed32: stream 213 | ] 214 | 215 | { #category : #'write and read' } 216 | PBCodedReadStream >> readSfixed32List [ 217 | 218 | | length list | 219 | 220 | length := coder readVarintRaw: stream. 221 | length \\ 4 ~= 0 222 | ifTrue: [ self error: 'Invalid sfixed32 list length' ]. 223 | 224 | list := OrderedCollection new: length / 4. 225 | list size timesRepeat: [ 226 | list add: (coder readSFixed32: stream) ]. 227 | 228 | ^ list 229 | ] 230 | 231 | { #category : #'write and read' } 232 | PBCodedReadStream >> readSfixed64 [ 233 | 234 | ^coder readSFixed64: stream 235 | ] 236 | 237 | { #category : #'write and read' } 238 | PBCodedReadStream >> readSfixed64List [ 239 | 240 | | length size list | 241 | 242 | length := coder readVarintRaw: stream. 243 | length \\ 8 ~= 0 244 | ifTrue: [ self error: 'Invalid sfixed64 list length' ]. 245 | size := length // 8. 246 | 247 | list := OrderedCollection new: size. 248 | size timesRepeat: [ 249 | list add: (coder readSFixed64: stream) ]. 250 | 251 | ^ list 252 | ] 253 | 254 | { #category : #'write and read' } 255 | PBCodedReadStream >> readSint32 [ 256 | 257 | ^coder decodeZigZag32: (coder readVarintRaw: stream) 258 | ] 259 | 260 | { #category : #'write and read' } 261 | PBCodedReadStream >> readSint64 [ 262 | 263 | ^coder decodeZigZag64: (coder readVarintRaw: stream) 264 | ] 265 | 266 | { #category : #'write and read' } 267 | PBCodedReadStream >> readString [ 268 | 269 | | byteCount | 270 | 271 | byteCount := coder readVarintRaw: stream. 272 | ^ coder readString: byteCount from: stream 273 | ] 274 | 275 | { #category : #'as yet unclassified' } 276 | PBCodedReadStream >> readTag [ 277 | 278 | | lastTag | 279 | 280 | lastTag := self coder readVarintRaw: stream. 281 | (self coder getTagFieldNumber: lastTag) = 0 282 | ifTrue: [ self invalidProtobufError: 'Invalid tag' ]. 283 | ^ lastTag 284 | ] 285 | 286 | { #category : #'write and read' } 287 | PBCodedReadStream >> readUint32 [ 288 | ^ self coder readVarint32: stream 289 | ] 290 | 291 | { #category : #'write and read' } 292 | PBCodedReadStream >> readUint64 [ 293 | 294 | ^self coder readVarintRaw: stream 295 | ] 296 | 297 | { #category : #'as yet unclassified' } 298 | PBCodedReadStream >> skipField: aTag [ 299 | 300 | (self coder isVarintField: aTag) 301 | ifTrue: [ 302 | self coder readVarintRaw: stream. 303 | ^self ]. 304 | 305 | (self coder is64bitField: aTag) 306 | ifTrue: [ 307 | stream skip: 8. 308 | ^self ]. 309 | 310 | (self coder isLengthDelimitedField: aTag) 311 | ifTrue: [ 312 | stream skip: (self coder readVarintRaw: stream). 313 | ^self ]. 314 | 315 | (self coder is32bitField: aTag) 316 | ifTrue: [ 317 | stream skip: 4. 318 | ^self ]. 319 | 320 | self error: 'Unknown wire type' 321 | 322 | ] 323 | -------------------------------------------------------------------------------- /Protobuf-Core/PBCodedWriteStream.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBCodedWriteStream, 3 | #superclass : #Object, 4 | #instVars : [ 5 | 'stream', 6 | 'coder' 7 | ], 8 | #pools : [ 9 | 'PBProtobufConstants' 10 | ], 11 | #category : #'Protobuf-Core' 12 | } 13 | 14 | { #category : #'instance creation' } 15 | PBCodedWriteStream class >> on: aByteStream [ 16 | 17 | ^self new on: aByteStream 18 | ] 19 | 20 | { #category : #'as yet unclassified' } 21 | PBCodedWriteStream >> buffer: aBlock [ 22 | 23 | ^ByteArray streamContents: aBlock 24 | ] 25 | 26 | { #category : #accessing } 27 | PBCodedWriteStream >> coder [ 28 | 29 | ^ coder 30 | ] 31 | 32 | { #category : #accessing } 33 | PBCodedWriteStream >> contents [ 34 | 35 | ^stream contents 36 | ] 37 | 38 | { #category : #initialization } 39 | PBCodedWriteStream >> on: aByteStream [ 40 | 41 | self on: aByteStream coder: PBProtobufCoder 42 | ] 43 | 44 | { #category : #initialization } 45 | PBCodedWriteStream >> on: aByteStream coder: aCoder [ 46 | 47 | stream := aByteStream. 48 | coder := aCoder 49 | ] 50 | 51 | { #category : #writing } 52 | PBCodedWriteStream >> writeEnum: anEnumInteger [ 53 | 54 | anEnumInteger isNil 55 | ifTrue: [ ^ self ]. 56 | coder writeVarintRaw: anEnumInteger on: stream 57 | 58 | ] 59 | 60 | { #category : #writing } 61 | PBCodedWriteStream >> writeField: aFieldNr bool: aValue [ 62 | "Only write somthing if is true." 63 | 64 | aValue = true 65 | ifTrue: [ 66 | self writeTag: aFieldNr type: WireTypeVarint. 67 | coder writeVarintRaw: 1 on: stream ] 68 | ] 69 | 70 | { #category : #writing } 71 | PBCodedWriteStream >> writeField: aFieldNr boolList: aList [ 72 | 73 | aList isEmptyOrNil 74 | ifTrue: [ ^ self ]. 75 | 76 | self writeTag: aFieldNr type: WireTypeLengthDelimited. 77 | coder writeVarintRaw: aList size on: stream. 78 | aList do: [ :eachBool | 79 | coder writeVarintRaw: (eachBool ifTrue: [ 1 ] ifFalse: [ 0 ]) on: stream ] 80 | ] 81 | 82 | { #category : #writing } 83 | PBCodedWriteStream >> writeField: aFieldNr bytes: aByteArray [ 84 | 85 | aByteArray isEmptyOrNil 86 | ifTrue: [ ^ self ]. 87 | 88 | self writeTag: aFieldNr type: WireTypeLengthDelimited. 89 | coder writeVarintRaw: aByteArray size on: stream. 90 | stream nextPutAll: aByteArray 91 | ] 92 | 93 | { #category : #writing } 94 | PBCodedWriteStream >> writeField: aFieldNr double: aValue [ 95 | 96 | aValue isNil 97 | ifTrue: [ ^ self ]. 98 | 99 | self writeTag: aFieldNr type: WireType64bit. 100 | coder writeDouble: aValue on: stream 101 | ] 102 | 103 | { #category : #writing } 104 | PBCodedWriteStream >> writeField: aFieldNr doubleList: aList [ 105 | 106 | aList isEmptyOrNil 107 | ifTrue: [ ^ self ]. 108 | 109 | self writeTag: aFieldNr type: WireTypeLengthDelimited. 110 | coder writeVarintRaw: aList size * 8 on: stream. 111 | aList do: [ :eachInt | 112 | coder writeDouble: eachInt on: stream ] 113 | ] 114 | 115 | { #category : #writing } 116 | PBCodedWriteStream >> writeField: aFieldNr fixed32: aValue [ 117 | 118 | aValue isNil 119 | ifTrue: [ ^ self ]. 120 | 121 | self writeTag: aFieldNr type: WireType32bit. 122 | coder writeFixed32: aValue on: stream 123 | ] 124 | 125 | { #category : #writing } 126 | PBCodedWriteStream >> writeField: aFieldNr fixed32List: aList [ 127 | 128 | aList isEmptyOrNil 129 | ifTrue: [ ^ self ]. 130 | 131 | self writeTag: aFieldNr type: WireTypeLengthDelimited. 132 | coder writeVarintRaw: aList size * 4 on: stream. 133 | aList do: [ :eachInt | 134 | coder writeFixed32: eachInt on: stream ] 135 | ] 136 | 137 | { #category : #writing } 138 | PBCodedWriteStream >> writeField: aFieldNr fixed64: aValue [ 139 | 140 | aValue isNil 141 | ifTrue: [ ^ self ]. 142 | 143 | self writeTag: aFieldNr type: WireType64bit. 144 | coder writeFixed64: aValue on: stream 145 | ] 146 | 147 | { #category : #writing } 148 | PBCodedWriteStream >> writeField: aFieldNr fixed64List: aList [ 149 | 150 | aList isEmptyOrNil 151 | ifTrue: [ ^ self ]. 152 | 153 | self writeTag: aFieldNr type: WireTypeLengthDelimited. 154 | coder writeVarintRaw: aList size * 8 on: stream. 155 | aList do: [ :eachInt | 156 | coder writeFixed64: eachInt on: stream ] 157 | ] 158 | 159 | { #category : #writing } 160 | PBCodedWriteStream >> writeField: aFieldNr float: aValue [ 161 | 162 | aValue isNil 163 | ifTrue: [ ^ self ]. 164 | 165 | self writeTag: aFieldNr type: WireType64bit. 166 | coder writeFloat: aValue on: stream 167 | ] 168 | 169 | { #category : #writing } 170 | PBCodedWriteStream >> writeField: aFieldNr floatList: aList [ 171 | 172 | aList isEmptyOrNil 173 | ifTrue: [ ^ self ]. 174 | 175 | self writeTag: aFieldNr type: WireTypeLengthDelimited. 176 | coder writeVarintRaw: aList size * 4 on: stream. 177 | aList do: [ :eachInt | 178 | coder writeFloat: eachInt on: stream ] 179 | ] 180 | 181 | { #category : #writing } 182 | PBCodedWriteStream >> writeField: aFieldNr int32: aValue [ 183 | 184 | aValue isNil 185 | ifTrue: [ ^ self ]. 186 | 187 | self writeTag: aFieldNr type: WireTypeVarint. 188 | coder writeVarint32: aValue on: stream 189 | ] 190 | 191 | { #category : #writing } 192 | PBCodedWriteStream >> writeField: aFieldNr int32List: aList [ 193 | 194 | | bufStream | 195 | 196 | aList isEmptyOrNil 197 | ifTrue: [ ^ self ]. 198 | 199 | bufStream := WriteStream on: (ByteArray new: aList size * 4). 200 | aList do: [ :eachInteger | 201 | coder writeVarint32: eachInteger on: bufStream ]. 202 | 203 | self writeField: aFieldNr bytes: bufStream contents 204 | ] 205 | 206 | { #category : #writing } 207 | PBCodedWriteStream >> writeField: aFieldNr int64: aValue [ 208 | 209 | aValue isNil 210 | ifTrue: [ ^ self ]. 211 | 212 | self writeTag: aFieldNr type: WireTypeVarint. 213 | coder writeVarint64: aValue on: stream 214 | ] 215 | 216 | { #category : #writing } 217 | PBCodedWriteStream >> writeField: aFieldNr message: aMessage [ 218 | | msgBytes | 219 | aMessage isNil 220 | ifTrue: [ ^ self ]. 221 | aMessage isEnum 222 | ifTrue: [ self writeField: aFieldNr int32: aMessage value ] 223 | ifFalse: [ msgBytes := self 224 | buffer: [ :s | aMessage writeTo: (self class on: s) ]. 225 | self writeField: aFieldNr bytes: msgBytes ] 226 | 227 | ] 228 | 229 | { #category : #writing } 230 | PBCodedWriteStream >> writeField: aFieldNr messageList: aList [ 231 | 232 | aList isNil 233 | ifTrue: [ ^ self ]. 234 | 235 | aList do: [ :eachMessage | 236 | self writeField: aFieldNr message: eachMessage ] 237 | ] 238 | 239 | { #category : #writing } 240 | PBCodedWriteStream >> writeField: aFieldNr sfixed32: aValue [ 241 | 242 | aValue isNil 243 | ifTrue: [ ^ self ]. 244 | 245 | self writeTag: aFieldNr type: WireType32bit. 246 | coder writeSFixed32: aValue on: stream 247 | ] 248 | 249 | { #category : #writing } 250 | PBCodedWriteStream >> writeField: aFieldNr sfixed32List: aList [ 251 | 252 | aList isEmptyOrNil 253 | ifTrue: [ ^ self ]. 254 | 255 | self writeTag: aFieldNr type: WireTypeLengthDelimited. 256 | coder writeVarintRaw: aList size * 4 on: stream. 257 | aList do: [ :eachInt | 258 | coder writeSFixed32: eachInt on: stream ] 259 | ] 260 | 261 | { #category : #writing } 262 | PBCodedWriteStream >> writeField: aFieldNr sfixed64: aValue [ 263 | 264 | aValue isNil 265 | ifTrue: [ ^ self ]. 266 | 267 | self writeTag: aFieldNr type: WireType64bit. 268 | coder writeSFixed64: aValue on: stream 269 | ] 270 | 271 | { #category : #writing } 272 | PBCodedWriteStream >> writeField: aFieldNr sfixed64List: aList [ 273 | 274 | aList isEmptyOrNil 275 | ifTrue: [ ^ self ]. 276 | 277 | self writeTag: aFieldNr type: WireTypeLengthDelimited. 278 | coder writeVarintRaw: aList size * 8 on: stream. 279 | aList do: [ :eachInt | 280 | coder writeSFixed64: eachInt on: stream ] 281 | ] 282 | 283 | { #category : #writing } 284 | PBCodedWriteStream >> writeField: aFieldNr sint32: aValue [ 285 | 286 | aValue isNil 287 | ifTrue: [ ^ self ]. 288 | 289 | self writeTag: aFieldNr type: WireTypeVarint. 290 | coder writeVarintRaw: (coder encodeZigZag32: aValue) on: stream 291 | ] 292 | 293 | { #category : #writing } 294 | PBCodedWriteStream >> writeField: aFieldNr sint64: aValue [ 295 | 296 | aValue isNil 297 | ifTrue: [ ^ self ]. 298 | 299 | self writeTag: aFieldNr type: WireTypeVarint. 300 | coder writeVarintRaw: (coder encodeZigZag64: aValue) on: stream 301 | ] 302 | 303 | { #category : #writing } 304 | PBCodedWriteStream >> writeField: aFieldNr string: aValue [ 305 | 306 | | bytes | 307 | 308 | aValue isNil 309 | ifTrue: [ ^ self ]. 310 | 311 | bytes := self buffer: [ :s | coder writeString: aValue on: s ]. 312 | self writeField: aFieldNr bytes: bytes 313 | ] 314 | 315 | { #category : #writing } 316 | PBCodedWriteStream >> writeField: aFieldNr stringList: aList [ 317 | 318 | aList isNil 319 | ifTrue: [ ^ self ]. 320 | 321 | aList do: [ :eachString | 322 | self writeField: aFieldNr string: eachString ] 323 | ] 324 | 325 | { #category : #writing } 326 | PBCodedWriteStream >> writeField: aFieldNr uint32: aValue [ 327 | 328 | aValue isNil 329 | ifTrue: [ ^ self ]. 330 | 331 | self writeTag: aFieldNr type: WireTypeVarint. 332 | coder writeVarintRaw: aValue on: stream 333 | ] 334 | 335 | { #category : #writing } 336 | PBCodedWriteStream >> writeField: aFieldNr uint64: aValue [ 337 | 338 | aValue isNil 339 | ifTrue: [ ^ self ]. 340 | 341 | self writeTag: aFieldNr type: WireTypeVarint. 342 | coder writeVarintRaw: aValue on: stream 343 | ] 344 | 345 | { #category : #writing } 346 | PBCodedWriteStream >> writeTag: aFieldNr type: aWireTypeNr [ 347 | 348 | coder writeVarintRaw: (coder makeTag: aFieldNr wireType: aWireTypeNr) on: stream 349 | ] 350 | -------------------------------------------------------------------------------- /Protobuf-Core/PBEnum.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBEnum, 3 | #superclass : #PBType, 4 | #instVars : [ 5 | 'value' 6 | ], 7 | #category : #'Protobuf-Core' 8 | } 9 | 10 | { #category : #testing } 11 | PBEnum >> isEnum [ ^true 12 | ] 13 | 14 | { #category : #'input-output' } 15 | PBEnum >> readFrom: aCodedReadStream [ 16 | value :=aCodedReadStream coder readVarint32: aCodedReadStream 17 | ] 18 | 19 | { #category : #accessing } 20 | PBEnum >> value [ 21 | ^value 22 | ] 23 | 24 | { #category : #accessing } 25 | PBEnum >> value:aVal [ 26 | value:= aVal 27 | ] 28 | 29 | { #category : #'input-output' } 30 | PBEnum >> writeTo: pbWriteStream [ 31 | pbWriteStream writeEnum:value 32 | 33 | 34 | ] 35 | -------------------------------------------------------------------------------- /Protobuf-Core/PBMessage.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBMessage, 3 | #superclass : #PBType, 4 | #category : #'Protobuf-Core' 5 | } 6 | 7 | { #category : #testing } 8 | PBMessage >> isMessage [ 9 | ^ true 10 | ] 11 | 12 | { #category : #'input-output' } 13 | PBMessage >> readUnknownField: aTag from: anInput [ 14 | 15 | anInput skipField: aTag 16 | ] 17 | -------------------------------------------------------------------------------- /Protobuf-Core/PBProtobufCoder.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBProtobufCoder, 3 | #superclass : #Object, 4 | #pools : [ 5 | 'PBProtobufConstants' 6 | ], 7 | #category : #'Protobuf-Core' 8 | } 9 | 10 | { #category : #'coder-varint' } 11 | PBProtobufCoder class >> decodeVarint32: aByteArray [ 12 | 13 | ^ self readVarint32: aByteArray readStream 14 | ] 15 | 16 | { #category : #'coder-varint' } 17 | PBProtobufCoder class >> decodeVarint64: aByteArray [ 18 | 19 | ^ self readVarint64: aByteArray readStream 20 | ] 21 | 22 | { #category : #'coder-varint' } 23 | PBProtobufCoder class >> decodeZigZag32: anInteger [ 24 | 25 | ^(anInteger bitAt: 1) = 0 26 | ifTrue: [ anInteger >> 1 ] 27 | ifFalse: [ ((anInteger + 1) >> 1) negated ] 28 | ] 29 | 30 | { #category : #'coder-varint' } 31 | PBProtobufCoder class >> decodeZigZag64: anInteger [ 32 | 33 | ^(anInteger bitAt: 1) = 0 34 | ifTrue: [ anInteger >> 1 ] 35 | ifFalse: [ ((anInteger + 1) >> 1) negated ] 36 | ] 37 | 38 | { #category : #'coder-varint' } 39 | PBProtobufCoder class >> encodeVarint32: anInteger [ 40 | 41 | ^ ByteArray streamContents: [ :s | self writeVarint32: anInteger on: s ] 42 | ] 43 | 44 | { #category : #'coder-varint' } 45 | PBProtobufCoder class >> encodeVarint64: anInteger [ 46 | 47 | ^ ByteArray streamContents: [ :s | self writeVarint64: anInteger on: s ] 48 | ] 49 | 50 | { #category : #'coder-varint' } 51 | PBProtobufCoder class >> encodeZigZag32: anInteger [ 52 | 53 | ^ anInteger >= 0 54 | ifTrue: [ (anInteger << 1) ] 55 | ifFalse: [ (anInteger negated << 1) - 1 ] 56 | ] 57 | 58 | { #category : #'coder-varint' } 59 | PBProtobufCoder class >> encodeZigZag64: anInteger [ 60 | 61 | ^ anInteger >= 0 62 | ifTrue: [ (anInteger << 1) ] 63 | ifFalse: [ (anInteger negated << 1) - 1 ] 64 | ] 65 | 66 | { #category : #'coder-tags' } 67 | PBProtobufCoder class >> getTagFieldNumber: anInteger [ 68 | "Given a tag value, determines the field number (the upper 29 bits)." 69 | 70 | ^ anInteger >> 3 71 | ] 72 | 73 | { #category : #'coder-tags' } 74 | PBProtobufCoder class >> getTagWireType: anInteger [ 75 | "Given a tag value, determines the wire type (the lower 3 bits)." 76 | 77 | ^ anInteger bitAnd: 2r111 78 | ] 79 | 80 | { #category : #testing } 81 | PBProtobufCoder class >> is32bitField: aTag [ 82 | 83 | ^(self getTagWireType: aTag) = WireType32bit 84 | ] 85 | 86 | { #category : #testing } 87 | PBProtobufCoder class >> is64bitField: aTag [ 88 | 89 | ^(self getTagWireType: aTag) = WireType64bit 90 | ] 91 | 92 | { #category : #testing } 93 | PBProtobufCoder class >> isLengthDelimitedField: aTag [ 94 | 95 | ^(self getTagWireType: aTag) = WireTypeLengthDelimited 96 | ] 97 | 98 | { #category : #testing } 99 | PBProtobufCoder class >> isVarintField: aTag [ 100 | 101 | ^(self getTagWireType: aTag) = WireTypeVarint 102 | ] 103 | 104 | { #category : #'coder-tags' } 105 | PBProtobufCoder class >> makeTag: aFieldNr wireType: aTypeNr [ 106 | 107 | ^ (aFieldNr << 3) bitOr: aTypeNr 108 | ] 109 | 110 | { #category : #'coder-fixed' } 111 | PBProtobufCoder class >> readDouble: aByteStream [ 112 | 113 | ^ (aByteStream next: 8) doubleAt: 1 114 | ] 115 | 116 | { #category : #'coder-fixed' } 117 | PBProtobufCoder class >> readFixed32: aByteStream [ 118 | 119 | | n | 120 | n := aByteStream next. 121 | n := (n bitShift: 8) + aByteStream next. 122 | n := (n bitShift: 8) + aByteStream next. 123 | n := (n bitShift: 8) + aByteStream next. 124 | ^ n 125 | ] 126 | 127 | { #category : #'coder-fixed' } 128 | PBProtobufCoder class >> readFixed64: aByteStream [ 129 | 130 | | n | 131 | n := aByteStream next. 132 | 7 timesRepeat: [ 133 | n := (n bitShift: 8) + aByteStream next ]. 134 | ^ n 135 | ] 136 | 137 | { #category : #'coder-fixed' } 138 | PBProtobufCoder class >> readFloat: aByteStream [ 139 | 140 | ^ (aByteStream next: 4) floatAt: 1 141 | ] 142 | 143 | { #category : #'coder-fixed' } 144 | PBProtobufCoder class >> readSFixed32: aByteStream [ 145 | 146 | | n firstDigit | 147 | n := firstDigit := aByteStream next. 148 | n := (n bitShift: 8) + aByteStream next. 149 | n := (n bitShift: 8) + aByteStream next. 150 | n := (n bitShift: 8) + aByteStream next. 151 | firstDigit >= 128 ifTrue: [n := -16r100000000 + n]. "decode negative 32-bit integer" 152 | ^ n 153 | 154 | ] 155 | 156 | { #category : #'coder-fixed' } 157 | PBProtobufCoder class >> readSFixed64: aByteStream [ 158 | 159 | | n firstDigit | 160 | n := firstDigit := aByteStream next. 161 | 7 timesRepeat: [ 162 | n := (n bitShift: 8) + aByteStream next ]. 163 | firstDigit >= 128 ifTrue: [n := -16r10000000000000000 + n]. "decode negative 64-bit integer" 164 | ^ n 165 | 166 | ] 167 | 168 | { #category : #'coder-length-delimited' } 169 | PBProtobufCoder class >> readString: aByteSize from: aByteStream [ 170 | 171 | | decoder limit | 172 | 173 | decoder := self utf8Encoder. 174 | limit := aByteStream position + aByteSize. 175 | ^ String streamContents: [ :s | 176 | [ aByteStream position < limit ] 177 | whileTrue: [ s nextPut: (decoder nextFromStream: aByteStream) ] ] 178 | ] 179 | 180 | { #category : #'coder-varint' } 181 | PBProtobufCoder class >> readVarint32: aByteStream [ 182 | 183 | ^ self readVarint64: aByteStream 184 | ] 185 | 186 | { #category : #'coder-varint' } 187 | PBProtobufCoder class >> readVarint64: aByteStream [ 188 | 189 | | val | 190 | 191 | val := self readVarintRaw: aByteStream. 192 | 193 | ^val < 16r8000000000000000 194 | ifTrue: [ val ] 195 | ifFalse: [ val - 16r10000000000000000 ] 196 | ] 197 | 198 | { #category : #'coder-varint' } 199 | PBProtobufCoder class >> readVarintRaw: aByteStream [ 200 | 201 | | val byte shift | 202 | 203 | val := 0. 204 | shift := 0. 205 | 206 | [ byte := aByteStream next. 207 | byte isNil 208 | ifTrue: [ self error: 'Invalid protobuf stream' ]. 209 | val := val + ((byte bitAnd: 16r7F) << shift). 210 | byte < 128 ] 211 | whileFalse: [ shift := shift + 7 ]. 212 | ^ val 213 | ] 214 | 215 | { #category : #'coder-length-delimited' } 216 | PBProtobufCoder class >> utf8Encoder [ 217 | 218 | ^ ZnUTF8Encoder utf8 219 | ] 220 | 221 | { #category : #'coder-fixed' } 222 | PBProtobufCoder class >> writeDouble: aFloat on: aByteStream [ 223 | 224 | aByteStream nextPutAll: ( 225 | (ByteArray new: 8) 226 | doubleAt: 1 put: aFloat; 227 | yourself) 228 | 229 | ] 230 | 231 | { #category : #'coder-fixed' } 232 | PBProtobufCoder class >> writeFixed32: anInteger on: aByteStream [ 233 | aByteStream nextPut: (anInteger byteAt: 4). 234 | aByteStream nextPut: (anInteger byteAt: 3). 235 | aByteStream nextPut: (anInteger byteAt: 2). 236 | aByteStream nextPut: (anInteger byteAt: 1) 237 | ] 238 | 239 | { #category : #'coder-fixed' } 240 | PBProtobufCoder class >> writeFixed64: anInteger on: aByteStream [ 241 | aByteStream nextPut: (anInteger byteAt: 8). 242 | aByteStream nextPut: (anInteger byteAt: 7). 243 | aByteStream nextPut: (anInteger byteAt: 6). 244 | aByteStream nextPut: (anInteger byteAt: 5). 245 | aByteStream nextPut: (anInteger byteAt: 4). 246 | aByteStream nextPut: (anInteger byteAt: 3). 247 | aByteStream nextPut: (anInteger byteAt: 2). 248 | aByteStream nextPut: (anInteger byteAt: 1) 249 | ] 250 | 251 | { #category : #'coder-fixed' } 252 | PBProtobufCoder class >> writeFloat: aFloat on: aByteStream [ 253 | 254 | aByteStream nextPutAll: ( 255 | (ByteArray new: 4) 256 | floatAt: 1 put: aFloat; 257 | yourself) 258 | 259 | ] 260 | 261 | { #category : #'coder-fixed' } 262 | PBProtobufCoder class >> writeSFixed32: anInteger on: aByteStream [ 263 | 264 | self writeFixed32: (anInteger < 0 265 | ifTrue: [ 16r100000000 + anInteger ] 266 | ifFalse: [ anInteger ]) on: aByteStream 267 | ] 268 | 269 | { #category : #'coder-fixed' } 270 | PBProtobufCoder class >> writeSFixed64: anInteger on: aByteStream [ 271 | 272 | self writeFixed64: (anInteger < 0 273 | ifTrue: [ 16r10000000000000000 + anInteger ] 274 | ifFalse: [ anInteger ]) on: aByteStream 275 | ] 276 | 277 | { #category : #'coder-length-delimited' } 278 | PBProtobufCoder class >> writeString: aString on: aByteStream [ 279 | 280 | self utf8Encoder next: aString size putAll: aString startingAt: 1 toStream: aByteStream 281 | ] 282 | 283 | { #category : #'coder-varint' } 284 | PBProtobufCoder class >> writeVarint32: anInteger on: aByteStream [ 285 | 286 | self writeVarint64: anInteger on: aByteStream 287 | ] 288 | 289 | { #category : #'coder-varint' } 290 | PBProtobufCoder class >> writeVarint64: anInteger on: aByteStream [ 291 | 292 | self writeVarintRaw: ( 293 | anInteger < 0 294 | ifTrue: [ 16r10000000000000000 + anInteger ] 295 | ifFalse: [ anInteger ]) 296 | on: aByteStream 297 | ] 298 | 299 | { #category : #'coder-varint' } 300 | PBProtobufCoder class >> writeVarintRaw: aPositiveInteger on: aByteStream [ 301 | 302 | | val | 303 | 304 | val := aPositiveInteger. 305 | [ true ] 306 | whileTrue: [ 307 | val < 128 308 | ifTrue: [ 309 | aByteStream nextPut: val. 310 | ^self ] 311 | ifFalse: [ 312 | aByteStream nextPut: (val bitAnd: 16r7F) + 16r80. 313 | val := val >> 7 ] ] 314 | ] 315 | -------------------------------------------------------------------------------- /Protobuf-Core/PBProtobufConstants.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBProtobufConstants, 3 | #superclass : #SharedPool, 4 | #classVars : [ 5 | 'WireType32bit', 6 | 'WireType64bit', 7 | 'WireTypeLengthDelimited', 8 | 'WireTypeVarint' 9 | ], 10 | #category : #'Protobuf-Core' 11 | } 12 | 13 | { #category : #initialization } 14 | PBProtobufConstants class >> initialize [ 15 | "PBProtobufConstants initialize" 16 | 17 | WireTypeVarint := 0. 18 | WireType64bit := 1. 19 | WireTypeLengthDelimited := 2. 20 | WireType32bit := 5. 21 | 22 | ] 23 | -------------------------------------------------------------------------------- /Protobuf-Core/PBType.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBType, 3 | #superclass : #Object, 4 | #category : #'Protobuf-Core' 5 | } 6 | 7 | { #category : #'instance creation' } 8 | PBType class >> readFrom: aCodedReadStream [ 9 | ^ self new readFrom: aCodedReadStream 10 | ] 11 | 12 | { #category : #comparing } 13 | PBType >> = otherMessage [ 14 | 15 | self == otherMessage 16 | ifTrue: [ ^ true ]. 17 | self class = otherMessage class 18 | ifFalse: [ ^ false ]. 19 | 1 to: self class instSize do: [ :index | 20 | (self instVarAt: index) = (otherMessage instVarAt: index) 21 | ifFalse: [ ^ false ] ]. 22 | ^ true 23 | ] 24 | 25 | { #category : #converting } 26 | PBType >> asBytes [ 27 | ^ ByteArray 28 | streamContents: [ :s | self writeTo: (PBCodedWriteStream on: s) ] 29 | ] 30 | 31 | { #category : #comparing } 32 | PBType >> hash [ 33 | | value | 34 | value := self class hash. 35 | 1 to: self class instSize do: [ :index | value := value bitXor: (self instVarAt: index) hash ]. 36 | ^ value 37 | ] 38 | 39 | { #category : #testing } 40 | PBType >> isEnum [ 41 | ^false 42 | ] 43 | 44 | { #category : #testing } 45 | PBType >> isMessage [ 46 | ^ false 47 | ] 48 | 49 | { #category : #'input-output' } 50 | PBType >> readFrom: pbReadStream [ 51 | self subclassResponsibility 52 | ] 53 | 54 | { #category : #'input-output' } 55 | PBType >> writeTo: aCodedReadStream [ 56 | self subclassResponsibility 57 | ] 58 | -------------------------------------------------------------------------------- /Protobuf-Core/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Protobuf-Core' } 2 | -------------------------------------------------------------------------------- /Protobuf-Tools-Tests/PBProtobufCodeGeneratorTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBProtobufCodeGeneratorTest, 3 | #superclass : #RBRefactoringTest, 4 | #category : #'Protobuf-Tools-Tests' 5 | } 6 | 7 | { #category : #'as yet unclassified' } 8 | PBProtobufCodeGeneratorTest >> createMessageType1 [ 9 | 10 | ^PBProtobufMessageNode name: 'TestMsg1' 11 | fields: (Array 12 | with: (PBProtobufFieldNode number: 1 name: 'fieldOne' typeName: 'string') 13 | with: (PBProtobufFieldNode number: 2 name: 'fieldTwo' typeName: 'int64')) 14 | options: #() 15 | ] 16 | 17 | { #category : #'as yet unclassified' } 18 | PBProtobufCodeGeneratorTest >> createSmalltalkMessageDef1 [ 19 | 20 | ^(PBSmalltalkMessageType on: self createMessageType1) 21 | packageName: self class category; 22 | yourself 23 | ] 24 | 25 | { #category : #tests } 26 | PBProtobufCodeGeneratorTest >> testSmalltalkMessageDef1 [ 27 | 28 | | refactoring msgDef newClass updateRefactoring | 29 | 30 | msgDef := self createSmalltalkMessageDef1. 31 | 32 | refactoring := PBAddMessageClassRefactoring addClassFor: msgDef. 33 | self executeRefactoring: refactoring. 34 | 35 | newClass := refactoring model classNamed: msgDef className. 36 | 37 | updateRefactoring := PBUpdateMessageClassRefactoring messageType: msgDef class: newClass. 38 | self executeRefactoring: updateRefactoring. 39 | 40 | 41 | 42 | 43 | ] 44 | -------------------------------------------------------------------------------- /Protobuf-Tools-Tests/PBProtobufGoogleApiImporter.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBProtobufGoogleApiImporter, 3 | #superclass : #Object, 4 | #instVars : [ 5 | 'basePath' 6 | ], 7 | #category : #'Protobuf-Tools-Tests' 8 | } 9 | 10 | { #category : #tests } 11 | PBProtobufGoogleApiImporter class >> test [ 12 | 13 | | instance | 14 | 15 | instance := self new 16 | basePath: './protobuf' asFileReference; 17 | yourself. 18 | 19 | instance parse: 'google/pubsub/v1/pubsub.proto' 20 | ] 21 | 22 | { #category : #accessing } 23 | PBProtobufGoogleApiImporter >> basePath [ 24 | ^ basePath 25 | ] 26 | 27 | { #category : #accessing } 28 | PBProtobufGoogleApiImporter >> basePath: anObject [ 29 | basePath := anObject 30 | ] 31 | 32 | { #category : #accessing } 33 | PBProtobufGoogleApiImporter >> import: aPathname [ 34 | 35 | ^ (self basePath / aPathname) readStream contents 36 | ] 37 | 38 | { #category : #accessing } 39 | PBProtobufGoogleApiImporter >> parse: aPathname [ 40 | 41 | ^ (self basePath / aPathname) readStreamDo: [ :stream | 42 | self parserClass new parse: stream contents ] 43 | ] 44 | 45 | { #category : #accessing } 46 | PBProtobufGoogleApiImporter >> parserClass [ 47 | ^ PBProtobufParser 48 | ] 49 | -------------------------------------------------------------------------------- /Protobuf-Tools-Tests/PBProtobufGrammarTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBProtobufGrammarTest, 3 | #superclass : #PP2CompositeNodeTest, 4 | #category : #'Protobuf-Tools-Tests' 5 | } 6 | 7 | { #category : #accessing } 8 | PBProtobufGrammarTest >> parserClass [ 9 | ^ PBProtobufGrammar 10 | ] 11 | 12 | { #category : #tests } 13 | PBProtobufGrammarTest >> testBoolLiteral1 [ 14 | self 15 | parse: 'true' 16 | rule: #boolLiteral. 17 | 18 | ] 19 | 20 | { #category : #tests } 21 | PBProtobufGrammarTest >> testBoolLiteral2 [ 22 | self 23 | parse: 'false' 24 | rule: #boolLiteral. 25 | 26 | ] 27 | 28 | { #category : #tests } 29 | PBProtobufGrammarTest >> testComment1 [ 30 | self 31 | parse: '// Hello world' 32 | rule: #comment. 33 | self 34 | parse: '//Hello world ' 35 | rule: #comment. 36 | self 37 | parse: ' 38 | // Hello world ' 39 | rule: #comment 40 | ] 41 | 42 | { #category : #tests } 43 | PBProtobufGrammarTest >> testComment2 [ 44 | 45 | self 46 | parse: '/* Hello world */' 47 | rule: #comment. 48 | 49 | self 50 | parse: '/* 51 | * Hello world 52 | */' 53 | rule: #comment. 54 | 55 | self 56 | parse: '/* comment1 */ 57 | 58 | ' 59 | rule: #comment. 60 | 61 | ] 62 | 63 | { #category : #tests } 64 | PBProtobufGrammarTest >> testConstant1 [ 65 | self 66 | parse: '-123' 67 | rule: #constant. 68 | 69 | ] 70 | 71 | { #category : #tests } 72 | PBProtobufGrammarTest >> testConstant2 [ 73 | self 74 | parse: '123' 75 | rule: #constant. 76 | 77 | ] 78 | 79 | { #category : #tests } 80 | PBProtobufGrammarTest >> testConstant3 [ 81 | self 82 | parse: '"pop"' 83 | rule: #constant. 84 | 85 | ] 86 | 87 | { #category : #tests } 88 | PBProtobufGrammarTest >> testConstant4 [ 89 | self 90 | parse: 'foo.bar' 91 | rule: #constant. 92 | 93 | ] 94 | 95 | { #category : #tests } 96 | PBProtobufGrammarTest >> testDecimalLiteral1 [ 97 | self 98 | parse: '12345' 99 | rule: #decimalLiteral. 100 | 101 | ] 102 | 103 | { #category : #tests } 104 | PBProtobufGrammarTest >> testEnum1 [ 105 | self 106 | parse: 'enum EnumAllowingAlias { 107 | option allow_alias = true; 108 | UNKNOWN = 0; 109 | STARTED = 1; 110 | RUNNING = 2 [(custom_option) = "hello world"]; 111 | }' 112 | rule: #enum 113 | ] 114 | 115 | { #category : #tests } 116 | PBProtobufGrammarTest >> testEnumBody1 [ 117 | self 118 | parse: '{XYZ = 1;AB=99;}' 119 | rule: #enumBody. 120 | 121 | ] 122 | 123 | { #category : #tests } 124 | PBProtobufGrammarTest >> testEnumBody2 [ 125 | self 126 | parse: '{ option allow_alias = true; 127 | XYZ = 321; 128 | AB = 99; 129 | }' 130 | rule: #enumBody. 131 | 132 | ] 133 | 134 | { #category : #tests } 135 | PBProtobufGrammarTest >> testEnumField1 [ 136 | self 137 | parse: 'STARTED = 1;' 138 | rule: #enumField. 139 | 140 | ] 141 | 142 | { #category : #tests } 143 | PBProtobufGrammarTest >> testEnumField2 [ 144 | self 145 | parse: 'RUNNING = 2 [deprecated=true,other_option=123, third="last"];' 146 | rule: #enumField 147 | ] 148 | 149 | { #category : #tests } 150 | PBProtobufGrammarTest >> testEnumField3 [ 151 | self 152 | parse: 'RUNNING = 2 [(custom_option) = "hello world"];' 153 | rule: #enumField 154 | ] 155 | 156 | { #category : #tests } 157 | PBProtobufGrammarTest >> testField1 [ 158 | self 159 | parse: 'foo.bar nested_message = 12;' 160 | rule: #field 161 | ] 162 | 163 | { #category : #tests } 164 | PBProtobufGrammarTest >> testField2 [ 165 | self 166 | parse: 'repeated int32 samples = 4 [packed=true];' 167 | rule: #field. 168 | self 169 | parse: 'repeated int32 samples=4 [ packed = true ] ; ' 170 | rule: #field. 171 | self 172 | parse: 'repeated int32 samples=4[packed=true];' 173 | rule: #field 174 | ] 175 | 176 | { #category : #tests } 177 | PBProtobufGrammarTest >> testFieldName1 [ 178 | self 179 | parse: 'nested_message' 180 | rule: #fieldName 181 | ] 182 | 183 | { #category : #tests } 184 | PBProtobufGrammarTest >> testFloatLiteral1 [ 185 | self 186 | parse: '123.45' 187 | rule: #floatLiteral. 188 | 189 | ] 190 | 191 | { #category : #tests } 192 | PBProtobufGrammarTest >> testFloatLiteral2 [ 193 | self 194 | parse: '123.45e-3' 195 | rule: #floatLiteral. 196 | 197 | ] 198 | 199 | { #category : #tests } 200 | PBProtobufGrammarTest >> testFullIdent [ 201 | self 202 | parse: 'foo.bar' 203 | rule: #fullIdent. 204 | 205 | ] 206 | 207 | { #category : #tests } 208 | PBProtobufGrammarTest >> testHexLiteral1 [ 209 | self 210 | parse: '0xffff' 211 | rule: #hexLiteral. 212 | 213 | ] 214 | 215 | { #category : #tests } 216 | PBProtobufGrammarTest >> testHexLiteral2 [ 217 | self 218 | parse: '0XFFAA' 219 | rule: #hexLiteral. 220 | 221 | ] 222 | 223 | { #category : #tests } 224 | PBProtobufGrammarTest >> testImport1 [ 225 | self 226 | parse: 'import public "other.proto";' 227 | rule: #import. 228 | ] 229 | 230 | { #category : #tests } 231 | PBProtobufGrammarTest >> testIntLiteral0 [ 232 | self 233 | parse: '0' 234 | rule: #intLiteral 235 | ] 236 | 237 | { #category : #tests } 238 | PBProtobufGrammarTest >> testIntLiteral1 [ 239 | self 240 | parse: '1' 241 | rule: #intLiteral 242 | ] 243 | 244 | { #category : #tests } 245 | PBProtobufGrammarTest >> testMapField1 [ 246 | self 247 | parse: 'map projects = 2;' 248 | rule: #mapField 249 | ] 250 | 251 | { #category : #tests } 252 | PBProtobufGrammarTest >> testMessage1 [ 253 | self 254 | parse: 'message Msg { int32 my_num = 1; }' 255 | rule: #message. 256 | 257 | ] 258 | 259 | { #category : #tests } 260 | PBProtobufGrammarTest >> testMessage2 [ 261 | self 262 | parse: 'message Outer { 263 | option (my_option).a = true; 264 | message Inner { 265 | int64 ival = 1; 266 | } 267 | map my_map = 2; 268 | }' 269 | rule: #message. 270 | 271 | ] 272 | 273 | { #category : #tests } 274 | PBProtobufGrammarTest >> testMessage3 [ 275 | self 276 | parse: 'message outer { 277 | option (my_option).a = true; 278 | message inner { 279 | int64 ival = 1; 280 | } 281 | repeated inner inner_message = 2; 282 | EnumAllowingAlias enum_field =3; 283 | map my_map = 4; 284 | }' 285 | rule: #message. 286 | 287 | ] 288 | 289 | { #category : #tests } 290 | PBProtobufGrammarTest >> testMessage4 [ 291 | self 292 | parse: 'message SearchRequest { 293 | string query = 1; 294 | int32 page_number = 2; // Which page number do we want? 295 | int32 result_per_page = 3; // Number of results to return per page. 296 | }' 297 | rule: #message. 298 | ] 299 | 300 | { #category : #tests } 301 | PBProtobufGrammarTest >> testMessageType1 [ 302 | self 303 | parse: 'foo.bar' 304 | rule: #messageType 305 | ] 306 | 307 | { #category : #tests } 308 | PBProtobufGrammarTest >> testOctalLiteral1 [ 309 | self 310 | parse: '0777' 311 | rule: #octalLiteral. 312 | 313 | ] 314 | 315 | { #category : #tests } 316 | PBProtobufGrammarTest >> testOneof1 [ 317 | self 318 | parse: 'oneof foo { 319 | string name = 4; 320 | SubMessage sub_message = 9; 321 | }' 322 | rule: #oneof 323 | ] 324 | 325 | { #category : #tests } 326 | PBProtobufGrammarTest >> testOneof2 [ 327 | self 328 | parse: 'oneof foo {}' 329 | rule: #oneof. 330 | self 331 | parse: 'oneof foo {;}' 332 | rule: #oneof. 333 | self 334 | parse: 'oneof foo {;;}' 335 | rule: #oneof 336 | ] 337 | 338 | { #category : #tests } 339 | PBProtobufGrammarTest >> testOneofField1 [ 340 | self 341 | parse: 'foo.bar nested_message = 12;' 342 | rule: #oneofField 343 | ] 344 | 345 | { #category : #tests } 346 | PBProtobufGrammarTest >> testOption1 [ 347 | self 348 | parse: 'option java_package = "com.example.foo";' 349 | rule: #option. 350 | self 351 | parse: 'option java_package = "com.example.foo" ; 352 | ' 353 | rule: #option. 354 | self 355 | parse: 'option java_package = "com.example.foo";' 356 | rule: #option 357 | 358 | ] 359 | 360 | { #category : #tests } 361 | PBProtobufGrammarTest >> testOption2 [ 362 | self 363 | parse: 'option xyz = 123;' 364 | rule: #option. 365 | ] 366 | 367 | { #category : #tests } 368 | PBProtobufGrammarTest >> testOption3 [ 369 | self 370 | parse: 'option optimize_for = CODE_SIZE;' 371 | rule: #option. 372 | ] 373 | 374 | { #category : #tests } 375 | PBProtobufGrammarTest >> testProto1 [ 376 | self 377 | parse: 'syntax = "proto3";' 378 | rule: #proto. 379 | ] 380 | 381 | { #category : #tests } 382 | PBProtobufGrammarTest >> testProto2 [ 383 | self 384 | parse: 'syntax = "proto3"; 385 | import public "other.proto"; 386 | option java_package = "com.example.foo"; 387 | enum EnumAllowingAlias { 388 | option allow_alias = true; 389 | UNKNOWN = 0; 390 | STARTED = 1; 391 | RUNNING = 2 [(custom_option) = "hello world"]; 392 | } 393 | message outer { 394 | option (my_option).a = true; 395 | message inner { 396 | int64 ival = 1; 397 | } 398 | repeated inner inner_message = 2; 399 | EnumAllowingAlias enum_field =3; 400 | map my_map = 4; 401 | }' 402 | rule: #proto. 403 | ] 404 | 405 | { #category : #tests } 406 | PBProtobufGrammarTest >> testProto3 [ 407 | self 408 | parse: 'syntax = "proto3"; 409 | 410 | /* SearchRequest represents a search query, with pagination options to 411 | * indicate which results to include in the response. */ 412 | 413 | message SearchRequest { 414 | string query = 1; 415 | int32 page_number = 2; // Which page number do we want? 416 | int32 result_per_page = 3; // Number of results to return per page. 417 | }' 418 | rule: #proto. 419 | ] 420 | 421 | { #category : #tests } 422 | PBProtobufGrammarTest >> testRange1 [ 423 | self 424 | parse: '1' 425 | rule: #range. 426 | self 427 | parse: '1 to 99' 428 | rule: #range. 429 | self 430 | parse: '100 to max' 431 | rule: #range 432 | 433 | ] 434 | 435 | { #category : #tests } 436 | PBProtobufGrammarTest >> testReserved1 [ 437 | self 438 | parse: 'reserved 2, 15, 9 to 11;' 439 | rule: #reserved 440 | ] 441 | 442 | { #category : #tests } 443 | PBProtobufGrammarTest >> testRpc1 [ 444 | self 445 | parse: 'rpc Search (SearchRequest) returns (SearchResponse);' 446 | rule: #rpc 447 | ] 448 | 449 | { #category : #tests } 450 | PBProtobufGrammarTest >> testService1 [ 451 | self 452 | parse: 'service SearchService { 453 | rpc Search (SearchRequest) returns (SearchResponse); 454 | }' 455 | rule: #service 456 | ] 457 | 458 | { #category : #tests } 459 | PBProtobufGrammarTest >> testStrLiteral1 [ 460 | self 461 | parse: '"pipo"' 462 | rule: #strLiteral. 463 | 464 | ] 465 | 466 | { #category : #tests } 467 | PBProtobufGrammarTest >> testStrLiteral2 [ 468 | self 469 | parse: '''pipo''' 470 | rule: #strLiteral. 471 | 472 | ] 473 | 474 | { #category : #tests } 475 | PBProtobufGrammarTest >> testSyntax [ 476 | self 477 | parse: 'syntax = "proto3";' 478 | rule: #syntax. 479 | ] 480 | 481 | { #category : #tests } 482 | PBProtobufGrammarTest >> testType1 [ 483 | self 484 | parse: 'int64' 485 | rule: #type 486 | ] 487 | 488 | { #category : #tests } 489 | PBProtobufGrammarTest >> testType2 [ 490 | self 491 | parse: 'foo.bar' 492 | rule: #type 493 | ] 494 | -------------------------------------------------------------------------------- /Protobuf-Tools-Tests/PBProtobufParserTest.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBProtobufParserTest, 3 | #superclass : #PBProtobufGrammarTest, 4 | #category : #'Protobuf-Tools-Tests' 5 | } 6 | 7 | { #category : #accessing } 8 | PBProtobufParserTest >> parserClass [ 9 | ^ PBProtobufParser 10 | ] 11 | 12 | { #category : #accessing } 13 | PBProtobufParserTest >> result [ 14 | ^ result 15 | ] 16 | 17 | { #category : #tests } 18 | PBProtobufParserTest >> testBoolLiteral1 [ 19 | 20 | super testBoolLiteral1. 21 | self assert: self result equals: true 22 | ] 23 | 24 | { #category : #tests } 25 | PBProtobufParserTest >> testBoolLiteral2 [ 26 | 27 | super testBoolLiteral2. 28 | self assert: self result equals: false 29 | ] 30 | 31 | { #category : #tests } 32 | PBProtobufParserTest >> testConstant1 [ 33 | 34 | super testConstant1. 35 | self assert: self result equals: -123 36 | ] 37 | 38 | { #category : #tests } 39 | PBProtobufParserTest >> testConstant2 [ 40 | 41 | super testConstant2. 42 | self assert: self result equals: 123 43 | ] 44 | 45 | { #category : #tests } 46 | PBProtobufParserTest >> testConstant3 [ 47 | 48 | super testConstant3. 49 | self assert: self result equals: 'pop' 50 | ] 51 | 52 | { #category : #tests } 53 | PBProtobufParserTest >> testConstant4 [ 54 | 55 | super testConstant4. 56 | self assert: self result equals: 'foo.bar' 57 | ] 58 | 59 | { #category : #tests } 60 | PBProtobufParserTest >> testDecimalLiteral1 [ 61 | 62 | super testDecimalLiteral1. 63 | self assert: self result equals: 12345 64 | ] 65 | 66 | { #category : #tests } 67 | PBProtobufParserTest >> testEnum1 [ 68 | 69 | super testEnum1. 70 | self assert: self result name equals: 'EnumAllowingAlias'. 71 | ] 72 | 73 | { #category : #tests } 74 | PBProtobufParserTest >> testEnumBody1 [ 75 | 76 | super testEnumBody1. 77 | self assert: self result equals: ( 78 | PBProtobufEnum name: '' 79 | values: (Array 80 | with: (PBProtobufEnumValue name: 'XYZ' number: 1) 81 | with: (PBProtobufEnumValue name: 'AB' number: 99)) 82 | options: #()) 83 | ] 84 | 85 | { #category : #tests } 86 | PBProtobufParserTest >> testEnumBody2 [ 87 | 88 | super testEnumBody2. 89 | self assert: self result equals: ( 90 | PBProtobufEnum name: '' 91 | values: (Array 92 | with: (PBProtobufEnumValue name: 'XYZ' number: 321) 93 | with: (PBProtobufEnumValue name: 'AB' number: 99)) 94 | options: (Array 95 | with: (PBProtobufOptionNode name: 'allow_alias' value: true))) 96 | ] 97 | 98 | { #category : #tests } 99 | PBProtobufParserTest >> testEnumField1 [ 100 | 101 | super testEnumField1. 102 | self assert: self result equals: (PBProtobufEnumValue name: 'STARTED' number: 1 options: #()) 103 | ] 104 | 105 | { #category : #tests } 106 | PBProtobufParserTest >> testEnumField2 [ 107 | 108 | super testEnumField2. 109 | self assert: self result equals: ( 110 | PBProtobufEnumValue name: 'RUNNING' 111 | number: 2 112 | options: (Array with: 'deprecated' -> true with: 'other_option' -> 123 with: 'third' -> 'last')) 113 | ] 114 | 115 | { #category : #tests } 116 | PBProtobufParserTest >> testEnumField3 [ 117 | 118 | super testEnumField3. 119 | self assert: self result equals: ( 120 | PBProtobufEnumValue name: 'RUNNING' 121 | number: 2 122 | options: (Array with: '(custom_option)' -> 'hello world')) 123 | ] 124 | 125 | { #category : #tests } 126 | PBProtobufParserTest >> testField1 [ 127 | super testField1. 128 | self assert: self result name equals: 'nested_message'. 129 | self assert: self result number equals: 12. 130 | self assert: self result type name equals: 'foo.bar' 131 | ] 132 | 133 | { #category : #tests } 134 | PBProtobufParserTest >> testFloatLiteral1 [ 135 | 136 | super testFloatLiteral1. 137 | self assert: result equals: 123.45 138 | 139 | ] 140 | 141 | { #category : #tests } 142 | PBProtobufParserTest >> testFloatLiteral2 [ 143 | 144 | super testFloatLiteral2. 145 | self assert: result equals: 123.45e-3 146 | 147 | ] 148 | 149 | { #category : #tests } 150 | PBProtobufParserTest >> testFullIdent [ 151 | super testFullIdent. 152 | self assert: self result equals: 'foo.bar' 153 | ] 154 | 155 | { #category : #tests } 156 | PBProtobufParserTest >> testHexLiteral1 [ 157 | 158 | super testHexLiteral1. 159 | self assert: self result equals: 16rFFFF 160 | ] 161 | 162 | { #category : #tests } 163 | PBProtobufParserTest >> testHexLiteral2 [ 164 | 165 | super testHexLiteral2. 166 | self assert: self result equals: 16rFFAA 167 | ] 168 | 169 | { #category : #tests } 170 | PBProtobufParserTest >> testImport1 [ 171 | 172 | super testImport1. 173 | 174 | self assert: self result name equals: 'other.proto'. 175 | self assert: self result isPublic equals: true. 176 | self assert: self result isWeak equals: false. 177 | ] 178 | 179 | { #category : #tests } 180 | PBProtobufParserTest >> testMapField1 [ 181 | super testMapField1. 182 | self assert: self result name equals: 'projects'. 183 | self assert: self result number equals: 2. 184 | ] 185 | 186 | { #category : #tests } 187 | PBProtobufParserTest >> testMessage1 [ 188 | 189 | super testMessage1. 190 | self assert: self result name equals: 'Msg'. 191 | self assert: self result fields size equals: 1. 192 | self assert: self result fields first name equals: 'my_num' 193 | ] 194 | 195 | { #category : #tests } 196 | PBProtobufParserTest >> testMessage2 [ 197 | 198 | super testMessage2. 199 | self assert: self result name equals: 'Outer'. 200 | self assert: self result fields size equals: 1. 201 | self assert: self result fields first name equals: 'my_map' 202 | ] 203 | 204 | { #category : #tests } 205 | PBProtobufParserTest >> testMessage3 [ 206 | 207 | super testMessage3. 208 | self assert: self result name equals: 'outer'. 209 | self assert: self result fields size equals: 3. 210 | self assert: self result fields first name equals: 'inner_message' 211 | ] 212 | 213 | { #category : #tests } 214 | PBProtobufParserTest >> testOctalLiteral1 [ 215 | 216 | super testOctalLiteral1. 217 | self assert: self result equals: 8r777 218 | ] 219 | 220 | { #category : #tests } 221 | PBProtobufParserTest >> testOption1 [ 222 | 223 | super testOption1. 224 | self assert: self result name equals: 'java_package'. 225 | self assert: self result value equals: 'com.example.foo'. 226 | ] 227 | 228 | { #category : #tests } 229 | PBProtobufParserTest >> testOption2 [ 230 | 231 | super testOption2. 232 | self assert: self result name equals: 'xyz'. 233 | self assert: self result value equals: 123. 234 | ] 235 | 236 | { #category : #tests } 237 | PBProtobufParserTest >> testProto1 [ 238 | 239 | super testProto1. 240 | 241 | self assert: result imports isEmpty. 242 | self assert: result options isEmpty. 243 | self assert: result messages isEmpty. 244 | 245 | ] 246 | 247 | { #category : #tests } 248 | PBProtobufParserTest >> testProto2 [ 249 | 250 | super testProto2. 251 | 252 | self assert: result options size equals: 1. 253 | self assert: result messages size equals: 1. 254 | 255 | ] 256 | 257 | { #category : #tests } 258 | PBProtobufParserTest >> testProto3 [ 259 | 260 | super testProto3. 261 | 262 | self assert: result options isEmpty. 263 | self assert: result messages size equals: 1. 264 | 265 | ] 266 | 267 | { #category : #tests } 268 | PBProtobufParserTest >> testStrLiteral1 [ 269 | 270 | super testStrLiteral1. 271 | self assert: result equals: 'pipo' 272 | 273 | ] 274 | 275 | { #category : #tests } 276 | PBProtobufParserTest >> testStrLiteral2 [ 277 | 278 | super testStrLiteral2. 279 | self assert: result equals: 'pipo' 280 | 281 | ] 282 | 283 | { #category : #tests } 284 | PBProtobufParserTest >> testType1 [ 285 | 286 | super testType1. 287 | self assert: self result name equals: 'int64'. 288 | 289 | ] 290 | 291 | { #category : #tests } 292 | PBProtobufParserTest >> testType2 [ 293 | 294 | super testType2. 295 | self assert: self result name equals: 'foo.bar'. 296 | 297 | ] 298 | -------------------------------------------------------------------------------- /Protobuf-Tools-Tests/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Protobuf-Tools-Tests' } 2 | -------------------------------------------------------------------------------- /Protobuf-Tools/PBAddEnumClassRefactoring.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBAddEnumClassRefactoring, 3 | #superclass : #RBRefactoring, 4 | #instVars : [ 5 | 'messageType' 6 | ], 7 | #category : #'Protobuf-Tools-Generator' 8 | } 9 | 10 | { #category : #'instance creation' } 11 | PBAddEnumClassRefactoring class >> model: aRBSmalltalk addClassFor: aSmalltalkEnumDef [ 12 | ^ self new 13 | model: aRBSmalltalk; 14 | addClassFor: aSmalltalkEnumDef; 15 | yourself 16 | ] 17 | -------------------------------------------------------------------------------- /Protobuf-Tools/PBAddMessageClassRefactoring.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBAddMessageClassRefactoring, 3 | #superclass : #RBRefactoring, 4 | #instVars : [ 5 | 'messageType' 6 | ], 7 | #category : #'Protobuf-Tools-Generator' 8 | } 9 | 10 | { #category : #'instance creation' } 11 | PBAddMessageClassRefactoring class >> addClassFor: aSmalltalkMessageDef [ 12 | 13 | ^self new 14 | addClassFor: aSmalltalkMessageDef; 15 | yourself 16 | 17 | ] 18 | 19 | { #category : #'instance creation' } 20 | PBAddMessageClassRefactoring class >> model: aRBSmalltalk addClassFor: aSmalltalkMessageDef [ 21 | 22 | ^self new 23 | model: aRBSmalltalk; 24 | addClassFor: aSmalltalkMessageDef; 25 | yourself 26 | ] 27 | 28 | { #category : #initialization } 29 | PBAddMessageClassRefactoring >> addClassFor: aSmalltalkMessageDef [ 30 | 31 | messageType := aSmalltalkMessageDef 32 | ] 33 | 34 | { #category : #accessing } 35 | PBAddMessageClassRefactoring >> category [ 36 | 37 | ^ self messageType packageName 38 | ] 39 | 40 | { #category : #accessing } 41 | PBAddMessageClassRefactoring >> className [ 42 | 43 | ^ self messageType className 44 | ] 45 | 46 | { #category : #accessing } 47 | PBAddMessageClassRefactoring >> messageType [ 48 | 49 | ^ messageType 50 | ] 51 | 52 | { #category : #preconditions } 53 | PBAddMessageClassRefactoring >> preconditions [ 54 | 55 | ^(RBCondition isValidClassName: self className) 56 | ] 57 | 58 | { #category : #accessing } 59 | PBAddMessageClassRefactoring >> superclass [ 60 | 61 | ^ self model classNamed: #PBMessage 62 | ] 63 | 64 | { #category : #transforming } 65 | PBAddMessageClassRefactoring >> transform [ 66 | 67 | (self model) 68 | defineClass: ('<1p> subclass: #<2s> instanceVariableNames: '''' classVariableNames: '''' poolDictionaries: '''' category: <3p>' 69 | expandMacrosWith: self superclass 70 | with: self className 71 | with: self category asString) 72 | ] 73 | -------------------------------------------------------------------------------- /Protobuf-Tools/PBGoogleProtobufResources.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBGoogleProtobufResources, 3 | #superclass : #Object, 4 | #category : #'Protobuf-Tools' 5 | } 6 | 7 | { #category : #resources } 8 | PBGoogleProtobufResources class >> any_proto [ 9 | 10 | ^'syntax = "proto3"; 11 | 12 | package google.protobuf; 13 | 14 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 15 | option go_package = "github.com/golang/protobuf/ptypes/any"; 16 | option java_package = "com.google.protobuf"; 17 | option java_outer_classname = "AnyProto"; 18 | option java_multiple_files = true; 19 | option objc_class_prefix = "GPB"; 20 | 21 | // ''Any'' contains an arbitrary serialized protocol buffer message along with a 22 | // URL that describes the type of the serialized message. 23 | // 24 | // Protobuf library provides support to pack/unpack Any values in the form 25 | // of utility functions or additional generated methods of the Any type. 26 | // 27 | // Example 1: Pack and unpack a message in C++. 28 | // 29 | // Foo foo = ...; 30 | // Any any; 31 | // any.PackFrom(foo); 32 | // ... 33 | // if (any.UnpackTo(&foo)) { 34 | // ... 35 | // } 36 | // 37 | // Example 2: Pack and unpack a message in Java. 38 | // 39 | // Foo foo = ...; 40 | // Any any = Any.pack(foo); 41 | // ... 42 | // if (any.is(Foo.class)) { 43 | // foo = any.unpack(Foo.class); 44 | // } 45 | // 46 | // Example 3: Pack and unpack a message in Python. 47 | // 48 | // foo = Foo(...) 49 | // any = Any() 50 | // any.Pack(foo) 51 | // ... 52 | // if any.Is(Foo.DESCRIPTOR): 53 | // any.Unpack(foo) 54 | // ... 55 | // 56 | // Example 4: Pack and unpack a message in Go 57 | // 58 | // foo := &pb.Foo{...} 59 | // any, err := ptypes.MarshalAny(foo) 60 | // ... 61 | // foo := &pb.Foo{} 62 | // if err := ptypes.UnmarshalAny(any, foo); err != nil { 63 | // ... 64 | // } 65 | // 66 | // The pack methods provided by protobuf library will by default use 67 | // ''type.googleapis.com/full.type.name'' as the type URL and the unpack 68 | // methods only use the fully qualified type name after the last ''/'' 69 | // in the type URL, for example "foo.bar.com/x/y.z" will yield type 70 | // name "y.z". 71 | // 72 | // 73 | // JSON 74 | // ==== 75 | // The JSON representation of an ''Any'' value uses the regular 76 | // representation of the deserialized, embedded message, with an 77 | // additional field ''@type'' which contains the type URL. Example: 78 | // 79 | // package google.profile; 80 | // message Person { 81 | // string first_name = 1; 82 | // string last_name = 2; 83 | // } 84 | // 85 | // { 86 | // "@type": "type.googleapis.com/google.profile.Person", 87 | // "firstName": , 88 | // "lastName": 89 | // } 90 | // 91 | // If the embedded message type is well-known and has a custom JSON 92 | // representation, that representation will be embedded adding a field 93 | // ''value'' which holds the custom JSON in addition to the ''@type'' 94 | // field. Example (for message [google.protobuf.Duration][]): 95 | // 96 | // { 97 | // "@type": "type.googleapis.com/google.protobuf.Duration", 98 | // "value": "1.212s" 99 | // } 100 | // 101 | message Any { 102 | // A URL/resource name whose content describes the type of the 103 | // serialized protocol buffer message. 104 | // 105 | // For URLs which use the scheme ''http'', ''https'', or no scheme, the 106 | // following restrictions and interpretations apply: 107 | // 108 | // * If no scheme is provided, ''https'' is assumed. 109 | // * The last segment of the URL''s path must represent the fully 110 | // qualified name of the type (as in ''path/google.protobuf.Duration''). 111 | // The name should be in a canonical form (e.g., leading "." is 112 | // not accepted). 113 | // * An HTTP GET on the URL must yield a [google.protobuf.Type][] 114 | // value in binary format, or produce an error. 115 | // * Applications are allowed to cache lookup results based on the 116 | // URL, or have them precompiled into a binary to avoid any 117 | // lookup. Therefore, binary compatibility needs to be preserved 118 | // on changes to types. (Use versioned type names to manage 119 | // breaking changes.) 120 | // 121 | // Schemes other than ''http'', ''https'' (or the empty scheme) might be 122 | // used with implementation specific semantics. 123 | // 124 | string type_url = 1; 125 | 126 | // Must be a valid serialized protocol buffer of the above specified type. 127 | bytes value = 2; 128 | }' 129 | ] 130 | 131 | { #category : #copyright } 132 | PBGoogleProtobufResources class >> copyright [ 133 | " 134 | // Protocol Buffers - Google's data interchange format 135 | // Copyright 2008 Google Inc. All rights reserved. 136 | // https://developers.google.com/protocol-buffers/ 137 | // 138 | // Redistribution and use in source and binary forms, with or without 139 | // modification, are permitted provided that the following conditions are 140 | // met: 141 | // 142 | // * Redistributions of source code must retain the above copyright 143 | // notice, this list of conditions and the following disclaimer. 144 | // * Redistributions in binary form must reproduce the above 145 | // copyright notice, this list of conditions and the following disclaimer 146 | // in the documentation and/or other materials provided with the 147 | // distribution. 148 | // * Neither the name of Google Inc. nor the names of its 149 | // contributors may be used to endorse or promote products derived from 150 | // this software without specific prior written permission. 151 | // 152 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 153 | // ""AS IS"" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 154 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 155 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 156 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 157 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 158 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 159 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 160 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 161 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 162 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 163 | " 164 | 165 | ] 166 | 167 | { #category : #parsing } 168 | PBGoogleProtobufResources class >> parse [ 169 | 170 | | parser context resultContext | 171 | 172 | context := PP2Context new. 173 | parser := PBProtobufParser new. 174 | 175 | resultContext := parser parse: self any_proto withContext: context. 176 | ] 177 | 178 | { #category : #resources } 179 | PBGoogleProtobufResources class >> source_context_proto [ 180 | 181 | ^'syntax = "proto3"; 182 | 183 | package google.protobuf; 184 | 185 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 186 | option java_package = "com.google.protobuf"; 187 | option java_outer_classname = "SourceContextProto"; 188 | option java_multiple_files = true; 189 | option objc_class_prefix = "GPB"; 190 | option go_package = "google.golang.org/genproto/protobuf/source_context;source_context"; 191 | 192 | // ''SourceContext'' represents information about the source of a 193 | // protobuf element, like the file in which it is defined. 194 | message SourceContext { 195 | // The path-qualified name of the .proto file that contained the associated 196 | // protobuf element. For example: `"google/protobuf/source_context.proto"`. 197 | string file_name = 1; 198 | }' 199 | ] 200 | 201 | { #category : #resources } 202 | PBGoogleProtobufResources class >> type_proto [ 203 | 204 | ^'syntax = "proto3"; 205 | 206 | package google.protobuf; 207 | 208 | import "google/protobuf/any.proto"; 209 | import "google/protobuf/source_context.proto"; 210 | 211 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 212 | option cc_enable_arenas = true; 213 | option java_package = "com.google.protobuf"; 214 | option java_outer_classname = "TypeProto"; 215 | option java_multiple_files = true; 216 | option objc_class_prefix = "GPB"; 217 | option go_package = "google.golang.org/genproto/protobuf/ptype;ptype"; 218 | 219 | // A protocol buffer message type. 220 | message Type { 221 | // The fully qualified message name. 222 | string name = 1; 223 | // The list of fields. 224 | repeated Field fields = 2; 225 | // The list of types appearing in `oneof` definitions in this type. 226 | repeated string oneofs = 3; 227 | // The protocol buffer options. 228 | repeated Option options = 4; 229 | // The source context. 230 | SourceContext source_context = 5; 231 | // The source syntax. 232 | Syntax syntax = 6; 233 | } 234 | 235 | // A single field of a message type. 236 | message Field { 237 | // Basic field types. 238 | enum Kind { 239 | // Field type unknown. 240 | TYPE_UNKNOWN = 0; 241 | // Field type double. 242 | TYPE_DOUBLE = 1; 243 | // Field type float. 244 | TYPE_FLOAT = 2; 245 | // Field type int64. 246 | TYPE_INT64 = 3; 247 | // Field type uint64. 248 | TYPE_UINT64 = 4; 249 | // Field type int32. 250 | TYPE_INT32 = 5; 251 | // Field type fixed64. 252 | TYPE_FIXED64 = 6; 253 | // Field type fixed32. 254 | TYPE_FIXED32 = 7; 255 | // Field type bool. 256 | TYPE_BOOL = 8; 257 | // Field type string. 258 | TYPE_STRING = 9; 259 | // Field type group. Proto2 syntax only, and deprecated. 260 | TYPE_GROUP = 10; 261 | // Field type message. 262 | TYPE_MESSAGE = 11; 263 | // Field type bytes. 264 | TYPE_BYTES = 12; 265 | // Field type uint32. 266 | TYPE_UINT32 = 13; 267 | // Field type enum. 268 | TYPE_ENUM = 14; 269 | // Field type sfixed32. 270 | TYPE_SFIXED32 = 15; 271 | // Field type sfixed64. 272 | TYPE_SFIXED64 = 16; 273 | // Field type sint32. 274 | TYPE_SINT32 = 17; 275 | // Field type sint64. 276 | TYPE_SINT64 = 18; 277 | }; 278 | 279 | // Whether a field is optional, required, or repeated. 280 | enum Cardinality { 281 | // For fields with unknown cardinality. 282 | CARDINALITY_UNKNOWN = 0; 283 | // For optional fields. 284 | CARDINALITY_OPTIONAL = 1; 285 | // For required fields. Proto2 syntax only. 286 | CARDINALITY_REQUIRED = 2; 287 | // For repeated fields. 288 | CARDINALITY_REPEATED = 3; 289 | }; 290 | 291 | // The field type. 292 | Kind kind = 1; 293 | // The field cardinality. 294 | Cardinality cardinality = 2; 295 | // The field number. 296 | int32 number = 3; 297 | // The field name. 298 | string name = 4; 299 | // The field type URL, without the scheme, for message or enumeration 300 | // types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`. 301 | string type_url = 6; 302 | // The index of the field type in `Type.oneofs`, for message or enumeration 303 | // types. The first type has index 1; zero means the type is not in the list. 304 | int32 oneof_index = 7; 305 | // Whether to use alternative packed wire representation. 306 | bool packed = 8; 307 | // The protocol buffer options. 308 | repeated Option options = 9; 309 | // The field JSON name. 310 | string json_name = 10; 311 | // The string value of the default value of this field. Proto2 syntax only. 312 | string default_value = 11; 313 | } 314 | 315 | // Enum type definition. 316 | message Enum { 317 | // Enum type name. 318 | string name = 1; 319 | // Enum value definitions. 320 | repeated EnumValue enumvalue = 2; 321 | // Protocol buffer options. 322 | repeated Option options = 3; 323 | // The source context. 324 | SourceContext source_context = 4; 325 | // The source syntax. 326 | Syntax syntax = 5; 327 | } 328 | 329 | // Enum value definition. 330 | message EnumValue { 331 | // Enum value name. 332 | string name = 1; 333 | // Enum value number. 334 | int32 number = 2; 335 | // Protocol buffer options. 336 | repeated Option options = 3; 337 | } 338 | 339 | // A protocol buffer option, which can be attached to a message, field, 340 | // enumeration, etc. 341 | message Option { 342 | // The option''s name. For protobuf built-in options (options defined in 343 | // descriptor.proto), this is the short name. For example, "map_entry". 344 | // For custom options, it should be the fully-qualified name. For example, 345 | // "google.api.http". 346 | string name = 1; 347 | // The option''s value packed in an Any message. If the value is a primitive, 348 | // the corresponding wrapper type defined in google/protobuf/wrappers.proto 349 | // should be used. If the value is an enum, it should be stored as an int32 350 | // value using the google.protobuf.Int32Value type. 351 | Any value = 2; 352 | } 353 | 354 | // The syntax in which a protocol buffer element is defined. 355 | enum Syntax { 356 | // Syntax ''proto2''. 357 | SYNTAX_PROTO2 = 0; 358 | // Syntax ''proto3''. 359 | SYNTAX_PROTO3 = 1; 360 | }' 361 | 362 | ] 363 | -------------------------------------------------------------------------------- /Protobuf-Tools/PBProtobufCodeGenerator.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBProtobufCodeGenerator, 3 | #superclass : #Object, 4 | #instVars : [ 5 | 'messageTypes', 6 | 'enumTypes' 7 | ], 8 | #category : #'Protobuf-Tools-Generator' 9 | } 10 | 11 | { #category : #'as yet unclassified' } 12 | PBProtobufCodeGenerator >> refactoringsForMessage: aMessageType [ 13 | 14 | | classRefactoring | 15 | 16 | classRefactoring := RBAddClassRefactoring addClass: aMessageType className 17 | superclass: aMessageType superclass 18 | subclasses: #() 19 | category: aMessageType packageName. 20 | ] 21 | -------------------------------------------------------------------------------- /Protobuf-Tools/PBProtobufCommentNode.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBProtobufCommentNode, 3 | #superclass : #PBProtobufNode, 4 | #instVars : [ 5 | 'text' 6 | ], 7 | #category : #'Protobuf-Tools-Model' 8 | } 9 | 10 | { #category : #'instance creation' } 11 | PBProtobufCommentNode class >> text: aString [ 12 | 13 | ^ self new initWithText: aString 14 | ] 15 | 16 | { #category : #initialization } 17 | PBProtobufCommentNode >> initWithText: aString [ 18 | 19 | text := aString 20 | ] 21 | 22 | { #category : #accessing } 23 | PBProtobufCommentNode >> text [ 24 | ^ text 25 | ] 26 | -------------------------------------------------------------------------------- /Protobuf-Tools/PBProtobufEnum.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBProtobufEnum, 3 | #superclass : #PBProtobufNode, 4 | #instVars : [ 5 | 'name', 6 | 'values', 7 | 'options' 8 | ], 9 | #category : #'Protobuf-Tools-Model' 10 | } 11 | 12 | { #category : #'instance creation' } 13 | PBProtobufEnum class >> name: aName values: anEnumValueColl options: anOptionColl [ 14 | 15 | ^self new initWithName: aName values: anEnumValueColl options: anOptionColl 16 | ] 17 | 18 | { #category : #initialization } 19 | PBProtobufEnum >> initWithName: aName values: anEnumValueColl options: anOptionColl [ 20 | 21 | name := aName. 22 | values := anEnumValueColl asArray. 23 | options := anOptionColl asArray 24 | ] 25 | 26 | { #category : #testing } 27 | PBProtobufEnum >> isEnumNode [ 28 | ^ true 29 | ] 30 | 31 | { #category : #accessing } 32 | PBProtobufEnum >> name [ 33 | ^ name 34 | ] 35 | 36 | { #category : #accessing } 37 | PBProtobufEnum >> options [ 38 | ^ options 39 | ] 40 | 41 | { #category : #printing } 42 | PBProtobufEnum >> printOn: aStream [ 43 | 44 | aStream 45 | nextPutAll: self class name; 46 | nextPut: $<; 47 | print: self name; 48 | nextPut: $> 49 | ] 50 | 51 | { #category : #accessing } 52 | PBProtobufEnum >> values [ 53 | ^ values 54 | ] 55 | 56 | { #category : #copying } 57 | PBProtobufEnum >> withName: newName [ 58 | 59 | ^self class name: newName values: values options: options 60 | ] 61 | -------------------------------------------------------------------------------- /Protobuf-Tools/PBProtobufEnumValue.class.st: -------------------------------------------------------------------------------- 1 | " 2 | Protocol Buffers EnumValue definition. 3 | " 4 | Class { 5 | #name : #PBProtobufEnumValue, 6 | #superclass : #PBProtobufNode, 7 | #instVars : [ 8 | 'name', 9 | 'number', 10 | 'options' 11 | ], 12 | #category : #'Protobuf-Tools-Model' 13 | } 14 | 15 | { #category : #'instance creation' } 16 | PBProtobufEnumValue class >> name: aName number: anInteger [ 17 | 18 | ^self name: aName number: anInteger options: #() 19 | ] 20 | 21 | { #category : #'instance creation' } 22 | PBProtobufEnumValue class >> name: aName number: anInteger options: anOptionColl [ 23 | 24 | ^self new initWithName: aName number: anInteger options: anOptionColl 25 | ] 26 | 27 | { #category : #initialization } 28 | PBProtobufEnumValue >> initWithName: aName number: anInteger options: anOptionColl [ 29 | 30 | name := aName. 31 | number := anInteger. 32 | options := anOptionColl 33 | ] 34 | 35 | { #category : #testing } 36 | PBProtobufEnumValue >> isEnumValueNode [ 37 | 38 | ^true 39 | ] 40 | 41 | { #category : #accessing } 42 | PBProtobufEnumValue >> name [ 43 | ^ name 44 | ] 45 | 46 | { #category : #accessing } 47 | PBProtobufEnumValue >> number [ 48 | ^ number 49 | ] 50 | 51 | { #category : #accessing } 52 | PBProtobufEnumValue >> options [ 53 | ^ options 54 | ] 55 | -------------------------------------------------------------------------------- /Protobuf-Tools/PBProtobufFieldNode.class.st: -------------------------------------------------------------------------------- 1 | " 2 | Protocol Buffers Field definition. A single field of a message type. 3 | " 4 | Class { 5 | #name : #PBProtobufFieldNode, 6 | #superclass : #PBProtobufNode, 7 | #instVars : [ 8 | 'number', 9 | 'name', 10 | 'type', 11 | 'cardinality', 12 | 'typeUrl', 13 | 'oneofIndex' 14 | ], 15 | #pools : [ 16 | 'PBProtobufConstants' 17 | ], 18 | #category : #'Protobuf-Tools-Model' 19 | } 20 | 21 | { #category : #'instance creation' } 22 | PBProtobufFieldNode class >> number: aNumber name: aName type: aFieldType [ 23 | 24 | ^self number: aNumber name: aName type: aFieldType cardinality: #CARDINALITY_OPTIONAL 25 | ] 26 | 27 | { #category : #'instance creation' } 28 | PBProtobufFieldNode class >> number: aNumber name: aName type: aFieldType cardinality: aCardEnum [ 29 | 30 | ^self new initWithNumber: aNumber 31 | name: aName 32 | type: aFieldType 33 | cardinality: aCardEnum 34 | ] 35 | 36 | { #category : #'instance creation' } 37 | PBProtobufFieldNode class >> number: aNumber name: aName typeName: aTypeName [ 38 | 39 | ^self number: aNumber 40 | name: aName 41 | type: (PBProtobufTypeNode name: aTypeName) 42 | ] 43 | 44 | { #category : #accessing } 45 | PBProtobufFieldNode >> cardinality [ 46 | ^ cardinality 47 | ] 48 | 49 | { #category : #accessing } 50 | PBProtobufFieldNode >> defaultValue [ 51 | 52 | ^ self isCardinalityRepeated 53 | ifTrue: [ #() ] 54 | ifFalse: [ self type defaultValue ] 55 | ] 56 | 57 | { #category : #initialization } 58 | PBProtobufFieldNode >> initWithNumber: aNumber name: aName type: aFieldType cardinality: aCardEnum [ 59 | 60 | cardinality := aCardEnum. 61 | number := aNumber. 62 | name := aName. 63 | type := aFieldType 64 | ] 65 | 66 | { #category : #testing } 67 | PBProtobufFieldNode >> isCardinalityOptional [ 68 | 69 | ^ self cardinality = #CARDINALITY_OPTIONAL 70 | ] 71 | 72 | { #category : #testing } 73 | PBProtobufFieldNode >> isCardinalityRepeated [ 74 | 75 | ^ self cardinality = #CARDINALITY_REPEATED 76 | ] 77 | 78 | { #category : #testing } 79 | PBProtobufFieldNode >> isFieldNode [ 80 | ^true 81 | ] 82 | 83 | { #category : #accessing } 84 | PBProtobufFieldNode >> name [ 85 | ^ name 86 | ] 87 | 88 | { #category : #accessing } 89 | PBProtobufFieldNode >> number [ 90 | 91 | ^ number 92 | ] 93 | 94 | { #category : #printing } 95 | PBProtobufFieldNode >> printOn: aStream [ 96 | 97 | aStream 98 | nextPutAll: self class name; 99 | nextPut: $<; 100 | print: self name; 101 | nextPut: $> 102 | ] 103 | 104 | { #category : #accessing } 105 | PBProtobufFieldNode >> tagNumber [ 106 | 107 | ^ PBProtobufCoder makeTag: self number wireType: self type wireType 108 | ] 109 | 110 | { #category : #accessing } 111 | PBProtobufFieldNode >> type [ 112 | ^ type 113 | ] 114 | 115 | { #category : #accessing } 116 | PBProtobufFieldNode >> typeName [ 117 | ^ self type name 118 | ] 119 | 120 | { #category : #accessing } 121 | PBProtobufFieldNode >> typeUrl [ 122 | ^ typeUrl 123 | ] 124 | 125 | { #category : #accessing } 126 | PBProtobufFieldNode >> wireType [ 127 | 128 | ^ self isCardinalityRepeated 129 | ifTrue: [ WireTypeLengthDelimited ] 130 | ifFalse: [ self type wireType ] 131 | ] 132 | -------------------------------------------------------------------------------- /Protobuf-Tools/PBProtobufFileNode.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBProtobufFileNode, 3 | #superclass : #PBProtobufNode, 4 | #instVars : [ 5 | 'options', 6 | 'package', 7 | 'imports', 8 | 'messages', 9 | 'enums', 10 | 'services' 11 | ], 12 | #category : #'Protobuf-Tools-Model' 13 | } 14 | 15 | { #category : #'instance creation' } 16 | PBProtobufFileNode class >> fromNodes: aParseNodes [ 17 | 18 | ^self new initFromNodes: aParseNodes 19 | ] 20 | 21 | { #category : #accessing } 22 | PBProtobufFileNode >> enums [ 23 | ^ enums 24 | ] 25 | 26 | { #category : #accessing } 27 | PBProtobufFileNode >> imports [ 28 | ^ imports 29 | ] 30 | 31 | { #category : #initialization } 32 | PBProtobufFileNode >> initFromNodes: aParseNodes [ 33 | package := aParseNodes 34 | detect: [ :each | each isPackageNode ] 35 | ifNone: [ nil ]. 36 | imports := aParseNodes select: [ :each | each isImportNode ]. 37 | options := aParseNodes select: [ :each | each isOptionNode ]. 38 | messages := aParseNodes select: [ :each | each isMessageNode ]. 39 | self flag: 'added by CAs'. 40 | enums := aParseNodes select: [ :each | each isEnumNode ] 41 | ] 42 | 43 | { #category : #accessing } 44 | PBProtobufFileNode >> messages [ 45 | ^ messages 46 | ] 47 | 48 | { #category : #accessing } 49 | PBProtobufFileNode >> options [ 50 | ^ options 51 | ] 52 | 53 | { #category : #accessing } 54 | PBProtobufFileNode >> package [ 55 | ^ package 56 | ] 57 | 58 | { #category : #accessing } 59 | PBProtobufFileNode >> services [ 60 | ^ services 61 | ] 62 | -------------------------------------------------------------------------------- /Protobuf-Tools/PBProtobufGrammar.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBProtobufGrammar, 3 | #superclass : #PP2CompositeNode, 4 | #instVars : [ 5 | 'boolLiteral', 6 | 'charEscape', 7 | 'charValue', 8 | 'comment', 9 | 'constant', 10 | 'decimalLiteral', 11 | 'digits', 12 | 'emptyStatement', 13 | 'enum', 14 | 'enumBody', 15 | 'enumField', 16 | 'enumName', 17 | 'enumType', 18 | 'enumValueOption', 19 | 'exponent', 20 | 'field', 21 | 'fieldName', 22 | 'fieldNames', 23 | 'fieldNumber', 24 | 'fieldOption', 25 | 'fieldOptions', 26 | 'floatLiteral', 27 | 'fullIdent', 28 | 'hexDigit', 29 | 'hexDigits', 30 | 'hexEscape', 31 | 'hexLiteral', 32 | 'ident', 33 | 'import', 34 | 'intLiteral', 35 | 'keyType', 36 | 'mapField', 37 | 'mapName', 38 | 'message', 39 | 'messageBody', 40 | 'messageName', 41 | 'messageType', 42 | 'nonZeroDigit', 43 | 'octalDigit', 44 | 'octalDigits', 45 | 'octalLiteral', 46 | 'octEscape', 47 | 'oneof', 48 | 'oneofField', 49 | 'oneofName', 50 | 'option', 51 | 'optionName', 52 | 'package', 53 | 'proto', 54 | 'quote', 55 | 'range', 56 | 'ranges', 57 | 'reserved', 58 | 'rpc', 59 | 'rpcName', 60 | 'service', 61 | 'serviceName', 62 | 'strLiteral', 63 | 'syntax', 64 | 'topLevelDef', 65 | 'type', 66 | 'whiteSpace', 67 | 'enumFieldOptions' 68 | ], 69 | #category : #'Protobuf-Tools-Parser' 70 | } 71 | 72 | { #category : #'grammar-literals' } 73 | PBProtobufGrammar >> boolLiteral [ 74 | 75 | ^ 'true' asPParser / 'false' asPParser 76 | ] 77 | 78 | { #category : #primitives } 79 | PBProtobufGrammar >> charEscape [ 80 | 81 | ^ $\ asPParser , (PP2PredicateObjectNode anyOf: 'abfnrtv\''"') 82 | ] 83 | 84 | { #category : #primitives } 85 | PBProtobufGrammar >> charValue [ 86 | 87 | ^ hexEscape / octEscape / charEscape / ((PP2PredicateObjectNode anyOf: '''"\') not , #any asPParser) 88 | ] 89 | 90 | { #category : #'grammar-toplevel' } 91 | PBProtobufGrammar >> comment [ 92 | 93 | ^ (('/*' asPParser, ('*/' asPParser not, #any asPParser) star, '*/' asPParser) trim / 94 | ('//' asPParser, (#newline asPParser not, #any asPParser) star) trim) flatten 95 | ] 96 | 97 | { #category : #'grammar-literals' } 98 | PBProtobufGrammar >> constant [ 99 | 100 | ^ boolLiteral / 101 | fullIdent / 102 | ((PP2PredicateObjectNode anyOf: '-+') optional, intLiteral) / 103 | ((PP2PredicateObjectNode anyOf: '-+') optional, floatLiteral) / 104 | strLiteral 105 | ] 106 | 107 | { #category : #'grammar-literals' } 108 | PBProtobufGrammar >> decimalLiteral [ 109 | 110 | ^ (nonZeroDigit, digits optional) flatten 111 | ] 112 | 113 | { #category : #primitives } 114 | PBProtobufGrammar >> digits [ 115 | "digit is already defined, no need to redefine it" 116 | 117 | ^#digit asPParser plus 118 | ] 119 | 120 | { #category : #'grammar-literals' } 121 | PBProtobufGrammar >> emptyStatement [ 122 | 123 | ^ $; asPParser 124 | ] 125 | 126 | { #category : #'grammar-toplevel' } 127 | PBProtobufGrammar >> enum [ 128 | 129 | ^'enum' asPParser, whiteSpace plus, enumName, enumBody 130 | ] 131 | 132 | { #category : #'grammar-literals' } 133 | PBProtobufGrammar >> enumBody [ 134 | 135 | ^${ asPParser trim, (comment / option / enumField / emptyStatement) star, $} asPParser trim 136 | ] 137 | 138 | { #category : #'grammar-literals' } 139 | PBProtobufGrammar >> enumField [ 140 | 141 | ^ ident, $= asPParser trim, intLiteral, enumFieldOptions optional, $; asPParser trim 142 | ] 143 | 144 | { #category : #'grammar-literals' } 145 | PBProtobufGrammar >> enumFieldOptions [ 146 | 147 | ^ $[ asPParser trim, (enumValueOption, ($, asPParser trim, enumValueOption) star), $] asPParser trim 148 | ] 149 | 150 | { #category : #'grammar-literals' } 151 | PBProtobufGrammar >> enumName [ 152 | 153 | ^ ident 154 | ] 155 | 156 | { #category : #'grammar-literals' } 157 | PBProtobufGrammar >> enumType [ 158 | 159 | ^ '.' asPParser optional, (ident, '.' asPParser) star, enumName 160 | ] 161 | 162 | { #category : #'grammar-literals' } 163 | PBProtobufGrammar >> enumValueOption [ 164 | 165 | ^ optionName, $= asPParser trim, constant 166 | ] 167 | 168 | { #category : #primitives } 169 | PBProtobufGrammar >> exponent [ 170 | 171 | ^ (PP2PredicateObjectNode anyOf: 'eE'), (PP2PredicateObjectNode anyOf: '+-') optional, digits 172 | ] 173 | 174 | { #category : #'grammar-literals' } 175 | PBProtobufGrammar >> field [ 176 | 177 | ^ ('repeated' asPParser, whiteSpace plus) optional, type, whiteSpace plus, fieldName, $= asPParser trim, fieldNumber, ( $[ asPParser trim, fieldOptions, $] asPParser trim) optional, $; asPParser trim 178 | ] 179 | 180 | { #category : #'grammar-literals' } 181 | PBProtobufGrammar >> fieldName [ 182 | 183 | ^ ident 184 | ] 185 | 186 | { #category : #'grammar-literals' } 187 | PBProtobufGrammar >> fieldNames [ 188 | 189 | ^ fieldName, ($, asPParser trim, fieldName) star 190 | ] 191 | 192 | { #category : #'grammar-literals' } 193 | PBProtobufGrammar >> fieldNumber [ 194 | 195 | ^ intLiteral 196 | ] 197 | 198 | { #category : #'grammar-literals' } 199 | PBProtobufGrammar >> fieldOption [ 200 | 201 | ^ optionName, $= asPParser trim, constant 202 | ] 203 | 204 | { #category : #'grammar-literals' } 205 | PBProtobufGrammar >> fieldOptions [ 206 | 207 | ^ fieldOption, ($, asPParser trim, fieldOption) star 208 | ] 209 | 210 | { #category : #'grammar-literals' } 211 | PBProtobufGrammar >> floatLiteral [ 212 | 213 | ^ ((digits, '.' asPParser, digits optional, exponent optional) / 214 | (digits, exponent) / 215 | ('.' asPParser, digits, exponent optional)) flatten 216 | ] 217 | 218 | { #category : #primitives } 219 | PBProtobufGrammar >> fullIdent [ 220 | 221 | ^ (ident, ('.' asPParser, ident) star) flatten 222 | ] 223 | 224 | { #category : #primitives } 225 | PBProtobufGrammar >> hexDigit [ 226 | 227 | ^#hex asPParser 228 | ] 229 | 230 | { #category : #primitives } 231 | PBProtobufGrammar >> hexDigits [ 232 | 233 | ^hexDigit plus 234 | ] 235 | 236 | { #category : #primitives } 237 | PBProtobufGrammar >> hexEscape [ 238 | 239 | ^ $\ asPParser , (PP2PredicateObjectNode anyOf: 'xX'), hexDigit, hexDigit 240 | ] 241 | 242 | { #category : #'grammar-literals' } 243 | PBProtobufGrammar >> hexLiteral [ 244 | 245 | ^ ($0 asPParser, (PP2PredicateObjectNode anyOf: 'xX' ), hexDigits) flatten 246 | ] 247 | 248 | { #category : #primitives } 249 | PBProtobufGrammar >> ident [ 250 | 251 | | word letter | 252 | letter := (PP2PredicateObjectNode 253 | on: [ :each | each isLetter ] 254 | message: 'letter expected'). 255 | 256 | word := (PP2PredicateObjectNode 257 | on: [ :each | each isAlphaNumeric or: [ each = $_ ] ] 258 | message: 'letter, digit or underscore expected'). 259 | 260 | ^ (letter, word star) flatten 261 | ] 262 | 263 | { #category : #'grammar-toplevel' } 264 | PBProtobufGrammar >> import [ 265 | 266 | ^ 'import' asPParser, whiteSpace plus, (('weak' asPParser / 'public' asPParser), whiteSpace plus) optional, strLiteral, $; asPParser trim 267 | ] 268 | 269 | { #category : #'grammar-literals' } 270 | PBProtobufGrammar >> intLiteral [ 271 | 272 | ^(decimalLiteral / octalLiteral / hexLiteral) 273 | ] 274 | 275 | { #category : #'grammar-literals' } 276 | PBProtobufGrammar >> keyType [ 277 | 278 | ^ 'int32' asPParser / 279 | 'int64' asPParser / 280 | 'uint32' asPParser / 281 | 'uint64' asPParser / 282 | 'sint32' asPParser / 283 | 'sint64' asPParser / 284 | 'fixed32' asPParser / 285 | 'fixed64' asPParser / 286 | 'sfixed32' asPParser / 287 | 'sfixed64' asPParser / 288 | 'bool' asPParser / 289 | 'string' asPParser 290 | ] 291 | 292 | { #category : #'grammar-literals' } 293 | PBProtobufGrammar >> mapField [ 294 | 295 | ^'map' asPParser, $< asPParser, keyType, $, asPParser trim, type, $> asPParser, whiteSpace star, mapName, $= asPParser trim, fieldNumber, ( $[ asPParser trim, fieldOptions, $] asPParser trim) optional, $; asPParser trim 296 | ] 297 | 298 | { #category : #'grammar-literals' } 299 | PBProtobufGrammar >> mapName [ 300 | 301 | ^ ident 302 | ] 303 | 304 | { #category : #'grammar-toplevel' } 305 | PBProtobufGrammar >> message [ 306 | 307 | ^'message' asPParser, whiteSpace plus, messageName, messageBody 308 | ] 309 | 310 | { #category : #'grammar-literals' } 311 | PBProtobufGrammar >> messageBody [ 312 | 313 | ^${ asPParser trim, (comment / field / enum / message / option / oneof / mapField / reserved / emptyStatement) star, $} asPParser trim 314 | ] 315 | 316 | { #category : #'grammar-literals' } 317 | PBProtobufGrammar >> messageName [ 318 | 319 | ^ ident 320 | ] 321 | 322 | { #category : #'grammar-literals' } 323 | PBProtobufGrammar >> messageType [ 324 | 325 | ^ ('.' asPParser optional, (ident, '.' asPParser) star, messageName) flatten 326 | ] 327 | 328 | { #category : #'grammar-literals' } 329 | PBProtobufGrammar >> nonZeroDigit [ 330 | 331 | ^ PP2PredicateObjectNode anyOf: '123456789' 332 | ] 333 | 334 | { #category : #primitives } 335 | PBProtobufGrammar >> octEscape [ 336 | 337 | ^ $\ asPParser, octalDigit, octalDigit, octalDigit 338 | ] 339 | 340 | { #category : #primitives } 341 | PBProtobufGrammar >> octalDigit [ 342 | 343 | ^PP2PredicateObjectNode anyOf: '01234567' 344 | ] 345 | 346 | { #category : #primitives } 347 | PBProtobufGrammar >> octalDigits [ 348 | 349 | ^ octalDigit plus 350 | ] 351 | 352 | { #category : #'grammar-literals' } 353 | PBProtobufGrammar >> octalLiteral [ 354 | 355 | ^ (($0 asPParser), octalDigit star) flatten 356 | ] 357 | 358 | { #category : #'grammar-literals' } 359 | PBProtobufGrammar >> oneof [ 360 | 361 | ^ 'oneof' asPParser, whiteSpace plus, oneofName, ${ asPParser trim, (oneofField / emptyStatement) star, $} asPParser trim 362 | ] 363 | 364 | { #category : #'grammar-literals' } 365 | PBProtobufGrammar >> oneofField [ 366 | 367 | ^type, whiteSpace plus, fieldName, $= asPParser trim, fieldNumber, ( $[ asPParser trim, fieldOptions, $] asPParser trim) optional, $; asPParser trim 368 | ] 369 | 370 | { #category : #'grammar-literals' } 371 | PBProtobufGrammar >> oneofName [ 372 | 373 | ^ ident 374 | ] 375 | 376 | { #category : #'grammar-literals' } 377 | PBProtobufGrammar >> option [ 378 | 379 | ^ 'option' asPParser, whiteSpace plus, optionName, $= asPParser trim, constant, $; asPParser trim 380 | ] 381 | 382 | { #category : #'grammar-literals' } 383 | PBProtobufGrammar >> optionName [ 384 | 385 | ^ ((ident / ($( asPParser, fullIdent, $) asPParser)), ( $. asPParser, ident) star) flatten 386 | ] 387 | 388 | { #category : #'grammar-literals' } 389 | PBProtobufGrammar >> package [ 390 | 391 | ^ 'package' asPParser, whiteSpace plus, fullIdent, $; asPParser trim 392 | ] 393 | 394 | { #category : #'grammar-toplevel' } 395 | PBProtobufGrammar >> proto [ 396 | 397 | ^ comment star, syntax, (comment / import / package / option / message / enum / service / emptyStatement) star 398 | ] 399 | 400 | { #category : #primitives } 401 | PBProtobufGrammar >> quote [ 402 | 403 | ^ PP2PredicateObjectNode anyOf: '''"' 404 | ] 405 | 406 | { #category : #'grammar-literals' } 407 | PBProtobufGrammar >> range [ 408 | 409 | ^ intLiteral, ('to' asPParser trim, (intLiteral / 'max' asPParser)) optional 410 | ] 411 | 412 | { #category : #'grammar-literals' } 413 | PBProtobufGrammar >> ranges [ 414 | 415 | ^range, ($, asPParser trim, range) star 416 | ] 417 | 418 | { #category : #'grammar-literals' } 419 | PBProtobufGrammar >> reserved [ 420 | 421 | ^ 'reserved' asPParser, whiteSpace plus, (ranges / fieldNames), $; asPParser trim 422 | ] 423 | 424 | { #category : #'grammar-literals' } 425 | PBProtobufGrammar >> rpc [ 426 | 427 | ^ 'rpc' asPParser, 428 | whiteSpace plus, rpcName, 429 | $( asPParser trim, 'stream' asPParser optional, messageType, $) asPParser trim, 430 | 'returns' asPParser, $( asPParser trim, 'stream' asPParser optional, messageType, $) asPParser trim, 431 | (( ${ asPParser trim, (option / emptyStatement) star, $} asPParser trim) / $; asPParser trim) 432 | ] 433 | 434 | { #category : #'grammar-literals' } 435 | PBProtobufGrammar >> rpcName [ 436 | 437 | ^ ident 438 | ] 439 | 440 | { #category : #'grammar-toplevel' } 441 | PBProtobufGrammar >> service [ 442 | 443 | ^ 'service' asPParser, whiteSpace plus, serviceName, ${ asPParser trim, (option / rpc / emptyStatement) star, $} asPParser trim 444 | ] 445 | 446 | { #category : #'grammar-literals' } 447 | PBProtobufGrammar >> serviceName [ 448 | 449 | ^ ident 450 | ] 451 | 452 | { #category : #accessing } 453 | PBProtobufGrammar >> start [ 454 | "Default start production." 455 | 456 | ^ proto 457 | ] 458 | 459 | { #category : #'grammar-literals' } 460 | PBProtobufGrammar >> strLiteral [ 461 | 462 | ^ ($' asPParser, charValue star flatten, $' asPParser) / 463 | ($" asPParser, charValue star flatten, $" asPParser) 464 | ] 465 | 466 | { #category : #'grammar-literals' } 467 | PBProtobufGrammar >> syntax [ 468 | 469 | ^ 'syntax' asPParser, $= asPParser trim, quote, 'proto3' asPParser, quote, $; asPParser trim 470 | ] 471 | 472 | { #category : #'grammar-toplevel' } 473 | PBProtobufGrammar >> topLevelDef [ 474 | 475 | ^message / enum / service 476 | ] 477 | 478 | { #category : #'grammar-literals' } 479 | PBProtobufGrammar >> type [ 480 | 481 | ^ 'double' asPParser / 482 | 'float' asPParser / 483 | 'int32' asPParser / 484 | 'int64' asPParser / 485 | 'uint32' asPParser / 486 | 'uint64' asPParser / 487 | 'sint32' asPParser / 488 | 'sint64' asPParser / 489 | 'fixed32' asPParser / 490 | 'fixed64' asPParser / 491 | 'sfixed32' asPParser / 492 | 'sfixed64' asPParser / 493 | 'bool' asPParser / 494 | 'string' asPParser / 495 | 'bytes' asPParser / 496 | messageType / 497 | enumType 498 | ] 499 | 500 | { #category : #primitives } 501 | PBProtobufGrammar >> whiteSpace [ 502 | 503 | ^#space asPParser 504 | ] 505 | -------------------------------------------------------------------------------- /Protobuf-Tools/PBProtobufImportNode.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBProtobufImportNode, 3 | #superclass : #PBProtobufNode, 4 | #instVars : [ 5 | 'name', 6 | 'isPublic', 7 | 'isWeak' 8 | ], 9 | #category : #'Protobuf-Tools-Model' 10 | } 11 | 12 | { #category : #'instance creation' } 13 | PBProtobufImportNode class >> name: aName public: publicFlag weak: weakFlag [ 14 | 15 | ^ self new initWithName: aName public: publicFlag weak: weakFlag 16 | ] 17 | 18 | { #category : #initialization } 19 | PBProtobufImportNode >> initWithName: aName public: publicFlag weak: weakFlag [ 20 | 21 | name := aName. 22 | isPublic := publicFlag. 23 | isWeak := weakFlag 24 | ] 25 | 26 | { #category : #testing } 27 | PBProtobufImportNode >> isImportNode [ 28 | ^ true 29 | ] 30 | 31 | { #category : #testing } 32 | PBProtobufImportNode >> isPublic [ 33 | ^ isPublic 34 | ] 35 | 36 | { #category : #testing } 37 | PBProtobufImportNode >> isWeak [ 38 | ^ isWeak 39 | ] 40 | 41 | { #category : #accessing } 42 | PBProtobufImportNode >> name [ 43 | ^ name 44 | ] 45 | -------------------------------------------------------------------------------- /Protobuf-Tools/PBProtobufMessageNode.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBProtobufMessageNode, 3 | #superclass : #PBProtobufNode, 4 | #instVars : [ 5 | 'name', 6 | 'fields', 7 | 'options' 8 | ], 9 | #category : #'Protobuf-Tools-Model' 10 | } 11 | 12 | { #category : #'instance creation' } 13 | PBProtobufMessageNode class >> name: aName fields: aFieldColl options: anOptionColl [ 14 | 15 | ^self new initWithName: aName fields: aFieldColl options: anOptionColl 16 | ] 17 | 18 | { #category : #accessing } 19 | PBProtobufMessageNode >> fields [ 20 | ^ fields 21 | ] 22 | 23 | { #category : #initialization } 24 | PBProtobufMessageNode >> initWithName: aName fields: aFieldColl options: anOptionColl [ 25 | 26 | name := aName. 27 | fields := aFieldColl asArray. 28 | options := anOptionColl asArray 29 | ] 30 | 31 | { #category : #testing } 32 | PBProtobufMessageNode >> isMessageNode [ 33 | 34 | ^ true 35 | ] 36 | 37 | { #category : #accessing } 38 | PBProtobufMessageNode >> name [ 39 | ^ name 40 | ] 41 | 42 | { #category : #accessing } 43 | PBProtobufMessageNode >> options [ 44 | ^ options 45 | ] 46 | 47 | { #category : #printing } 48 | PBProtobufMessageNode >> printOn: aStream [ 49 | 50 | aStream 51 | nextPutAll: self class name; 52 | nextPut: $<; 53 | print: self name; 54 | nextPut: $> 55 | ] 56 | 57 | { #category : #copying } 58 | PBProtobufMessageNode >> withName: newName [ 59 | 60 | ^self class name: newName fields: fields options: options 61 | ] 62 | -------------------------------------------------------------------------------- /Protobuf-Tools/PBProtobufNode.class.st: -------------------------------------------------------------------------------- 1 | " 2 | I am the base class for all the PBProtobuf parse nodes. 3 | " 4 | Class { 5 | #name : #PBProtobufNode, 6 | #superclass : #Object, 7 | #category : #'Protobuf-Tools-Model' 8 | } 9 | 10 | { #category : #comparing } 11 | PBProtobufNode >> = otherMessage [ 12 | 13 | self == otherMessage 14 | ifTrue: [ ^true ]. 15 | self class = otherMessage class 16 | ifFalse: [ ^false ]. 17 | 18 | 1 to: self class instSize do: [ :index| 19 | (self instVarAt: index) = (otherMessage instVarAt: index) 20 | ifFalse: [ ^false ] ]. 21 | ^ true 22 | ] 23 | 24 | { #category : #comparing } 25 | PBProtobufNode >> hash [ 26 | 27 | | value | 28 | value := self class hash. 29 | 1 to: self class instSize do: [ :index | 30 | value := value bitXor: (self instVarAt: index) hash ]. 31 | ^value 32 | ] 33 | 34 | { #category : #testing } 35 | PBProtobufNode >> isEnumNode [ 36 | ^ false 37 | ] 38 | 39 | { #category : #testing } 40 | PBProtobufNode >> isEnumValueNode [ 41 | 42 | ^false 43 | ] 44 | 45 | { #category : #testing } 46 | PBProtobufNode >> isFieldNode [ 47 | ^false 48 | ] 49 | 50 | { #category : #testing } 51 | PBProtobufNode >> isImportNode [ 52 | ^false 53 | ] 54 | 55 | { #category : #testing } 56 | PBProtobufNode >> isMessageNode [ 57 | 58 | ^false 59 | ] 60 | 61 | { #category : #testing } 62 | PBProtobufNode >> isOptionNode [ 63 | 64 | ^false 65 | ] 66 | 67 | { #category : #testing } 68 | PBProtobufNode >> isPackageNode [ 69 | 70 | ^false 71 | ] 72 | -------------------------------------------------------------------------------- /Protobuf-Tools/PBProtobufOptionNode.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBProtobufOptionNode, 3 | #superclass : #PBProtobufNode, 4 | #instVars : [ 5 | 'name', 6 | 'value' 7 | ], 8 | #category : #'Protobuf-Tools-Model' 9 | } 10 | 11 | { #category : #'instance creation' } 12 | PBProtobufOptionNode class >> name: aName value: aValue [ 13 | 14 | ^ self new initWithName: aName value: aValue 15 | ] 16 | 17 | { #category : #initialization } 18 | PBProtobufOptionNode >> initWithName: aName value: aValue [ 19 | 20 | name := aName. 21 | value := aValue 22 | ] 23 | 24 | { #category : #testing } 25 | PBProtobufOptionNode >> isOptionNode [ 26 | 27 | ^true 28 | ] 29 | 30 | { #category : #accessing } 31 | PBProtobufOptionNode >> name [ 32 | ^ name 33 | ] 34 | 35 | { #category : #printing } 36 | PBProtobufOptionNode >> printOn: aStream [ 37 | 38 | aStream 39 | nextPutAll: self class name; 40 | nextPut: $<; 41 | print: self name; 42 | nextPut: $=; 43 | print: value; 44 | nextPut: $> 45 | ] 46 | 47 | { #category : #accessing } 48 | PBProtobufOptionNode >> value [ 49 | ^ value 50 | ] 51 | -------------------------------------------------------------------------------- /Protobuf-Tools/PBProtobufPackageNode.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBProtobufPackageNode, 3 | #superclass : #PBProtobufNode, 4 | #instVars : [ 5 | 'name' 6 | ], 7 | #category : #'Protobuf-Tools-Model' 8 | } 9 | 10 | { #category : #'instance creation' } 11 | PBProtobufPackageNode class >> name: aString [ 12 | 13 | ^self new initWithName: aString 14 | ] 15 | 16 | { #category : #initialization } 17 | PBProtobufPackageNode >> initWithName: aString [ 18 | 19 | name := aString 20 | ] 21 | 22 | { #category : #testing } 23 | PBProtobufPackageNode >> isPackageNode [ 24 | 25 | ^true 26 | ] 27 | 28 | { #category : #accessing } 29 | PBProtobufPackageNode >> name [ 30 | ^ name 31 | ] 32 | 33 | { #category : #printing } 34 | PBProtobufPackageNode >> printOn: aStream [ 35 | 36 | aStream 37 | nextPutAll: self class name; 38 | nextPut: $<; 39 | print: self name; 40 | nextPut: $> 41 | ] 42 | -------------------------------------------------------------------------------- /Protobuf-Tools/PBProtobufParser.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBProtobufParser, 3 | #superclass : #PBProtobufGrammar, 4 | #instVars : [ 5 | 'start' 6 | ], 7 | #category : #'Protobuf-Tools-Parser' 8 | } 9 | 10 | { #category : #'grammar-literals' } 11 | PBProtobufParser >> boolLiteral [ 12 | 13 | ^super boolLiteral ==> [ :v | v = 'true' ] 14 | ] 15 | 16 | { #category : #'grammar-literals' } 17 | PBProtobufParser >> comment [ 18 | 19 | ^super comment ==> [ :str | PBProtobufCommentNode text: str ] 20 | ] 21 | 22 | { #category : #'grammar-literals' } 23 | PBProtobufParser >> constant [ 24 | 25 | ^super constant ==> [ :val | 26 | val class = Array 27 | ifTrue: [ 28 | val first = $- 29 | ifTrue: [ (val at: 2) negated ] 30 | ifFalse: [ val at: 2 ] ] 31 | ifFalse: [ 32 | val ] ] 33 | ] 34 | 35 | { #category : #'grammar-literals' } 36 | PBProtobufParser >> decimalLiteral [ 37 | 38 | ^super decimalLiteral ==> [ :str | self numberParser parse: str ] 39 | 40 | ] 41 | 42 | { #category : #'grammar-toplevel' } 43 | PBProtobufParser >> enum [ 44 | ^ super enum 45 | ==> [ :array | 46 | | name body | 47 | name := array at: 3. 48 | body := array at: 4. 49 | body withName: name ] 50 | ] 51 | 52 | { #category : #'grammar-literals' } 53 | PBProtobufParser >> enumBody [ 54 | 55 | ^super enumBody ==> [ :array | 56 | | contents | 57 | contents := array at: 2. 58 | PBProtobufEnum name: '' 59 | values: (contents select: [ :each | each isEnumValueNode] ) 60 | options: (contents select: [ :each | each isOptionNode ]) ] 61 | ] 62 | 63 | { #category : #'grammar-literals' } 64 | PBProtobufParser >> enumField [ 65 | 66 | ^super enumField ==> [ :array | 67 | PBProtobufEnumValue name: (array at: 1) 68 | number: (array at: 3) 69 | options: ((array at: 4) ifNil: [ #() ]) ] 70 | 71 | ] 72 | 73 | { #category : #'grammar-literals' } 74 | PBProtobufParser >> enumFieldOptions [ 75 | 76 | ^super enumFieldOptions ==> [ :array | 77 | | list result | 78 | list := array at: 2. 79 | result := OrderedCollection new. 80 | list notEmpty 81 | ifTrue: [ 82 | result add: list first. 83 | list size > 1 84 | ifTrue: [ 85 | result addAll: ((list at: 2) collect: [ :eachArray | eachArray last ]) ] ]. 86 | result asArray ] 87 | ] 88 | 89 | { #category : #accessing } 90 | PBProtobufParser >> enumValueOption [ 91 | "Answer an association with the options name as key and the constant as value." 92 | 93 | ^super enumValueOption ==> [ :array | (array at: 1) -> (array at: 3) ] 94 | ] 95 | 96 | { #category : #accessing } 97 | PBProtobufParser >> field [ 98 | 99 | ^super field ==> [ :array | 100 | 101 | | fType fCardinality fName fNumber | 102 | 103 | fType := array at: 2. 104 | fCardinality := array first = 'repeated' 105 | ifTrue: [ #CARDINALITY_REPEATED ] 106 | ifFalse: [ #CARDINALITY_OPTIONAL ]. 107 | fName := array at: 4. 108 | fNumber := (array at: 6) asNumber. 109 | 110 | PBProtobufFieldNode number: fNumber 111 | name: fName 112 | type: fType 113 | cardinality: fCardinality ] 114 | ] 115 | 116 | { #category : #'grammar-literals' } 117 | PBProtobufParser >> floatLiteral [ 118 | 119 | ^super floatLiteral ==> [ :str | self numberParser parse: str ] 120 | 121 | ] 122 | 123 | { #category : #accessing } 124 | PBProtobufParser >> fullIdent [ 125 | 126 | ^super fullIdent ==> [ :str| str ] 127 | ] 128 | 129 | { #category : #'grammar-literals' } 130 | PBProtobufParser >> hexLiteral [ 131 | 132 | ^super hexLiteral ==> [ :str | self numberParser parse: '16r', (str allButFirst: 2) ] 133 | 134 | ] 135 | 136 | { #category : #'grammar-toplevel' } 137 | PBProtobufParser >> import [ 138 | 139 | ^super import ==> [ :array | 140 | PBProtobufImportNode name: (array at: 4) 141 | public: (((array at: 3) ifNil: [ #() ]) includes: 'public') 142 | weak: (((array at: 3) ifNil: [ #() ]) includes: 'weak') ] 143 | ] 144 | 145 | { #category : #accessing } 146 | PBProtobufParser >> mapField [ 147 | 148 | ^super mapField ==> [ :array | 149 | 150 | | fType fCardinality fName fNumber | 151 | 152 | fType := #TYPE_MESSAGE. 153 | fCardinality := array first = 'repeated' 154 | ifTrue: [ #CARDINALITY_REPEATED ] 155 | ifFalse: [ #CARDINALITY_OPTIONAL ]. 156 | fName := array at: 8. 157 | fNumber := (array at: 10) asNumber. 158 | 159 | PBProtobufFieldNode number: fNumber 160 | name: fName 161 | type: fType 162 | cardinality: fCardinality ] 163 | ] 164 | 165 | { #category : #'grammar-toplevel' } 166 | PBProtobufParser >> message [ 167 | 168 | ^super message ==> [ :array | 169 | | name body | 170 | name := array at: 3. 171 | body := array at: 4. 172 | body withName: name ] 173 | ] 174 | 175 | { #category : #'grammar-literals' } 176 | PBProtobufParser >> messageBody [ 177 | 178 | ^super messageBody ==> [ :array | 179 | | contents | 180 | contents := array at: 2. 181 | PBProtobufMessageNode name: '' 182 | fields: (contents select: [ :each | each isFieldNode] ) 183 | options: (contents select: [ :each | each isOptionNode ]) ] 184 | ] 185 | 186 | { #category : #accessing } 187 | PBProtobufParser >> numberParser [ 188 | 189 | ^NumberParser 190 | ] 191 | 192 | { #category : #'grammar-literals' } 193 | PBProtobufParser >> octalLiteral [ 194 | 195 | ^super octalLiteral ==> [ :str | self numberParser parse: '8r', str ] 196 | ] 197 | 198 | { #category : #accessing } 199 | PBProtobufParser >> option [ 200 | "Answer an association with the full identifier String as key and the constant as value." 201 | 202 | ^super option ==> [ :array | 203 | PBProtobufOptionNode name: (array at: 3) value: (array at: 5) ] 204 | ] 205 | 206 | { #category : #'grammar-toplevel' } 207 | PBProtobufParser >> package [ 208 | 209 | ^super package ==> [ :array | PBProtobufPackageNode name: (array at: 3) ] 210 | ] 211 | 212 | { #category : #'grammar-toplevel' } 213 | PBProtobufParser >> proto [ 214 | 215 | ^super proto ==> [ :array | 216 | | relevantNodes | 217 | relevantNodes := (array at: 3). 218 | PBProtobufFileNode fromNodes: relevantNodes ] 219 | ] 220 | 221 | { #category : #'grammar-literals' } 222 | PBProtobufParser >> strLiteral [ 223 | 224 | ^super strLiteral ==> [ :array | array at: 2 ] 225 | 226 | ] 227 | 228 | { #category : #'grammar-literals' } 229 | PBProtobufParser >> type [ 230 | 231 | ^super type ==> [ :str | PBProtobufTypeNode name: str ] 232 | ] 233 | -------------------------------------------------------------------------------- /Protobuf-Tools/PBProtobufTypeNode.class.st: -------------------------------------------------------------------------------- 1 | " 2 | Protocol Buffers message type. 3 | " 4 | Class { 5 | #name : #PBProtobufTypeNode, 6 | #superclass : #PBProtobufNode, 7 | #instVars : [ 8 | 'name' 9 | ], 10 | #pools : [ 11 | 'PBProtobufConstants' 12 | ], 13 | #category : #'Protobuf-Tools-Model' 14 | } 15 | 16 | { #category : #resources } 17 | PBProtobufTypeNode class >> bool [ 18 | 19 | ^self name: 'bool' 20 | ] 21 | 22 | { #category : #resources } 23 | PBProtobufTypeNode class >> bytes [ 24 | 25 | ^self name: 'bytes' 26 | ] 27 | 28 | { #category : #resources } 29 | PBProtobufTypeNode class >> double [ 30 | 31 | ^self name: 'double' 32 | ] 33 | 34 | { #category : #resources } 35 | PBProtobufTypeNode class >> fixed32 [ 36 | 37 | ^self name: 'fixed32' 38 | ] 39 | 40 | { #category : #resources } 41 | PBProtobufTypeNode class >> fixed64 [ 42 | 43 | ^self name: 'fixed64' 44 | ] 45 | 46 | { #category : #resources } 47 | PBProtobufTypeNode class >> float [ 48 | 49 | ^self name: 'float' 50 | ] 51 | 52 | { #category : #resources } 53 | PBProtobufTypeNode class >> int32 [ 54 | 55 | ^self name: 'int32' 56 | ] 57 | 58 | { #category : #resources } 59 | PBProtobufTypeNode class >> int64 [ 60 | 61 | ^self name: 'int64' 62 | ] 63 | 64 | { #category : #'instance creation' } 65 | PBProtobufTypeNode class >> name: aName [ 66 | 67 | ^self new initWithName: aName 68 | ] 69 | 70 | { #category : #resources } 71 | PBProtobufTypeNode class >> scalarValueTypeNames [ 72 | 73 | ^self standardTypes keys 74 | ] 75 | 76 | { #category : #resources } 77 | PBProtobufTypeNode class >> sint32 [ 78 | 79 | ^self name: 'sint32' 80 | ] 81 | 82 | { #category : #resources } 83 | PBProtobufTypeNode class >> sint64 [ 84 | 85 | ^self name: 'sint64' 86 | ] 87 | 88 | { #category : #resources } 89 | PBProtobufTypeNode class >> standardTypes [ 90 | 91 | ^ Dictionary new 92 | at: 'double' put: #TYPE_DOUBLE; 93 | at: 'float' put: #TYPE_FLOAT; 94 | at: 'int64' put: #TYPE_INT64; 95 | at: 'uint64' put: #TYPE_UINT64; 96 | at: 'int32' put: #TYPE_INT32; 97 | at: 'uint32' put: #TYPE_UINT32; 98 | at: 'fixed64' put: #TYPE_FIXED64; 99 | at: 'fixed32' put: #TYPE_FIXED32; 100 | at: 'bool' put: #TYPE_BOOL; 101 | at: 'string' put: #TYPE_STRING; 102 | at: 'bytes' put: #TYPE_BYTES; 103 | at: 'sfixed64' put: #TYPE_SFIXED64; 104 | at: 'sfixed32' put: #TYPE_SFIXED32; 105 | at: 'sint32' put: #TYPE_SINT32; 106 | at: 'sint64' put: #TYPE_SINT64; 107 | yourself 108 | 109 | ] 110 | 111 | { #category : #resources } 112 | PBProtobufTypeNode class >> string [ 113 | 114 | ^self name: 'string' 115 | ] 116 | 117 | { #category : #resources } 118 | PBProtobufTypeNode class >> uint32 [ 119 | 120 | ^self name: 'uint32' 121 | ] 122 | 123 | { #category : #resources } 124 | PBProtobufTypeNode class >> uint64 [ 125 | 126 | ^self name: 'uint64' 127 | ] 128 | 129 | { #category : #accessing } 130 | PBProtobufTypeNode >> defaultParameterName [ 131 | 132 | self isIntegerType 133 | ifTrue: [ ^ 'anInteger' ]. 134 | 135 | self isStringType 136 | ifTrue: [ ^ 'aString' ]. 137 | 138 | self isBooleanType 139 | ifTrue: [ ^ 'aBoolean' ]. 140 | 141 | self isFloatType 142 | ifTrue: [ ^ 'aFloat' ]. 143 | 144 | self isBytesType 145 | ifTrue: [ ^ 'aByteArray' ]. 146 | 147 | ^'anObject' 148 | ] 149 | 150 | { #category : #accessing } 151 | PBProtobufTypeNode >> defaultValue [ 152 | 153 | "For numeric types, the default value is zero." 154 | (self isIntegerType or: [ self isFloatType ]) 155 | ifTrue: [ ^ 0 ]. 156 | 157 | "For strings, the default value is the empty string." 158 | self isStringType 159 | ifTrue: [ ^ '' ]. 160 | 161 | "For bools, the default value is false." 162 | self isBooleanType 163 | ifTrue: [ ^ false ]. 164 | 165 | "For bytes, the default value is empty bytes." 166 | self isBytesType 167 | ifTrue: [ ^ #[] ]. 168 | 169 | "For enums, the default value is the first defined enum value, which must be 0." 170 | self isEnumType 171 | ifTrue: [ ^0 "todo" ]. 172 | 173 | "For message fields, the field is not set. Its exact value is language-dependent." 174 | ^nil 175 | ] 176 | 177 | { #category : #initialization } 178 | PBProtobufTypeNode >> initWithName: aName [ 179 | 180 | name := aName 181 | ] 182 | 183 | { #category : #testing } 184 | PBProtobufTypeNode >> isBooleanType [ 185 | 186 | ^ self name = 'bool' 187 | ] 188 | 189 | { #category : #testing } 190 | PBProtobufTypeNode >> isBytesType [ 191 | 192 | ^ self name = 'bytes' 193 | ] 194 | 195 | { #category : #testing } 196 | PBProtobufTypeNode >> isEnumType [ 197 | 198 | ^false 199 | 200 | 201 | ] 202 | 203 | { #category : #testing } 204 | PBProtobufTypeNode >> isFloatType [ 205 | 206 | ^ #( 'float' 'double' ) includes: self name 207 | ] 208 | 209 | { #category : #testing } 210 | PBProtobufTypeNode >> isIntegerType [ 211 | 212 | ^ #( 'int32' 'int64' 'uint32' 'uint64' 'sint32' 'sint64' 'fixed32' 'fixed64' ) includes: self name 213 | ] 214 | 215 | { #category : #testing } 216 | PBProtobufTypeNode >> isScalarValueType [ 217 | 218 | ^self class scalarValueTypeNames includes: self name 219 | 220 | 221 | ] 222 | 223 | { #category : #testing } 224 | PBProtobufTypeNode >> isStringType [ 225 | 226 | ^ self name = 'string' 227 | ] 228 | 229 | { #category : #accessing } 230 | PBProtobufTypeNode >> name [ 231 | ^ name 232 | ] 233 | 234 | { #category : #printing } 235 | PBProtobufTypeNode >> printOn: aStream [ 236 | 237 | aStream 238 | nextPutAll: self class name; 239 | nextPut: $<; 240 | print: self name; 241 | nextPut: $> 242 | ] 243 | 244 | { #category : #accessing } 245 | PBProtobufTypeNode >> wireType [ 246 | 247 | ( self isEnumType or: [ #( 'int32' 'int64' 'uint32' 'uint64' 'sint32' 'sint64' 'bool' ) includes: self name ]) 248 | ifTrue: [ ^WireTypeVarint ]. 249 | 250 | ( #( 'fixed64' 'sfixed64' 'double' ) includes: self name ) 251 | ifTrue: [ ^WireType64bit ]. 252 | 253 | ( #( 'sfixed32' 'sfixed32' 'float' ) includes: self name ) 254 | ifTrue: [ ^WireType32bit ]. 255 | 256 | ^WireTypeLengthDelimited 257 | ] 258 | -------------------------------------------------------------------------------- /Protobuf-Tools/PBSmalltalkEnumType.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBSmalltalkEnumType, 3 | #superclass : #PBSmalltalkNodeWrapper, 4 | #instVars : [ 5 | 'packageName', 6 | 'className', 7 | 'values' 8 | ], 9 | #category : #'Protobuf-Tools-Generator' 10 | } 11 | 12 | { #category : #accessing } 13 | PBSmalltalkEnumType >> className [ 14 | ^ className 15 | ] 16 | 17 | { #category : #accessing } 18 | PBSmalltalkEnumType >> className: aName [ 19 | className := aName 20 | ] 21 | 22 | { #category : #actions } 23 | PBSmalltalkEnumType >> generateIn: aRBSmalltalk [ 24 | | refactoring newClass updateRefactoring | 25 | refactoring := PBAddMessageClassRefactoring 26 | model: aRBSmalltalk 27 | addClassFor: self. 28 | refactoring execute. 29 | newClass := refactoring model classNamed: self className. 30 | updateRefactoring := PBUpdateMessageClassRefactoring 31 | messageType: self 32 | class: newClass. 33 | updateRefactoring model: aRBSmalltalk. 34 | updateRefactoring execute 35 | ] 36 | 37 | { #category : #initialization } 38 | PBSmalltalkEnumType >> initDefaults [ 39 | className := self node name capitalized asSymbol 40 | ] 41 | 42 | { #category : #initialization } 43 | PBSmalltalkEnumType >> on: anEnumNode [ 44 | 45 | super on: anEnumNode. 46 | values := anEnumNode values 47 | collect: [ :each | PBSmalltalkEnumValueType on: each ]. 48 | "what to do about options ? " 49 | self initDefaults 50 | ] 51 | 52 | { #category : #accessing } 53 | PBSmalltalkEnumType >> packageName [ 54 | ^ packageName 55 | ] 56 | 57 | { #category : #accessing } 58 | PBSmalltalkEnumType >> packageName: aName [ 59 | packageName := aName 60 | ] 61 | -------------------------------------------------------------------------------- /Protobuf-Tools/PBSmalltalkEnumValueType.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBSmalltalkEnumValueType, 3 | #superclass : #PBSmalltalkNodeWrapper, 4 | #category : #'Protobuf-Tools-Generator' 5 | } 6 | 7 | { #category : #initialization } 8 | PBSmalltalkEnumValueType >> initDefaults [ 9 | "variableName := self node name uncapitalized asSymbol. 10 | self isCardinalityRepeated 11 | ifTrue: [ variableName := variableName , 'List' ]" 12 | ] 13 | 14 | { #category : #accessing } 15 | PBSmalltalkEnumValueType >> name [ 16 | ^ self node name 17 | ] 18 | 19 | { #category : #accessing } 20 | PBSmalltalkEnumValueType >> number [ 21 | ^ self node number 22 | ] 23 | 24 | { #category : #initialization } 25 | PBSmalltalkEnumValueType >> on: aNode [ 26 | super on: aNode. 27 | 28 | self initDefaults 29 | ] 30 | 31 | { #category : #accessing } 32 | PBSmalltalkEnumValueType >> options [ 33 | ^ self node options 34 | ] 35 | -------------------------------------------------------------------------------- /Protobuf-Tools/PBSmalltalkFieldType.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBSmalltalkFieldType, 3 | #superclass : #PBSmalltalkNodeWrapper, 4 | #instVars : [ 5 | 'variableName' 6 | ], 7 | #category : #'Protobuf-Tools-Generator' 8 | } 9 | 10 | { #category : #accessing } 11 | PBSmalltalkFieldType >> comment [ 12 | 13 | ^String streamContents: [ :s | 14 | self node isCardinalityRepeated 15 | ifTrue: [ s nextPutAll: 'repeated ' ]. 16 | s 17 | nextPutAll: self node typeName; 18 | space; 19 | nextPutAll: self node name; 20 | nextPutAll: ' = '; 21 | print: self node number ] 22 | ] 23 | 24 | { #category : #accessing } 25 | PBSmalltalkFieldType >> defaultValue [ 26 | 27 | ^ self node defaultValue 28 | ] 29 | 30 | { #category : #initialization } 31 | PBSmalltalkFieldType >> initDefaults [ 32 | 33 | variableName := self node name uncapitalized asSymbol. 34 | self isCardinalityRepeated 35 | ifTrue: [ variableName := variableName, 'List' ] 36 | ] 37 | 38 | { #category : #testing } 39 | PBSmalltalkFieldType >> isCardinalityRepeated [ 40 | 41 | ^self node isCardinalityRepeated 42 | ] 43 | 44 | { #category : #accessing } 45 | PBSmalltalkFieldType >> number [ 46 | 47 | ^self node number 48 | ] 49 | 50 | { #category : #initialization } 51 | PBSmalltalkFieldType >> on: aMessageNode [ 52 | 53 | super on: aMessageNode. 54 | 55 | self initDefaults 56 | ] 57 | 58 | { #category : #accessing } 59 | PBSmalltalkFieldType >> parameterName [ 60 | 61 | ^ self isCardinalityRepeated 62 | ifTrue: [ self type defaultParameterName, 'List' ] 63 | ifFalse: [ self type defaultParameterName ] 64 | ] 65 | 66 | { #category : #accessing } 67 | PBSmalltalkFieldType >> tagNumber [ 68 | 69 | ^self node tagNumber 70 | ] 71 | 72 | { #category : #accessing } 73 | PBSmalltalkFieldType >> type [ 74 | 75 | ^self node type 76 | ] 77 | 78 | { #category : #accessing } 79 | PBSmalltalkFieldType >> typeClassName [ 80 | 81 | ^ self isCardinalityRepeated 82 | ifTrue: [ OrderedCollection name ] 83 | ifFalse: [ self typeName ] 84 | ] 85 | 86 | { #category : #accessing } 87 | PBSmalltalkFieldType >> typeName [ 88 | 89 | ^self node typeName 90 | ] 91 | 92 | { #category : #accessing } 93 | PBSmalltalkFieldType >> typeNameCapitalized [ 94 | 95 | ^self typeName capitalized 96 | ] 97 | 98 | { #category : #accessing } 99 | PBSmalltalkFieldType >> variableName [ 100 | 101 | ^variableName 102 | ] 103 | -------------------------------------------------------------------------------- /Protobuf-Tools/PBSmalltalkMessageType.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBSmalltalkMessageType, 3 | #superclass : #PBSmalltalkNodeWrapper, 4 | #instVars : [ 5 | 'packageName', 6 | 'className', 7 | 'fields' 8 | ], 9 | #category : #'Protobuf-Tools-Generator' 10 | } 11 | 12 | { #category : #accessing } 13 | PBSmalltalkMessageType >> className [ 14 | ^ className 15 | ] 16 | 17 | { #category : #accessing } 18 | PBSmalltalkMessageType >> className: aName [ 19 | className := aName 20 | ] 21 | 22 | { #category : #actions } 23 | PBSmalltalkMessageType >> demo [ 24 | "self new demo" 25 | 26 | | msgNode | 27 | 28 | msgNode := PBProtobufMessageNode name: 'TestMsg1' 29 | fields: (Array 30 | with: (PBProtobufFieldNode number: 1 name: 'fieldOne' typeName: 'string') 31 | with: (PBProtobufFieldNode number: 2 name: 'fieldTwo' typeName: 'int64') 32 | with: (PBProtobufFieldNode number: 6 33 | name: 'flag' 34 | type: (PBProtobufTypeNode name: 'bool') 35 | cardinality: #CARDINALITY_REPEATED)) 36 | options: #(). 37 | 38 | self on: msgNode. 39 | self packageName: 'Protobuf-ZDemo'. 40 | 41 | self generateIn: (RBNamespace onEnvironment: RBBrowserEnvironment new) 42 | 43 | 44 | ] 45 | 46 | { #category : #accessing } 47 | PBSmalltalkMessageType >> fields [ 48 | ^ fields 49 | ] 50 | 51 | { #category : #actions } 52 | PBSmalltalkMessageType >> generateIn: aRBSmalltalk [ 53 | 54 | | refactoring newClass updateRefactoring | 55 | 56 | refactoring := PBAddMessageClassRefactoring model: aRBSmalltalk addClassFor: self. 57 | refactoring execute. 58 | 59 | newClass := refactoring model classNamed: self className. 60 | 61 | updateRefactoring := PBUpdateMessageClassRefactoring messageType: self class: newClass. 62 | updateRefactoring model: aRBSmalltalk. 63 | updateRefactoring execute. 64 | 65 | ] 66 | 67 | { #category : #initialization } 68 | PBSmalltalkMessageType >> initDefaults [ 69 | 70 | className := self node name capitalized asSymbol 71 | ] 72 | 73 | { #category : #initialization } 74 | PBSmalltalkMessageType >> on: aMessageNode [ 75 | 76 | super on: aMessageNode. 77 | 78 | fields := aMessageNode fields collect: [ :each | 79 | PBSmalltalkFieldType on: each ]. 80 | 81 | self initDefaults 82 | ] 83 | 84 | { #category : #accessing } 85 | PBSmalltalkMessageType >> packageName [ 86 | ^ packageName 87 | ] 88 | 89 | { #category : #accessing } 90 | PBSmalltalkMessageType >> packageName: aName [ 91 | packageName := aName 92 | ] 93 | -------------------------------------------------------------------------------- /Protobuf-Tools/PBSmalltalkNodeWrapper.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBSmalltalkNodeWrapper, 3 | #superclass : #Object, 4 | #instVars : [ 5 | 'node' 6 | ], 7 | #category : #'Protobuf-Tools-Generator' 8 | } 9 | 10 | { #category : #'instance creation' } 11 | PBSmalltalkNodeWrapper class >> on: aMessageNode [ 12 | 13 | ^self new on: aMessageNode 14 | ] 15 | 16 | { #category : #accessing } 17 | PBSmalltalkNodeWrapper >> node [ 18 | ^ node 19 | ] 20 | 21 | { #category : #initialization } 22 | PBSmalltalkNodeWrapper >> on: aNode [ 23 | 24 | node := aNode 25 | ] 26 | -------------------------------------------------------------------------------- /Protobuf-Tools/PBSmalltalkPackage.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBSmalltalkPackage, 3 | #superclass : #PBSmalltalkNodeWrapper, 4 | #instVars : [ 5 | 'packageName' 6 | ], 7 | #category : #'Protobuf-Tools-Generator' 8 | } 9 | -------------------------------------------------------------------------------- /Protobuf-Tools/PBUpdateEnumClassRefactoring.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBUpdateEnumClassRefactoring, 3 | #superclass : #RBRefactoring, 4 | #instVars : [ 5 | 'class', 6 | 'messageType' 7 | ], 8 | #category : #'Protobuf-Tools-Generator' 9 | } 10 | -------------------------------------------------------------------------------- /Protobuf-Tools/PBUpdateMessageClassRefactoring.class.st: -------------------------------------------------------------------------------- 1 | Class { 2 | #name : #PBUpdateMessageClassRefactoring, 3 | #superclass : #RBRefactoring, 4 | #instVars : [ 5 | 'class', 6 | 'messageType' 7 | ], 8 | #category : #'Protobuf-Tools-Generator' 9 | } 10 | 11 | { #category : #'as yet unclassified' } 12 | PBUpdateMessageClassRefactoring class >> messageType: aSmalltalkMessageType class: aClass [ 13 | 14 | ^self new messageType: aSmalltalkMessageType class: aClass 15 | ] 16 | 17 | { #category : #transforming } 18 | PBUpdateMessageClassRefactoring >> compileClearMethod [ 19 | 20 | | source | 21 | 22 | source := String streamContents: [ :s | self printClearMethodSourceOn: s ]. 23 | 24 | class 25 | compile: source 26 | classified: #('initialization'). 27 | 28 | ] 29 | 30 | { #category : #transforming } 31 | PBUpdateMessageClassRefactoring >> compileField: aFieldType [ 32 | 33 | | getter setter | 34 | 35 | class addInstanceVariable: aFieldType variableName. 36 | 37 | getter := String streamContents: [ :s | 38 | s 39 | nextPutAll: aFieldType variableName; cr; 40 | tab; nextPut: $"; nextPutAll: aFieldType comment; nextPut: $"; cr; 41 | tab; nextPutAll: '^ '; nextPutAll: aFieldType variableName ]. 42 | 43 | class 44 | compile: getter 45 | classified: #(accessing). 46 | 47 | setter := String streamContents: [ :s | 48 | s 49 | nextPutAll: aFieldType variableName; nextPut: $:; space; nextPutAll: aFieldType parameterName; cr; 50 | tab; nextPut: $"; nextPutAll: aFieldType comment; nextPut: $"; cr; 51 | tab; nextPutAll: aFieldType variableName; nextPutAll: ' := '; nextPutAll: aFieldType parameterName ]. 52 | 53 | class 54 | compile: setter 55 | classified: #(accessing). 56 | 57 | ] 58 | 59 | { #category : #transforming } 60 | PBUpdateMessageClassRefactoring >> compileInitializeMethod [ 61 | 62 | | source | 63 | 64 | source := String streamContents: [ :s | self printInitializeMethodSourceOn: s ]. 65 | 66 | class 67 | compile: source 68 | classified: #('initialization'). 69 | 70 | ] 71 | 72 | { #category : #transforming } 73 | PBUpdateMessageClassRefactoring >> compileReadFromMethod [ 74 | 75 | | source | 76 | 77 | source := String streamContents: [ :s | self printReadFromSourceOn: s ]. 78 | 79 | class 80 | compile: source 81 | classified: #('input-output'). 82 | 83 | ] 84 | 85 | { #category : #transforming } 86 | PBUpdateMessageClassRefactoring >> compileWriteTo [ 87 | 88 | | source | 89 | 90 | source := String streamContents: [ :s | self printWriteToSourceOn: s ]. 91 | 92 | class 93 | compile: source 94 | classified: #('input-output'). 95 | 96 | ] 97 | 98 | { #category : #initialization } 99 | PBUpdateMessageClassRefactoring >> messageType: aSmalltalkMessageType class: aClass [ 100 | 101 | messageType := aSmalltalkMessageType. 102 | class := aClass 103 | ] 104 | 105 | { #category : #preconditions } 106 | PBUpdateMessageClassRefactoring >> preconditions [ 107 | ^ RBCondition empty 108 | ] 109 | 110 | { #category : #transforming } 111 | PBUpdateMessageClassRefactoring >> printClearMethodSourceOn: s [ 112 | 113 | s 114 | nextPutAll: 'clear'; cr; 115 | tab; nextPutAll: '"Reset all Protobuf fields to their default values."'; cr; cr. 116 | 117 | messageType fields 118 | do: [ :eachField | 119 | s 120 | tab; 121 | nextPutAll: eachField variableName; 122 | nextPutAll: ' := '; 123 | print: eachField defaultValue ] 124 | separatedBy: [ 125 | s nextPut: $.; cr ] 126 | ] 127 | 128 | { #category : #transforming } 129 | PBUpdateMessageClassRefactoring >> printInitializeMethodSourceOn: s [ 130 | 131 | s 132 | nextPutAll: 'initialize'; cr; 133 | tab; nextPutAll: 'super initialize.'; cr; 134 | tab; nextPutAll: 'self clear' 135 | ] 136 | 137 | { #category : #transforming } 138 | PBUpdateMessageClassRefactoring >> printReadFromSourceOn: s [ 139 | 140 | s 141 | nextPutAll: 'readFrom: pbReadStream'; cr; 142 | tab; nextPutAll: '"Read this Protobuf message from the stream."'; cr; cr; 143 | tab; nextPutAll: '| dict done |'; cr; cr; 144 | tab; nextPutAll: 'dict := IdentityDictionary new'; cr. 145 | 146 | messageType fields 147 | do: [ :eachField | 148 | s 149 | tab; tab; nextPutAll: 'add: '; 150 | print: eachField tagNumber; 151 | nextPutAll: ' -> [ '; 152 | nextPutAll: eachField variableName; 153 | nextPutAll: ' := pbReadStream read'. 154 | eachField type isScalarValueType 155 | ifTrue: [ 156 | s nextPutAll: eachField typeNameCapitalized. 157 | eachField isCardinalityRepeated 158 | ifTrue: [ s nextPutAll: 'List' ]. 159 | ] 160 | ifFalse: [ 161 | eachField type isEnumType 162 | ifTrue: [ 163 | s nextPutAll: 'Enum: '; nextPutAll: eachField typeClassName ] 164 | ifFalse: [ 165 | "Must be message type" 166 | s nextPutAll: 'Message: '; nextPutAll: eachField typeClassName ] ]. 167 | s nextPutAll: ' ];'; cr ]. 168 | s tab; tab; nextPutAll: 'yourself.'; cr; cr. 169 | 170 | s 171 | tab; nextPutAll: 'self clear.'; cr; 172 | tab; nextPutAll: 'done := false.'; cr; 173 | tab; nextPutAll: '[ done ] whileFalse: ['; cr; 174 | tab; tab; nextPutAll: '| tag |'; cr; 175 | tab; tab; nextPutAll: 'tag := pbReadStream readTag.'; cr; 176 | tab; tab; nextPutAll: '(dict at: tag ifAbsent: [ self readUnknownField: tag from: pbReadStream ]) value.'; cr; 177 | tab; tab; nextPutAll: 'done := pbReadStream atEnd ]' 178 | ] 179 | 180 | { #category : #transforming } 181 | PBUpdateMessageClassRefactoring >> printWriteToSourceOn: s [ 182 | 183 | s 184 | nextPutAll: 'writeTo: pbWriteStream'; cr; 185 | tab; nextPutAll: '"Serialize this Protobuf message to the stream."'; cr; cr; 186 | tab; nextPutAll: 'pbWriteStream'; cr. 187 | messageType fields 188 | do: [ :eachField | 189 | s 190 | tab; tab; nextPutAll: 'writeField: '; print: eachField number; space. 191 | eachField type isScalarValueType 192 | ifTrue: [ 193 | s nextPutAll: eachField typeName. 194 | eachField isCardinalityRepeated 195 | ifTrue: [ s nextPutAll: 'List' ]. 196 | ] 197 | ifFalse: [ 198 | eachField type isEnumType 199 | ifTrue: [ 200 | s nextPutAll: 'enum' ] 201 | ifFalse: [ 202 | "Must be message type" 203 | s nextPutAll: 'message' ] ]. 204 | s nextPutAll: ': '; nextPutAll: eachField variableName ] 205 | separatedBy: [ 206 | s nextPut: $;; cr ] 207 | ] 208 | 209 | { #category : #transforming } 210 | PBUpdateMessageClassRefactoring >> transform [ 211 | 212 | messageType fields do: [ :eachField | 213 | self compileField: eachField ]. 214 | 215 | self compileClearMethod. 216 | self compileInitializeMethod. 217 | self compileReadFromMethod. 218 | self compileWriteTo. 219 | 220 | ] 221 | -------------------------------------------------------------------------------- /Protobuf-Tools/package.st: -------------------------------------------------------------------------------- 1 | Package { #name : #'Protobuf-Tools' } 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # protobuf-smalltalk 2 | [![Build Status](https://travis-ci.org/jvdsandt/protobuf-smalltalk.svg?branch=master)](https://travis-ci.org/jvdsandt/protobuf-smalltalk) 3 | 4 | Protocol buffers support for Smalltalk. [Protocol buffers](https://developers.google.com/protocol-buffers/) 5 | is a language and 6 | platform-neutral serialization protocol created by Google. This projects adds support for 7 | the proto3 version of this protocol to the Smalltalk programming language. 8 | 9 | The library is developed in [Pharo](https://pharo.org/) Smalltalk and uses [PetitParser2](https://github.com/kursjan/petitparser2) 10 | for parsing proto files. 11 | 12 | 13 | ## Installing protobuf-smalltalk 14 | 15 | Pharo: 16 | 17 | ```smalltalk 18 | Metacello new 19 | baseline: 'Protobuf'; 20 | repository: 'github://jvdsandt/protobuf-smalltalk'; 21 | load. 22 | ``` --------------------------------------------------------------------------------