The InputStream Interface in Swift
On this page:
Initializing an InputStream
in Swift
The InputStream
class provides two initializers:
public class InputStream { public convenience init(communicator: Communicator, bytes: Foundation.Data) {...} public required init(communicator: Communicator, encoding: EncodingVersion, bytes: Foundation.Data) {...} }
These initializers accept up to 3 parameters:
- A communicator instance
- An encoding version
- A Foundation.Data object containing the encoded data that you intend to decode
If you omit an encoding version, the stream uses the default encoding version of the communicator or the most recent encoding version.
Extracting from an InputStream
in Swift
InputStream
provides a number of read
methods that allow you to extract Slice types from the stream.
For example, you can extract a boolean and a sequence of strings from a stream as follows:
var data: Foundation.Data = ... let in = Ice.InputStream(communicator: communicator, data: data) let b: Bool = try in.read() let seq: [String] = try in.read()
Here are the methods for extracting data from a stream:
public extension InputStream { /// Reads a numeric value from the stream. func read<Element>() throws -> Element where Element: StreamableNumeric /// Reads an optional numeric value from the stream. func read<Element>(tag: Int32) throws -> Element? where Element: StreamableNumeric /// Reads a sequence of numeric values from the stream. func read<Element>() throws -> [Element] where Element: StreamableNumeric /// Reads an optional sequence of numeric values from the stream. func read<Element>(tag: Int32) throws -> [Element]? where Element: StreamableNumeric /// Reads a byte from the stream. func read() throws -> UInt8 /// Reads a sequence of bytes from the stream. func read() throws -> [UInt8] /// Reads a sequence of bytes from the stream. func read() throws -> Data /// Reads an optional sequence of bytes from the stream. func read(tag: Int32) throws -> Data? /// Reads a boolean value from the stream. func read() throws -> Bool /// Reads an optional boolean value from the stream. func read(tag: Int32) throws -> Bool? /// Reads a sequence of boolean value from the stream. func read() throws -> [Bool] /// Reads an optional sequence of boolean value from the stream. func read(tag: Int32) throws -> [Bool]? /// Reads a size from the stream. func readSize() throws -> Int32 /// Reads a sequence size from the stream and ensures the stream has enough /// bytes for `size` elements, where each element's size is at least minSize. func readAndCheckSeqSize(minSize: Int) throws -> Int /// Reads an enumerator from the stream, as a byte. func read(enumMaxValue: Int32) throws -> UInt8 /// Reads an enumerator from the stream, as a Int32. func read(enumMaxValue: Int32) throws -> Int32 /// Reads a string from the stream. func read() throws -> String /// Reads an optional string from the stream. func read(tag: Int32) throws -> String? /// Reads a sequence of strings from the stream. func read() throws -> [String] /// Reads an optional sequence of strings from the stream. func read(tag: Int32) throws -> [String]? /// Reads a proxy from the stream. func read(_: ObjectPrx.Protocol) throws -> ObjectPrx? /// Reads an optional proxy from the stream. func read(tag: Int32, type _: ObjectPrx.Protocol) throws -> ObjectPrx? /// Reads a value from the stream. func read(cb: ((Value?) throws -> Void)?) throws /// Reads an optional value from the stream. func read(tag: Int32, cb: ((Value?) throws -> Void)?) throws }
The read methods are overloaded to allow you to extract all of primitive types, as well as sequences of primitive types. The Slice to Swift compiler generate additional read overloads for user-defined types. The remaining methods have the following semantics:
func readSize() throws -> Int32
The Ice encoding has a compact representation to indicate size. This method extracts a size and returns it as an integer.
func readAndCheckSeqSize(minSize: Int) throws -> Int
LikereadSize
, this method reads a size and returns it, but also verifies that there is enough data remaining in the buffer to successfully unmarshal the elements of the sequence. TheminWireSize
parameter indicates the smallest possible on-the-wire representation of a single sequence element. If the buffer contains insufficient data to unmarshal the sequence, the method throwsUnmarshalOutOfBoundsException
.
void throwException()
This method extracts a user exception from the stream and throws it. If the stored exception is of an unknown type, the method attempts to extract and throw a less-derived exception. If this fails, it throwsUnknownUserException
with for the 1.1 encoding andUnmarshalOutOfBoundsException
for the 1.0 encoding.
func startSlice() throws -> String
func endSlice() throws
func skipSlice() throws
Start, end, and skip a slice. These methods are used when manually extracting the slices of a class instance or user exception. ThestartSlice
method returns the type ID of the next slice, which may be an empty string depending on the format used to encode the instance or exception.
func startValue()
func endValue(preserve: Bool) throws -> SlicedData?
ThestartValue
method must be called prior to reading the slices of a class instance. TheendValue
method must be called after all slices have been read. Pass true toendValue
in order to preserve the slices of any unknown more-derived types, or false to discard the slices. Ifpreserve
is true and the stream actually preserved any slices, the return value ofendValue
is a non-nilSlicedData
object that encapsulates the slice data. If the caller later wishes to forward the instance with any preserved slices intact, it must supply thisSlicedData
object to the output stream.
func startException()
func endException(preserve: Bool) throws -> SlicedData?
ThestartException
method must be called prior to reading the slices of an exception. TheendException
method must be called after all slices have been read. Pass true toendException
in order to preserve the slices of any unknown more-derived types, or false to discard the slices. Ifpreserve
is true and the stream actually preserved any slices, the return value ofendException
is a non-nilSlicedData
object that encapsulates the slice data. If the caller later wishes to forward the exception with any preserved slices intact, it must supply thisSlicedData
object to the output stream.
func startEncapsulation() throws -> EncodingVersion
func endEncapsulation() throws
func skipEncapsulation() throws -> EncodingVersion
Start, end, and skip an encapsulation, respectively. ThestartEncapsulation
andskipEncapsulation
methods return the encoding version used to encode the contents of the encapsulation.
func skipEmptyEncapsulation() throws -> EncodingVersion
Skips an encapsulation that is expected to be empty and returns its encoding version. The stream raisesEncapsulationException
if the encapsulation is not empty.
func readPendingValues() throws
With encoding version 1.0, an application must call this method after all other data has been extracted, but only if class instances were encoded. This method extracts the state of class instances and invokes their corresponding callback objects (seereadValue
). This method is no-op with encoding version 1.1.
func skip(_ count: Int) throws
Skips the given number of bytes.
func skipSize() throws
Reads a size at the current position and skips that number of bytes.
func readOptional(tag: Int32, expectedFormat: OptionalFormat) throws -> Bool
Returns true if an optional value with the given tag and format is present, or false otherwise. If this method returns true, the data associated with that optional value must be read next. Optional values must be read in order by tag from least to greatest. TheOptionalFormat
enumeration is defined as follows:C#enum OptionalFormat: UInt8 { case F1 = 0 case F2 = 1 case F4 = 2 case F8 = 3 case Size = 4 case VSize = 5 case FSize = 6 case Class = 7 ... }
Refer to the encoding discussion for more information on the meaning of these values.
InputStream
Extensions
The InputStream
class provides all of the low-level methods necessary for decoding Ice types. However, it would be tedious and error-prone to manually decode complex Ice-types such as classes, structures, and enumerated types. the Slice compiler generates extensions to the InputStream
for decoding complex Ice types.
We will use the following Slice definitions to demonstrate the language mapping:
module M { struct S { ... } enum E { ... } class C { ... } interface I { ... } }
The Slice compiler generates the corresponding InputStream extension shown below:
/// An Ice.InputStream extension to read S structured values from the stream. public extension Ice.InputStream { /// Read a `S` structured value from the stream. func read() throws -> S { ... } /// Read an optional `S?` structured value from the stream. func read(tag: Swift.Int32) throws -> S? { ... } } /// An Ice.InputStream extension to read E enumerated values from the stream. public extension Ice.InputStream { /// Read an enumerated value. func read() throws -> E /// Read an optional enumerated value from the stream. func read(tag: Swift.Int32) throws -> E? } /// Extension to Ice.InputStream class to support reading proxy of type IPrx. public extension Ice.InputStream { /// Extracts a proxy from the stream. The stream must have been initialized with a communicator. func read(_ type: IPrx.Protocol) throws -> IPrx? { ... } /// Extracts a proxy from the stream. The stream must have been initialized with a communicator. func read(tag: Swift.Int32, type: IPrx.Protocol) throws -> IPrx? { ... } }
No additional code is generated for unmarshaling instances of class types, such as type C that we defined above. Applications should use InputStream.read
to extract class instances.