fix(abcip): #611 review round 1 — native keeps BOOL type distinction, WriteWidthRefusal tests, doc caveats
- L2: WriteWidthRefusal leaves a BOOL over a wider value to a runtime that sees the CIP type (native): mistyped integer member -> BadTypeMismatch (as its read), 0xD3 BOOL-array DWORD -> BadNotSupported; libplctag keeps BadNotSupported for both (size only). - L4: direct theory over WriteWidthRefusal (1/2/4/8 widths incl LINT/ULINT/LREAL, String/Dt, unknown size) + array/bit-selector exemptions with a non-vacuous control. - L1: CLAUDE.md member/BIT-member writes are ab_server-proven only. - L3: patch 0003 blind spots documented (Docker README, AbServer-Test-Fixture.md); nits. Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
This commit is contained in:
@@ -1197,7 +1197,7 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
// BOOL-array DWORD wrote all 32 bits. Discovered UDT members are where a mis-authored type
|
||||
// is most likely (browse-commit fills dataType from the template, an operator may retype).
|
||||
size = runtime.GetSize();
|
||||
refusal = WriteWidthRefusal(def, parsedPath?.BitIndex, size);
|
||||
refusal = WriteWidthRefusal(def, parsedPath?.BitIndex, size, runtimeTypesBool: runtime is NativeAbCipTagRuntime);
|
||||
if (refusal is null)
|
||||
{
|
||||
runtime.EncodeValue(def.DataType, parsedPath?.BitIndex, w.Value);
|
||||
@@ -1710,15 +1710,24 @@ public sealed class AbCipDriver : IDriver, IReadable, IWritable, ITagDiscovery,
|
||||
/// would clobber the neighbouring bits, the same refusal the native runtime raises; any other width
|
||||
/// mismatch is <c>BadTypeMismatch</c>. Arrays, bit selectors (<c>Flags.3</c>, served by the
|
||||
/// read-modify-write path) and an unknown size (<c><= 0</c>) are not judged here.
|
||||
/// <para>
|
||||
/// A BOOL over a wider value is left to the runtime when it can see the CIP type
|
||||
/// (<paramref name="runtimeTypesBool"/> — the native transport): it tells a packed BOOL-array DWORD
|
||||
/// (<c>0xD3</c>, <c>BadNotSupported</c>) from a mistyped integer member (<c>BadTypeMismatch</c>, the
|
||||
/// same verdict as its read), and refuses both before sending. libplctag exposes only the size, so the
|
||||
/// two are indistinguishable there and both get the safe <c>BadNotSupported</c>.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="def">The tag being written.</param>
|
||||
/// <param name="bitIndex">The parsed bit selector, if any.</param>
|
||||
/// <param name="size">The runtime's read-buffer size in bytes.</param>
|
||||
/// <param name="runtimeTypesBool">The runtime checks a BOOL write against the controller's CIP type itself.</param>
|
||||
/// <returns>The refusal status, or <c>null</c>.</returns>
|
||||
internal static uint? WriteWidthRefusal(AbCipTagDefinition def, int? bitIndex, int size)
|
||||
internal static uint? WriteWidthRefusal(AbCipTagDefinition def, int? bitIndex, int size, bool runtimeTypesBool = false)
|
||||
{
|
||||
if (IsArrayTag(def) || bitIndex is not null || size <= 0) return null;
|
||||
if (ExpectedScalarWriteWidth(def.DataType) is not { } width || size == width) return null;
|
||||
if (def.DataType == AbCipDataType.Bool && runtimeTypesBool) return null;
|
||||
return def.DataType == AbCipDataType.Bool
|
||||
? AbCipStatusMapper.BadNotSupported
|
||||
: AbCipStatusMapper.BadTypeMismatch;
|
||||
|
||||
Reference in New Issue
Block a user