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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//! Callback trait and iterator context for training and inference sessions.
//!
//! Port provenance: `oa/core/callback.h`, `oa/core/iterator.h`.
//!
//! [`Callback`] is the Keras-style hook interface used by `TrainingLoop` and
//! any future `ItBatch` / `ItInference` session types. All three methods have
//! default no-op implementations so callers only override what they need.
//!
//! [`IteratorContext`] is a thin object-safe view of the current iterator
//! state that callbacks receive. Decoupled from the concrete session type so
//! that callback code does not need to name it.
//!
//! # Usage
//!
//! ```rust,ignore
//! use oa::{Callback, IteratorContext};
//!
//! struct PrintProgress;
//!
//! impl Callback for PrintProgress {
//! fn on_step(&mut self, ctx: &dyn IteratorContext) {
//! if ctx.index() % 100 == 0 {
//! println!("step {}/{}", ctx.index(), ctx.total().unwrap_or(0));
//! }
//! }
//! }
//! ```
// ─── IteratorContext ──────────────────────────────────────────────────────────
/// Object-safe view of an iterator's current state, passed to every [`Callback`]
/// hook.
///
/// The concrete iterator (e.g. `TrainingLoop`) implements this privately; the
/// callback only needs the interface.
// ─── Callback ─────────────────────────────────────────────────────────────────
/// Keras-style hook interface for OA iterator sessions.
///
/// Attach one or more callbacks to a session via its `add_callback` method.
/// All hooks receive a `&dyn IteratorContext` so callbacks stay decoupled from
/// the concrete session type.
///
/// # Mapping from C++
///
/// | C++ | Rust |
/// |---------------------------|----------------------------|
/// | `onBegin(Iterator&)` | `on_begin(&mut self, ctx)` |
/// | `onStep(Iterator&)` | `on_step(&mut self, ctx)` |
/// | `onEnd(Iterator&)` | `on_end(&mut self, ctx)` |
///
/// C++ used virtual inheritance; Rust uses dynamic dispatch through `Box<dyn Callback>`.
/// The C++ move-constructor convention maps to Rust's normal ownership — place
/// `Box<dyn Callback>` values in a `Vec` rather than raw pointers.
// ─── CallbackSet ─────────────────────────────────────────────────────────────
/// Ordered list of [`Callback`] objects attached to a session.
///
/// Callbacks fire in insertion order. This mirrors `oa::Iterator::addCallback`
/// but is an explicit value rather than a virtual base member so the concrete
/// session type can own it directly.