neo4j-ruby-driver 6.0.3.alpha.0 → 6.2.1.beta.2

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 (348) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +113 -411
  3. data/{ruby → lib}/neo4j/driver/access_mode.rb +2 -1
  4. data/lib/neo4j/driver/auth_token_managers.rb +31 -0
  5. data/lib/neo4j/driver/auth_tokens.rb +41 -0
  6. data/lib/neo4j/driver/auto_commit_retries_mode.rb +18 -0
  7. data/lib/neo4j/driver/bolt/bolt_version.rb +67 -0
  8. data/lib/neo4j/driver/bolt/connection.rb +1091 -0
  9. data/lib/neo4j/driver/bolt/handshake.rb +236 -0
  10. data/lib/neo4j/driver/bolt/message/failure.rb +139 -0
  11. data/lib/neo4j/driver/bolt/message/ignored.rb +27 -0
  12. data/lib/neo4j/driver/bolt/message/record.rb +30 -0
  13. data/lib/neo4j/driver/bolt/message/success.rb +34 -0
  14. data/lib/neo4j/driver/bolt/message.rb +112 -0
  15. data/lib/neo4j/driver/bolt/pool.rb +255 -0
  16. data/lib/neo4j/driver/bolt/protocol/base.rb +146 -0
  17. data/lib/neo4j/driver/bolt/protocol/v3.rb +43 -0
  18. data/lib/neo4j/driver/bolt/protocol/v4.rb +24 -0
  19. data/lib/neo4j/driver/bolt/protocol/v43.rb +28 -0
  20. data/lib/neo4j/driver/bolt/protocol/v44.rb +23 -0
  21. data/lib/neo4j/driver/bolt/protocol/v5.rb +27 -0
  22. data/lib/neo4j/driver/bolt/protocol/v51.rb +24 -0
  23. data/lib/neo4j/driver/bolt/protocol/v52.rb +28 -0
  24. data/lib/neo4j/driver/bolt/protocol/v53.rb +27 -0
  25. data/lib/neo4j/driver/bolt/protocol/v54.rb +14 -0
  26. data/lib/neo4j/driver/bolt/protocol/v55.rb +17 -0
  27. data/lib/neo4j/driver/bolt/protocol/v56.rb +14 -0
  28. data/lib/neo4j/driver/bolt/protocol/v57.rb +31 -0
  29. data/lib/neo4j/driver/bolt/protocol/v58.rb +15 -0
  30. data/lib/neo4j/driver/bolt/protocol/v6.rb +43 -0
  31. data/lib/neo4j/driver/bolt/protocol/v61.rb +21 -0
  32. data/lib/neo4j/driver/bolt/protocol_version_handler.rb +39 -0
  33. data/lib/neo4j/driver/bolt/record_buffer.rb +143 -0
  34. data/lib/neo4j/driver/bolt/stream_handler.rb +53 -0
  35. data/lib/neo4j/driver/bolt/tls_config.rb +129 -0
  36. data/lib/neo4j/driver/bolt/wire.rb +321 -0
  37. data/lib/neo4j/driver/bookmark.rb +15 -0
  38. data/lib/neo4j/driver/bookmark_managers.rb +39 -0
  39. data/lib/neo4j/driver/client_certificate.rb +19 -0
  40. data/lib/neo4j/driver/client_certificate_manager.rb +37 -0
  41. data/lib/neo4j/driver/client_certificate_managers.rb +15 -0
  42. data/lib/neo4j/driver/client_certificates.rb +14 -0
  43. data/lib/neo4j/driver/direct/connection_provider.rb +262 -0
  44. data/lib/neo4j/driver/driver.rb +268 -0
  45. data/lib/neo4j/driver/eager_result.rb +10 -0
  46. data/lib/neo4j/driver/exceptions/neo4j_exception.rb +16 -7
  47. data/lib/neo4j/driver/exceptions/no_such_record_exception.rb +1 -1
  48. data/lib/neo4j/driver/exceptions/protocol_exception.rb +0 -5
  49. data/lib/neo4j/driver/exceptions/security_retryable_exception.rb +14 -0
  50. data/lib/neo4j/driver/exceptions/transaction_terminated_exception.rb +13 -0
  51. data/lib/neo4j/driver/graph_database.rb +29 -0
  52. data/lib/neo4j/driver/internal/clock.rb +20 -0
  53. data/lib/neo4j/driver/internal/clock_adapter.rb +21 -0
  54. data/lib/neo4j/driver/internal/default_bookmark_manager.rb +54 -0
  55. data/lib/neo4j/driver/internal/deprecator.rb +9 -5
  56. data/lib/neo4j/driver/internal/driver_factory.rb +128 -0
  57. data/lib/neo4j/driver/internal/duration_normalizer.rb +14 -39
  58. data/lib/neo4j/driver/internal/extras.rb +23 -0
  59. data/lib/neo4j/driver/internal/home_db_cache.rb +57 -0
  60. data/lib/neo4j/driver/internal/internal_auth_token_manager.rb +37 -0
  61. data/lib/neo4j/driver/internal/metrics.rb +31 -0
  62. data/lib/neo4j/driver/internal/security/static_auth_token_manager.rb +25 -0
  63. data/lib/neo4j/driver/internal/validator.rb +16 -2
  64. data/lib/neo4j/driver/net.rb +29 -0
  65. data/lib/neo4j/driver/packstream/markers.rb +49 -0
  66. data/lib/neo4j/driver/packstream/packer.rb +335 -0
  67. data/lib/neo4j/driver/packstream/structure.rb +27 -0
  68. data/lib/neo4j/driver/packstream/unpacker.rb +170 -0
  69. data/lib/neo4j/driver/record.rb +43 -0
  70. data/lib/neo4j/driver/result.rb +282 -0
  71. data/lib/neo4j/driver/routing/load_balancer.rb +706 -0
  72. data/lib/neo4j/driver/routing/routed_connection.rb +132 -0
  73. data/lib/neo4j/driver/routing/routing_table.rb +127 -0
  74. data/lib/neo4j/driver/routing/server_address.rb +25 -0
  75. data/lib/neo4j/driver/routing_control.rb +13 -0
  76. data/lib/neo4j/driver/session.rb +577 -0
  77. data/lib/neo4j/driver/summary/database_info.rb +25 -0
  78. data/lib/neo4j/driver/summary/gql_notification.rb +38 -0
  79. data/lib/neo4j/driver/summary/gql_status_object.rb +35 -0
  80. data/lib/neo4j/driver/summary/notification.rb +46 -0
  81. data/lib/neo4j/driver/summary/plan.rb +23 -0
  82. data/lib/neo4j/driver/summary/profile.rb +28 -0
  83. data/lib/neo4j/driver/summary/query.rb +19 -0
  84. data/lib/neo4j/driver/summary/query_type.rb +5 -1
  85. data/lib/neo4j/driver/summary/result_summary.rb +215 -0
  86. data/lib/neo4j/driver/summary/server_info.rb +33 -0
  87. data/lib/neo4j/driver/summary/summary_counters.rb +72 -0
  88. data/lib/neo4j/driver/transaction.rb +344 -0
  89. data/lib/neo4j/driver/types/duration.rb +76 -0
  90. data/lib/neo4j/driver/types/entity.rb +40 -0
  91. data/lib/neo4j/driver/types/local_date_time.rb +77 -8
  92. data/lib/neo4j/driver/types/local_time.rb +50 -7
  93. data/lib/neo4j/driver/types/node.rb +18 -0
  94. data/lib/neo4j/driver/types/offset_time.rb +78 -7
  95. data/lib/neo4j/driver/types/path.rb +68 -0
  96. data/lib/neo4j/driver/types/point.rb +38 -18
  97. data/lib/neo4j/driver/types/relationship.rb +32 -0
  98. data/lib/neo4j/driver/types/temporal_value.rb +44 -0
  99. data/lib/neo4j/driver/types/unbound_relationship.rb +24 -0
  100. data/lib/neo4j/driver/types/unresolvable_zoned_date_time.rb +38 -0
  101. data/lib/neo4j/driver/types/unsupported_type.rb +25 -0
  102. data/lib/neo4j/driver/types/uuid.rb +29 -0
  103. data/{ruby → lib}/neo4j/driver/version.rb +1 -1
  104. data/lib/neo4j/driver.rb +15 -0
  105. data/lib/neo4j-ruby-driver_loader.rb +34 -20
  106. metadata +115 -441
  107. data/lib/neo4j/driver/internal/bolt_server_address.rb +0 -97
  108. data/lib/neo4j/driver/synchronizable.rb +0 -23
  109. data/lib/neo4j/driver/types/time.rb +0 -45
  110. data/ruby/neo4j/driver/auth_tokens.rb +0 -34
  111. data/ruby/neo4j/driver/bookmark.rb +0 -21
  112. data/ruby/neo4j/driver/config.rb +0 -89
  113. data/ruby/neo4j/driver/graph_database.rb +0 -78
  114. data/ruby/neo4j/driver/internal/async/connection/bolt_protocol_util.rb +0 -51
  115. data/ruby/neo4j/driver/internal/async/connection/bootstrap_factory.rb +0 -22
  116. data/ruby/neo4j/driver/internal/async/connection/channel_attributes.rb +0 -31
  117. data/ruby/neo4j/driver/internal/async/connection/channel_connected_listener.rb +0 -32
  118. data/ruby/neo4j/driver/internal/async/connection/channel_connector_impl.rb +0 -83
  119. data/ruby/neo4j/driver/internal/async/connection/channel_pipeline_builder_impl.rb +0 -22
  120. data/ruby/neo4j/driver/internal/async/connection/direct_connection.rb +0 -30
  121. data/ruby/neo4j/driver/internal/async/connection/event_loop_group_factory.rb +0 -83
  122. data/ruby/neo4j/driver/internal/async/connection/handshake_completed_listener.rb +0 -27
  123. data/ruby/neo4j/driver/internal/async/connection/handshake_handler.rb +0 -113
  124. data/ruby/neo4j/driver/internal/async/connection/netty_channel_initializer.rb +0 -57
  125. data/ruby/neo4j/driver/internal/async/connection/netty_domain_name_resolver.rb +0 -26
  126. data/ruby/neo4j/driver/internal/async/connection/netty_domain_name_resolver_group.rb +0 -19
  127. data/ruby/neo4j/driver/internal/async/connection/routing_connection.rb +0 -36
  128. data/ruby/neo4j/driver/internal/async/connection/stream.rb +0 -12
  129. data/ruby/neo4j/driver/internal/async/connection/stream_reader.rb +0 -16
  130. data/ruby/neo4j/driver/internal/async/connection_context.rb +0 -10
  131. data/ruby/neo4j/driver/internal/async/immutable_connection_context.rb +0 -24
  132. data/ruby/neo4j/driver/internal/async/inbound/byte_buf_input.rb +0 -30
  133. data/ruby/neo4j/driver/internal/async/inbound/channel_error_handler.rb +0 -77
  134. data/ruby/neo4j/driver/internal/async/inbound/chunk_decoder.rb +0 -41
  135. data/ruby/neo4j/driver/internal/async/inbound/connect_timeout_handler.rb +0 -32
  136. data/ruby/neo4j/driver/internal/async/inbound/connection_read_timeout_handler.rb +0 -17
  137. data/ruby/neo4j/driver/internal/async/inbound/inbound_message_dispatcher.rb +0 -171
  138. data/ruby/neo4j/driver/internal/async/inbound/inbound_message_handler.rb +0 -42
  139. data/ruby/neo4j/driver/internal/async/inbound/message_decoder.rb +0 -51
  140. data/ruby/neo4j/driver/internal/async/internal_async_session.rb +0 -92
  141. data/ruby/neo4j/driver/internal/async/internal_async_transaction.rb +0 -13
  142. data/ruby/neo4j/driver/internal/async/leak_logging_network_session.rb +0 -34
  143. data/ruby/neo4j/driver/internal/async/network_connection.rb +0 -194
  144. data/ruby/neo4j/driver/internal/async/network_session.rb +0 -150
  145. data/ruby/neo4j/driver/internal/async/outbound/chunk_aware_byte_buf_output.rb +0 -110
  146. data/ruby/neo4j/driver/internal/async/outbound/outbound_message_handler.rb +0 -39
  147. data/ruby/neo4j/driver/internal/async/pool/channel.rb +0 -66
  148. data/ruby/neo4j/driver/internal/async/pool/channel_pool.rb +0 -31
  149. data/ruby/neo4j/driver/internal/async/pool/channel_tracker.rb +0 -135
  150. data/ruby/neo4j/driver/internal/async/pool/connection_pool_impl.rb +0 -156
  151. data/ruby/neo4j/driver/internal/async/pool/netty_channel_health_checker.rb +0 -87
  152. data/ruby/neo4j/driver/internal/async/pool/netty_channel_pool.rb +0 -52
  153. data/ruby/neo4j/driver/internal/async/pool/network_connection_factory.rb +0 -21
  154. data/ruby/neo4j/driver/internal/async/pool/pool_settings.rb +0 -34
  155. data/ruby/neo4j/driver/internal/async/pool/timed_stack.rb +0 -15
  156. data/ruby/neo4j/driver/internal/async/result_cursors_holder.rb +0 -17
  157. data/ruby/neo4j/driver/internal/async/unmanaged_transaction.rb +0 -212
  158. data/ruby/neo4j/driver/internal/bookmark_holder.rb +0 -9
  159. data/ruby/neo4j/driver/internal/cluster/cluster_composition.rb +0 -48
  160. data/ruby/neo4j/driver/internal/cluster/cluster_composition_lookup_result.rb +0 -14
  161. data/ruby/neo4j/driver/internal/cluster/cluster_routing_table.rb +0 -122
  162. data/ruby/neo4j/driver/internal/cluster/identity_resolver.rb +0 -10
  163. data/ruby/neo4j/driver/internal/cluster/loadbalancing/least_connected_load_balancing_strategy.rb +0 -68
  164. data/ruby/neo4j/driver/internal/cluster/loadbalancing/load_balancer.rb +0 -125
  165. data/ruby/neo4j/driver/internal/cluster/loadbalancing/round_robin_array_index.rb +0 -13
  166. data/ruby/neo4j/driver/internal/cluster/multi_databases_routing_procedure_runner.rb +0 -31
  167. data/ruby/neo4j/driver/internal/cluster/rediscovery_impl.rb +0 -147
  168. data/ruby/neo4j/driver/internal/cluster/route_message_routing_procedure_runner.rb +0 -43
  169. data/ruby/neo4j/driver/internal/cluster/routing_context.rb +0 -77
  170. data/ruby/neo4j/driver/internal/cluster/routing_procedure_cluster_composition_provider.rb +0 -60
  171. data/ruby/neo4j/driver/internal/cluster/routing_procedure_response.rb +0 -35
  172. data/ruby/neo4j/driver/internal/cluster/routing_settings.rb +0 -24
  173. data/ruby/neo4j/driver/internal/cluster/routing_table_handler_impl.rb +0 -95
  174. data/ruby/neo4j/driver/internal/cluster/routing_table_registry_impl.rb +0 -121
  175. data/ruby/neo4j/driver/internal/cluster/single_database_routing_procedure_runner.rb +0 -73
  176. data/ruby/neo4j/driver/internal/connection_settings.rb +0 -16
  177. data/ruby/neo4j/driver/internal/cursor/async_result_cursor_impl.rb +0 -55
  178. data/ruby/neo4j/driver/internal/cursor/async_result_cursor_only_factory.rb +0 -24
  179. data/ruby/neo4j/driver/internal/cursor/disposable_async_result_cursor.rb +0 -61
  180. data/ruby/neo4j/driver/internal/cursor/result_cursor_factory_impl.rb +0 -24
  181. data/ruby/neo4j/driver/internal/cursor/rx_result_cursor_impl.rb +0 -110
  182. data/ruby/neo4j/driver/internal/database_name_util.rb +0 -37
  183. data/ruby/neo4j/driver/internal/default_bookmark_holder.rb +0 -9
  184. data/ruby/neo4j/driver/internal/default_domain_name_resolver.rb +0 -11
  185. data/ruby/neo4j/driver/internal/direct_connection_provider.rb +0 -40
  186. data/ruby/neo4j/driver/internal/driver_factory.rb +0 -126
  187. data/ruby/neo4j/driver/internal/eager_result_value.rb +0 -5
  188. data/ruby/neo4j/driver/internal/handlers/begin_tx_response_handler.rb +0 -20
  189. data/ruby/neo4j/driver/internal/handlers/channel_releasing_reset_response_handler.rb +0 -30
  190. data/ruby/neo4j/driver/internal/handlers/commit_tx_response_handler.rb +0 -23
  191. data/ruby/neo4j/driver/internal/handlers/hello_response_handler.rb +0 -65
  192. data/ruby/neo4j/driver/internal/handlers/init_response_handler.rb +0 -34
  193. data/ruby/neo4j/driver/internal/handlers/legacy_pull_all_response_handler.rb +0 -199
  194. data/ruby/neo4j/driver/internal/handlers/no_op_response_handler.rb +0 -16
  195. data/ruby/neo4j/driver/internal/handlers/ping_response_handler.rb +0 -29
  196. data/ruby/neo4j/driver/internal/handlers/pull_handlers.rb +0 -32
  197. data/ruby/neo4j/driver/internal/handlers/pulln/auto_pull_response_handler.rb +0 -169
  198. data/ruby/neo4j/driver/internal/handlers/pulln/basic_pull_response_handler.rb +0 -298
  199. data/ruby/neo4j/driver/internal/handlers/pulln/fetch_size_util.rb +0 -20
  200. data/ruby/neo4j/driver/internal/handlers/reset_response_handler.rb +0 -34
  201. data/ruby/neo4j/driver/internal/handlers/rollback_tx_response_handler.rb +0 -25
  202. data/ruby/neo4j/driver/internal/handlers/route_message_response_handler.rb +0 -21
  203. data/ruby/neo4j/driver/internal/handlers/routing_response_handler.rb +0 -79
  204. data/ruby/neo4j/driver/internal/handlers/run_response_handler.rb +0 -38
  205. data/ruby/neo4j/driver/internal/handlers/session_pull_response_completion_listener.rb +0 -34
  206. data/ruby/neo4j/driver/internal/handlers/transaction_pull_response_completion_listener.rb +0 -20
  207. data/ruby/neo4j/driver/internal/impersonation_util.rb +0 -22
  208. data/ruby/neo4j/driver/internal/internal_bookmark.rb +0 -9
  209. data/ruby/neo4j/driver/internal/internal_database_name.rb +0 -9
  210. data/ruby/neo4j/driver/internal/internal_driver.rb +0 -83
  211. data/ruby/neo4j/driver/internal/internal_entity.rb +0 -21
  212. data/ruby/neo4j/driver/internal/internal_node.rb +0 -21
  213. data/ruby/neo4j/driver/internal/internal_pair.rb +0 -9
  214. data/ruby/neo4j/driver/internal/internal_path.rb +0 -35
  215. data/ruby/neo4j/driver/internal/internal_point2_d.rb +0 -9
  216. data/ruby/neo4j/driver/internal/internal_point3_d.rb +0 -6
  217. data/ruby/neo4j/driver/internal/internal_record.rb +0 -27
  218. data/ruby/neo4j/driver/internal/internal_relationship.rb +0 -27
  219. data/ruby/neo4j/driver/internal/internal_result.rb +0 -49
  220. data/ruby/neo4j/driver/internal/internal_session.rb +0 -91
  221. data/ruby/neo4j/driver/internal/internal_transaction.rb +0 -48
  222. data/ruby/neo4j/driver/internal/logging/channel_activity_logger.rb +0 -29
  223. data/ruby/neo4j/driver/internal/logging/channel_error_logger.rb +0 -17
  224. data/ruby/neo4j/driver/internal/logging/prefixed_logger.rb +0 -19
  225. data/ruby/neo4j/driver/internal/logging/reformatted_logger.rb +0 -17
  226. data/ruby/neo4j/driver/internal/messaging/abstract_message_writer.rb +0 -23
  227. data/ruby/neo4j/driver/internal/messaging/bolt_protocol.rb +0 -32
  228. data/ruby/neo4j/driver/internal/messaging/bolt_protocol_version.rb +0 -48
  229. data/ruby/neo4j/driver/internal/messaging/common/common_message_reader.rb +0 -51
  230. data/ruby/neo4j/driver/internal/messaging/common/common_value.rb +0 -33
  231. data/ruby/neo4j/driver/internal/messaging/common/common_value_packer.rb +0 -104
  232. data/ruby/neo4j/driver/internal/messaging/common/common_value_unpacker.rb +0 -256
  233. data/ruby/neo4j/driver/internal/messaging/encode/begin_message_encoder.rb +0 -15
  234. data/ruby/neo4j/driver/internal/messaging/encode/commit_message_encoder.rb +0 -14
  235. data/ruby/neo4j/driver/internal/messaging/encode/discard_all_message_encoder.rb +0 -14
  236. data/ruby/neo4j/driver/internal/messaging/encode/discard_message_encoder.rb +0 -15
  237. data/ruby/neo4j/driver/internal/messaging/encode/goodbye_message_encoder.rb +0 -14
  238. data/ruby/neo4j/driver/internal/messaging/encode/hello_message_encoder.rb +0 -15
  239. data/ruby/neo4j/driver/internal/messaging/encode/init_message_encoder.rb +0 -16
  240. data/ruby/neo4j/driver/internal/messaging/encode/logoff_message_encoder.rb +0 -14
  241. data/ruby/neo4j/driver/internal/messaging/encode/logon_message_encoder.rb +0 -15
  242. data/ruby/neo4j/driver/internal/messaging/encode/pull_all_message_encoder.rb +0 -14
  243. data/ruby/neo4j/driver/internal/messaging/encode/pull_message_encoder.rb +0 -15
  244. data/ruby/neo4j/driver/internal/messaging/encode/reset_message_encoder.rb +0 -14
  245. data/ruby/neo4j/driver/internal/messaging/encode/rollback_message_encoder.rb +0 -14
  246. data/ruby/neo4j/driver/internal/messaging/encode/route_message_encoder.rb +0 -24
  247. data/ruby/neo4j/driver/internal/messaging/encode/route_v44_message_encoder.rb +0 -22
  248. data/ruby/neo4j/driver/internal/messaging/encode/run_message_encoder.rb +0 -16
  249. data/ruby/neo4j/driver/internal/messaging/encode/run_with_metadata_message_encoder.rb +0 -17
  250. data/ruby/neo4j/driver/internal/messaging/request/abstract_streaming_message.rb +0 -25
  251. data/ruby/neo4j/driver/internal/messaging/request/begin_message.rb +0 -25
  252. data/ruby/neo4j/driver/internal/messaging/request/commit_message.rb +0 -20
  253. data/ruby/neo4j/driver/internal/messaging/request/discard_all_message.rb +0 -20
  254. data/ruby/neo4j/driver/internal/messaging/request/discard_message.rb +0 -23
  255. data/ruby/neo4j/driver/internal/messaging/request/goodbye_message.rb +0 -20
  256. data/ruby/neo4j/driver/internal/messaging/request/hello_message.rb +0 -30
  257. data/ruby/neo4j/driver/internal/messaging/request/init_message.rb +0 -19
  258. data/ruby/neo4j/driver/internal/messaging/request/logoff_message.rb +0 -13
  259. data/ruby/neo4j/driver/internal/messaging/request/logon_message.rb +0 -13
  260. data/ruby/neo4j/driver/internal/messaging/request/message_with_metadata.rb +0 -17
  261. data/ruby/neo4j/driver/internal/messaging/request/multi_database_util.rb +0 -26
  262. data/ruby/neo4j/driver/internal/messaging/request/pull_all_message.rb +0 -23
  263. data/ruby/neo4j/driver/internal/messaging/request/pull_message.rb +0 -22
  264. data/ruby/neo4j/driver/internal/messaging/request/reset_message.rb +0 -32
  265. data/ruby/neo4j/driver/internal/messaging/request/rollback_message.rb +0 -20
  266. data/ruby/neo4j/driver/internal/messaging/request/route_message.rb +0 -28
  267. data/ruby/neo4j/driver/internal/messaging/request/run_message.rb +0 -23
  268. data/ruby/neo4j/driver/internal/messaging/request/run_with_metadata_message.rb +0 -49
  269. data/ruby/neo4j/driver/internal/messaging/request/transaction_metadata_builder.rb +0 -24
  270. data/ruby/neo4j/driver/internal/messaging/response/failure_message.rb +0 -40
  271. data/ruby/neo4j/driver/internal/messaging/response/ignored_message.rb +0 -29
  272. data/ruby/neo4j/driver/internal/messaging/response/record_message.rb +0 -33
  273. data/ruby/neo4j/driver/internal/messaging/response/success_message.rb +0 -34
  274. data/ruby/neo4j/driver/internal/messaging/v3/bolt_protocol_v3.rb +0 -82
  275. data/ruby/neo4j/driver/internal/messaging/v3/message_format_v3.rb +0 -17
  276. data/ruby/neo4j/driver/internal/messaging/v3/message_writer_v3.rb +0 -27
  277. data/ruby/neo4j/driver/internal/messaging/v4/bolt_protocol_v4.rb +0 -29
  278. data/ruby/neo4j/driver/internal/messaging/v4/message_format_v4.rb +0 -13
  279. data/ruby/neo4j/driver/internal/messaging/v4/message_writer_v4.rb +0 -17
  280. data/ruby/neo4j/driver/internal/messaging/v41/bolt_protocol_v41.rb +0 -25
  281. data/ruby/neo4j/driver/internal/messaging/v42/bolt_protocol_v42.rb +0 -13
  282. data/ruby/neo4j/driver/internal/messaging/v43/bolt_protocol_v43.rb +0 -19
  283. data/ruby/neo4j/driver/internal/messaging/v43/message_format_v43.rb +0 -14
  284. data/ruby/neo4j/driver/internal/messaging/v43/message_writer_v43.rb +0 -20
  285. data/ruby/neo4j/driver/internal/messaging/v44/bolt_protocol_v44.rb +0 -17
  286. data/ruby/neo4j/driver/internal/messaging/v44/message_format_v44.rb +0 -14
  287. data/ruby/neo4j/driver/internal/messaging/v44/message_writer_v44.rb +0 -15
  288. data/ruby/neo4j/driver/internal/messaging/v5/bolt_protocol_v5.rb +0 -21
  289. data/ruby/neo4j/driver/internal/messaging/v5/message_format_v5.rb +0 -18
  290. data/ruby/neo4j/driver/internal/messaging/v5/value_unpacker_v5.rb +0 -17
  291. data/ruby/neo4j/driver/internal/messaging/v51/bolt_protocol_v51.rb +0 -40
  292. data/ruby/neo4j/driver/internal/messaging/v51/message_format_v51.rb +0 -14
  293. data/ruby/neo4j/driver/internal/messaging/v51/message_writer_v51.rb +0 -17
  294. data/ruby/neo4j/driver/internal/metrics/connection_pool_metrics_listener.rb +0 -34
  295. data/ruby/neo4j/driver/internal/metrics/internal_abstract_metrics.rb +0 -46
  296. data/ruby/neo4j/driver/internal/metrics/internal_connection_pool_metrics.rb +0 -105
  297. data/ruby/neo4j/driver/internal/metrics/internal_metrics.rb +0 -82
  298. data/ruby/neo4j/driver/internal/metrics/internal_metrics_provider.rb +0 -18
  299. data/ruby/neo4j/driver/internal/metrics/listener_event.rb +0 -17
  300. data/ruby/neo4j/driver/internal/metrics/metrics_provider.rb +0 -24
  301. data/ruby/neo4j/driver/internal/metrics/time_recorder_listener_event.rb +0 -15
  302. data/ruby/neo4j/driver/internal/packstream/byte_array_incompatible_packer.rb +0 -12
  303. data/ruby/neo4j/driver/internal/packstream/pack_input.rb +0 -47
  304. data/ruby/neo4j/driver/internal/packstream/pack_output.rb +0 -39
  305. data/ruby/neo4j/driver/internal/packstream/pack_stream.rb +0 -324
  306. data/ruby/neo4j/driver/internal/packstream/pack_type.rb +0 -17
  307. data/ruby/neo4j/driver/internal/read_only_bookmark_holder.rb +0 -13
  308. data/ruby/neo4j/driver/internal/resolved_bolt_server_address.rb +0 -35
  309. data/ruby/neo4j/driver/internal/retry/exponential_backoff_retry_logic.rb +0 -150
  310. data/ruby/neo4j/driver/internal/revocation_strategy.rb +0 -19
  311. data/ruby/neo4j/driver/internal/scheme.rb +0 -32
  312. data/ruby/neo4j/driver/internal/security/internal_auth_token.rb +0 -15
  313. data/ruby/neo4j/driver/internal/security/security_plan_impl.rb +0 -48
  314. data/ruby/neo4j/driver/internal/security_setting.rb +0 -66
  315. data/ruby/neo4j/driver/internal/session_factory_impl.rb +0 -32
  316. data/ruby/neo4j/driver/internal/spi/connection.rb +0 -19
  317. data/ruby/neo4j/driver/internal/spi/connection_pool.rb +0 -9
  318. data/ruby/neo4j/driver/internal/spi/response_handler.rb +0 -23
  319. data/ruby/neo4j/driver/internal/summary/internal_database_info.rb +0 -7
  320. data/ruby/neo4j/driver/internal/summary/internal_input_position.rb +0 -11
  321. data/ruby/neo4j/driver/internal/summary/internal_notification.rb +0 -16
  322. data/ruby/neo4j/driver/internal/summary/internal_plan.rb +0 -41
  323. data/ruby/neo4j/driver/internal/summary/internal_profiled_plan.rb +0 -32
  324. data/ruby/neo4j/driver/internal/summary/internal_result_summary.rb +0 -33
  325. data/ruby/neo4j/driver/internal/summary/internal_server_info.rb +0 -6
  326. data/ruby/neo4j/driver/internal/summary/internal_summary_counters.rb +0 -18
  327. data/ruby/neo4j/driver/internal/svm/netty_substitutions.rb +0 -196
  328. data/ruby/neo4j/driver/internal/svm/z_lib_substitutions.rb +0 -21
  329. data/ruby/neo4j/driver/internal/util/certificate_tool.rb +0 -65
  330. data/ruby/neo4j/driver/internal/util/clock.rb +0 -29
  331. data/ruby/neo4j/driver/internal/util/error_util.rb +0 -104
  332. data/ruby/neo4j/driver/internal/util/extract.rb +0 -123
  333. data/ruby/neo4j/driver/internal/util/format.rb +0 -39
  334. data/ruby/neo4j/driver/internal/util/futures.rb +0 -99
  335. data/ruby/neo4j/driver/internal/util/iterables.rb +0 -35
  336. data/ruby/neo4j/driver/internal/util/lock_util.rb +0 -23
  337. data/ruby/neo4j/driver/internal/util/metadata_extractor.rb +0 -101
  338. data/ruby/neo4j/driver/internal/util/mutex.rb +0 -9
  339. data/ruby/neo4j/driver/internal/util/preconditions.rb +0 -16
  340. data/ruby/neo4j/driver/internal/util/result_holder.rb +0 -72
  341. data/ruby/neo4j/driver/internal/util/server_version.rb +0 -60
  342. data/ruby/neo4j/driver/logging1.rb +0 -51
  343. data/ruby/neo4j/driver/net/server_address.rb +0 -9
  344. data/ruby/neo4j/driver/query.rb +0 -48
  345. data/ruby/neo4j/driver/records.rb +0 -13
  346. data/ruby/neo4j/driver/transaction_config.rb +0 -50
  347. data/ruby/neo4j/driver/values.rb +0 -26
  348. data/ruby/neo4j/driver.rb +0 -30
