13.13.2 Stream-Oriented Attributes
The type-related operational attributes Write, Read, 
Output, and Input convert values to a stream of elements and reconstruct 
values from a stream.
  
Static Semantics
  For every subtype 
S of an elementary type T, the following representation attribute 
is defined: 
  S'Stream_Size
Denotes the number of bits read 
from or written to a stream by the default implementations of S'Read 
and S'Write. Hence, the number of stream elements required per item of 
elementary type 
T is:
 
T'Stream_Size / Ada.Streams.Stream_Element'Size
The value of this attribute is of type 
universal_integer and is a multiple of Stream_Element'Size.
Stream_Size may be specified for first 
subtypes via an 
attribute_definition_clause; 
the 
expression 
of such a clause shall be static, nonnegative, and a multiple of Stream_Element'Size.
 
Implementation Advice
  If not specified, the value of Stream_Size for 
an elementary type should be the number of bits that corresponds to the 
minimum number of stream elements required by the first subtype of the 
type, rounded up to the nearest factor or multiple of the word size that 
is also a multiple of the stream element size. 
  The 
recommended level of support for the Stream_Size attribute is: 
 
A Stream_Size clause should be supported for a 
discrete or fixed point type T if the specified Stream_Size is 
a multiple of Stream_Element'Size and is no less than the size of the 
first subtype of T, and no greater than the size of the largest 
type of the same elementary class (signed integer, modular integer, enumeration, 
ordinary fixed point, or decimal fixed point). 
Static Semantics
For every subtype S of a specific type T, 
the following attributes are defined. 
S'Write
S'Write denotes a procedure with 
the following specification: 
 
procedure S'Write(
   Stream : not null access Ada.Streams.Root_Stream_Type'Class;
   Item : in T)
S'Write writes the value of Item 
to Stream.
S'Read
S'Read denotes a procedure with 
the following specification: 
 
procedure S'Read(
   Stream : not null access Ada.Streams.Root_Stream_Type'Class;
   Item : out T)
S'Read reads the value of Item from 
Stream. 
  For an untagged derived type, the Write (resp. 
Read) attribute is inherited according to the rules given in 
13.1 
if the attribute is specified and available for the parent type at the 
point where 
T is declared. For a tagged derived type, these attributes 
are not inherited, but rather the default implementations are used.
 
  The default implementations 
of the Write and Read attributes, where available, execute as follows:
For elementary types, Read reads (and Write writes) 
the number of stream elements implied by the Stream_Size for the type 
T; the representation of those stream elements is implementation 
defined. For composite types, the Write or Read attribute for each component 
is called in canonical order, which is last dimension varying fastest 
for an array (unless the convention of the array is Fortran, in which 
case it is first dimension varying fastest), and positional aggregate 
order for a record. Bounds are not included in the stream if T 
is an array type. If T is a discriminated type, discriminants 
are included only if they have defaults. If T is a tagged type, 
the tag is not included. For type extensions, the Write or Read attribute 
for the parent type is called, followed by the Write or Read attribute 
of each component of the extension part, in canonical order. For a limited 
type extension, if the attribute of the parent type or any progenitor 
type of T is available anywhere within the immediate scope of 
T, and the attribute of the parent type or the type of any of 
the extension components is not available at the freezing point of T, 
then the attribute of T shall be directly specified.
  If T is a discriminated type and its discriminants 
have defaults, then S'Read first reads the discriminants from the stream 
without modifying Item. S'Read then creates an object of type 
T constrained by these discriminants. The value of this object 
is then converted to the subtype of Item and is assigned to Item. 
Finally, the Read attribute for each nondiscriminant component of Item 
is called in canonical order as described above. Normal default initialization 
and finalization take place for the created object.
  Constraint_Error is raised by the predefined Write 
attribute if the value of the elementary item is outside the range of 
values representable using Stream_Size bits. For a signed integer type, 
an enumeration type, or a fixed point type, the range is unsigned only 
if the integer code for the lower bound of the first subtype is nonnegative, 
and a (symmetric) signed range that covers all values of the first subtype 
would require more than Stream_Size bits; otherwise, the range is signed.
For every subtype S'Class 
of a class-wide type T'Class: 
S'Class'Write
S'Class'Write denotes a procedure 
with the following specification: 
 
