//! # openfut-protocol-blaze
//!
//! Game-independent EA Blaze wire protocol: Fire2 framing and the Heat2/TDF
//! codec.
//!
//! ## What belongs here
//!
//! Only things that are true of Blaze itself:
//!
//! * [`fire2`] — the 16-byte frame header and frame/stream splitting
//! * [`heat2`] — tag packing, varints, and the eleven TDF value types
//! * [`message`] — a frame plus its decoded body, routed by numeric
//!   component/command
//! * [`diagnostics`] — dumps for capture review
//!
//! ## What does not belong here
//!
//! Anything that would have to change for a different title: command and
//! component name tables, notification IDs, response schemas, login sequencing,
//! session identity. FIFA 17 says `0x0009/0x0007` is `Util::preAuth`; this
//! crate only knows it is component 9, command 7. A game adapter owns the rest.
//!
//! The test for a change landing in the right place: *could FIFA 18 or FIFA 23
//! use this without importing FIFA 17's command tables?* If not, it belongs in
//! an adapter.
//!
//! ## Provenance and confidence
//!
//! Ported from the Python implementation in `fifa17-recon/tools/` that drove a
//! retail FIFA 17 client from Origin login to an opened FUT pack — the
//! project's behavioural oracle. Parity is not asserted, it is tested: the
//! vectors in `fixtures/` are generated from that Python code and replayed
//! byte-for-byte by `tests/oracle_parity.rs`.
//!
//! Confidence is not uniform, and the code says so rather than leaving it in a
//! comment. Int, string, blob and struct layouts are proven against captured
//! traffic; list, map, union, varlist, objtype, objid and float are not, and
//! [`heat2::TypeId::is_verified`] reports which is which.
//!
//! ```
//! use openfut_protocol_blaze::fire2::{Frame, MsgType};
//! use openfut_protocol_blaze::heat2::{self, Struct, Value};
//!
//! let body = Struct::new()
//!     .with("PID", Value::Int(33068179))
//!     .with("NAME", Value::String("CAGE".into()));
//!
//! let frame = Frame::new(0x0001, 0x000A, 7, MsgType::Reply, heat2::encode(&body));
//! let wire = frame.encode();
//!
//! let (parsed, used) = Frame::parse(&wire).unwrap();
//! assert_eq!(used, wire.len());
//! assert_eq!(parsed.header.component, 0x0001);
//! assert_eq!(wire[13], 0x20); // msgType REPLY in the top 3 bits, userIndex 0
//! ```

#![forbid(unsafe_code)]

pub mod diagnostics;
pub mod error;
pub mod fire2;
pub mod heat2;
pub mod message;

pub use error::{Error, Result};
pub use fire2::{Frame, Header, MsgType};
pub use heat2::{Struct, Tag, TypeId, Value};
pub use message::Message;
