Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Primitive one-of type always passes nil as its argument for decoder #1608

Closed
pouyayarandi opened this issue Apr 3, 2024 · 8 comments
Closed
Labels

Comments

@pouyayarandi
Copy link
Contributor

When I implement a decoder for decoding a one-of type, if its associated value of one-of is primitive (string, double, etc) it always pass nil for decoder method that I've implemented as Decoder protocol requirement.

Please be sure to include:

  • OS: macOS 14.0

  • Xcode version: 15.3

  • Swift version: 5.10

  • Branch: main

  • .proto snippet:

oneof o {
  int32 oneof_int32 = 61;
  int64 oneof_int64 = 62;
}
@pouyayarandi
Copy link
Contributor Author

For more details, I also found an issue in generated code for one-of fields. First for a better vision, when a non one-of field is getting decoded it passes its current value to the decoder as an inout parameter. Like this:

case 11: try { try decoder.decodeSingularFloatField(value: &_storage._singularFloat) }()

But in one of fields it happens completely different. It's a sample of code that generated for decoding a one-of field:

case 71: try {
  var v: Float?
  try decoder.decodeSingularFloatField(value: &v)
  if let v = v {
    if _storage._o != nil {try decoder.handleConflictingOneOf()}
    _storage._o = .oneofFloat(v)
  }
}()

In the above code the inout parameter that is passing to decode method is always nil (v variable is never set before passing to decoder method). My suggestion would be to add a line of code setting the current value to variable if it's possible:

case 71: try {
  var v: Float?
  if case .oneofFloat(let _v)? = _storage._o {v = _v}    // add this line
  try decoder.decodeSingularFloatField(value: &v)
  if let v = v {
    if _storage._o != nil {try decoder.handleConflictingOneOf()}
    _storage._o = .oneofFloat(v)
  }
}()

@thomasvl
Copy link
Collaborator

thomasvl commented Apr 3, 2024

We should probably look at some of the upstream binary tests to see if they have some good example of merging tests that we should bring over, would help make sure we catch these types of issues.

@thomasvl
Copy link
Collaborator

thomasvl commented Apr 3, 2024

We'll need to give this some more thought, but for primitive fields, the fact that we pass nil might not matter, yes it could be a single to the decoder the value was set, but for we also have the handleConflictingOneOf callback for that. The pace we really need to pass it is where merge would be adding instead of replacing, so sub message, maps?, and probably repeated fields. So it might make sense to only do the fetch in those cases to keep the code sizes down.

@thomasvl thomasvl added the bug label Apr 3, 2024
@pouyayarandi
Copy link
Contributor Author

pouyayarandi commented Apr 3, 2024

I'm not sure we are on the same page, but let me explain a scenario for it:

Let's say we have a message (m1) with oneof field and we try to merge it with another message (m2) with the same type. The oneof type has two possible cases oneof_int32(int32) and oneof_int64(int64). If we merge m1 with m2 by a field mask of both oneof_int32 and oneof_int64 paths, we expect that m1 oneof field should be same as m2. But currently, since merge decoder can't get value of oneof paths, it becomes nil.

@thomasvl
Copy link
Collaborator

thomasvl commented Apr 3, 2024

Ah, that's potentially a different problem then I was thinking of, I was thinking purely about the nested messages within the oneof, and if the same oneof field is set, a merge wouldn't combine the submessage like it would for a non oneof field. Yea, I guess for collection of the field being set, we might need to always provide the value.

Anyway, all the more reason for the addition of merging related tests not just specific to the field mask cases.

@pouyayarandi
Copy link
Contributor Author

pouyayarandi commented Apr 13, 2024

I guess reproducing and fixing of this bug would be easier in case #1505 get merged first

@thomasvl
Copy link
Collaborator

Generally, fixing this seems worthwhile independent of that PR. Just need someone to code up some test cases and the fixes.

@pouyayarandi
Copy link
Contributor Author

pouyayarandi commented May 3, 2024

I close this issue as I commented in #1632 my problem fixed without any additional code generation.

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants