module ITU_X213_Types {

/* ITU_X213_Types, defining abstract TTCN-3 data types for ITU-T Rec. X.213.
 *
 * (C) 2024 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
 * All rights reserved.
 * Author: Pau Espin Pedrol <pespin@sysmocom.de>
 *
 * Released under the terms of GNU General Public License, Version 2 or
 * (at your option) any later version.
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */


import from General_Types all;
import from Osmocom_Types all;

/* Network Service access point */

/* initial domain part (IDP). = authority and format identifier (AFI) + initial domain identifier (IDI). */

type enumerated NSAP_AFI {
	NSAP_AFI_IANA_ICP_DEC ('34'H),
	NSAP_AFI_IANA_ICP_BIN ('35'H)
} with { variant "FIELDLENGTH(8)" };

type enumerated NSAP_IDI_IANA_ICP {
	NSAP_IDI_IANA_ICP_IPv6 ('0000'H),
	NSAP_IDI_IANA_ICP_IPv4 ('0001'H)
} with { variant "FIELDLENGTH(16)"
	 variant "BYTEORDER(last)" };

type record NSAP_DSP_IANA_ICP_BIN_IPv6 {
	OCT16 addr,
	OCT1 padding
};

type record NSAP_DSP_IANA_ICP_BIN_IPv4 {
	OCT4 addr,
	octetstring padding length (0..13) optional
};

type union NSAP_DSP_IANA_ICP_BIN {
	NSAP_DSP_IANA_ICP_BIN_IPv6 ipv6,
	NSAP_DSP_IANA_ICP_BIN_IPv4 ipv4,
	octetstring other
};

type record NSAP_IDI_IANA_ICP_BIN {
	NSAP_IDI_IANA_ICP	icp,
	NSAP_DSP_IANA_ICP_BIN	dsp
} with { variant (dsp) "CROSSTAG(ipv6, 	icp = NSAP_IDI_IANA_ICP_IPv6;
				 ipv4, 	icp = NSAP_IDI_IANA_ICP_IPv4;
				 other,	OTHERWISE)"
};

type union NSAP_IDI {
	NSAP_IDI_IANA_ICP_BIN iana_icp_bin,
	octetstring other
};

type record NSAP_IDP {
	NSAP_AFI afi,
	NSAP_IDI idi
} with { variant (idi) "CROSSTAG(iana_icp_bin, 	afi = NSAP_AFI_IANA_ICP_BIN;
				 other,	OTHERWISE)"
};

type record NSAP_Address {
	NSAP_IDP	idp
};


external function enc_NSAP_Address(in NSAP_Address pco_data) return octetstring
with { extension "prototype(convert)" extension "encode(RAW)" }

external function dec_NSAP_Address(in octetstring pco_payload) return NSAP_Address
with { extension "prototype(convert) decode(RAW)" };

/**********************
 * ITU_X213_Templates:
 **********************/

template (present) NSAP_DSP_IANA_ICP_BIN_IPv6 tr_NSAP_IANA_IPv6_Address(template (present) OCT16 addr := ?) := {
	addr := addr,
	padding := ?
};
template (value) NSAP_DSP_IANA_ICP_BIN_IPv6 ts_NSAP_IANA_IPv6_Address(template (value) OCT16 addr) := {
	addr := addr,
	padding := '00'O
};

template (present) NSAP_DSP_IANA_ICP_BIN_IPv4 tr_NSAP_IANA_IPv4_Address(template (present) OCT4 addr := ?, template octetstring padding := *) := {
	addr := addr,
	padding := padding
};
template (value) NSAP_DSP_IANA_ICP_BIN_IPv4 ts_NSAP_IANA_IPv4_Address(template (value) OCT4 addr, template (omit) octetstring padding := omit) := {
	addr := addr,
	padding := padding
};

template (present) NSAP_DSP_IANA_ICP_BIN tr_NSAP_IANA_u_IPv6_Address(template (present) OCT16 addr := ?) := {
	ipv6 := tr_NSAP_IANA_IPv6_Address(addr)
};
template (value) NSAP_DSP_IANA_ICP_BIN ts_NSAP_IANA_u_IPv6_Address(template (value) OCT16 addr) := {
	ipv6 := ts_NSAP_IANA_IPv6_Address(addr)
};

template (present) NSAP_DSP_IANA_ICP_BIN tr_NSAP_IANA_u_IPv4_Address(template (present) OCT4 addr := ?, template octetstring padding := *) := {
	ipv4 := tr_NSAP_IANA_IPv4_Address(addr, padding)
};
template (value) NSAP_DSP_IANA_ICP_BIN ts_NSAP_IANA_u_IPv4_Address(template (value) OCT4 addr, template (omit) octetstring padding := omit) := {
	ipv4 := ts_NSAP_IANA_IPv4_Address(addr, padding)
};

template (present) NSAP_IDI_IANA_ICP_BIN tr_NSAP_IDI_IANA_ICP_BIN(template (present) NSAP_IDI_IANA_ICP icp := ?,
								  template (present) NSAP_DSP_IANA_ICP_BIN dsp := ?) := {
	icp := icp,
	dsp := dsp
};
template (value) NSAP_IDI_IANA_ICP_BIN ts_NSAP_IDI_IANA_ICP_BIN(template (value) NSAP_IDI_IANA_ICP icp,
								template (value) NSAP_DSP_IANA_ICP_BIN dsp) := {
	icp := icp,
	dsp := dsp
};

template (present) NSAP_IDI tr_NSAP_IDI_u_IANA_ICP_BIN(template (present) NSAP_IDI_IANA_ICP_BIN iana_icp_bin := ?) := {
	iana_icp_bin := iana_icp_bin
};
template (value) NSAP_IDI ts_NSAP_IDI_u_IANA_ICP_BIN(template (value) NSAP_IDI_IANA_ICP_BIN iana_icp_bin) := {
	iana_icp_bin := iana_icp_bin
};

template (present) NSAP_IDP tr_NSAP_IDP(template (present) NSAP_AFI afi := ?, template (present) NSAP_IDI idi := ?) := {
	afi := afi,
	idi := idi
};
template (value) NSAP_IDP ts_NSAP_IDP(template (value) NSAP_AFI afi, template (value) NSAP_IDI idi) := {
	afi := afi,
	idi := idi
};

template (present) NSAP_Address tr_NSAP_Address_IANA_BIN_IPv6(template (present) OCT16 addr := ?) := {
	idp := tr_NSAP_IDP(NSAP_AFI_IANA_ICP_BIN,
			   tr_NSAP_IDI_u_IANA_ICP_BIN(tr_NSAP_IDI_IANA_ICP_BIN(NSAP_IDI_IANA_ICP_IPv6,
									       tr_NSAP_IANA_u_IPv6_Address(addr))))
};
template (value) NSAP_Address ts_NSAP_Address_IANA_BIN_IPv6(template (value) OCT16 addr) := {
	idp := ts_NSAP_IDP(NSAP_AFI_IANA_ICP_BIN,
			   ts_NSAP_IDI_u_IANA_ICP_BIN(ts_NSAP_IDI_IANA_ICP_BIN(NSAP_IDI_IANA_ICP_IPv6,
									       ts_NSAP_IANA_u_IPv6_Address(addr))))
};

template (present) NSAP_Address tr_NSAP_Address_IANA_BIN_IPv4(template (present) OCT4 addr := ?,
							      template octetstring padding := *) := {
	idp := tr_NSAP_IDP(NSAP_AFI_IANA_ICP_BIN,
			   tr_NSAP_IDI_u_IANA_ICP_BIN(tr_NSAP_IDI_IANA_ICP_BIN(NSAP_IDI_IANA_ICP_IPv4,
									       tr_NSAP_IANA_u_IPv4_Address(addr, padding))))
};
template (value) NSAP_Address ts_NSAP_Address_IANA_BIN_IPv4(template (value) OCT4 addr,
							    template (omit) octetstring padding := omit) := {
	idp := ts_NSAP_IDP(NSAP_AFI_IANA_ICP_BIN,
			   ts_NSAP_IDI_u_IANA_ICP_BIN(ts_NSAP_IDI_IANA_ICP_BIN(NSAP_IDI_IANA_ICP_IPv4,
									       ts_NSAP_IANA_u_IPv4_Address(addr, padding))))
};
/* IPv4 with padding so that TLA is 20 bytes. This is quite common: */
template (value) NSAP_Address ts_NSAP_Address_IANA_BIN_IPv4Len20(template (value) OCT4 addr) :=
	ts_NSAP_Address_IANA_BIN_IPv4(addr, '00000000000000000000000000'O);


} with { encode "RAW"; variant "FIELDORDER(msb)" }
