לדלג לתוכן

פתרון layout ויחידות אורך

הקוד הבא מאמת layout שנבחר עבור מבנה עם Flags בן byte אחד. תחת ה־ABI הרגיל של היעד total מתיישר ל־offset של 16 וגודל המבנה הוא 24. אם הצד הטבעי נבנה עם packing אחר, הבדיקה צריכה להיכשל במקום לשנות את ההצהרה בשקט.

using System.Runtime.InteropServices;
using System.Text;

if (Marshal.SizeOf<ResultV2>() != 24 ||
    Marshal.OffsetOf<ResultV2>(nameof(ResultV2.Total)).ToInt64() != 16)
    throw new InvalidOperationException("layout mismatch");
string text = "א🙂";
var utf8 = new UTF8Encoding(false, true);
Console.WriteLine($"UTF16 units={text.Length}, UTF8 bytes={utf8.GetByteCount(text)}");
try { _ = utf8.GetBytes("\uD800"); }
catch (EncoderFallbackException) { Console.WriteLine("invalid surrogate"); }

[StructLayout(LayoutKind.Sequential)]
struct ResultV2
{
    public uint Size;
    public int Ok;
    public byte Flags;
    public ulong Total;
}

ה־wrapper הדו־שלבי יבדוק required מול התקרה לפני ההקצאה, ויבצע לכל היותר מספר ניסיונות ידוע, למשל שלושה. בכל ניסיון הוא יעביר את הקיבולת האמיתית של המערך ויקבל status שמבדיל הצלחה, buffer-too-small וכשל אחר. בהצלחה הוא יפענח רק את מספר ה־byte-ים שנכתבו, לפי חוזה שמגדיר אם האפס המסיים נספר. אין להפעיל GetString על כל המערך המוקצה אם רק prefix מולא.

המחרוזת בדוגמה מכילה שלוש יחידות UTF-16 ושישה byte-ים ב־UTF-8. תו אפס פנימי מקודד ל־byte אפס ואינו סוף אוטומטי של string מנוהל, אבל עלול לסיים מחרוזת ב־API טבעי שמבוסס על אפס. הבדיקה עם UTF8Encoding מחמיר דוחה surrogate לא תקין במקום להפיק replacement character ולשנות בשקט את הנתון.