@@ -0,0 +1,335 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ module PackStream
6
+ # PackStream Packer - serializes Ruby objects to PackStream binary format
7
+ # Based on https://neo4j.com/docs/bolt/current/packstream/
8
+ class Packer
9
+ include Markers
10
+
11
+ # When true, datetimes are packed as the UTC-seconds Bolt 5.0+
12
+ # structures (0x49 / 0x69) instead of the legacy local-seconds
13
+ # variants (0x46 / 0x66). Connection sets this after a
14
+ # successful handshake negotiates Bolt 5.0+; ignored on 4.x.
15
+ attr_accessor :use_utc_datetime
16
+
17
+ def initialize(protocol)
18
+ @buffer = String.new(encoding: Encoding::BINARY)
19
+ @use_utc_datetime = false
20
+ @protocol = protocol
21
+ end
22
+
23
+ def pack(value)
24
+ case value
25
+ when nil
26
+ pack_null
27
+ when true, false
28
+ pack_boolean(value)
29
+ when Integer
30
+ pack_integer(value)
31
+ when Float
32
+ pack_float(value)
33
+ when String
34
+ # Pack binary strings as BYTES, text strings as STRING
35
+ value.encoding == Encoding::BINARY ? pack_bytes(value) : pack_string(value)
36
+ when Symbol
37
+ pack_string(value.to_s)
38
+ when Hash
39
+ # Check Hash before Enumerable since Hash is also Enumerable
40
+ pack_map(value)
41
+ when Types::Node, Types::Relationship, Types::Path, Types::UnsupportedType
42
+ # Graph types are not valid query parameters; neither is an
43
+ # UnsupportedType (a value the driver couldn't materialise — it
44
+ # must not be sent back to the server). Reject before the Enumerable
45
+ # branch since Path includes Enumerable.
46
+ Exceptions::ClientException.unable_to_convert(value)
47
+ when Array, Set, Range
48
+ # Known sized collections — pack_list uses #size, which is O(1) here.
49
+ pack_list(value)
50
+ when Enumerable
51
+ # Generic Enumerable (lazy enumerators, custom collections) — materialise
52
+ # so #size is well-defined.
53
+ pack_list(value.to_a)
54
+ when ::DateTime, ::Time
55
+ # Check DateTime before Date — DateTime < Date in Ruby, so the
56
+ # Date branch would match first and pack away the time component.
57
+ pack_datetime(value)
58
+ when ::Date
59
+ # Pack Ruby Date as Neo4j Date structure
60
+ pack_date(value)
61
+ when Types::LocalDateTime
62
+ pack_local_datetime(value)
63
+ when Types::LocalTime
64
+ pack_local_time(value)
65
+ when Types::OffsetTime
66
+ pack_offset_time(value)
67
+ when Types::Point
68
+ pack_point(value)
69
+ when Types::Duration
70
+ pack_duration(value)
71
+ when Types::UUID
72
+ # A PackStream V2 type: only the negotiated protocol decides whether
73
+ # it can be sent — V61 packs it, every earlier version rejects it.
74
+ @protocol.pack_uuid(self, value)
75
+ else
76
+ Exceptions::ClientException.unable_to_convert(value)
77
+ end
78
+ self
79
+ end
80
+
81
+ # Serialise a Bolt protocol message (a PackStream::Structure) onto the buffer.
82
+ # Distinct from #pack so the user-value path doesn't carry knowledge of
83
+ # the wire-level Structure type.
84
+ def pack_message(structure)
85
+ pack_structure(structure)
86
+ self
87
+ end
88
+
89
+ def bytes
90
+ @buffer
91
+ end
92
+
93
+ def reset
94
+ @buffer.clear
95
+ self
96
+ end
97
+
98
+ # PackStream V2 UUID (Bolt 6.1+): marker 0xE0 + 16 raw bytes. Called by
99
+ # Protocol::V61#pack_uuid — every earlier protocol rejects a UUID
100
+ # instead, so this is only reached once 6.1 is negotiated.
101
+ def pack_uuid_value(value)
102
+ @buffer << [UUID].pack('C')
103
+ @buffer << [value.to_s.delete('-')].pack('H*')
104
+ end
105
+
106
+ private
107
+
108
+ def pack_null
109
+ @buffer << [NULL].pack('C')
110
+ end
111
+
112
+ def pack_boolean(value)
113
+ @buffer << [value ? BOOLEAN_TRUE : BOOLEAN_FALSE].pack('C')
114
+ end
115
+
116
+ def pack_integer(value)
117
+ if value >= -16 && value <= 127
118
+ # TINY_INT: -16 to +127
119
+ @buffer << [value].pack('c')
120
+ elsif value >= -128 && value <= 127
121
+ @buffer << [INT_8, value].pack('Cc')
122
+ elsif value >= -32_768 && value <= 32_767
123
+ @buffer << [INT_16, value].pack('Cs>')
124
+ elsif value >= -2_147_483_648 && value <= 2_147_483_647
125
+ @buffer << [INT_32, value].pack('Cl>')
126
+ elsif value >= -9_223_372_036_854_775_808 && value <= 9_223_372_036_854_775_807
127
+ @buffer << [INT_64, value].pack('Cq>')
128
+ else
129
+ raise ArgumentError, "Integer value out of range: #{value}"
130
+ end
131
+ end
132
+
133
+ def pack_float(value)
134
+ @buffer << [FLOAT_64].pack('C')
135
+ @buffer << [value].pack('G')
136
+ end
137
+
138
+ def pack_string(value)
139
+ bytes = value.encode(Encoding::UTF_8).b
140
+ size = bytes.bytesize
141
+
142
+ if size < 16
143
+ @buffer << [TINY_STRING | size].pack('C')
144
+ elsif size <= 255
145
+ @buffer << [STRING_8, size].pack('CC')
146
+ elsif size <= 65_535
147
+ @buffer << [STRING_16, size].pack('CS>')
148
+ elsif size <= 2_147_483_647
149
+ @buffer << [STRING_32, size].pack('CL>')
150
+ else
151
+ raise ArgumentError, "String too long: #{size} bytes"
152
+ end
153
+
154
+ @buffer << bytes
155
+ end
156
+
157
+ def pack_bytes(value)
158
+ size = value.bytesize
159
+
160
+ if size <= 255
161
+ @buffer << [BYTES_8, size].pack('CC')
162
+ elsif size <= 65_535
163
+ @buffer << [BYTES_16, size].pack('CS>')
164
+ elsif size <= 2_147_483_647
165
+ @buffer << [BYTES_32, size].pack('CL>')
166
+ else
167
+ raise ArgumentError, "Bytes too long: #{size} bytes"
168
+ end
169
+
170
+ @buffer << value
171
+ end
172
+
173
+ def pack_list(value)
174
+ size = value.size
175
+
176
+ if size < 16
177
+ @buffer << [TINY_LIST | size].pack('C')
178
+ elsif size <= 255
179
+ @buffer << [LIST_8, size].pack('CC')
180
+ elsif size <= 65_535
181
+ @buffer << [LIST_16, size].pack('CS>')
182
+ elsif size <= 2_147_483_647
183
+ @buffer << [LIST_32, size].pack('CL>')
184
+ else
185
+ raise ArgumentError, "List too long: #{size} items"
186
+ end
187
+
188
+ value.each { pack(it) }
189
+ end
190
+
191
+ def pack_map(value)
192
+ size = value.size
193
+
194
+ if size < 16
195
+ @buffer << [TINY_MAP | size].pack('C')
196
+ elsif size <= 255
197
+ @buffer << [MAP_8, size].pack('CC')
198
+ elsif size <= 65_535
199
+ @buffer << [MAP_16, size].pack('CS>')
200
+ elsif size <= 2_147_483_647
201
+ @buffer << [MAP_32, size].pack('CL>')
202
+ else
203
+ raise ArgumentError, "Map too long: #{size} entries"
204
+ end
205
+
206
+ value.each do |key, val|
207
+ pack(key.to_s)
208
+ pack(val)
209
+ end
210
+ end
211
+
212
+ def pack_structure(value)
213
+ size = value.fields.size
214
+
215
+ if size < 16
216
+ @buffer << [TINY_STRUCT | size].pack('C')
217
+ elsif size <= 255
218
+ @buffer << [STRUCT_8, size].pack('CC')
219
+ elsif size <= 65_535
220
+ @buffer << [STRUCT_16, size].pack('CS>')
221
+ else
222
+ raise ArgumentError, "Structure too large: #{size} fields"
223
+ end
224
+
225
+ @buffer << [value.signature].pack('C')
226
+ value.fields.each { |field| pack(field) }
227
+ end
228
+
229
+ def pack_date(value)
230
+ days = (value - ::Date.new(1970, 1, 1)).to_i
231
+ # Date structure: signature 0x44, 1 field (days)
232
+ @buffer << [TINY_STRUCT | 1, 0x44].pack('CC')
233
+ pack_integer(days)
234
+ end
235
+
236
+ def pack_datetime(value)
237
+ # Normalise DateTime to Time so we can rely on Time's API (nsec,
238
+ # utc_offset, to_i) uniformly.
239
+ value = value.to_time if value.is_a?(::DateTime)
240
+
241
+ tz_offset = value.utc_offset
242
+ nanoseconds = value.nsec
243
+ # Bolt 5.0+ (and 4.4-with-patch_bolt:utc) want true UTC
244
+ # seconds in 0x49 / 0x69; the legacy 0x46 / 0x66 carry LOCAL
245
+ # seconds (wall-clock treated as if it were UTC). See the
246
+ # matching hydration handlers in Bolt::Connection.
247
+ if @use_utc_datetime
248
+ epoch_seconds = value.to_i
249
+ offset_sig = 0x49
250
+ zone_sig = 0x69
251
+ else
252
+ epoch_seconds = value.to_i + tz_offset
253
+ offset_sig = 0x46
254
+ zone_sig = 0x66
255
+ end
256
+ zone_name = named_zone_for(value)
257
+
258
+ if zone_name
259
+ # ZonedDateTime: fields [seconds, nanos, tz_name]
260
+ @buffer << [TINY_STRUCT | 3, zone_sig].pack('CC')
261
+ pack_integer(epoch_seconds)
262
+ pack_integer(nanoseconds)
263
+ pack_string(zone_name)
264
+ else
265
+ # DateTime with offset: fields [seconds, nanos, tz_offset]
266
+ @buffer << [TINY_STRUCT | 3, offset_sig].pack('CC')
267
+ pack_integer(epoch_seconds)
268
+ pack_integer(nanoseconds)
269
+ pack_integer(tz_offset)
270
+ end
271
+ end
272
+
273
+ # Return the IANA zone name for a TimeWithZone-like value when it has
274
+ # one, otherwise nil (so the caller falls back to offset-only 0x46).
275
+ # Offset-shaped names like "+07:00" or "-05:00" don't round-trip
276
+ # through Neo4j's zoned DateTime and are treated as nil.
277
+ def named_zone_for(value)
278
+ return nil unless value.respond_to?(:time_zone)
279
+
280
+ tz = value.time_zone
281
+ name = tz.respond_to?(:name) ? tz.name : nil
282
+ return nil if name.nil? || name.empty? || name.match?(/\A[+-]?\d/)
283
+
284
+ name
285
+ end
286
+
287
+ def pack_local_datetime(value)
288
+ # LocalDateTime structure: signature 0x64, 2 fields (seconds, nanos)
289
+ @buffer << [TINY_STRUCT | 2, 0x64].pack('CC')
290
+ pack_integer(value.epoch_seconds)
291
+ pack_integer(value.nanoseconds)
292
+ end
293
+
294
+ def pack_offset_time(value)
295
+ # OffsetTime structure: signature 0x54, 2 fields (nanos, tz_offset)
296
+ @buffer << [TINY_STRUCT | 2, 0x54].pack('CC')
297
+ pack_integer(value.nanoseconds)
298
+ pack_integer(value.tz_offset_seconds)
299
+ end
300
+
301
+ def pack_local_time(value)
302
+ # LocalTime structure: signature 0x74, 1 field (nanos)
303
+ @buffer << [TINY_STRUCT | 1, 0x74].pack('CC')
304
+ pack_integer(value.nanoseconds)
305
+ end
306
+
307
+ def pack_point(value)
308
+ if value.z.nil?
309
+ # Point2D: signature 0x58, 3 fields (srid, x, y)
310
+ @buffer << [TINY_STRUCT | 3, 0x58].pack('CC')
311
+ pack_integer(value.srid)
312
+ pack_float(value.x)
313
+ pack_float(value.y)
314
+ else
315
+ # Point3D: signature 0x59, 4 fields (srid, x, y, z)
316
+ @buffer << [TINY_STRUCT | 4, 0x59].pack('CC')
317
+ pack_integer(value.srid)
318
+ pack_float(value.x)
319
+ pack_float(value.y)
320
+ pack_float(value.z)
321
+ end
322
+ end
323
+
324
+ def pack_duration(value)
325
+ # Duration: signature 0x45, 4 fields (months, days, seconds, nanoseconds)
326
+ @buffer << [TINY_STRUCT | 4, 0x45].pack('CC')
327
+ pack_integer(value.months)
328
+ pack_integer(value.days)
329
+ pack_integer(value.seconds)
330
+ pack_integer(value.nanoseconds)
331
+ end
332
+ end
333
+ end
334
+ end
335
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ module PackStream
6
+ # Represents a PackStream Structure with a signature and fields
7
+ class Structure
8
+ attr_reader :signature, :fields
9
+
10
+ def initialize(signature, fields = [])
11
+ @signature = signature
12
+ @fields = fields
13
+ end
14
+
15
+ def ==(other)
16
+ other.is_a?(Structure) &&
17
+ other.signature == @signature &&
18
+ other.fields == @fields
19
+ end
20
+
21
+ def to_s
22
+ "Structure(0x#{@signature.to_s(16).upcase}, #{@fields.inspect})"
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,170 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ module PackStream
6
+ # PackStream Unpacker - deserializes PackStream binary format to Ruby objects
7
+ class Unpacker
8
+ include Markers
9
+
10
+ def initialize(io, protocol)
11
+ @io = io
12
+ @hydration_handlers = {}
13
+ @protocol = protocol
14
+ end
15
+
16
+ def register_hydration_handler(signature, handler = nil, &block)
17
+ @hydration_handlers[signature] = handler || block
18
+ end
19
+
20
+ def unpack
21
+ marker_byte = read_bytes(1).unpack1('C')
22
+ unpack_value(marker_byte)
23
+ end
24
+
25
+ # PackStream V2 UUID (Bolt 6.1+): 16 raw bytes (big-endian) after the
26
+ # marker, rendered to the canonical hyphenated form for Types::UUID.
27
+ # Called by Protocol::V61#unpack_uuid — earlier protocols reject the
28
+ # marker instead, so this is only reached once 6.1 is negotiated.
29
+ def unpack_uuid_value
30
+ hex = read_bytes(16).unpack1('H*')
31
+ Types::UUID.from_string(
32
+ "#{hex[0, 8]}-#{hex[8, 4]}-#{hex[12, 4]}-#{hex[16, 4]}-#{hex[20, 12]}"
33
+ )
34
+ end
35
+
36
+ # A ProtocolException (not a bare RuntimeError) so the failure reaches
37
+ # the user as a DriverError. The wording carries "PackStream" and the
38
+ # zero-padded marker byte — e.g. a UUID (0xE0) received before Bolt 6.1,
39
+ # which Protocol::Base#unpack_uuid routes here. testkit's UUID-over-6.0
40
+ # assertion greps the lowercased message for "unknown packstream" and
41
+ # "e0", both of which this satisfies.
42
+ def raise_unknown_marker(marker)
43
+ raise Exceptions::ProtocolException,
44
+ format('Unknown PackStream type marker: 0x%02x', marker)
45
+ end
46
+
47
+ private
48
+
49
+ def unpack_value(marker)
50
+ case marker
51
+ when NULL
52
+ nil
53
+ when BOOLEAN_FALSE
54
+ false
55
+ when BOOLEAN_TRUE
56
+ true
57
+ when FLOAT_64
58
+ read_bytes(8).unpack1('G')
59
+ when INT_8
60
+ read_bytes(1).unpack1('c')
61
+ when INT_16
62
+ read_bytes(2).unpack1('s>')
63
+ when INT_32
64
+ read_bytes(4).unpack1('l>')
65
+ when INT_64
66
+ read_bytes(8).unpack1('q>')
67
+ when 0xC8..0xCB
68
+ # Already handled above, but needed for case coverage
69
+ raise "Unexpected marker in unpack_value: #{marker}"
70
+ when BYTES_8
71
+ size = read_bytes(1).unpack1('C')
72
+ read_bytes(size).force_encoding(Encoding::BINARY)
73
+ when BYTES_16
74
+ size = read_bytes(2).unpack1('S>')
75
+ read_bytes(size).force_encoding(Encoding::BINARY)
76
+ when BYTES_32
77
+ size = read_bytes(4).unpack1('L>')
78
+ read_bytes(size).force_encoding(Encoding::BINARY)
79
+ when STRING_8
80
+ size = read_bytes(1).unpack1('C')
81
+ read_bytes(size).force_encoding(Encoding::UTF_8)
82
+ when STRING_16
83
+ size = read_bytes(2).unpack1('S>')
84
+ read_bytes(size).force_encoding(Encoding::UTF_8)
85
+ when STRING_32
86
+ size = read_bytes(4).unpack1('L>')
87
+ read_bytes(size).force_encoding(Encoding::UTF_8)
88
+ when LIST_8
89
+ size = read_bytes(1).unpack1('C')
90
+ unpack_list(size)
91
+ when LIST_16
92
+ size = read_bytes(2).unpack1('S>')
93
+ unpack_list(size)
94
+ when LIST_32
95
+ size = read_bytes(4).unpack1('L>')
96
+ unpack_list(size)
97
+ when MAP_8
98
+ size = read_bytes(1).unpack1('C')
99
+ unpack_map(size)
100
+ when MAP_16
101
+ size = read_bytes(2).unpack1('S>')
102
+ unpack_map(size)
103
+ when MAP_32
104
+ size = read_bytes(4).unpack1('L>')
105
+ unpack_map(size)
106
+ when STRUCT_8
107
+ size = read_bytes(1).unpack1('C')
108
+ unpack_structure(size)
109
+ when STRUCT_16
110
+ size = read_bytes(2).unpack1('S>')
111
+ unpack_structure(size)
112
+ when UUID
113
+ # A PackStream V2 type: only the negotiated protocol decides whether
114
+ # the marker is known — V61 reads it, every earlier version rejects
115
+ # it as an unknown marker.
116
+ @protocol.unpack_uuid(self)
117
+ else
118
+ # Check for TINY types
119
+ if (marker & 0xF0) == TINY_STRING
120
+ size = marker & 0x0F
121
+ read_bytes(size).force_encoding(Encoding::UTF_8)
122
+ elsif (marker & 0xF0) == TINY_LIST
123
+ size = marker & 0x0F
124
+ unpack_list(size)
125
+ elsif (marker & 0xF0) == TINY_MAP
126
+ size = marker & 0x0F
127
+ unpack_map(size)
128
+ elsif (marker & 0xF0) == TINY_STRUCT
129
+ size = marker & 0x0F
130
+ unpack_structure(size)
131
+ elsif marker >= 0xF0 || marker <= 0x7F
132
+ # TINY_INT range: -16 to 127
133
+ # Values from 0xF0-0xFF represent -16 to -1
134
+ # Values from 0x00-0x7F represent 0 to 127
135
+ if marker >= 0xF0
136
+ marker - 256 # Convert to negative
137
+ else
138
+ marker
139
+ end
140
+ else
141
+ raise_unknown_marker(marker)
142
+ end
143
+ end
144
+ end
145
+
146
+ def unpack_list(size) = Array.new(size) { unpack }
147
+
148
+ def unpack_map(size)
149
+ {}.tap { |map| size.times { map[unpack.to_sym] = unpack } }
150
+ end
151
+
152
+ def unpack_structure(size)
153
+ signature = read_bytes(1).unpack1('C')
154
+ fields = Array.new(size) { unpack }
155
+ handler = @hydration_handlers[signature] or
156
+ raise "No hydration handler for PackStream structure signature 0x#{signature.to_s(16)}"
157
+
158
+ handler.call(fields)
159
+ end
160
+
161
+ def read_bytes(n)
162
+ data = @io.read(n)
163
+ raise IOError, 'Unexpected end of stream' if data.nil? || data.bytesize < n
164
+
165
+ data
166
+ end
167
+ end
168
+ end
169
+ end
170
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Neo4j
4
+ module Driver
5
+ # Represents a single record (row) in a result
6
+ class Record
7
+ def initialize(keys, values)
8
+ @keys = keys
9
+ @values = values
10
+ # Create map with string keys for consistent lookup
11
+ @map = {}
12
+ @keys.each_with_index do |key, idx|
13
+ @map[key.to_s] = @values[idx]
14
+ end
15
+ end
16
+
17
+ attr_reader :keys, :values
18
+
19
+ def [](key)
20
+ case key
21
+ when Integer
22
+ @values[key]
23
+ when String, Symbol
24
+ @map[key.to_s]
25
+ else
26
+ raise ArgumentError, "Invalid key type: #{key.class}"
27
+ end
28
+ end
29
+
30
+ def first
31
+ @values.first
32
+ end
33
+
34
+ def to_h
35
+ @map.dup
36
+ end
37
+
38
+ def each(&)
39
+ @map.each(&)
40
+ end
41
+ end
42
+ end
43
+ end