I'm a C programmer and started learning Ada a few weeks ago. I have been puzzled by how Ada handles foreign binary data, such as when decoding a communications packet stored in a serial input buffer.
In C, I would define a packed structure to reflect the layout of the packet, and then cast the pointer-to-buffer to pointer-to-structure to access the individual elements in the communications data. What is the typical way to do such decoding in Ada?
I have tried to replicate the same method for C in Ada with the following
-- Fundamental types for fields in the packet
type Station_Addr_Type is mod 2**8;
type Func_Code_Type is (FUNC1, FUNC2);
for Func_Code_Type use
(
FUNC1 => 1,
FUNC2 => 2
);
type Packet is
record
Station_Addr : Station_Addr_Type;
Func_Code : Func_Code_Type;
end record;
-- attempts to reflect packet binary layout
for Packet use
record at mod 1;
Station_Addr at 0 range 0 .. 7;
Func_Code at 1 range 0 .. 7;
end record;
I then defined the array for the communications receive buffer that accepts foreign binary data (possibly from a different architecture):
type Communication_Data is mod 2**8;
for Communication_Data'Size use 8;
type Communication_Buffer is array (Natural range <>) of Communication_Data;
Buffer : Communication_Buffer (0 .. 20);
Then a procedure that decodes such communications
procedure Decode_Packet (Packet_Provided : in Packet);
-- non-working sample
declare
begin
-- Attempts to sanity-check packet by object casting
Decode_Packet (Packet (Buffer));
---------------^----
Error: invalid conversion, not compatible with type "Communication_Buffer"
exception
when others =>
raise Decode_Failure;
end;
However, the compiler forbids such casting with error as shown. Thanks for reading this far. My question is,
Regarding the correct way of decoding foreign binary data, am I "in the ball park", or is there a better way of doing this?
Buffer : Communication_Buffer (0 .. 20);
Pkg : Packet;
pragma Import (Ada, Pkg);
for Pkg'Address use Buffer (0)'Address;
The same with aspect syntax:
Buffer : Communication_Buffer (0 .. 20);
Pkg : Packet
with Import, Address => Buffer (0)'Address;
subtype Packet_Buffer is Communication_Buffer (1 .. 2);
function To_Packet is new Ada.Unchecked_Conversion
(Packet_Buffer, Packet);
Pkg : Packet := To_Packet (Buffer (0 .. 1));
PS. If you want an endianness independent code you may also need a Scalar_Storage_Order (GNAT implementation defined) aspect.
PS. I recommend also take a look at "Safe Communication" chapter of Safe and Secure Software booklet.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With