Skip to content

Commit 3a8b1c1

Browse files
committed
REF: Use optional in DBN metadata
1 parent a60ca8c commit 3a8b1c1

File tree

13 files changed

+57
-60
lines changed

13 files changed

+57
-60
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
`HistoricalClient::TimeseriesGetRangeToFile()` to a `std::filesystem::path`
1010
- Changed the type of the `file_path` parameter in the `DbnFileStore`, `InFileStream`,
1111
and `OutFileStream` constructors to a `std::filesystem::path`
12+
- Made `stype_in` and `schema` optionals in `Metadata` to align with how
13+
`Metadata` is represented in other languages and removed the boolean
14+
`has_mixed_stype_in` and `has_mixed_schema` fields
1215

1316
## 0.36.0 - 2025-05-27
1417

include/databento/dbn.hpp

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <date/date.h>
44

55
#include <cstdint>
6+
#include <optional>
67
#include <ostream>
78
#include <string>
89
#include <vector>
@@ -37,12 +38,10 @@ struct Metadata {
3738
std::uint8_t version;
3839
// The dataset code.
3940
std::string dataset;
40-
// Indicates the DBN stream may contain multiple record types and data
41-
// schemas. If true, the schema field should be ignored.
42-
bool has_mixed_schema;
43-
// The data record schema which affects the type record of present. If
44-
// has_mixed_schema is true, this field should be ignored.
45-
Schema schema;
41+
// The data record schema which affects the type record of present. Will be
42+
// nullopt for live where there can be a mix of `schema`s across
43+
// subscriptions.
44+
std::optional<Schema> schema;
4645
// The UNIX timestamp of the query start, or the first record if the file was
4746
// split.
4847
UnixNanos start;
@@ -51,12 +50,9 @@ struct Metadata {
5150
UnixNanos end;
5251
// The maximum number of records for the query.
5352
std::uint64_t limit;
54-
// Indicates the DBN stream may been create with a mix of stype_in. This
55-
// will always be the case for live data where stype_in is specified per
56-
// subscription.
57-
bool has_mixed_stype_in;
58-
// The input symbology type. Should be ignored if has_mixed_schemas is true.
59-
SType stype_in;
53+
// The input symbology type. Will be nullopt for live data where there can be
54+
// a mix of `stype_in`s across subscriptions.
55+
std::optional<SType> stype_in;
6056
// The output symbology type.
6157
SType stype_out;
6258
// Whether the records contain an appended send timestamp.
@@ -105,13 +101,10 @@ inline bool operator!=(const SymbolMapping& lhs, const SymbolMapping& rhs) {
105101

106102
inline bool operator==(const Metadata& lhs, const Metadata& rhs) {
107103
return lhs.version == rhs.version && lhs.dataset == rhs.dataset &&
108-
(lhs.has_mixed_schema ? rhs.has_mixed_schema
109-
: lhs.schema == rhs.schema) &&
110-
lhs.start == rhs.start && lhs.end == rhs.end &&
111-
lhs.limit == rhs.limit &&
112-
(lhs.has_mixed_stype_in ? rhs.has_mixed_stype_in
113-
: lhs.stype_in == rhs.stype_in) &&
114-
lhs.stype_out == rhs.stype_out && lhs.ts_out == rhs.ts_out &&
104+
lhs.schema == rhs.schema && lhs.start == rhs.start &&
105+
lhs.end == rhs.end && lhs.limit == rhs.limit &&
106+
lhs.stype_in == rhs.stype_in && lhs.stype_out == rhs.stype_out &&
107+
lhs.ts_out == rhs.ts_out &&
115108
lhs.symbol_cstr_len == rhs.symbol_cstr_len &&
116109
lhs.symbols == rhs.symbols && lhs.partial == rhs.partial &&
117110
lhs.not_found == rhs.not_found && lhs.mappings == rhs.mappings;

src/dbn.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,10 @@ std::ostream& operator<<(std::ostream& stream, const Metadata& metadata) {
3434
.Build()
3535
.AddField("version", metadata.version)
3636
.AddField("dataset", metadata.dataset)
37-
.AddField("has_mixed_schema", metadata.has_mixed_schema)
3837
.AddField("schema", metadata.schema)
3938
.AddField("start", metadata.start)
4039
.AddField("end", metadata.end)
4140
.AddField("limit", metadata.limit)
42-
.AddField("has_mixed_stype_in", metadata.has_mixed_stype_in)
4341
.AddField("stype_in", metadata.stype_in)
4442
.AddField("stype_out", metadata.stype_out)
4543
.AddField("ts_out", metadata.ts_out)

src/dbn_decoder.cpp

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include <algorithm> // copy
66
#include <cstring> // strncmp
7+
#include <optional>
78
#include <vector>
89

910
#include "databento/compat.hpp"
@@ -121,12 +122,9 @@ databento::Metadata DbnDecoder::DecodeMetadataFields(
121122
res.dataset = Consume(buffer, kDatasetCstrLen, "dataset");
122123
const auto raw_schema = Consume<std::uint16_t>(buffer);
123124
if (raw_schema == kNullSchema) {
124-
res.has_mixed_schema = true;
125-
// must initialize
126-
res.schema = Schema::Mbo;
125+
res.schema = std::nullopt;
127126
} else {
128-
res.has_mixed_schema = false;
129-
res.schema = static_cast<Schema>(raw_schema);
127+
res.schema = {static_cast<Schema>(raw_schema)};
130128
}
131129
res.start =
132130
UnixNanos{std::chrono::nanoseconds{Consume<std::uint64_t>(buffer)}};
@@ -138,12 +136,9 @@ databento::Metadata DbnDecoder::DecodeMetadataFields(
138136
}
139137
const auto raw_stype_in = Consume<std::uint8_t>(buffer);
140138
if (raw_stype_in == kNullSType) {
141-
res.has_mixed_stype_in = true;
142-
// must initialize
143-
res.stype_in = SType::InstrumentId;
139+
res.stype_in = std::nullopt;
144140
} else {
145-
res.has_mixed_stype_in = false;
146-
res.stype_in = static_cast<SType>(raw_stype_in);
141+
res.stype_in = {static_cast<SType>(raw_stype_in)};
147142
}
148143
res.stype_out = static_cast<SType>(Consume<std::uint8_t>(buffer));
149144
res.ts_out = static_cast<bool>(Consume<std::uint8_t>(buffer));

src/dbn_encoder.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,10 @@ void DbnEncoder::EncodeMetadata(const Metadata& metadata, IWritable* output) {
9494
const auto [length, end_padding] = CalcLength(metadata);
9595
EncodeAsBytes(length, output);
9696
EncodeFixedLenCStr(kDatasetCstrLen, metadata.dataset, output);
97-
if (metadata.has_mixed_schema) {
98-
EncodeAsBytes(kNullSchema, output);
97+
if (metadata.schema.has_value()) {
98+
EncodeAsBytes(*metadata.schema, output);
9999
} else {
100-
EncodeAsBytes(metadata.schema, output);
100+
EncodeAsBytes(kNullSchema, output);
101101
}
102102
EncodeAsBytes(metadata.start, output);
103103
EncodeAsBytes(metadata.end, output);
@@ -106,10 +106,10 @@ void DbnEncoder::EncodeMetadata(const Metadata& metadata, IWritable* output) {
106106
// backwards compatibility for record_count
107107
EncodeAsBytes(kNullRecordCount, output);
108108
}
109-
if (metadata.has_mixed_stype_in) {
110-
EncodeAsBytes(kNullSType, output);
109+
if (metadata.stype_in.has_value()) {
110+
EncodeAsBytes(*metadata.stype_in, output);
111111
} else {
112-
EncodeAsBytes(metadata.stype_in, output);
112+
EncodeAsBytes(kNullSType, output);
113113
}
114114
EncodeAsBytes(metadata.stype_out, output);
115115
EncodeAsBytes(static_cast<std::uint8_t>(metadata.ts_out), output);

src/stream_op_helper.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <cstring> // strlen
66
#include <iomanip> // quoted
77
#include <ios> // boolalpha
8+
#include <optional>
89
#include <ostream> // ostream
910
#include <sstream> // stringstream
1011
#include <string>
@@ -56,6 +57,15 @@ class StreamOpHelper {
5657

5758
void FmtToStream(const std::ostringstream& val) { stream_ << val.str(); }
5859

60+
template <typename T>
61+
void FmtToStream(const std::optional<T>& val) {
62+
if (val.has_value()) {
63+
stream_ << *val;
64+
} else {
65+
stream_ << "nullopt";
66+
}
67+
}
68+
5969
template <std::size_t N>
6070
void FmtToStream(const std::array<char, N>& val) {
6171
stream_ << '"';

src/symbol_map.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ using databento::TsSymbolMap;
1414

1515
namespace {
1616
bool IsInverse(const databento::Metadata& metadata) {
17-
if (!metadata.has_mixed_stype_in) {
18-
if (metadata.stype_in == databento::SType::InstrumentId) {
17+
if (metadata.stype_in.has_value()) {
18+
if (*metadata.stype_in == databento::SType::InstrumentId) {
1919
return true;
2020
}
2121
if (metadata.stype_out == databento::SType::InstrumentId) {

tests/src/dbn_encoder_tests.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,10 @@ TEST(DbnEncoderTests, TestEncodeDecodeMetadataIdentity) {
1818
const Metadata metadata{
1919
kDbnVersion,
2020
dataset::kGlbxMdp3,
21-
false,
2221
Schema::Mbp10,
2322
UnixNanos{std::chrono::nanoseconds{1657230820000000000}},
2423
UnixNanos{std::chrono::nanoseconds{1658960170000000000}},
2524
0,
26-
false,
2725
SType::RawSymbol,
2826
SType::InstrumentId,
2927
true,

tests/src/dbn_tests.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,10 @@ TEST(DbnTests, TestMetadataToString) {
1111
const Metadata target{
1212
kDbnVersion,
1313
dataset::kGlbxMdp3,
14-
false,
1514
Schema::Ohlcv1D,
1615
UnixNanos{std::chrono::seconds{1696959347}},
1716
UnixNanos{std::chrono::seconds{1696950000}},
1817
{},
19-
false,
2018
SType::RawSymbol,
2119
SType::InstrumentId,
2220
false,
@@ -30,12 +28,10 @@ TEST(DbnTests, TestMetadataToString) {
3028
ASSERT_EQ(res, R"(Metadata {
3129
version = 3,
3230
dataset = "GLBX.MDP3",
33-
has_mixed_schema = false,
3431
schema = ohlcv-1d,
3532
start = 2023-10-10T17:35:47.000000000Z,
3633
end = 2023-10-10T15:00:00.000000000Z,
3734
limit = 0,
38-
has_mixed_stype_in = false,
3935
stype_in = raw_symbol,
4036
stype_out = instrument_id,
4137
ts_out = false,

tests/src/live_blocking_tests.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ TEST_F(LiveBlockingTests, TestStartAndUpgrade) {
7777
.BuildBlocking();
7878
const auto metadata = target.Start();
7979
EXPECT_EQ(metadata.version, exp_version);
80-
EXPECT_TRUE(metadata.has_mixed_schema);
80+
EXPECT_FALSE(metadata.schema.has_value());
8181
EXPECT_EQ(metadata.dataset, dataset::kGlbxMdp3);
8282
}
8383
}
@@ -557,7 +557,7 @@ TEST_F(LiveBlockingTests, TestReconnectAndResubscribe) {
557557
ASSERT_TRUE(std::holds_alternative<LiveSubscription::NoStart>(
558558
target.Subscriptions()[0].start));
559559
const auto metadata = target.Start();
560-
EXPECT_TRUE(metadata.has_mixed_schema);
560+
EXPECT_FALSE(metadata.schema.has_value());
561561
const auto rec2 = target.NextRecord();
562562
ASSERT_TRUE(rec2.Holds<TradeMsg>());
563563
ASSERT_EQ(rec2.Get<TradeMsg>(), kRec);

0 commit comments

Comments
 (0)