Skip to main content

Module identifiers

Module identifiers 

Source
Expand description

Domain-typed identifiers: Account, Currency, Tag, Link.

These newtype wrappers around InternedStr give the type system enough vocabulary to distinguish the different kinds of identifier the beancount AST carries. Pre-newtype, every identifier was just an InternedStr — passing an account where a currency was expected (or vice versa) compiled fine, and the bug surfaced only at runtime via wrong-but-validly-shaped string matching. Now the same mistake is a type error.

§Design

Each newtype is a transparent wrapper:

  • Deref<Target = str> so calls like account.starts_with("Assets:") work without .as_str() everywhere.
  • AsRef<str> and Borrow<str> so HashMap lookups by &str keep working (some_map.get("Assets:Bank") where the map is keyed by Account).
  • PartialEq against str / &str / String / InternedStr / the newtype’s own type, so account == "Assets:Bank" keeps reading naturally without coercion.
  • From<&str>, From<String>, From<InternedStr> for construction at call sites that have a string and need the typed form.
  • Hash delegates to the inner InternedStr’s hash, so HashMap<Account, V> and HashMap<InternedStr, V> produce the same bucketing for the same underlying string.

What you DON’T get for free is cross-newtype assignment:

fn want_currency(_: Currency) {}
let acct = Account::from("Assets:Bank");
want_currency(acct); // ← type error

Conversions between newtypes are deliberate (Currency::from(account.into_interned())) so the compiler can flag accidental crossings.

§When to use which

All four newtypes — Currency, Account, Tag, and Link — are fully plumbed through the AST, including MetaValue variants:

  • Currency: Commodity.currency, Open.currencies entries, Amount.currency, CostSpec.currency, Price.currency, IncompleteAmount::CurrencyOnly, MetaValue::Currency.
  • Account: Open.account, Close.account, Balance.account, Pad.account / source_account, Note.account, Document.account, Posting.account, MetaValue::Account.
  • Tag: Transaction.tags entries, pushtag/poptag stack, Document.tags, MetaValue::Tag.
  • Link: Transaction.links entries, Document.links, MetaValue::Link.

The plugin wire-format type rustledger_plugin_types::MetaValueData deliberately keeps String payloads — plugin-types is a minimal WASM-compatible crate that does not depend on rustledger-core, and plugins run without access to the workspace interner anyway. The convert boundary (rustledger_plugin::convert::from_wrapper) wraps the incoming strings in fresh Arc<str>s; the cross-file canonicalization to one Arc<str> per identifier string happens later in rustledger_loader::dedup::reintern_directives, which walks both AST identifier fields and MetaValue::* payloads inside metadata.

Structs§

Account
Domain-typed identifier for a beancount account name (e.g. Assets:Cash:USD). See the module docs for rationale.
AccountResolver
The resolver for an archived Account
AccountTypes
Config-aware account-type classifier.
ArchivedAccount
An archived Account
ArchivedCurrency
An archived Currency
ArchivedLink
An archived Link
ArchivedTag
An archived Tag
Currency
Domain-typed identifier for a currency code (e.g. USD, EUR, AAPL). See the module docs for rationale.
CurrencyResolver
The resolver for an archived Currency
Link
Domain-typed identifier for a beancount link (e.g. ^invoice-2024-01). See the module docs for rationale.
LinkResolver
The resolver for an archived Link
Tag
Domain-typed identifier for a beancount tag (e.g. #travel). See the module docs for rationale.
TagResolver
The resolver for an archived Tag

Enums§

AccountTypeKind
The five beancount account-type kinds, independent of their configured root names.

Constants§

ACCOUNT_TYPES
The five Beancount root account types, in declaration order.

Functions§

account_type
The lowercased root account type for account — the segment before the first : — or "unknown" if it is not one of ACCOUNT_TYPES.
is_default_account_root
Whether a bare word is one of the DEFAULT account-type roots.
is_subaccount_or_equal
Returns true if child is the same account as parent, or a sub-account of it.