diff --git a/CHANGELOG.md b/CHANGELOG.md index 28ac3b3..44da036 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## 0.24.0 - 2024-12-10 + +### Enhancements +- Upgraded `async-compression` version to 0.4.18 +- Upgraded `proc-macro2` version to 1.0.92 + +### Breaking changes +- Changed async DBN decoding to return `Ok(None)` when an incomplete record remains in + the stream. This matches the existing behavior of sync DBN decoding + +### Bug fixes +- Added handling for `UNDEF_TIMESTAMP` in `pretty_` timestamp getters for Python. They + now return `None` in the case of `UNDEF_TIMESTAMP` + ## 0.23.1 - 2024-11-12 ### Enhancements diff --git a/Cargo.lock b/Cargo.lock index 35297f5..b59db23 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -28,9 +28,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.15" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -43,43 +43,43 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.52.0", + "windows-sys", ] [[package]] name = "anstyle-wincon" -version = "3.0.4" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] name = "anyhow" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" +checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" [[package]] name = "assert_cmd" @@ -99,9 +99,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.17" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cb8f1d480b0ea3783ab015936d2a55c87e219676f0c0b7dec61494043f21857" +checksum = "df895a515f70646414f4b45c0b79082783b80552b373a68283012928df56f522" dependencies = [ "futures-core", "memchr", @@ -140,9 +140,9 @@ checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bstr" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" +checksum = "1a68f1f47cdf0ec8ee4b941b2eee2a80cb796db73118c0dd09ac63fbe405be22" dependencies = [ "memchr", "regex-automata", @@ -151,9 +151,9 @@ dependencies = [ [[package]] name = "bytes" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "cbindgen" @@ -168,16 +168,16 @@ dependencies = [ "quote", "serde", "serde_json", - "syn 2.0.87", + "syn 2.0.90", "tempfile", "toml", ] [[package]] name = "cc" -version = "1.1.31" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" +checksum = "27f657647bcff5394bf56c7317665bbf790a137a50eaaa5c6bfbb9e27a518f2d" dependencies = [ "jobserver", "libc", @@ -192,9 +192,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.5.20" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" dependencies = [ "clap_builder", "clap_derive", @@ -202,9 +202,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.20" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" dependencies = [ "anstream", "anstyle", @@ -222,26 +222,26 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "colorchoice" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "csv" -version = "1.3.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" +checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" dependencies = [ "csv-core", "itoa", @@ -260,7 +260,7 @@ dependencies = [ [[package]] name = "databento-dbn" -version = "0.23.1" +version = "0.24.0" dependencies = [ "dbn", "pyo3", @@ -271,7 +271,7 @@ dependencies = [ [[package]] name = "dbn" -version = "0.23.1" +version = "0.24.0" dependencies = [ "async-compression", "csv", @@ -293,7 +293,7 @@ dependencies = [ [[package]] name = "dbn-c" -version = "0.23.1" +version = "0.24.0" dependencies = [ "anyhow", "cbindgen", @@ -303,7 +303,7 @@ dependencies = [ [[package]] name = "dbn-cli" -version = "0.23.1" +version = "0.24.0" dependencies = [ "anyhow", "assert_cmd", @@ -318,14 +318,14 @@ dependencies = [ [[package]] name = "dbn-macros" -version = "0.23.1" +version = "0.24.0" dependencies = [ "csv", "dbn", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", "trybuild", ] @@ -359,12 +359,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] @@ -375,9 +375,9 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fastrand" -version = "2.1.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "float-cmp" @@ -444,7 +444,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -497,9 +497,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "hashbrown" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "heck" @@ -515,9 +515,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", "hashbrown", @@ -537,9 +537,9 @@ checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jobserver" @@ -562,9 +562,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.162" +version = "0.2.168" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" +checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" [[package]] name = "linux-raw-sys" @@ -650,7 +650,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -670,9 +670,9 @@ checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -688,9 +688,9 @@ checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "portable-atomic" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" +checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" [[package]] name = "powerfmt" @@ -739,9 +739,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -793,7 +793,7 @@ dependencies = [ "proc-macro2", "pyo3-macros-backend", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -806,7 +806,7 @@ dependencies = [ "proc-macro2", "pyo3-build-config", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -820,9 +820,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -832,9 +832,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -879,7 +879,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.87", + "syn 2.0.90", "unicode-ident", ] @@ -900,15 +900,15 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.40" +version = "0.38.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0" +checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] @@ -931,29 +931,29 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.213" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ea7893ff5e2466df8d720bb615088341b295f849602c6956047f8f80f0e9bc1" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.213" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e85ad2009c50b58e87caa8cd6dac16bdf511bbfb7af6c33df902396aa480fa5" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] name = "serde_json" -version = "1.0.132" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", "memchr", @@ -1010,7 +1010,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1026,9 +1026,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.87" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -1057,7 +1057,7 @@ dependencies = [ "fastrand", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys", ] [[package]] @@ -1071,12 +1071,12 @@ dependencies = [ [[package]] name = "terminal_size" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f599bd7ca042cfdf8f4512b277c02ba102247820f9d9d4a9f521f496751a6ef" +checksum = "5352447f921fda68cf61b4101566c0bdb5104eff6804d0678e5227580ab6a4e9" dependencies = [ "rustix", - "windows-sys 0.59.0", + "windows-sys", ] [[package]] @@ -1087,29 +1087,29 @@ checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" [[package]] name = "thiserror" -version = "2.0.3" +version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" +checksum = "8fec2a1820ebd077e2b90c4df007bebf344cd394098a13c563957d0afc83ea47" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.3" +version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" +checksum = "d65750cab40f4ff1929fb1ba509e9914eb756131cef4210da8d5d700d26f6312" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] name = "time" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ "deranged", "itoa", @@ -1128,9 +1128,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" dependencies = [ "num-conv", "time-core", @@ -1138,9 +1138,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.41.0" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" dependencies = [ "backtrace", "bytes", @@ -1156,7 +1156,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.90", ] [[package]] @@ -1231,9 +1231,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unindent" @@ -1262,16 +1262,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", + "windows-sys", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index b3043fb..ea7a69f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,13 +11,13 @@ resolver = "2" [workspace.package] authors = ["Databento "] edition = "2021" -version = "0.23.1" +version = "0.24.0" documentation = "https://databento.com/docs" repository = "https://github.com/databento/dbn" license = "Apache-2.0" [workspace.dependencies] -anyhow = "1.0.93" +anyhow = "1.0.94" csv = "1.3" pyo3 = "0.22.6" pyo3-build-config = "0.22.6" diff --git a/c/Cargo.toml b/c/Cargo.toml index 317163b..4d72a56 100644 --- a/c/Cargo.toml +++ b/c/Cargo.toml @@ -16,7 +16,7 @@ crate-type = ["staticlib"] [dependencies] anyhow = { workspace = true } dbn = { path = "../rust/dbn", features = [] } -libc = "0.2.162" +libc = "0.2.168" [build-dependencies] cbindgen = { version = "0.27.0", default-features = false } diff --git a/c/src/decode.rs b/c/src/decode.rs index 45beb58..af4f9f0 100644 --- a/c/src/decode.rs +++ b/c/src/decode.rs @@ -54,7 +54,7 @@ pub unsafe extern "C" fn DbnDecoder_metadata(decoder: *mut Decoder) -> *const Me #[no_mangle] pub unsafe extern "C" fn DbnDecoder_decode(decoder: *mut Decoder) -> *const RecordHeader { if let Some(Ok(Some(rec))) = decoder.as_mut().map(|d| d.decode_record_ref()) { - return rec.header(); + rec.header() } else { null() } diff --git a/python/pyproject.toml b/python/pyproject.toml index da4960b..f2bc4fe 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "databento-dbn" -version = "0.23.1" +version = "0.24.0" description = "Python bindings for encoding and decoding Databento Binary Encoding (DBN)" authors = ["Databento "] license = "Apache-2.0" @@ -17,7 +17,7 @@ build-backend = "maturin" [project] name = "databento-dbn" -version = "0.23.1" +version = "0.24.0" authors = [ { name = "Databento", email = "support@databento.com" } ] diff --git a/python/python/databento_dbn/_lib.pyi b/python/python/databento_dbn/_lib.pyi index d23ca22..74cf886 100644 --- a/python/python/databento_dbn/_lib.pyi +++ b/python/python/databento_dbn/_lib.pyi @@ -1140,7 +1140,7 @@ class Record(SupportsBytes): """ @property - def pretty_ts_event(self) -> dt.datetime: + def pretty_ts_event(self) -> dt.datetime | None: """ The matching-engine-received timestamp expressed as a datetime or a `pandas.Timestamp`, if available. @@ -1281,7 +1281,7 @@ class _MBOBase: """ @property - def pretty_ts_recv(self) -> dt.datetime: + def pretty_ts_recv(self) -> dt.datetime | None: """ The capture-server-received timestamp as a datetime or `pandas.Timestamp`, if available. @@ -1705,7 +1705,7 @@ class _MBPBase: """ @property - def pretty_ts_recv(self) -> dt.datetime: + def pretty_ts_recv(self) -> dt.datetime | None: """ The capture-server-received timestamp as a datetime or `pandas.Timestamp`, if available. @@ -1897,7 +1897,7 @@ class BBOMsg(Record): """ @property - def pretty_ts_recv(self) -> dt.datetime: + def pretty_ts_recv(self) -> dt.datetime | None: """ The capture-server-received timestamp as a datetime or `pandas.Timestamp`, if available. @@ -2054,7 +2054,7 @@ class CMBP1Msg(Record): """ @property - def pretty_ts_recv(self) -> dt.datetime: + def pretty_ts_recv(self) -> dt.datetime | None: """ The interval timestamp as a datetime or `pandas.Timestamp` if available. @@ -2197,7 +2197,7 @@ class CBBOMsg(Record): """ @property - def pretty_ts_recv(self) -> dt.datetime: + def pretty_ts_recv(self) -> dt.datetime | None: """ The capture-server-received timestamp as a datetime or `pandas.Timestamp`, if available. @@ -2506,7 +2506,7 @@ class InstrumentDefMsg(Record): tick_rule: int | None = None, ) -> None: ... @property - def pretty_ts_recv(self) -> dt.datetime: + def pretty_ts_recv(self) -> dt.datetime | None: """ The capture-server-received timestamp as a datetime or `pandas.Timestamp`, if available. @@ -2573,11 +2573,13 @@ class InstrumentDefMsg(Record): """ @property - def pretty_expiration(self) -> dt.datetime: + def pretty_expiration(self) -> dt.datetime | None: """ The last eligible trade time expressed as a datetime or `pandas.Timestamp`, if available. + Some publishers only provide date-level granularity. + Returns ------- datetime.datetime @@ -2590,6 +2592,9 @@ class InstrumentDefMsg(Record): The last eligible trade time expressed as a number of nanoseconds since the UNIX epoch. + Will be `UNDEF_TIMESTAMP` when null, such as for equities. Some publishers + only provide date-level granularity. + Returns ------- int @@ -2597,11 +2602,13 @@ class InstrumentDefMsg(Record): """ @property - def pretty_activation(self) -> dt.datetime: + def pretty_activation(self) -> dt.datetime | None: """ The time of instrument activation expressed as a datetime or `pandas.Timestamp`, if available. + Some publishers only provide date-level granularity. + Returns ------- datetime.datetime @@ -2614,6 +2621,9 @@ class InstrumentDefMsg(Record): The time of instrument activation expressed as a number of nanoseconds since the UNIX epoch. + Will be `UNDEF_TIMESTAMP` when null, such as for equities. Some publishers + only provide date-level granularity. + Returns ------- int @@ -3447,7 +3457,7 @@ class InstrumentDefMsgV1(Record): tick_rule: int | None = None, ) -> None: ... @property - def pretty_ts_recv(self) -> dt.datetime: + def pretty_ts_recv(self) -> dt.datetime | None: """ The capture-server-received timestamp as a datetime or `pandas.Timestamp`, if available. @@ -3514,11 +3524,13 @@ class InstrumentDefMsgV1(Record): """ @property - def pretty_expiration(self) -> dt.datetime: + def pretty_expiration(self) -> dt.datetime | None: """ The last eligible trade time expressed as a datetime or `pandas.Timestamp`, if available. + Some publishers only provide date-level granularity. + Returns ------- datetime.datetime @@ -3531,6 +3543,9 @@ class InstrumentDefMsgV1(Record): The last eligible trade time expressed as a number of nanoseconds since the UNIX epoch. + Will be `UNDEF_TIMESTAMP` when null, such as for equities. Some publishers + only provide date-level granularity. + Returns ------- int @@ -3538,11 +3553,13 @@ class InstrumentDefMsgV1(Record): """ @property - def pretty_activation(self) -> dt.datetime: + def pretty_activation(self) -> dt.datetime | None: """ The time of instrument activation expressed as a datetime or `pandas.Timestamp`, if available. + Some publishers only provide date-level granularity. + Returns ------- datetime.datetime @@ -3555,6 +3572,9 @@ class InstrumentDefMsgV1(Record): The time of instrument activation expressed as a number of nanoseconds since the UNIX epoch. + Will be `UNDEF_TIMESTAMP` when null, such as for equities. Some publishers + only provide date-level granularity. + Returns ------- int @@ -4337,7 +4357,7 @@ class ImbalanceMsg(Record): significant_imbalance: str, ) -> None: ... @property - def pretty_ts_recv(self) -> dt.datetime: + def pretty_ts_recv(self) -> dt.datetime | None: """ The capture-server-received timestamp as a datetime or `pandas.Timestamp`, if available. @@ -4660,7 +4680,7 @@ class StatMsg(Record): stat_flags: int = 0, ) -> None: ... @property - def pretty_ts_recv(self) -> dt.datetime: + def pretty_ts_recv(self) -> dt.datetime | None: """ The capture-server-received timestamp as a datetime or `pandas.Timestamp`, if available. @@ -4684,7 +4704,7 @@ class StatMsg(Record): """ @property - def pretty_ts_ref(self) -> dt.datetime: + def pretty_ts_ref(self) -> dt.datetime | None: """ Reference timestamp expressed as the number of nanoseconds since the UNIX epoch as a datetime or `pandas.Timestamp`, if available. @@ -4823,7 +4843,7 @@ class StatusMsg(Record): """ @property - def pretty_ts_recv(self) -> dt.datetime: + def pretty_ts_recv(self) -> dt.datetime | None: """ The capture-server-received timestamp as a datetime or `pandas.Timestamp`, if available. @@ -5007,7 +5027,7 @@ class SymbolMappingMsg(Record): """ @property - def pretty_start_ts(self) -> dt.datetime: + def pretty_start_ts(self) -> dt.datetime | None: """ The start of the mapping interval expressed as a datetime or `pandas.Timestamp`, if available. @@ -5031,7 +5051,7 @@ class SymbolMappingMsg(Record): """ @property - def pretty_end_ts(self) -> dt.datetime: + def pretty_end_ts(self) -> dt.datetime | None: """ The end of the mapping interval expressed as a datetime or `pandas.Timestamp`, if available. @@ -5201,7 +5221,7 @@ class Transcoder: pretty_px : bool, default True Whether to serialize fixed-precision prices as decimal strings. Only applicable to CSV and JSON. - pretty_ts : bool, default True + pretty_ts : bool, default Tru | Nonee Whether to serialize nanosecond UNIX timestamps as ISO8601 datetime strings. Only applicable to CSV and JSON. map_symbols : bool, default None diff --git a/rust/dbn-cli/Cargo.toml b/rust/dbn-cli/Cargo.toml index caf6c48..94b0317 100644 --- a/rust/dbn-cli/Cargo.toml +++ b/rust/dbn-cli/Cargo.toml @@ -16,7 +16,7 @@ name = "dbn" path = "src/main.rs" [dependencies] -dbn = { path = "../dbn", version = "=0.23.1", default-features = false } +dbn = { path = "../dbn", version = "=0.24.0", default-features = false } anyhow = { workspace = true } clap = { version = "4.5", features = ["derive", "wrap_help"] } diff --git a/rust/dbn-cli/tests/integration_tests.rs b/rust/dbn-cli/tests/integration_tests.rs index 97b7b43..04a8ad6 100644 --- a/rust/dbn-cli/tests/integration_tests.rs +++ b/rust/dbn-cli/tests/integration_tests.rs @@ -580,11 +580,12 @@ fn broken_pipe_is_silent( if !fragment_flag.is_empty() { dbn_cmd.arg(fragment_flag); } - let dbn_res = dbn_cmd + let mut dbn_res = dbn_cmd .stdout(process::Stdio::piped()) .stderr(process::Stdio::piped()) .spawn() .unwrap(); + dbn_res.wait().unwrap(); let mut false_cmd = process::Command::new("false"); false_cmd.stdin(dbn_res.stdout.unwrap()); Command::from_std(false_cmd) diff --git a/rust/dbn-macros/Cargo.toml b/rust/dbn-macros/Cargo.toml index 510ff7b..8e905ab 100644 --- a/rust/dbn-macros/Cargo.toml +++ b/rust/dbn-macros/Cargo.toml @@ -13,7 +13,7 @@ proc-macro = true [dependencies] # Get name of current crate in macros, like $crate in macro_rules macros proc-macro-crate = "3.2.0" -proc-macro2 = "1.0.89" +proc-macro2 = "1.0.92" # Convert code to token streams quote = "1.0.37" # Token parsing diff --git a/rust/dbn/Cargo.toml b/rust/dbn/Cargo.toml index f47fa1a..afcc3c7 100644 --- a/rust/dbn/Cargo.toml +++ b/rust/dbn/Cargo.toml @@ -25,9 +25,9 @@ serde = ["dep:serde", "time/parsing", "time/serde"] trivial_copy = [] [dependencies] -dbn-macros = { version = "=0.23.1", path = "../dbn-macros" } +dbn-macros = { version = "=0.24.0", path = "../dbn-macros" } -async-compression = { version = "0.4.17", features = ["tokio", "zstd"], optional = true } +async-compression = { version = "0.4.18", features = ["tokio", "zstd"], optional = true } csv = { workspace = true } fallible-streaming-iterator = { version = "0.1.9", features = ["std"] } # Fast integer to string conversion diff --git a/rust/dbn/src/compat.rs b/rust/dbn/src/compat.rs index 0256b23..74b1783 100644 --- a/rust/dbn/src/compat.rs +++ b/rust/dbn/src/compat.rs @@ -130,12 +130,18 @@ pub struct InstrumentDefMsgV1 { #[pyo3(get, set)] pub display_factor: i64, /// The last eligible trade time expressed as a number of nanoseconds since the - /// UNIX epoch. Will be [`crate::UNDEF_TIMESTAMP`] when null, such as for equities. + /// UNIX epoch. + /// + /// Will be [`crate::UNDEF_TIMESTAMP`] when null, such as for equities. Some publishers + /// only provide date-level granularity. #[dbn(unix_nanos)] #[pyo3(get, set)] pub expiration: u64, /// The time of instrument activation expressed as a number of nanoseconds since the - /// UNIX epoch. Will be [`crate::UNDEF_TIMESTAMP`] when null, such as for equities. + /// UNIX epoch. + /// + /// Will be [`crate::UNDEF_TIMESTAMP`] when null, such as for equities. Some publishers + /// only provide date-level granularity. #[dbn(unix_nanos)] #[pyo3(get, set)] pub activation: u64, diff --git a/rust/dbn/src/decode.rs b/rust/dbn/src/decode.rs index 6946719..d1ed03f 100644 --- a/rust/dbn/src/decode.rs +++ b/rust/dbn/src/decode.rs @@ -126,7 +126,7 @@ where LegacyDbz(dbz::Decoder), } -impl<'a, R> DynDecoder<'a, BufReader> +impl DynDecoder<'_, BufReader> where R: io::Read, { @@ -156,7 +156,7 @@ where } } -impl<'a, R> DynDecoder<'a, R> +impl DynDecoder<'_, R> where R: io::BufRead, { @@ -223,7 +223,7 @@ where } } -impl<'a> DynDecoder<'a, BufReader> { +impl DynDecoder<'_, BufReader> { /// Creates a new [`DynDecoder`] from the file at `path`. It will decode records /// from previous DBN versions according to `upgrade_policy`. /// @@ -247,7 +247,7 @@ impl<'a> DynDecoder<'a, BufReader> { } } -impl<'a, R> DecodeRecordRef for DynDecoder<'a, R> +impl DecodeRecordRef for DynDecoder<'_, R> where R: io::BufRead, { @@ -261,7 +261,7 @@ where } #[allow(deprecated)] -impl<'a, R> DbnMetadata for DynDecoder<'a, R> +impl DbnMetadata for DynDecoder<'_, R> where R: io::BufRead, { @@ -283,7 +283,7 @@ where } #[allow(deprecated)] -impl<'a, R> DecodeRecord for DynDecoder<'a, R> +impl DecodeRecord for DynDecoder<'_, R> where R: io::BufRead, { @@ -296,7 +296,7 @@ where } } -impl<'a, R> DecodeStream for DynDecoder<'a, R> +impl DecodeStream for DynDecoder<'_, R> where R: io::BufRead, { @@ -322,7 +322,7 @@ where ZStd(::zstd::stream::Decoder<'a, R>), } -impl<'a, R> DynReader<'a, BufReader> +impl DynReader<'_, BufReader> where R: io::Read, { @@ -348,7 +348,7 @@ where } } -impl<'a, R> DynReader<'a, R> +impl DynReader<'_, R> where R: io::BufRead, { @@ -403,7 +403,7 @@ where } } -impl<'a> DynReader<'a, BufReader> { +impl DynReader<'_, BufReader> { /// Creates a new [`DynReader`] from the file at `path`. /// /// # Errors @@ -423,7 +423,7 @@ impl<'a> DynReader<'a, BufReader> { } } -impl<'a, R> io::Read for DynReader<'a, R> +impl io::Read for DynReader<'_, R> where R: io::BufRead, { @@ -435,7 +435,7 @@ where } } -impl<'a, R> private::BufferSlice for DynDecoder<'a, R> +impl private::BufferSlice for DynDecoder<'_, R> where R: io::BufRead, { diff --git a/rust/dbn/src/decode/dbn/async.rs b/rust/dbn/src/decode/dbn/async.rs index d3d0219..c2eedd8 100644 --- a/rust/dbn/src/decode/dbn/async.rs +++ b/rust/dbn/src/decode/dbn/async.rs @@ -111,7 +111,7 @@ where /// # Cancel safety /// This method is cancel safe. It can be used within a `tokio::select!` statement /// without the potential for corrupting the input stream. - pub async fn decode_record<'a, T: HasRType + 'a>(&'a mut self) -> Result> { + pub async fn decode_record<'a, T: HasRType + 'a>(&'a mut self) -> Result> { self.decoder.decode().await } @@ -310,7 +310,7 @@ where /// # Cancel safety /// This method is cancel safe. It can be used within a `tokio::select!` statement /// without the potential for corrupting the input stream. - pub async fn decode<'a, T: HasRType + 'a>(&'a mut self) -> Result> { + pub async fn decode<'a, T: HasRType + 'a>(&'a mut self) -> Result> { let rec_ref = self.decode_ref().await?; if let Some(rec_ref) = rec_ref { rec_ref @@ -377,16 +377,7 @@ where })) }; } else if self.state == DecoderState::Eof { - // there should be no remaining bytes in the buffer after reaching EOF - // and yielding all complete records - return if self.read_buf.remaining() == 0 { - Ok(None) - } else { - Err(crate::Error::decode(format!( - "unexpected partial record remaining in stream: {} bytes", - self.read_buf.remaining() - ))) - }; + return Ok(None); } else { self.state = DecoderState::Read; } @@ -834,13 +825,24 @@ mod tests { ); } + #[tokio::test] + async fn test_decode_partial_record() { + let buf = vec![6u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; + assert!(buf[0] as usize * RecordHeader::LENGTH_MULTIPLIER > buf.len()); + + let mut target = RecordDecoder::new(buf.as_slice()); + let res = target.decode_ref().await; + dbg!(&res); + assert!(matches!(res, Ok(None))); + } + #[tokio::test] async fn test_decode_record_length_longer_than_buffer() { let rec = ErrorMsg::new(1680703198000000000, "Test", true); let mut target = RecordDecoder::new(&rec.as_ref()[..rec.record_size() - 1]); let res = target.decode_ref().await; dbg!(&res); - assert!(matches!(res, Err(Error::Decode(msg)) if msg.starts_with("unexpected"))); + assert!(matches!(res, Ok(None))); } #[tokio::test] diff --git a/rust/dbn/src/decode/dbn/sync.rs b/rust/dbn/src/decode/dbn/sync.rs index 4de65e5..ebefcda 100644 --- a/rust/dbn/src/decode/dbn/sync.rs +++ b/rust/dbn/src/decode/dbn/sync.rs @@ -91,7 +91,7 @@ where } } -impl<'a, R> Decoder>> +impl Decoder>> where R: io::Read, { @@ -107,7 +107,7 @@ where } } -impl<'a, R> Decoder> +impl Decoder> where R: io::BufRead, { @@ -140,7 +140,7 @@ impl Decoder> { } } -impl<'a> Decoder>> { +impl Decoder>> { /// Creates a DBN [`Decoder`] from the Zstandard-compressed file at `path`. /// /// # Errors @@ -1069,6 +1069,17 @@ mod tests { ); } + #[test] + fn test_decode_partial_record() { + let buf = vec![6u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; + assert!(buf[0] as usize * RecordHeader::LENGTH_MULTIPLIER > buf.len()); + + let mut target = RecordDecoder::new(buf.as_slice()); + let res = target.decode_ref(); + dbg!(&res); + assert!(matches!(res, Ok(None))); + } + #[test] fn test_decode_record_length_less_than_header() { let buf = vec![3u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; diff --git a/rust/dbn/src/encode/dbn/sync.rs b/rust/dbn/src/encode/dbn/sync.rs index 5edf85a..8fd92ed 100644 --- a/rust/dbn/src/encode/dbn/sync.rs +++ b/rust/dbn/src/encode/dbn/sync.rs @@ -46,7 +46,7 @@ where } } -impl<'a, W> Encoder> +impl Encoder> where W: io::Write, { diff --git a/rust/dbn/src/encode/dyn_encoder.rs b/rust/dbn/src/encode/dyn_encoder.rs index aa13b0b..2e56631 100644 --- a/rust/dbn/src/encode/dyn_encoder.rs +++ b/rust/dbn/src/encode/dyn_encoder.rs @@ -155,7 +155,7 @@ where } } -impl<'a, W> DynEncoder<'a, W> +impl DynEncoder<'_, W> where W: io::Write, { @@ -230,7 +230,7 @@ where } } -impl<'a, W> EncodeRecord for DynEncoder<'a, W> +impl EncodeRecord for DynEncoder<'_, W> where W: io::Write, { @@ -243,7 +243,7 @@ where } } -impl<'a, W> EncodeRecordRef for DynEncoder<'a, W> +impl EncodeRecordRef for DynEncoder<'_, W> where W: io::Write, { @@ -256,7 +256,7 @@ where } } -impl<'a, W> EncodeDbn for DynEncoder<'a, W> +impl EncodeDbn for DynEncoder<'_, W> where W: io::Write, { @@ -276,7 +276,7 @@ where } } -impl<'a, W> EncodeRecordTextExt for DynEncoder<'a, W> +impl EncodeRecordTextExt for DynEncoder<'_, W> where W: io::Write, { @@ -289,7 +289,7 @@ where } } -impl<'a, W> EncodeRecord for DynEncoderImpl<'a, W> +impl EncodeRecord for DynEncoderImpl<'_, W> where W: io::Write, { @@ -310,7 +310,7 @@ where } } -impl<'a, W> EncodeRecordRef for DynEncoderImpl<'a, W> +impl EncodeRecordRef for DynEncoderImpl<'_, W> where W: io::Write, { @@ -331,7 +331,7 @@ where } } -impl<'a, W> EncodeDbn for DynEncoderImpl<'a, W> +impl EncodeDbn for DynEncoderImpl<'_, W> where W: io::Write, { @@ -363,7 +363,7 @@ where } } -impl<'a, W> EncodeRecordTextExt for DynEncoderImpl<'a, W> +impl EncodeRecordTextExt for DynEncoderImpl<'_, W> where W: io::Write, { diff --git a/rust/dbn/src/encode/dyn_writer.rs b/rust/dbn/src/encode/dyn_writer.rs index 8a30590..c8509ca 100644 --- a/rust/dbn/src/encode/dyn_writer.rs +++ b/rust/dbn/src/encode/dyn_writer.rs @@ -17,7 +17,7 @@ where Zstd(zstd::stream::AutoFinishEncoder<'a, W>), } -impl<'a, W> DynWriter<'a, W> +impl DynWriter<'_, W> where W: io::Write, { @@ -41,7 +41,7 @@ where } } -impl<'a, W> io::Write for DynWriter<'a, W> +impl io::Write for DynWriter<'_, W> where W: io::Write, { diff --git a/rust/dbn/src/python/record.rs b/rust/dbn/src/python/record.rs index 7f42cac..abe5125 100644 --- a/rust/dbn/src/python/record.rs +++ b/rust/dbn/src/python/record.rs @@ -126,12 +126,12 @@ impl MboMsg { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_event()) } #[getter] - fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_recv) } @@ -339,12 +339,12 @@ impl BboMsg { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_event()) } #[getter] - fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_recv) } @@ -486,12 +486,12 @@ impl Cmbp1Msg { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_event()) } #[getter] - fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_recv) } @@ -643,12 +643,12 @@ impl CbboMsg { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_event()) } #[getter] - fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_recv) } @@ -854,12 +854,12 @@ impl TradeMsg { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_event()) } #[getter] - fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_recv) } @@ -1019,12 +1019,12 @@ impl Mbp1Msg { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_event()) } #[getter] - fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_recv) } @@ -1196,12 +1196,12 @@ impl Mbp10Msg { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_event()) } #[getter] - fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_recv) } @@ -1352,7 +1352,7 @@ impl OhlcvMsg { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_event()) } @@ -1479,12 +1479,12 @@ impl StatusMsg { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_event()) } #[getter] - fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_recv) } @@ -1830,22 +1830,22 @@ impl InstrumentDefMsg { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_event()) } #[getter] - fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_recv) } #[getter] - fn get_pretty_activation(&self, py: Python<'_>) -> PyResult { + fn get_pretty_activation(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.activation) } #[getter] - fn get_pretty_expiration(&self, py: Python<'_>) -> PyResult { + fn get_pretty_expiration(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.expiration) } @@ -2275,22 +2275,22 @@ impl InstrumentDefMsgV1 { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_event()) } #[getter] - fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_recv) } #[getter] - fn get_pretty_activation(&self, py: Python<'_>) -> PyResult { + fn get_pretty_activation(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.activation) } #[getter] - fn get_pretty_expiration(&self, py: Python<'_>) -> PyResult { + fn get_pretty_expiration(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.expiration) } @@ -2530,12 +2530,12 @@ impl ImbalanceMsg { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_event()) } #[getter] - fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_recv) } @@ -2710,17 +2710,17 @@ impl StatMsg { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_event()) } #[getter] - fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_recv) } #[getter] - fn get_pretty_ts_ref(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_ref(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_ref) } @@ -2815,7 +2815,7 @@ impl ErrorMsg { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_event()) } @@ -2914,7 +2914,7 @@ impl ErrorMsgV1 { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_event()) } @@ -3036,17 +3036,17 @@ impl SymbolMappingMsg { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_event()) } #[getter] - fn get_pretty_end_ts(&self, py: Python<'_>) -> PyResult { + fn get_pretty_end_ts(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.end_ts) } #[getter] - fn get_pretty_start_ts(&self, py: Python<'_>) -> PyResult { + fn get_pretty_start_ts(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.start_ts) } @@ -3180,17 +3180,17 @@ impl SymbolMappingMsgV1 { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_event()) } #[getter] - fn get_pretty_end_ts(&self, py: Python<'_>) -> PyResult { + fn get_pretty_end_ts(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.end_ts) } #[getter] - fn get_pretty_start_ts(&self, py: Python<'_>) -> PyResult { + fn get_pretty_start_ts(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.start_ts) } @@ -3294,7 +3294,7 @@ impl SystemMsg { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_event()) } @@ -3398,7 +3398,7 @@ impl SystemMsgV1 { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult { + fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { new_py_timestamp_or_datetime(py, self.ts_event()) } @@ -3552,7 +3552,10 @@ impl>> IntoPy for WithTsOut { } } -fn new_py_timestamp_or_datetime(py: Python<'_>, timestamp: u64) -> PyResult { +fn new_py_timestamp_or_datetime(py: Python<'_>, timestamp: u64) -> PyResult> { + if timestamp == UNDEF_TIMESTAMP { + return Ok(None); + } if let Ok(pandas) = PyModule::import_bound(py, intern!(py, "pandas")) { let kwargs = PyDict::new_bound(py); if kwargs.set_item(intern!(py, "utc"), true).is_ok() @@ -3565,10 +3568,10 @@ fn new_py_timestamp_or_datetime(py: Python<'_>, timestamp: u64) -> PyResult From<&'a RecordEnum> for RecordRefEnum<'a> { } } -impl<'a> RecordRefEnum<'a> { +impl RecordRefEnum<'_> { /// Converts the reference enum into an owned enum value. pub fn to_owned(&self) -> RecordEnum { #[allow(clippy::clone_on_copy)] // required for when trivial_copy feature is disabled @@ -382,7 +382,7 @@ impl RecordMut for RecordEnum { } } -impl<'a> Record for RecordRefEnum<'a> { +impl Record for RecordRefEnum<'_> { fn header(&self) -> &crate::RecordHeader { match self { RecordRefEnum::Mbo(rec) => rec.header(), diff --git a/rust/dbn/src/record_ref.rs b/rust/dbn/src/record_ref.rs index be99f13..df723d1 100644 --- a/rust/dbn/src/record_ref.rs +++ b/rust/dbn/src/record_ref.rs @@ -194,7 +194,7 @@ impl<'a> From> for RecordRef<'a> { } } -impl<'a> Debug for RecordRef<'a> { +impl Debug for RecordRef<'_> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("RecordRef") .field(