# Code style
The style of the hand-written `adi`, `grandslam` and `xcode` crates. It applies to new code in
apple-crates and Antarctic. When this file and those crates disagree, the crates win.
## Naming
- Acronyms stay upper-case in types, traits and variants: `ADIError`, `HTTPSession`, `URLBag`,
`TeamID`. Apple names with a lower-case prefix only capitalise the first letter: `IOS`, `TvOS`,
`ICloud`. In snake_case, each acronym is one lower-case word: `ds_id`, `set_idms_routing`.
- Locals and fields are spelled out in full. Keep Apple's wire names (`spim`, `cpim`, `ptm`, `tk`,
`mid`, `otp`). Raw bytes before encoding take a `_b` suffix.
- Functions start with a verb. A short entry point delegates to `_with_` variants
(`http_session` → `http_session_with_idms_env`). Request builders are `_request_builder`.
Wire types are named after their endpoint.
- Lifetimes are `'lt` (and `'adi`), or `'_` when no name is needed. Never mix them with `'a` in a file.
## Types and API shape
- Plain data has `pub` fields and is built with struct literals: no builders, setters or getters.
- Tokens and identifiers are tuple newtypes with a private field, `From` and `AsRef`.
- Session layers wrap the layer below (`pub http_session: Inner` plus one credential, `new(inner,
credential)`) and forward its request builders by hand. No `Deref`, no generic service traits.
- Small traits, with associated consts or types. Generics only for compile-time typing; `&dyn Trait`
for runtime providers. Bounds inline, no `where` clauses. Implement `From`, never `Into`.
- Protocol states that aren't failures are variants of an outcome enum returned in `Ok`.
- Plain `pub async fn` with sequential awaits. Libraries spawn nothing, pick no runtime, and keep
ADI and crypto calls synchronous.
- Derive only what's needed, in this order: `Debug, Clone, Copy, Default, PartialEq, Eq, Hash,
Serialize, Deserialize`. Types holding credentials don't derive `Debug`.
- Wire structs use `#[serde(rename_all = "camelCase")]`. String-backed enums map to
`&'static str` in one `match`.
- Native resources are linear guards: `#[must_use]` and a `Drop` that panics unless
`std::thread::panicking()`.
## Errors
- `thiserror` everywhere, one enum per operation or module, living next to the code returning it.
- Variants are named after the layer that failed (`Network`, `Anisette`, `Parsing`, `Apple`) and
carry the source error or the offending `Dictionary`. Server failures are struct variants.
Mark the rest with `// vvv Internal errors vvv`.
- Messages are sentences: what failed, then `: {0}`, no trailing period.
- `map_err` takes a function path (`map_err(AuthError::Parsing)`). A crate result alias is welcome.
## Control flow
- No `let ... else`, and few early returns. Prefer `if`/`match` as tail expressions, tuple matches
and or-patterns (`None | Some(0) => Ok(())`).
- Shadow names through a pipeline, and annotate `let`s instead of using a turbofish.
- Combinators take function paths when one fits (`.and_then(Value::as_string)`);
use `.map(..).transpose()?`.
- One fluent chain per HTTP request, ending with `.error_for_status()?` and `.bytes().await?`, then
parsed into an annotated binding. Build plists with `dict!`/`array!` and send them with
`plist_to_body`/`dict_to_body`.
- No `.unwrap()` in library code. `expect` only for invariants, with a sentence message, and a
`// UNWRAP safety:` comment when it isn't obvious.
- Edition 2024 `unsafe` blocks wrap just the unsafe expression. Out-parameters use `MaybeUninit`.
## Layout and comments
- `rustfmt`, run per package. Long `#[error]` attributes and comments stay on one line.
- Inline format captures (`"{name}"`); `.to_string()`/`String::from`, not `.to_owned()`.
- Match arms say `TypeName::Variant`, not `Self::Variant`.
- One `use` block in rustfmt order, without nested braces; items used once go by full path.
- Flat crates: `foo.rs` plus `foo/`, never `mod.rs`; private modules re-exported with
`pub use foo::*`; files of roughly 300–500 lines.
- Short `///` docs on public entry points only, no `//!` essays or rustdoc templates.
- Inline comments are first person and informal, explaining Apple quirks and uncertainty, never
restating the code. Tags: `// TODO:`, `// HACK`, `// UNWRAP safety:`.
- Tests: inline `#[cfg(test)] mod tests { use super::*; }` with tiny mocks. Network crates get
runnable examples reading credentials from environment variables.
- Libraries rarely log (`warn!` for surprises), and never log credentials or decrypted dictionaries.