From 080327650cdf39bd0b19165178f61835dab7a61f Mon Sep 17 00:00:00 2001 From: Pouya Yarandi <30620887+pouyayarandi@users.noreply.github.com> Date: Sat, 17 Aug 2024 14:25:43 +0330 Subject: [PATCH 1/5] add documentation --- Documentation/API.md | 73 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/Documentation/API.md b/Documentation/API.md index e98e7f80b..ff02eb81e 100644 --- a/Documentation/API.md +++ b/Documentation/API.md @@ -615,6 +615,16 @@ public func -(lhs: Google_Protobuf_Timestamp, rhs: Google_Protobuf_Duration) -> public func +(lhs: Google_Protobuf_Timestamp, rhs: Google_Protobuf_Duration) -> Google_Protobuf_Timestamp ``` +## Google_Protobuf_FieldMask + +The `Google_Protobuf_FieldMask` contains a list of field paths, where each path is a string that identifies a particular field or nested field in the message. This is particularly useful for selectively updating or trimming messages. + +```protobuf +message FieldMask { + // The set of field mask paths. + repeated string paths = 1; +} +``` ## Extensions @@ -696,6 +706,69 @@ Descriptor objects. It is something that could get revisited in the future, but will need careful consideration; the bloat/size issues is of the most concern because of Swift's common use for mobile applications. +## FieldMask Utilities + +### Merging Two Messages + +The `merge(from:fieldMask:)` function in Swift Protobuf enables developers to selectively merge fields from one message into another, guided by a `Google_Protobuf_FieldMask`. This method is particularly useful when you need to update only specific fields in a message without affecting others. The `merge` function is available as a method on `Message` types and requires two parameters: the source message (`from`) containing the data to merge and the `fieldMask` that specifies which fields should be updated. + +For example, consider a message with the following structure: + +```protobuf +message ExampleMessage { + string foo = 1; + string bar = 2; +} +``` + +Assume we have two instances of `ExampleMessage`: + +```swift +let message1: ExampleMessage = .with { $0.foo = "foo1" } +let message2: ExampleMessage = .with { $0.bar = "bar2" } +``` + +To merge `message2` into `message1` but only update the `bar` field, you can define a `Google_Protobuf_FieldMask` like this: + +```swift +let fieldMask = Google_Protobuf_FieldMask.with { $0.paths = ["bar"] } +``` + +Then, you apply the merge: + +```swift +try message1.merge(from: message2, fieldMask: fieldMask) +``` + +After this operation, `message1.bar` will have the value `"bar2"` from `message2`, while `message1.foo` remains `"foo1"`. The `merge` function operates in-place, meaning it directly modifies `message1`. This targeted approach is beneficial when handling partial updates, as it prevents unintended changes to other fields. Proper configuration of the `fieldMask` is essential to ensure that only the desired fields are updated. Additionally, since the `merge` function may throw errors if the operation fails, it's important to handle these exceptions appropriately. This API is a powerful tool for managing partial updates in protocol buffer messages, providing developers with precise control over the merging process. + +### Trimming a Message + +The `trim(keeping:)` function allows developers to retain only specific fields in a protocol buffer message while clearing the rest. This function is particularly useful when you want to ensure that only certain fields are preserved in a message, effectively "trimming" the message to contain just the necessary data. + +Consider the `ExampleMessage` structure from the previous example. Suppose you have an instance of `ExampleMessage` initialized as follows: + +```swift +let message = ExampleMessage.with { + $0.foo = "foo" + $0.bar = "bar" +} +``` + +If you want to trim this message so that only the `bar` field retains its value, you can define a `Google_Protobuf_FieldMask` like this: + +```swift +let fieldMask = Google_Protobuf_FieldMask.with { $0.paths = ["bar"] } +``` + +Then, you apply the `trim` function: + +```swift +message.trim(keeping: fieldMask) +``` + +After this operation, the `bar` field in `message` will still have the value `"bar"`, while the `foo` field will be cleared, resetting to its default value (an empty string, in this case). The `trim(keeping:)` function is performed in-place, meaning it directly modifies the original message. This function is ideal for scenarios where it's necessary to remove all but a few specified fields, ensuring that the resulting message contains only the data you want to keep. This precise control over the message structure can be essential when working with large or complex messages, where only a subset of the data is relevant for a particular operation or transmission. The `trim` function enhances the flexibility of message management in Swift Protobuf, making it easier to handle scenarios where selective field retention is required. + ## Aside: proto2 vs. proto3 The terms *proto2* and *proto3* refer to two different dialects of the proto From e18338e5ceeee3748072fdb31bba27c7ed79ab32 Mon Sep 17 00:00:00 2001 From: Pouya Yarandi <30620887+pouyayarandi@users.noreply.github.com> Date: Sat, 17 Aug 2024 16:05:29 +0330 Subject: [PATCH 2/5] Update API.md --- Documentation/API.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/API.md b/Documentation/API.md index ff02eb81e..8c156a082 100644 --- a/Documentation/API.md +++ b/Documentation/API.md @@ -615,7 +615,7 @@ public func -(lhs: Google_Protobuf_Timestamp, rhs: Google_Protobuf_Duration) -> public func +(lhs: Google_Protobuf_Timestamp, rhs: Google_Protobuf_Duration) -> Google_Protobuf_Timestamp ``` -## Google_Protobuf_FieldMask +### Google_Protobuf_FieldMask The `Google_Protobuf_FieldMask` contains a list of field paths, where each path is a string that identifies a particular field or nested field in the message. This is particularly useful for selectively updating or trimming messages. From 3006aa96d9f3fd10218e0bc5830efdb72c1aa63b Mon Sep 17 00:00:00 2001 From: Pouya Yarandi <30620887+pouyayarandi@users.noreply.github.com> Date: Sat, 17 Aug 2024 16:22:14 +0330 Subject: [PATCH 3/5] Add fieldmask example --- Documentation/API.md | 81 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 70 insertions(+), 11 deletions(-) diff --git a/Documentation/API.md b/Documentation/API.md index 8c156a082..06d63e168 100644 --- a/Documentation/API.md +++ b/Documentation/API.md @@ -617,15 +617,41 @@ public func +(lhs: Google_Protobuf_Timestamp, rhs: Google_Protobuf_Duration) -> ### Google_Protobuf_FieldMask -The `Google_Protobuf_FieldMask` contains a list of field paths, where each path is a string that identifies a particular field or nested field in the message. This is particularly useful for selectively updating or trimming messages. +`Google_Protobuf_FieldMask` is used to specify which fields in +a protocol buffer message should be included in operations such as updates or merges. +It allows precise control over which parts of the message +are affected by defining a list of field paths. + +For example, consider a protocol buffer message with nested fields: ```protobuf -message FieldMask { - // The set of field mask paths. - repeated string paths = 1; +message ParentMessage { + string name = 1; + ChildMessage child = 2; + + message ChildMessage { + string childName = 1; + int32 age = 2; + } } ``` +If you want to update only the `name` field of `ParentMessage` +and the `childName` field within `ChildMessage`, +you would define a `FieldMask` as follows: + +```swift +let fieldMask = Google_Protobuf_FieldMask.with { + $0.paths = ["name", "child.childName"] +} +``` + +In this example, the `paths` list includes `"name"` to target +the `name` field in `ParentMessage` and `"child.childName"` +to target the `childName` field inside the nested `ChildMessage`. +This setup allows you to perform operations that affect +only these specified fields while leaving others unchanged. + ## Extensions Extensions are used to add additional properties to messages defined elsewhere. @@ -710,7 +736,13 @@ concern because of Swift's common use for mobile applications. ### Merging Two Messages -The `merge(from:fieldMask:)` function in Swift Protobuf enables developers to selectively merge fields from one message into another, guided by a `Google_Protobuf_FieldMask`. This method is particularly useful when you need to update only specific fields in a message without affecting others. The `merge` function is available as a method on `Message` types and requires two parameters: the source message (`from`) containing the data to merge and the `fieldMask` that specifies which fields should be updated. +The `merge(from:fieldMask:)` function in Swift Protobuf enables developers +to selectively merge fields from one message into another, guided by a `Google_Protobuf_FieldMask`. +This method is particularly useful when you need to update only specific +fields in a message without affecting others. +The `merge` function is available as a method on `Message` types and requires two parameters: +the source message (`from`) containing the data to merge +and the `fieldMask` that specifies which fields should be updated. For example, consider a message with the following structure: @@ -728,7 +760,8 @@ let message1: ExampleMessage = .with { $0.foo = "foo1" } let message2: ExampleMessage = .with { $0.bar = "bar2" } ``` -To merge `message2` into `message1` but only update the `bar` field, you can define a `Google_Protobuf_FieldMask` like this: +To merge `message2` into `message1` but only update the `bar` field, +you can define a `Google_Protobuf_FieldMask` like this: ```swift let fieldMask = Google_Protobuf_FieldMask.with { $0.paths = ["bar"] } @@ -740,13 +773,28 @@ Then, you apply the merge: try message1.merge(from: message2, fieldMask: fieldMask) ``` -After this operation, `message1.bar` will have the value `"bar2"` from `message2`, while `message1.foo` remains `"foo1"`. The `merge` function operates in-place, meaning it directly modifies `message1`. This targeted approach is beneficial when handling partial updates, as it prevents unintended changes to other fields. Proper configuration of the `fieldMask` is essential to ensure that only the desired fields are updated. Additionally, since the `merge` function may throw errors if the operation fails, it's important to handle these exceptions appropriately. This API is a powerful tool for managing partial updates in protocol buffer messages, providing developers with precise control over the merging process. +After this operation, `message1.bar` will have the value `"bar2"` from `message2`, +while `message1.foo` remains `"foo1"`. The `merge` function operates in-place, +meaning it directly modifies `message1`. +This targeted approach is beneficial when handling partial updates, +as it prevents unintended changes to other fields. +Proper configuration of the `fieldMask` is essential to ensure that only the desired +fields are updated. +Additionally, since the `merge` function may throw errors if the operation fails, +it's important to handle these exceptions appropriately. +This API is a powerful tool for managing partial updates in protocol buffer messages, +providing developers with precise control over the merging process. ### Trimming a Message -The `trim(keeping:)` function allows developers to retain only specific fields in a protocol buffer message while clearing the rest. This function is particularly useful when you want to ensure that only certain fields are preserved in a message, effectively "trimming" the message to contain just the necessary data. +The `trim(keeping:)` function allows developers to retain only specific +fields in a protocol buffer message while clearing the rest. +This function is particularly useful when you want to ensure that only certain +fields are preserved in a message, effectively "trimming" the message +to contain just the necessary data. -Consider the `ExampleMessage` structure from the previous example. Suppose you have an instance of `ExampleMessage` initialized as follows: +Consider the `ExampleMessage` structure from the previous example. +Suppose you have an instance of `ExampleMessage` initialized as follows: ```swift let message = ExampleMessage.with { @@ -755,7 +803,8 @@ let message = ExampleMessage.with { } ``` -If you want to trim this message so that only the `bar` field retains its value, you can define a `Google_Protobuf_FieldMask` like this: +If you want to trim this message so that only the `bar` field retains its value, +you can define a `Google_Protobuf_FieldMask` like this: ```swift let fieldMask = Google_Protobuf_FieldMask.with { $0.paths = ["bar"] } @@ -767,7 +816,17 @@ Then, you apply the `trim` function: message.trim(keeping: fieldMask) ``` -After this operation, the `bar` field in `message` will still have the value `"bar"`, while the `foo` field will be cleared, resetting to its default value (an empty string, in this case). The `trim(keeping:)` function is performed in-place, meaning it directly modifies the original message. This function is ideal for scenarios where it's necessary to remove all but a few specified fields, ensuring that the resulting message contains only the data you want to keep. This precise control over the message structure can be essential when working with large or complex messages, where only a subset of the data is relevant for a particular operation or transmission. The `trim` function enhances the flexibility of message management in Swift Protobuf, making it easier to handle scenarios where selective field retention is required. +After this operation, the `bar` field in `message` will still have the value `"bar"`, +while the `foo` field will be cleared, resetting to its default value (an empty string, +in this case). The `trim(keeping:)` function is performed in-place, meaning it directly +modifies the original message. +This function is ideal for scenarios where it's necessary to remove all but a few +specified fields, ensuring that the resulting message contains only the data you want to keep. +This precise control over the message structure can be essential when working with +large or complex messages, where only a subset of the data is relevant for a +particular operation or transmission. The `trim` function enhances the flexibility +of message management in Swift Protobuf, making it easier to handle scenarios +where selective field retention is required. ## Aside: proto2 vs. proto3 From 816d598b255d30deec3c4d7950f828d5b27f778b Mon Sep 17 00:00:00 2001 From: Pouya Yarandi <30620887+pouyayarandi@users.noreply.github.com> Date: Fri, 23 Aug 2024 20:58:40 +0330 Subject: [PATCH 4/5] fix comments --- Documentation/API.md | 70 +++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/Documentation/API.md b/Documentation/API.md index 06d63e168..bcc099c73 100644 --- a/Documentation/API.md +++ b/Documentation/API.md @@ -638,7 +638,7 @@ message ParentMessage { If you want to update only the `name` field of `ParentMessage` and the `childName` field within `ChildMessage`, -you would define a `FieldMask` as follows: +you would use a `FieldMask` as follows: ```swift let fieldMask = Google_Protobuf_FieldMask.with { @@ -748,50 +748,61 @@ For example, consider a message with the following structure: ```protobuf message ExampleMessage { + + message NestedMessage { + string baz = 1; + string qux = 2; + } + string foo = 1; string bar = 2; + NestedMessage nested = 3; } ``` Assume we have two instances of `ExampleMessage`: ```swift -let message1: ExampleMessage = .with { $0.foo = "foo1" } -let message2: ExampleMessage = .with { $0.bar = "bar2" } -``` - -To merge `message2` into `message1` but only update the `bar` field, -you can define a `Google_Protobuf_FieldMask` like this: +let message1: ExampleMessage = .with { + $0.foo = "foo1" + $0.nested = .with { + $0.baz = "baz1" + } +} -```swift -let fieldMask = Google_Protobuf_FieldMask.with { $0.paths = ["bar"] } +let message2: ExampleMessage = .with { + $0.foo = "foo2" + $0.bar = "bar2" + $0.nested = .with { + $0.baz = "baz2" + $0.qux = "qux2" + } +} ``` -Then, you apply the merge: +To merge `message2` into `message1` but only update the `bar` field +and `qux` field of `nested`, you can use a `Google_Protobuf_FieldMask` +like this: ```swift +let fieldMask = Google_Protobuf_FieldMask.with { + $0.paths = ["bar", "nested.qux"] +} try message1.merge(from: message2, fieldMask: fieldMask) ``` After this operation, `message1.bar` will have the value `"bar2"` from `message2`, -while `message1.foo` remains `"foo1"`. The `merge` function operates in-place, -meaning it directly modifies `message1`. -This targeted approach is beneficial when handling partial updates, -as it prevents unintended changes to other fields. -Proper configuration of the `fieldMask` is essential to ensure that only the desired -fields are updated. -Additionally, since the `merge` function may throw errors if the operation fails, -it's important to handle these exceptions appropriately. -This API is a powerful tool for managing partial updates in protocol buffer messages, -providing developers with precise control over the merging process. +and `message1.nested.qux` will have the value `"qux2"` from `message2`, +while `message1.foo` and `message1.nested.baz` remain `"foo1"` and `"baz1"`. +Be aware that including `"nested"` in the FieldMask paths will cause all fields +within `message1.nested` to be updated from `message2` (including `baz` and `qux`), +whereas adding `"nested.qux"` only affects the `qux` field in the `nested` message. +The `merge` function operates in-place, meaning it directly modifies `message1`. ### Trimming a Message The `trim(keeping:)` function allows developers to retain only specific -fields in a protocol buffer message while clearing the rest. -This function is particularly useful when you want to ensure that only certain -fields are preserved in a message, effectively "trimming" the message -to contain just the necessary data. +fields in a protocol buffer message while clearing the rest. Consider the `ExampleMessage` structure from the previous example. Suppose you have an instance of `ExampleMessage` initialized as follows: @@ -804,7 +815,7 @@ let message = ExampleMessage.with { ``` If you want to trim this message so that only the `bar` field retains its value, -you can define a `Google_Protobuf_FieldMask` like this: +you can use a `Google_Protobuf_FieldMask` like this: ```swift let fieldMask = Google_Protobuf_FieldMask.with { $0.paths = ["bar"] } @@ -819,14 +830,7 @@ message.trim(keeping: fieldMask) After this operation, the `bar` field in `message` will still have the value `"bar"`, while the `foo` field will be cleared, resetting to its default value (an empty string, in this case). The `trim(keeping:)` function is performed in-place, meaning it directly -modifies the original message. -This function is ideal for scenarios where it's necessary to remove all but a few -specified fields, ensuring that the resulting message contains only the data you want to keep. -This precise control over the message structure can be essential when working with -large or complex messages, where only a subset of the data is relevant for a -particular operation or transmission. The `trim` function enhances the flexibility -of message management in Swift Protobuf, making it easier to handle scenarios -where selective field retention is required. +modifies the original message. ## Aside: proto2 vs. proto3 From 5a2daa5cb5db6566c828790ac95a41a084a5ced9 Mon Sep 17 00:00:00 2001 From: Pouya Yarandi <30620887+pouyayarandi@users.noreply.github.com> Date: Fri, 23 Aug 2024 21:08:44 +0330 Subject: [PATCH 5/5] remove `allow developers to ...` in sentences --- Documentation/API.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/API.md b/Documentation/API.md index bcc099c73..5b4d01a56 100644 --- a/Documentation/API.md +++ b/Documentation/API.md @@ -736,8 +736,8 @@ concern because of Swift's common use for mobile applications. ### Merging Two Messages -The `merge(from:fieldMask:)` function in Swift Protobuf enables developers -to selectively merge fields from one message into another, guided by a `Google_Protobuf_FieldMask`. +The `merge(from:fieldMask:)` function in Swift Protobuf selectively merges +fields from one message into another, guided by a `Google_Protobuf_FieldMask`. This method is particularly useful when you need to update only specific fields in a message without affecting others. The `merge` function is available as a method on `Message` types and requires two parameters: @@ -801,7 +801,7 @@ The `merge` function operates in-place, meaning it directly modifies `message1`. ### Trimming a Message -The `trim(keeping:)` function allows developers to retain only specific +The `trim(keeping:)` function retains only specific fields in a protocol buffer message while clearing the rest. Consider the `ExampleMessage` structure from the previous example.