feedparser-rs 0.6.0__tar.gz → 0.7.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/Cargo.lock +32 -16
  2. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/Cargo.toml +3 -6
  3. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/PKG-INFO +2 -1
  4. {feedparser_rs-0.6.0/crates/feedparser-rs-py → feedparser_rs-0.7.0}/README.md +1 -0
  5. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/Cargo.toml +0 -2
  6. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/README.md +3 -2
  7. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/http/client.rs +3 -3
  8. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/limits.rs +36 -1
  9. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/namespace/threading.rs +4 -4
  10. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/parser/atom.rs +68 -61
  11. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/parser/common.rs +31 -55
  12. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/parser/detect.rs +11 -11
  13. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/parser/json.rs +327 -0
  14. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/parser/rss.rs +53 -42
  15. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/parser/rss10.rs +22 -22
  16. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/types/common.rs +36 -36
  17. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/types/entry.rs +22 -1
  18. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/types/feed.rs +29 -1
  19. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/util/ssrf.rs +121 -89
  20. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/tests/http_integration.rs +1 -1
  21. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/tests/integration_tests.rs +17 -0
  22. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-py/Cargo.toml +1 -1
  23. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0/crates/feedparser-rs-py}/README.md +1 -0
  24. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-py/src/limits.rs +1 -18
  25. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-py/src/types/common.rs +53 -1
  26. feedparser_rs-0.7.0/crates/feedparser-rs-py/src/types/compat.rs +127 -0
  27. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-py/src/types/entry.rs +30 -4
  28. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-py/src/types/feed_meta.rs +27 -3
  29. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-py/src/types/parsed_feed.rs +2 -2
  30. feedparser_rs-0.7.0/crates/feedparser-rs-py/tests/test_json_extensions.py +56 -0
  31. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/pyproject.toml +1 -1
  32. feedparser_rs-0.6.0/crates/feedparser-rs-py/src/types/compat.rs +0 -123
  33. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/benches/parsing.rs +0 -0
  34. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/benches/types.rs +0 -0
  35. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/examples/error_handling.rs +0 -0
  36. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/examples/feeds/malformed_feed.xml +0 -0
  37. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/examples/feeds/sample_atom.xml +0 -0
  38. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/examples/feeds/sample_podcast.xml +0 -0
  39. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/examples/feeds/sample_rss.xml +0 -0
  40. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/examples/parse_file.rs +0 -0
  41. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/examples/parse_url.rs +0 -0
  42. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/examples/podcast_feed.rs +0 -0
  43. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/examples/profile_memory.rs +0 -0
  44. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/compat/mod.rs +0 -0
  45. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/error.rs +0 -0
  46. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/http/mod.rs +0 -0
  47. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/http/resolver.rs +0 -0
  48. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/http/response.rs +0 -0
  49. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/http/validation.rs +0 -0
  50. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/lib.rs +0 -0
  51. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/namespace/cc.rs +0 -0
  52. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/namespace/content.rs +0 -0
  53. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/namespace/dublin_core.rs +0 -0
  54. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/namespace/georss.rs +0 -0
  55. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/namespace/media_rss.rs +0 -0
  56. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/namespace/mod.rs +0 -0
  57. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/namespace/slash.rs +0 -0
  58. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/namespace/syndication.rs +0 -0
  59. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/options.rs +0 -0
  60. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/parser/context.rs +0 -0
  61. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/parser/mod.rs +0 -0
  62. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/parser/namespace_detection.rs +0 -0
  63. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/types/generics.rs +0 -0
  64. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/types/mod.rs +0 -0
  65. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/types/podcast.rs +0 -0
  66. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/types/thread.rs +0 -0
  67. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/types/version.rs +0 -0
  68. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/util/base_url.rs +0 -0
  69. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/util/date.rs +0 -0
  70. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/util/encoding.rs +0 -0
  71. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/util/mod.rs +0 -0
  72. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/util/sanitize.rs +0 -0
  73. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/src/util/text.rs +0 -0
  74. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/tests/encoding_integration.rs +0 -0
  75. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/tests/fixtures/rss10/rss10_channel_selfclosing_refs.xml +0 -0
  76. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/tests/guid_entity_tests.rs +0 -0
  77. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/tests/issue45_test.rs +0 -0
  78. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/tests/namespace_edge_cases.rs +0 -0
  79. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/tests/namespace_integration.rs +0 -0
  80. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/tests/test_adversarial_input.rs +0 -0
  81. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/tests/test_author_detail.rs +0 -0
  82. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/tests/test_entry_author_precedence.rs +0 -0
  83. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/tests/test_georss_cc_namespaces.rs +0 -0
  84. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/tests/test_media_namespace.rs +0 -0
  85. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/tests/test_parser_limits.rs +0 -0
  86. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/tests/test_podcast_namespace.rs +0 -0
  87. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/tests/test_rss10.rs +0 -0
  88. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/tests/test_rss_optional_elements.rs +0 -0
  89. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/tests/test_sanitize_wiring.rs +0 -0
  90. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/tests/test_slash_wfw_namespaces.rs +0 -0
  91. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/tests/test_thr_namespace.rs +0 -0
  92. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/tests/test_threading_namespace.rs +0 -0
  93. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/tests/test_timezone_preservation.rs +0 -0
  94. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/tests/test_truncated_feeds.rs +0 -0
  95. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/tests/test_url_resolution.rs +0 -0
  96. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-core/tests/test_url_security.rs +0 -0
  97. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-py/src/error.rs +0 -0
  98. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-py/src/lib.rs +0 -0
  99. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-py/src/types/datetime.rs +0 -0
  100. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-py/src/types/geo.rs +0 -0
  101. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-py/src/types/media.rs +0 -0
  102. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-py/src/types/mod.rs +0 -0
  103. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-py/src/types/podcast.rs +0 -0
  104. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-py/src/types/syndication.rs +0 -0
  105. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-py/src/types/thread.rs +0 -0
  106. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-py/tests/test_basic.py +0 -0
  107. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-py/tests/test_bindings.py +0 -0
  108. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-py/tests/test_compat.py +0 -0
  109. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-py/tests/test_dict_methods.py +0 -0
  110. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-py/tests/test_guid_entities.py +0 -0
  111. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-py/tests/test_integration.py +0 -0
  112. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-py/tests/test_itunes_flat_keys.py +0 -0
  113. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-py/tests/test_subscriptable.py +0 -0
  114. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-py/tests/test_syndication.py +0 -0
  115. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/crates/feedparser-rs-py/uv.lock +0 -0
  116. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/python/feedparser_rs/__init__.py +0 -0
  117. {feedparser_rs-0.6.0 → feedparser_rs-0.7.0}/python/feedparser_rs/py.typed +0 -0