procedure S'Class'Write(
   Stream : not null access Ada.Streams.Root_Stream_Type'Class;
   Item   : in T'Class)
Dispatches to the subprogram denoted by 
the Write attribute of the specific type identified by the tag of Item.
S'Class'Read
S'Class'Read denotes a procedure 
with the following specification: 
 
procedure S'Class'Read(
   Stream : not null access Ada.Streams.Root_Stream_Type'Class;
   Item : out T'Class)
Dispatches to the subprogram denoted by 
the Read attribute of the specific type identified by the tag of Item. 
Paragraph 17 was 
deleted. 
Static Semantics
For every subtype S of a specific type T, 
the following attributes are defined. 
S'Output
S'Output denotes a procedure 
with the following specification: 
 
procedure S'Output(
   Stream : not null access Ada.Streams.Root_Stream_Type'Class;
   Item : in T)
S'Output writes the value of Item 
to Stream, including any bounds or discriminants. 
S'Input
S'Input denotes a function with 
the following specification: 
 
function S'Input(
   Stream : not null access Ada.Streams.Root_Stream_Type'Class)
   return T
S'Input reads and returns one value from 
Stream, using any bounds or discriminants written by a corresponding 
S'Output to determine how much to read. 
 For an untagged derived type, the Output (resp. 
Input) attribute is inherited according to the rules given in 
13.1 
if the attribute is specified and available for the parent type at the 
point where 
T is declared. For a tagged derived type, these attributes 
are not inherited, but rather the default implementations are used.
 
   The default implementations 
of the Output and Input attributes, where available, execute as follows: 
If T is an array type, S'Output first writes 
the bounds, and S'Input first reads the bounds. If T has discriminants 
without defaults, S'Output first writes the discriminants (using the 
Write attribute of the discriminant type for each), and S'Input first 
reads the discriminants (using the Read attribute of the discriminant 
type for each).
S'Output then calls S'Write to write the value 
of 
Item to the stream. S'Input then creates an object of type 
T, with the bounds or (when without defaults) the discriminants, 
if any, taken from the stream, passes it to S'Read, and returns the value 
of the object. If 
T has discriminants, then this object is unconstrained 
if and only the discriminants have defaults. Normal default initialization 
and finalization take place for this object (see 
3.3.1, 
7.6, and 
7.6.1). 
 
   If T is an abstract type, then S'Input 
is an abstract function.
For every subtype S'Class 
of a class-wide type T'Class: 
S'Class'Output
S'Class'Output denotes a procedure 
with the following specification: 
 
