hl7-3-soap 0.1.1

HL7 v3 over SOAP: the envelope, faults, message carriage, WSDL, and acknowledgement evaluation that carry Health Level Seven (HL7) version 3 (v3) messages over HTTP. HL7 v3's own historically dominant transport.
Documentation
//! HL7 v3 over SOAP: the envelope, faults, message carriage, WSDL, and
//! acknowledgement evaluation that carry HL7 v3 messages over HTTP.
//!
//! Unlike v2 — where MLLP is the usual transport and SOAP is the exception
//! — SOAP *is* HL7 v3's own historically dominant transport: v3 was
//! designed alongside SOAP/WS-*, and real deployments (NHS England's
//! Personal Demographics Service, IHE profiles built on v3) carry it that
//! way. This crate is that transport, and it is deliberately the same
//! shape as its `hl7-2-soap` cousin: it does the protocol and nothing
//! else.
//!
//! # What it does
//!
//! - [`parse`] a SOAP envelope and take the single payload out of its body
//! - [`Fault`]s, each carrying the HTTP status that belongs with it
//! - [`message`] — read which interaction a v3 payload is, its control ID,
//!   and its claimed assigning authority, and check a payload against what
//!   the interface accepts
//! - [`response`] — build the real HL7 v3 acknowledgement, and read one as
//!   accepted or rejected
//! - [`wsdl`] — describe the endpoint to client tooling, at its real address
//!
//! # What it does not do
//!
//! No HTTP client and no HTTP server: this crate turns bytes into meaning
//! and back, and leaves the socket to whatever the caller already uses.
//! No RIM decoding and no domain-payload interpretation either — `hl7-3`
//! owns those; this crate reads only what it needs to route and
//! acknowledge a message, the same restraint `hl7-2-soap` applies to v2.
//!
//! # Receiving
//!
//! ```
//! use hl7_3_soap::{Fault, message, response};
//!
//! fn handle(request_body: &str) -> (u16, String) {
//!     match accept(request_body) {
//!         Ok(control_id) => (200, response::success(&control_id)),
//!         Err(fault) => (fault.status, fault.to_envelope()),
//!     }
//! }
//!
//! fn accept(request_body: &str) -> Result<String, Fault> {
//!     let envelope = hl7_3_soap::parse(request_body)?;
//!     let payload = envelope.payload()?;
//!     message::check(payload, &["PRPA_IN201305UV02".to_string()], &[])?;
//!     // ...decode the payload with hl7-3, and forward it, here...
//!     Ok(message::control_id(payload).unwrap_or_default().to_string())
//! }
//!
//! let request = r#"<Envelope><Body><PRPA_IN201305UV02><id extension="9"/></PRPA_IN201305UV02></Body></Envelope>"#;
//! assert_eq!(handle(request).0, 200);
//!
//! let wrong = r#"<Envelope><Body><PRPA_IN201306UV02/></Body></Envelope>"#;
//! assert_eq!(handle(wrong).0, 400);
//! ```
//!
//! # Sending
//!
//! ```
//! use hl7_3_soap::{envelope, response::{self, Outcome}};
//!
//! let body = envelope::wrap_xml(r#"<PRPA_IN201305UV02><id extension="9"/></PRPA_IN201305UV02>"#);
//! // ...POST `body` with Content-Type: text/xml; charset=utf-8...
//! # let (status, reply) = (200, response::success("9"));
//! match response::evaluate(status, &reply) {
//!     Outcome::Accepted => {}
//!     Outcome::Rejected(reason) => panic!("not delivered: {reason}"),
//! }
//! ```
//!
//! See `spec/index.md` for the exact rules (source of truth).

#![warn(missing_docs, clippy::pedantic)]
// XML literals keep their `r#"..."#` delimiters even where no `"` currently
// forces them: these are documents, and adding a quoted attribute to one
// should not also mean changing its delimiter.
#![allow(clippy::needless_raw_string_hashes)]

pub mod envelope;
pub mod fault;
pub mod message;
pub mod response;
pub mod wsdl;

/// The XML reader this crate is built on, re-exported so callers can name
/// [`xml::Element`] and walk a payload themselves without adding their own
/// dependency.
///
/// `hl7-2-xml-lite-helper` has no dependencies of its own, and is shared
/// with the other crates in this family that read XML, so there is one
/// parser to audit rather than one per crate.
pub use hl7_2_xml_lite_helper as xml;

pub use envelope::{Envelope, parse, wrap_xml};
pub use fault::{Fault, SOAP_NS};
pub use response::Outcome;

/// The content type a SOAP 1.1 request and response are sent with.
///
/// SOAP 1.1 uses `text/xml`; SOAP 1.2 would use `application/soap+xml`.
/// This crate speaks 1.1, matching `hl7-2-soap` and the real HL7 v3
/// interfaces it was built from.
pub const CONTENT_TYPE: &str = "text/xml; charset=utf-8";