Skip to main content

ferrilog_core/encode/
mod.rs

1pub mod format;
2pub mod primitives;
3pub mod strings;
4pub mod traits;
5
6pub const ENCODED_SIZE_DYNAMIC: usize = usize::MAX;
7
8pub const FORMAT_ALIGN_NONE: u8 = 0;
9pub const FORMAT_ALIGN_LEFT: u8 = 1;
10pub const FORMAT_ALIGN_RIGHT: u8 = 2;
11pub const FORMAT_ALIGN_CENTER: u8 = 3;
12pub const FORMAT_PRECISION_NONE: usize = usize::MAX;
13
14/// Trait that must be implemented by all types that can be written to the log queue.
15///
16/// Built-in types are implemented by the library; custom types can derive it
17/// via `#[derive(Encode)]`.
18///
19/// ## Three-layer type path
20///
21/// - **Layer 1 (Fast Primitive)**: i32/u64/f64/bool, etc. -- dedicated number_format
22/// - **Layer 2 (Fast String)**: &str/String -- length-prefixed encoding
23/// - **Layer 3 (General Display)**: user-defined types -- Display fallback
24pub trait Encode {
25    /// Compile-time hint for encoded byte width. Dynamic-width types keep the sentinel value.
26    const ENCODED_SIZE_HINT: usize = ENCODED_SIZE_DYNAMIC;
27
28    /// Returns the number of bytes needed to encode this value into the queue.
29    fn encoded_size(&self) -> usize;
30
31    /// Encodes the value at `buffer + offset` (hot path).
32    ///
33    /// # Safety
34    /// `buffer + offset` must have sufficient space (guaranteed by `alloc_message`).
35    unsafe fn encode(&self, buffer: *mut u8, offset: &mut usize);
36
37    /// Encodes the value at a fixed byte offset from `buffer`.
38    ///
39    /// The default implementation forwards to [`Encode::encode`] using a local
40    /// offset variable. Fixed-width types can override this to perform a direct
41    /// write at a compile-time-known payload position.
42    ///
43    /// # Safety
44    /// `buffer + offset` must have sufficient space for the encoded value.
45    #[inline(always)]
46    unsafe fn encode_at_offset(&self, buffer: *mut u8, offset: usize) {
47        let mut offset = offset;
48        unsafe {
49            <Self as Encode>::encode(self, buffer, &mut offset);
50        }
51    }
52
53    /// Decodes from `buffer + offset` and appends the formatted result to `output` (cold path).
54    ///
55    /// `format_spec` is a format specifier such as `".4"` or `"#x"`;
56    /// an empty string means the default format.
57    ///
58    /// # Safety
59    /// `buffer + offset` must point to valid encoded data.
60    unsafe fn decode_and_format(
61        buffer: *const u8,
62        offset: &mut usize,
63        output: &mut Vec<u8>,
64        format_spec: &str,
65    );
66
67    /// Decodes from `buffer + offset` and appends the formatted result.
68    ///
69    /// The default implementation forwards to [`Encode::decode_and_format`]
70    /// using a local mutable offset. Fixed-width types can override this to
71    /// perform a direct read at a compile-time-known payload position.
72    ///
73    /// # Safety
74    /// `buffer + offset` must point to valid encoded data.
75    #[inline(always)]
76    unsafe fn decode_and_format_at_offset(
77        buffer: *const u8,
78        offset: usize,
79        output: &mut Vec<u8>,
80        format_spec: &str,
81    ) {
82        let mut offset = offset;
83        unsafe {
84            <Self as Encode>::decode_and_format(buffer, &mut offset, output, format_spec);
85        }
86    }
87}
88
89/// Extreme-performance encoding path.
90///
91/// Currently selected explicitly by `log_fast!()` / `prewarm_fast!()`;
92/// only supports an empty format specifier by default.
93///
94/// # Safety
95///
96/// Implementors must guarantee that `encode_fast` writes exactly
97/// `encoded_size_fast()` bytes starting at `buffer + *offset`, and that
98/// `decode_and_append_fast` reads the same number of bytes from a buffer
99/// previously written by `encode_fast`.
100pub unsafe trait EncodeFast: Encode {
101    /// Returns the encoded byte size using the fast path (defaults to [`Encode::encoded_size`]).
102    fn encoded_size_fast(&self) -> usize {
103        <Self as Encode>::encoded_size(self)
104    }
105
106    /// Encodes the value using the fast path (defaults to [`Encode::encode`]).
107    ///
108    /// # Safety
109    /// Same requirements as [`Encode::encode`].
110    unsafe fn encode_fast(&self, buffer: *mut u8, offset: &mut usize) {
111        unsafe {
112            <Self as Encode>::encode(self, buffer, offset);
113        }
114    }
115
116    /// Encodes the value using the fast path at a fixed byte offset.
117    ///
118    /// The default implementation forwards to [`Encode::encode_at_offset`],
119    /// which lets fixed-width types benefit from compile-time layout
120    /// specialization without duplicating logic.
121    ///
122    /// # Safety
123    /// Same requirements as [`Encode::encode_at_offset`].
124    #[inline(always)]
125    unsafe fn encode_fast_at_offset(&self, buffer: *mut u8, offset: usize) {
126        unsafe {
127            <Self as Encode>::encode_at_offset(self, buffer, offset);
128        }
129    }
130
131    /// Decodes and appends using the fast path with an empty format specifier
132    /// (defaults to [`Encode::decode_and_format`]).
133    ///
134    /// # Safety
135    /// Same requirements as [`Encode::decode_and_format`].
136    unsafe fn decode_and_append_fast(buffer: *const u8, offset: &mut usize, output: &mut Vec<u8>) {
137        unsafe {
138            <Self as Encode>::decode_and_format(buffer, offset, output, "");
139        }
140    }
141
142    /// Decodes and appends using the fast path from `buffer + offset`.
143    ///
144    /// The default implementation forwards to [`EncodeFast::decode_and_append_fast`]
145    /// using a local mutable offset.
146    ///
147    /// # Safety
148    /// Same requirements as [`EncodeFast::decode_and_append_fast`].
149    #[inline(always)]
150    unsafe fn decode_and_append_fast_at_offset(
151        buffer: *const u8,
152        offset: usize,
153        output: &mut Vec<u8>,
154    ) {
155        let mut offset = offset;
156        unsafe {
157            <Self as EncodeFast>::decode_and_append_fast(buffer, &mut offset, output);
158        }
159    }
160}
161
162// Re-export everything that was previously public from this module.
163pub use format::{VecWriter, append_display_const_default, append_display_with_spec};
164pub use traits::{
165    EncodeBinary, EncodeConstBinaryFormat, EncodeConstDefaultFormat, EncodeConstFloatFormat,
166    EncodeConstLowerHexFormat, EncodeConstOctalFormat, EncodeConstUpperHexFormat, EncodeLowerHex,
167    EncodeOctal, EncodeUpperHex,
168};