Skip to main content

nautilus_common/
enums.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2026 Nautech Systems Pty Ltd. All rights reserved.
3//  https://nautechsystems.io
4//
5//  Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6//  You may not use this file except in compliance with the License.
7//  You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9//  Unless required by applicable law or agreed to in writing, software
10//  distributed under the License is distributed on an "AS IS" BASIS,
11//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//  See the License for the specific language governing permissions and
13//  limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16//! Enumerations for common components.
17
18use log::Level;
19use serde::{Deserialize, Serialize};
20use strum::{Display, EnumIter, EnumString, FromRepr};
21
22/// The state of a component within the system.
23#[repr(C)]
24#[derive(
25    Copy,
26    Clone,
27    Debug,
28    Default,
29    Display,
30    Hash,
31    PartialEq,
32    Eq,
33    PartialOrd,
34    Ord,
35    FromRepr,
36    EnumIter,
37    EnumString,
38    Serialize,
39    Deserialize,
40)]
41#[strum(ascii_case_insensitive)]
42#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
43#[cfg_attr(
44    feature = "python",
45    pyo3::pyclass(
46        frozen,
47        eq,
48        eq_int,
49        module = "nautilus_trader.core.nautilus_pyo3.common.enums",
50        from_py_object,
51        rename_all = "SCREAMING_SNAKE_CASE",
52    )
53)]
54#[cfg_attr(
55    feature = "python",
56    pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.common")
57)]
58pub enum ComponentState {
59    /// When a component is instantiated, but not yet ready to fulfill its specification.
60    #[default]
61    PreInitialized = 0,
62    /// When a component is able to be started.
63    Ready = 1,
64    /// When a component is executing its actions on `start`.
65    Starting = 2,
66    /// When a component is operating normally and can fulfill its specification.
67    Running = 3,
68    /// When a component is executing its actions on `stop`.
69    Stopping = 4,
70    /// When a component has successfully stopped.
71    Stopped = 5,
72    /// When a component is started again after its initial start.
73    Resuming = 6,
74    /// When a component is executing its actions on `reset`.
75    Resetting = 7,
76    /// When a component is executing its actions on `dispose`.
77    Disposing = 8,
78    /// When a component has successfully shut down and released all of its resources.
79    Disposed = 9,
80    /// When a component is executing its actions on `degrade`.
81    Degrading = 10,
82    /// When a component has successfully degraded and may not meet its full specification.
83    Degraded = 11,
84    /// When a component is executing its actions on `fault`.
85    Faulting = 12,
86    /// When a component has successfully shut down due to a detected fault.
87    Faulted = 13,
88}
89
90impl ComponentState {
91    pub fn variant_name(&self) -> String {
92        let s = self.to_string();
93        format!("{}{}", s[0..1].to_uppercase(), s[1..].to_lowercase())
94    }
95}
96
97/// A trigger condition for a component within the system.
98#[repr(C)]
99#[derive(
100    Copy,
101    Clone,
102    Debug,
103    Display,
104    Hash,
105    PartialEq,
106    Eq,
107    PartialOrd,
108    Ord,
109    FromRepr,
110    EnumIter,
111    EnumString,
112    Serialize,
113    Deserialize,
114)]
115#[strum(ascii_case_insensitive)]
116#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
117#[cfg_attr(
118    feature = "python",
119    pyo3::pyclass(
120        frozen,
121        eq,
122        eq_int,
123        module = "nautilus_trader.core.nautilus_pyo3.common.enums",
124        from_py_object,
125        rename_all = "SCREAMING_SNAKE_CASE",
126    )
127)]
128#[cfg_attr(
129    feature = "python",
130    pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.common")
131)]
132pub enum ComponentTrigger {
133    /// A trigger for the component to initialize.
134    Initialize = 1,
135    /// A trigger for the component to start.
136    Start = 2,
137    /// A trigger when the component has successfully started.
138    StartCompleted = 3,
139    /// A trigger for the component to stop.
140    Stop = 4,
141    /// A trigger when the component has successfully stopped.
142    StopCompleted = 5,
143    /// A trigger for the component to resume (after being stopped).
144    Resume = 6,
145    /// A trigger when the component has successfully resumed.
146    ResumeCompleted = 7,
147    /// A trigger for the component to reset.
148    Reset = 8,
149    /// A trigger when the component has successfully reset.
150    ResetCompleted = 9,
151    /// A trigger for the component to dispose and release resources.
152    Dispose = 10,
153    /// A trigger when the component has successfully disposed.
154    DisposeCompleted = 11,
155    /// A trigger for the component to degrade.
156    Degrade = 12,
157    /// A trigger when the component has successfully degraded.
158    DegradeCompleted = 13,
159    /// A trigger for the component to fault.
160    Fault = 14,
161    /// A trigger when the component has successfully faulted.
162    FaultCompleted = 15,
163}
164
165/// Represents the environment context for a Nautilus system.
166#[repr(C)]
167#[derive(
168    Copy,
169    Clone,
170    Debug,
171    Display,
172    Hash,
173    PartialEq,
174    Eq,
175    PartialOrd,
176    Ord,
177    FromRepr,
178    EnumIter,
179    EnumString,
180    Serialize,
181    Deserialize,
182)]
183#[strum(ascii_case_insensitive)]
184#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
185#[cfg_attr(
186    feature = "python",
187    pyo3::pyclass(
188        frozen,
189        eq,
190        eq_int,
191        module = "nautilus_trader.core.nautilus_pyo3.common.enums",
192        from_py_object,
193        rename_all = "SCREAMING_SNAKE_CASE",
194    )
195)]
196#[cfg_attr(
197    feature = "python",
198    pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.common")
199)]
200pub enum Environment {
201    Backtest,
202    Sandbox,
203    Live,
204}
205
206/// The log level for log messages.
207#[repr(C)]
208#[derive(
209    Copy,
210    Clone,
211    Debug,
212    Display,
213    Hash,
214    PartialEq,
215    Eq,
216    PartialOrd,
217    Ord,
218    FromRepr,
219    EnumIter,
220    EnumString,
221    Serialize,
222    Deserialize,
223)]
224#[strum(ascii_case_insensitive)]
225#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
226#[cfg_attr(
227    feature = "python",
228    pyo3::pyclass(
229        frozen,
230        eq,
231        eq_int,
232        module = "nautilus_trader.core.nautilus_pyo3.common.enums",
233        from_py_object,
234        rename_all = "SCREAMING_SNAKE_CASE",
235    )
236)]
237#[cfg_attr(
238    feature = "python",
239    pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.common")
240)]
241pub enum LogLevel {
242    /// The **OFF** log level. A level lower than all other log levels (off).
243    #[strum(serialize = "OFF")]
244    #[serde(rename = "OFF")]
245    Off = 0,
246    /// The **TRACE** log level. Only available in Rust for debug/development builds.
247    #[strum(serialize = "TRACE")]
248    #[serde(rename = "TRACE")]
249    Trace = 1,
250    /// The **DEBUG** log level.
251    #[strum(serialize = "DEBUG")]
252    #[serde(rename = "DEBUG")]
253    Debug = 2,
254    /// The **INFO** log level.
255    #[strum(serialize = "INFO")]
256    #[serde(rename = "INFO")]
257    Info = 3,
258    /// The **WARNING** log level.
259    #[strum(serialize = "WARN", serialize = "WARNING")]
260    #[serde(rename = "WARNING")]
261    Warning = 4,
262    /// The **ERROR** log level.
263    #[strum(serialize = "ERROR")]
264    #[serde(rename = "ERROR")]
265    Error = 5,
266}
267
268/// The log color for log messages.
269#[repr(C)]
270#[derive(
271    Copy,
272    Clone,
273    Debug,
274    Display,
275    Hash,
276    PartialEq,
277    Eq,
278    PartialOrd,
279    Ord,
280    FromRepr,
281    EnumIter,
282    EnumString,
283    Serialize,
284    Deserialize,
285)]
286#[strum(ascii_case_insensitive)]
287#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
288#[cfg_attr(
289    feature = "python",
290    pyo3::pyclass(
291        frozen,
292        eq,
293        eq_int,
294        module = "nautilus_trader.core.nautilus_pyo3.common.enums",
295        from_py_object,
296        rename_all = "SCREAMING_SNAKE_CASE",
297    )
298)]
299#[cfg_attr(
300    feature = "python",
301    pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.common")
302)]
303pub enum LogColor {
304    /// The default/normal log color.
305    #[strum(serialize = "NORMAL")]
306    Normal = 0,
307    /// The green log color, typically used with [`LogLevel::Info`] log levels and associated with success events.
308    #[strum(serialize = "GREEN")]
309    Green = 1,
310    /// The blue log color, typically used with [`LogLevel::Info`] log levels and associated with user actions.
311    #[strum(serialize = "BLUE")]
312    Blue = 2,
313    /// The magenta log color, typically used with [`LogLevel::Info`] log levels.
314    #[strum(serialize = "MAGENTA")]
315    Magenta = 3,
316    /// The cyan log color, typically used with [`LogLevel::Info`] log levels.
317    #[strum(serialize = "CYAN")]
318    Cyan = 4,
319    /// The yellow log color, typically used with [`LogLevel::Warning`] log levels.
320    #[strum(serialize = "YELLOW")]
321    Yellow = 5,
322    /// The red log color, typically used with [`LogLevel::Error`] level.
323    #[strum(serialize = "RED")]
324    Red = 6,
325}
326
327impl LogColor {
328    #[must_use]
329    pub const fn as_ansi(&self) -> &str {
330        match *self {
331            Self::Normal => "",
332            Self::Green => "\x1b[92m",
333            Self::Blue => "\x1b[94m",
334            Self::Magenta => "\x1b[35m",
335            Self::Cyan => "\x1b[36m",
336            Self::Yellow => "\x1b[1;33m",
337            Self::Red => "\x1b[1;31m",
338        }
339    }
340}
341
342impl From<u8> for LogColor {
343    fn from(value: u8) -> Self {
344        match value {
345            1 => Self::Green,
346            2 => Self::Blue,
347            3 => Self::Magenta,
348            4 => Self::Cyan,
349            5 => Self::Yellow,
350            6 => Self::Red,
351            _ => Self::Normal,
352        }
353    }
354}
355
356impl From<Level> for LogColor {
357    fn from(value: Level) -> Self {
358        match value {
359            Level::Error => Self::Red,
360            Level::Warn => Self::Yellow,
361            Level::Info => Self::Normal,
362            Level::Debug => Self::Normal,
363            Level::Trace => Self::Normal,
364        }
365    }
366}
367
368/// An ANSI log line format specifier.
369/// This is used for formatting log messages with ANSI escape codes.
370#[repr(C)]
371#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, FromRepr, EnumString, Display)]
372#[strum(ascii_case_insensitive)]
373#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
374#[cfg_attr(
375    feature = "python",
376    pyo3::pyclass(
377        frozen,
378        eq,
379        eq_int,
380        module = "nautilus_trader.core.nautilus_pyo3.common.enums",
381        from_py_object,
382        rename_all = "SCREAMING_SNAKE_CASE",
383    )
384)]
385#[cfg_attr(
386    feature = "python",
387    pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.common")
388)]
389pub enum LogFormat {
390    /// Header log format. This ANSI escape code is used for magenta text color,
391    /// often used for headers or titles in the log output.
392    #[strum(serialize = "\x1b[95m")]
393    Header,
394
395    /// Endc log format. This ANSI escape code is used to reset all format attributes
396    /// to their defaults. It should be used after applying other formats.
397    #[strum(serialize = "\x1b[0m")]
398    Endc,
399
400    /// Bold log format. This ANSI escape code is used to make the text bold in the log output.
401    #[strum(serialize = "\x1b[1m")]
402    Bold,
403
404    /// Underline log format. This ANSI escape code is used to underline the text in the log output.
405    #[strum(serialize = "\x1b[4m")]
406    Underline,
407}
408
409/// The serialization encoding.
410#[repr(C)]
411#[derive(
412    Copy,
413    Clone,
414    Debug,
415    Default,
416    Display,
417    Hash,
418    PartialEq,
419    Eq,
420    PartialOrd,
421    Ord,
422    FromRepr,
423    EnumIter,
424    EnumString,
425    Serialize,
426    Deserialize,
427)]
428#[strum(ascii_case_insensitive)]
429#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
430#[cfg_attr(
431    feature = "python",
432    pyo3::pyclass(
433        frozen,
434        eq,
435        eq_int,
436        module = "nautilus_trader.core.nautilus_pyo3.common.enums",
437        from_py_object,
438        rename_all = "SCREAMING_SNAKE_CASE",
439    )
440)]
441#[cfg_attr(
442    feature = "python",
443    pyo3_stub_gen::derive::gen_stub_pyclass_enum(module = "nautilus_trader.common")
444)]
445pub enum SerializationEncoding {
446    /// The JavaScript Object Notation (JSON) encoding.
447    #[default]
448    #[serde(rename = "json")]
449    Json = 0,
450    /// The MessagePack encoding.
451    #[serde(rename = "msgpack")]
452    MsgPack = 1,
453    /// The Cap'n Proto encoding.
454    #[serde(rename = "capnp")]
455    Capnp = 2,
456    /// The Simple Binary Encoding (SBE) encoding.
457    #[serde(rename = "sbe")]
458    Sbe = 3,
459}
460
461#[cfg(test)]
462mod tests {
463    use rstest::rstest;
464
465    use super::SerializationEncoding;
466
467    #[rstest]
468    fn serialization_encoding_default_is_json() {
469        assert_eq!(
470            SerializationEncoding::default(),
471            SerializationEncoding::Json
472        );
473    }
474
475    #[rstest]
476    fn serialization_encoding_repr_values_are_stable() {
477        assert_eq!(SerializationEncoding::Json as u8, 0);
478        assert_eq!(SerializationEncoding::MsgPack as u8, 1);
479        assert_eq!(SerializationEncoding::Capnp as u8, 2);
480        assert_eq!(SerializationEncoding::Sbe as u8, 3);
481    }
482}