procedure S'Class'Output(
   Stream : not null access Ada.Streams.Root_Stream_Type'Class;
   Item   : in T'Class)
First writes the external tag of 
Item 
to 
Stream (by calling String'Output(
Stream, Tags.External_Tag(
Item'Tag)) 
— see 
3.9) and then dispatches to the 
subprogram denoted by the Output attribute of the specific type identified 
by the tag. Tag_Error is raised if the tag of Item identifies a type 
declared at an accessibility level deeper than that of S. 
 
S'Class'Input
S'Class'Input denotes a function 
with the following specification: 
 
function S'Class'Input(
   Stream : not null access Ada.Streams.Root_Stream_Type'Class)
   return T'Class
First reads the external tag from 
Stream 
and determines the corresponding internal tag (by calling Tags.Descendant_Tag(String'Input(
Stream), 
S'Tag) which might raise Tag_Error — see 
3.9) 
and then dispatches to the subprogram denoted by the Input attribute 
of the specific type identified by the internal tag; returns that result. 
If the specific type identified by the internal tag is abstract, Constraint_Error 
is raised.
 
 In the default 
implementation of Read and Input for a composite type, for each scalar 
component that is a discriminant or that has an implicit initial value, 
a check is made that the value returned by Read for the component belongs 
to its subtype. 
Constraint_Error is raised if this 
check fails. For other scalar components, no check is made. For each 
component that is of an access type, if the implementation can detect 
that the value returned by Read for the component is not a value of its 
subtype, Constraint_Error is raised. If the value is not a value of its 
subtype and this error is not detected, the component has an abnormal 
value, and erroneous execution can result (see 
13.9.1). 
In the default implementation of Read for a composite type with defaulted 
discriminants, if the actual parameter of Read is constrained, a check 
is made that the discriminants read from the stream are equal to those 
of the actual parameter. Constraint_Error is raised if this check fails.
 
 It is unspecified at which point 
and in which order these checks are performed. In particular, if Constraint_Error 
is raised due to the failure of one of these checks, it is unspecified 
how many stream elements have been read from the stream.
 
 In the default implementation 
of Read and Input for a type, End_Error is raised if the end of the stream 
is reached before the reading of a value of the type is completed.
 
 The 
stream-oriented attributes may be specified for any type via an 
attribute_definition_clause. 
Alternatively, each of the specific stream-oriented attributes may be 
specified using an 
aspect_specification 
on any 
type_declaration, 
with the aspect name being the corresponding attribute name. Each of 
the class-wide stream-oriented attributes may be specified using an 
aspect_specification 
for a tagged type 
T using the name of the stream-oriented attribute 
followed by 'Class; such class-wide aspects do not apply to other descendants 
of 
T. 
 
 A stream-oriented 
attribute for a subtype of a specific type 
T is 
available 
at places where one of the following conditions is true: 
 
T is nonlimited.
The 
attribute_designator 
is Read (resp. Write) and 
T is a limited record extension, and 
the attribute Read (resp. Write) is available for the parent type of 
T and for the types of all of the extension components. 
 
T is a limited untagged derived type, and 
the attribute was inherited for the type. 
The 
attribute_designator 
is Input (resp. Output), and 
T is a limited type, and the attribute 
Read (resp. Write) is available for 
T. 
 
 A stream-oriented 
attribute for a subtype of a class-wide type T'Class is available 
at places where one of the following conditions is true:
T is nonlimited;
the corresponding attribute of T is available, 
provided that if T has a partial view, the corresponding attribute 
is available at the end of the visible part where T is declared.
 An 
attribute_reference 
for one of the stream-oriented attributes is illegal unless the attribute 
is available at the place of the 
attribute_reference. 
Furthermore, an 
attribute_reference 
for 
T'Input is illegal if 
T is an abstract type.
 
In addition to the places where Legality Rules normally apply (see 
12.3), 
these rules also apply in the private part of an instance of a generic 
unit.
 
   Unless inherited from a parent type, if any, for 
an untagged type having a task, protected, or explicitly limited record 
part, the default implementation of each of the Read, Write, Input, and 
Output attributes raises Program_Error and performs no other action.
 In the 
parameter_and_result_profiles 
for the default implementations of the stream-oriented attributes, the 
subtype of the Item parameter is the base subtype of 
T if 
T 
is a scalar type, and the first subtype otherwise. The same rule applies 
to the result of the Input attribute.
 
 For an 
attribute_definition_clause 
specifying one of these attributes, the subtype of the 
Item parameter 
shall be the first subtype or the base subtype if scalar, and the first 
subtype if not scalar. The same rule applies to the result of the Input 
function.
 
 A type is 
said to 
support external streaming if Read and Write attributes 
are provided for sending values of such a type between active partitions, 
with Write marshalling the representation, and Read unmarshalling the 
representation. A limited type supports external streaming only if it 
has available Read and Write attributes. A type with a part that is of 
a nonremote access type supports external streaming only if that access 
type or the type of some part that includes the access type component, 
has Read and Write attributes that have been specified via an 
attribute_definition_clause, 
and that 
attribute_definition_clause 
is visible. An anonymous access type does not support external streaming. 
All other types (including remote access types, see 
E.2.2) 
support external streaming.
 
Erroneous Execution
 If the internal tag returned 
by Descendant_Tag to T'Class'Input identifies a type that is not library-level 
and whose tag has not been created, or does not exist in the partition 
at the time of the call, execution is erroneous. 
 
Implementation Requirements
 For every subtype S of a language-defined 
nonlimited specific type T, the output generated by S'Output or 
S'Write shall be readable by S'Input or S'Read, respectively. This rule 
applies across partitions if the implementation conforms to the Distributed 
Systems Annex.
 If Constraint_Error is raised during a call to Read 
because of failure of one the above checks, the implementation shall 
ensure that the discriminants of the actual parameter of Read are not 
modified. 
Implementation Permissions
 The number of calls performed by the predefined 
implementation of the stream-oriented attributes on the Read and Write 
operations of the stream type is unspecified. An implementation may take 
advantage of this permission to perform internal buffering. However, 
all the calls on the Read and Write operations of the stream type needed 
to implement an explicit invocation of a stream-oriented attribute shall 
take place before this invocation returns. An explicit invocation is 
one appearing explicitly in the program text, possibly through a generic 
instantiation (see 
12.3).
 
   If T is a discriminated type and its discriminants 
have defaults, then in two cases an execution of the default implementation 
of S'Read is not required to create an anonymous object of type T: 
If the discriminant values that are read in are equal to the corresponding 
discriminant values of Item, then no object of type T need 
be created and Item may be used instead. If they are not equal 
and Item is a constrained variable, then Constraint_Error may 
be raised at that point, before any further values are read from the 
stream and before the object of type T is created.
   A default implementation of S'Input that calls 
the default implementation of S'Read may create a constrained anonymous 
object with discriminants that match those in the stream. 
40  For a definite subtype S of a type T, 
only T'Write and T'Read are needed to pass an arbitrary 
value of the subtype through a stream. For an indefinite subtype S of 
a type T, T'Output and T'Input will normally be 
needed, since T'Write and T'Read do not pass bounds, discriminants, 
or tags.
41  User-specified attributes of S'Class 
are not inherited by other class-wide types descended from S. 
Examples
Example of user-defined 
Write attribute: 
procedure My_Write(
  Stream : not null access Ada.Streams.Root_Stream_Type'Class;
  Item   : My_Integer'Base);
for My_Integer'Write use My_Write;
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe