Skip to main content

define_operation_with_response

Macro define_operation_with_response 

Source
macro_rules! define_operation_with_response {
    (
        operation: $op_struct:ident,
        action: $action:literal,
        service: $service:ident,
        request: {
            $($field:ident: $field_type:ty),* $(,)?
        },
        response: $response_struct:ident {
            $($resp_field:ident: $resp_type:ty),* $(,)?
        },
        request_xml_mapping: {
            $($req_field:ident: $req_xml_name:literal),* $(,)?
        },
        xml_mapping: {
            $($xml_field:ident: $xml_path:literal),* $(,)?
        } $(,)?
    ) => { ... };
    (
        operation: $op_struct:ident,
        action: $action:literal,
        service: $service:ident,
        request: {
            $($field:ident: $field_type:ty),* $(,)?
        },
        response: $response_struct:ident {
            $($resp_field:ident: $resp_type:ty),* $(,)?
        },
        xml_mapping: {
            $($xml_field:ident: $xml_path:literal),* $(,)?
        } $(,)?
    ) => { ... };
}
Expand description

Macro for defining operations with XML response parsing

§Example

define_operation_with_response! {
    operation: GetVolumeOperation,
    action: "GetVolume",
    service: RenderingControl,
    request: {
        channel: String,
    },
    response: GetVolumeResponse {
        current_volume: u8,
    },
    xml_mapping: {
        current_volume: "CurrentVolume",
    },
}

§Request element names

UPnP argument names come from each device’s SCPD and use casing that cannot be derived mechanically from snake_case (ObjectID, EnqueuedURI, NumberOfTracks). For single-word request fields the macro derives the element name by capitalizing the first character (channel -> Channel). Multi-word request fields must declare their element name explicitly via the optional request_xml_mapping: block, which is otherwise a compile error:

define_operation_with_response! {
    operation: SaveQueueOperation,
    action: "SaveQueue",
    service: AVTransport,
    request: {
        title: String,
        object_id: String,
    },
    response: SaveQueueResponse {
        assigned_object_id: String,
    },
    request_xml_mapping: {
        title: "Title",
        object_id: "ObjectID",
    },
    xml_mapping: {
        assigned_object_id: "AssignedObjectID",
    },
}

When present, request_xml_mapping: must list every request field (enforced by an exhaustive destructuring of the generated request struct) and its order determines the order arguments are written to the SOAP body.