using System.Buffers.Binary;
using System.Collections;
namespace ZB.MOM.WW.OtOpcUa.Driver.AbCip;
///
/// Encodes a whole-array write (review 07 U10): count elements at the element type's wire width,
/// little-endian, exactly the layout a Logix atomic array holds and the read path decodes. Shared by both
/// runtimes so the bytes on the wire are transport-independent.
///
///
/// Element values CONVERT, they are not exact-matched. ScadaBridge (and any OPC UA client that
/// round-trips what it read) writes CLR lists such as int[] to an INT array — the read path itself
/// publishes INT/SINT elements as int — so each element goes through the same the
/// scalar path uses. A value that does not fit is an (BadOutOfRange) and one that
/// cannot convert a / (BadTypeMismatch), all
/// thrown before any byte is sent.
/// BOOL arrays (bit-packed DWORDs — a byte-per-element encode would clobber neighbour bits), STRING arrays
/// (structures) and structure arrays are not encodable here; the driver refuses them BadNotSupported
/// before a runtime exists.
///
internal static class AbCipArrayCodec
{
/// Wire width of one element of an encodable array type, or null when the type is not encodable.
/// The element type.
/// The element width in bytes, or null.
public static int? ElementWidth(AbCipDataType type) => type switch
{
AbCipDataType.SInt or AbCipDataType.USInt => 1,
AbCipDataType.Int or AbCipDataType.UInt => 2,
AbCipDataType.DInt or AbCipDataType.UDInt or AbCipDataType.Real or AbCipDataType.Dt => 4,
AbCipDataType.LInt or AbCipDataType.ULInt or AbCipDataType.LReal => 8,
_ => null,
};
///
/// The elements of an array write value, or null when the value is not a list (a scalar, a string, null).
/// Any non-string is accepted — int[], short[], List<object> …
///
/// The client's write value.
/// The elements, or null.
public static object?[]? Elements(object? value) => value switch
{
null or string => null,
IEnumerable list => [.. list.Cast