Hi Florian,

Thanks for your quick response. I'm stuck on this.

1) It's not working. When I send the protobuf to the backend server (it's 
not our api nor server) using the first method, I get a right response. But 
using the second method I receive this error:
ProtoBuf.ProtoException: Invalid wire-type; this usually means you have 
over-written a file without truncating or setting the length; see 
https://stackoverflow.com/q/2152978/23354
   at ProtoBuf.ProtoReader.StartSubItem(ProtoReader reader) in 
C:\code\protobuf-net\src\protobuf-net\ProtoReader.cs:line 637
   at ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key, 
ProtoReader reader, Type type) in 
C:\code\protobuf-net\src\protobuf-net\ProtoReader.cs:line 584
   at proto_40(Object , ProtoReader )
   at ProtoBuf.Meta.TypeModel.DeserializeCore(ProtoReader reader, Type 
type, Object value, Boolean noAutoCreate) in 
C:\code\protobuf-net\src\protobuf-net\Meta\TypeModel.cs:line 722
   at ProtoBuf.Meta.TypeModel.Deserialize(Stream source, Object value, Type 
type, SerializationContext context) in 
C:\code\protobuf-net\src\protobuf-net\Meta\TypeModel.cs:line 599
   at 
WebBeds.Connect.AspNetCore.Formatters.ProtobufInputFormatter.ReadRequestBodyAsync(InputFormatterContext
 
context)
   at 
Microsoft.AspNetCore.Mvc.Formatters.InputFormatter.ReadAsync(InputFormatterContext
 
context)
   at 
Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder.BindModelAsync(ModelBindingContext
 
bindingContext)
   at 
Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext
 
actionContext, IModelBinder modelBinder, IValueProvider valueProvider, 
ParameterDescriptor parameter, ModelMetadata metadata, Object value, Object 
container)
   at 
Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d.MoveNext()
--- End of stack trace from previous location ---
   at 
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker
 
invoker, Task lastTask, State next, Scope scope, Object state, Boolean 
isCompleted)
   at 
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextExceptionFilterAsync>g__Awaited|26_0(ResourceInvoker
 
invoker, Task lastTask, State next, Scope scope, Object state, Boolean 
isCompleted


2) This is the proto:

The request with the 'Meta' element:

message Request {
   Meta Meta = 1;
   repeated int32 Hotels = 2 [packed = false];
   Country Market = 3;
   repeated Room Rooms = 4;
   .bcl.DateTime CheckIn = 5;
   .bcl.DateTime CheckOut = 6;
   OptionalCriteria OptionalCriteria = 7;
}

The 'Meta' element that contains the 'CutOffTime' that we want to modify:

message Meta {
   int32 Client = 1;
   int32 Brand = 2;
   bool UseCache = 3;
   .bcl.TimeSpan CutOffTime = 4;
   bool B2C = 5;
   Language Language = 6;
   Currency Currency = 7;
   bool IncludeProviderAuditData = 8;
   SalesChannel SalesChannel = 9;
   string AgentId = 10;
}

The 'CutOffTime':

message TimeSpan {
  sint64 value = 1; // the size of the timespan (in units of the selected 
scale)
  TimeSpanScale scale = 2; // the scale of the timespan [default = DAYS]
  enum TimeSpanScale {
    DAYS = 0;
    HOURS = 1;
    MINUTES = 2;
    SECONDS = 3;
    MILLISECONDS = 4;
TICKS = 5;

    MINMAX = 15; // dubious
  }
}

Thanks,

Joan.






On Wednesday, September 20, 2023 at 10:40:08 AM UTC+2 Florian Enner wrote:

> 1) A "varint" is a "variable length integer". When you replace a large 
> number with a small one, it's entirely possible to lose some bytes and 
> still be valid. You need to check the actual output.
>
> 2) Can you provide the proto definition of the field you want to modify? 
> Scalar fields get set to the last encountered value, so the easiest option 
> may be to copy the original bytes and append a delta containing the 
> differences.
>  
>
>
>
> On Wednesday, September 20, 2023 at 10:19:07 AM UTC+2 Joan Balagueró wrote:
>
>> Hello,
>>
>> I have a protobuf message like this into a byte array:
>>
>>         1: { // META element
>>             1: 2
>>             2: 1
>>             3: 1
>>             4: {            // CutOffTime element within META
>>                 1: 10
>>                 2: 3
>>                }
>>             5: 1
>>             6: 40
>>         }
>>         2: 9836 // HOTEL element
>>         3: 724 // MARKET element
>>
>>
>> We need to traverse this message and write it to a 'CodeOutputStream', 
>> but changing the values of the 'cutoff' element to, for example to '4: { 1: 
>> 7, 2: 4 }'. I'm not able to do it, I need some help.
>>
>> A basic algorithm that writes the same protobuf to another byte array but 
>> without changing anything works. Here I try the special case of 'META' (key 
>> = 1) that contains the 'cutoff' element.
>>
>> Map<Integer, UnknownFieldSet.Field> rootFields = 
>> UnknownFieldSet.parseFrom(document).asMap();
>>
>>             for (Map.Entry<Integer, UnknownFieldSet.Field> entry : 
>> rootFields.entrySet()) {
>>                 if (entry.getKey() == 1) {
>>                     ByteString bs = 
>> entry.getValue().getLengthDelimitedList().get(0);
>>                     output.writeByteArray(1, bs.toByteArray());
>>                 }
>>                 else {
>>                     entry.getValue().writeTo(entry.getKey(), output);
>>                 }
>>             }
>>
>>
>> Now I try to go a bit further, trying to read the cuotff element, change 
>> the values and rewrite them to the 'output'. And here is when I'm not able 
>> to solve the problem. Below my try that does not work, it generates a byte 
>> array
>> of 69 bytes instead of 73 (I'm losing 4 bytes):
>>
>> Map<Integer, UnknownFieldSet.Field> rootFields = 
>> UnknownFieldSet.parseFrom(document).asMap();
>>             
>> for (Map.Entry<Integer, UnknownFieldSet.Field> entry : 
>> rootFields.entrySet()) {
>>                 if (entry.getKey() == 1) {
>>                     ByteString bs = 
>> entry.getValue().getLengthDelimitedList().get(0);
>>                     Map<Integer, UnknownFieldSet.Field> ufs = 
>> UnknownFieldSet.parseFrom(bs).asMap();
>>
>>                     for (Map.Entry<Integer, UnknownFieldSet.Field> item : 
>> ufs.entrySet()) {
>>                         if (item.getKey() == 4) {
>>                             Map<Integer, UnknownFieldSet.Field> cutoff = 
>> UnknownFieldSet.parseFrom(item.getValue().getLengthDelimitedList().get(0)).asMap();
>>                             cutoff.put(1, 
>> UnknownFieldSet.Field.newBuilder().addVarint(7).build()).writeTo(1, output);
>>                             cutoff.put(2, 
>> UnknownFieldSet.Field.newBuilder().addVarint(4).build()).writeTo(1, output);
>>                         }
>>                         else {
>>                             item.getValue().writeTo(item.getKey(), 
>> output);
>>                         }
>>                     }
>>                 }
>>                 else {
>>                     entry.getValue().writeTo(entry.getKey(), output);
>>                 }
>>             }
>>
>> Any help would be really appreciated.
>>
>> Thanks,
>>
>> Joan.
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Protocol Buffers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/protobuf/f72c72ea-47ed-40ee-92b2-42de999b7057n%40googlegroups.com.

Reply via email to