/// Real-time (or near-real-time) quote snapshot for a symbol.
pub const Quote = struct {
    symbol: []const u8,
    /// Display-name storage. Inline (not a slice) so the name travels
    /// with the value: the TUI stores a `Quote` by value in tab state,
    /// and provider parsers copy the name out of transient JSON before
    /// that JSON is freed. Read via `name()`, write via `setName()`;
    /// never touch these two fields directly. The buffer is zero-filled
    /// (not `undefined`) so a Quote constructed without a name - the
    /// providers only call `setName` when one is present - still yields
    /// an empty `name()` and can never expose uninitialized bytes.
    name_buf: [256]u8 = @splat(0),
    name_len: usize = 0,
    exchange: []const u8,
    datetime: []const u8,
    close: f64,
    open: f64,
    high: f64,
    low: f64,
    volume: u64,
    previous_close: f64,
    change: f64,
    percent_change: f64,
    average_volume: u64,
    fifty_two_week_low: f64,
    fifty_two_week_high: f64,

    /// The display name, or "" when unset. Borrowed from the Quote;
    /// valid for as long as the Quote value is alive.
    pub fn name(self: *const Quote) []const u8 {
        return self.name_buf[0..self.name_len];
    }

    /// Copy `s` into the inline name buffer, truncating to capacity.
    /// Callers should pass an already-trimmed string.
    pub fn setName(self: *Quote, s: []const u8) void {
        const n = @min(s.len, self.name_buf.len);
        @memcpy(self.name_buf[0..n], s[0..n]);
        self.name_len = n;
    }
};
