1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
//! 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).
// 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.
/// 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 ;
pub use ;
pub use 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";