Next: , Previous: , Up: Structuring Data   [Contents][Index]

### 4.9 Functions in Structs

Further reading of the Packet Specification 1.2 reveals that each Packet has an additional `crc` field. The content of this field is derived from both the payload bytes and the control bytes.

But this is no vulgar CRC we are talking about. On the contrary, it is a special function developed by the CRC Foundation in partnership with the Packet Foundation, called superCRC (patented, TM).

Fortunately, the CRC Foundation distributes a pickle `supercrc.pk`, that provides a `calculate_crc` function with the following spec:

```fun calculate_crc = (byte[] data, byte[] control) int:
```

So let’s use the function like this in our type, after loading the supercrc pickle:

```load supercrc;

type Packet =
struct
{
byte magic = 0xab;
byte size;

var real_size = (size == 0xff ? 0 : size);

byte[real_size] control;

int crc = calculate_crc (payload, control);
};
```

However, there is a caveat: it happens that the calculation of the CRC may involve arithmetic and division, so the CRC Foundation warns us that the `calculate_crc` function may raise E_div_by_zero. However, the Packet 1.2 Specification tells us that in these situations, the `crc` field of the packet should contain zero. If we used the type above, any exception raised by `calculate_crc` would be propagated by the mapper/constructor:

```(poke) Packet @ 12#B
unhandled division by zero exception
```

A solution is to use a function that takes care of the extra needed logic, wrapping calculate_crc:

```load supercrc;

type Packet =
struct
{
byte magic = 0xab;
byte size;

var real_size = (size == 0xff ? 0 : size);

byte[real_size] control;

fun corrected_crc = int:
{