<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <div class="moz-cite-prefix">Am 05.07.2019 um 08:08 schrieb Sven
      Barth:<br>
    </div>
    <blockquote type="cite"
cite="mid:CAFMUeB_Nq5Y5CmswK2qDBFH_VdqszZiBkoDMDS+GAydxxtrozg@mail.gmail.com">
      <meta http-equiv="content-type" content="text/html; charset=UTF-8">
      <div dir="auto">
        <div>
          <div class="gmail_quote">
            <div dir="ltr" class="gmail_attr">Jonas Maebe <<a
                href="mailto:jonas@freepascal.org"
                moz-do-not-send="true">jonas@freepascal.org</a>>
              schrieb am Do., 4. Juli 2019, 21:21:<br>
            </div>
            <blockquote class="gmail_quote" style="margin:0 0 0
              .8ex;border-left:1px #ccc solid;padding-left:1ex">On
              03/07/2019 09:26, Ondrej Pokorny wrote:<br>
              > On 02.07.2019 23:34, Jonas Maebe wrote:<br>
              >> Invalid data means undefined behaviour, always.
              "is" is not a special<br>
              >> case that is immune to this.<br>
              > <br>
              > Don't you really see the need to handle invalid data
              with a /defined/<br>
              > behavior?<br>
              <br>
              My point is that is impossible to do so, so trying to do
              it in a way<br>
              that works in some/most cases, is much more dangerous than
              categorically<br>
              refusing to try to do it, as it creates a false sense of
              security.<br>
            </blockquote>
          </div>
        </div>
        <div dir="auto"><br>
        </div>
        <div dir="auto">Then how would you read data from e.g. a stream
          into an enum or subrange if the stream may contain invalid
          data? <br>
        </div>
      </div>
    </blockquote>
    I now did a proof of concept for that task myself:<br>
    <br>
    === code begin ===<br>
    <br>
    program tptrhlp;<br>
    <br>
    {$mode objfpc}<br>
    {$modeswitch typehelpers}<br>
    <br>
    uses<br>
      Classes, SysUtils;<br>
    <br>
    type<br>
      TStreamHelper = type helper for TStream<br>
      public<br>
        generic function ReadEnum<T>(out aEnum: T): Boolean;<br>
      end;<br>
    <br>
    generic function TStreamHelper.ReadEnum<T>(out aEnum: T):
    Boolean;<br>
    var<br>
      buf: array[0..SizeOf(T) - 1] of Byte absolute aEnum;<br>
      tmp: LongInt;<br>
    begin<br>
      if Read(buf[0], SizeOf(buf)) <> SizeOf(buf) then<br>
        Exit(False)<br>
      else begin<br>
        case SizeOf(T) of<br>
          1:<br>
            tmp := PByte(@buf[0])^;<br>
          2:<br>
            tmp := PWord(@buf[0])^;<br>
          3:<br>
            tmp := LongWord(PWord(@buf[0])^) or
    (LongInt(PByte(@buf[2])^) shl 16);<br>
          4:<br>
            tmp := PLongWord(@buf[0])^;<br>
        end;<br>
        Result := (tmp >= Ord(Low(T))) and (tmp <= Ord(High(T)));<br>
      end;<br>
    end;<br>
    <br>
    type<br>
      {$PACKENUM 1}<br>
      TMyEnum = (<br>
        meOne,<br>
        meTwo,<br>
        meThree<br>
      );<br>
    var<br>
      s: TMemoryStream;<br>
      e: TMyEnum;<br>
      b: Byte;<br>
    begin<br>
      s := TMemoryStream.Create;<br>
      try<br>
        try<br>
          Writeln(SizeOf(TMyEnum));<br>
          b := 1;<br>
          s.Write(b, SizeOf(b));<br>
          b := 3;<br>
          s.Write(b, SizeOf(b));<br>
          s.Position := 0;<br>
          if not s.specialize ReadEnum<TMyEnum>(e) then<br>
            raise EStreamError.Create('Failed to read enum value');<br>
          Writeln('Read value: ', e);<br>
          if not s.specialize ReadEnum<TMyEnum>(e) then<br>
            raise EstreamError.CReate('Failed to read enum value');<br>
        except<br>
          on e: Exception do<br>
            Writeln(e.ClassName, ': ', e.Message);<br>
        end;<br>
      finally<br>
        s.Free;<br>
      end;<br>
    end. <br>
    <br>
    === code end ===<br>
    <br>
    Note 1: Needs today's trunk cause I fixed generic methods in helpers
    in mode ObjFPC<br>
    Note 2: Similar code can also be done for ranges (though there the
    sizes 5 to 8 need to be handled as well)<br>
    Note 3: I didn't test whether this works correctly on Big Endian
    systems<br>
    Note 4: The compiler will optimize away the unneeded case branches
    :)<br>
    <br>
    Regards,<br>
    Sven<br>
  </body>
</html>