Server-Side Swift Mapping for Interfaces
The server-side mapping for interfaces provides an up-call API for the Ice runtime: by implementing instance methods in a servant class, you provide the hook that gets the thread of control from the Ice server-side runtime into your application code.
Skeleton Protocols
On the server side, interfaces map to skeleton protocols. A skeleton protocol specifies an instance method for each operation on the corresponding Slice interface. For example, consider our Slice definition for the Node interface:
module Filesystem
{
interface Node
{
idempotent string name();
}
// ...
}
The Slice compiler generates the following definitions for this interface:
// Skeleton protocol
public protocol Node: Ice.Dispatcher {
func name(current: Ice.Current) async throws -> Swift.String
}
extension Node {
public func dispatch(
_ request: sending Ice.IncomingRequest) async throws ->
Ice.OutgoingResponse {
...
}
}
The important points to note here are:
For each Slice interface
<interface-name>, the compiler generates a Swift protocol<interface-name>(Nodein this example).This skeleton protocol extends
Ice.Dispatcher, and the Slice compiler generates an extension for the skeleton protocol that implementsdispatch(Dispatcher’s only method).The base servant protocol in Swift is
Ice.Dispatcher; skeleton protocols do not derive fromIce.Object.
Servant Implementation
In order to provide an implementation for an Ice object, you must create a servant struct, class or actor that adopts the corresponding skeleton protocol. For example, to create a servant for the Node interface, you could write:
struct MNode: Node {
private let name: String
init(name: String) {
self.name = name
}
func name(current _: Ice.Current) -> String {
name
}
}
Note that MNode adopts Node, the skeleton protocol.
As far as Ice is concerned, the MNode struct must implement only a single method: the name method from its skeleton. This makes the servant struct a concrete type that can be instantiated. You can add other methods and fields as you see fit to support your implementation. For example, in the preceding definition, we added a name field and an initializer.