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

SwitchEndianness causes unexpected side effect. #122

Open
iamalexcater opened this issue Jul 18, 2024 · 4 comments
Open

SwitchEndianness causes unexpected side effect. #122

iamalexcater opened this issue Jul 18, 2024 · 4 comments
Labels

Comments

@iamalexcater
Copy link

The generic array argument values have their endianness reversed when calling WriteMultipleRegistersAsync or ReadWriteMultipleRegistersAsync<TRead, TWrite> when SwapBytes is true. This is arguably undesirable with reference to the Principle Of Least Astonishment.

@Apollo3zehn
Copy link
Owner

Apollo3zehn commented Jul 22, 2024

Thanks for your input! Endianness handling in this library has caused much confusion and it needs a total redesign. Maybe something like ReadHoldingRegisters(...).Slice(2, 8).Cast<long>().SwitchEndianness();

Related issues:
#45
#52
#86
#88

I have very limited time for this project but I see the rising need for a better API and hope to find some time for it soon.

@Apollo3zehn Apollo3zehn added the v6 label Jul 22, 2024
@schotime
Copy link
Contributor

schotime commented Aug 7, 2024

I actually always now connect with the default endianness and then use the api that returns the Memory and perform the following. Definitely agree on a refactor of the endianness.

  public static byte[] ReorderBytes(this byte[] bytes, ModbusEndianness modbusEndianness)
  {
      if (modbusEndianness == ModbusEndianness.Mid)
      {
          for (int i = 0; i < bytes.Length; i += 2)
          {
              (bytes[i], bytes[i + 1]) = (bytes[i + 1], bytes[i]);
          }
      }
      else if (modbusEndianness == ModbusEndianness.Big)
      {
          Array.Reverse(bytes);
      }

      return bytes;
  }

@iamalexcater
Copy link
Author

iamalexcater commented Aug 7, 2024

Agreed, I can see that it has become a confusing topic for many people; the API needs some thought in this regard.

The issue I originally attempted to highlight is the fact that if I call WriteMultipleRegistersAsync (and SwapBytes is true) then the T[] 'dataset' argument is modified via the call to ModbusUtils.SwitchEndianness, which might result in the caller observing this mutation. This is undesirable IMO.

I have since discovered that issue #52 describes the very same problem. @Apollo3zehn responded explaining that this was likely related to usage of ArrayPool, but this is not correct; the array that is owned by the client is directly mutated.

The dataset argument should not be modified and IMO ought to be a ReadOnlyMemory<T>

@Apollo3zehn
Copy link
Owner

Thansks for your input, I will collect everything and come up with a new API design in the coming weeks (and ask for your kind feedback again :-))

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

No branches or pull requests

3 participants