@@ -155,7 +155,7 @@ dependencies = [
155
155
  "addr2line",
156
156
  "cfg-if",
157
157
  "libc",
158
- "miniz_oxide",
158
+ "miniz_oxide 0.8.9",
159
159
  "object",
160
160
  "rustc-demangle",
161
161
  "windows-link",
@@ -582,7 +582,7 @@ checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223"
582
582
 
583
583
  [[package]]
584
584
  name = "feedparser-rs"
585
- version = "0.6.0"
585
+ version = "0.7.0"
586
586
  dependencies = [
587
587
  "ammonia",
588
588
  "chrono",
@@ -592,10 +592,8 @@ dependencies = [
592
592
  "encoding_rs",
593
593
  "flate2",
594
594
  "html-escape",
595
- "memchr",
596
595
  "mockito",
597
596
  "quick-xml",
598
- "regex",
599
597
  "reqwest",
600
598
  "serde",
601
599
  "serde_json",
@@ -606,7 +604,7 @@ dependencies = [
606
604
 
607
605
  [[package]]
608
606
  name = "feedparser-rs-node"
609
- version = "0.6.0"
607
+ version = "0.7.0"
610
608
  dependencies = [
611
609
  "chrono",
612
610
  "feedparser-rs",
@@ -620,12 +618,12 @@ dependencies = [
620
618
 
621
619
  [[package]]
622
620
  name = "feedparser-rs-py"
623
- version = "0.6.0"
621
+ version = "0.7.0"
624
622
  dependencies = [
625
623
  "chrono",
626
624
  "feedparser-rs",
627
- "once_cell",
628
625
  "pyo3",
626
+ "serde_json",
629
627
  ]
630
628
 
631
629
  [[package]]
@@ -636,12 +634,13 @@ checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890"
636
634
 
637
635
  [[package]]
638
636
  name = "flate2"
639
- version = "1.1.9"
637
+ version = "1.1.10"
640
638
  source = "registry+https://github.com/rust-lang/crates.io-index"
641
- checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c"
639
+ checksum = "6e634e2e0ebac1ee034020da1ca582e17ffe4e0f5e985823721e168928136dcb"
642
640
  dependencies = [
643
641
  "crc32fast",
644
- "miniz_oxide",
642
+ "miniz_oxide 0.9.1",
643
+ "zlib-rs",
645
644
  ]
646
645
 
647
646
  [[package]]
@@ -800,9 +799,9 @@ checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7"
800
799
 
801
800
  [[package]]
802
801
  name = "h2"
803
- version = "0.4.15"
802
+ version = "0.4.16"
804
803
  source = "registry+https://github.com/rust-lang/crates.io-index"
805
- checksum = "6cb093c84e8bd9b188d4c4a8cb6579fc016968d14c99882163cd3ff402a4f155"
804
+ checksum = "a9f37a958b41b3b19ee2707c06439c0e9e547e847223eb791ecb0cb821c65e27"
806
805
  dependencies = [
807
806
  "atomic-waker",
808
807
  "bytes",
@@ -1267,6 +1266,15 @@ name = "miniz_oxide"
1267
1266
  version = "0.8.9"
1268
1267
  source = "registry+https://github.com/rust-lang/crates.io-index"
1269
1268
  checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
1269
+ dependencies = [
1270
+ "adler2",
1271
+ ]
1272
+
1273
+ [[package]]
1274
+ name = "miniz_oxide"
1275
+ version = "0.9.1"
1276
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1277
+ checksum = "b63fbc4a50860e98e7b2aa7804ded1db5cbc3aff9193adaff57a6931bf7c4b4c"
1270
1278
  dependencies = [
1271
1279
  "adler2",
1272
1280
  "simd-adler32",
@@ -1316,9 +1324,9 @@ dependencies = [
1316
1324
 
1317
1325
  [[package]]
1318
1326
  name = "napi"
1319
- version = "3.12.1"
1327
+ version = "3.12.2"
1320
1328
  source = "registry+https://github.com/rust-lang/crates.io-index"
1321
- checksum = "459197f1592f4c3dbbf9c1b13f5a4599a343e4ef66b96bc340e2a518b36a6662"
1329
+ checksum = "58c5f4d5375213fdb7be2655e152386e82f026f9a5ba36a75556e11359aafe09"
1322
1330
  dependencies = [
1323
1331
  "anyhow",
1324
1332
  "bitflags",
@@ -1329,6 +1337,8 @@ dependencies = [
1329
1337
  "napi-sys",
1330
1338
  "nohash-hasher",
1331
1339
  "rustc-hash 2.1.3",
1340
+ "serde",
1341
+ "serde_json",
1332
1342
  ]
1333
1343
 
1334
1344
  [[package]]
@@ -1638,9 +1648,9 @@ dependencies = [
1638
1648
 
1639
1649
  [[package]]
1640
1650
  name = "quick-xml"
1641
- version = "0.41.0"
1651
+ version = "0.42.0"
1642
1652
  source = "registry+https://github.com/rust-lang/crates.io-index"
1643
- checksum = "e660451e55124f798a69a5af3f49ccfbefbd41910eefd25caf2393e1f3473ec1"
1653
+ checksum = "41b1177fdf999d2321d3fb46ff47159d9c1fb9ad66a4879f8c50a0b504615e9b"
1644
1654
  dependencies = [
1645
1655
  "memchr",
1646
1656
  ]
@@ -2898,6 +2908,12 @@ dependencies = [
2898
2908
  "syn 3.0.3",
2899
2909
  ]
2900
2910
 
2911
+ [[package]]
2912
+ name = "zlib-rs"
2913
+ version = "0.6.7"
2914
+ source = "registry+https://github.com/rust-lang/crates.io-index"
2915
+ checksum = "34b31d188d9d685a4f9c7b46d6e36631b07058d2cfe190267adce54dc230bf12"
2916
+
2901
2917
  [[package]]
2902
2918
  name = "zmij"
2903
2919
  version = "1.0.23"
@@ -3,9 +3,9 @@ members = ["crates/feedparser-rs-core", "crates/feedparser-rs-py"]
3
3
  resolver = "2"
4
4
 
5
5
  [workspace.package]
6
- version = "0.6.0"
6
+ version = "0.7.0"
7
7
  edition = "2024"
8
- rust-version = "1.88.0"
8
+ rust-version = "1.91.0"
9
9
  authors = ["bug-ops"]
10
10
  license = "MIT OR Apache-2.0"
11
11
  repository = "https://github.com/bug-ops/feedparser-rs"
@@ -21,14 +21,11 @@ criterion = "0.8"
21
21
  encoding_rs = "0.8"
22
22
  flate2 = "1.1"
23
23
  html-escape = "0.2"
24
- memchr = "2.8"
25
24
  mockito = "1.7"
26
25
  napi = "3.12"
27
26
  napi-derive = "3.6"
28
- once_cell = "1.21"
29
27
  pyo3 = "0.29"
30
- quick-xml = "0.41"
31
- regex = "1.13"
28
+ quick-xml = "0.42"
32
29
  reqwest = { version = "0.13", default-features = false }
33
30
  serde = "1.0"
34
31
  serde_json = "1.0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: feedparser-rs
3
- Version: 0.6.0
3
+ Version: 0.7.0
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: License :: OSI Approved :: MIT License
@@ -38,6 +38,7 @@ High-performance RSS/Atom/JSON Feed parser for Python with feedparser-compatible
38
38
  - **Sanitized by default**: HTML-bearing fields are sanitized against XSS unless explicitly disabled via `sanitize_html=False`
39
39
  - **Multi-format**: RSS 0.9x/1.0/2.0, Atom 0.3/1.0, JSON Feed 1.0/1.1
40
40
  - **Podcast support**: iTunes and Podcast 2.0 namespace extensions
41
+ - **JSON Feed extensions**: `_`-prefixed custom objects (e.g. `_cast`) captured as `feed.json_extensions`/`entry.json_extensions` dicts
41
42
  - **feedparser-compatible**: Dict-style access, field aliases, same API patterns
42
43
  - **DoS protection**: Built-in resource limits
43
44
 
@@ -15,6 +15,7 @@ High-performance RSS/Atom/JSON Feed parser for Python with feedparser-compatible
15
15
  - **Sanitized by default**: HTML-bearing fields are sanitized against XSS unless explicitly disabled via `sanitize_html=False`
16
16
  - **Multi-format**: RSS 0.9x/1.0/2.0, Atom 0.3/1.0, JSON Feed 1.0/1.1
17
17
  - **Podcast support**: iTunes and Podcast 2.0 namespace extensions
18
+ - **JSON Feed extensions**: `_`-prefixed custom objects (e.g. `_cast`) captured as `feed.json_extensions`/`entry.json_extensions` dicts
18
19
  - **feedparser-compatible**: Dict-style access, field aliases, same API patterns
19
20
  - **DoS protection**: Built-in resource limits
20
21
 
@@ -16,9 +16,7 @@ chrono = { workspace = true, features = ["std", "clock"] }
16
16
  compact_str.workspace = true
17
17
  encoding_rs.workspace = true
18
18
  html-escape.workspace = true
19
- memchr.workspace = true
20
19
  quick-xml.workspace = true
21
- regex.workspace = true
22
20
  reqwest = { workspace = true, features = [
23
21
  "blocking",
24
22
  "gzip",
@@ -19,6 +19,7 @@ This is the core parsing library that powers the Python and Node.js bindings.
19
19
  - **HTTP support**: Fetch feeds from URLs with compression and conditional GET
20
20
  - **Podcast support**: iTunes and Podcast 2.0 namespace extensions
21
21
  - **Namespace extensions**: Dublin Core, Media RSS (`media:title`, `media:description`, `media:content`, `media:thumbnail`, `media:credit`, `media:copyright`, `media:rating`, `media:keywords`), Syndication, GeoRSS, Creative Commons
22
+ - **JSON Feed extension objects**: generic capture of underscore-prefixed custom objects (e.g. `_cast`) at feed- and item-level via `json_extensions`
22
23
  - **Well-tested**: 91%+ test coverage with real-world feed fixtures
23
24
 
24
25
  ## Installation
@@ -35,7 +36,7 @@ feedparser-rs = "0.6"
35
36
  ```
36
37
 
37
38
  > [!IMPORTANT]
38
- > Requires Rust 1.88.0 or later (edition 2024).
39
+ > Requires Rust 1.91.0 or later (edition 2024).
39
40
 
40
41
  ## Quick Start
41
42
 
@@ -190,7 +191,7 @@ cargo bench
190
191
 
191
192
  ## MSRV Policy
192
193
 
193
- Minimum Supported Rust Version: **1.88.0** (edition 2024).
194
+ Minimum Supported Rust Version: **1.91.0** (edition 2024).
194
195
 
195
196
  MSRV increases are considered breaking changes and will result in a minor version bump.
196
197
 
@@ -537,7 +537,7 @@ mod tests {
537
537
 
538
538
  #[test]
539
539
  fn test_custom_timeout() {
540
- let timeout = Duration::from_secs(60);
540
+ let timeout = Duration::from_mins(1);
541
541
  let client = FeedHttpClient::new().unwrap().with_timeout(timeout);
542
542
  assert_eq!(client.timeout, timeout);
543
543
  }
@@ -547,7 +547,7 @@ mod tests {
547
547
  // `Duration::MAX` would overflow `Instant::now() + timeout` inside
548
548
  // reqwest's blocking wait and panic; it must be clamped instead.
549
549
  let client = FeedHttpClient::new().unwrap().with_timeout(Duration::MAX);
550
- assert_eq!(client.timeout, Duration::from_secs(3600));
550
+ assert_eq!(client.timeout, Duration::from_hours(1));
551
551
  }
552
552
 
553
553
  #[test]
@@ -558,7 +558,7 @@ mod tests {
558
558
  let timeout = Duration::from_secs(7);
559
559
  let client = FeedHttpClient::new().unwrap().with_timeout(timeout);
560
560
  let request = client
561
- .build_request("http://example.test/feed.xml", HeaderMap::new())
561
+ .build_request("https://example.test/feed.xml", HeaderMap::new())
562
562
  .unwrap();
563
563
  assert_eq!(request.timeout(), Some(&timeout));
564
564
  }
@@ -110,7 +110,10 @@ pub struct ParserLimits {
110
110
 
111
111
  /// Maximum text field length in bytes
112
112
  ///
113
- /// Prevents excessive memory from huge title/description fields.
113
+ /// Prevents excessive memory from huge title/description fields. Also bounds
114
+ /// the per-value serialized size of a captured JSON Feed extension object
115
+ /// (see `max_json_extensions`); an oversized extension value is dropped
116
+ /// entirely rather than truncated.
114
117
  ///
115
118
  /// Default: 10 MB
116
119
  pub max_text_length: usize,
@@ -209,6 +212,20 @@ pub struct ParserLimits {
209
212
  ///
210
213
  /// Default: 20
211
214
  pub max_podcast_value_time_splits: usize,
215
+
216
+ /// Maximum number of JSON Feed extension objects captured per scope
217
+ ///
218
+ /// JSON Feed permits custom object keys (starting with `_` followed by a
219
+ /// letter) anywhere in a feed; this bounds how many distinct keys are
220
+ /// captured per feed-root or item-root scope, counted independently. When a
221
+ /// scope has more extension keys than this limit, the surviving keys are the
222
+ /// alphabetically-first ones, not the document-order-first ones: `serde_json`
223
+ /// backs a JSON object with a `BTreeMap` by default (the `preserve_order`
224
+ /// feature, which would switch it to an `IndexMap` and make truncation
225
+ /// document-order-first, is not enabled).
226
+ ///
227
+ /// Default: 100
228
+ pub max_json_extensions: usize,
212
229
  }
213
230
 
214
231
  impl Default for ParserLimits {
@@ -245,6 +262,7 @@ impl Default for ParserLimits {
245
262
  max_podcast_follow: 20,
246
263
  max_podcast_chat: 20,
247
264
  max_podcast_value_time_splits: 20,
265
+ max_json_extensions: 100,
248
266
  }
249
267
  }
250
268
  }
@@ -293,6 +311,7 @@ impl ParserLimits {
293
311
  max_podcast_follow: 5,
294
312
  max_podcast_chat: 5,
295
313
  max_podcast_value_time_splits: 5,
314
+ max_json_extensions: 20,
296
315
  }
297
316
  }
298
317
 
@@ -339,6 +358,7 @@ impl ParserLimits {
339
358
  max_podcast_follow: 100,
340
359
  max_podcast_chat: 100,
341
360
  max_podcast_value_time_splits: 50,
361
+ max_json_extensions: 500,
342
362
  }
343
363
  }
344
364
 
@@ -635,4 +655,19 @@ mod tests {
635
655
  assert!(result.is_err());
636
656
  assert!(matches!(result, Err(LimitError::CollectionTooLarge { .. })));
637
657
  }
658
+
659
+ #[test]
660
+ fn test_max_json_extensions_tiers() {
661
+ assert_eq!(ParserLimits::default().max_json_extensions, 100);
662
+ assert_eq!(ParserLimits::strict().max_json_extensions, 20);
663
+ assert_eq!(ParserLimits::permissive().max_json_extensions, 500);
664
+ assert!(
665
+ ParserLimits::strict().max_json_extensions
666
+ < ParserLimits::default().max_json_extensions
667
+ );
668
+ assert!(
669
+ ParserLimits::permissive().max_json_extensions
670
+ > ParserLimits::default().max_json_extensions
671
+ );
672
+ }
638
673
  }
@@ -69,10 +69,10 @@ pub fn parse_in_reply_to_from_attrs<'a>(
69
69
  continue;
70
70
  };
71
71
  match attr.key.as_ref() {
72
- b"ref" => ref_ = non_empty(&value).map(|s| s.to_string().into()),
73
- b"href" => href = non_empty(&value).map(|s| s.to_string().into()),
74
- b"type" => type_ = non_empty(&value).map(|s| s.to_string().into()),
75
- b"source" => source = non_empty(&value).map(|s| s.to_string().into()),
72
+ "ref" => ref_ = non_empty(&value).map(|s| s.to_string().into()),
73
+ "href" => href = non_empty(&value).map(|s| s.to_string().into()),
74
+ "type" => type_ = non_empty(&value).map(|s| s.to_string().into()),
75
+ "source" => source = non_empty(&value).map(|s| s.to_string().into()),
76
76
  _ => {}
77
77
  }
78
78
  }